(*
 * Copyright (c) 2000-2002 Stefan Kral
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *)

(* This module contains code for hashing vsimdinstrs.  This feature is
 * used extensively in the code optimizer (vOptimization.ml) to speedup
 * the tree-matching process.
 *)

open VSimdBasics

(* for hashing purposes *)
type vsimdinstrcategory = 
  | VSIC_Load
  | VSIC_Store
  | VSIC_UnaryMulConst
  | VSIC_UnaryCopy
  | VSIC_UnarySwap
  | VSIC_UnaryChsLo
  | VSIC_UnaryChsHi
  | VSIC_UnaryChsLoHi
  | VSIC_BinAdd2
  | VSIC_BinSub2
  | VSIC_BinMul2
  | VSIC_BinAcc2
  | VSIC_BinFMcA2
  | VSIC_BinFMcS2
  | VSIC_BinFNMcA2
  | VSIC_BinUnpackL
  | VSIC_BinUnpackH
  | VSIC_BinUnpackLH
  | VSIC_TernFMA2
  | VSIC_TernFMS2

(* vsimdinstr category map *)
module VSICMap = Map.Make(struct 
			    type t = vsimdinstrcategory
			    let compare = compare
			  end)

let vsicmap_findE k m = try VSICMap.find k m with Not_found -> []
let vsicmap_addE k v m = VSICMap.add k (v::(vsicmap_findE k m)) m

(****************************************************************************)

let vsimdunaryopcategories_chs = 
  [
   VSIC_UnaryChsLo;
   VSIC_UnaryChsHi;
   VSIC_UnaryChsLoHi;
  ]

let vsimdunaryopcategories_nocopy = 
  VSIC_UnarySwap::VSIC_UnaryMulConst::vsimdunaryopcategories_chs

let vsimdunaryopcategories_all = 
  VSIC_UnaryCopy::vsimdunaryopcategories_nocopy

let vsimdbinopcategories_par = [VSIC_BinAdd2; VSIC_BinSub2; VSIC_BinMul2]

let vsimdbinopcategories_fmpar = [VSIC_BinFMcA2; VSIC_BinFMcS2; VSIC_BinFNMcA2]

let vsimdbinopcategories_all =
  [
   VSIC_BinAcc2; 
   VSIC_BinUnpackL;
   VSIC_BinUnpackLH;
   VSIC_BinUnpackH;
  ] @ 
  vsimdbinopcategories_fmpar @ 
  vsimdbinopcategories_par

let vsimdallcategories = 
  [VSIC_Load; VSIC_Store] @ 
  vsimdunaryopcategories_all @ 
  vsimdbinopcategories_all

(****************************************************************************)

let vsimdchsposToCategory = function
  | V_ChsLo   -> VSIC_UnaryChsLo
  | V_ChsHi   -> VSIC_UnaryChsHi
  | V_ChsLoHi -> VSIC_UnaryChsLoHi

let vsimdunaryopToCategory = function
  | V_Id	 -> VSIC_UnaryCopy
  | V_Swap	 -> VSIC_UnarySwap
  | V_SwapChsL	 -> VSIC_UnarySwap
  | V_SwapChsH	 -> VSIC_UnarySwap
  | V_Chs p 	 -> vsimdchsposToCategory p
  | V_MulConst _ -> VSIC_UnaryMulConst

let vsimdbinaryopToCategory = function
  | V_Acc2 _   -> VSIC_BinAcc2
  | V_UnpackL  -> VSIC_BinUnpackL
  | V_UnpackH  -> VSIC_BinUnpackH
  | V_UnpackLH -> VSIC_BinUnpackLH
  | V_Sub2     -> VSIC_BinSub2
  | V_Add2     -> VSIC_BinAdd2
  | V_Mul2     -> VSIC_BinMul2
  | V_FNMcA2 _ -> VSIC_BinFNMcA2
  | V_FMcA2 _  -> VSIC_BinFMcA2
  | V_FMcS2 _  -> VSIC_BinFMcS2

let vsimdternaryopToCategory = function
  | V_FMA2 -> VSIC_TernFMA2
  | V_FMS2 -> VSIC_TernFMS2

let vsimdinstrToCategory = function
  | V_SimdLoad2 _	        -> VSIC_Load
  | V_SimdStore2 _ 	        -> VSIC_Store
  | V_SimdUnaryOp(op,_,_)       -> vsimdunaryopToCategory op
  | V_SimdBinaryOp(op,_,_,_)    -> vsimdbinaryopToCategory op
  | V_SimdTernaryOp(op,_,_,_,_) -> vsimdternaryopToCategory op

let vsimdinstrToCategories i = [vsimdinstrToCategory i]



