#
# <op-name> => {
# "op_flags" => "N|L|C|X|I|F|Y|H|c|K",
-# "irn_flags" => "R|N|I"
+# "irn_flags" => "R|N|I|S"
# "arity" => "0|1|2|3 ... |variable|dynamic|any",
# "state" => "floats|pinned|mem_pinned|exc_pinned",
# "args" => [
# R rematerializeable
# N not spillable
# I ignore for register allocation
+# S modifies stack pointer
#
# state: state of the operation, OPTIONAL (default is "floats")
#
{ "name" => "ecx", "type" => 1 },
{ "name" => "esi", "type" => 2 },
{ "name" => "edi", "type" => 2 },
+# { "name" => "r11", "type" => 1 },
+# { "name" => "r12", "type" => 1 },
+# { "name" => "r13", "type" => 1 },
+# { "name" => "r14", "type" => 1 },
+# { "name" => "r15", "type" => 1 },
+# { "name" => "r16", "type" => 1 },
+# { "name" => "r17", "type" => 1 },
+# { "name" => "r18", "type" => 1 },
+# { "name" => "r19", "type" => 1 },
+# { "name" => "r20", "type" => 1 },
+# { "name" => "r21", "type" => 1 },
+# { "name" => "r22", "type" => 1 },
+# { "name" => "r23", "type" => 1 },
+# { "name" => "r24", "type" => 1 },
+# { "name" => "r25", "type" => 1 },
+# { "name" => "r26", "type" => 1 },
+# { "name" => "r27", "type" => 1 },
+# { "name" => "r28", "type" => 1 },
+# { "name" => "r29", "type" => 1 },
+# { "name" => "r30", "type" => 1 },
+# { "name" => "r31", "type" => 1 },
+# { "name" => "r32", "type" => 1 },
{ "name" => "ebp", "type" => 2 },
{ "name" => "esp", "type" => 4 },
{ "name" => "gp_NOREG", "type" => 6 }, # we need a dummy register for NoReg nodes
{ "name" => "st5", "type" => 1 },
{ "name" => "st6", "type" => 1 },
{ "name" => "st7", "type" => 1 },
- { "name" => "st_NOREG", "type" => 6 }, # we need a dummy register for NoReg nodes
- { "name" => "st_UKNWN", "type" => 6 }, # we need a dummy register for Unknown nodes
{ "mode" => "mode_E" }
]
); # %reg_classes
"comment" => "construct Add: Add(a, b) = Add(b, a) = a + b",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
- "emit" => '. add %ia32_emit_binop /* Add(%A1, %A2) -> %D1 */',
+ "emit" => '. add %ia32_emit_binop /* Add(%A3, %A4) -> %D1 */',
"outs" => [ "res", "M" ],
},
+"AddC" => {
+ "comment" => "construct Add with Carry: AddC(a, b) = Add(b, a) = a + b + carry",
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
+ "emit" => '. adc %ia32_emit_binop /* AddC(%A3, %A4) -> %D1 */',
+ "outs" => [ "res", "M" ],
+},
+
+"l_Add" => {
+ "op_flags" => "C",
+ "irn_flags" => "R",
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Add: Add(a, b) = Add(b, a) = a + b",
+ "arity" => 2,
+},
+
+"l_AddC" => {
+ "op_flags" => "C",
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Add with Carry: AddC(a, b) = Add(b, a) = a + b + carry",
+ "arity" => 2,
+},
+
+"MulS" => {
+ "comment" => "construct MulS: MulS(a, b) = MulS(b, a) = a * b",
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx" ] },
+ "emit" => '. mul %ia32_emit_unop /* Mul(%A1, %A2) -> %D1 */',
+ "outs" => [ "EAX", "EDX", "M" ],
+},
+
+"l_MulS" => {
+ "op_flags" => "C",
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered MulS: MulS(a, b) = MulS(b, a) = a * b",
+ "outs" => [ "EAX", "EDX", "M" ],
+ "arity" => 2
+},
+
"Mul" => {
"irn_flags" => "R",
"comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
"outs" => [ "res", "M" ],
},
+"l_Mul" => {
+ "op_flags" => "C",
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Mul: Mul(a, b) = Mul(b, a) = a * b",
+ "arity" => 2
+},
+
# Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX
"Mulh" => {
"comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax in_r3", "edx in_r4" ] },
- "emit" => '. imul %ia32_emit_binop /* Mulh(%A1, %A2) -> %D1 */',
+ "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx" ] },
+ "emit" => '. imul %ia32_emit_unop /* Mulh(%A1, %A2) -> %D1 */',
"outs" => [ "EAX", "EDX", "M" ],
},
"outs" => [ "res", "M" ],
},
+"l_Eor" => {
+ "op_flags" => "C",
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Eor: Eor(a, b) = Eor(b, a) = a EOR b",
+ "arity" => 2
+},
+
"Max" => {
"irn_flags" => "R",
"comment" => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b",
'
},
-"CMov" => {
- "irn_flags" => "R",
- "comment" => "construct Mux: Mux(sel, a, b) == sel ? a : b",
- "reg_req" => { "in" => [ "gp", "gp", "gp" ], "out" => [ "in_r2" ] },
- "emit" =>
-'. cmp %S1, 0 /* compare Sel for CMov (%A2, %A3) */
-. cmovne %D1, %S3 /* sel == true -> return %S3 */
-'
-},
-
# not commutative operations
"Sub" => {
"comment" => "construct Sub: Sub(a, b) = a - b",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
- "emit" => '. sub %ia32_emit_binop /* Sub(%A1, %A2) -> %D1 */',
+ "emit" => '. sub %ia32_emit_binop /* Sub(%A3, %A4) -> %D1 */',
"outs" => [ "res", "M" ],
},
+"SubC" => {
+ "comment" => "construct Sub with Carry: SubC(a, b) = a - b - carry",
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
+ "emit" => '. sbb %ia32_emit_binop /* SubC(%A3, %A4) -> %D1 */',
+ "outs" => [ "res", "M" ],
+},
+
+"l_Sub" => {
+ "irn_flags" => "R",
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Sub: Sub(a, b) = a - b",
+ "arity" => 2,
+},
+
+"l_SubC" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Sub with Carry: SubC(a, b) = a - b - carry",
+ "arity" => 2,
+},
+
"DivMod" => {
"op_flags" => "F|L",
"state" => "exc_pinned",
- "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "eax in_r1", "edx in_r3" ] },
+ "reg_req" => { "in" => [ "eax", "gp", "edx", "none" ], "out" => [ "eax", "edx" ] },
"attr" => "ia32_op_flavour_t dm_flav",
"init_attr" => " attr->data.op_flav = dm_flav;",
"cmp_attr" => " return attr_a->data.op_flav != attr_b->data.op_flav;\n",
"emit" =>
-' if (mode_is_signed(get_irn_mode(n))) {
+' if (mode_is_signed(get_ia32_res_mode(n))) {
4. idiv %S2 /* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
}
else {
"outs" => [ "res", "M" ],
},
+"l_Shl" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Shl: Shl(a, b) = a << b",
+ "arity" => 2
+},
+
+"ShlD" => {
+ "irn_flags" => "R",
+ "comment" => "construct ShlD: ShlD(a, b, c) = a, b << count (shift left count bits from b into a)",
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r5" ] },
+ "emit" =>
+'
+if (get_ia32_immop_type(n) == ia32_ImmNone) {
+ if (get_ia32_op_type(n) == ia32_AddrModeD) {
+4. shld %ia32_emit_am, %S4, %%cl /* ShlD(%A3, %A4, %A5) -> %D1 */
+ }
+ else {
+4. shld %S3, %S4, %%cl /* ShlD(%A3, %A4, %A5) -> %D1 */
+ }
+}
+else {
+ if (get_ia32_op_type(n) == ia32_AddrModeD) {
+4. shld %ia32_emit_am, %S4, %C /* ShlD(%A3, %A4, %A5) -> %D1 */
+ }
+ else {
+4. shld %S3, %S4, %C /* ShlD(%A3, %A4, %A5) -> %D1 */
+ }
+}
+',
+ "outs" => [ "res", "M" ],
+},
+
+"l_ShlD" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered ShlD: ShlD(a, b, c) = a, b << count (shift left count bits from b into a)",
+ "arity" => 3
+},
+
"Shr" => {
"irn_flags" => "R",
"comment" => "construct Shr: Shr(a, b) = a >> b",
"outs" => [ "res", "M" ],
},
+"l_Shr" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Shr: Shr(a, b) = a << b",
+ "arity" => 2
+},
+
+"ShrD" => {
+ "irn_flags" => "R",
+ "comment" => "construct ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)",
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r5" ] },
+ "emit" =>
+'
+if (get_ia32_immop_type(n) == ia32_ImmNone) {
+ if (get_ia32_op_type(n) == ia32_AddrModeD) {
+4. shrd %ia32_emit_am, %S4, %%cl /* ShrD(%A3, %A4, %A5) -> %D1 */
+ }
+ else {
+4. shrd %S3, %S4, %%cl /* ShrD(%A3, %A4, %A5) -> %D1 */
+ }
+}
+else {
+ if (get_ia32_op_type(n) == ia32_AddrModeD) {
+4. shrd %ia32_emit_am, %S4, %C /* ShrD(%A3, %A4, %A5) -> %D1 */
+ }
+ else {
+4. shrd %S3, %S4, %C /* ShrD(%A3, %A4, %A5) -> %D1 */
+ }
+}
+',
+ "outs" => [ "res", "M" ],
+},
+
+"l_ShrD" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)",
+ "arity" => 3
+},
+
"Shrs" => {
"irn_flags" => "R",
"comment" => "construct Shrs: Shrs(a, b) = a >> b",
"outs" => [ "res", "M" ],
},
+"l_Shrs" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Shrs: Shrs(a, b) = a << b",
+ "arity" => 2
+},
+
"RotR" => {
"irn_flags" => "R",
"comment" => "construct RotR: RotR(a, b) = a ROTR b",
"outs" => [ "res", "M" ],
},
+"l_Minus" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Minus: Minus(a) = -a",
+ "arity" => 1,
+},
+
"Inc" => {
"irn_flags" => "R",
"comment" => "construct Increment: Inc(a) = a++",
"irn_flags" => "R",
"comment" => "represents an integer constant",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
- "reg_req" => { "out" => [ "gp" ] },
+ "reg_req" => { "in" => [ "none" ], "out" => [ "gp" ] },
},
"Cdq" => {
"Load" => {
"op_flags" => "L|F",
- "irn_flags" => "R",
"state" => "exc_pinned",
"comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"outs" => [ "res", "M" ],
},
+"l_Load" => {
+ "op_flags" => "L|F",
+ "cmp_attr" => " return 1;\n",
+ "comment" => "construct lowered Load: Load(ptr, mem) = LD ptr -> reg",
+ "outs" => [ "res", "M" ],
+ "arity" => 2,
+},
+
+"l_Store" => {
+ "op_flags" => "L|F",
+ "cmp_attr" => " return 1;\n",
+ "state" => "exc_pinned",
+ "comment" => "construct lowered Store: Store(ptr, val, mem) = ST ptr,val",
+ "arity" => 3,
+ "outs" => [ "M" ],
+},
+
"Store" => {
"op_flags" => "L|F",
"state" => "exc_pinned",
"Push" => {
"comment" => "push a gp register on the stack",
"reg_req" => { "in" => [ "esp", "gp", "none" ], "out" => [ "esp" ] },
- "emit" => '. push %S2 /* Push(%A2) */',
+ "emit" => '
+if (get_ia32_id_cnst(n)) {
+ if (get_ia32_immop_type(n) == ia32_ImmConst) {
+4. push %C /* Push const on stack */
+} else {
+4. push OFFSET FLAT:%C /* Push symconst on stack */
+ }
+}
+else if (get_ia32_op_type(n) == ia32_Normal) {
+2. push %S2 /* Push(%A2) */
+}
+else {
+2. push %ia32_emit_am /* Push memory to stack */
+};
+',
"outs" => [ "stack", "M" ],
},
"Pop" => {
"comment" => "pop a gp register from the stack",
"reg_req" => { "in" => [ "esp", "none" ], "out" => [ "gp", "esp" ] },
- "emit" => '. pop %D1 /* Pop -> %D1 */',
+ "emit" => '
+if (get_ia32_op_type(n) == ia32_Normal) {
+2. pop %D1 /* Pop from stack into %D1 */
+}
+else {
+2. pop %ia32_emit_am /* Pop from stack into memory */
+}
+',
"outs" => [ "res", "stack", "M" ],
},
"outs" => [ "frame", "stack", "M" ],
},
+"AddSP" => {
+ "irn_flags" => "S|I",
+ "comment" => "allocate space on stack",
+ "reg_req" => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] },
+ "outs" => [ "stack", "M" ],
+},
+
#-----------------------------------------------------------------------------#
# _____ _____ ______ __ _ _ _ #
# / ____/ ____| ____| / _| | | | | | #
# not commutative operations
+"xAndNot" => {
+ "irn_flags" => "R",
+ "comment" => "construct SSE AndNot: AndNot(a, b) = a AND NOT b",
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3 !in_r4" ] },
+ "emit" => '. andnp%M %ia32_emit_binop /* SSE AndNot(%A3, %A4) -> %D1 */',
+ "outs" => [ "res", "M" ],
+},
+
"xSub" => {
"irn_flags" => "R",
"comment" => "construct SSE Sub: Sub(a, b) = a - b",
# other operations
+"xCmp" => {
+ "irn_flags" => "R",
+ "comment" => "construct SSE Compare: Cmp(a, b) == a = a cmp b",
+ "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3 !in_r4" ] },
+ "outs" => [ "res", "M" ],
+},
+
"xCondJmp" => {
"op_flags" => "L|X|Y",
"comment" => "construct conditional jump: UCOMIS A, B && JMPxx LABEL",
"irn_flags" => "R",
"comment" => "represents a SSE constant",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
- "reg_req" => { "out" => [ "xmm" ] },
- "emit" => '. mov%M %D1, %C /* Load fConst into register */',
+ "reg_req" => { "in" => [ "none" ], "out" => [ "xmm" ] },
+ "emit" => '. movs%M %D1, %C /* Load fConst into register */',
},
# Load / Store
"xLoad" => {
"op_flags" => "L|F",
- "irn_flags" => "R",
"state" => "exc_pinned",
"comment" => "construct SSE Load: Load(ptr, mem) = LD ptr",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"outs" => [ "M" ],
},
+"xStoreSimple" => {
+ "op_flags" => "L|F",
+ "state" => "exc_pinned",
+ "comment" => "construct Store without index: Store(ptr, val, mem) = ST ptr,val",
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "reg_req" => { "in" => [ "gp", "xmm", "none" ] },
+ "emit" => '. movs%M %ia32_emit_am, %S2 /* store XMM0 onto stack */',
+ "outs" => [ "M" ],
+},
+
+"l_X87toSSE" => {
+ "op_flags" => "L|F",
+ "comment" => "construct: transfer a value from x87 FPU into a SSE register",
+ "cmp_attr" => " return 1;\n",
+ "arity" => 3,
+},
+
+"l_SSEtoX87" => {
+ "op_flags" => "L|F",
+ "comment" => "construct: transfer a value from SSE register to x87 FPU",
+ "cmp_attr" => " return 1;\n",
+ "arity" => 3,
+},
+
+"GetST0" => {
+ "op_flags" => "L|F",
+ "irn_flags" => "I",
+ "state" => "exc_pinned",
+ "comment" => "store ST0 onto stack",
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "reg_req" => { "in" => [ "gp", "none" ] },
+ "emit" => '. fstp %ia32_emit_am /* store ST0 onto stack */',
+ "outs" => [ "M" ],
+},
+
+"SetST0" => {
+ "op_flags" => "L|F",
+ "irn_flags" => "I",
+ "state" => "exc_pinned",
+ "comment" => "load ST0 from stack",
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "st0", "none" ] },
+ "emit" => '. fld %ia32_emit_am /* load ST0 from stack */',
+ "outs" => [ "res", "M" ],
+},
+
# CopyB
"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" => [ "none" ] },
+ "reg_req" => { "in" => [ "edi", "esi", "ecx", "none" ], "out" => [ "edi", "esi", "ecx", "none" ] },
+ "outs" => [ "DST", "SRC", "CNT", "M" ],
},
"CopyB_i" => {
"state" => "pinned",
"comment" => "implements a memcopy: CopyB(dst, src, mem) == memcpy(dst, src, attr(size))",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
- "reg_req" => { "in" => [ "edi", "esi", "none" ], "out" => [ "none" ] },
+ "reg_req" => { "in" => [ "edi", "esi", "none" ], "out" => [ "edi", "esi", "none" ] },
+ "outs" => [ "DST", "SRC", "M" ],
},
# Conversions
"outs" => [ "res", "M" ],
},
+"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" ] }
+},
+
+"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" ] }
+},
+
+"xCmpCMov" => {
+ "irn_flags" => "R",
+ "comment" => "construct Conditional Move: SSE Compare + int CMov ",
+ "reg_req" => { "in" => [ "xmm", "xmm", "gp", "gp" ], "out" => [ "in_r4" ] }
+},
+
+"vfCmpCMov" => {
+ "irn_flags" => "R",
+ "comment" => "construct Conditional Move: x87 Compare + int CMov",
+ "reg_req" => { "in" => [ "vfp", "vfp", "gp", "gp" ], "out" => [ "in_r4" ] }
+},
+
+"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", "none" ] },
+ "outs" => [ "res", "M" ],
+},
+
+"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" ] },
+},
+
+"xCmpSet" => {
+ "irn_flags" => "R",
+ "comment" => "construct Set: SSE Compare + int Set",
+ "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "eax ebx ecx edx", "none" ] },
+ "outs" => [ "res", "M" ],
+},
+
+"vfCmpSet" => {
+ "irn_flags" => "R",
+ "comment" => "construct Set: x87 Compare + int Set",
+ "reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "eax ebx ecx edx", "none" ] },
+ "outs" => [ "res", "M" ],
+},
+
+"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" ] }
+},
+
#----------------------------------------------------------#
# _ _ _ __ _ _ #
# (_) | | | | / _| | | | #
"vfmul" => {
"irn_flags" => "R",
- "comment" => "virtual fp Mul: Mul(a, b) = Mul(b, a) = a + b",
+ "comment" => "virtual fp Mul: Mul(a, b) = Mul(b, a) = a * b",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
"outs" => [ "res", "M" ],
},
+"l_vfmul" => {
+ "op_flags" => "C",
+ "cmp_attr" => " return 1;\n",
+ "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",
"outs" => [ "res", "M" ],
},
+"l_vfsub" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "lowered virtual fp Sub: Sub(a, b) = a - b",
+ "arity" => 2,
+},
+
"vfdiv" => {
"comment" => "virtual fp Div: Div(a, b) = a / b",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"outs" => [ "res", "M" ],
},
+"l_vfdiv" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "lowered virtual fp Div: Div(a, b) = a / b",
+ "arity" => 2,
+},
+
"vfabs" => {
"irn_flags" => "R",
"comment" => "virtual fp Abs: Abs(a) = |a|",
"vfld" => {
"op_flags" => "L|F",
- "irn_flags" => "R",
"state" => "exc_pinned",
"comment" => "virtual fp Load: Load(ptr, mem) = LD ptr -> reg",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
# Conversions
"vfild" => {
- "irn_flags" => "R",
"comment" => "virtual fp integer Load: Load(ptr, mem) = iLD ptr -> reg",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "vfp", "none" ] },
"outs" => [ "res", "M" ],
},
+"l_vfild" => {
+ "cmp_attr" => " return 1;\n",
+ "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",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"outs" => [ "M" ],
},
+"l_vfist" => {
+ "cmp_attr" => " return 1;\n",
+ "comment" => "lowered virtual fp integer Store: Store(ptr, val, mem) = iST ptr,val",
+ "outs" => [ "M" ],
+ "arity" => 3,
+},
+
+
# constants
"vfldz" => {
"vfConst" => {
"op_flags" => "c",
"irn_flags" => "R",
+ "init_attr" => " set_ia32_ls_mode(res, mode);",
"comment" => "represents a virtual floating point constant",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
- "reg_req" => { "out" => [ "vfp" ] },
+ "reg_req" => { "in" => [ "none" ], "out" => [ "vfp" ] },
},
# other
"fild" => {
"op_flags" => "R",
- "irn_flags" => "R",
+ "rd_constructor" => "NONE",
"comment" => "x87 fp integer Load: Load(ptr, mem) = iLD ptr -> reg",
"reg_req" => { },
"emit" => '. fild %ia32_emit_am /* integer Load((%A1)) -> %D1 */',
"fldz" => {
"op_flags" => "R",
+ "irn_flags" => "R",
"rd_constructor" => "NONE",
"comment" => "x87 fp Load 0.0: Ld 0.0 -> reg",
"reg_req" => { },
"fld1" => {
"op_flags" => "R",
+ "irn_flags" => "R",
"rd_constructor" => "NONE",
"comment" => "x87 fp Load 1.0: Ld 1.0 -> reg",
"reg_req" => { },
"fldpi" => {
"op_flags" => "R",
+ "irn_flags" => "R",
"rd_constructor" => "NONE",
"comment" => "x87 fp Load pi: Ld pi -> reg",
"reg_req" => { },
"fldln2" => {
"op_flags" => "R",
+ "irn_flags" => "R",
"rd_constructor" => "NONE",
"comment" => "x87 fp Load ln 2: Ld ln 2 -> reg",
"reg_req" => { },
"fldlg2" => {
"op_flags" => "R",
+ "irn_flags" => "R",
"rd_constructor" => "NONE",
"comment" => "x87 fp Load lg 2: Ld lg 2 -> reg",
"reg_req" => { },
"fldl2t" => {
"op_flags" => "R",
+ "irn_flags" => "R",
"rd_constructor" => "NONE",
"comment" => "x87 fp Load ld 10: Ld ld 10 -> reg",
"reg_req" => { },
"fldl2e" => {
"op_flags" => "R",
+ "irn_flags" => "R",
"rd_constructor" => "NONE",
"comment" => "x87 fp Load ld e: Ld ld e -> reg",
"reg_req" => { },
},
"fldConst" => {
- "op_flags" => "R",
- "op_flags" => "c",
+ "op_flags" => "R|c",
"irn_flags" => "R",
+ "rd_constructor" => "NONE",
"comment" => "represents a x87 constant",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "out" => [ "st" ] },
- "emit" => '. fld%M %C /* Load fConst into register -> %D1 */',
+ "emit" => '. fld %ia32_emit_adr /* Load fConst into register -> %D1 */',
},
# fxch, fpush, fpop