X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_spec.pl;h=64673b0fb54d80e1b7f51071d956cf674123d949;hb=217290f085a982f29062ff1d7613ca48a88bfbf4;hp=5224895e7fe18b4fb1a772c6b69aff04f2b36dbc;hpb=590df14827a8ff5a5b53c506ac654876107bd8c9;p=libfirm diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 5224895e7..64673b0fb 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -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,8 +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);", - DAM0 => "${arch}_emit_am_or_dest_register(node, 0);", binop => "${arch}_emit_binop(node);", x87_binop => "${arch}_emit_x87_binop(node);", CMP0 => "${arch}_emit_cmp_suffix_node(node, 0);", @@ -246,20 +252,10 @@ sub ia32_custom_init_attr { } 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,unary") { + if($am eq "source,unary") { $res .= "\tset_ia32_am_support(res, ia32_am_Source, 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") { @@ -327,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, }, @@ -343,6 +340,7 @@ Asm => { modified_flags => 1, }, +# "allocates" a free register ProduceVal => { op_flags => "c", irn_flags => "R", @@ -370,10 +368,12 @@ ProduceVal => { Add => { irn_flags => "R", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5", "none", "flags" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], + out => [ "in_r4 in_r5", "flags", "none" ] }, ins => [ "base", "index", "mem", "left", "right" ], + outs => [ "res", "flags", "M" ], emit => '. add%M %binop', - am => "full,binary", + am => "source,binary", units => [ "GP" ], latency => 1, mode => $mode_gp, @@ -406,10 +406,12 @@ AddMem8Bit => { Adc => { state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4 in_r5" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], + out => [ "in_r4 in_r5", "flags", "none" ] }, ins => [ "base", "index", "mem", "left", "right", "eflags" ], + outs => [ "res", "flags", "M" ], emit => '. adc%M %binop', - am => "full,binary", + am => "source,binary", units => [ "GP" ], latency => 1, mode => $mode_gp, @@ -431,10 +433,11 @@ Mul => { # we should not rematrialize this node. It produces 2 results and has # very strict constrains state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] }, + 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" ], + outs => [ "res_low", "res_high", "M" ], am => "source,binary", latency => 10, units => [ "GP" ], @@ -456,9 +459,9 @@ IMul => { # TODO: adjust out requirements for the 3 operand form # (no need for should_be_same then) reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], - out => [ "in_r4 in_r5", "none", "flags" ] }, + out => [ "in_r4 in_r5", "flags", "none" ] }, ins => [ "base", "index", "mem", "left", "right" ], - outs => [ "res", "M", "flags" ], + outs => [ "res", "flags", "M" ], am => "source,binary", latency => 5, units => [ "GP" ], @@ -469,10 +472,11 @@ IMul => { IMul1OP => { irn_flags => "R", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] }, + 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" ], + outs => [ "res_low", "res_high", "M" ], am => "source,binary", latency => 5, units => [ "GP" ], @@ -480,21 +484,21 @@ IMul1OP => { }, 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" ], + outs => [ "res_low", "res_high", "M" ], arity => 2 }, And => { irn_flags => "R", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], + out => [ "in_r4 in_r5", "flags", "none" ] }, ins => [ "base", "index", "mem", "left", "right" ], + outs => [ "res", "flags", "M" ], op_modes => "commutative | am | immediate | mode_neutral", - am => "full,binary", + am => "source,binary", emit => '. and%M %binop', units => [ "GP" ], latency => 1, @@ -529,9 +533,11 @@ AndMem8Bit => { Or => { irn_flags => "R", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], + out => [ "in_r4 in_r5", "flags", "none" ] }, ins => [ "base", "index", "mem", "left", "right" ], - am => "full,binary", + outs => [ "res", "flags", "M" ], + am => "source,binary", emit => '. or%M %binop', units => [ "GP" ], latency => 1, @@ -566,9 +572,11 @@ OrMem8Bit => { Xor => { irn_flags => "R", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], + out => [ "in_r4 in_r5", "flags", "none" ] }, ins => [ "base", "index", "mem", "left", "right" ], - am => "full,binary", + outs => [ "res", "flags", "M" ], + am => "source,binary", emit => '. xor%M %binop', units => [ "GP" ], latency => 1, @@ -605,9 +613,11 @@ XorMem8Bit => { Sub => { irn_flags => "R", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4", "none", "flags" ] }, - ins => [ "base", "index", "mem", "left", "right" ], - am => "full,binary", + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], + out => [ "in_r4", "flags", "none" ] }, + ins => [ "base", "index", "mem", "minuend", "subtrahend" ], + outs => [ "res", "flags", "M" ], + am => "source,binary", emit => '. sub%M %binop', units => [ "GP" ], latency => 1, @@ -619,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, @@ -631,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, @@ -641,9 +651,11 @@ SubMem8Bit => { Sbb => { state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4 !in_r5" ] }, - ins => [ "base", "index", "mem", "left", "right", "eflags" ], - am => "full,binary", + reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], + out => [ "in_r4 !in_r5", "flags", "none" ] }, + ins => [ "base", "index", "mem", "minuend", "subtrahend", "eflags" ], + outs => [ "res", "flags", "M" ], + am => "source,binary", emit => '. sbb%M %binop', units => [ "GP" ], latency => 1, @@ -653,22 +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" ], out => [ "eax", "none", "none", "edx" ] }, - ins => [ "base", "index", "mem", "left_low", "left_high", "right" ], - outs => [ "div_res", "M", "unused", "mod_res" ], + reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ], + out => [ "eax", "flags", "none", "edx", "none" ] }, + 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 @@ -677,11 +690,12 @@ IDiv => { Div => { op_flags => "F|L", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "none", "none", "edx" ] }, - ins => [ "base", "index", "mem", "left_low", "left_high", "right" ], - outs => [ "div_res", "M", "unused", "mod_res" ], + reg_req => { in => [ "gp", "gp", "none", "gp", "eax", "edx" ], + out => [ "eax", "flags", "none", "edx", "none" ] }, + 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 @@ -689,8 +703,10 @@ Div => { Shl => { irn_flags => "R", - reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, - ins => [ "left", "right" ], + reg_req => { in => [ "gp", "ecx" ], + out => [ "in_r1 !in_r2", "flags" ] }, + ins => [ "val", "count" ], + outs => [ "res", "flags" ], emit => '. shl %SB1, %S0', units => [ "GP" ], latency => 1, @@ -711,16 +727,17 @@ ShlMem => { }, l_ShlDep => { - cmp_attr => "return 1;", - ins => [ "left", "right", "dep" ], - # value, cnt, dependency - arity => 3 + cmp_attr => "return 1;", + ins => [ "val", "count", "dep" ], + arity => 3 }, ShlD => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r2 !in_r3" ] }, - ins => [ "left_high", "left_low", "right" ], + reg_req => { in => [ "gp", "gp", "ecx" ], + out => [ "in_r1 !in_r2 !in_r3", "flags" ] }, + ins => [ "val_high", "val_low", "count" ], + outs => [ "res", "flags" ], emit => ". shld%M %SB2, %S1, %D0", latency => 6, units => [ "GP" ], @@ -730,14 +747,16 @@ ShlD => { l_ShlD => { cmp_attr => "return 1;", - ins => [ "high", "low", "count" ], + ins => [ "val_high", "val_low", "count" ], arity => 3, }, Shr => { irn_flags => "R", - reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, + reg_req => { in => [ "gp", "ecx" ], + out => [ "in_r1 !in_r2", "flags" ] }, ins => [ "val", "count" ], + outs => [ "res", "flags" ], emit => '. shr %SB1, %S0', units => [ "GP" ], mode => $mode_gp, @@ -759,15 +778,16 @@ ShrMem => { l_ShrDep => { cmp_attr => "return 1;", - ins => [ "left", "right", "dep" ], - # value, cnt, dependency + ins => [ "val", "count", "dep" ], arity => 3 }, ShrD => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r2 !in_r3" ] }, - ins => [ "left_high", "left_low", "right" ], + reg_req => { in => [ "gp", "gp", "ecx" ], + out => [ "in_r1 !in_r2 !in_r3", "flags" ] }, + ins => [ "val_high", "val_low", "count" ], + outs => [ "res", "flags" ], emit => ". shrd%M %SB2, %S1, %D0", latency => 6, units => [ "GP" ], @@ -778,13 +798,15 @@ ShrD => { l_ShrD => { cmp_attr => "return 1;", arity => 3, - ins => [ "high", "low", "count" ], + ins => [ "val_high", "val_low", "count" ], }, Sar => { irn_flags => "R", - reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, + reg_req => { in => [ "gp", "ecx" ], + out => [ "in_r1 !in_r2", "flags" ] }, ins => [ "val", "count" ], + outs => [ "res", "flags" ], emit => '. sar %SB1, %S0', units => [ "GP" ], latency => 1, @@ -806,15 +828,16 @@ SarMem => { l_SarDep => { cmp_attr => "return 1;", - ins => [ "left", "right", "dep" ], - # value, cnt, dependency + ins => [ "val", "count", "dep" ], arity => 3 }, Ror => { irn_flags => "R", - reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, + reg_req => { in => [ "gp", "ecx" ], + out => [ "in_r1 !in_r2", "flags" ] }, ins => [ "val", "count" ], + outs => [ "res", "flags" ], emit => '. ror %SB1, %S0', units => [ "GP" ], latency => 1, @@ -836,8 +859,10 @@ RorMem => { Rol => { irn_flags => "R", - reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, + reg_req => { in => [ "gp", "ecx" ], + out => [ "in_r1 !in_r2", "flags" ] }, ins => [ "val", "count" ], + outs => [ "res", "flags" ], emit => '. rol %SB1, %S0', units => [ "GP" ], latency => 1, @@ -861,9 +886,11 @@ RolMem => { Neg => { irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "in_r1" ] }, + reg_req => { in => [ "gp" ], + out => [ "in_r1", "flags" ] }, emit => '. neg %S0', ins => [ "val" ], + outs => [ "res", "flags" ], units => [ "GP" ], latency => 1, mode => $mode_gp, @@ -894,7 +921,10 @@ Minus64Bit => { Inc => { irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "in_r1" ] }, + reg_req => { in => [ "gp" ], + out => [ "in_r1", "flags" ] }, + ins => [ "val" ], + outs => [ "res", "flags" ], emit => '. inc %S0', units => [ "GP" ], mode => $mode_gp, @@ -916,7 +946,10 @@ IncMem => { Dec => { irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "in_r1" ] }, + reg_req => { in => [ "gp" ], + out => [ "in_r1", "flags" ] }, + ins => [ "val" ], + outs => [ "res", "flags" ], emit => '. dec %S0', units => [ "GP" ], mode => $mode_gp, @@ -938,12 +971,15 @@ DecMem => { Not => { irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "in_r1" ] }, + reg_req => { in => [ "gp" ], + out => [ "in_r1", "flags" ] }, ins => [ "val" ], + outs => [ "res", "flags" ], emit => '. not %S0', units => [ "GP" ], latency => 1, mode => $mode_gp, + # no flags modified }, NotMem => { @@ -955,6 +991,25 @@ NotMem => { units => [ "GP" ], latency => 1, mode => "mode_M", + # no flags modified +}, + +Cmc => { + reg_req => { in => [ "flags" ], out => [ "flags" ] }, + emit => '.cmc', + units => [ "GP" ], + latency => 1, + mode => $mode_flags, + modified_flags => $status_flags +}, + +Stc => { + reg_req => { out => [ "flags" ] }, + emit => '.stc', + units => [ "GP" ], + latency => 1, + mode => $mode_flags, + modified_flags => $status_flags }, # other operations @@ -962,9 +1017,10 @@ NotMem => { 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", @@ -1090,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, @@ -1119,9 +1175,18 @@ Const => { mode => $mode_gp, }, +GetEIP => { + op_flags => "c", + reg_req => { out => [ "gp" ] }, + units => [ "GP" ], + latency => 5, + mode => $mode_gp, + modified_flags => $status_flags, +}, + Unknown_GP => { state => "pinned", - op_flags => "c", + op_flags => "c|NB", irn_flags => "I", reg_req => { out => [ "gp_UKNWN" ] }, units => [], @@ -1132,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 => [], @@ -1144,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 => [], @@ -1166,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 => [], @@ -1178,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 => [], @@ -1234,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, @@ -1249,9 +1314,9 @@ Cltd => { Load => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] }, + reg_req => { in => [ "gp", "gp", "none" ], out => [ "gp", "none", "none" ] }, ins => [ "base", "index", "mem" ], - outs => [ "res", "M" ], + outs => [ "res", "M", "X_exc" ], latency => 0, emit => ". mov%SE%ME%.l %AM, %D0", units => [ "GP" ], @@ -1275,8 +1340,9 @@ l_Store => { Store => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none", "none" ] }, ins => [ "base", "index", "mem", "val" ], + outs => [ "M", "X_exc" ], emit => '. mov%M %SI3, %AM', latency => 2, units => [ "GP" ], @@ -1286,8 +1352,9 @@ Store => { Store8Bit => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none" ] }, + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none", "none" ] }, ins => [ "base", "index", "mem", "val" ], + outs => [ "M", "X_exc" ], emit => '. mov%M %SB3, %AM', latency => 2, units => [ "GP" ], @@ -1309,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, @@ -1320,11 +1387,20 @@ Push => { Pop => { state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "gp", "none", "none", "esp" ] }, - emit => '. pop%M %DAM0', + reg_req => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp" ] }, + ins => [ "mem", "stack" ], outs => [ "res", "M", "unused", "stack:I|S" ], + emit => '. pop%M %D0', + latency => 3, # Pop is more expensive than Push on Athlon + units => [ "GP" ], +}, + +PopMem => { + state => "exc_pinned", + reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp" ] }, ins => [ "base", "index", "mem", "stack" ], - am => "dest,unary", + outs => [ "unused0", "M", "unused1", "stack:I|S" ], + emit => '. pop%M %AM', latency => 3, # Pop is more expensive than Push on Athlon units => [ "GP" ], }, @@ -1353,7 +1429,7 @@ AddSP => { am => "source,binary", emit => '. addl %binop', latency => 1, - outs => [ "stack:S", "M" ], + outs => [ "stack:I|S", "M" ], units => [ "GP" ], modified_flags => $status_flags }, @@ -1372,6 +1448,14 @@ SubSP => { modified_flags => $status_flags }, +RepPrefix => { + op_flags => "K", + state => "pinned", + mode => "mode_M", + emit => ". rep", + latency => 0, +}, + LdTls => { irn_flags => "R", reg_req => { out => [ "gp" ] }, @@ -1379,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 +}, #-----------------------------------------------------------------------------# # _____ _____ ______ __ _ _ _ # @@ -1389,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 @@ -1409,7 +1564,7 @@ xAdd => { emit => '. add%XXM %binop', latency => 4, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xMul => { @@ -1421,7 +1576,7 @@ xMul => { emit => '. mul%XXM %binop', latency => 4, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xMax => { @@ -1433,7 +1588,7 @@ xMax => { emit => '. max%XXM %binop', latency => 2, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xMin => { @@ -1445,7 +1600,7 @@ xMin => { emit => '. min%XXM %binop', latency => 2, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xAnd => { @@ -1457,7 +1612,7 @@ xAnd => { emit => '. andp%XSD %binop', latency => 3, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xOr => { @@ -1469,7 +1624,7 @@ xOr => { emit => '. orp%XSD %binop', latency => 3, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xXor => { @@ -1481,7 +1636,7 @@ xXor => { emit => '. xorp%XSD %binop', latency => 3, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, # not commutative operations @@ -1495,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', @@ -1545,12 +1700,12 @@ Ucomi => { xLoad => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] }, + reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none", "none" ] }, ins => [ "base", "index", "mem" ], + outs => [ "res", "M", "X_exc" ], emit => '. mov%XXM %AM, %D0', attr => "ir_mode *load_mode", init_attr => "attr->ls_mode = load_mode;", - outs => [ "res", "M" ], latency => 0, units => [ "SSE" ], }, @@ -1558,8 +1713,9 @@ xLoad => { xStore => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "xmm" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none", "none" ] }, ins => [ "base", "index", "mem", "val" ], + outs => [ "M", "X_exc" ], emit => '. mov%XXM %S3, %AM', latency => 0, units => [ "SSE" ], @@ -1602,16 +1758,17 @@ CvtSI2SD => { }, -l_X87toSSE => { +l_LLtoFloat => { op_flags => "L|F", cmp_attr => "return 1;", - arity => 3, + ins => [ "val_high", "val_low" ], }, -l_SSEtoX87 => { +l_FloattoLL => { op_flags => "L|F", cmp_attr => "return 1;", - arity => 3, + ins => [ "val" ], + outs => [ "res_high", "res_low" ], }, # CopyB @@ -1675,7 +1832,7 @@ Conv_I2FP => { am => "source,unary", latency => 10, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm, }, Conv_FP2I => { @@ -1695,7 +1852,7 @@ Conv_FP2FP => { am => "source,unary", latency => 8, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm, }, #----------------------------------------------------------# @@ -1743,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" ], @@ -1754,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, @@ -1797,9 +1954,9 @@ vfld => { irn_flags => "R", op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] }, + reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none", "none" ] }, ins => [ "base", "index", "mem" ], - outs => [ "res", "M" ], + outs => [ "res", "M", "X_exc" ], attr => "ir_mode *load_mode", init_attr => "attr->attr.ls_mode = load_mode;", latency => 2, @@ -1811,8 +1968,9 @@ vfst => { irn_flags => "R", op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "vfp" ] }, + reg_req => { in => [ "gp", "gp", "none", "vfp" ], out => [ "none", "none" ] }, ins => [ "base", "index", "mem", "val" ], + outs => [ "M", "X_exc" ], attr => "ir_mode *store_mode", init_attr => "attr->attr.ls_mode = store_mode;", latency => 2, @@ -1849,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", @@ -2202,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 => { @@ -2344,7 +2524,7 @@ femms => { FucomFnstsw => { reg_req => { }, emit => ". fucom %X1\n". - ". fnstsw", + ". fnstsw %%ax", attr_type => "ia32_x87_attr_t", latency => 2, }, @@ -2352,7 +2532,7 @@ FucomFnstsw => { FucompFnstsw => { reg_req => { }, emit => ". fucomp %X1\n". - ". fnstsw", + ". fnstsw %%ax", attr_type => "ia32_x87_attr_t", latency => 2, }, @@ -2360,7 +2540,7 @@ FucompFnstsw => { FucomppFnstsw => { reg_req => { }, emit => ". fucompp\n". - ". fnstsw", + ". fnstsw %%ax", attr_type => "ia32_x87_attr_t", latency => 2, }, @@ -2382,7 +2562,7 @@ Fucompi => { FtstFnstsw => { reg_req => { }, emit => ". ftst\n". - ". fnstsw", + ". fnstsw %%ax", attr_type => "ia32_x87_attr_t", latency => 2, }, @@ -2454,4 +2634,4 @@ foreach my $op (keys(%nodes)) { $node->{op_attr_init} = $op_attr_init; } -print "ok"; +print "";