added support for 64bit Minus lowering
[libfirm] / ir / be / ia32 / ia32_spec.pl
index 4a468af..c25cf1b 100644 (file)
@@ -104,6 +104,28 @@ $comment_string = "/*";
             { "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
@@ -191,10 +213,46 @@ $comment_string = "/*";
   "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",
+  "comment"   => "construct lowered Add: Add(a, b) = Add(b, a) = a + b",
+  "arity"     => 2,
+},
+
+"l_AddC" => {
+  "op_flags"  => "C",
+  "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", "gp", "gp", "none" ], "out" => [ "eax in_r3", "edx in_r4" ] },
+  "emit"      => '. mul %ia32_emit_binop /* Mul(%A1, %A2) -> %D1 */',
+  "outs"      => [ "EAX", "EDX", "M" ],
+},
+
+"l_MulS" => {
+  "op_flags"  => "C",
+  "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",
@@ -204,6 +262,12 @@ $comment_string = "/*";
   "outs"      => [ "res", "M" ],
 },
 
+"l_Mul" => {
+  "op_flags"  => "C",
+  "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",
@@ -270,16 +334,6 @@ $comment_string = "/*";
 '
 },
 
-"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" => {
@@ -287,10 +341,29 @@ $comment_string = "/*";
   "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",
+  "comment"   => "construct lowered Sub: Sub(a, b) = a - b",
+  "arity"     => 2,
+},
+
+"l_SubC" => {
+  "comment"   => "construct lowered Sub with Carry: SubC(a, b) = a - b - carry",
+  "arity"     => 2,
+},
+
 "DivMod" => {
   "op_flags"  => "F|L",
   "state"     => "exc_pinned",
@@ -318,6 +391,43 @@ $comment_string = "/*";
   "outs"      => [ "res", "M" ],
 },
 
+"l_Shl" => {
+  "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" => {
+  "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",
@@ -327,6 +437,43 @@ $comment_string = "/*";
   "outs"      => [ "res", "M" ],
 },
 
+"l_Shr" => {
+  "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" => {
+  "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",
@@ -336,6 +483,11 @@ $comment_string = "/*";
   "outs"      => [ "res", "M" ],
 },
 
+"l_Shrs" => {
+  "comment"   => "construct lowered Shrs: Shrs(a, b) = a << b",
+  "arity"     => 2
+},
+
 "RotR" => {
   "irn_flags" => "R",
   "comment"     => "construct RotR: RotR(a, b) = a ROTR b",
@@ -365,6 +517,11 @@ $comment_string = "/*";
   "outs"      => [ "res", "M" ],
 },
 
+"l_Minus" => {
+  "comment"   => "construct lowered Minus: Minus(a) = -a",
+  "arity"     => 1,
+},
+
 "Inc" => {
   "irn_flags" => "R",
   "comment"   => "construct Increment: Inc(a) = a++",
@@ -611,6 +768,15 @@ else {
 
 # 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",
@@ -631,6 +797,13 @@ else {
 
 # 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",
@@ -645,7 +818,7 @@ else {
   "comment"   => "represents a SSE constant",
   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "none" ], "out" => [ "xmm" ] },
-  "emit"      => '. mov%M %D1, %C /* Load fConst into register */',
+  "emit"      => '. movs%M %D1, %C /* Load fConst into register */',
 },
 
 # Load / Store
@@ -725,6 +898,63 @@ else {
   "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" ] }
+},
+
 #----------------------------------------------------------#
 #        _      _               _    __ _             _    #
 #       (_)    | |             | |  / _| |           | |   #
@@ -885,6 +1115,7 @@ else {
 "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"   => { "in" => [ "none" ], "out" => [ "vfp" ] },
@@ -1080,6 +1311,7 @@ else {
 "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 */',
@@ -1160,13 +1392,13 @@ else {
 },
 
 "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