Remove classify_tarval(). Use tarval_is_null(), tarval_is_one() and tarval_is_all_one...
[libfirm] / ir / be / ia32 / ia32_spec.pl
index 5c44177..9abf467 100644 (file)
@@ -253,8 +253,14 @@ $arch = "ia32";
        S3 => "${arch}_emit_source_register(env, node, 3);",
        S4 => "${arch}_emit_source_register(env, node, 4);",
        S5 => "${arch}_emit_source_register(env, node, 5);",
-       SB0 => "${arch}_emit_8bit_source_register(env, node, 0);",
+       SB1 => "${arch}_emit_8bit_source_register(env, node, 1);",
+       SB2 => "${arch}_emit_8bit_source_register(env, node, 2);",
+       SB3 => "${arch}_emit_8bit_source_register(env, node, 3);",
        SW0 => "${arch}_emit_16bit_source_register(env, node, 0);",
+       SI0 => "${arch}_emit_source_register_or_immediate(env, node, 0);",
+       SI1 => "${arch}_emit_source_register_or_immediate(env, node, 1);",
+       SI2 => "${arch}_emit_source_register_or_immediate(env, node, 2);",
+       SI3 => "${arch}_emit_source_register_or_immediate(env, node, 3);",
        D0 => "${arch}_emit_dest_register(env, node, 0);",
        D1 => "${arch}_emit_dest_register(env, node, 1);",
        D2 => "${arch}_emit_dest_register(env, node, 2);",
@@ -264,7 +270,6 @@ $arch = "ia32";
        X0 => "${arch}_emit_x87_name(env, node, 0);",
        X1 => "${arch}_emit_x87_name(env, node, 1);",
        X2 => "${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
                   ia32_emit_mode_suffix(env, node);",
@@ -278,8 +283,9 @@ $arch = "ia32";
        unop2 => "${arch}_emit_unop(env, node, 2);",
        unop3 => "${arch}_emit_unop(env, node, 3);",
        unop4 => "${arch}_emit_unop(env, node, 4);",
+       unop5 => "${arch}_emit_unop(env, node, 5);",
        DAM0  => "${arch}_emit_am_or_dest_register(env, node, 0);",
-       DAM1  => "${arch}_emit_am_or_dest_register(env, node, 0);",
+       DAM1  => "${arch}_emit_am_or_dest_register(env, node, 1);",
        binop => "${arch}_emit_binop(env, node);",
        x87_binop => "${arch}_emit_x87_binop(env, node);",
 );
@@ -298,6 +304,39 @@ $arch = "ia32";
 $default_attr_type = "ia32_attr_t";
 $default_copy_attr = "ia32_copy_attr";
 
+sub ia32_custom_init_attr {
+       my $node = shift;
+       my $name = shift;
+       my $res = "";
+       if(defined($node->{modified_flags})) {
+               $res .= "\tset_ia32_flags(res, get_ia32_flags(res) | arch_irn_flags_modify_flags);\n";
+       }
+       if(defined($node->{am})) {
+               my $am = $node->{am};
+               if($am eq "full,binary") {
+                       $res .= "\tset_ia32_am_support(res, ia32_am_Full, ia32_am_binary);";
+               } elsif($am eq "full,unary") {
+                       $res .= "\tset_ia32_am_support(res, ia32_am_Full, ia32_am_unary);";
+               } elsif($am eq "source,binary") {
+                       $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_binary);";
+               } elsif($am eq "dest,unary") {
+                       $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_unary);";
+               } elsif($am eq "dest,binary") {
+                       $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_binary);";
+               } elsif($am eq "dest,ternary") {
+                       $res .= "\tset_ia32_am_support(res, ia32_am_Dest, ia32_am_ternary);";
+               } elsif($am eq "source,ternary") {
+                       $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_ternary);";
+               } elsif($am eq "none") {
+                       # nothing to do
+               } else {
+                       die("Invalid address mode '$am' specified on op $name");
+               }
+       }
+       return $res;
+}
+$custom_init_attr_func = \&ia32_custom_init_attr;
+
 %init_attr = (
        ia32_attr_t     => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
        ia32_x87_attr_t =>
@@ -374,32 +413,48 @@ ProduceVal => {
 
 # commutative operations
 
-# NOTE:
-# All nodes supporting Addressmode have 5 INs:
-# 1 - base    r1 == NoReg in case of no AM or no base
-# 2 - index   r2 == NoReg in case of no AM or no index
-# 3 - op1     r3 == always present
-# 4 - op2     r4 == NoReg in case of immediate operation
-# 5 - mem     NoMem in case of no AM otherwise it takes the mem from the Load
-
 Add => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
-       ins       => [ "base", "index", "left", "right", "mem" ],
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4", "none", "flags" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. add%M %binop',
+       am        => "full,binary",
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
+AddMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       emit      => ". add%M %SI3, %AM",
+       units     => [ "GP" ],
+       mode      => "mode_M",
+       modified_flags => $status_flags
+},
+
 Adc => {
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right", "eflags" ],
        emit      => '. adc%M %binop',
+       am        => "full,binary",
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
+l_Add => {
+       op_flags  => "C",
+       reg_req   => { in => [ "none", "none" ], out => [ "none" ] },
+       ins       => [ "left", "right" ],
+},
+
+l_Adc => {
+       reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
+       ins       => [ "left", "right", "eflags" ],
+},
+
 Add64Bit => {
        irn_flags => "R",
        arity     => 4,
@@ -407,34 +462,22 @@ Add64Bit => {
        emit      => '
 . movl %S0, %D0
 . movl %S1, %D1
-. addl %S2, %D0
-. adcl %S3, %D1
+. addl %SI2, %D0
+. adcl %SI3, %D1
 ',
        outs      => [ "low_res", "high_res" ],
        units     => [ "GP" ],
        modified_flags => $status_flags
 },
 
-l_Add => {
-       op_flags  => "C",
-       irn_flags => "R",
-       cmp_attr  => "return 1;",
-       arity     => 2,
-},
-
-l_Adc => {
-       op_flags  => "C",
-       cmp_attr  => "return 1;",
-       arity     => 2,
-},
-
 Mul => {
        # we should not rematrialize this node. It produces 2 results and has
        # very strict constrains
-       reg_req   => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] },
-       emit      => '. mul%M %unop3',
+       reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] },
+       ins       => [ "base", "index", "mem", "val_high", "val_low" ],
+       emit      => '. mul%M %unop4',
        outs      => [ "EAX", "EDX", "M" ],
-       ins       => [ "base", "index", "val_high", "val_low", "mem" ],
+       am        => "source,binary",
        latency   => 10,
        units     => [ "GP" ],
        modified_flags => $status_flags
@@ -451,8 +494,10 @@ l_Mul => {
 
 IMul => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. imul%M %binop',
+       am        => "source,binary",
        latency   => 5,
        units     => [ "GP" ],
        mode      => $mode_gp,
@@ -461,52 +506,85 @@ IMul => {
 
 IMul1OP => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] },
-       emit      => '. imul%M %unop3',
+       reg_req   => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] },
+       ins       => [ "base", "index", "mem", "val_high", "val_low" ],
+       emit      => '. imul%M %unop4',
        outs      => [ "EAX", "EDX", "M" ],
-       ins       => [ "base", "index", "val_high", "val_low", "mem" ],
+       am        => "source,binary",
        latency   => 5,
        units     => [ "GP" ],
        modified_flags => $status_flags
 },
 
 l_IMul => {
+       # we should not rematrialize this node. It produces 2 results and has
+       # very strict constrains
        op_flags  => "C",
        cmp_attr  => "return 1;",
+       outs      => [ "EAX", "EDX", "M" ],
        arity     => 2
 },
 
 And => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
+       am        => "full,binary",
        emit      => '. and%M %binop',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
+AndMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       emit      => '. and%M %SI3, %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
+       modified_flags => $status_flags
+},
+
 Or => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
+       am        => "full,binary",
        emit      => '. or%M %binop',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
+OrMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       emit      => '. or%M %SI3, %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
+       modified_flags => $status_flags
+},
+
 Xor => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
+       am        => "full,binary",
        emit      => '. xor%M %binop',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
-l_Xor => {
-       op_flags  => "C",
-       cmp_attr  => "return 1;",
-       arity     => 2,
+XorMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       emit      => '. xor%M %SI3, %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
        modified_flags => $status_flags
 },
 
@@ -514,15 +592,29 @@ l_Xor => {
 
 Sub => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
+       am        => "full,binary",
        emit      => '. sub%M %binop',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
+SubMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       emit      => '. sub%M %SI3, %AM',
+       units     => [ "GP" ],
+       mode      => 'mode_M',
+       modified_flags => $status_flags
+},
+
 Sbb => {
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3 !in_r4" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 !in_r5" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
+       am        => "full,binary",
        emit      => '. sbb%M %binop',
        units     => [ "GP" ],
        mode      => $mode_gp,
@@ -536,33 +628,24 @@ Sub64Bit => {
        emit      => '
 . movl %S0, %D0
 . movl %S1, %D1
-. subl %S2, %D0
-. sbbl %S3, %D1
+. subl %SI2, %D0
+. sbbl %SI3, %D1
 ',
        outs      => [ "low_res", "high_res" ],
        units     => [ "GP" ],
        modified_flags => $status_flags
 },
 
-l_Sub => {
-       irn_flags => "R",
-       cmp_attr  => "return 1;",
-       arity     => 2,
-},
-
-l_Sbb => {
-       cmp_attr  => "return 1;",
-       arity     => 2,
-},
-
 IDiv => {
        op_flags  => "F|L",
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] },
+       ins       => [ "base", "index", "mem", "left_low", "left_high", "right" ],
+       outs      => [ "div_res", "mod_res", "M" ],
        attr      => "ia32_op_flavour_t dm_flav",
+       am        => "source,ternary",
        init_attr => "attr->data.op_flav = dm_flav;",
-       emit      => ". idiv%M %unop4",
-       outs      => [ "div_res", "mod_res", "M" ],
+       emit      => ". idiv%M %unop5",
        latency   => 25,
        units     => [ "GP" ],
        modified_flags => $status_flags
@@ -571,11 +654,13 @@ IDiv => {
 Div => {
        op_flags  => "F|L",
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] },
+       ins       => [ "base", "index", "mem", "left_low", "left_high", "right" ],
+       outs      => [ "div_res", "mod_res", "M" ],
        attr      => "ia32_op_flavour_t dm_flav",
+       am        => "source,ternary",
        init_attr => "attr->data.op_flav = dm_flav;",
-       emit      => ". div%M %unop4",
-       outs      => [ "div_res", "mod_res", "M" ],
+       emit      => ". div%M %unop5",
        latency   => 25,
        units     => [ "GP" ],
        modified_flags => $status_flags
@@ -583,50 +668,49 @@ Div => {
 
 Shl => {
        irn_flags => "R",
-       # "in_r3" would be enough as out requirement, but the register allocator
-       # does strange things then and doesn't respect the constraint for in4
-       # if the same value is attached to in3 and in4 (if you have "i << i" in C)
-       reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
-       ins       => [ "base", "index", "left", "right", "mem" ],
-       emit      => '. shl%M %binop',
+       reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+       ins       => [ "left", "right" ],
+       am        => "dest,binary",
+       emit      => '. shl %SB1, %S0',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
-l_Shl => {
+ShlMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "count" ],
+       emit      => '. shl%M %SB3, %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
+       modified_flags => $status_flags
+},
+
+l_ShlDep => {
        cmp_attr  => "return 1;",
-       arity     => 2
+       # value, cnt, dependency
+       arity     => 3
 },
 
 ShlD => {
-       irn_flags => "R",
+       # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shl
+       #
        # 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) {
-               . shld%M %%cl, %S3, %AM
-       } else {
-               . shld%M %%cl, %S3, %S2
-       }
-} else {
-       if (get_ia32_op_type(node) == ia32_AddrModeD) {
-               . shld%M %C, %S3, %AM
-       } else {
-               . shld%M %C, %S3, %S2
-       }
-}
-',
+       # 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" ] },
+
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r3" ] },
+       ins       => [ "left_high", "left_low", "right" ],
+       am        => "dest,ternary",
+       emit      => '. shld%M %SB2, %S1, %S0',
        latency   => 6,
        units     => [ "GP" ],
        mode      => $mode_gp,
@@ -640,20 +724,34 @@ l_ShlD => {
 
 Shr => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
-       emit      => '. shr%M %binop',
+       reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+       ins       => [ "val", "count" ],
+       am        => "dest,binary",
+       emit      => '. shr %SB1, %S0',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
-l_Shr => {
+ShrMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "count" ],
+       emit      => '. shr%M %SB3, %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
+       modified_flags => $status_flags
+},
+
+l_ShrDep => {
        cmp_attr  => "return 1;",
-       arity     => 2
+       # value, cnt, dependency
+       arity     => 3
 },
 
 ShrD => {
-       irn_flags => "R",
+       # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shr
+       #
        # 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
@@ -662,22 +760,13 @@ ShrD => {
        # 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) {
-               . shrd%M %%cl, %S3, %AM
-       } else {
-               . shrd%M %%cl, %S3, %S2
-       }
-} else {
-       if (get_ia32_op_type(node) == ia32_AddrModeD) {
-               . shrd%M %C, %S3, %AM
-       } else {
-               . shrd%M %C, %S3, %S2
-       }
-}
-',
+       # reg_req   => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] },
+
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r3" ] },
+       ins       => [ "left_high", "left_low", "right" ],
+       am        => "dest,ternary",
+       emit      => '. shrd%M %SB2, %S1, %S0',
        latency   => 6,
        units     => [ "GP" ],
        mode      => $mode_gp,
@@ -691,57 +780,105 @@ l_ShrD => {
 
 Sar => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
-       emit      => '. sar%M %binop',
+       reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+       ins       => [ "val", "count" ],
+       am        => "dest,binary",
+       emit      => '. sar %SB1, %S0',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
+SarMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "count" ],
+       emit      => '. sar%M %SB3, %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
+       modified_flags => $status_flags
+},
+
 l_Sar => {
        cmp_attr  => "return 1;",
+       # value, cnt
        arity     => 2
 },
 
+l_SarDep => {
+       cmp_attr  => "return 1;",
+       # value, cnt, dependency
+       arity     => 3
+},
+
 Ror => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
-       emit      => '. ror%M %binop',
+       reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+       ins       => [ "val", "count" ],
+       am        => "dest,binary",
+       emit      => '. ror %SB1, %S0',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
+RorMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "count" ],
+       emit      => '. ror%M %SB3, %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
+       modified_flags => $status_flags
+},
+
 Rol => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] },
-       emit      => '. rol%M %binop',
+       reg_req   => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] },
+       ins       => [ "val", "count" ],
+       am        => "dest,binary",
+       emit      => '. rol %SB1, %S0',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
+RolMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "count" ],
+       emit      => '. rol%M %SB3, %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
+       modified_flags => $status_flags
+},
+
 # unary operations
 
 Neg => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
-       emit      => '. neg%M %unop2',
-       ins       => [ "base", "index", "val", "mem" ],
+       reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
+       emit      => '. neg %S0',
+       ins       => [ "val" ],
+       am        => "dest,unary",
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
+NegMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem" ],
+       emit      => '. neg%M %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
+       modified_flags => $status_flags
+},
+
 Minus64Bit => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "!in", "!in" ] },
-       emit      => '
-. movl %S0, %D0
-. movl %S0, %D1
-. subl %S1, %D0
-. sbbl %S2, %D1
-',
+       reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1", "gp" ] },
        outs      => [ "low_res", "high_res" ],
        units     => [ "GP" ],
        modified_flags => $status_flags
@@ -755,61 +892,86 @@ l_Neg => {
 
 Inc => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
-       emit      => '. inc%M %unop2',
+       reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
+       am        => "dest,unary",
+       emit      => '. inc %S0',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
 },
 
-Dec => {
+IncMem => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
-       emit      => '. dec%M %unop2',
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem" ],
+       emit      => '. inc%M %AM',
        units     => [ "GP" ],
-       mode      => $mode_gp,
+       mode      => "mode_M",
        modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
 },
 
-Not => {
+Dec => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
-       ins       => [ "base", "index", "val", "mem" ],
-       emit      => '. not%M %unop2',
+       reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
+       am        => "dest,unary",
+       emit      => '. dec %S0',
        units     => [ "GP" ],
        mode      => $mode_gp,
-       modified_flags => []
+       modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
 },
 
-Zex8 => {
+DecMem => {
        irn_flags => "R",
-       reg_req   => { in => [ "eax ebx ecx edx" ], out => [ "gp" ] },
-       emit      => '. movzbl %SB0, %D0',
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem" ],
+       emit      => '. dec%M %AM',
        units     => [ "GP" ],
-       mode      => $mode_gp,
-       modified_flags => []
+       mode      => "mode_M",
+       modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
 },
 
-Zex16 => {
+Not => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp" ], out => [ "gp" ] },
-       emit      => '. movzwl %SW0, %D0',
+       reg_req   => { in => [ "gp" ], out => [ "in_r1" ] },
+       ins       => [ "val" ],
+       am        => "dest,unary",
+       emit      => '. not %S0',
        units     => [ "GP" ],
        mode      => $mode_gp,
-       modified_flags => []
 },
 
+NotMem => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem" ],
+       emit      => '. not%M %AM',
+       units     => [ "GP" ],
+       mode      => "mode_M",
+},
 
 # other operations
 
-CondJmp => {
+CmpJmp => {
        state     => "pinned",
        op_flags  => "L|X|Y",
-       reg_req   => { in  => [ "gp", "gp", "gp", "gp", "none" ],
-                      out => [ "none", "none"] },
-       ins       => [ "base", "index", "left", "right", "mem" ],
+       reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ], out => [ "none", "none"] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        outs      => [ "false", "true" ],
        attr      => "long pnc",
+       am        => "source,binary",
+       init_attr => "attr->pn_code = pnc;",
+       latency   => 3,
+       units     => [ "BRANCH" ],
+},
+
+CmpJmp8Bit => {
+       state     => "pinned",
+       op_flags  => "L|X|Y",
+       reg_req   => { in  => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "none", "none"] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
+       outs      => [ "false", "true" ],
+       attr      => "long pnc",
+       am        => "source,binary",
        init_attr => "attr->pn_code = pnc;",
        latency   => 3,
        units     => [ "BRANCH" ],
@@ -818,11 +980,24 @@ CondJmp => {
 TestJmp => {
        state     => "pinned",
        op_flags  => "L|X|Y",
-       reg_req   => { in  => [ "gp", "gp", "gp", "gp", "none" ],
-                      out => [ "none", "none" ] },
-       ins       => [ "base", "index", "left", "right", "mem" ],
+       reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ], out => [ "none", "none" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
+       outs      => [ "false", "true" ],
+       attr      => "long pnc",
+       am        => "source,binary",
+       init_attr => "attr->pn_code = pnc;",
+       latency   => 3,
+       units     => [ "BRANCH" ],
+},
+
+TestJmp8Bit => {
+       state     => "pinned",
+       op_flags  => "L|X|Y",
+       reg_req   => { in  => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "none", "none" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        outs      => [ "false", "true" ],
        attr      => "long pnc",
+       am        => "source,binary",
        init_attr => "attr->pn_code = pnc;",
        latency   => 3,
        units     => [ "BRANCH" ],
@@ -840,12 +1015,10 @@ SwitchJmp => {
 IJmp => {
        state     => "pinned",
        op_flags  => "X",
-       reg_req   => { in => [ "gp", "gp", "gp", "none" ] },
-       ins       => [ "base", "index", "val", "mem" ],
-       emit      => '. jmp *%unop2',
+       reg_req   => { in => [ "gp" ] },
+       emit      => '. jmp *%S0',
        units     => [ "BRANCH" ],
        mode      => "mode_X",
-       modified_flags => []
 },
 
 Const => {
@@ -853,6 +1026,8 @@ Const => {
        irn_flags => "R",
        reg_req   => { out => [ "gp" ] },
        units     => [ "GP" ],
+       attr      => "ir_entity *symconst, int symconst_sign, long offset",
+       attr_type => "ia32_immediate_attr_t",
        mode      => $mode_gp,
 },
 
@@ -933,6 +1108,7 @@ FldCW => {
        op_flags  => "L|F",
        state     => "pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
+       ins       => [ "base", "index", "mem" ],
        latency   => 5,
        emit      => ". fldcw %AM",
        mode      => $mode_fpcw,
@@ -943,7 +1119,8 @@ FldCW => {
 FnstCW => {
        op_flags  => "L|F",
        state     => "pinned",
-       reg_req   => { in => [ "gp", "gp", "fp_cw", "none" ], out => [ "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "fpcw" ],
        latency   => 5,
        emit      => ". fnstcw %AM",
        mode      => "mode_M",
@@ -994,9 +1171,9 @@ l_Store => {
 Store => {
        op_flags  => "L|F",
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] },
-       ins       => [ "base", "index", "val", "mem" ],
-       emit      => '. mov%M %binop',
+       reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       emit      => '. mov%M %SI3, %AM',
        latency   => 2,
        units     => [ "GP" ],
        mode      => "mode_M",
@@ -1005,8 +1182,9 @@ Store => {
 Store8Bit => {
        op_flags  => "L|F",
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => ["none" ] },
-       emit      => '. mov%M %binop',
+       reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       emit      => '. mov%M %SB3, %AM',
        latency   => 2,
        units     => [ "GP" ],
        mode      => "mode_M",
@@ -1015,31 +1193,31 @@ Store8Bit => {
 Lea => {
        irn_flags => "R",
        reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
+       ins       => [ "base", "index" ],
        emit      => '. leal %AM, %D0',
        latency   => 2,
        units     => [ "GP" ],
        mode      => $mode_gp,
-       modified_flags => [],
 },
 
 Push => {
-       reg_req   => { in => [ "gp", "gp", "gp", "esp", "none" ], out => [ "esp", "none" ] },
-       emit      => '. push%M %unop2',
-       ins       => [ "base", "index", "val", "stack", "mem" ],
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp", "none" ] },
+       ins       => [ "base", "index", "mem", "val", "stack" ],
+       emit      => '. push%M %unop3',
        outs      => [ "stack:I|S", "M" ],
+       am        => "source,binary",
        latency   => 2,
        units     => [ "GP" ],
-       modified_flags => [],
 },
 
 Pop => {
-       reg_req   => { in => [ "gp", "gp", "esp", "none" ], out => [ "esp", "gp", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "esp" ], out => [ "esp", "gp", "none" ] },
        emit      => '. pop%M %DAM1',
        outs      => [ "stack:I|S", "res", "M" ],
-       ins       => [ "base", "index", "stack", "mem" ],
+       ins       => [ "base", "index", "mem", "stack" ],
+       am        => "dest,unary",
        latency   => 3, # Pop is more expensive than Push on Athlon
        units     => [ "GP" ],
-       modified_flags => [],
 },
 
 Enter => {
@@ -1060,7 +1238,10 @@ Leave => {
 
 AddSP => {
        irn_flags => "I",
-       reg_req   => { in => [ "gp", "gp", "esp", "gp", "none" ], out => [ "in_r3", "none" ] },
+       state     => "pinned",
+       reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] },
+       ins       => [ "base", "index", "mem", "stack", "size" ],
+       am        => "source,binary",
        emit      => '. addl %binop',
        outs      => [ "stack:S", "M" ],
        units     => [ "GP" ],
@@ -1069,7 +1250,10 @@ AddSP => {
 
 SubSP => {
 #irn_flags => "I",
-       reg_req   => { in => [ "gp", "gp", "esp", "gp", "none" ], out => [ "in_r3", "gp", "none" ] },
+       state     => "pinned",
+       reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] },
+       ins       => [ "base", "index", "mem", "stack", "size" ],
+       am        => "source,binary",
        emit      => ". subl %binop\n".
                     ". movl %%esp, %D1",
        outs      => [ "stack:I|S", "addr", "M" ],
@@ -1085,11 +1269,9 @@ LdTls => {
 
 # the int instruction
 int => {
-       reg_req   => { in => [ "none" ], out => [ "none" ] },
+       reg_req   => { in => [ "gp" ], out => [ "none" ] },
        mode      => "mode_M",
-       attr      => "tarval *tv",
-       init_attr => "\tset_ia32_Immop_tarval(res, tv);",
-       emit      => '. int %C',
+       emit      => '. int %SI0',
        units     => [ "GP" ],
        cmp_attr  => "return 1;",
 },
@@ -1104,11 +1286,21 @@ int => {
 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
 #-----------------------------------------------------------------------------#
 
+xZero => {
+       irn_flags => "R",
+       reg_req   => { out => [ "xmm" ] },
+       emit      => '. xorp%XSD %D1, %D1',
+       latency   => 3,
+       units     => [ "SSE" ],
+       mode      => "mode_E",
+},
+
 # commutative operations
 
 xAdd => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. add%XXM %binop',
        latency   => 4,
        units     => [ "SSE" ],
@@ -1117,7 +1309,8 @@ xAdd => {
 
 xMul => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. mul%XXM %binop',
        latency   => 4,
        units     => [ "SSE" ],
@@ -1126,7 +1319,8 @@ xMul => {
 
 xMax => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. max%XXM %binop',
        latency   => 2,
        units     => [ "SSE" ],
@@ -1135,7 +1329,8 @@ xMax => {
 
 xMin => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. min%XXM %binop',
        latency   => 2,
        units     => [ "SSE" ],
@@ -1144,7 +1339,8 @@ xMin => {
 
 xAnd => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. andp%XSD %binop',
        latency   => 3,
        units     => [ "SSE" ],
@@ -1153,7 +1349,8 @@ xAnd => {
 
 xOr => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. orp%XSD %binop',
        units     => [ "SSE" ],
        mode      => "mode_E",
@@ -1161,7 +1358,8 @@ xOr => {
 
 xXor => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. xorp%XSD %binop',
        latency   => 3,
        units     => [ "SSE" ],
@@ -1172,7 +1370,8 @@ xXor => {
 
 xAndNot => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3 !in_r4" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. andnp%XSD %binop',
        latency   => 3,
        units     => [ "SSE" ],
@@ -1181,7 +1380,8 @@ xAndNot => {
 
 xSub => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        emit      => '. sub%XXM %binop',
        latency   => 4,
        units     => [ "SSE" ],
@@ -1190,7 +1390,8 @@ xSub => {
 
 xDiv => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3 !in_r4", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        outs      => [ "res", "M" ],
        emit      => '. div%XXM %binop',
        latency   => 16,
@@ -1201,17 +1402,18 @@ xDiv => {
 
 xCmp => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3 !in_r4" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        latency   => 3,
        units     => [ "SSE" ],
        mode      => "mode_E",
 },
 
-xCondJmp => {
+xCmpJmp => {
        state     => "pinned",
        op_flags  => "L|X|Y",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "none", "none" ] },
-       ins       => [ "base", "index", "left", "right", "mem" ],
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "none", "none" ] },
+       ins       => [ "base", "index", "mem", "left", "right" ],
        outs      => [ "false", "true" ],
        attr      => "long pnc",
        init_attr => "attr->pn_code = pnc;",
@@ -1219,34 +1421,28 @@ xCondJmp => {
        units     => [ "SSE" ],
 },
 
-xConst => {
-       op_flags  => "c",
-       irn_flags => "R",
-       reg_req   => { out => [ "xmm" ] },
-       emit      => '. mov%XXM %C, %D0',
-       latency   => 2,
-       units     => [ "SSE" ],
-       mode      => "mode_E",
-},
-
 # Load / Store
 
 xLoad => {
        op_flags  => "L|F",
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] },
+       ins       => [ "base", "index", "mem" ],
        emit      => '. mov%XXM %AM, %D0',
+       attr      => "ir_mode *load_mode",
+       init_attr => "attr->ls_mode = load_mode;",
        outs      => [ "res", "M" ],
-       latency   => 2,
+       latency   => 0,
        units     => [ "SSE" ],
 },
 
 xStore => {
        op_flags => "L|F",
        state    => "exc_pinned",
-       reg_req  => { in => [ "gp", "gp", "xmm", "none" ] },
-       emit     => '. mov%XXM %binop',
-       latency  => 2,
+       reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       emit     => '. mov%XXM %S3, %AM',
+       latency  => 0,
        units    => [ "SSE" ],
        mode     => "mode_M",
 },
@@ -1254,17 +1450,18 @@ xStore => {
 xStoreSimple => {
        op_flags => "L|F",
        state    => "exc_pinned",
-       reg_req  => { in => [ "gp", "gp", "xmm", "none" ] },
-       ins      => [ "base", "index", "val", "mem" ],
-       emit     => '. mov%XXM %S2, %AM',
-       latency  => 2,
+       reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
+       ins      => [ "base", "index", "mem", "val" ],
+       emit     => '. mov%XXM %S3, %AM',
+       latency  => 0,
        units    => [ "SSE" ],
        mode     => "mode_M",
 },
 
 CvtSI2SS => {
        op_flags => "L|F",
-       reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm" ] },
+       reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
+       ins      => [ "base", "index", "mem", "val" ],
        emit     => '. cvtsi2ss %D0, %AM',
        latency  => 2,
        units    => [ "SSE" ],
@@ -1273,8 +1470,9 @@ CvtSI2SS => {
 
 CvtSI2SD => {
        op_flags => "L|F",
-       reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm" ] },
-       emit     => '. cvtsi2sd %unop2',
+       reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] },
+       ins      => [ "base", "index", "mem", "val" ],
+       emit     => '. cvtsi2sd %unop3',
        latency  => 2,
        units    => [ "SSE" ],
        mode     => $mode_xmm
@@ -1301,7 +1499,8 @@ CopyB => {
        reg_req  => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] },
        outs     => [ "DST", "SRC", "CNT", "M" ],
        units    => [ "GP" ],
-       modified_flags => [ "DF" ]
+# we don't care about this flag, so no need to mark this node
+#      modified_flags => [ "DF" ]
 },
 
 CopyB_i => {
@@ -1310,43 +1509,53 @@ CopyB_i => {
        reg_req  => { in => [ "edi", "esi", "none" ], out => [  "edi", "esi", "none" ] },
        outs     => [ "DST", "SRC", "M" ],
        units    => [ "GP" ],
-       modified_flags => [ "DF" ]
+# we don't care about this flag, so no need to mark this node
+#      modified_flags => [ "DF" ]
 },
 
 # Conversions
 
 Conv_I2I => {
-       reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3", "none" ] },
-       units    => [ "GP" ],
-       ins      => [ "base", "index", "val", "mem" ],
-       mode     => $mode_gp,
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "in_r4", "none" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       units     => [ "GP" ],
+       attr      => "ir_mode *smaller_mode",
+       init_attr => "attr->ls_mode = smaller_mode;",
+       mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
 Conv_I2I8Bit => {
-       reg_req  => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => [ "in_r3", "none" ] },
-       ins      => [ "base", "index", "val", "mem" ],
-       units    => [ "GP" ],
-       mode     => $mode_gp,
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "in_r4", "none" ] },
+       ins       => [ "base", "index", "mem", "val" ],
+       units     => [ "GP" ],
+       attr      => "ir_mode *smaller_mode",
+       init_attr => "attr->ls_mode = smaller_mode;",
+       mode      => $mode_gp,
        modified_flags => $status_flags
 },
 
 Conv_I2FP => {
-       reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm", "none" ] },
+       reg_req  => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] },
+       ins      => [ "base", "index", "mem", "val" ],
        latency  => 10,
        units    => [ "SSE" ],
        mode     => "mode_E",
 },
 
 Conv_FP2I => {
-       reg_req  => { in => [ "gp", "gp", "xmm", "none" ], out => [ "gp", "none" ] },
+       reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] },
+       ins      => [ "base", "index", "mem", "val" ],
        latency  => 10,
        units    => [ "SSE" ],
        mode     => $mode_gp,
 },
 
 Conv_FP2FP => {
-       reg_req  => { in => [ "gp", "gp", "xmm", "none" ], out => [ "xmm", "none" ] },
+       reg_req  => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] },
+       ins      => [ "base", "index", "mem", "val" ],
        latency  => 8,
        units    => [ "SSE" ],
        mode     => "mode_E",
@@ -1354,8 +1563,19 @@ Conv_FP2FP => {
 
 CmpCMov => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none", "gp", "gp" ], out => [ "in_r7" ] },
-       ins       => [ "base", "index", "cmp_left", "cmp_right", "mem", "val_true", "val_false" ],
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
+       attr      => "pn_Cmp pn_code",
+       init_attr => "attr->pn_code = pn_code;",
+       latency   => 2,
+       units     => [ "GP" ],
+       mode      => $mode_gp,
+},
+
+CmpCMov8Bit => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
        attr      => "pn_Cmp pn_code",
        init_attr => "attr->pn_code = pn_code;",
        latency   => 2,
@@ -1365,8 +1585,19 @@ CmpCMov => {
 
 TestCMov => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none", "gp", "gp" ], out => [ "in_r7" ] },
-       ins       => [ "base", "index", "cmp_left", "cmp_right", "mem", "val_true", "val_false" ],
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
+       attr      => "pn_Cmp pn_code",
+       init_attr => "attr->pn_code = pn_code;",
+       latency   => 2,
+       units     => [ "GP" ],
+       mode      => $mode_gp,
+},
+
+TestCMov8Bit => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
        attr      => "pn_Cmp pn_code",
        init_attr => "attr->pn_code = pn_code;",
        latency   => 2,
@@ -1384,17 +1615,29 @@ xCmpCMov => {
 
 vfCmpCMov => {
        irn_flags => "R",
-       reg_req   => { in => [ "vfp", "vfp", "gp", "gp" ], out => [ "in_r4" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "gp", "gp" ], out => [ "in_r7" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ],
        latency   => 10,
-       units     => [ "VFP" ],
+       units     => [ "VFP", "GP" ],
        mode      => $mode_gp,
        attr_type => "ia32_x87_attr_t",
 },
 
 CmpSet => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "eax ebx ecx edx" ] },
-       ins       => [ "base", "index", "cmp_left", "cmp_right", "mem" ],
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "eax ebx ecx edx" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
+       attr      => "pn_Cmp pn_code",
+       init_attr => "attr->pn_code = pn_code;",
+       latency   => 2,
+       units     => [ "GP" ],
+       mode      => $mode_gp,
+},
+
+CmpSet8Bit => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "eax ebx ecx edx" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
        attr      => "pn_Cmp pn_code",
        init_attr => "attr->pn_code = pn_code;",
        latency   => 2,
@@ -1404,8 +1647,19 @@ CmpSet => {
 
 TestSet => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "eax ebx ecx edx" ] },
-       ins       => [ "base", "index", "cmp_left", "cmp_right", "mem" ],
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "eax ebx ecx edx" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
+       attr      => "pn_Cmp pn_code",
+       init_attr => "attr->pn_code = pn_code;",
+       latency   => 2,
+       units     => [ "GP" ],
+       mode      => $mode_gp,
+},
+
+TestSet8Bit => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "eax ebx ecx edx" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
        attr      => "pn_Cmp pn_code",
        init_attr => "attr->pn_code = pn_code;",
        latency   => 2,
@@ -1415,7 +1669,8 @@ TestSet => {
 
 xCmpSet => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "eax ebx ecx edx" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eax ebx ecx edx" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
        latency   => 5,
        units     => [ "SSE" ],
        mode      => $mode_gp,
@@ -1423,7 +1678,8 @@ xCmpSet => {
 
 vfCmpSet => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "eax ebx ecx edx" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp" ], out => [ "eax ebx ecx edx" ] },
+       ins       => [ "base", "index", "mem", "cmp_left", "cmp_right" ],
        latency   => 10,
        units     => [ "VFP" ],
        mode      => $mode_gp,
@@ -1455,8 +1711,8 @@ vfCMov => {
 
 vfadd => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
-       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
+       reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1465,8 +1721,8 @@ vfadd => {
 
 vfmul => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
-       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
+       reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1481,8 +1737,8 @@ l_vfmul => {
 
 vfsub => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
-       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
+       reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1495,8 +1751,8 @@ l_vfsub => {
 },
 
 vfdiv => {
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp", "none" ] },
-       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
+       reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
+       ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
        outs      => [ "res", "M" ],
        latency   => 20,
        units     => [ "VFP" ],
@@ -1510,8 +1766,8 @@ l_vfdiv => {
 },
 
 vfprem => {
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
-       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
+       reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
        latency   => 20,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1551,8 +1807,8 @@ vfld => {
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
        ins       => [ "base", "index", "mem" ],
        outs      => [ "res", "M" ],
-       attr      => "ir_mode *store_mode",
-       init_attr => "attr->attr.ls_mode = store_mode;",
+       attr      => "ir_mode *load_mode",
+       init_attr => "attr->attr.ls_mode = load_mode;",
        latency   => 2,
        units     => [ "VFP" ],
        attr_type => "ia32_x87_attr_t",
@@ -1561,8 +1817,8 @@ vfld => {
 vfst => {
        op_flags  => "L|F",
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "vfp", "none" ] },
-       ins       => [ "base", "index", "val", "mem" ],
+       reg_req   => { in => [ "gp", "gp", "none", "vfp" ] },
+       ins       => [ "base", "index", "mem", "val" ],
        attr      => "ir_mode *store_mode",
        init_attr => "attr->attr.ls_mode = store_mode;",
        latency   => 2,
@@ -1591,8 +1847,8 @@ l_vfild => {
 
 vfist => {
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "vfp", "fpcw", "none" ] },
-       ins       => [ "base", "index", "val", "fpcw", "mem" ],
+       reg_req   => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
+       ins       => [ "base", "index", "mem", "val", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_M",
@@ -1672,19 +1928,9 @@ vfldl2e => {
        attr_type => "ia32_x87_attr_t",
 },
 
-vfConst => {
-       op_flags  => "c",
-       irn_flags => "R",
-       reg_req   => { out => [ "vfp" ] },
-       latency   => 3,
-       units     => [ "VFP" ],
-       mode      => "mode_E",
-       attr_type => "ia32_x87_attr_t",
-},
-
 # other
 
-vfCondJmp => {
+vfCmpJmp => {
        state     => "pinned",
        op_flags  => "L|X|Y",
        reg_req   => { in => [ "vfp", "vfp" ], out => [ "none", "none", "eax" ] },
@@ -1881,7 +2127,7 @@ fild => {
        op_flags  => "R",
        rd_constructor => "NONE",
        reg_req   => { },
-       emit      => '. fild%XM %AM',
+       emit      => '. fild%M %AM',
        attr_type => "ia32_x87_attr_t",
 },
 
@@ -1890,7 +2136,7 @@ fist => {
        state     => "exc_pinned",
        rd_constructor => "NONE",
        reg_req   => { },
-       emit      => '. fist%XM %AM',
+       emit      => '. fist%M %AM',
        mode      => "mode_M",
        attr_type => "ia32_x87_attr_t",
 },
@@ -1900,7 +2146,7 @@ fistp => {
        state     => "exc_pinned",
        rd_constructor => "NONE",
        reg_req   => { },
-       emit      => '. fistp%XM %AM',
+       emit      => '. fistp%M %AM',
        mode      => "mode_M",
        attr_type => "ia32_x87_attr_t",
 },
@@ -1992,13 +2238,37 @@ fpushCopy => {
 },
 
 fpop => {
-       op_flags  => "R|K",
+       op_flags  => "K",
        reg_req   => { },
        cmp_attr  => "return 1;",
        emit      => '. fstp %X0',
        attr_type => "ia32_x87_attr_t",
 },
 
+ffreep => {
+       op_flags  => "K",
+       reg_req   => { },
+       cmp_attr  => "return 1;",
+       emit      => '. ffreep %X0',
+       attr_type => "ia32_x87_attr_t",
+},
+
+emms => {
+       op_flags  => "K",
+       reg_req   => { },
+       cmp_attr  => "return 1;",
+       emit      => '. emms',
+       attr_type => "ia32_x87_attr_t",
+},
+
+femms => {
+       op_flags  => "K",
+       reg_req   => { },
+       cmp_attr  => "return 1;",
+       emit      => '. femms',
+       attr_type => "ia32_x87_attr_t",
+},
+
 # compare
 
 fcomJmp => {
@@ -2062,7 +2332,8 @@ xxLoad => {
 xxStore => {
        op_flags => "L|F",
        state    => "exc_pinned",
-       reg_req  => { in => [ "gp", "gp", "xmm", "none" ] },
+       reg_req  => { in => [ "gp", "gp", "none", "xmm" ] },
+       ins      => [ "base", "index", "mem", "val" ],
        emit     => '. movdqu %binop',
        units    => [ "SSE" ],
        mode     => "mode_M",