X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_spec.pl;h=f4c6328aa3561886e896c899d37d1043d40055fd;hb=a1a465eb2b3f54027b29f829423fffd0396937f4;hp=2964ac3282a627473cd6540820b92b23ade8d3ab;hpb=d0fd8cbd543084f073614b26cfd914977add11cb;p=libfirm diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 2964ac328..f4c6328aa 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -73,6 +73,10 @@ $comment_string = "/*"; # # outs: if a node defines more than one output, the names of the projections # nodes having outs having automatically the mode mode_T +# One can also annotate some flags for each out, additional to irn_flags. +# They are separated from name with a colon ':', and concatenated by pipe '|' +# Only I and S are available at the moment (same meaning as in irn_flags). +# example: [ "frame:I", "stack:I|S", "M" ] # # comment: OPTIONAL comment for the node constructor # @@ -100,6 +104,8 @@ $comment_string = "/*"; # 1 - caller save (register must be saved by the caller of a function) # 2 - callee save (register must be saved by the called function) # 4 - ignore (do not assign this register) +# 8 - emitter can choose an arbitrary register of this class +# 16 - the register is a virtual one # NOTE: Last entry of each class is the largest Firm-Mode a register can hold %reg_classes = ( "gp" => [ @@ -133,8 +139,8 @@ $comment_string = "/*"; # { "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" => "gp_UKNWN", "type" => 6 }, # we need a dummy register for Unknown nodes + { "name" => "gp_NOREG", "type" => 2 | 4 | 16 }, # we need a dummy register for NoReg nodes + { "name" => "gp_UKNWN", "type" => 2 | 4 | 8 | 16}, # we need a dummy register for Unknown nodes { "mode" => "mode_P" } ], "xmm" => [ @@ -146,21 +152,21 @@ $comment_string = "/*"; { "name" => "xmm5", "type" => 1 }, { "name" => "xmm6", "type" => 1 }, { "name" => "xmm7", "type" => 1 }, - { "name" => "xmm_NOREG", "type" => 6 }, # we need a dummy register for NoReg nodes - { "name" => "xmm_UKNWN", "type" => 6 }, # we need a dummy register for Unknown nodes + { "name" => "xmm_NOREG", "type" => 2 | 4 | 16 }, # we need a dummy register for NoReg nodes + { "name" => "xmm_UKNWN", "type" => 2 | 4 | 8 | 16}, # we need a dummy register for Unknown nodes { "mode" => "mode_D" } ], "vfp" => [ - { "name" => "vf0", "type" => 1 }, - { "name" => "vf1", "type" => 1 }, - { "name" => "vf2", "type" => 1 }, - { "name" => "vf3", "type" => 1 }, - { "name" => "vf4", "type" => 1 }, - { "name" => "vf5", "type" => 1 }, - { "name" => "vf6", "type" => 1 }, - { "name" => "vf7", "type" => 1 }, - { "name" => "vfp_NOREG", "type" => 6 }, # we need a dummy register for NoReg nodes - { "name" => "vfp_UKNWN", "type" => 6 }, # we need a dummy register for Unknown nodes + { "name" => "vf0", "type" => 1 | 16 }, + { "name" => "vf1", "type" => 1 | 16 }, + { "name" => "vf2", "type" => 1 | 16 }, + { "name" => "vf3", "type" => 1 | 16 }, + { "name" => "vf4", "type" => 1 | 16 }, + { "name" => "vf5", "type" => 1 | 16 }, + { "name" => "vf6", "type" => 1 | 16 }, + { "name" => "vf7", "type" => 1 | 16 }, + { "name" => "vfp_NOREG", "type" => 2 | 4 | 16 }, # we need a dummy register for NoReg nodes + { "name" => "vfp_UKNWN", "type" => 2 | 4 | 8 | 16}, # we need a dummy register for Unknown nodes { "mode" => "mode_E" } ], "st" => [ @@ -246,6 +252,8 @@ $comment_string = "/*"; }, "MulS" => { + # we should not rematrialize this node. It produces 2 results and has + # very strict constrains "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" ] }, @@ -255,6 +263,8 @@ $comment_string = "/*"; }, "l_MulS" => { + # we should not rematrialize this node. It produces 2 results and has + # very strict constrains "op_flags" => "C", "cmp_attr" => " return 1;\n", "comment" => "construct lowered MulS: MulS(a, b) = MulS(b, a) = a * b", @@ -281,6 +291,8 @@ $comment_string = "/*"; # Mulh is an exception from the 4 INs with AM because the target is always EAX:EDX "Mulh" => { + # we should not rematrialize this node. It produces 2 results and has + # very strict constrains "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", "eax", "gp", "none" ], "out" => [ "eax", "edx" ] }, @@ -369,7 +381,7 @@ $comment_string = "/*"; "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" ] }, + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. sbb %ia32_emit_binop /* SubC(%A3, %A4) -> %D1 */', "outs" => [ "res", "M" ], }, @@ -410,7 +422,7 @@ $comment_string = "/*"; "irn_flags" => "R", "comment" => "construct Shl: Shl(a, b) = a << b", "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", - "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] }, + "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx gp_NOREG", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. shl %ia32_emit_binop /* Shl(%A1, %A2) -> %D1 */', "outs" => [ "res", "M" ], }, @@ -425,7 +437,15 @@ $comment_string = "/*"; "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" ] }, + # Out requirements is: different from all in + # This is because, out must be different from LowPart and ShiftCount. + # We could say "!ecx !in_r4" but it can occur, that all values live through + # this Shift and the only value dying is the ShiftCount. Then there would be a + # register missing, as result must not be ecx and all other registers are + # occupied. What we should write is "!in_r4 !in_r5", but this is not supported + # (and probably never will). So we create artificial interferences of the result + # with all inputs, so the spiller can always assure a free register. + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "ecx", "none" ], "out" => [ "!in" ] }, "emit" => ' if (get_ia32_immop_type(n) == ia32_ImmNone) { @@ -459,7 +479,7 @@ else { "irn_flags" => "R", "comment" => "construct Shr: Shr(a, b) = a >> b", "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", - "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] }, + "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx gp_NOREG", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. shr %ia32_emit_binop /* Shr(%A1, %A2) -> %D1 */', "outs" => [ "res", "M" ], }, @@ -474,7 +494,15 @@ else { "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" ] }, + # Out requirements is: different from all in + # This is because, out must be different from LowPart and ShiftCount. + # We could say "!ecx !in_r4" but it can occur, that all values live through + # this Shift and the only value dying is the ShiftCount. Then there would be a + # register missing, as result must not be ecx and all other registers are + # occupied. What we should write is "!in_r4 !in_r5", but this is not supported + # (and probably never will). So we create artificial interferences of the result + # with all inputs, so the spiller can always assure a free register. + "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "ecx", "none" ], "out" => [ "!in" ] }, "emit" => ' if (get_ia32_immop_type(n) == ia32_ImmNone) { @@ -508,7 +536,7 @@ else { "irn_flags" => "R", "comment" => "construct Shrs: Shrs(a, b) = a >> b", "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", - "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] }, + "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx gp_NOREG", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. sar %ia32_emit_binop /* Shrs(%A1, %A2) -> %D1 */', "outs" => [ "res", "M" ], }, @@ -629,11 +657,12 @@ else { "irn_flags" => "R", "comment" => "represents an integer constant", "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", - "reg_req" => { "in" => [ "none" ], "out" => [ "gp" ] }, + "reg_req" => { "out" => [ "gp" ] }, }, "Cdq" => { - "irn_flags" => "R", + # we should not rematrialize this node. It produces 2 results and has + # very strict constrains "comment" => "construct CDQ: sign extend EAX -> EDX:EAX", "reg_req" => { "in" => [ "gp" ], "out" => [ "eax in_r1", "edx" ] }, "emit" => '. cdq /* sign extend EAX -> EDX:EAX, (%A1) */', @@ -648,6 +677,7 @@ else { "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "gp" ] }, + "latency" => 3, "emit" => ' if (get_mode_size_bits(get_ia32_ls_mode(n)) < 32) { 4. mov%Mx %D1, %ia32_emit_am /* Load((%A1)) -> %D1 */ @@ -684,6 +714,7 @@ else { "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ] }, "emit" => '. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */', "outs" => [ "M" ], + "latency" => 3, }, "Store8Bit" => { @@ -691,9 +722,10 @@ else { "state" => "exc_pinned", "comment" => "construct 8Bit Store: Store(ptr, val, mem) = ST ptr,val", "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", - "reg_req" => { "in" => [ "gp", "gp", "eax ebx ecx edx", "none" ] }, + "reg_req" => { "in" => [ "gp", "gp", "eax ebx ecx edx gp_NOREG", "none" ] }, "emit" => '. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */', "outs" => [ "M" ], + "latency" => 3, }, "Lea" => { @@ -706,39 +738,19 @@ else { }, "Push" => { - "comment" => "push a gp register on the stack", - "reg_req" => { "in" => [ "esp", "gp", "none" ], "out" => [ "esp" ] }, - "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" ], + "comment" => "push on the stack", + "reg_req" => { "in" => [ "gp", "gp", "gp", "esp", "none" ], "out" => [ "esp" ] }, + "emit" => '. push %ia32_emit_unop /* PUSH(%A1) */', + "outs" => [ "stack:I|S", "M" ], "latency" => 3, }, "Pop" => { + # We don't set class modify stack here (but we will do this on proj 1) "comment" => "pop a gp register from the stack", - "reg_req" => { "in" => [ "esp", "none" ], "out" => [ "gp", "esp" ] }, - "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" ], + "reg_req" => { "in" => [ "gp", "gp", "esp", "none" ], "out" => [ "gp", "esp" ] }, + "emit" => '. pop %ia32_emit_unop /* POP(%A1) */', + "outs" => [ "res", "stack:I|S", "M" ], "latency" => 4, }, @@ -746,7 +758,7 @@ else { "comment" => "create stack frame", "reg_req" => { "in" => [ "esp" ], "out" => [ "ebp", "esp" ] }, "emit" => '. enter /* Enter */', - "outs" => [ "frame", "stack", "M" ], + "outs" => [ "frame:I", "stack:I|S", "M" ], "latency" => 15, }, @@ -754,17 +766,32 @@ else { "comment" => "destroy stack frame", "reg_req" => { "in" => [ "esp", "ebp" ], "out" => [ "ebp", "esp" ] }, "emit" => '. leave /* Leave */', - "outs" => [ "frame", "stack", "M" ], + "outs" => [ "frame:I", "stack:I|S", "M" ], "latency" => 3, }, "AddSP" => { - "irn_flags" => "S|I", + "irn_flags" => "I", "comment" => "allocate space on stack", "reg_req" => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] }, - "outs" => [ "stack", "M" ], + "outs" => [ "stack:S", "M" ], +}, + +"SubSP" => { + "irn_flags" => "I", + "comment" => "free space on stack", + "reg_req" => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] }, + "outs" => [ "stack:S", "M" ], }, +"LdTls" => { + "irn_flags" => "R", + "comment" => "get the TLS base address", + "reg_req" => { "out" => [ "gp" ] }, +}, + + + #-----------------------------------------------------------------------------# # _____ _____ ______ __ _ _ _ # # / ____/ ____| ____| / _| | | | | | # @@ -901,7 +928,7 @@ else { "irn_flags" => "R", "comment" => "represents a SSE constant", "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", - "reg_req" => { "in" => [ "none" ], "out" => [ "xmm" ] }, + "reg_req" => { "out" => [ "xmm" ] }, "emit" => '. movs%M %D1, %C /* Load fConst into register */', "latency" => 2, }, @@ -973,7 +1000,7 @@ else { "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" ] }, + "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "vf0", "none" ] }, "emit" => '. fld %ia32_emit_am /* load ST0 from stack */', "outs" => [ "res", "M" ], "latency" => 2, @@ -1319,7 +1346,7 @@ else { "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" => { "in" => [ "none" ], "out" => [ "vfp" ] }, + "reg_req" => { "out" => [ "vfp" ] }, "latency" => 3, }, @@ -1347,7 +1374,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 Add: Add(a, b) = Add(b, a) = a + b", "reg_req" => { }, - "emit" => '. fadd %ia32_emit_x87_binop /* x87 fadd(%A1, %A2) -> %D1 */', + "emit" => '. fadd %ia32_emit_x87_binop /* x87 fadd(%A3, %A4) -> %D1 */', }, "faddp" => { @@ -1355,7 +1382,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 Add: Add(a, b) = Add(b, a) = a + b", "reg_req" => { }, - "emit" => '. faddp %ia32_emit_x87_binop /* x87 fadd(%A1, %A2) -> %D1 */', + "emit" => '. faddp %ia32_emit_x87_binop /* x87 fadd(%A3, %A4) -> %D1 */', }, "fmul" => { @@ -1363,7 +1390,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Mul: Mul(a, b) = Mul(b, a) = a + b", "reg_req" => { }, - "emit" => '. fmul %ia32_emit_x87_binop /* x87 fmul(%A1, %A2) -> %D1 */', + "emit" => '. fmul %ia32_emit_x87_binop /* x87 fmul(%A3, %A4) -> %D1 */', }, "fmulp" => { @@ -1371,7 +1398,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Mul: Mul(a, b) = Mul(b, a) = a + b", "reg_req" => { }, - "emit" => '. fmulp %ia32_emit_x87_binop /* x87 fmul(%A1, %A2) -> %D1 */',, + "emit" => '. fmulp %ia32_emit_x87_binop /* x87 fmul(%A3, %A4) -> %D1 */',, }, "fsub" => { @@ -1379,7 +1406,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Sub: Sub(a, b) = a - b", "reg_req" => { }, - "emit" => '. fsub %ia32_emit_x87_binop /* x87 fsub(%A1, %A2) -> %D1 */', + "emit" => '. fsub %ia32_emit_x87_binop /* x87 fsub(%A3, %A4) -> %D1 */', }, "fsubp" => { @@ -1387,7 +1414,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Sub: Sub(a, b) = a - b", "reg_req" => { }, - "emit" => '. fsubp %ia32_emit_x87_binop /* x87 fsub(%A1, %A2) -> %D1 */', + "emit" => '. fsubp %ia32_emit_x87_binop /* x87 fsub(%A3, %A4) -> %D1 */', }, "fsubr" => { @@ -1396,7 +1423,7 @@ else { "irn_flags" => "R", "comment" => "x87 fp SubR: SubR(a, b) = b - a", "reg_req" => { }, - "emit" => '. fsubr %ia32_emit_x87_binop /* x87 fsubr(%A1, %A2) -> %D1 */', + "emit" => '. fsubr %ia32_emit_x87_binop /* x87 fsubr(%A3, %A4) -> %D1 */', }, "fsubrp" => { @@ -1405,7 +1432,7 @@ else { "irn_flags" => "R", "comment" => "x87 fp SubR: SubR(a, b) = b - a", "reg_req" => { }, - "emit" => '. fsubrp %ia32_emit_x87_binop /* x87 fsubr(%A1, %A2) -> %D1 */', + "emit" => '. fsubrp %ia32_emit_x87_binop /* x87 fsubr(%A3, %A4) -> %D1 */', }, "fdiv" => { @@ -1413,7 +1440,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Div: Div(a, b) = a / b", "reg_req" => { }, - "emit" => '. fdiv %ia32_emit_x87_binop /* x87 fdiv(%A1, %A2) -> %D1 */', + "emit" => '. fdiv %ia32_emit_x87_binop /* x87 fdiv(%A3, %A4) -> %D1 */', }, "fdivp" => { @@ -1421,7 +1448,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Div: Div(a, b) = a / b", "reg_req" => { }, - "emit" => '. fdivp %ia32_emit_x87_binop /* x87 fdiv(%A1, %A2) -> %D1 */', + "emit" => '. fdivp %ia32_emit_x87_binop /* x87 fdiv(%A3, %A4) -> %D1 */', }, "fdivr" => { @@ -1429,7 +1456,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp DivR: DivR(a, b) = b / a", "reg_req" => { }, - "emit" => '. fdivr %ia32_emit_x87_binop /* x87 fdivr(%A1, %A2) -> %D1 */', + "emit" => '. fdivr %ia32_emit_x87_binop /* x87 fdivr(%A3, %A4) -> %D1 */', }, "fdivrp" => { @@ -1437,7 +1464,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp DivR: DivR(a, b) = b / a", "reg_req" => { }, - "emit" => '. fdivrp %ia32_emit_x87_binop /* x87 fdivr(%A1, %A2) -> %D1 */', + "emit" => '. fdivrp %ia32_emit_x87_binop /* x87 fdivr(%A3, %A4) -> %D1 */', }, "fabs" => { @@ -1445,7 +1472,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Abs: Abs(a) = |a|", "reg_req" => { }, - "emit" => '. fabs /* x87 fabs(%S1) -> %D1 */', + "emit" => '. fabs /* x87 fabs(%A1) -> %D1 */', }, "fchs" => { @@ -1453,7 +1480,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Chs: Chs(a) = -a", "reg_req" => { }, - "emit" => '. fchs /* x87 fchs(%S1) -> %D1 */', + "emit" => '. fchs /* x87 fchs(%A1) -> %D1 */', }, "fsin" => { @@ -1461,7 +1488,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Sin: Sin(a) = sin(a)", "reg_req" => { }, - "emit" => '. fsin /* x87 sin(%S1) -> %D1 */', + "emit" => '. fsin /* x87 sin(%A1) -> %D1 */', }, "fcos" => { @@ -1469,7 +1496,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Cos: Cos(a) = cos(a)", "reg_req" => { }, - "emit" => '. fcos /* x87 cos(%S1) -> %D1 */', + "emit" => '. fcos /* x87 cos(%A1) -> %D1 */', }, "fsqrt" => { @@ -1477,7 +1504,7 @@ else { "rd_constructor" => "NONE", "comment" => "x87 fp Sqrt: Sqrt(a) = a ^ 0.5", "reg_req" => { }, - "emit" => '. fsqrt $ /* x87 sqrt(%S1) -> %D1 */', + "emit" => '. fsqrt $ /* x87 sqrt(%A1) -> %D1 */', }, # x87 Load and Store @@ -1538,65 +1565,58 @@ else { # constants "fldz" => { - "op_flags" => "R", + "op_flags" => "R|c", "irn_flags" => "R", - "rd_constructor" => "NONE", "comment" => "x87 fp Load 0.0: Ld 0.0 -> reg", - "reg_req" => { }, + "reg_req" => { "out" => [ "vfp" ] }, "emit" => '. fldz /* x87 0.0 -> %D1 */', }, "fld1" => { - "op_flags" => "R", + "op_flags" => "R|c", "irn_flags" => "R", - "rd_constructor" => "NONE", "comment" => "x87 fp Load 1.0: Ld 1.0 -> reg", - "reg_req" => { }, + "reg_req" => { "out" => [ "vfp" ] }, "emit" => '. fld1 /* x87 1.0 -> %D1 */', }, "fldpi" => { - "op_flags" => "R", + "op_flags" => "R|c", "irn_flags" => "R", - "rd_constructor" => "NONE", "comment" => "x87 fp Load pi: Ld pi -> reg", - "reg_req" => { }, + "reg_req" => { "out" => [ "vfp" ] }, "emit" => '. fldpi /* x87 pi -> %D1 */', }, "fldln2" => { - "op_flags" => "R", + "op_flags" => "R|c", "irn_flags" => "R", - "rd_constructor" => "NONE", "comment" => "x87 fp Load ln 2: Ld ln 2 -> reg", - "reg_req" => { }, + "reg_req" => { "out" => [ "vfp" ] }, "emit" => '. fldln2 /* x87 ln(2) -> %D1 */', }, "fldlg2" => { - "op_flags" => "R", + "op_flags" => "R|c", "irn_flags" => "R", - "rd_constructor" => "NONE", "comment" => "x87 fp Load lg 2: Ld lg 2 -> reg", - "reg_req" => { }, + "reg_req" => { "out" => [ "vfp" ] }, "emit" => '. fldlg2 /* x87 log(2) -> %D1 */', }, "fldl2t" => { - "op_flags" => "R", + "op_flags" => "R|c", "irn_flags" => "R", - "rd_constructor" => "NONE", "comment" => "x87 fp Load ld 10: Ld ld 10 -> reg", - "reg_req" => { }, + "reg_req" => { "out" => [ "vfp" ] }, "emit" => '. fldll2t /* x87 ld(10) -> %D1 */', }, "fldl2e" => { - "op_flags" => "R", + "op_flags" => "R|c", "irn_flags" => "R", - "rd_constructor" => "NONE", "comment" => "x87 fp Load ld e: Ld ld e -> reg", - "reg_req" => { }, + "reg_req" => { "out" => [ "vfp" ] }, "emit" => '. fldl2e /* x87 ld(e) -> %D1 */', }, @@ -1606,25 +1626,34 @@ else { "rd_constructor" => "NONE", "comment" => "represents a x87 constant", "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", - "reg_req" => { "out" => [ "st" ] }, + "reg_req" => { "out" => [ "vfp" ] }, "emit" => '. fld %ia32_emit_adr /* Load fConst into register -> %D1 */', }, # fxch, fpush, fpop # Note that it is NEVER allowed to do CSE on these nodes +# Moreover, note the virtual register requierements! "fxch" => { "op_flags" => "R|K", "comment" => "x87 stack exchange", - "reg_req" => { "in" => [ "st"], "out" => [ "st" ] }, + "reg_req" => { }, "cmp_attr" => " return 1;\n", "emit" => '. fxch %X1 /* x87 swap %X1, %X3 */', }, "fpush" => { + "op_flags" => "R|K", + "comment" => "x87 stack push", + "reg_req" => {}, + "cmp_attr" => " return 1;\n", + "emit" => '. fld %X1 /* x87 push %X1 */', +}, + +"fpushCopy" => { "op_flags" => "R", "comment" => "x87 stack push", - "reg_req" => { "in" => [ "st"], "out" => [ "st" ] }, + "reg_req" => { "in" => [ "vfp"], "out" => [ "vfp" ] }, "cmp_attr" => " return 1;\n", "emit" => '. fld %X1 /* x87 push %X1 */', }, @@ -1632,7 +1661,7 @@ else { "fpop" => { "op_flags" => "R|K", "comment" => "x87 stack pop", - "reg_req" => { "in" => [ "st"], "out" => [ "st" ] }, + "reg_req" => { }, "cmp_attr" => " return 1;\n", "emit" => '. fstp %X1 /* x87 pop %X1 */', },