#
# <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")
#
"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", "gp", "gp", "none" ], "out" => [ "eax in_r3", "edx" ] },
+ "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx" ] },
"emit" => '. mul %ia32_emit_unop /* Mul(%A1, %A2) -> %D1 */',
"outs" => [ "EAX", "EDX", "M" ],
},
"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" ] },
+ "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx" ] },
"emit" => '. imul %ia32_emit_unop /* Mulh(%A1, %A2) -> %D1 */',
"outs" => [ "EAX", "EDX", "M" ],
},
"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 {
"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",
"emit" => '
if (get_ia32_id_cnst(n)) {
if (get_ia32_immop_type(n) == ia32_ImmConst) {
-. push %C /* Push(%A2) */
- } else {
-. push OFFSET FLAT:%C /* Push(%A2) */
+4. push %C /* Push const on stack */
+} else {
+4. push OFFSET FLAT:%C /* Push symconst on stack */
}
}
-else {
-. push %S2 /* Push(%A2) */
+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" ],
+},
+
#-----------------------------------------------------------------------------#
# _____ _____ ______ __ _ _ _ #
# / ____/ ____| ____| / _| | | | | | #
"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",
"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
"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" ] },
"fild" => {
"op_flags" => "R",
- "irn_flags" => "R",
"rd_constructor" => "NONE",
"comment" => "x87 fp integer Load: Load(ptr, mem) = iLD ptr -> reg",
"reg_req" => { },
"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" => { },