Do not use clobbered GP register as input registers (not for output is implicit).
[libfirm] / ir / be / ia32 / ia32_spec.pl
index 364d5c0..64673b0 100644 (file)
@@ -28,10 +28,15 @@ $arch = "ia32";
 #   comment   => "any comment for constructor",
 #   reg_req   => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] },
 #   cmp_attr  => "c source code for comparing node attributes",
+#   outs      => { "out1", "out2" } # optional, creates pn_op_out1, ... consts
+#   ins       => { "in1", "in2" }   # optional, creates n_op_in1, ... consts
+#   mode      => "mode_Iu"          # optional, predefines the mode
 #   emit      => "emit code with templates",
-#   attr      => "attitional attribute arguments for constructor"
-#   init_attr => "emit attribute initialization template"
-#   rd_constructor => "c source code which constructs an ir_node"
+#   attr      => "attitional attribute arguments for constructor",
+#   init_attr => "emit attribute initialization template",
+#   rd_constructor => "c source code which constructs an ir_node",
+#   hash_func => "name of the hash function for this operation",
+#   latency   => "latency of this operation (can be float)"
 #   attr_type => "name of the attribute struct",
 # },
 #
@@ -51,6 +56,8 @@ $arch = "ia32";
 #   H   irop_flag_highlevel
 #   c   irop_flag_constlike
 #   K   irop_flag_keep
+#   NB  irop_flag_dump_noblock
+#   NI  irop_flag_dump_noinput
 #
 # irn_flags: special node flags, OPTIONAL (default is 0)
 # following irn_flags are supported:
@@ -197,6 +204,7 @@ $arch = "ia32";
        SB1 => "${arch}_emit_8bit_source_register_or_immediate(node, 1);",
        SB2 => "${arch}_emit_8bit_source_register_or_immediate(node, 2);",
        SB3 => "${arch}_emit_8bit_source_register_or_immediate(node, 3);",
+       SI1 => "${arch}_emit_source_register_or_immediate(node, 1);",
        SI3 => "${arch}_emit_source_register_or_immediate(node, 3);",
        D0 => "${arch}_emit_dest_register(node, 0);",
        D1 => "${arch}_emit_dest_register(node, 1);",
@@ -213,7 +221,6 @@ $arch = "ia32";
        AM => "${arch}_emit_am(node);",
        unop3 => "${arch}_emit_unop(node, 3);",
        unop4 => "${arch}_emit_unop(node, 4);",
-       unop5 => "${arch}_emit_unop(node, 5);",
        binop => "${arch}_emit_binop(node);",
        x87_binop => "${arch}_emit_x87_binop(node);",
        CMP0  => "${arch}_emit_cmp_suffix_node(node, 0);",
@@ -316,6 +323,7 @@ Immediate => {
        reg_req   => { out => [ "gp_NOREG" ] },
        attr      => "ir_entity *symconst, int symconst_sign, long offset",
        attr_type => "ia32_immediate_attr_t",
+       hash_func => "ia32_hash_Immediate",
        latency   => 0,
        mode      => $mode_gp,
 },
@@ -332,6 +340,7 @@ Asm => {
        modified_flags => 1,
 },
 
+# "allocates" a free register
 ProduceVal => {
        op_flags  => "c",
        irn_flags => "R",
@@ -606,7 +615,7 @@ Sub => {
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ],
                       out => [ "in_r4", "flags", "none" ] },
-       ins       => [ "base", "index", "mem", "left", "right" ],
+       ins       => [ "base", "index", "mem", "minuend", "subtrahend" ],
        outs      => [ "res", "flags", "M" ],
        am        => "source,binary",
        emit      => '. sub%M %binop',
@@ -620,7 +629,7 @@ SubMem => {
        irn_flags => "R",
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] },
-       ins       => [ "base", "index", "mem", "val" ],
+       ins       => [ "base", "index", "mem", "subtrahend" ],
        emit      => '. sub%M %SI3, %AM',
        units     => [ "GP" ],
        latency   => 1,
@@ -632,7 +641,7 @@ SubMem8Bit => {
        irn_flags => "R",
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] },
-       ins       => [ "base", "index", "mem", "val" ],
+       ins       => [ "base", "index", "mem", "subtrahend" ],
        emit      => '. sub%M %SB3, %AM',
        units     => [ "GP" ],
        latency   => 1,
@@ -644,7 +653,7 @@ Sbb => {
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ],
                       out => [ "in_r4 !in_r5", "flags", "none" ] },
-       ins       => [ "base", "index", "mem", "left", "right", "eflags" ],
+       ins       => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ],
        outs      => [ "res", "flags", "M" ],
        am        => "source,binary",
        emit      => '. sbb%M %binop',
@@ -656,23 +665,23 @@ Sbb => {
 
 l_Sub => {
        reg_req   => { in => [ "none", "none" ], out => [ "none" ] },
-       ins       => [ "left", "right" ],
+       ins       => [ "minuend", "subtrahend" ],
 },
 
 l_Sbb => {
        reg_req   => { in => [ "none", "none", "none" ], out => [ "none" ] },
-       ins       => [ "left", "right", "eflags" ],
+       ins       => [ "minuend", "subtrahend", "eflags" ],
 },
 
 IDiv => {
        op_flags  => "F|L",
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ],
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
                       out => [ "eax", "flags", "none", "edx", "none" ] },
-       ins       => [ "base", "index", "mem", "left_low", "left_high", "right" ],
+       ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
        outs      => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
        am        => "source,ternary",
-       emit      => ". idiv%M %unop5",
+       emit      => ". idiv%M %unop3",
        latency   => 25,
        units     => [ "GP" ],
        modified_flags => $status_flags
@@ -681,12 +690,12 @@ IDiv => {
 Div => {
        op_flags  => "F|L",
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ],
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ],
                       out => [ "eax", "flags", "none", "edx", "none" ] },
-       ins       => [ "base", "index", "mem", "left_low", "left_high", "right" ],
+       ins       => [ "base", "index", "mem", "divisor", "dividend_low", "dividend_high" ],
        outs      => [ "div_res", "flags", "M", "mod_res", "X_exc" ],
        am        => "source,ternary",
-       emit      => ". div%M %unop5",
+       emit      => ". div%M %unop3",
        latency   => 25,
        units     => [ "GP" ],
        modified_flags => $status_flags
@@ -914,6 +923,7 @@ Inc => {
        irn_flags => "R",
        reg_req   => { in => [ "gp" ],
                       out => [ "in_r1", "flags" ] },
+       ins       => [ "val" ],
        outs      => [ "res", "flags" ],
        emit      => '. inc %S0',
        units     => [ "GP" ],
@@ -938,6 +948,7 @@ Dec => {
        irn_flags => "R",
        reg_req   => { in => [ "gp" ],
                       out => [ "in_r1", "flags" ] },
+       ins       => [ "val" ],
        outs      => [ "res", "flags" ],
        emit      => '. dec %S0',
        units     => [ "GP" ],
@@ -1006,9 +1017,10 @@ Stc => {
 Cmp => {
        irn_flags => "R",
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] },
+       reg_req   => { in  => [ "gp", "gp", "none", "gp", "gp" ],
+                      out => [ "flags", "none", "none" ] },
        ins       => [ "base", "index", "mem", "left", "right" ],
-       outs      => [ "eflags" ],
+       outs      => [ "eflags", "unused", "M" ],
        am        => "source,binary",
        emit      => '. cmp%M %binop',
        attr      => "int ins_permuted, int cmp_unsigned",
@@ -1134,7 +1146,7 @@ SwitchJmp => {
        reg_req   => { in => [ "gp" ], out => [ "none" ] },
        mode      => "mode_T",
        attr_type => "ia32_condcode_attr_t",
-       attr      => "pn_Cmp pnc",
+       attr      => "long pnc",
        latency   => 3,
        units     => [ "BRANCH" ],
        modified_flags => $status_flags,
@@ -1174,7 +1186,7 @@ GetEIP => {
 
 Unknown_GP => {
        state     => "pinned",
-       op_flags  => "c",
+       op_flags  => "c|NB",
        irn_flags => "I",
        reg_req   => { out => [ "gp_UKNWN" ] },
        units     => [],
@@ -1185,7 +1197,7 @@ Unknown_GP => {
 
 Unknown_VFP => {
        state     => "pinned",
-       op_flags  => "c",
+       op_flags  => "c|NB",
        irn_flags => "I",
        reg_req   => { out => [ "vfp_UKNWN" ] },
        units     => [],
@@ -1197,18 +1209,18 @@ Unknown_VFP => {
 
 Unknown_XMM => {
        state     => "pinned",
-       op_flags  => "c",
+       op_flags  => "c|NB",
        irn_flags => "I",
        reg_req   => { out => [ "xmm_UKNWN" ] },
        units     => [],
        emit      => "",
        latency   => 0,
-       mode      => "mode_E"
+       mode      => $mode_xmm
 },
 
 NoReg_GP => {
        state     => "pinned",
-       op_flags  => "c",
+       op_flags  => "c|NB|NI",
        irn_flags => "I",
        reg_req   => { out => [ "gp_NOREG" ] },
        units     => [],
@@ -1219,7 +1231,7 @@ NoReg_GP => {
 
 NoReg_VFP => {
        state     => "pinned",
-       op_flags  => "c",
+       op_flags  => "c|NB|NI",
        irn_flags => "I",
        reg_req   => { out => [ "vfp_NOREG" ] },
        units     => [],
@@ -1231,7 +1243,7 @@ NoReg_VFP => {
 
 NoReg_XMM => {
        state     => "pinned",
-       op_flags  => "c",
+       op_flags  => "c|NB|NI",
        irn_flags => "I",
        reg_req   => { out => [ "xmm_NOREG" ] },
        units     => [],
@@ -1287,7 +1299,7 @@ FnstCWNOP => {
 Cltd => {
        # we should not rematrialize this node. It has very strict constraints.
        reg_req   => { in => [ "eax", "edx" ], out => [ "edx" ] },
-       ins       => [ "val", "globbered" ],
+       ins       => [ "val", "clobbered" ],
        emit      => '. cltd',
        latency   => 1,
        mode      => $mode_gp,
@@ -1364,9 +1376,9 @@ Lea => {
 
 Push => {
        state     => "exc_pinned",
-       reg_req   => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp", "none" ] },
+       reg_req   => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp", "none" ] },
        ins       => [ "base", "index", "mem", "val", "stack" ],
-       emit      => '. push%M %unop4',
+       emit      => '. push%M %unop3',
        outs      => [ "stack:I|S", "M" ],
        am        => "source,binary",
        latency   => 2,
@@ -1451,6 +1463,17 @@ LdTls => {
        latency   => 1,
 },
 
+Bt => {
+       irn_flags => "R",
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp" ], out => [ "flags" ] },
+       ins       => [ "left", "right" ],
+       emit      => '. bt%M %S1, %S0',
+       units     => [ "GP" ],
+       latency   => 1,
+       mode      => $mode_flags,
+       modified_flags => $status_flags  # only CF is set, but the other flags are undefined
+},
 
 #-----------------------------------------------------------------------------#
 #   _____ _____ ______    __ _             _                     _            #
@@ -1461,13 +1484,73 @@ LdTls => {
 # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ #
 #-----------------------------------------------------------------------------#
 
+# produces a 0/+0.0
 xZero => {
        irn_flags => "R",
        reg_req   => { out => [ "xmm" ] },
        emit      => '. xorp%XSD %D0, %D0',
        latency   => 3,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
+},
+
+xPzero => {
+       irn_flags => "R",
+       reg_req   => { out => [ "xmm" ] },
+       emit      => '. pxor %D0, %D0',
+       latency   => 3,
+       units     => [ "SSE" ],
+       mode      => $mode_xmm
+},
+
+# produces all 1 bits
+xAllOnes => {
+       irn_flags => "R",
+       reg_req   => { out => [ "xmm" ] },
+       emit      => '. pcmpeqb %D0, %D0',
+       latency   => 3,
+       units     => [ "SSE" ],
+       mode      => $mode_xmm
+},
+
+# integer shift left, dword
+xPslld => {
+       irn_flags => "R",
+       reg_req   => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
+       emit      => '. pslld %SI1, %D0',
+       latency   => 3,
+       units     => [ "SSE" ],
+       mode      => $mode_xmm
+},
+
+# integer shift left, qword
+xPsllq => {
+       irn_flags => "R",
+       reg_req   => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
+       emit      => '. psllq %SI1, %D0',
+       latency   => 3,
+       units     => [ "SSE" ],
+       mode      => $mode_xmm
+},
+
+# integer shift right, dword
+xPsrld => {
+       irn_flags => "R",
+       reg_req   => { in => [ "xmm", "xmm" ], out => [ "in_r1 !in_r2" ] },
+       emit      => '. psrld %SI1, %D0',
+       latency   => 1,
+       units     => [ "SSE" ],
+       mode      => $mode_xmm
+},
+
+# mov from integer to SSE register
+xMovd  => {
+       irn_flags => "R",
+       reg_req   => { in => [ "gp" ], out => [ "xmm" ] },
+       emit      => '. movd %S0, %D0',
+       latency   => 1,
+       units     => [ "SSE" ],
+       mode      => $mode_xmm
 },
 
 # commutative operations
@@ -1481,7 +1564,7 @@ xAdd => {
        emit      => '. add%XXM %binop',
        latency   => 4,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
 },
 
 xMul => {
@@ -1493,7 +1576,7 @@ xMul => {
        emit      => '. mul%XXM %binop',
        latency   => 4,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
 },
 
 xMax => {
@@ -1505,7 +1588,7 @@ xMax => {
        emit      => '. max%XXM %binop',
        latency   => 2,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
 },
 
 xMin => {
@@ -1517,7 +1600,7 @@ xMin => {
        emit      => '. min%XXM %binop',
        latency   => 2,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
 },
 
 xAnd => {
@@ -1529,7 +1612,7 @@ xAnd => {
        emit      => '. andp%XSD %binop',
        latency   => 3,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
 },
 
 xOr => {
@@ -1541,7 +1624,7 @@ xOr => {
        emit      => '. orp%XSD %binop',
        latency   => 3,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
 },
 
 xXor => {
@@ -1553,7 +1636,7 @@ xXor => {
        emit      => '. xorp%XSD %binop',
        latency   => 3,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
 },
 
 # not commutative operations
@@ -1567,26 +1650,26 @@ xAndNot => {
        emit      => '. andnp%XSD %binop',
        latency   => 3,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
 },
 
 xSub => {
        irn_flags => "R",
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] },
-       ins       => [ "base", "index", "mem", "left", "right" ],
+       ins       => [ "base", "index", "mem", "minuend", "subtrahend" ],
        am        => "source,binary",
        emit      => '. sub%XXM %binop',
        latency   => 4,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm
 },
 
 xDiv => {
        irn_flags => "R",
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] },
-       ins       => [ "base", "index", "mem", "left", "right" ],
+       ins       => [ "base", "index", "mem", "dividend", "divisor" ],
        am        => "source,binary",
        outs      => [ "res", "M" ],
        emit      => '. div%XXM %binop',
@@ -1749,7 +1832,7 @@ Conv_I2FP => {
        am        => "source,unary",
        latency   => 10,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm,
 },
 
 Conv_FP2I => {
@@ -1769,7 +1852,7 @@ Conv_FP2FP => {
        am        => "source,unary",
        latency   => 8,
        units     => [ "SSE" ],
-       mode      => "mode_E",
+       mode      => $mode_xmm,
 },
 
 #----------------------------------------------------------#
@@ -1817,7 +1900,7 @@ vfsub => {
 #      irn_flags => "R",
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] },
-       ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
+       ins       => [ "base", "index", "mem", "minuend", "subtrahend", "fpcw" ],
        am        => "source,binary",
        latency   => 4,
        units     => [ "VFP" ],
@@ -1828,7 +1911,7 @@ vfsub => {
 vfdiv => {
        state     => "exc_pinned",
        reg_req   => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] },
-       ins       => [ "base", "index", "mem", "left", "right", "fpcw" ],
+       ins       => [ "base", "index", "mem", "dividend", "divisor", "fpcw" ],
        am        => "source,binary",
        outs      => [ "res", "M" ],
        latency   => 20,
@@ -1924,6 +2007,17 @@ vfist => {
        attr_type => "ia32_x87_attr_t",
 },
 
+# SSE3 fisttp instruction
+vfisttp => {
+       state     => "exc_pinned",
+       reg_req   => { in => [ "gp", "gp", "none", "vfp" ], out => [ "in_r4", "none" ]},
+       ins       => [ "base", "index", "mem", "val" ],
+       outs      => [ "res", "M" ],
+       latency   => 4,
+       units     => [ "VFP" ],
+       attr_type => "ia32_x87_attr_t",
+},
+
 l_vfist => {
        cmp_attr  => "return 1;",
        state     => "exc_pinned",
@@ -2277,6 +2371,17 @@ fistp => {
        latency   => 2,
 },
 
+# SSE3 firsttp instruction
+fisttp => {
+       state     => "exc_pinned",
+       rd_constructor => "NONE",
+       reg_req   => { },
+       emit      => '. fisttp%M %AM',
+       mode      => "mode_M",
+       attr_type => "ia32_x87_attr_t",
+       latency   => 2,
+},
+
 # constants
 
 fldz => {