fix cvt emitter
[libfirm] / ir / be / ia32 / ia32_spec.pl
index 8c82bd8..af4fc48 100644 (file)
@@ -2,15 +2,11 @@
 # $Id$
 # This is the specification for the ia32 assembler Firm-operations
 
+$new_emit_syntax = 1;
+
 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
 $arch = "ia32";
 
-# this string marks the beginning of a comment in emit
-$comment_string = "/*";
-
-# the number of additional opcodes you want to register
-#$additional_opcodes = 0;
-
 # The node description is done as a perl hash initializer with the
 # following structure:
 #
@@ -73,6 +69,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,82 +100,113 @@ $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" => [
-            { "name" => "eax", "type" => 1 },
-            { "name" => "edx", "type" => 1 },
-            { "name" => "ebx", "type" => 2 },
-            { "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" => "gp_UKNWN", "type" => 6 },  # we need a dummy register for Unknown nodes
-                       { "mode" => "mode_P" }
-          ],
-  "xmm" => [
-            { "name" => "xmm0", "type" => 1 },
-            { "name" => "xmm1", "type" => 1 },
-            { "name" => "xmm2", "type" => 1 },
-            { "name" => "xmm3", "type" => 1 },
-            { "name" => "xmm4", "type" => 1 },
-            { "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
-                       { "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
-                       { "mode" => "mode_E" }
-          ],
-  "st" => [
-            { "name" => "st0", "type" => 1 },
-            { "name" => "st1", "type" => 1 },
-            { "name" => "st2", "type" => 1 },
-            { "name" => "st3", "type" => 1 },
-            { "name" => "st4", "type" => 1 },
-            { "name" => "st5", "type" => 1 },
-            { "name" => "st6", "type" => 1 },
-            { "name" => "st7", "type" => 1 },
-                       { "mode" => "mode_E" }
-          ]
+       "gp" => [
+               { "name" => "eax", "type" => 1 },
+               { "name" => "edx", "type" => 1 },
+               { "name" => "ebx", "type" => 2 },
+               { "name" => "ecx", "type" => 1 },
+               { "name" => "esi", "type" => 2 },
+               { "name" => "edi", "type" => 2 },
+               { "name" => "ebp", "type" => 2 },
+               { "name" => "esp", "type" => 4 },
+               { "name" => "gp_NOREG", "type" => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
+               { "name" => "gp_UKNWN", "type" => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
+               { "mode" => "mode_Iu" }
+       ],
+       "xmm" => [
+               { "name" => "xmm0", "type" => 1 },
+               { "name" => "xmm1", "type" => 1 },
+               { "name" => "xmm2", "type" => 1 },
+               { "name" => "xmm3", "type" => 1 },
+               { "name" => "xmm4", "type" => 1 },
+               { "name" => "xmm5", "type" => 1 },
+               { "name" => "xmm6", "type" => 1 },
+               { "name" => "xmm7", "type" => 1 },
+               { "name" => "xmm_NOREG", "type" => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
+               { "name" => "xmm_UKNWN", "type" => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
+               { "mode" => "mode_E" }
+       ],
+       "vfp" => [
+               { "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" => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes
+               { "name" => "vfp_UKNWN", "type" => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
+               { "mode" => "mode_E" }
+       ],
+       "st" => [
+               { "name" => "st0", "type" => 1 },
+               { "name" => "st1", "type" => 1 },
+               { "name" => "st2", "type" => 1 },
+               { "name" => "st3", "type" => 1 },
+               { "name" => "st4", "type" => 1 },
+               { "name" => "st5", "type" => 1 },
+               { "name" => "st6", "type" => 1 },
+               { "name" => "st7", "type" => 1 },
+               { "mode" => "mode_E" }
+       ],
+       "fp_cw" => [    # the floating point control word
+               { "name" => "fpcw", "type" => 0 },
+        { "mode" => "mode_Hu" },
+       ],
 ); # %reg_classes
 
+%cpu = (
+  "GP"     => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ],
+  "SSE"    => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ],
+  "VFP"    => [ 1, "VFP_VF0", "VFP_VF1", "VFP_VF2", "VFP_VF3", "VFP_VF4", "VFP_VF5", "VFP_VF6", "VFP_VF7" ],
+  "BRANCH" => [ 1, "BRANCH1", "BRANCH2" ],
+); # %cpu
+
+%vliw = (
+       "bundle_size"       => 1,
+       "bundels_per_cycle" => 1
+); # vliw
+
+%emit_templates = (
+       "S1" => "${arch}_emit_source_register(env, node, 0);",
+       "S2" => "${arch}_emit_source_register(env, node, 1);",
+       "S3" => "${arch}_emit_source_register(env, node, 2);",
+       "S4" => "${arch}_emit_source_register(env, node, 3);",
+       "S5" => "${arch}_emit_source_register(env, node, 4);",
+       "S6" => "${arch}_emit_source_register(env, node, 5);",
+       "D1" => "${arch}_emit_dest_register(env, node, 0);",
+       "D2" => "${arch}_emit_dest_register(env, node, 1);",
+       "D3" => "${arch}_emit_dest_register(env, node, 2);",
+       "D4" => "${arch}_emit_dest_register(env, node, 3);",
+       "D5" => "${arch}_emit_dest_register(env, node, 4);",
+       "D6" => "${arch}_emit_dest_register(env, node, 5);",
+       "A1" => "${arch}_emit_in_node_name(env, node, 0);",
+       "A2" => "${arch}_emit_in_node_name(env, node, 1);",
+       "A3" => "${arch}_emit_in_node_name(env, node, 2);",
+       "A4" => "${arch}_emit_in_node_name(env, node, 3);",
+       "A5" => "${arch}_emit_in_node_name(env, node, 4);",
+       "A6" => "${arch}_emit_in_node_name(env, node, 5);",
+       "X1" => "${arch}_emit_x87_name(env, node, 0);",
+       "X2" => "${arch}_emit_x87_name(env, node, 1);",
+       "X3" => "${arch}_emit_x87_name(env, node, 2);",
+       "C"  => "${arch}_emit_immediate(env, node);",
+       "SE" => "${arch}_emit_extend_suffix(env, get_ia32_ls_mode(node));",
+       "ME" => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n
+       ${arch}_emit_mode_suffix(env, get_ia32_ls_mode(node));",
+       "M"  => "${arch}_emit_mode_suffix(env, get_ia32_ls_mode(node));",
+       "XM" => "${arch}_emit_x87_mode_suffix(env, node);",
+       "XXM" => "${arch}_emit_xmm_mode_suffix(env, node);",
+       "AM" => "${arch}_emit_am(env, node);",
+       "unop" => "${arch}_emit_unop(env, node);",
+       "binop" => "${arch}_emit_binop(env, node);",
+       "x87_binop" => "${arch}_emit_x87_binop(env, node);",
+);
+
 #--------------------------------------------------#
 #                        _                         #
 #                       (_)                        #
@@ -187,6 +218,8 @@ $comment_string = "/*";
 #                                      |_|         #
 #--------------------------------------------------#
 
+$default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);";
+
 %operands = (
 );
 
@@ -216,213 +249,214 @@ $comment_string = "/*";
 "Add" => {
   "irn_flags" => "R",
   "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(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. addl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
-"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",
+"Adc" => {
+  "comment"   => "construct Add with Carry: Adc(a, b) = Add(b, a) = a + b + carry",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. adc %ia32_emit_binop /* AddC(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. adcl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
+},
+
+"Add64Bit" => {
+  "irn_flags" => "R",
+  "comment"   => "construct 64Bit Add: Add(a_l, a_h, b_l, b_h) = a_l + b_l; a_h + b_h + carry",
+  "arity"     => 4,
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp" ], "out" => [ "!in", "!in" ] },
+  "emit"      => '
+. movl %S1, %D1
+. movl %S2, %D2
+. addl %S3, %D1
+. adcl %S4, %D2
+',
+  "outs"      => [ "low_res", "high_res" ],
+  "units"     => [ "GP" ],
 },
 
 "l_Add" => {
   "op_flags"  => "C",
   "irn_flags" => "R",
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "construct lowered Add: Add(a, b) = Add(b, a) = a + b",
   "arity"     => 2,
 },
 
-"l_AddC" => {
+"l_Adc" => {
   "op_flags"  => "C",
-  "cmp_attr"  => "  return 1;\n",
-  "comment"   => "construct lowered Add with Carry: AddC(a, b) = Add(b, a) = a + b + carry",
+  "cmp_attr"  => "return 1;",
+  "comment"   => "construct lowered Add with Carry: Adc(a, b) = Adc(b, a) = a + b + carry",
   "arity"     => 2,
 },
 
-"MulS" => {
+"Mul" => {
   # 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" ] },
-  "emit"      => '. mul %ia32_emit_unop /* Mul(%A1, %A2) -> %D1 */',
+  "reg_req"   => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx", "none" ] },
+  "emit"      => '. mull %unop',
   "outs"      => [ "EAX", "EDX", "M" ],
   "latency"   => 10,
+  "units"     => [ "GP" ],
 },
 
-"l_MulS" => {
+"l_Mul" => {
   # 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",
+  "cmp_attr"  => "return 1;",
+  "comment"   => "construct lowered MulS: Mul(a, b) = Mul(b, a) = a * b",
   "outs"      => [ "EAX", "EDX", "M" ],
   "arity"     => 2
 },
 
-"Mul" => {
+"IMul" => {
   "irn_flags" => "R",
   "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" => [ "in_r3" ] },
-  "emit"      => '. imul %ia32_emit_binop /* Mul(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. imull %binop',
   "latency"   => 5,
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
-"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" => {
-  # 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" ] },
-  "emit"      => '. imul %ia32_emit_unop /* Mulh(%A1, %A2) -> %D1 */',
+"IMul1OP" => {
+  "irn_flags" => "R",
+  "comment"   => "construct Mul (1 operand format): Mul(a, b) = Mul(b, a) = a * b",
+  "reg_req"   => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx", "none" ] },
+  "emit"      => '. imull %unop',
   "outs"      => [ "EAX", "EDX", "M" ],
   "latency"   => 5,
+  "units"     => [ "GP" ],
+},
+
+"l_IMul" => {
+  "op_flags"  => "C",
+  "cmp_attr"  => "return 1;",
+  "comment"   => "construct lowered IMul: IMul(a, b) = IMul(b, a) = a * b",
+  "arity"     => 2
 },
 
 "And" => {
   "irn_flags" => "R",
   "comment"   => "construct And: And(a, b) = And(b, a) = a AND 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"      => '. and %ia32_emit_binop /* And(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. andl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 "Or" => {
   "irn_flags" => "R",
   "comment"   => "construct Or: Or(a, b) = Or(b, a) = a OR 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"      => '. or %ia32_emit_binop /* Or(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. orl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
-"Eor" => {
+"Xor" => {
   "irn_flags" => "R",
-  "comment"   => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
+  "comment"   => "construct Xor: Xor(a, b) = Xor(b, a) = a EOR b",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. xor %ia32_emit_binop /* Xor(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. xorl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
-"l_Eor" => {
+"l_Xor" => {
   "op_flags"  => "C",
-  "cmp_attr"  => "  return 1;\n",
-  "comment"   => "construct lowered Eor: Eor(a, b) = Eor(b, a) = a EOR b",
+  "cmp_attr"  => "return 1;",
+  "comment"   => "construct lowered Xor: Xor(a, b) = Xor(b, a) = a XOR b",
   "arity"     => 2
 },
 
-"Max" => {
-  "irn_flags" => "R",
-  "comment"   => "construct Max: Max(a, b) = Max(b, a) = a > b ? a : b",
-  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
-  "emit"      =>
-'2. cmp %S1, %S2 /* prepare Max (%S1 - %S2), (%A1, %A2) */
-  if (mode_is_signed(get_irn_mode(n))) {
-4.  cmovl %D1, %S2 /* %S1 is less %S2 */
-  }
-  else {
-4.  cmovb %D1, %S2 /* %S1 is below %S2 */
-  }
-',
-  "latency"   => 2,
-},
-
-"Min" => {
-  "irn_flags" => "R",
-  "comment"   => "construct Min: Min(a, b) = Min(b, a) = a < b ? a : b",
-  "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
-  "emit"      =>
-'2. cmp %S1, %S2 /* prepare Min (%S1 - %S2), (%A1, %A2) */
-  if (mode_is_signed(get_irn_mode(n))) {
-2.  cmovg %D1, %S2 /* %S1 is greater %S2 */
-  }
-  else {
-2.  cmova %D1, %S2, %D1 /* %S1 is above %S2 */
-  }
-',
-  "latency"   => 2,
-},
-
 # not commutative operations
 
 "Sub" => {
   "irn_flags" => "R",
   "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(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. subl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
-"SubC" => {
+"Sbb" => {
   "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 !in_r4" ] },
-  "emit"      => '. sbb %ia32_emit_binop /* SubC(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. sbbl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
+},
+
+"Sub64Bit" => {
+  "irn_flags" => "R",
+  "comment"   => "construct 64Bit Sub: Sub(a_l, a_h, b_l, b_h) = a_l - b_l; a_h - b_h - borrow",
+  "arity"     => 4,
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp" ], "out" => [ "!in", "!in" ] },
+  "emit"      => '
+. movl %S1, %D1
+. movl %S2, %D2
+. subl %S3, %D1
+. sbbl %S4, %D2
+',
+  "outs"      => [ "low_res", "high_res" ],
+  "units"     => [ "GP" ],
 },
 
 "l_Sub" => {
   "irn_flags" => "R",
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "construct lowered Sub: Sub(a, b) = a - b",
   "arity"     => 2,
 },
 
-"l_SubC" => {
-  "cmp_attr"  => "  return 1;\n",
+"l_Sbb" => {
+  "cmp_attr"  => "return 1;",
   "comment"   => "construct lowered Sub with Carry: SubC(a, b) = a - b - carry",
   "arity"     => 2,
 },
 
-"DivMod" => {
+"IDiv" => {
   "op_flags"  => "F|L",
   "state"     => "exc_pinned",
-  "reg_req"   => { "in" => [ "eax", "gp", "edx", "none" ], "out" => [ "eax", "edx" ] },
+  "reg_req"   => { "in" => [ "gp", "gp", "eax", "edx", "gp", "none" ], "out" => [ "eax", "edx", "none" ] },
   "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_ia32_res_mode(n))) {
-4.  idiv %S2 /* signed DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
-  }
-  else {
-4.  div %S2 /* unsigned DivMod(%S1, %S2) -> %D1, (%A1, %A2, %A3) */
-  }
-',
+  "init_attr" => "attr->data.op_flav = dm_flav;",
+  "emit"      => ". idivl %unop",
+  "outs"      => [ "div_res", "mod_res", "M" ],
+  "latency"   => 25,
+  "units"     => [ "GP" ],
+},
+
+"Div" => {
+  "op_flags"  => "F|L",
+  "state"     => "exc_pinned",
+  "reg_req"   => { "in" => [ "gp", "gp", "eax", "edx", "gp", "none" ], "out" => [ "eax", "edx", "none" ] },
+  "attr"      => "ia32_op_flavour_t dm_flav",
+  "init_attr" => "attr->data.op_flav = dm_flav;",
+  "emit"      => ". divl %unop",
   "outs"      => [ "div_res", "mod_res", "M" ],
   "latency"   => 25,
+  "units"     => [ "GP" ],
 },
 
 "Shl" => {
   "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" ] },
-  "emit"      => '. shl %ia32_emit_binop /* Shl(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. shll %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 "l_Shl" => {
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "construct lowered Shl: Shl(a, b) = a << b",
   "arity"     => 2
 },
@@ -430,48 +464,53 @@ $comment_string = "/*";
 "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" => [ "!ecx in_r3 !in_r4" ] },
+  # 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) {
-  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 */
-  }
+if (get_ia32_immop_type(node) == ia32_ImmNone) {
+       if (get_ia32_op_type(node) == ia32_AddrModeD) {
+               . shldl %%cl, %S4, %AM
+       } else {
+               . shldl %%cl, %S4, %S3
+       }
+} else {
+       if (get_ia32_op_type(node) == ia32_AddrModeD) {
+               . shldl $%C, %S4, %AM
+       } else {
+               . shldl $%C, %S4, %S3
+       }
 }
 ',
-  "outs"      => [ "res", "M" ],
   "latency"   => 6,
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 "l_ShlD" => {
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "construct lowered ShlD: ShlD(a, b, c) = a, b << count (shift left count bits from b into a)",
-  "arity"     => 3
+  "arity"     => 3,
 },
 
 "Shr" => {
   "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" ] },
-  "emit"      => '. shr %ia32_emit_binop /* Shr(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. shrl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 "l_Shr" => {
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "construct lowered Shr: Shr(a, b) = a << b",
   "arity"     => 2
 },
@@ -479,83 +518,103 @@ else {
 "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" => [ "!ecx in_r3 !in_r4" ] },
-  "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 */
-  }
+  # 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(node) == ia32_ImmNone) {
+       if (get_ia32_op_type(node) == ia32_AddrModeD) {
+               . shrdl %%cl, %S4, %AM
+       } else {
+               . shrdl %%cl, %S4, %S3
+       }
+} else {
+       if (get_ia32_op_type(node) == ia32_AddrModeD) {
+               . shrdl $%C, %S4, %AM
+       } else {
+               . shrdl $%C, %S4, %S3
+       }
 }
 ',
-  "outs"      => [ "res", "M" ],
   "latency"   => 6,
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 "l_ShrD" => {
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "construct lowered ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)",
   "arity"     => 3
 },
 
-"Shrs" => {
+"Sar" => {
   "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" ] },
-  "emit"      => '. sar %ia32_emit_binop /* Shrs(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. sarl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
-"l_Shrs" => {
-  "cmp_attr"  => "  return 1;\n",
-  "comment"   => "construct lowered Shrs: Shrs(a, b) = a << b",
+"l_Sar" => {
+  "cmp_attr"  => "return 1;",
+  "comment"   => "construct lowered Sar: Sar(a, b) = a << b",
   "arity"     => 2
 },
 
-"RotR" => {
+"Ror" => {
   "irn_flags" => "R",
-  "comment"     => "construct RotR: RotR(a, b) = a ROTR 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" ] },
-  "emit"        => '. ror %ia32_emit_binop /* RotR(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "comment"   => "construct Ror: Ror(a, b) = a ROR b",
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
+  "emit"      => '. rorl %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
-"RotL" => {
+"Rol" => {
   "irn_flags" => "R",
-  "comment"   => "construct RotL: RotL(a, b) = a ROTL b",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
+  "comment"   => "construct Rol: Rol(a, b) = a ROL b",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
-  "emit"      => '. rol %ia32_emit_binop /* RotL(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. roll %binop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 # unary operations
 
-"Minus" => {
+"Neg" => {
   "irn_flags" => "R",
   "comment"   => "construct Minus: Minus(a) = -a",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. neg %ia32_emit_unop /* Neg(%A1) -> %D1, (%A1) */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. negl %unop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
-"l_Minus" => {
-  "cmp_attr"  => "  return 1;\n",
+"Minus64Bit" => {
+  "irn_flags" => "R",
+  "comment"   => "construct 64Bit Minus: Minus(a_l, a_h, 0) = 0 - a_l; 0 - a_h - borrow",
+  "arity"     => 4,
+  "reg_req"   => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in", "!in" ] },
+  "emit"      => '
+. movl %S1, %D1
+. movl %S1, %D2
+. subl %S2, %D1
+. sbbl %S3, %D2
+',
+  "outs"      => [ "low_res", "high_res" ],
+  "units"     => [ "GP" ],
+},
+
+
+"l_Neg" => {
+  "cmp_attr"  => "return 1;",
   "comment"   => "construct lowered Minus: Minus(a) = -a",
   "arity"     => 1,
 },
@@ -563,28 +622,28 @@ else {
 "Inc" => {
   "irn_flags" => "R",
   "comment"   => "construct Increment: Inc(a) = a++",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. inc %ia32_emit_unop /* Inc(%S1) -> %D1, (%A1) */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. incl %unop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 "Dec" => {
   "irn_flags" => "R",
   "comment"   => "construct Decrement: Dec(a) = a--",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. dec %ia32_emit_unop /* Dec(%S1) -> %D1, (%A1) */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. decl %unop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 "Not" => {
   "irn_flags" => "R",
   "comment"   => "construct Not: Not(a) = !a",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. not %ia32_emit_unop /* Not(%S1) -> %D1, (%A1) */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. notl %unop',
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 # other operations
@@ -592,59 +651,152 @@ else {
 "CondJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "construct conditional jump: CMP A, B && JMPxx LABEL",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ] },
   "outs"      => [ "false", "true" ],
   "latency"   => 3,
+  "units"     => [ "BRANCH" ],
 },
 
 "TestJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "construct conditional jump: TEST A, B && JMPxx LABEL",
   "reg_req"  => { "in" => [ "gp", "gp" ] },
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "outs"      => [ "false", "true" ],
   "latency"   => 3,
+  "units"     => [ "BRANCH" ],
 },
 
 "CJmpAM" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "construct conditional jump without CMP (replaces CondJmp): JMPxx LABEL",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "none", "none" ] },
   "outs"      => [ "false", "true" ],
+  "units"     => [ "BRANCH" ],
 },
 
 "CJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "construct conditional jump without CMP (replaces TestJmp): JMPxx LABEL",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp" ] },
+  "units"     => [ "BRANCH" ],
 },
 
 "SwitchJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "construct switch",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp" ], "out" => [ "none" ] },
   "latency"   => 3,
+  "units"     => [ "BRANCH" ],
 },
 
 "Const" => {
   "op_flags"  => "c",
   "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" ] },
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
-"Cdq" => {
+"Unknown_GP" => {
+  "op_flags"  => "c",
+  "irn_flags" => "I",
+  "comment"   => "unknown value",
+  "reg_req"   => { "out" => [ "gp_UKNWN" ] },
+  "units"     => [],
+  "emit"      => "",
+  "mode"      => "mode_Iu"
+},
+
+"Unknown_VFP" => {
+  "op_flags"  => "c",
+  "irn_flags" => "I",
+  "comment"   => "unknown value",
+  "reg_req"   => { "out" => [ "vfp_UKNWN" ] },
+  "units"     => [],
+  "emit"      => "",
+  "mode"      => "mode_E"
+},
+
+"Unknown_XMM" => {
+  "op_flags"  => "c",
+  "irn_flags" => "I",
+  "comment"   => "unknown value",
+  "reg_req"   => { "out" => [ "xmm_UKNWN" ] },
+  "units"     => [],
+  "emit"      => "",
+  "mode"      => "mode_E"
+},
+
+"NoReg_GP" => {
+  "op_flags"  => "c",
+  "irn_flags" => "I",
+  "comment"   => "unknown GP value",
+  "reg_req"   => { "out" => [ "gp_NOREG" ] },
+  "units"     => [],
+  "emit"      => "",
+  "mode"      => "mode_Iu"
+},
+
+"NoReg_VFP" => {
+  "op_flags"  => "c",
+  "irn_flags" => "I",
+  "comment"   => "unknown VFP value",
+  "reg_req"   => { "out" => [ "vfp_NOREG" ] },
+  "units"     => [],
+  "emit"      => "",
+  "mode"      => "mode_E"
+},
+
+"NoReg_XMM" => {
+  "op_flags"  => "c",
+  "irn_flags" => "I",
+  "comment"   => "unknown XMM value",
+  "reg_req"   => { "out" => [ "xmm_NOREG" ] },
+  "units"     => [],
+  "emit"      => "",
+  "mode"      => "mode_E"
+},
+
+"ChangeCW" => {
+  "irn_flags" => "R",
+  "comment"   => "change floating point control word",
+  "reg_req"   => { "out" => [ "fp_cw" ] },
+  "mode"      => "mode_Hu",
+  "latency"   => 3,
+  "units"     => [ "GP" ],
+},
+
+"FldCW" => {
+  "op_flags"  => "L|F",
+  "state"     => "exc_pinned",
+  "comment"   => "load floating point control word FldCW(ptr, mem) = LD ptr -> reg",
+  "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "fp_cw" ] },
+  "latency"   => 5,
+  "emit"      => ". fldcw %AM",
+  "mode"      => "mode_Hu",
+  "units"     => [ "GP" ],
+},
+
+"FstCW" => {
+  "op_flags"  => "L|F",
+  "state"     => "exc_pinned",
+  "comment"   => "store floating point control word: FstCW(ptr, mem) = ST ptr -> reg",
+  "reg_req"   => { "in" => [ "gp", "gp", "fp_cw", "none" ] },
+  "latency"   => 5,
+  "emit"      => ". fstcw %AM",
+  "mode"      => "mode_M",
+  "units"     => [ "GP" ],
+},
+
+"Cltd" => {
   # 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) */',
+  "emit"      => '. cltd',
   "outs"      => [ "EAX", "EDX" ],
+  "units"     => [ "GP" ],
 },
 
 # Load / Store
@@ -653,23 +805,16 @@ else {
   "op_flags"  => "L|F",
   "state"     => "exc_pinned",
   "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" ] },
+  "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "gp", "none" ] },
   "latency"   => 3,
-  "emit"      =>
-'  if (get_mode_size_bits(get_ia32_ls_mode(n)) < 32) {
-4.   mov%Mx %D1, %ia32_emit_am /* Load((%A1)) -> %D1 */
-  }
-  else {
-4.   mov %D1, %ia32_emit_am /* Load((%A1)) -> %D1 */
-  }
-',
+  "emit"      => ". mov%SE%ME%.l %AM, %D1",
   "outs"      => [ "res", "M" ],
+  "units"     => [ "GP" ],
 },
 
 "l_Load" => {
   "op_flags"  => "L|F",
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "construct lowered Load: Load(ptr, mem) = LD ptr -> reg",
   "outs"      => [ "res", "M" ],
   "arity"     => 2,
@@ -677,117 +822,104 @@ else {
 
 "l_Store" => {
   "op_flags"  => "L|F",
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "state"     => "exc_pinned",
   "comment"   => "construct lowered Store: Store(ptr, val, mem) = ST ptr,val",
   "arity"     => 3,
-  "outs"      => [ "M" ],
+  "mode"      => "mode_M",
 },
 
 "Store" => {
   "op_flags"  => "L|F",
   "state"     => "exc_pinned",
   "comment"   => "construct 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", "gp", "none" ] },
-  "emit"      => '. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */',
-  "outs"      => [ "M" ],
+  "emit"      => '. mov%M %binop',
   "latency"   => 3,
+  "units"     => [ "GP" ],
+  "mode"      => "mode_M",
 },
 
 "Store8Bit" => {
   "op_flags"  => "L|F",
   "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" ] },
-  "emit"      => '. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */',
-  "outs"      => [ "M" ],
+  "emit"      => '. mov%M %binop',
   "latency"   => 3,
+  "units"     => [ "GP" ],
+  "mode"      => "mode_M",
 },
 
 "Lea" => {
   "irn_flags" => "R",
   "comment"   => "construct Lea: Lea(a,b) = lea [a+b*const+offs] | res = a + b * const + offs with const = 0,1,2,4,8",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] },
-  "emit"      => '. lea %D1, %ia32_emit_am /* LEA(%A1, %A2) */',
+  "emit"      => '. leal %AM, %D1',
   "latency"   => 2,
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 "Push" => {
-  # We don't set class modify_stack here (but we will do this on proj 0)
-  "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", "none" ] },
+  "emit"      => '. pushl %unop',
+  "outs"      => [ "stack:I|S", "M" ],
   "latency"   => 3,
+  "units"     => [ "GP" ],
 },
 
 "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" => [ "esp", "gp", "none" ] },
+  "emit"      => '. popl %unop',
+  "outs"      => [ "stack:I|S", "res", "M" ],
   "latency"   => 4,
+  "units"     => [ "GP" ],
 },
 
 "Enter" => {
   "comment"   => "create stack frame",
   "reg_req"   => { "in" => [ "esp" ], "out" => [ "ebp", "esp" ] },
-  "emit"      => '. enter /* Enter */',
-  "outs"      => [ "frame", "stack", "M" ],
+  "emit"      => '. enter',
+  "outs"      => [ "frame:I", "stack:I|S", "M" ],
   "latency"   => 15,
+  "units"     => [ "GP" ],
 },
 
 "Leave" => {
   "comment"   => "destroy stack frame",
   "reg_req"   => { "in" => [ "esp", "ebp" ], "out" => [ "ebp", "esp" ] },
-  "emit"      => '. leave /* Leave */',
-  "outs"      => [ "frame", "stack", "M" ],
+  "emit"      => '. leave',
+  "outs"      => [ "frame:I", "stack:I|S" ],
   "latency"   => 3,
+  "units"     => [ "GP" ],
 },
 
 "AddSP" => {
   "irn_flags" => "I",
   "comment"   => "allocate space on stack",
-  "reg_req"   => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] },
-  "outs"      => [ "stack", "M" ],
+  "reg_req"   => { "in" => [ "gp", "gp", "esp", "gp", "none" ], "out" => [ "in_r3", "none" ] },
+  "emit"      => '. addl %binop',
+  "outs"      => [ "stack:S", "M" ],
+  "units"     => [ "GP" ],
 },
 
 "SubSP" => {
   "irn_flags" => "I",
   "comment"   => "free space on stack",
-  "reg_req"   => { "in" => [ "esp", "gp" ], "out" => [ "esp", "none" ] },
-  "outs"      => [ "stack", "M" ],
+  "reg_req"   => { "in" => [ "gp", "gp", "esp", "gp", "none" ], "out" => [ "in_r3", "none" ] },
+  "emit"      => '. subl %binop',
+  "outs"      => [ "stack:S", "M" ],
+  "units"     => [ "GP" ],
 },
 
 "LdTls" => {
   "irn_flags" => "R",
   "comment"   => "get the TLS base address",
   "reg_req"   => { "out" => [ "gp" ] },
+  "units"     => [ "GP" ],
 },
 
 
@@ -806,70 +938,70 @@ else {
 "xAdd" => {
   "irn_flags" => "R",
   "comment"   => "construct SSE 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", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. adds%M %ia32_emit_binop /* SSE Add(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. add%XXM %binop',
   "latency"   => 4,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 "xMul" => {
   "irn_flags" => "R",
   "comment"   => "construct SSE 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", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. muls%M %ia32_emit_binop /* SSE Mul(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. mul%XXM %binop',
   "latency"   => 4,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 "xMax" => {
   "irn_flags" => "R",
   "comment"   => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. maxs%M %ia32_emit_binop /* SSE Max(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. max%XXM %binop',
   "latency"   => 2,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 "xMin" => {
   "irn_flags" => "R",
   "comment"   => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. mins%M %ia32_emit_binop /* SSE Min(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. min%XXM %binop',
   "latency"   => 2,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 "xAnd" => {
   "irn_flags" => "R",
   "comment"   => "construct SSE And: And(a, b) = a AND b",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. andp%M %ia32_emit_binop /* SSE And(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. andp%XXM %binop',
   "latency"   => 3,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 "xOr" => {
   "irn_flags" => "R",
   "comment"   => "construct SSE Or: Or(a, b) = a OR b",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. orp%M %ia32_emit_binop /* SSE Or(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. orp%XXM %binop',
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
-"xEor" => {
+"xXor" => {
   "irn_flags" => "R",
-  "comment"   => "construct SSE Eor: Eor(a, b) = a XOR b",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
+  "comment"   => "construct SSE Xor: Xor(a, b) = a XOR b",
   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. xorp%M %ia32_emit_binop /* SSE Xor(%A3, %A4) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. xorp%XXM %binop',
   "latency"   => 3,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 # not commutative operations
@@ -877,31 +1009,31 @@ else {
 "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" ],
+  "emit"      => '. andnp%XXM %binop',
   "latency"   => 3,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 "xSub" => {
   "irn_flags" => "R",
   "comment"   => "construct SSE Sub: Sub(a, b) = a - b",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] },
-  "emit"      => '. subs%M %ia32_emit_binop /* SSE Sub(%A1, %A2) -> %D1 */',
-  "outs"      => [ "res", "M" ],
+  "emit"      => '. sub%XXM %binop',
   "latency"   => 4,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 "xDiv" => {
   "irn_flags" => "R",
   "comment"   => "construct SSE Div: Div(a, b) = a / 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"      => '. divs%M %ia32_emit_binop /* SSE Div(%A1, %A2) -> %D1 */',
   "outs"      => [ "res", "M" ],
+  "emit"      => '. div%XXM %binop',
   "latency"   => 16,
+  "units"     => [ "SSE" ],
 },
 
 # other operations
@@ -910,27 +1042,29 @@ else {
   "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" ],
   "latency"   => 3,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 "xCondJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "construct conditional jump: UCOMIS A, B && JMPxx LABEL",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "none", "none" ] },
   "outs"      => [ "false", "true" ],
   "latency"   => 5,
+  "units"     => [ "SSE" ],
 },
 
 "xConst" => {
   "op_flags"  => "c",
   "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" ] },
-  "emit"      => '. movs%M %D1, %C /* Load fConst into register */',
+  "reg_req"   => { "out" => [ "xmm" ] },
+  "emit"      => '. mov%XXM $%C, %D1',
   "latency"   => 2,
+  "units"     => [ "SSE" ],
+  "mode"      => "mode_E",
 },
 
 # Load / Store
@@ -939,46 +1073,46 @@ else {
   "op_flags"  => "L|F",
   "state"     => "exc_pinned",
   "comment"   => "construct SSE Load: Load(ptr, mem) = LD ptr",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
-  "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "xmm" ] },
-  "emit"      => '. movs%M %D1, %ia32_emit_am /* Load((%A1)) -> %D1 */',
+  "reg_req"   => { "in" => [ "gp", "gp", "none" ], "out" => [ "xmm", "none" ] },
+  "emit"      => '. mov%XXM %AM, %D1',
   "outs"      => [ "res", "M" ],
   "latency"   => 2,
+  "units"     => [ "SSE" ],
 },
 
 "xStore" => {
   "op_flags" => "L|F",
   "state"    => "exc_pinned",
   "comment"  => "construct 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", "xmm", "none" ] },
-  "emit"     => '. movs%M %ia32_emit_binop /* Store(%S3) -> (%A1) */',
-  "outs"      => [ "M" ],
-  "latency"   => 2,
+  "emit"     => '. mov%XXM %binop',
+  "latency"  => 2,
+  "units"    => [ "SSE" ],
+  "mode"     => "mode_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" ],
-  "latency"   => 2,
+  "emit"     => '. mov%XXM %S2, %AM',
+  "latency"  => 2,
+  "units"    => [ "SSE" ],
+  "mode"     => "mode_M",
 },
 
 "l_X87toSSE" => {
   "op_flags" => "L|F",
   "comment"  => "construct: transfer a value from x87 FPU into a SSE register",
-  "cmp_attr" => "  return 1;\n",
+  "cmp_attr" => "return 1;",
   "arity"    => 3,
 },
 
 "l_SSEtoX87" => {
   "op_flags" => "L|F",
   "comment"  => "construct: transfer a value from SSE register to x87 FPU",
-  "cmp_attr" => "  return 1;\n",
+  "cmp_attr" => "return 1;",
   "arity"    => 3,
 },
 
@@ -987,11 +1121,11 @@ else {
   "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" ],
+  "reg_req"  => { "in" => [ "gp", "gp", "none" ] },
+  "emit"     => '. fstp%XM %AM',
   "latency"  => 4,
+  "units"    => [ "SSE" ],
+  "mode"     => "mode_M",
 },
 
 "SetST0" => {
@@ -999,11 +1133,11 @@ else {
   "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 */',
+  "reg_req"  => { "in" => [ "gp", "none" ], "out" => [ "vf0", "none" ] },
+  "emit"     => '. fld%M %AM',
   "outs"     => [ "res", "M" ],
   "latency"  => 2,
+  "units"     => [ "SSE" ],
 },
 
 # CopyB
@@ -1014,55 +1148,56 @@ else {
   "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))",
-  "cmp_attr" => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "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" ] },
-  "cmp_attr" => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
   "comment"  => "construct Conv Int -> Int",
-  "outs"     => [ "res", "M" ],
+  "units"     => [ "GP" ],
+  "mode"     => "mode_Iu",
 },
 
 "Conv_I2I8Bit" => {
   "reg_req"  => { "in" => [ "gp", "gp", "eax ebx ecx edx", "none" ], "out" => [ "in_r3", "none" ] },
-  "cmp_attr" => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
   "comment"  => "construct Conv Int -> Int",
-  "outs"     => [ "res", "M" ],
+  "units"     => [ "GP" ],
+  "mode"     => "mode_Iu",
 },
 
 "Conv_I2FP" => {
   "reg_req"  => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "xmm", "none" ] },
-  "cmp_attr" => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
   "comment"  => "construct Conv Int -> Floating Point",
-  "outs"     => [ "res", "M" ],
   "latency"  => 10,
+  "units"    => [ "SSE" ],
+  "mode"     => "mode_E",
 },
 
 "Conv_FP2I" => {
   "reg_req"  => { "in" => [ "gp", "gp", "xmm", "none" ], "out" => [ "gp", "none" ] },
-  "cmp_attr" => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
   "comment"  => "construct Conv Floating Point -> Int",
-  "outs"     => [ "res", "M" ],
   "latency"  => 10,
+  "units"    => [ "SSE" ],
+  "mode"     => "mode_Iu",
 },
 
 "Conv_FP2FP" => {
   "reg_req"  => { "in" => [ "gp", "gp", "xmm", "none" ], "out" => [ "xmm", "none" ] },
-  "cmp_attr" => "  return ia32_compare_conv_attr(attr_a, attr_b);\n",
   "comment"  => "construct Conv Floating Point -> Floating Point",
-  "outs"     => [ "res", "M" ],
   "latency"  => 8,
+  "units"    => [ "SSE" ],
+  "mode"     => "mode_E",
 },
 
 "CmpCMov" => {
@@ -1070,6 +1205,8 @@ else {
   "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" => {
@@ -1077,6 +1214,8 @@ else {
   "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" => {
@@ -1084,6 +1223,8 @@ else {
   "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" => {
@@ -1091,14 +1232,17 @@ else {
   "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", "none" ] },
-  "outs"      => [ "res", "M" ],
+  "reg_req"   => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax ebx ecx edx" ] },
   "latency"   => 2,
+  "units"     => [ "GP" ],
+  "mode"      => "mode_Iu",
 },
 
 "PsiCondSet" => {
@@ -1106,22 +1250,26 @@ else {
   "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", "none" ] },
-  "outs"      => [ "res", "M" ],
+  "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", "none" ] },
-  "outs"      => [ "res", "M" ],
+  "reg_req"   => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "eax ebx ecx edx" ] },
   "latency"   => 10,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_Iu",
 },
 
 "vfCMov" => {
@@ -1129,6 +1277,8 @@ else {
   "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",
 },
 
 #----------------------------------------------------------#
@@ -1148,24 +1298,24 @@ else {
 "vfadd" => {
   "irn_flags" => "R",
   "comment"   => "virtual fp 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", "vfp", "vfp", "none" ], "out" => [ "vfp" ] },
-  "outs"      => [ "res", "M" ],
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfmul" => {
   "irn_flags" => "R",
   "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" ],
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "l_vfmul" => {
   "op_flags"  => "C",
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "lowered virtual fp Mul: Mul(a, b) = Mul(b, a) = a * b",
   "arity"     => 2,
 },
@@ -1173,29 +1323,44 @@ else {
 "vfsub" => {
   "irn_flags" => "R",
   "comment"   => "virtual fp Sub: Sub(a, b) = 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" ],
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "l_vfsub" => {
-  "cmp_attr"  => "  return 1;\n",
+  "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",
-  "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" ],
   "latency"   => 20,
+  "units"     => [ "VFP" ],
 },
 
 "l_vfdiv" => {
-  "cmp_attr"  => "  return 1;\n",
+  "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,
 },
 
@@ -1204,6 +1369,8 @@ else {
   "comment"   => "virtual fp Abs: Abs(a) = |a|",
   "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
   "latency"   => 2,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfchs" => {
@@ -1211,6 +1378,8 @@ else {
   "comment"   => "virtual fp Chs: Chs(a) = -a",
   "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
   "latency"   => 2,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfsin" => {
@@ -1218,6 +1387,8 @@ else {
   "comment"   => "virtual fp Sin: Sin(a) = sin(a)",
   "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
   "latency"   => 150,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfcos" => {
@@ -1225,6 +1396,8 @@ else {
   "comment"   => "virtual fp Cos: Cos(a) = cos(a)",
   "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
   "latency"   => 150,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfsqrt" => {
@@ -1232,6 +1405,8 @@ else {
   "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
@@ -1240,34 +1415,34 @@ else {
   "op_flags"  => "L|F",
   "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",
   "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",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "none" ] },
-  "outs"      => [ "M" ],
   "latency"   => 2,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_M",
 },
 
 # Conversions
 
 "vfild" => {
   "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" ],
   "latency"   => 4,
+  "units"     => [ "VFP" ],
 },
 
 "l_vfild" => {
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "lowered virtual fp integer Load: Load(ptr, mem) = iLD ptr -> reg",
   "outs"      => [ "res", "M" ],
   "arity"     => 2,
@@ -1275,17 +1450,17 @@ else {
 
 "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",
   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "none" ] },
-  "outs"      => [ "M" ],
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_M",
 },
 
 "l_vfist" => {
-  "cmp_attr"  => "  return 1;\n",
+  "cmp_attr"  => "return 1;",
   "comment"   => "lowered virtual fp integer Store: Store(ptr, val, mem) = iST ptr,val",
-  "outs"      => [ "M" ],
   "arity"     => 3,
+  "mode"      => "mode_M",
 },
 
 
@@ -1296,6 +1471,8 @@ else {
   "comment"   => "virtual fp Load 0.0: Ld 0.0 -> reg",
   "reg_req"   => { "out" => [ "vfp" ] },
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfld1" => {
@@ -1303,6 +1480,8 @@ else {
   "comment"   => "virtual fp Load 1.0: Ld 1.0 -> reg",
   "reg_req"   => { "out" => [ "vfp" ] },
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfldpi" => {
@@ -1310,6 +1489,8 @@ else {
   "comment"   => "virtual fp Load pi: Ld pi -> reg",
   "reg_req"   => { "out" => [ "vfp" ] },
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfldln2" => {
@@ -1317,6 +1498,8 @@ else {
   "comment"   => "virtual fp Load ln 2: Ld ln 2 -> reg",
   "reg_req"   => { "out" => [ "vfp" ] },
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfldlg2" => {
@@ -1324,6 +1507,8 @@ else {
   "comment"   => "virtual fp Load lg 2: Ld lg 2 -> reg",
   "reg_req"   => { "out" => [ "vfp" ] },
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfldl2t" => {
@@ -1331,6 +1516,8 @@ else {
   "comment"   => "virtual fp Load ld 10: Ld ld 10 -> reg",
   "reg_req"   => { "out" => [ "vfp" ] },
   "latency"   => 4,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 "vfldl2e" => {
@@ -1338,16 +1525,19 @@ else {
   "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);",
+#  "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,
+  "units"     => [ "VFP" ],
+  "mode"      => "mode_E",
 },
 
 # other
@@ -1355,10 +1545,10 @@ else {
 "vfCondJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "represents a virtual floating point compare",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "none", "none", "eax" ] },
   "outs"      => [ "false", "true", "temp_reg_eax" ],
   "latency"   => 10,
+  "units"     => [ "VFP" ],
 },
 
 #------------------------------------------------------------------------#
@@ -1374,7 +1564,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(%A3, %A4) -> %D1 */',
+  "emit"      => '. fadd%XM %x87_binop',
 },
 
 "faddp" => {
@@ -1382,7 +1572,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(%A3, %A4) -> %D1 */',
+  "emit"      => '. faddp %x87_binop',
 },
 
 "fmul" => {
@@ -1390,7 +1580,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(%A3, %A4) -> %D1 */',
+  "emit"      => '. fmul%XM %x87_binop',
 },
 
 "fmulp" => {
@@ -1398,7 +1588,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(%A3, %A4) -> %D1 */',,
+  "emit"      => '. fmulp %x87_binop',,
 },
 
 "fsub" => {
@@ -1406,7 +1596,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp Sub: Sub(a, b) = a - b",
   "reg_req"   => { },
-  "emit"      => '. fsub %ia32_emit_x87_binop /* x87 fsub(%A3, %A4) -> %D1 */',
+  "emit"      => '. fsub%XM %x87_binop',
 },
 
 "fsubp" => {
@@ -1414,7 +1604,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp Sub: Sub(a, b) = a - b",
   "reg_req"   => { },
-  "emit"      => '. fsubp %ia32_emit_x87_binop /* x87 fsub(%A3, %A4) -> %D1 */',
+  "emit"      => '. fsubp %x87_binop',
 },
 
 "fsubr" => {
@@ -1423,7 +1613,7 @@ else {
   "irn_flags" => "R",
   "comment"   => "x87 fp SubR: SubR(a, b) = b - a",
   "reg_req"   => { },
-  "emit"      => '. fsubr %ia32_emit_x87_binop /* x87 fsubr(%A3, %A4) -> %D1 */',
+  "emit"      => '. fsubr%XM %x87_binop',
 },
 
 "fsubrp" => {
@@ -1432,7 +1622,25 @@ else {
   "irn_flags" => "R",
   "comment"   => "x87 fp SubR: SubR(a, b) = b - a",
   "reg_req"   => { },
-  "emit"      => '. fsubrp %ia32_emit_x87_binop /* x87 fsubr(%A3, %A4) -> %D1 */',
+  "emit"      => '. fsubrp %x87_binop',
+},
+
+"fprem" => {
+  "op_flags"  => "R",
+  "rd_constructor" => "NONE",
+  "comment"   => "x87 fp Rem: Rem(a, b) = a - Q * b (Q is integer)",
+  "reg_req"   => { },
+  "emit"      => '. fprem1',
+},
+
+# this node is just here, to keep the simulator running
+# we can omit this when a fprem simulation function exists
+"fpremp" => {
+  "op_flags"  => "R",
+  "rd_constructor" => "NONE",
+  "comment"   => "x87 fp Rem: Rem(a, b) = a - Q * b (Q is integer)",
+  "reg_req"   => { },
+  "emit"      => '. fprem1',
 },
 
 "fdiv" => {
@@ -1440,7 +1648,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp Div: Div(a, b) = a / b",
   "reg_req"   => { },
-  "emit"      => '. fdiv %ia32_emit_x87_binop /* x87 fdiv(%A3, %A4) -> %D1 */',
+  "emit"      => '. fdiv%XM %x87_binop',
 },
 
 "fdivp" => {
@@ -1448,7 +1656,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp Div: Div(a, b) = a / b",
   "reg_req"   => { },
-  "emit"      => '. fdivp %ia32_emit_x87_binop /* x87 fdiv(%A3, %A4) -> %D1 */',
+  "emit"      => '. fdivp %x87_binop',
 },
 
 "fdivr" => {
@@ -1456,7 +1664,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp DivR: DivR(a, b) = b / a",
   "reg_req"   => { },
-  "emit"      => '. fdivr %ia32_emit_x87_binop /* x87 fdivr(%A3, %A4) -> %D1 */',
+  "emit"      => '. fdivr%XM %x87_binop',
 },
 
 "fdivrp" => {
@@ -1464,7 +1672,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp DivR: DivR(a, b) = b / a",
   "reg_req"   => { },
-  "emit"      => '. fdivrp %ia32_emit_x87_binop /* x87 fdivr(%A3, %A4) -> %D1 */',
+  "emit"      => '. fdivrp %x87_binop',
 },
 
 "fabs" => {
@@ -1472,7 +1680,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp Abs: Abs(a) = |a|",
   "reg_req"   => { },
-  "emit"      => '. fabs /* x87 fabs(%A1) -> %D1 */',
+  "emit"      => '. fabs',
 },
 
 "fchs" => {
@@ -1480,7 +1688,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp Chs: Chs(a) = -a",
   "reg_req"   => { },
-  "emit"      => '. fchs /* x87 fchs(%A1) -> %D1 */',
+  "emit"      => '. fchs',
 },
 
 "fsin" => {
@@ -1488,7 +1696,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp Sin: Sin(a) = sin(a)",
   "reg_req"   => { },
-  "emit"      => '. fsin /* x87 sin(%A1) -> %D1 */',
+  "emit"      => '. fsin',
 },
 
 "fcos" => {
@@ -1496,7 +1704,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp Cos: Cos(a) = cos(a)",
   "reg_req"   => { },
-  "emit"      => '. fcos /* x87 cos(%A1) -> %D1 */',
+  "emit"      => '. fcos',
 },
 
 "fsqrt" => {
@@ -1504,7 +1712,7 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp Sqrt: Sqrt(a) = a ^ 0.5",
   "reg_req"   => { },
-  "emit"      => '. fsqrt $ /* x87 sqrt(%A1) -> %D1 */',
+  "emit"      => '. fsqrt $',
 },
 
 # x87 Load and Store
@@ -1515,7 +1723,7 @@ else {
   "state"     => "exc_pinned",
   "comment"   => "x87 fp Load: Load(ptr, mem) = LD ptr -> reg",
   "reg_req"   => { },
-  "emit"      => '. fld %ia32_emit_am /* Load((%A1)) -> %D1 */',
+  "emit"      => '. fld%XM %AM',
 },
 
 "fst" => {
@@ -1524,7 +1732,8 @@ else {
   "state"     => "exc_pinned",
   "comment"   => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val",
   "reg_req"   => { },
-  "emit"      => '. fst %ia32_emit_am /* Store(%A3) -> (%A1) */',
+  "emit"      => '. fst%XM %AM',
+  "mode"      => "mode_M",
 },
 
 "fstp" => {
@@ -1533,7 +1742,8 @@ else {
   "state"     => "exc_pinned",
   "comment"   => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val",
   "reg_req"   => { },
-  "emit"      => '. fstp %ia32_emit_am /* Store(%A3) -> (%A1) and pop */',
+  "emit"      => '. fstp%XM %AM',
+  "mode"      => "mode_M",
 },
 
 # Conversions
@@ -1543,7 +1753,7 @@ else {
   "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 */',
+  "emit"      => '. fild%XM %AM',
 },
 
 "fist" => {
@@ -1551,7 +1761,8 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp integer Store: Store(ptr, val, mem) = iST ptr,val",
   "reg_req"   => { },
-  "emit"      => '. fist %ia32_emit_am /* integer Store(%A3) -> (%A1) */',
+  "emit"      => '. fist%M %AM',
+  "mode"      => "mode_M",
 },
 
 "fistp" => {
@@ -1559,7 +1770,8 @@ else {
   "rd_constructor" => "NONE",
   "comment"   => "x87 fp integer Store: Store(ptr, val, mem) = iST ptr,val",
   "reg_req"   => { },
-  "emit"      => '. fistp %ia32_emit_am /* integer Store(%A3) -> (%A1) and pop */',
+  "emit"      => '. fistp%M %AM',
+  "mode"      => "mode_M",
 },
 
 # constants
@@ -1568,56 +1780,56 @@ else {
   "op_flags"  => "R|c",
   "irn_flags"  => "R",
   "comment"   => "x87 fp Load 0.0: Ld 0.0 -> reg",
-  "reg_req"   => { },
-  "emit"      => '. fldz /* x87 0.0 -> %D1 */',
+  "reg_req"   => { "out" => [ "vfp" ] },
+  "emit"      => '. fldz',
 },
 
 "fld1" => {
   "op_flags"  => "R|c",
   "irn_flags"  => "R",
   "comment"   => "x87 fp Load 1.0: Ld 1.0 -> reg",
-  "reg_req"   => { },
-  "emit"      => '. fld1 /* x87 1.0 -> %D1 */',
+  "reg_req"   => { "out" => [ "vfp" ] },
+  "emit"      => '. fld1',
 },
 
 "fldpi" => {
   "op_flags"  => "R|c",
   "irn_flags"  => "R",
   "comment"   => "x87 fp Load pi: Ld pi -> reg",
-  "reg_req"   => { },
-  "emit"      => '. fldpi /* x87 pi -> %D1 */',
+  "reg_req"   => { "out" => [ "vfp" ] },
+  "emit"      => '. fldpi',
 },
 
 "fldln2" => {
   "op_flags"  => "R|c",
   "irn_flags"  => "R",
   "comment"   => "x87 fp Load ln 2: Ld ln 2 -> reg",
-  "reg_req"   => { },
-  "emit"      => '. fldln2 /* x87 ln(2) -> %D1 */',
+  "reg_req"   => { "out" => [ "vfp" ] },
+  "emit"      => '. fldln2',
 },
 
 "fldlg2" => {
   "op_flags"  => "R|c",
   "irn_flags"  => "R",
   "comment"   => "x87 fp Load lg 2: Ld lg 2 -> reg",
-  "reg_req"   => { },
-  "emit"      => '. fldlg2 /* x87 log(2) -> %D1 */',
+  "reg_req"   => { "out" => [ "vfp" ] },
+  "emit"      => '. fldlg2',
 },
 
 "fldl2t" => {
   "op_flags"  => "R|c",
   "irn_flags"  => "R",
   "comment"   => "x87 fp Load ld 10: Ld ld 10 -> reg",
-  "reg_req"   => { },
-  "emit"      => '. fldll2t /* x87 ld(10) -> %D1 */',
+  "reg_req"   => { "out" => [ "vfp" ] },
+  "emit"      => '. fldll2t',
 },
 
 "fldl2e" => {
   "op_flags"  => "R|c",
   "irn_flags"  => "R",
   "comment"   => "x87 fp Load ld e: Ld ld e -> reg",
-  "reg_req"   => { },
-  "emit"      => '. fldl2e /* x87 ld(e) -> %D1 */',
+  "reg_req"   => { "out" => [ "vfp" ] },
+  "emit"      => '. fldl2e',
 },
 
 "fldConst" => {
@@ -1625,36 +1837,44 @@ else {
   "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 %ia32_emit_adr /* Load fConst into register -> %D1 */',
+  "reg_req"   => { "out" => [ "vfp" ] },
+  "emit"      => '. fld $%C',
 },
 
 # 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" ] },
-  "cmp_attr"  => "  return 1;\n",
-  "emit"      => '. fxch %X1 /* x87 swap %X1, %X3 */',
+  "reg_req"   => { },
+  "cmp_attr"  => "return 1;",
+  "emit"      => '. fxch %X1',
 },
 
 "fpush" => {
+  "op_flags"  => "R|K",
+  "comment"   => "x87 stack push",
+  "reg_req"   => {},
+  "cmp_attr"  => "return 1;",
+  "emit"      => '. fld %X1',
+},
+
+"fpushCopy" => {
   "op_flags"  => "R",
   "comment"   => "x87 stack push",
-  "reg_req"   => { "in" => [ "st"], "out" => [ "st" ] },
-  "cmp_attr"  => "  return 1;\n",
-  "emit"      => '. fld %X1 /* x87 push %X1 */',
+  "reg_req"   => { "in" => [ "vfp"], "out" => [ "vfp" ] },
+  "cmp_attr"  => "return 1;",
+  "emit"      => '. fld %X1',
 },
 
 "fpop" => {
   "op_flags"  => "R|K",
   "comment"   => "x87 stack pop",
-  "reg_req"   => { "out" => [ "st" ] },
-  "cmp_attr"  => "  return 1;\n",
-  "emit"      => '. fstp %X1 /* x87 pop %X1 */',
+  "reg_req"   => { },
+  "cmp_attr"  => "return 1;",
+  "emit"      => '. fstp %X1',
 },
 
 # compare
@@ -1662,42 +1882,36 @@ else {
 "fcomJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "floating point compare",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { },
 },
 
 "fcompJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "floating point compare and pop",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { },
 },
 
 "fcomppJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "floating point compare and pop twice",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { },
 },
 
 "fcomrJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "floating point compare reverse",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { },
 },
 
 "fcomrpJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "floating point compare reverse and pop",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { },
 },
 
 "fcomrppJmp" => {
   "op_flags"  => "L|X|Y",
   "comment"   => "floating point compare reverse and pop twice",
-  "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { },
 },