X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_spec.pl;h=2d06b0eb949755fc82db5f517d55097b4d4f7a60;hb=8c9bd910f70b291d3ffc76d87dd514236152053f;hp=b37a10414a44478c133ecfd5504535ea9f274d5a;hpb=f5cd86ba2cbc3ec8ba823811fc77ebad92cd4034;p=libfirm diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index b37a10414..2d06b0eb9 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,11 +28,17 @@ $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", +# modified_flags => [ "CF", ... ] # optional, list of modified flags # }, # # ... # (all nodes you need to describe) @@ -51,13 +57,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 +78,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 +147,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 +200,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 +215,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 +244,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 +269,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, }, @@ -340,9 +336,10 @@ Asm => { init_attr => "attr->asm_text = asm_text;\n". "\tattr->register_map = register_map;\n", latency => 10, - modified_flags => 1, + modified_flags => $status_flags, }, +# "allocates" a free register ProduceVal => { op_flags => "c", irn_flags => "R", @@ -375,7 +372,7 @@ Add => { 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, @@ -413,7 +410,7 @@ Adc => { 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, @@ -433,13 +430,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" ], + out => [ "eax", "flags", "edx", "none" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. mul%M %unop4', - outs => [ "res_low", "res_high", "M" ], + outs => [ "res_low", "flags", "res_high", "M" ], am => "source,binary", latency => 10, units => [ "GP" ], @@ -448,10 +445,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 }, @@ -476,7 +473,7 @@ IMul1OP => { state => "exc_pinned", reg_req => { in => [ "gp", "gp", "none", "eax", "gp" ], out => [ "eax", "edx", "none" ] }, - ins => [ "base", "index", "mem", "val_high", "val_low" ], + ins => [ "base", "index", "mem", "left", "right" ], emit => '. imul%M %unop4', outs => [ "res_low", "res_high", "M" ], am => "source,binary", @@ -500,7 +497,7 @@ And => { 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, @@ -539,7 +536,7 @@ Or => { out => [ "in_r4 in_r5", "flags", "none" ] }, ins => [ "base", "index", "mem", "left", "right" ], outs => [ "res", "flags", "M" ], - am => "full,binary", + am => "source,binary", emit => '. or%M %binop', units => [ "GP" ], latency => 1, @@ -578,7 +575,7 @@ Xor => { out => [ "in_r4 in_r5", "flags", "none" ] }, ins => [ "base", "index", "mem", "left", "right" ], outs => [ "res", "flags", "M" ], - am => "full,binary", + am => "source,binary", emit => '. xor%M %binop', units => [ "GP" ], latency => 1, @@ -617,9 +614,9 @@ 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 => "full,binary", + am => "source,binary", emit => '. sub%M %binop', units => [ "GP" ], latency => 1, @@ -631,7 +628,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, @@ -643,7 +640,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, @@ -655,9 +652,9 @@ 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 => "full,binary", + am => "source,binary", emit => '. sbb%M %binop', units => [ "GP" ], latency => 1, @@ -667,23 +664,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", + am => "source,unary", + emit => ". idiv%M %unop3", latency => 25, units => [ "GP" ], modified_flags => $status_flags @@ -692,12 +689,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", + am => "source,unary", + emit => ". div%M %unop3", latency => 25, units => [ "GP" ], modified_flags => $status_flags @@ -913,7 +910,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, @@ -925,12 +922,13 @@ Inc => { irn_flags => "R", 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 => { @@ -942,19 +940,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", "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 => { @@ -966,7 +965,7 @@ DecMem => { units => [ "GP" ], mode => "mode_M", latency => 1, - modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ] + modified_flags => $status_flags_wo_cf }, Not => { @@ -1017,9 +1016,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", @@ -1145,7 +1145,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, @@ -1185,9 +1185,8 @@ GetEIP => { 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, @@ -1196,9 +1195,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", @@ -1208,20 +1206,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, @@ -1230,9 +1226,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", @@ -1242,9 +1237,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, @@ -1254,8 +1248,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" ], @@ -1265,7 +1258,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", @@ -1298,7 +1291,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, @@ -1321,21 +1314,6 @@ Load => { 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", @@ -1375,65 +1353,82 @@ 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:I|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 }, @@ -1453,6 +1448,33 @@ 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 + modified_flags => $status_flags +}, #-----------------------------------------------------------------------------# # _____ _____ ______ __ _ _ _ # @@ -1463,13 +1485,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 @@ -1483,7 +1565,7 @@ xAdd => { emit => '. add%XXM %binop', latency => 4, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xMul => { @@ -1495,7 +1577,7 @@ xMul => { emit => '. mul%XXM %binop', latency => 4, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xMax => { @@ -1507,7 +1589,7 @@ xMax => { emit => '. max%XXM %binop', latency => 2, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xMin => { @@ -1519,7 +1601,7 @@ xMin => { emit => '. min%XXM %binop', latency => 2, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xAnd => { @@ -1531,7 +1613,7 @@ xAnd => { emit => '. andp%XSD %binop', latency => 3, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xOr => { @@ -1543,7 +1625,7 @@ xOr => { emit => '. orp%XSD %binop', latency => 3, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, xXor => { @@ -1555,7 +1637,7 @@ xXor => { emit => '. xorp%XSD %binop', latency => 3, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm }, # not commutative operations @@ -1569,26 +1651,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', @@ -1720,10 +1802,22 @@ CopyB_i => { # Conversions +Cwtl => { + state => "exc_pinned", + reg_req => { in => [ "eax" ], out => [ "eax" ] }, + ins => [ "val" ], + outs => [ "res" ], + emit => '. cwtl', + units => [ "GP" ], + latency => 1, + mode => $mode_gp, +}, + Conv_I2I => { state => "exc_pinned", reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "gp", "none" ] }, ins => [ "base", "index", "mem", "val" ], + outs => [ "res", "M" ], am => "source,unary", units => [ "GP" ], latency => 1, @@ -1751,7 +1845,7 @@ Conv_I2FP => { am => "source,unary", latency => 10, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm, }, Conv_FP2I => { @@ -1771,7 +1865,7 @@ Conv_FP2FP => { am => "source,unary", latency => 8, units => [ "SSE" ], - mode => "mode_E", + mode => $mode_xmm, }, #----------------------------------------------------------# @@ -1819,7 +1913,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" ], @@ -1830,7 +1924,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, @@ -1910,12 +2004,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" ] }, @@ -1926,11 +2014,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", }, @@ -1939,6 +2031,7 @@ l_vfist => { vfldz => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1948,6 +2041,7 @@ vfldz => { vfld1 => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1957,6 +2051,7 @@ vfld1 => { vfldpi => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1966,6 +2061,7 @@ vfldpi => { vfldln2 => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1975,6 +2071,7 @@ vfldln2 => { vfldlg2 => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1984,6 +2081,7 @@ vfldlg2 => { vfldl2t => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -1993,6 +2091,7 @@ vfldl2t => { vfldl2e => { irn_flags => "R", reg_req => { out => [ "vfp" ] }, + outs => [ "res" ], latency => 4, units => [ "VFP" ], mode => "mode_E", @@ -2254,7 +2353,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, }, @@ -2263,7 +2362,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, @@ -2273,7 +2372,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,