- Introduce nodemap
[libfirm] / ir / be / ia32 / ia32_spec.pl
index 0582f82..ffcb5e7 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)
@@ -270,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);",
 );
@@ -286,7 +293,6 @@ $arch = "ia32";
 #                                      |_|         #
 #--------------------------------------------------#
 
-$default_cmp_attr  = "return ia32_compare_attr(attr_a, attr_b);";
 $default_attr_type = "ia32_attr_t";
 
 %init_attr = (
@@ -294,6 +300,20 @@ $default_attr_type = "ia32_attr_t";
        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 = (
@@ -313,6 +333,8 @@ Immediate => {
        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,
 },
 
@@ -320,6 +342,7 @@ Asm => {
        mode      => "mode_T",
        arity     => "variable",
        out_arity => "variable",
+       attr_type => "ia32_asm_attr_t",
 },
 
 #-----------------------------------------------------------------#
@@ -393,8 +416,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
@@ -422,8 +446,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
@@ -520,7 +545,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" ],
@@ -533,7 +558,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" ],
@@ -685,7 +710,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
@@ -714,7 +740,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" ]
@@ -723,7 +749,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" ]
@@ -732,7 +758,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 => []
@@ -864,7 +891,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",
@@ -875,7 +902,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",
@@ -886,19 +913,23 @@ 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,
+       latency   => 0,
        emit      => ". mov%SE%ME%.l %AM, %D0",
        outs      => [ "res", "M" ],
        units     => [ "GP" ],
@@ -924,7 +955,7 @@ Store => {
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] },
        emit      => '. mov%M %binop',
-       latency   => 3,
+       latency   => 2,
        units     => [ "GP" ],
        mode      => "mode_M",
 },
@@ -934,7 +965,7 @@ 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",
 },
@@ -951,18 +982,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 => [],
 },
@@ -1195,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
@@ -1217,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,
@@ -1228,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',
@@ -1262,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
@@ -1297,14 +1332,9 @@ Conv_FP2FP => {
 CmpCMov => {
        irn_flags => "R",
        reg_req   => { in => [ "gp", "gp", "gp", "gp" ], out => [ "in_r4" ] },
-       latency   => 2,
-       units     => [ "GP" ],
-       mode      => $mode_gp,
-},
-
-PsiCondCMov => {
-       irn_flags => "R",
-       reg_req   => { in => [ "gp", "gp", "gp" ], out => [ "in_r3" ] },
+       ins       => [ "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,
@@ -1330,14 +1360,9 @@ vfCmpCMov => {
 CmpSet => {
        irn_flags => "R",
        reg_req   => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "eax ebx ecx edx" ] },
-       latency   => 2,
-       units     => [ "GP" ],
-       mode      => $mode_gp,
-},
-
-PsiCondSet => {
-       irn_flags => "R",
-       reg_req   => { in => [ "gp" ], 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,
@@ -1385,7 +1410,8 @@ 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",
@@ -1394,7 +1420,8 @@ vfadd => {
 
 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",
@@ -1409,7 +1436,8 @@ 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",
@@ -1422,7 +1450,8 @@ 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" ],
@@ -1436,7 +1465,8 @@ 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",
@@ -1451,6 +1481,7 @@ l_vfprem => {
 vfabs => {
        irn_flags => "R",
        reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
+       ins       => [ "value" ],
        latency   => 2,
        units     => [ "VFP" ],
        mode      => "mode_E",
@@ -1460,46 +1491,23 @@ vfabs => {
 vfchs => {
        irn_flags => "R",
        reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
+       ins       => [ "value" ],
        latency   => 2,
        units     => [ "VFP" ],
        mode      => "mode_E",
        attr_type => "ia32_x87_attr_t",
 },
 
-vfsin => {
-       irn_flags => "R",
-       reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
-       latency   => 150,
-       units     => [ "VFP" ],
-       mode      => "mode_E",
-       attr_type => "ia32_x87_attr_t",
-},
-
-vfcos => {
-       irn_flags => "R",
-       reg_req   => { in => [ "vfp"], out => [ "vfp" ] },
-       latency   => 150,
-       units     => [ "VFP" ],
-       mode      => "mode_E",
-       attr_type => "ia32_x87_attr_t",
-},
-
-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
 
 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",
@@ -1509,6 +1517,9 @@ 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",
@@ -1518,8 +1529,10 @@ vfst => {
 # 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",
@@ -1532,7 +1545,9 @@ 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",
@@ -1541,6 +1556,7 @@ vfist => {
 
 l_vfist => {
        cmp_attr  => "return 1;",
+       state     => "exc_pinned",
        arity     => 3,
        mode      => "mode_M",
 },
@@ -1780,30 +1796,6 @@ fchs => {
        attr_type => "ia32_x87_attr_t",
 },
 
-fsin => {
-       op_flags  => "R",
-       rd_constructor => "NONE",
-       reg_req   => { },
-       emit      => '. fsin',
-       attr_type => "ia32_x87_attr_t",
-},
-
-fcos => {
-       op_flags  => "R",
-       rd_constructor => "NONE",
-       reg_req   => { },
-       emit      => '. fcos',
-       attr_type => "ia32_x87_attr_t",
-},
-
-fsqrt => {
-       op_flags  => "R",
-       rd_constructor => "NONE",
-       reg_req   => { },
-       emit      => '. fsqrt $',
-       attr_type => "ia32_x87_attr_t",
-},
-
 # x87 Load and Store
 
 fld => {
@@ -1847,6 +1839,7 @@ fild => {
 
 fist => {
        op_flags  => "R",
+       state     => "exc_pinned",
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fist%XM %AM',
@@ -1856,6 +1849,7 @@ fist => {
 
 fistp => {
        op_flags  => "R",
+       state     => "exc_pinned",
        rd_constructor => "NONE",
        reg_req   => { },
        emit      => '. fistp%XM %AM',