ad-hoc fix for lfoat compares (this is not mallons optimal solution yet)
[libfirm] / ir / be / ia32 / ia32_spec.pl
index 64e5a29..99991fc 100644 (file)
@@ -33,6 +33,7 @@ $arch = "ia32";
 #   init_attr => "emit attribute initialization template"
 #   rd_constructor => "c source code which constructs an ir_node"
 #   latency   => "latency of this operation (can be float)"
+#   attr_type => "name of the attribute struct",
 # },
 #
 # ... # (all nodes you need to describe)
@@ -121,6 +122,17 @@ $arch = "ia32";
                { name => "gp_UKNWN", type => 4 | 8 | 16 },  # we need a dummy register for Unknown nodes
                { mode => "mode_Iu" }
        ],
+       mmx => [
+               { name => "mm0", type => 4 },
+               { name => "mm1", type => 4 },
+               { name => "mm2", type => 4 },
+               { name => "mm3", type => 4 },
+               { name => "mm4", type => 4 },
+               { name => "mm5", type => 4 },
+               { name => "mm6", type => 4 },
+               { name => "mm7", type => 4 },
+               { mode => "mode_E" }
+       ],
        xmm => [
                { name => "xmm0", type => 1 },
                { name => "xmm1", type => 1 },
@@ -259,7 +271,13 @@ $arch = "ia32";
        XXM => "${arch}_emit_xmm_mode_suffix(env, node);",
        XSD => "${arch}_emit_xmm_mode_suffix_s(env, node);",
        AM => "${arch}_emit_am(env, node);",
-       unop => "${arch}_emit_unop(env, node);",
+       unop0 => "${arch}_emit_unop(env, node, 0);",
+       unop1 => "${arch}_emit_unop(env, node, 1);",
+       unop2 => "${arch}_emit_unop(env, node, 2);",
+       unop3 => "${arch}_emit_unop(env, node, 3);",
+       unop4 => "${arch}_emit_unop(env, node, 4);",
+       DAM0  => "${arch}_emit_am_or_dest_register(env, node, 0);",
+       DAM1  => "${arch}_emit_am_or_dest_register(env, node, 0);",
        binop => "${arch}_emit_binop(env, node);",
        x87_binop => "${arch}_emit_x87_binop(env, node);",
 );
@@ -275,8 +293,29 @@ $arch = "ia32";
 #                                      |_|         #
 #--------------------------------------------------#
 
-$default_cmp_attr  = "return ia32_compare_attr(attr_a, attr_b);";
 $default_attr_type = "ia32_attr_t";
+$default_copy_attr = "ia32_copy_attr";
+
+%init_attr = (
+       ia32_attr_t     => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);",
+       ia32_x87_attr_t =>
+               "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
+               "\tinit_ia32_x87_attributes(res);",
+       ia32_asm_attr_t =>
+               "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
+               "\tinit_ia32_x87_attributes(res);".
+               "\tinit_ia32_asm_attributes(res);",
+       ia32_immediate_attr_t =>
+               "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n".
+               "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);"
+);
+
+%compare_attr = (
+       ia32_attr_t           => "ia32_compare_nodes_attr",
+       ia32_x87_attr_t       => "ia32_compare_x87_attr",
+       ia32_asm_attr_t       => "ia32_compare_asm_attr",
+       ia32_immediate_attr_t => "ia32_compare_immediate_attr",
+);
 
 %operands = (
 );
@@ -290,17 +329,21 @@ $fpcw_flags   = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM",
 
 %nodes = (
 
-#Immediate => {
-#      irn_flags => "i",
-#      reg_req   => { out => [ "NoReg_GP" ] },
-#      mode      => $mode_gp,
-#      attr_type => "ia32_imm_t",
-#},
+Immediate => {
+       state     => "pinned",
+       op_flags  => "c",
+       irn_flags => "I",
+       reg_req   => { out => [ "gp_NOREG" ] },
+       attr      => "ir_entity *symconst, int symconst_sign, long offset",
+       attr_type => "ia32_immediate_attr_t",
+       mode      => $mode_gp,
+},
 
 Asm => {
        mode      => "mode_T",
        arity     => "variable",
        out_arity => "variable",
+       attr_type => "ia32_asm_attr_t",
 },
 
 #-----------------------------------------------------------------#
@@ -374,8 +417,9 @@ 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 %unop',
+       emit      => '. mul%M %unop3',
        outs      => [ "EAX", "EDX", "M" ],
+       ins       => [ "base", "index", "val_high", "val_low", "mem" ],
        latency   => 10,
        units     => [ "GP" ],
        modified_flags => $status_flags
@@ -403,8 +447,9 @@ IMul => {
 IMul1OP => {
        irn_flags => "R",
        reg_req   => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] },
-       emit      => '. imul%M %unop',
+       emit      => '. imul%M %unop3',
        outs      => [ "EAX", "EDX", "M" ],
+       ins       => [ "base", "index", "val_high", "val_low", "mem" ],
        latency   => 5,
        units     => [ "GP" ],
        modified_flags => $status_flags
@@ -501,7 +546,7 @@ IDiv => {
        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      => ". idiv%M %unop",
+       emit      => ". idiv%M %unop4",
        outs      => [ "div_res", "mod_res", "M" ],
        latency   => 25,
        units     => [ "GP" ],
@@ -514,7 +559,7 @@ Div => {
        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      => ". div%M %unop",
+       emit      => ". div%M %unop4",
        outs      => [ "div_res", "mod_res", "M" ],
        latency   => 25,
        units     => [ "GP" ],
@@ -523,6 +568,9 @@ 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',
@@ -541,11 +589,12 @@ ShlD => {
        # 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.
+       # 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      =>
 '
@@ -662,7 +711,8 @@ Rol => {
 Neg => {
        irn_flags => "R",
        reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
-       emit      => '. neg%M %unop',
+       emit      => '. neg%M %unop2',
+       ins       => [ "base", "index", "val", "mem" ],
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => $status_flags
@@ -691,7 +741,7 @@ l_Neg => {
 Inc => {
        irn_flags => "R",
        reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
-       emit      => '. inc%M %unop',
+       emit      => '. inc%M %unop2',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
@@ -700,7 +750,7 @@ Inc => {
 Dec => {
        irn_flags => "R",
        reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
-       emit      => '. dec%M %unop',
+       emit      => '. dec%M %unop2',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ]
@@ -709,7 +759,8 @@ Dec => {
 Not => {
        irn_flags => "R",
        reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] },
-       emit      => '. not%M %unop',
+       ins       => [ "base", "index", "val", "mem" ],
+       emit      => '. not%M %unop2',
        units     => [ "GP" ],
        mode      => $mode_gp,
        modified_flags => []
@@ -720,8 +771,12 @@ Not => {
 CondJmp => {
        state     => "pinned",
        op_flags  => "L|X|Y",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "none", "none"] },
+       reg_req   => { in  => [ "gp", "gp", "gp", "gp", "none" ],
+                      out => [ "none", "none"] },
+       ins       => [ "base", "index", "left", "right", "mem" ],
        outs      => [ "false", "true" ],
+       attr      => "long pnc",
+       init_attr => "attr->pn_code = pnc;",
        latency   => 3,
        units     => [ "BRANCH" ],
 },
@@ -729,33 +784,23 @@ CondJmp => {
 TestJmp => {
        state     => "pinned",
        op_flags  => "L|X|Y",
-       reg_req  => { in => [ "gp", "gp" ], out => [ "none", "none" ] },
+       reg_req   => { in  => [ "gp", "gp", "gp", "gp", "none" ],
+                      out => [ "none", "none" ] },
+       ins       => [ "base", "index", "left", "right", "mem" ],
        outs      => [ "false", "true" ],
+       attr      => "long pnc",
+       init_attr => "attr->pn_code = pnc;",
        latency   => 3,
        units     => [ "BRANCH" ],
 },
 
-CJmpAM => {
-       state     => "pinned",
-       op_flags  => "L|X|Y",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "none", "none" ] },
-       outs      => [ "false", "true" ],
-       units     => [ "BRANCH" ],
-},
-
-CJmp => {
-       state     => "pinned",
-       op_flags  => "L|X|Y",
-       reg_req   => { in => [ "gp", "gp" ] },
-       units     => [ "BRANCH" ],
-},
-
 SwitchJmp => {
        state     => "pinned",
        op_flags  => "L|X|Y",
        reg_req   => { in => [ "gp" ], out => [ "none" ] },
        latency   => 3,
        units     => [ "BRANCH" ],
+       mode      => "mode_T",
 },
 
 Const => {
@@ -783,7 +828,8 @@ Unknown_VFP => {
        reg_req   => { out => [ "vfp_UKNWN" ] },
        units     => [],
        emit      => "",
-       mode      => "mode_E"
+       mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 Unknown_XMM => {
@@ -813,7 +859,8 @@ NoReg_VFP => {
        reg_req   => { out => [ "vfp_NOREG" ] },
        units     => [],
        emit      => "",
-       mode      => "mode_E"
+       mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 NoReg_XMM => {
@@ -839,7 +886,7 @@ ChangeCW => {
 
 FldCW => {
        op_flags  => "L|F",
-       state     => "exc_pinned",
+       state     => "pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] },
        latency   => 5,
        emit      => ". fldcw %AM",
@@ -850,7 +897,7 @@ FldCW => {
 
 FnstCW => {
        op_flags  => "L|F",
-       state     => "exc_pinned",
+       state     => "pinned",
        reg_req   => { in => [ "gp", "gp", "fp_cw", "none" ], out => [ "none" ] },
        latency   => 5,
        emit      => ". fnstcw %AM",
@@ -861,21 +908,26 @@ FnstCW => {
 Cltd => {
        # we should not rematrialize this node. It produces 2 results and has
        # very strict constrains
-       reg_req   => { in => [ "gp" ], out => [ "eax in_r1", "edx" ] },
+       reg_req   => { in => [ "eax" ], out => [ "edx" ] },
+       ins       => [ "val" ],
        emit      => '. cltd',
-       outs      => [ "EAX", "EDX" ],
+       mode      => $mode_gp,
        units     => [ "GP" ],
 },
 
 # Load / Store
+#
+# Note that we add additional latency values depending on address mode, so a
+# lateny of 0 for load is correct
 
 Load => {
        op_flags  => "L|F",
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
-       latency   => 3,
-       emit      => ". mov%SE%ME%.l %AM, %D0",
+       ins       => [ "base", "index", "mem" ],
        outs      => [ "res", "M" ],
+       latency   => 0,
+       emit      => ". mov%SE%ME%.l %AM, %D0",
        units     => [ "GP" ],
 },
 
@@ -898,8 +950,9 @@ 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',
-       latency   => 3,
+       latency   => 2,
        units     => [ "GP" ],
        mode      => "mode_M",
 },
@@ -909,14 +962,14 @@ Store8Bit => {
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => ["none" ] },
        emit      => '. mov%M %binop',
-       latency   => 3,
+       latency   => 2,
        units     => [ "GP" ],
        mode      => "mode_M",
 },
 
 Lea => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp" ], out => [ "in_r1" ] },
+       reg_req   => { in => [ "gp", "gp" ], out => [ "gp" ] },
        emit      => '. leal %AM, %D0',
        latency   => 2,
        units     => [ "GP" ],
@@ -926,18 +979,20 @@ Lea => {
 
 Push => {
        reg_req   => { in => [ "gp", "gp", "gp", "esp", "none" ], out => [ "esp", "none" ] },
-       emit      => '. push%M %unop',
+       emit      => '. push%M %unop2',
+       ins       => [ "base", "index", "val", "stack", "mem" ],
        outs      => [ "stack:I|S", "M" ],
-       latency   => 3,
+       latency   => 2,
        units     => [ "GP" ],
        modified_flags => [],
 },
 
 Pop => {
        reg_req   => { in => [ "gp", "gp", "esp", "none" ], out => [ "esp", "gp", "none" ] },
-       emit      => '. pop%M %unop',
+       emit      => '. pop%M %DAM1',
        outs      => [ "stack:I|S", "res", "M" ],
-       latency   => 4,
+       ins       => [ "base", "index", "stack", "mem" ],
+       latency   => 3, # Pop is more expensive than Push on Athlon
        units     => [ "GP" ],
        modified_flags => [],
 },
@@ -1110,7 +1165,10 @@ xCondJmp => {
        state     => "pinned",
        op_flags  => "L|X|Y",
        reg_req   => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "none", "none" ] },
+       ins       => [ "base", "index", "left", "right", "mem" ],
        outs      => [ "false", "true" ],
+       attr      => "long pnc",
+       init_attr => "attr->pn_code = pnc;",
        latency   => 5,
        units     => [ "SSE" ],
 },
@@ -1170,7 +1228,7 @@ CvtSI2SS => {
 CvtSI2SD => {
        op_flags => "L|F",
        reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm" ] },
-       emit     => '. cvtsi2sd %unop',
+       emit     => '. cvtsi2sd %unop2',
        latency  => 2,
        units    => [ "SSE" ],
        mode     => $mode_xmm
@@ -1192,7 +1250,7 @@ l_SSEtoX87 => {
 GetST0 => {
        op_flags => "L|F",
        irn_flags => "I",
-       state    => "exc_pinned",
+       state    => "pinned",
        reg_req  => { in => [ "gp", "gp", "none" ] },
        emit     => '. fstp%XM %AM',
        latency  => 4,
@@ -1203,7 +1261,7 @@ GetST0 => {
 SetST0 => {
        op_flags => "L|F",
        irn_flags => "I",
-       state    => "exc_pinned",
+       state    => "pinned",
        reg_req  => { in => [ "gp", "gp", "none" ], out => [ "vf0", "none" ] },
        ins      => [ "base", "index", "mem" ],
        emit     => '. fld%XM %AM',
@@ -1237,12 +1295,14 @@ CopyB_i => {
 Conv_I2I => {
        reg_req  => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3", "none" ] },
        units    => [ "GP" ],
+       ins      => [ "base", "index", "val", "mem" ],
        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,
        modified_flags => $status_flags
@@ -1271,15 +1331,21 @@ Conv_FP2FP => {
 
 CmpCMov => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp", "gp" ], out => [ "in_r4" ] },
+       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" ],
+       attr      => "pn_Cmp pn_code",
+       init_attr => "attr->pn_code = pn_code;",
        latency   => 2,
        units     => [ "GP" ],
        mode      => $mode_gp,
 },
 
-PsiCondCMov => {
+TestCMov => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "in_r3" ] },
+       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" ],
+       attr      => "pn_Cmp pn_code",
+       init_attr => "attr->pn_code = pn_code;",
        latency   => 2,
        units     => [ "GP" ],
        mode      => $mode_gp,
@@ -1299,19 +1365,26 @@ vfCmpCMov => {
        latency   => 10,
        units     => [ "VFP" ],
        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" ],
+       attr      => "pn_Cmp pn_code",
+       init_attr => "attr->pn_code = pn_code;",
        latency   => 2,
        units     => [ "GP" ],
        mode      => $mode_gp,
 },
 
-PsiCondSet => {
+TestSet => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp" ], out => [ "eax ebx ecx edx" ] },
+       reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "eax ebx ecx edx" ] },
+       ins       => [ "base", "index", "cmp_left", "cmp_right", "mem" ],
+       attr      => "pn_Cmp pn_code",
+       init_attr => "attr->pn_code = pn_code;",
        latency   => 2,
        units     => [ "GP" ],
        mode      => $mode_gp,
@@ -1331,6 +1404,7 @@ vfCmpSet => {
        latency   => 10,
        units     => [ "VFP" ],
        mode      => $mode_gp,
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfCMov => {
@@ -1339,6 +1413,7 @@ vfCMov => {
        latency   => 10,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 #----------------------------------------------------------#
@@ -1357,18 +1432,22 @@ vfCMov => {
 
 vfadd => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfmul => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 l_vfmul => {
@@ -1379,10 +1458,12 @@ l_vfmul => {
 
 vfsub => {
        irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 l_vfsub => {
@@ -1391,10 +1472,12 @@ l_vfsub => {
 },
 
 vfdiv => {
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp", "none" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        outs      => [ "res", "M" ],
        latency   => 20,
        units     => [ "VFP" ],
+       attr_type => "ia32_x87_attr_t",
 },
 
 l_vfdiv => {
@@ -1404,10 +1487,12 @@ l_vfdiv => {
 },
 
 vfprem => {
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] },
+       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none", "fpcw" ], out => [ "vfp" ] },
+       ins       => [ "base", "index", "left", "right", "mem", "fpcw" ],
        latency   => 20,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 l_vfprem => {
@@ -1418,41 +1503,21 @@ l_vfprem => {
 vfabs => {
        irn_flags => "R",
        reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
+       ins       => [ "value" ],
        latency   => 2,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfchs => {
        irn_flags => "R",
        reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
+       ins       => [ "value" ],
        latency   => 2,
        units     => [ "VFP" ],
        mode      => "mode_E",
-},
-
-vfsin => {
-       irn_flags => "R",
-       reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
-       latency   => 150,
-       units     => [ "VFP" ],
-       mode      => "mode_E",
-},
-
-vfcos => {
-       irn_flags => "R",
-       reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
-       latency   => 150,
-       units     => [ "VFP" ],
-       mode      => "mode_E",
-},
-
-vfsqrt => {
-       irn_flags => "R",
-       reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
-       latency   => 30,
-       units     => [ "VFP" ],
-       mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 # virtual Load and Store
@@ -1461,27 +1526,38 @@ vfld => {
        op_flags  => "L|F",
        state     => "exc_pinned",
        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;",
        latency   => 2,
        units     => [ "VFP" ],
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfst => {
        op_flags  => "L|F",
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "vfp", "none" ] },
+       ins       => [ "base", "index", "val", "mem" ],
+       attr      => "ir_mode *store_mode",
+       init_attr => "attr->attr.ls_mode = store_mode;",
        latency   => 2,
        units     => [ "VFP" ],
        mode      => "mode_M",
+       attr_type => "ia32_x87_attr_t",
 },
 
 # Conversions
 
 vfild => {
+       state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] },
        outs      => [ "res", "M" ],
+       ins       => [ "base", "index", "mem" ],
        latency   => 4,
        units     => [ "VFP" ],
+       attr_type => "ia32_x87_attr_t",
 },
 
 l_vfild => {
@@ -1491,14 +1567,18 @@ l_vfild => {
 },
 
 vfist => {
+       state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "vfp", "fpcw", "none" ] },
+       ins       => [ "base", "index", "val", "fpcw", "mem" ],
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_M",
+       attr_type => "ia32_x87_attr_t",
 },
 
 l_vfist => {
        cmp_attr  => "return 1;",
+       state     => "exc_pinned",
        arity     => 3,
        mode      => "mode_M",
 },
@@ -1512,6 +1592,7 @@ vfldz => {
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfld1 => {
@@ -1520,6 +1601,7 @@ vfld1 => {
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfldpi => {
@@ -1528,6 +1610,7 @@ vfldpi => {
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfldln2 => {
@@ -1536,6 +1619,7 @@ vfldln2 => {
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfldlg2 => {
@@ -1544,6 +1628,7 @@ vfldlg2 => {
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfldl2t => {
@@ -1552,6 +1637,7 @@ vfldl2t => {
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfldl2e => {
@@ -1560,16 +1646,17 @@ vfldl2e => {
        latency   => 4,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 vfConst => {
        op_flags  => "c",
        irn_flags => "R",
-#  init_attr => "  set_ia32_ls_mode(res, mode);",
        reg_req   => { out => [ "vfp" ] },
        latency   => 3,
        units     => [ "VFP" ],
        mode      => "mode_E",
+       attr_type => "ia32_x87_attr_t",
 },
 
 # other
@@ -1577,10 +1664,14 @@ vfConst => {
 vfCondJmp => {
        state     => "pinned",
        op_flags  => "L|X|Y",
-       reg_req   => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "none", "none", "eax" ] },
+       reg_req   => { in => [ "vfp", "vfp" ], out => [ "none", "none", "eax" ] },
+       ins       => [ "left", "right" ],
        outs      => [ "false", "true", "temp_reg_eax" ],
+       attr      => "long pnc",
+       init_attr => "attr->attr.pn_code = pnc;",
        latency   => 10,
        units     => [ "VFP" ],
+       attr_type => "ia32_x87_attr_t",
 },
 
 #------------------------------------------------------------------------#
@@ -1599,13 +1690,15 @@ fadd => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fadd%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 faddp => {
        op_flags  => "R",
        rd_constructor => "NONE",
        reg_req   => { },
-       emit      => '. faddp %x87_binop',
+       emit      => '. faddp%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fmul => {
@@ -1613,13 +1706,15 @@ fmul => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fmul%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fmulp => {
        op_flags  => "R",
        rd_constructor => "NONE",
        reg_req   => { },
-       emit      => '. fmulp %x87_binop',,
+       emit      => '. fmulp%XM %x87_binop',,
+       attr_type => "ia32_x87_attr_t",
 },
 
 fsub => {
@@ -1627,6 +1722,7 @@ fsub => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fsub%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fsubp => {
@@ -1634,7 +1730,8 @@ fsubp => {
        rd_constructor => "NONE",
        reg_req   => { },
 # see note about gas bugs
-       emit      => '. fsubrp %x87_binop',
+       emit      => '. fsubrp%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fsubr => {
@@ -1643,6 +1740,7 @@ fsubr => {
        irn_flags => "R",
        reg_req   => { },
        emit      => '. fsubr%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fsubrp => {
@@ -1651,7 +1749,8 @@ fsubrp => {
        irn_flags => "R",
        reg_req   => { },
 # see note about gas bugs
-       emit      => '. fsubp %x87_binop',
+       emit      => '. fsubp%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fprem => {
@@ -1659,6 +1758,7 @@ fprem => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fprem1',
+       attr_type => "ia32_x87_attr_t",
 },
 
 # this node is just here, to keep the simulator running
@@ -1668,6 +1768,7 @@ fpremp => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fprem1',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fdiv => {
@@ -1675,6 +1776,7 @@ fdiv => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fdiv%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fdivp => {
@@ -1682,7 +1784,8 @@ fdivp => {
        rd_constructor => "NONE",
        reg_req   => { },
 # see note about gas bugs
-       emit      => '. fdivrp %x87_binop',
+       emit      => '. fdivrp%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fdivr => {
@@ -1690,6 +1793,7 @@ fdivr => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fdivr%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fdivrp => {
@@ -1697,7 +1801,8 @@ fdivrp => {
        rd_constructor => "NONE",
        reg_req   => { },
 # see note about gas bugs
-       emit      => '. fdivp %x87_binop',
+       emit      => '. fdivp%XM %x87_binop',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fabs => {
@@ -1705,6 +1810,7 @@ fabs => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fabs',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fchs => {
@@ -1712,27 +1818,7 @@ fchs => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fchs',
-},
-
-fsin => {
-       op_flags  => "R",
-       rd_constructor => "NONE",
-       reg_req   => { },
-       emit      => '. fsin',
-},
-
-fcos => {
-       op_flags  => "R",
-       rd_constructor => "NONE",
-       reg_req   => { },
-       emit      => '. fcos',
-},
-
-fsqrt => {
-       op_flags  => "R",
-       rd_constructor => "NONE",
-       reg_req   => { },
-       emit      => '. fsqrt $',
+       attr_type => "ia32_x87_attr_t",
 },
 
 # x87 Load and Store
@@ -1743,6 +1829,7 @@ fld => {
        state     => "exc_pinned",
        reg_req   => { },
        emit      => '. fld%XM %AM',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fst => {
@@ -1752,6 +1839,7 @@ fst => {
        reg_req   => { },
        emit      => '. fst%XM %AM',
        mode      => "mode_M",
+       attr_type => "ia32_x87_attr_t",
 },
 
 fstp => {
@@ -1761,6 +1849,7 @@ fstp => {
        reg_req   => { },
        emit      => '. fstp%XM %AM',
        mode      => "mode_M",
+       attr_type => "ia32_x87_attr_t",
 },
 
 # Conversions
@@ -1770,22 +1859,27 @@ fild => {
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fild%XM %AM',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fist => {
        op_flags  => "R",
+       state     => "exc_pinned",
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fist%XM %AM',
        mode      => "mode_M",
+       attr_type => "ia32_x87_attr_t",
 },
 
 fistp => {
        op_flags  => "R",
+       state     => "exc_pinned",
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fistp%XM %AM',
        mode      => "mode_M",
+       attr_type => "ia32_x87_attr_t",
 },
 
 # constants
@@ -1795,6 +1889,7 @@ fldz => {
        irn_flags  => "R",
        reg_req   => { },
        emit      => '. fldz',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fld1 => {
@@ -1802,6 +1897,7 @@ fld1 => {
        irn_flags  => "R",
        reg_req   => { },
        emit      => '. fld1',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fldpi => {
@@ -1809,6 +1905,7 @@ fldpi => {
        irn_flags  => "R",
        reg_req   => { },
        emit      => '. fldpi',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fldln2 => {
@@ -1816,6 +1913,7 @@ fldln2 => {
        irn_flags  => "R",
        reg_req   => { },
        emit      => '. fldln2',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fldlg2 => {
@@ -1823,6 +1921,7 @@ fldlg2 => {
        irn_flags  => "R",
        reg_req   => { },
        emit      => '. fldlg2',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fldl2t => {
@@ -1830,6 +1929,7 @@ fldl2t => {
        irn_flags  => "R",
        reg_req   => { },
        emit      => '. fldll2t',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fldl2e => {
@@ -1837,6 +1937,7 @@ fldl2e => {
        irn_flags  => "R",
        reg_req   => { },
        emit      => '. fldl2e',
+       attr_type => "ia32_x87_attr_t",
 },
 
 # fxch, fpush, fpop
@@ -1848,6 +1949,7 @@ fxch => {
        reg_req   => { },
        cmp_attr  => "return 1;",
        emit      => '. fxch %X0',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fpush => {
@@ -1855,6 +1957,7 @@ fpush => {
        reg_req   => {},
        cmp_attr  => "return 1;",
        emit      => '. fld %X0',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fpushCopy => {
@@ -1862,6 +1965,7 @@ fpushCopy => {
        reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
        cmp_attr  => "return 1;",
        emit      => '. fld %X0',
+       attr_type => "ia32_x87_attr_t",
 },
 
 fpop => {
@@ -1869,6 +1973,7 @@ fpop => {
        reg_req   => { },
        cmp_attr  => "return 1;",
        emit      => '. fstp %X0',
+       attr_type => "ia32_x87_attr_t",
 },
 
 # compare
@@ -1876,31 +1981,37 @@ fpop => {
 fcomJmp => {
        op_flags  => "L|X|Y",
        reg_req   => { },
+       attr_type => "ia32_x87_attr_t",
 },
 
 fcompJmp => {
        op_flags  => "L|X|Y",
        reg_req   => { },
+       attr_type => "ia32_x87_attr_t",
 },
 
 fcomppJmp => {
        op_flags  => "L|X|Y",
        reg_req   => { },
+       attr_type => "ia32_x87_attr_t",
 },
 
 fcomrJmp => {
        op_flags  => "L|X|Y",
        reg_req   => { },
+       attr_type => "ia32_x87_attr_t",
 },
 
 fcomrpJmp => {
        op_flags  => "L|X|Y",
        reg_req   => { },
+       attr_type => "ia32_x87_attr_t",
 },
 
 fcomrppJmp => {
        op_flags  => "L|X|Y",
        reg_req   => { },
+       attr_type => "ia32_x87_attr_t",
 },