+CopyB => {
+ op_flags => "F|H",
+ state => "pinned",
+ comment => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
+ reg_req => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
+ outs => [ "DST", "SRC", "CNT", "M" ],
+ units => [ "GP" ],
+},
+
+CopyB_i => {
+ op_flags => "F|H",
+ state => "pinned",
+ comment => "implements a memcopy: CopyB(dst, src, mem) == memcpy(dst, src, attr(size))",
+ reg_req => { in => [ "edi", "esi", "none" ], out => [ "edi", "esi", "none" ] },
+ outs => [ "DST", "SRC", "M" ],
+ units => [ "GP" ],
+},
+
+# Conversions
+
+Conv_I2I => {
+ reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3", "none" ] },
+ comment => "construct Conv Int -> Int",
+ units => [ "GP" ],
+ mode => "mode_Iu",
+},
+
+Conv_I2I8Bit => {
+ reg_req => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => [ "in_r3", "none" ] },
+ comment => "construct Conv Int -> Int",
+ units => [ "GP" ],
+ mode => "mode_Iu",
+},
+
+Conv_I2FP => {
+ reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm", "none" ] },
+ comment => "construct Conv Int -> Floating Point",
+ latency => 10,
+ units => [ "SSE" ],
+ mode => "mode_E",
+},
+
+Conv_FP2I => {
+ reg_req => { in => [ "gp", "gp", "xmm", "none" ], out => [ "gp", "none" ] },
+ comment => "construct Conv Floating Point -> Int",
+ latency => 10,
+ units => [ "SSE" ],
+ mode => "mode_Iu",
+},
+
+Conv_FP2FP => {
+ reg_req => { in => [ "gp", "gp", "xmm", "none" ], out => [ "xmm", "none" ] },
+ comment => "construct Conv Floating Point -> Floating Point",
+ latency => 8,
+ units => [ "SSE" ],
+ mode => "mode_E",
+},
+
+CmpCMov => {
+ irn_flags => "R",
+ comment => "construct Conditional Move: CMov(sel, a, b) == sel ? a : b",
+ reg_req => { in => [ "gp", "gp", "gp", "gp" ], out => [ "in_r4" ] },
+ latency => 2,
+ units => [ "GP" ],
+ mode => "mode_Iu",
+},
+
+PsiCondCMov => {
+ irn_flags => "R",
+ comment => "check if Psi condition tree evaluates to true and move result accordingly",
+ reg_req => { in => [ "gp", "gp", "gp" ], out => [ "in_r3" ] },
+ latency => 2,
+ units => [ "GP" ],
+ mode => "mode_Iu",
+},
+
+xCmpCMov => {
+ irn_flags => "R",
+ comment => "construct Conditional Move: SSE Compare + int CMov ",
+ reg_req => { in => [ "xmm", "xmm", "gp", "gp" ], out => [ "in_r4" ] },
+ latency => 5,
+ units => [ "SSE" ],
+ mode => "mode_Iu",
+},
+
+vfCmpCMov => {
+ irn_flags => "R",
+ comment => "construct Conditional Move: x87 Compare + int CMov",
+ reg_req => { in => [ "vfp", "vfp", "gp", "gp" ], out => [ "in_r4" ] },
+ latency => 10,
+ units => [ "VFP" ],
+ mode => "mode_Iu",
+},
+
+CmpSet => {
+ irn_flags => "R",
+ comment => "construct Set: Set(sel) == sel ? 1 : 0",
+ reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "eax ebx ecx edx" ] },
+ latency => 2,
+ units => [ "GP" ],
+ mode => "mode_Iu",
+},
+
+PsiCondSet => {
+ irn_flags => "R",
+ comment => "check if Psi condition tree evaluates to true and set result accordingly",
+ reg_req => { in => [ "gp" ], out => [ "eax ebx ecx edx" ] },
+ latency => 2,
+ units => [ "GP" ],
+ mode => "mode_Iu",
+},
+
+xCmpSet => {
+ irn_flags => "R",
+ comment => "construct Set: SSE Compare + int Set",
+ reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "eax ebx ecx edx" ] },
+ latency => 5,
+ units => [ "SSE" ],
+ mode => "mode_Iu",
+},
+
+vfCmpSet => {
+ irn_flags => "R",
+ comment => "construct Set: x87 Compare + int Set",
+ reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "eax ebx ecx edx" ] },
+ latency => 10,
+ units => [ "VFP" ],
+ mode => "mode_Iu",
+},
+
+vfCMov => {
+ irn_flags => "R",
+ comment => "construct x87 Conditional Move: vfCMov(sel, a, b) = sel ? a : b",
+ reg_req => { in => [ "vfp", "vfp", "vfp", "vfp" ], out => [ "vfp" ] },
+ latency => 10,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+#----------------------------------------------------------#
+# _ _ _ __ _ _ #
+# (_) | | | | / _| | | | #
+# __ ___ _ __| |_ _ _ __ _| | | |_| | ___ __ _| |_ #
+# \ \ / / | '__| __| | | |/ _` | | | _| |/ _ \ / _` | __| #
+# \ V /| | | | |_| |_| | (_| | | | | | | (_) | (_| | |_ #
+# \_/ |_|_| \__|\__,_|\__,_|_| |_| |_|\___/ \__,_|\__| #
+# | | #
+# _ __ ___ __| | ___ ___ #
+# | '_ \ / _ \ / _` |/ _ \/ __| #
+# | | | | (_) | (_| | __/\__ \ #
+# |_| |_|\___/ \__,_|\___||___/ #
+#----------------------------------------------------------#
+
+vfadd => {
+ irn_flags => "R",
+ comment => "virtual fp Add: Add(a, b) = Add(b, a) = a + b",
+ reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfmul => {
+ irn_flags => "R",
+ comment => "virtual fp Mul: Mul(a, b) = Mul(b, a) = a * b",
+ reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+l_vfmul => {
+ op_flags => "C",
+ cmp_attr => "return 1;",
+ comment => "lowered virtual fp Mul: Mul(a, b) = Mul(b, a) = a * b",
+ arity => 2,
+},
+
+vfsub => {
+ irn_flags => "R",
+ comment => "virtual fp Sub: Sub(a, b) = a - b",
+ reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+l_vfsub => {
+ cmp_attr => "return 1;",
+ comment => "lowered virtual fp Sub: Sub(a, b) = a - b",
+ arity => 2,
+},
+
+vfdiv => {
+ comment => "virtual fp Div: Div(a, b) = a / b",
+ reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+ outs => [ "res", "M" ],
+ latency => 20,
+ units => [ "VFP" ],
+},
+
+l_vfdiv => {
+ cmp_attr => "return 1;",
+ comment => "lowered virtual fp Div: Div(a, b) = a / b",
+ outs => [ "res", "M" ],
+ arity => 2,
+},
+
+vfprem => {
+ comment => "virtual fp Rem: Rem(a, b) = a - Q * b (Q is integer)",
+ reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+ latency => 20,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+l_vfprem => {
+ cmp_attr => "return 1;",
+ comment => "lowered virtual fp Rem: Rem(a, b) = a - Q * b (Q is integer)",
+ arity => 2,
+},
+
+vfabs => {
+ irn_flags => "R",
+ comment => "virtual fp Abs: Abs(a) = |a|",
+ reg_req => { in => [ "vfp"], out => [ "vfp" ] },
+ latency => 2,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfchs => {
+ irn_flags => "R",
+ comment => "virtual fp Chs: Chs(a) = -a",
+ reg_req => { in => [ "vfp"], out => [ "vfp" ] },
+ latency => 2,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfsin => {
+ irn_flags => "R",
+ comment => "virtual fp Sin: Sin(a) = sin(a)",
+ reg_req => { in => [ "vfp"], out => [ "vfp" ] },
+ latency => 150,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfcos => {
+ irn_flags => "R",
+ comment => "virtual fp Cos: Cos(a) = cos(a)",
+ reg_req => { in => [ "vfp"], out => [ "vfp" ] },
+ latency => 150,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfsqrt => {
+ irn_flags => "R",
+ comment => "virtual fp Sqrt: Sqrt(a) = a ^ 0.5",
+ reg_req => { in => [ "vfp"], out => [ "vfp" ] },
+ latency => 30,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+# virtual Load and Store
+
+vfld => {
+ op_flags => "L|F",
+ state => "exc_pinned",
+ comment => "virtual fp Load: Load(ptr, mem) = LD ptr -> reg",
+ reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
+ outs => [ "res", "M" ],
+ latency => 2,
+ units => [ "VFP" ],
+},
+
+vfst => {
+ op_flags => "L|F",
+ state => "exc_pinned",
+ comment => "virtual fp Store: Store(ptr, val, mem) = ST ptr,val",
+ reg_req => { in => [ "gp", "gp", "vfp", "none" ] },
+ latency => 2,
+ units => [ "VFP" ],
+ mode => "mode_M",
+},
+
+# Conversions
+
+vfild => {
+ comment => "virtual fp integer Load: Load(ptr, mem) = iLD ptr -> reg",
+ reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
+ outs => [ "res", "M" ],
+ latency => 4,
+ units => [ "VFP" ],
+},
+
+l_vfild => {
+ cmp_attr => "return 1;",
+ comment => "lowered virtual fp integer Load: Load(ptr, mem) = iLD ptr -> reg",
+ outs => [ "res", "M" ],
+ arity => 2,
+},
+
+vfist => {
+ comment => "virtual fp integer Store: Store(ptr, val, mem) = iST ptr,val",
+ reg_req => { in => [ "gp", "gp", "vfp", "none" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_M",
+},
+
+l_vfist => {
+ cmp_attr => "return 1;",
+ comment => "lowered virtual fp integer Store: Store(ptr, val, mem) = iST ptr,val",
+ arity => 3,
+ mode => "mode_M",
+},
+
+
+# constants
+
+vfldz => {
+ irn_flags => "R",
+ comment => "virtual fp Load 0.0: Ld 0.0 -> reg",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfld1 => {
+ irn_flags => "R",
+ comment => "virtual fp Load 1.0: Ld 1.0 -> reg",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfldpi => {
+ irn_flags => "R",
+ comment => "virtual fp Load pi: Ld pi -> reg",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfldln2 => {
+ irn_flags => "R",
+ comment => "virtual fp Load ln 2: Ld ln 2 -> reg",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfldlg2 => {
+ irn_flags => "R",
+ comment => "virtual fp Load lg 2: Ld lg 2 -> reg",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfldl2t => {
+ irn_flags => "R",
+ comment => "virtual fp Load ld 10: Ld ld 10 -> reg",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfldl2e => {
+ irn_flags => "R",
+ comment => "virtual fp Load ld e: Ld ld e -> reg",
+ reg_req => { out => [ "vfp" ] },
+ latency => 4,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+vfConst => {
+ op_flags => "c",
+ irn_flags => "R",
+# init_attr => " set_ia32_ls_mode(res, mode);",
+ comment => "represents a virtual floating point constant",
+ reg_req => { out => [ "vfp" ] },
+ latency => 3,
+ units => [ "VFP" ],
+ mode => "mode_E",
+},
+
+# other
+
+vfCondJmp => {
+ op_flags => "L|X|Y",
+ comment => "represents a virtual floating point compare",
+ reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "none", "none", "eax" ] },
+ outs => [ "false", "true", "temp_reg_eax" ],
+ latency => 10,
+ units => [ "VFP" ],
+},
+
+#------------------------------------------------------------------------#
+# ___ _____ __ _ _ _ #
+# __ _( _ )___ | / _| | ___ __ _| |_ _ __ ___ __| | ___ ___ #
+# \ \/ / _ \ / / | |_| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| #
+# > < (_) |/ / | _| | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ #
+# /_/\_\___//_/ |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
+#------------------------------------------------------------------------#
+
+# Note: gas is strangely buggy: fdivrp and fdivp as well as fsubrp and fsubp
+# are swapped, we work this around in the emitter...
+
+fadd => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ comment => "x87 Add: Add(a, b) = Add(b, a) = a + b",
+ reg_req => { },
+ emit => '. fadd%XM %x87_binop',
+},
+
+faddp => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ comment => "x87 Add: Add(a, b) = Add(b, a) = a + b",
+ reg_req => { },
+ emit => '. faddp %x87_binop',
+},
+
+fmul => {
+ op_flags => "R",
+ rd_constructor => "NONE",
+ comment => "x87 fp Mul: Mul(a, b) = Mul(b, a) = a + b",
+ reg_req => { },
+ emit => '. fmul%XM %x87_binop',