X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_spec.pl;h=192ebfee373296baa6fc450fce2f4dbddce3c1b7;hb=4808973ff03cc6c669ee627c9509f2646047d57f;hp=5224895e7fe18b4fb1a772c6b69aff04f2b36dbc;hpb=590df14827a8ff5a5b53c506ac654876107bd8c9;p=libfirm diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 5224895e7..192ebfee3 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -17,7 +17,7 @@ $arch = "ia32"; # # => { # op_flags => "N|L|C|X|I|F|Y|H|c|K", -# irn_flags => "R|N|I|S" +# irn_flags => "R|N" # arity => "0|1|2|3 ... |variable|dynamic|any", # state => "floats|pinned|mem_pinned|exc_pinned", # args => [ @@ -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,13 +56,13 @@ $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: # R rematerializeable # N not spillable -# I ignore for register allocation -# S modifies stack pointer # # state: state of the operation, OPTIONAL (default is "floats") # @@ -72,10 +77,7 @@ $arch = "ia32"; # # outs: if a node defines more than one output, the names of the projections # nodes having outs having automatically the mode mode_T -# One can also annotate some flags for each out, additional to irn_flags. -# They are separated from name with a colon ':', and concatenated by pipe '|' -# Only I and S are available at the moment (same meaning as in irn_flags). -# example: [ "frame:I", "stack:I|S", "M" ] +# example: [ "frame", "stack", "M" ] # # comment: OPTIONAL comment for the node constructor # @@ -144,14 +146,14 @@ $arch = "ia32"; { mode => "mode_E" } ], vfp => [ - { name => "vf0", type => 1 | 16 }, - { name => "vf1", type => 1 | 16 }, - { name => "vf2", type => 1 | 16 }, - { name => "vf3", type => 1 | 16 }, - { name => "vf4", type => 1 | 16 }, - { name => "vf5", type => 1 | 16 }, - { name => "vf6", type => 1 | 16 }, - { name => "vf7", type => 1 | 16 }, + { name => "vf0", type => 1 }, + { name => "vf1", type => 1 }, + { name => "vf2", type => 1 }, + { name => "vf3", type => 1 }, + { name => "vf4", type => 1 }, + { name => "vf5", type => 1 }, + { name => "vf6", type => 1 }, + { name => "vf7", type => 1 }, { name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes { name => "vfp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes { mode => "mode_E" } @@ -197,6 +199,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);", @@ -211,10 +214,8 @@ $arch = "ia32"; XXM => "${arch}_emit_xmm_mode_suffix(node);", XSD => "${arch}_emit_xmm_mode_suffix_s(node);", 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);", + unop3 => "${arch}_emit_unop(node, n_ia32_unary_op);", + unop4 => "${arch}_emit_unop(node, n_ia32_binary_right);", binop => "${arch}_emit_binop(node);", x87_binop => "${arch}_emit_x87_binop(node);", CMP0 => "${arch}_emit_cmp_suffix_node(node, 0);", @@ -242,26 +243,14 @@ sub ia32_custom_init_attr { my $res = ""; if(defined($node->{modified_flags})) { - $res .= "\tset_ia32_flags(res, get_ia32_flags(res) | arch_irn_flags_modify_flags);\n"; + $res .= "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n"; } if(defined($node->{am})) { my $am = $node->{am}; - if($am eq "full,binary") { - $res .= "\tset_ia32_am_support(res, ia32_am_Full, ia32_am_binary);"; - } elsif($am eq "full,unary") { - $res .= "\tset_ia32_am_support(res, ia32_am_Full, ia32_am_unary);"; - } elsif($am eq "source,unary") { - $res .= "\tset_ia32_am_support(res, ia32_am_Source, ia32_am_unary);"; + if($am eq "source,unary") { + $res .= "\tset_ia32_am_support(res, 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);"; + $res .= "\tset_ia32_am_support(res, ia32_am_binary);"; } elsif($am eq "none") { # nothing to do } else { @@ -279,54 +268,60 @@ sub ia32_custom_init_attr { $custom_init_attr_func = \&ia32_custom_init_attr; %init_attr = ( - ia32_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);", - ia32_x87_attr_t => - "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n". - "\tinit_ia32_x87_attributes(res);", ia32_asm_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n". "\tinit_ia32_x87_attributes(res);". "\tinit_ia32_asm_attributes(res);", - ia32_immediate_attr_t => + ia32_attr_t => + "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);", + ia32_call_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n". - "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);", + "\tinit_ia32_call_attributes(res, pop, call_tp);", + ia32_condcode_attr_t => + "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n". + "\tinit_ia32_condcode_attributes(res, pnc);", ia32_copyb_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n". "\tinit_ia32_copyb_attributes(res, size);", - ia32_condcode_attr_t => + ia32_immediate_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n". - "\tinit_ia32_condcode_attributes(res, pnc);", + "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);", + ia32_x87_attr_t => + "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n". + "\tinit_ia32_x87_attributes(res);", ); %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", - ia32_copyb_attr_t => "ia32_compare_copyb_attr", + ia32_attr_t => "ia32_compare_nodes_attr", + ia32_call_attr_t => "ia32_compare_call_attr", ia32_condcode_attr_t => "ia32_compare_condcode_attr", + ia32_copyb_attr_t => "ia32_compare_copyb_attr", + ia32_immediate_attr_t => "ia32_compare_immediate_attr", + ia32_x87_attr_t => "ia32_compare_x87_attr", ); %operands = ( ); -$mode_xmm = "mode_E"; -$mode_gp = "mode_Iu"; -$mode_flags = "mode_Iu"; -$mode_fpcw = "mode_fpcw"; -$status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ]; -$fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM", - "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ]; +$mode_xmm = "mode_E"; +$mode_gp = "mode_Iu"; +$mode_flags = "mode_Iu"; +$mode_fpcw = "mode_fpcw"; +$status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ]; +$status_flags_wo_cf = [ "PF", "AF", "ZF", "SF", "OF" ]; +$fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM", + "FP_PC0", "FP_PC1", "FP_RC0", "FP_RC1", "FP_X" ]; %nodes = ( Immediate => { state => "pinned", op_flags => "c", - irn_flags => "I", - reg_req => { out => [ "gp_NOREG" ] }, + reg_req => { out => [ "gp_NOREG:I" ] }, 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 +338,7 @@ Asm => { modified_flags => 1, }, +# "allocates" a free register ProduceVal => { op_flags => "c", irn_flags => "R", @@ -370,10 +366,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 +404,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, @@ -429,12 +429,13 @@ l_Adc => { Mul => { # we should not rematrialize this node. It produces 2 results and has - # very strict constrains + # very strict constraints state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] }, - ins => [ "base", "index", "mem", "val_high", "val_low" ], + reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ], + out => [ "eax", "flags", "edx", "none" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. mul%M %unop4', - outs => [ "EAX", "EDX", "M" ], + outs => [ "res_low", "flags", "res_high", "M" ], am => "source,binary", latency => 10, units => [ "GP" ], @@ -443,10 +444,10 @@ Mul => { l_Mul => { # we should not rematrialize this node. It produces 2 results and has - # very strict constrains + # very strict constraints op_flags => "C", cmp_attr => "return 1;", - outs => [ "EAX", "EDX", "M" ], + outs => [ "EAX", "flags", "EDX", "M" ], arity => 2 }, @@ -456,9 +457,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 +470,11 @@ IMul => { IMul1OP => { irn_flags => "R", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] }, - ins => [ "base", "index", "mem", "val_high", "val_low" ], + reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ], + out => [ "eax", "edx", "none" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. imul%M %unop4', - outs => [ "EAX", "EDX", "M" ], + outs => [ "res_low", "res_high", "M" ], am => "source,binary", latency => 5, units => [ "GP" ], @@ -480,21 +482,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 +531,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 +570,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 +611,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 +627,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 +639,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 +649,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 +663,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" ], - am => "source,ternary", - emit => ". idiv%M %unop5", + 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,unary", + emit => ". idiv%M %unop3", latency => 25, units => [ "GP" ], modified_flags => $status_flags @@ -677,11 +688,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" ], - am => "source,ternary", - emit => ". div%M %unop5", + 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,unary", + emit => ". div%M %unop3", latency => 25, units => [ "GP" ], modified_flags => $status_flags @@ -689,8 +701,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 +725,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 +745,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 +776,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 +796,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 +826,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 +857,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 +884,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, @@ -884,7 +909,7 @@ NegMem => { Minus64Bit => { irn_flags => "R", - reg_req => { in => [ "gp", "gp" ], out => [ "in_r1", "gp" ] }, + reg_req => { in => [ "gp", "gp" ], out => [ "in_r1", "in_r2" ] }, outs => [ "low_res", "high_res" ], units => [ "GP" ], latency => 3, @@ -894,12 +919,15 @@ 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, latency => 1, - modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ] + modified_flags => $status_flags_wo_cf }, IncMem => { @@ -911,17 +939,20 @@ IncMem => { units => [ "GP" ], mode => "mode_M", latency => 1, - modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ] + modified_flags => $status_flags_wo_cf }, 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, latency => 1, - modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ] + modified_flags => $status_flags_wo_cf }, DecMem => { @@ -933,17 +964,20 @@ DecMem => { units => [ "GP" ], mode => "mode_M", latency => 1, - modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ] + modified_flags => $status_flags_wo_cf }, 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 +989,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 +1015,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 +1144,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,11 +1173,19 @@ 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", - irn_flags => "I", - reg_req => { out => [ "gp_UKNWN" ] }, + op_flags => "c|NB", + reg_req => { out => [ "gp_UKNWN:I" ] }, units => [], emit => "", latency => 0, @@ -1132,9 +1194,8 @@ Unknown_GP => { Unknown_VFP => { state => "pinned", - op_flags => "c", - irn_flags => "I", - reg_req => { out => [ "vfp_UKNWN" ] }, + op_flags => "c|NB", + reg_req => { out => [ "vfp_UKNWN:I" ] }, units => [], emit => "", mode => "mode_E", @@ -1144,20 +1205,18 @@ Unknown_VFP => { Unknown_XMM => { state => "pinned", - op_flags => "c", - irn_flags => "I", - reg_req => { out => [ "xmm_UKNWN" ] }, + op_flags => "c|NB", + reg_req => { out => [ "xmm_UKNWN:I" ] }, units => [], emit => "", latency => 0, - mode => "mode_E" + mode => $mode_xmm }, NoReg_GP => { state => "pinned", - op_flags => "c", - irn_flags => "I", - reg_req => { out => [ "gp_NOREG" ] }, + op_flags => "c|NB|NI", + reg_req => { out => [ "gp_NOREG:I" ] }, units => [], emit => "", latency => 0, @@ -1166,9 +1225,8 @@ NoReg_GP => { NoReg_VFP => { state => "pinned", - op_flags => "c", - irn_flags => "I", - reg_req => { out => [ "vfp_NOREG" ] }, + op_flags => "c|NB|NI", + reg_req => { out => [ "vfp_NOREG:I" ] }, units => [], emit => "", mode => "mode_E", @@ -1178,9 +1236,8 @@ NoReg_VFP => { NoReg_XMM => { state => "pinned", - op_flags => "c", - irn_flags => "I", - reg_req => { out => [ "xmm_NOREG" ] }, + op_flags => "c|NB|NI", + reg_req => { out => [ "xmm_NOREG:I" ] }, units => [], emit => "", latency => 0, @@ -1190,8 +1247,7 @@ NoReg_XMM => { ChangeCW => { state => "pinned", op_flags => "c", - irn_flags => "I", - reg_req => { out => [ "fp_cw" ] }, + reg_req => { out => [ "fpcw:I" ] }, mode => $mode_fpcw, latency => 3, units => [ "GP" ], @@ -1201,7 +1257,7 @@ ChangeCW => { FldCW => { op_flags => "L|F", state => "pinned", - reg_req => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] }, + reg_req => { in => [ "gp", "gp", "none" ], out => [ "fpcw:I" ] }, ins => [ "base", "index", "mem" ], latency => 5, emit => ". fldcw %AM", @@ -1234,7 +1290,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,34 +1305,20 @@ 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" ], }, -l_Load => { - op_flags => "L|F", - cmp_attr => "return 1;", - outs => [ "res", "M" ], - arity => 2, -}, - -l_Store => { - op_flags => "L|F", - cmp_attr => "return 1;", - state => "exc_pinned", - arity => 3, - mode => "mode_M", -}, - 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 +1328,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,69 +1352,94 @@ 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:I|S", "none" ] }, ins => [ "base", "index", "mem", "val", "stack" ], - emit => '. push%M %unop4', - outs => [ "stack:I|S", "M" ], - am => "source,binary", + emit => '. push%M %unop3', + outs => [ "stack", "M" ], + am => "source,unary", latency => 2, units => [ "GP" ], }, Pop => { state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "gp", "none", "none", "esp" ] }, - emit => '. pop%M %DAM0', - outs => [ "res", "M", "unused", "stack:I|S" ], + reg_req => { in => [ "none", "esp" ], out => [ "gp", "none", "none", "esp:I|S" ] }, + ins => [ "mem", "stack" ], + outs => [ "res", "M", "unused", "stack" ], + emit => '. pop%M %D0', + latency => 3, # Pop is more expensive than Push on Athlon + units => [ "GP" ], +}, + +PopEbp => { + state => "exc_pinned", + reg_req => { in => [ "none", "esp" ], out => [ "ebp:I", "none", "none", "esp:I|S" ] }, + ins => [ "mem", "stack" ], + outs => [ "res", "M", "unused", "stack" ], + 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:I|S" ] }, ins => [ "base", "index", "mem", "stack" ], - am => "dest,unary", + outs => [ "unused0", "M", "unused1", "stack" ], + emit => '. pop%M %AM', latency => 3, # Pop is more expensive than Push on Athlon units => [ "GP" ], }, Enter => { - reg_req => { in => [ "esp" ], out => [ "ebp", "esp", "none" ] }, + reg_req => { in => [ "esp" ], out => [ "ebp", "esp:I|S", "none" ] }, emit => '. enter', - outs => [ "frame:I", "stack:I|S", "M" ], + outs => [ "frame", "stack", "M" ], latency => 15, units => [ "GP" ], }, Leave => { - reg_req => { in => [ "esp", "ebp" ], out => [ "ebp", "esp" ] }, + reg_req => { in => [ "ebp" ], out => [ "ebp:I", "esp:I|S" ] }, emit => '. leave', - outs => [ "frame:I", "stack:I|S" ], + outs => [ "frame", "stack" ], latency => 3, units => [ "GP" ], }, AddSP => { - irn_flags => "I", state => "pinned", - reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "none" ] }, ins => [ "base", "index", "mem", "stack", "size" ], am => "source,binary", emit => '. addl %binop', latency => 1, - outs => [ "stack:S", "M" ], + outs => [ "stack", "M" ], units => [ "GP" ], modified_flags => $status_flags }, SubSP => { -#irn_flags => "I", state => "pinned", - reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "esp:I|S", "gp", "none" ] }, ins => [ "base", "index", "mem", "stack", "size" ], am => "source,binary", emit => ". subl %binop\n". ". movl %%esp, %D1", latency => 2, - outs => [ "stack:I|S", "addr", "M" ], + outs => [ "stack", "addr", "M" ], units => [ "GP" ], 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 +1447,32 @@ 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 +}, + +Call => { + state => "exc_pinned", + reg_req => { + in => [ "gp", "gp", "none", "gp", "esp", "fpcw", "eax", "ecx", "edx" ], + out => [ "esp:I|S", "fpcw:I", "none", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ] + }, + ins => [ "base", "index", "mem", "addr", "stack", "fpcw", "eax", "ecx", "edx" ], + outs => [ "stack", "fpcw", "M", "eax", "ecx", "edx", "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" ], + attr_type => "ia32_call_attr_t", + attr => "unsigned pop, ir_type *call_tp", + am => "source,unary", + units => [ "BRANCH" ], + latency => 4, # random number +}, #-----------------------------------------------------------------------------# # _____ _____ ______ __ _ _ _ # @@ -1389,13 +1483,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 +1563,7 @@ xAdd => { emit => '. add%XXM %binop', latency => 4, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xMul => { @@ -1421,7 +1575,7 @@ xMul => { emit => '. mul%XXM %binop', latency => 4, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xMax => { @@ -1433,7 +1587,7 @@ xMax => { emit => '. max%XXM %binop', latency => 2, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xMin => { @@ -1445,7 +1599,7 @@ xMin => { emit => '. min%XXM %binop', latency => 2, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xAnd => { @@ -1457,7 +1611,7 @@ xAnd => { emit => '. andp%XSD %binop', latency => 3, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xOr => { @@ -1469,7 +1623,7 @@ xOr => { emit => '. orp%XSD %binop', latency => 3, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xXor => { @@ -1481,7 +1635,7 @@ xXor => { emit => '. xorp%XSD %binop', latency => 3, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, # not commutative operations @@ -1495,26 +1649,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 +1699,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 +1712,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 +1757,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 +1831,7 @@ Conv_I2FP => { am => "source,unary", latency => 10, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm, }, Conv_FP2I => { @@ -1695,7 +1851,7 @@ Conv_FP2FP => { am => "source,unary", latency => 8, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm, }, #----------------------------------------------------------# @@ -1743,7 +1899,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 +1910,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 +1953,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 +1967,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, @@ -1833,12 +1990,6 @@ vfild => { attr_type => "ia32_x87_attr_t", }, -l_vfild => { - cmp_attr => "return 1;", - outs => [ "res", "M" ], - arity => 2, -}, - vfist => { state => "exc_pinned", reg_req => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] }, @@ -1849,11 +2000,15 @@ vfist => { attr_type => "ia32_x87_attr_t", }, -l_vfist => { - cmp_attr => "return 1;", +# SSE3 fisttp instruction +vfisttp => { state => "exc_pinned", - arity => 3, - mode => "mode_M", + 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", }, @@ -1862,6 +2017,7 @@ l_vfist => { vfldz => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1871,6 +2027,7 @@ vfldz => { vfld1 => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1880,6 +2037,7 @@ vfld1 => { vfldpi => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1889,6 +2047,7 @@ vfldpi => { vfldln2 => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1898,6 +2057,7 @@ vfldln2 => { vfldlg2 => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1907,6 +2067,7 @@ vfldlg2 => { vfldl2t => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1916,6 +2077,7 @@ vfldl2t => { vfldl2e => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -2177,7 +2339,7 @@ fild => { state => "exc_pinned", rd_constructor => "NONE", reg_req => { }, - emit => '. fild%M %AM', + emit => '. fild%XM %AM', attr_type => "ia32_x87_attr_t", latency => 2, }, @@ -2186,7 +2348,7 @@ fist => { state => "exc_pinned", rd_constructor => "NONE", reg_req => { }, - emit => '. fist%M %AM', + emit => '. fist%XM %AM', mode => "mode_M", attr_type => "ia32_x87_attr_t", latency => 2, @@ -2196,7 +2358,18 @@ fistp => { state => "exc_pinned", rd_constructor => "NONE", reg_req => { }, - emit => '. fistp%M %AM', + emit => '. fistp%XM %AM', + mode => "mode_M", + attr_type => "ia32_x87_attr_t", + latency => 2, +}, + +# SSE3 firsttp instruction +fisttp => { + state => "exc_pinned", + rd_constructor => "NONE", + reg_req => { }, + emit => '. fisttp%XM %AM', mode => "mode_M", attr_type => "ia32_x87_attr_t", latency => 2, @@ -2344,7 +2517,7 @@ femms => { FucomFnstsw => { reg_req => { }, emit => ". fucom %X1\n". - ". fnstsw", + ". fnstsw %%ax", attr_type => "ia32_x87_attr_t", latency => 2, }, @@ -2352,7 +2525,7 @@ FucomFnstsw => { FucompFnstsw => { reg_req => { }, emit => ". fucomp %X1\n". - ". fnstsw", + ". fnstsw %%ax", attr_type => "ia32_x87_attr_t", latency => 2, }, @@ -2360,7 +2533,7 @@ FucompFnstsw => { FucomppFnstsw => { reg_req => { }, emit => ". fucompp\n". - ". fnstsw", + ". fnstsw %%ax", attr_type => "ia32_x87_attr_t", latency => 2, }, @@ -2382,7 +2555,7 @@ Fucompi => { FtstFnstsw => { reg_req => { }, emit => ". ftst\n". - ". fnstsw", + ". fnstsw %%ax", attr_type => "ia32_x87_attr_t", latency => 2, }, @@ -2454,4 +2627,4 @@ foreach my $op (keys(%nodes)) { $node->{op_attr_init} = $op_attr_init; } -print "ok"; +print "";