X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_spec.pl;h=dc0c49d8e41c5c6c1f9a6b28b54bef0bbae8a38d;hb=90f2e217df8deecb71f08af6bb28f9decd6795b0;hp=feefb1d1cb0e306a329cac20562a5a96fc040a45;hpb=97c79556e25a27333a20f9f8d1094e7b7b3792ec;p=libfirm diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index feefb1d1c..dc0c49d8e 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -33,6 +33,7 @@ $arch = "ia32"; # init_attr => "emit attribute initialization template" # rd_constructor => "c source code which constructs an ir_node" # latency => "latency of this operation (can be float)" +# attr_type => "name of the attribute struct", # }, # # ... # (all nodes you need to describe) @@ -109,10 +110,10 @@ $arch = "ia32"; # NOTE: Last entry of each class is the largest Firm-Mode a register can hold %reg_classes = ( gp => [ - { name => "eax", type => 1 }, { name => "edx", type => 1 }, - { name => "ebx", type => 2 }, { name => "ecx", type => 1 }, + { name => "eax", type => 1 }, + { name => "ebx", type => 2 }, { name => "esi", type => 2 }, { name => "edi", type => 2 }, { name => "ebp", type => 2 }, @@ -130,7 +131,7 @@ $arch = "ia32"; { name => "mm5", type => 4 }, { name => "mm6", type => 4 }, { name => "mm7", type => 4 }, - { mode => "mode_E" } + { mode => "mode_E", flags => "manual_ra" } ], xmm => [ { name => "xmm0", type => 1 }, @@ -167,72 +168,18 @@ $arch = "ia32"; { name => "st5", realname => "st(5)", type => 4 }, { name => "st6", realname => "st(6)", type => 4 }, { name => "st7", realname => "st(7)", type => 4 }, - { mode => "mode_E" } + { mode => "mode_E", flags => "manual_ra" } ], fp_cw => [ # the floating point control word - { name => "fpcw", type => 4 | 32}, - { mode => "mode_fpcw" } + { name => "fpcw", type => 4|32 }, + { mode => "mode_fpcw", flags => "manual_ra|state" } ], flags => [ - { name => "eflags", type => 4 }, - { mode => "mode_Iu" } - ], - fp_sw => [ - { name => "fpsw", type => 4 }, - { mode => "mode_Hu" } + { name => "eflags", type => 0 }, + { mode => "mode_Iu", flags => "manual_ra" } ], ); # %reg_classes -%flags = ( - CF => { reg => "eflags", bit => 0 }, - PF => { reg => "eflags", bit => 2 }, - AF => { reg => "eflags", bit => 4 }, - ZF => { reg => "eflags", bit => 6 }, - SF => { reg => "eflags", bit => 7 }, - TF => { reg => "eflags", bit => 8 }, - IF => { reg => "eflags", bit => 9 }, - DF => { reg => "eflags", bit => 10 }, - OF => { reg => "eflags", bit => 11 }, - IOPL0 => { reg => "eflags", bit => 12 }, - IOPL1 => { reg => "eflags", bit => 13 }, - NT => { reg => "eflags", bit => 14 }, - RF => { reg => "eflags", bit => 16 }, - VM => { reg => "eflags", bit => 17 }, - AC => { reg => "eflags", bit => 18 }, - VIF => { reg => "eflags", bit => 19 }, - VIP => { reg => "eflags", bit => 20 }, - ID => { reg => "eflags", bit => 21 }, - - FP_IE => { reg => "fpsw", bit => 0 }, - FP_DE => { reg => "fpsw", bit => 1 }, - FP_ZE => { reg => "fpsw", bit => 2 }, - FP_OE => { reg => "fpsw", bit => 3 }, - FP_UE => { reg => "fpsw", bit => 4 }, - FP_PE => { reg => "fpsw", bit => 5 }, - FP_SF => { reg => "fpsw", bit => 6 }, - FP_ES => { reg => "fpsw", bit => 7 }, - FP_C0 => { reg => "fpsw", bit => 8 }, - FP_C1 => { reg => "fpsw", bit => 9 }, - FP_C2 => { reg => "fpsw", bit => 10 }, - FP_TOP0 => { reg => "fpsw", bit => 11 }, - FP_TOP1 => { reg => "fpsw", bit => 12 }, - FP_TOP2 => { reg => "fpsw", bit => 13 }, - FP_C3 => { reg => "fpsw", bit => 14 }, - FP_B => { reg => "fpsw", bit => 15 }, - - FP_IM => { reg => "fpcw", bit => 0 }, - FP_DM => { reg => "fpcw", bit => 1 }, - FP_ZM => { reg => "fpcw", bit => 2 }, - FP_OM => { reg => "fpcw", bit => 3 }, - FP_UM => { reg => "fpcw", bit => 4 }, - FP_PM => { reg => "fpcw", bit => 5 }, - FP_PC0 => { reg => "fpcw", bit => 8 }, - FP_PC1 => { reg => "fpcw", bit => 9 }, - FP_RC0 => { reg => "fpcw", bit => 10 }, - FP_RC1 => { reg => "fpcw", bit => 11 }, - FP_X => { reg => "fpcw", bit => 12 } -); # %flags - %cpu = ( GP => [ 1, "GP_EAX", "GP_EBX", "GP_ECX", "GP_EDX", "GP_ESI", "GP_EDI", "GP_EBP" ], SSE => [ 1, "SSE_XMM0", "SSE_XMM1", "SSE_XMM2", "SSE_XMM3", "SSE_XMM4", "SSE_XMM5", "SSE_XMM6", "SSE_XMM7" ], @@ -246,33 +193,49 @@ $arch = "ia32"; ); # vliw %emit_templates = ( - S0 => "${arch}_emit_source_register(env, node, 0);", - S1 => "${arch}_emit_source_register(env, node, 1);", - S2 => "${arch}_emit_source_register(env, node, 2);", - S3 => "${arch}_emit_source_register(env, node, 3);", - S4 => "${arch}_emit_source_register(env, node, 4);", - S5 => "${arch}_emit_source_register(env, node, 5);", - D0 => "${arch}_emit_dest_register(env, node, 0);", - D1 => "${arch}_emit_dest_register(env, node, 1);", - D2 => "${arch}_emit_dest_register(env, node, 2);", - D3 => "${arch}_emit_dest_register(env, node, 3);", - D4 => "${arch}_emit_dest_register(env, node, 4);", - D5 => "${arch}_emit_dest_register(env, node, 5);", - X0 => "${arch}_emit_x87_name(env, node, 0);", - X1 => "${arch}_emit_x87_name(env, node, 1);", - X2 => "${arch}_emit_x87_name(env, node, 2);", - C => "${arch}_emit_immediate(env, node);", - SE => "${arch}_emit_extend_suffix(env, get_ia32_ls_mode(node));", + S0 => "${arch}_emit_source_register(node, 0);", + S1 => "${arch}_emit_source_register(node, 1);", + S2 => "${arch}_emit_source_register(node, 2);", + S3 => "${arch}_emit_source_register(node, 3);", + S4 => "${arch}_emit_source_register(node, 4);", + S5 => "${arch}_emit_source_register(node, 5);", + 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);", + SI0 => "${arch}_emit_source_register_or_immediate(node, 0);", + SI1 => "${arch}_emit_source_register_or_immediate(node, 1);", + SI2 => "${arch}_emit_source_register_or_immediate(node, 2);", + SI3 => "${arch}_emit_source_register_or_immediate(node, 3);", + D0 => "${arch}_emit_dest_register(node, 0);", + D1 => "${arch}_emit_dest_register(node, 1);", + D2 => "${arch}_emit_dest_register(node, 2);", + D3 => "${arch}_emit_dest_register(node, 3);", + D4 => "${arch}_emit_dest_register(node, 4);", + D5 => "${arch}_emit_dest_register(node, 5);", + DB0 => "${arch}_emit_8bit_dest_register(node, 0);", + X0 => "${arch}_emit_x87_register(node, 0);", + X1 => "${arch}_emit_x87_register(node, 1);", + X2 => "${arch}_emit_x87_register(node, 2);", + SE => "${arch}_emit_extend_suffix(get_ia32_ls_mode(node));", ME => "if(get_mode_size_bits(get_ia32_ls_mode(node)) != 32)\n - ia32_emit_mode_suffix(env, node);", - M => "${arch}_emit_mode_suffix(env, node);", - XM => "${arch}_emit_x87_mode_suffix(env, node);", - XXM => "${arch}_emit_xmm_mode_suffix(env, node);", - XSD => "${arch}_emit_xmm_mode_suffix_s(env, node);", - AM => "${arch}_emit_am(env, node);", - unop => "${arch}_emit_unop(env, node);", - binop => "${arch}_emit_binop(env, node);", - x87_binop => "${arch}_emit_x87_binop(env, node);", + ia32_emit_mode_suffix(node);", + M => "${arch}_emit_mode_suffix(node);", + XM => "${arch}_emit_x87_mode_suffix(node);", + XXM => "${arch}_emit_xmm_mode_suffix(node);", + XSD => "${arch}_emit_xmm_mode_suffix_s(node);", + AM => "${arch}_emit_am(node);", + unop0 => "${arch}_emit_unop(node, 0);", + unop1 => "${arch}_emit_unop(node, 1);", + unop2 => "${arch}_emit_unop(node, 2);", + 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);", + DAM1 => "${arch}_emit_am_or_dest_register(node, 1);", + binop => "${arch}_emit_binop(node, 1);", + binop_nores => "${arch}_emit_binop(node, 0);", + x87_binop => "${arch}_emit_x87_binop(node);", + CMP0 => "${arch}_emit_cmp_suffix_node(node, 0);", ); #--------------------------------------------------# @@ -286,14 +249,69 @@ $arch = "ia32"; # |_| # #--------------------------------------------------# -$default_cmp_attr = "return ia32_compare_attr(attr_a, attr_b);"; $default_attr_type = "ia32_attr_t"; +$default_copy_attr = "ia32_copy_attr"; + +sub ia32_custom_init_attr { + my $node = shift; + my $name = shift; + my $res = ""; + if(defined($node->{modified_flags})) { + $res .= "\tset_ia32_flags(res, get_ia32_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,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") { + # nothing to do + } else { + die("Invalid address mode '$am' specified on op $name"); + } + } + return $res; +} +$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, latency);", + ia32_x87_attr_t => + "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n". + "\tinit_ia32_x87_attributes(res);", + ia32_asm_attr_t => + "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n". + "\tinit_ia32_x87_attributes(res);". + "\tinit_ia32_asm_attributes(res);", + ia32_immediate_attr_t => + "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);\n". + "\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, offset);" +); + +%compare_attr = ( + ia32_attr_t => "ia32_compare_nodes_attr", + ia32_x87_attr_t => "ia32_compare_x87_attr", + ia32_asm_attr_t => "ia32_compare_asm_attr", + ia32_immediate_attr_t => "ia32_compare_immediate_attr", +); %operands = ( ); $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", @@ -306,6 +324,9 @@ Immediate => { op_flags => "c", irn_flags => "I", reg_req => { out => [ "gp_NOREG" ] }, + attr => "ir_entity *symconst, int symconst_sign, long offset", + attr_type => "ia32_immediate_attr_t", + latency => 0, mode => $mode_gp, }, @@ -313,6 +334,19 @@ Asm => { mode => "mode_T", arity => "variable", out_arity => "variable", + attr_type => "ia32_asm_attr_t", + latency => 100, +}, + +ProduceVal => { + op_flags => "c", + irn_flags => "R", + reg_req => { out => [ "gp" ] }, + emit => "", + units => [ ], + latency => 0, + mode => $mode_gp, + cmp_attr => "return 1;", }, #-----------------------------------------------------------------# @@ -328,66 +362,66 @@ Asm => { # commutative operations -# NOTE: -# All nodes supporting Addressmode have 5 INs: -# 1 - base r1 == NoReg in case of no AM or no base -# 2 - index r2 == NoReg in case of no AM or no index -# 3 - op1 r3 == always present -# 4 - op2 r4 == NoReg in case of immediate operation -# 5 - mem NoMem in case of no AM otherwise it takes the mem from the Load - Add => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, - ins => [ "base", "index", "left", "right", "mem" ], + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5", "none", "flags" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. add%M %binop', + am => "full,binary", units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, -Adc => { - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, - emit => '. adc%M %binop', +AddMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => ". add%M %SI3, %AM", units => [ "GP" ], - mode => $mode_gp, + mode => "mode_M", modified_flags => $status_flags }, -Add64Bit => { +AddMem8Bit => { irn_flags => "R", - arity => 4, - reg_req => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] }, - emit => ' -. movl %S0, %D0 -. movl %S1, %D1 -. addl %S2, %D0 -. adcl %S3, %D1 -', - outs => [ "low_res", "high_res" ], + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => ". add%M %SB3, %AM", units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + +Adc => { + reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right", "eflags" ], + emit => '. adc%M %binop', + am => "full,binary", + units => [ "GP" ], + mode => $mode_gp, modified_flags => $status_flags }, l_Add => { op_flags => "C", - irn_flags => "R", - cmp_attr => "return 1;", - arity => 2, + reg_req => { in => [ "none", "none" ], out => [ "none" ] }, + ins => [ "left", "right" ], }, l_Adc => { - op_flags => "C", - cmp_attr => "return 1;", - arity => 2, + reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] }, + ins => [ "left", "right", "eflags" ], }, Mul => { # we should not rematrialize this node. It produces 2 results and has # very strict constrains - reg_req => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] }, - emit => '. mul%M %unop', + 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" ], + am => "source,binary", latency => 10, units => [ "GP" ], modified_flags => $status_flags @@ -404,8 +438,10 @@ l_Mul => { IMul => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. imul%M %binop', + am => "source,binary", latency => 5, units => [ "GP" ], mode => $mode_gp, @@ -414,51 +450,115 @@ IMul => { IMul1OP => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "eax", "gp", "none" ], out => [ "eax", "edx", "none" ] }, - emit => '. imul%M %unop', + 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" ], + am => "source,binary", latency => 5, units => [ "GP" ], modified_flags => $status_flags }, 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" ], arity => 2 }, And => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], + am => "full,binary", emit => '. and%M %binop', units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, +AndMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. and%M %SI3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + +AndMem8Bit => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. and%M %SB3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + Or => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], + am => "full,binary", emit => '. or%M %binop', units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, +OrMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. or%M %SI3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + +OrMem8Bit => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. or%M %SB3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + Xor => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], + am => "full,binary", emit => '. xor%M %binop', units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, -l_Xor => { - op_flags => "C", - cmp_attr => "return 1;", - arity => 2, +XorMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. xor%M %SI3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + +XorMem8Bit => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. xor%M %SB3, %AM', + units => [ "GP" ], + mode => "mode_M", modified_flags => $status_flags }, @@ -466,55 +566,65 @@ l_Xor => { Sub => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4", "none", "flags" ] }, + ins => [ "base", "index", "mem", "left", "right" ], + am => "full,binary", emit => '. sub%M %binop', units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, -Sbb => { - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "in_r3 !in_r4" ] }, - emit => '. sbb%M %binop', +SubMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. sub%M %SI3, %AM', units => [ "GP" ], - mode => $mode_gp, + mode => 'mode_M', modified_flags => $status_flags }, -Sub64Bit => { +SubMem8Bit => { irn_flags => "R", - arity => 4, - reg_req => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] }, - emit => ' -. movl %S0, %D0 -. movl %S1, %D1 -. subl %S2, %D0 -. sbbl %S3, %D1 -', - outs => [ "low_res", "high_res" ], + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. sub%M %SB3, %AM', + units => [ "GP" ], + mode => 'mode_M', + modified_flags => $status_flags +}, + +Sbb => { + reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "flags" ], out => [ "in_r4 !in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right", "eflags" ], + am => "full,binary", + emit => '. sbb%M %binop', units => [ "GP" ], + mode => $mode_gp, modified_flags => $status_flags }, l_Sub => { - irn_flags => "R", - cmp_attr => "return 1;", - arity => 2, + reg_req => { in => [ "none", "none" ], out => [ "none" ] }, + ins => [ "left", "right" ], }, l_Sbb => { - cmp_attr => "return 1;", - arity => 2, + reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] }, + ins => [ "left", "right", "eflags" ], }, IDiv => { op_flags => "F|L", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] }, + ins => [ "base", "index", "mem", "left_low", "left_high", "right" ], + outs => [ "div_res", "mod_res", "M" ], attr => "ia32_op_flavour_t dm_flav", + am => "source,ternary", init_attr => "attr->data.op_flav = dm_flav;", - emit => ". idiv%M %unop", - outs => [ "div_res", "mod_res", "M" ], + emit => ". idiv%M %unop5", latency => 25, units => [ "GP" ], modified_flags => $status_flags @@ -523,11 +633,13 @@ IDiv => { Div => { op_flags => "F|L", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "eax", "edx", "gp", "none" ], out => [ "eax", "edx", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "eax", "edx", "gp" ], out => [ "eax", "edx", "none" ] }, + ins => [ "base", "index", "mem", "left_low", "left_high", "right" ], + outs => [ "div_res", "mod_res", "M" ], attr => "ia32_op_flavour_t dm_flav", + am => "source,ternary", init_attr => "attr->data.op_flav = dm_flav;", - emit => ". div%M %unop", - outs => [ "div_res", "mod_res", "M" ], + emit => ". div%M %unop5", latency => 25, units => [ "GP" ], modified_flags => $status_flags @@ -535,21 +647,34 @@ Div => { Shl => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] }, - ins => [ "base", "index", "left", "right", "mem" ], - emit => '. shl%M %binop', + reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, + ins => [ "left", "right" ], + am => "dest,binary", + emit => '. shl %SB1, %S0', units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, -l_Shl => { +ShlMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "count" ], + emit => '. shl%M %SB3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + +l_ShlDep => { cmp_attr => "return 1;", - arity => 2 + # value, cnt, dependency + arity => 3 }, ShlD => { - irn_flags => "R", + # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shl + # # Out requirements is: different from all in # This is because, out must be different from LowPart and ShiftCount. # We could say "!ecx !in_r4" but it can occur, that all values live through @@ -558,23 +683,13 @@ ShlD => { # occupied. What we should write is "!in_r4 !in_r5", but this is not supported # (and probably never will). So we create artificial interferences of the result # with all inputs, so the spiller can always assure a free register. - reg_req => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] }, - emit => -' -if (get_ia32_immop_type(node) == ia32_ImmNone) { - if (get_ia32_op_type(node) == ia32_AddrModeD) { - . shld%M %%cl, %S3, %AM - } else { - . shld%M %%cl, %S3, %S2 - } -} else { - if (get_ia32_op_type(node) == ia32_AddrModeD) { - . shld%M %C, %S3, %AM - } else { - . shld%M %C, %S3, %S2 - } -} -', + # reg_req => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] }, + + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r3" ] }, + ins => [ "left_high", "left_low", "right" ], + am => "dest,ternary", + emit => '. shld%M %SB2, %S1, %S0', latency => 6, units => [ "GP" ], mode => $mode_gp, @@ -588,20 +703,34 @@ l_ShlD => { Shr => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] }, - emit => '. shr%M %binop', + reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, + ins => [ "val", "count" ], + am => "dest,binary", + emit => '. shr %SB1, %S0', units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, -l_Shr => { +ShrMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "count" ], + emit => '. shr%M %SB3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + +l_ShrDep => { cmp_attr => "return 1;", - arity => 2 + # value, cnt, dependency + arity => 3 }, ShrD => { - irn_flags => "R", + # FIXME: WHY? the right requirement is in_r3 !in_r5, especially this is the same as in Shr + # # Out requirements is: different from all in # This is because, out must be different from LowPart and ShiftCount. # We could say "!ecx !in_r4" but it can occur, that all values live through @@ -610,22 +739,13 @@ ShrD => { # occupied. What we should write is "!in_r4 !in_r5", but this is not supported # (and probably never will). So we create artificial interferences of the result # with all inputs, so the spiller can always assure a free register. - reg_req => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] }, - emit => ' -if (get_ia32_immop_type(node) == ia32_ImmNone) { - if (get_ia32_op_type(node) == ia32_AddrModeD) { - . shrd%M %%cl, %S3, %AM - } else { - . shrd%M %%cl, %S3, %S2 - } -} else { - if (get_ia32_op_type(node) == ia32_AddrModeD) { - . shrd%M %C, %S3, %AM - } else { - . shrd%M %C, %S3, %S2 - } -} -', + # reg_req => { in => [ "gp", "gp", "gp", "gp", "ecx", "none" ], out => [ "!in" ] }, + + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "ecx" ], out => [ "in_r1 !in_r3" ] }, + ins => [ "left_high", "left_low", "right" ], + am => "dest,ternary", + emit => '. shrd%M %SB2, %S1, %S0', latency => 6, units => [ "GP" ], mode => $mode_gp, @@ -639,56 +759,105 @@ l_ShrD => { Sar => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] }, - emit => '. sar%M %binop', + reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, + ins => [ "val", "count" ], + am => "dest,binary", + emit => '. sar %SB1, %S0', units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, +SarMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "count" ], + emit => '. sar%M %SB3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + l_Sar => { cmp_attr => "return 1;", + # value, cnt arity => 2 }, +l_SarDep => { + cmp_attr => "return 1;", + # value, cnt, dependency + arity => 3 +}, + Ror => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] }, - emit => '. ror%M %binop', + reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, + ins => [ "val", "count" ], + am => "dest,binary", + emit => '. ror %SB1, %S0', units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, +RorMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "count" ], + emit => '. ror%M %SB3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + Rol => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "ecx", "none" ], out => [ "in_r3 !in_r4" ] }, - emit => '. rol%M %binop', + reg_req => { in => [ "gp", "ecx" ], out => [ "in_r1 !in_r2" ] }, + ins => [ "val", "count" ], + am => "dest,binary", + emit => '. rol %SB1, %S0', units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, +RolMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "ecx" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "count" ], + emit => '. rol%M %SB3, %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + # unary operations Neg => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, - emit => '. neg%M %unop', + reg_req => { in => [ "gp" ], out => [ "in_r1" ] }, + emit => '. neg %S0', + ins => [ "val" ], + am => "dest,unary", units => [ "GP" ], mode => $mode_gp, modified_flags => $status_flags }, +NegMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + ins => [ "base", "index", "mem" ], + emit => '. neg%M %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => $status_flags +}, + Minus64Bit => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in", "!in" ] }, - emit => ' -. movl %S0, %D0 -. movl %S0, %D1 -. subl %S1, %D0 -. sbbl %S2, %D1 -', + reg_req => { in => [ "gp", "gp" ], out => [ "in_r1", "gp" ] }, outs => [ "low_res", "high_res" ], units => [ "GP" ], modified_flags => $status_flags @@ -702,63 +871,165 @@ l_Neg => { Inc => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, - emit => '. inc%M %unop', + reg_req => { in => [ "gp" ], out => [ "in_r1" ] }, + am => "dest,unary", + emit => '. inc %S0', units => [ "GP" ], mode => $mode_gp, modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ] }, +IncMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + ins => [ "base", "index", "mem" ], + emit => '. inc%M %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ] +}, + Dec => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, - emit => '. dec%M %unop', + reg_req => { in => [ "gp" ], out => [ "in_r1" ] }, + am => "dest,unary", + emit => '. dec %S0', units => [ "GP" ], mode => $mode_gp, modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ] }, +DecMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + ins => [ "base", "index", "mem" ], + emit => '. dec%M %AM', + units => [ "GP" ], + mode => "mode_M", + modified_flags => [ "OF", "SF", "ZF", "AF", "PF" ] +}, + Not => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3" ] }, - emit => '. not%M %unop', + reg_req => { in => [ "gp" ], out => [ "in_r1" ] }, + ins => [ "val" ], + am => "dest,unary", + emit => '. not %S0', units => [ "GP" ], mode => $mode_gp, - modified_flags => [] +}, + +NotMem => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + ins => [ "base", "index", "mem" ], + emit => '. not%M %AM', + units => [ "GP" ], + mode => "mode_M", }, # other operations -CondJmp => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "none", "none"] }, - outs => [ "false", "true" ], - latency => 3, - units => [ "BRANCH" ], +Cmp => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] }, + ins => [ "base", "index", "mem", "left", "right" ], + outs => [ "eflags" ], + am => "source,binary", + emit => '. cmp%M %binop_nores', + attr => "int flipped, int cmp_unsigned", + init_attr => "attr->data.cmp_flipped = flipped;\n". + "\tattr->data.cmp_unsigned = cmp_unsigned;\n", + latency => 1, + units => [ "GP" ], + mode => $mode_flags, + modified_flags => $status_flags }, -TestJmp => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp" ], out => [ "none", "none" ] }, - outs => [ "false", "true" ], - latency => 3, - units => [ "BRANCH" ], +Cmp8Bit => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] }, + ins => [ "base", "index", "mem", "left", "right" ], + outs => [ "eflags" ], + am => "source,binary", + emit => '. cmpb %binop_nores', + attr => "int flipped, int cmp_unsigned", + init_attr => "attr->data.cmp_flipped = flipped;\n". + "\tattr->data.cmp_unsigned = cmp_unsigned;\n", + latency => 1, + units => [ "GP" ], + mode => $mode_flags, + modified_flags => $status_flags }, -CJmpAM => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "none", "none" ] }, - outs => [ "false", "true" ], - units => [ "BRANCH" ], +Test => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] }, + ins => [ "base", "index", "mem", "left", "right" ], + outs => [ "eflags" ], + am => "source,binary", + emit => '. test%M %binop_nores', + attr => "int flipped, int cmp_unsigned", + init_attr => "attr->data.cmp_flipped = flipped;\n". + "\tattr->data.cmp_unsigned = cmp_unsigned;\n", + latency => 1, + units => [ "GP" ], + mode => $mode_flags, + modified_flags => $status_flags +}, + +Test8Bit => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ] , out => [ "flags" ] }, + ins => [ "base", "index", "mem", "left", "right" ], + outs => [ "eflags" ], + am => "source,binary", + emit => '. testb %binop_nores', + attr => "int flipped, int cmp_unsigned", + init_attr => "attr->data.cmp_flipped = flipped;\n". + "\tattr->data.cmp_unsigned = cmp_unsigned;\n", + latency => 1, + units => [ "GP" ], + mode => $mode_flags, + modified_flags => $status_flags +}, + +Set => { + #irn_flags => "R", + reg_req => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] }, + ins => [ "eflags" ], + am => "dest,unary", + attr => "pn_Cmp pnc", + init_attr => "attr->pn_code = pnc;\nset_ia32_ls_mode(res, mode_Bu);\n", + emit => '. set%CMP0 %DB0', + latency => 1, + units => [ "GP" ], + mode => $mode_gp, +}, + +CMov => { + #irn_flags => "R", + # (note: leave the false,true order intact to make it compatible with other + # ia32_binary ops) + reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "eflags" ], out => [ "in_r4" ] }, + ins => [ "base", "index", "mem", "val_false", "val_true", "eflags" ], + am => "source,binary", + attr => "pn_Cmp pn_code", + init_attr => "attr->pn_code = pn_code;", + latency => 1, + units => [ "GP" ], + mode => $mode_gp, }, -CJmp => { +Jcc => { state => "pinned", op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp" ] }, + reg_req => { in => [ "eflags" ], out => [ "none", "none" ] }, + ins => [ "eflags" ], + outs => [ "false", "true" ], + attr => "pn_Cmp pnc", + init_attr => "attr->pn_code = pnc;", + latency => 2, units => [ "BRANCH" ], }, @@ -768,6 +1039,17 @@ SwitchJmp => { reg_req => { in => [ "gp" ], out => [ "none" ] }, latency => 3, units => [ "BRANCH" ], + mode => "mode_T", + modified_flags => $status_flags +}, + +IJmp => { + state => "pinned", + op_flags => "X", + reg_req => { in => [ "gp" ] }, + emit => '. jmp *%S0', + units => [ "BRANCH" ], + mode => "mode_X", }, Const => { @@ -775,7 +1057,11 @@ Const => { irn_flags => "R", reg_req => { out => [ "gp" ] }, units => [ "GP" ], + attr => "ir_entity *symconst, int symconst_sign, long offset", + attr_type => "ia32_immediate_attr_t", mode => $mode_gp, +# depends on the const and is set in ia32_transform +# modified_flags => $status_flags }, Unknown_GP => { @@ -795,7 +1081,8 @@ Unknown_VFP => { reg_req => { out => [ "vfp_UKNWN" ] }, units => [], emit => "", - mode => "mode_E" + mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, Unknown_XMM => { @@ -825,7 +1112,8 @@ NoReg_VFP => { reg_req => { out => [ "vfp_NOREG" ] }, units => [], emit => "", - mode => "mode_E" + mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, NoReg_XMM => { @@ -851,8 +1139,9 @@ ChangeCW => { FldCW => { op_flags => "L|F", - state => "exc_pinned", + state => "pinned", reg_req => { in => [ "gp", "gp", "none" ], out => [ "fp_cw" ] }, + ins => [ "base", "index", "mem" ], latency => 5, emit => ". fldcw %AM", mode => $mode_fpcw, @@ -862,8 +1151,9 @@ FldCW => { FnstCW => { op_flags => "L|F", - state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "fp_cw", "none" ], out => [ "none" ] }, + state => "pinned", + reg_req => { in => [ "gp", "gp", "none", "fp_cw" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "fpcw" ], latency => 5, emit => ". fnstcw %AM", mode => "mode_M", @@ -871,23 +1161,27 @@ FnstCW => { }, Cltd => { - # we should not rematrialize this node. It produces 2 results and has - # very strict constrains - reg_req => { in => [ "gp" ], out => [ "eax in_r1", "edx" ] }, + # we should not rematrialize this node. It has very strict constraints. + reg_req => { in => [ "eax", "edx" ], out => [ "edx" ] }, + ins => [ "val", "globbered" ], emit => '. cltd', - outs => [ "EAX", "EDX" ], + mode => $mode_gp, units => [ "GP" ], }, # Load / Store +# +# Note that we add additional latency values depending on address mode, so a +# lateny of 0 for load is correct Load => { op_flags => "L|F", state => "exc_pinned", reg_req => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] }, - latency => 3, - emit => ". mov%SE%ME%.l %AM, %D0", + ins => [ "base", "index", "mem" ], outs => [ "res", "M" ], + latency => 0, + emit => ". mov%SE%ME%.l %AM, %D0", units => [ "GP" ], }, @@ -909,9 +1203,10 @@ l_Store => { Store => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] }, - emit => '. mov%M %binop', - latency => 3, + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. mov%M %SI3, %AM', + latency => 2, units => [ "GP" ], mode => "mode_M", }, @@ -919,39 +1214,45 @@ Store => { Store8Bit => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => ["none" ] }, - emit => '. mov%M %binop', - latency => 3, + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => ["none" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. mov%M %SB3, %AM', + latency => 2, units => [ "GP" ], mode => "mode_M", }, Lea => { irn_flags => "R", - reg_req => { in => [ "gp", "gp" ], out => [ "in_r1" ] }, + reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, + ins => [ "base", "index" ], emit => '. leal %AM, %D0', latency => 2, units => [ "GP" ], mode => $mode_gp, - modified_flags => [], +# well this isn't true for Lea, but we often transform Lea back to Add, Inc +# or Dec, so we set the flag + modified_flags => 1, }, Push => { - reg_req => { in => [ "gp", "gp", "gp", "esp", "none" ], out => [ "esp", "none" ] }, - emit => '. push%M %unop', + reg_req => { in => [ "gp", "gp", "none", "gp", "esp" ], out => [ "esp", "none" ] }, + ins => [ "base", "index", "mem", "val", "stack" ], + emit => '. push%M %unop3', outs => [ "stack:I|S", "M" ], - latency => 3, + am => "source,binary", + latency => 2, units => [ "GP" ], - modified_flags => [], }, Pop => { - reg_req => { in => [ "gp", "gp", "esp", "none" ], out => [ "esp", "gp", "none" ] }, - emit => '. pop%M %unop', + reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "esp", "gp", "none" ] }, + emit => '. pop%M %DAM1', outs => [ "stack:I|S", "res", "M" ], - latency => 4, + ins => [ "base", "index", "mem", "stack" ], + am => "dest,unary", + latency => 3, # Pop is more expensive than Push on Athlon units => [ "GP" ], - modified_flags => [], }, Enter => { @@ -972,7 +1273,10 @@ Leave => { AddSP => { irn_flags => "I", - reg_req => { in => [ "gp", "gp", "esp", "gp", "none" ], out => [ "in_r3", "none" ] }, + state => "pinned", + reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "none" ] }, + ins => [ "base", "index", "mem", "stack", "size" ], + am => "source,binary", emit => '. addl %binop', outs => [ "stack:S", "M" ], units => [ "GP" ], @@ -980,10 +1284,14 @@ AddSP => { }, SubSP => { - irn_flags => "I", - reg_req => { in => [ "gp", "gp", "esp", "gp", "none" ], out => [ "in_r3", "none" ] }, - emit => '. subl %binop', - outs => [ "stack:S", "M" ], +#irn_flags => "I", + state => "pinned", + reg_req => { in => [ "gp", "gp", "none", "esp", "gp" ], out => [ "in_r4", "gp", "none" ] }, + ins => [ "base", "index", "mem", "stack", "size" ], + am => "source,binary", + emit => ". subl %binop\n". + ". movl %%esp, %D1", + outs => [ "stack:I|S", "addr", "M" ], units => [ "GP" ], modified_flags => $status_flags }, @@ -996,11 +1304,9 @@ LdTls => { # the int instruction int => { - reg_req => { in => [ "none" ], out => [ "none" ] }, + reg_req => { in => [ "gp" ], out => [ "none" ] }, mode => "mode_M", - attr => "tarval *tv", - init_attr => "\tset_ia32_Immop_tarval(res, tv);", - emit => '. int %C', + emit => '. int %SI0', units => [ "GP" ], cmp_attr => "return 1;", }, @@ -1015,11 +1321,21 @@ int => { # |_____/_____/|______| |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ # #-----------------------------------------------------------------------------# +xZero => { + irn_flags => "R", + reg_req => { out => [ "xmm" ] }, + emit => '. xorp%XSD %D1, %D1', + latency => 3, + units => [ "SSE" ], + mode => "mode_E", +}, + # commutative operations xAdd => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. add%XXM %binop', latency => 4, units => [ "SSE" ], @@ -1028,7 +1344,8 @@ xAdd => { xMul => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. mul%XXM %binop', latency => 4, units => [ "SSE" ], @@ -1037,7 +1354,8 @@ xMul => { xMax => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. max%XXM %binop', latency => 2, units => [ "SSE" ], @@ -1046,7 +1364,8 @@ xMax => { xMin => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. min%XXM %binop', latency => 2, units => [ "SSE" ], @@ -1055,7 +1374,8 @@ xMin => { xAnd => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. andp%XSD %binop', latency => 3, units => [ "SSE" ], @@ -1064,7 +1384,8 @@ xAnd => { xOr => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. orp%XSD %binop', units => [ "SSE" ], mode => "mode_E", @@ -1072,7 +1393,8 @@ xOr => { xXor => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. xorp%XSD %binop', latency => 3, units => [ "SSE" ], @@ -1083,7 +1405,8 @@ xXor => { xAndNot => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3 !in_r4" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. andnp%XSD %binop', latency => 3, units => [ "SSE" ], @@ -1092,7 +1415,8 @@ xAndNot => { xSub => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] }, + ins => [ "base", "index", "mem", "left", "right" ], emit => '. sub%XXM %binop', latency => 4, units => [ "SSE" ], @@ -1101,7 +1425,8 @@ xSub => { xDiv => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3 !in_r4", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5", "none" ] }, + ins => [ "base", "index", "mem", "left", "right" ], outs => [ "res", "M" ], emit => '. div%XXM %binop', latency => 16, @@ -1110,31 +1435,19 @@ xDiv => { # other operations -xCmp => { +Ucomi => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "in_r3 !in_r4" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eflags" ] }, + ins => [ "base", "index", "mem", "left", "right" ], + outs => [ "flags" ], + am => "source,binary", + attr => "int flipped", + init_attr => "attr->data.cmp_flipped = flipped;", + emit => ' .ucomi%XXM %binop_nores', latency => 3, units => [ "SSE" ], - mode => "mode_E", -}, - -xCondJmp => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "none", "none" ] }, - outs => [ "false", "true" ], - latency => 5, - units => [ "SSE" ], -}, - -xConst => { - op_flags => "c", - irn_flags => "R", - reg_req => { out => [ "xmm" ] }, - emit => '. mov%XXM %C, %D0', - latency => 2, - units => [ "SSE" ], - mode => "mode_E", + mode => $mode_flags, + modified_flags => 1, }, # Load / Store @@ -1143,18 +1456,22 @@ xLoad => { op_flags => "L|F", state => "exc_pinned", reg_req => { in => [ "gp", "gp", "none" ], out => [ "xmm", "none" ] }, + ins => [ "base", "index", "mem" ], emit => '. mov%XXM %AM, %D0', + attr => "ir_mode *load_mode", + init_attr => "attr->ls_mode = load_mode;", outs => [ "res", "M" ], - latency => 2, + latency => 0, units => [ "SSE" ], }, xStore => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "xmm", "none" ] }, - emit => '. mov%XXM %binop', - latency => 2, + reg_req => { in => [ "gp", "gp", "none", "xmm" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. mov%XXM %S3, %AM', + latency => 0, units => [ "SSE" ], mode => "mode_M", }, @@ -1162,17 +1479,18 @@ xStore => { xStoreSimple => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "xmm", "none" ] }, - ins => [ "base", "index", "val", "mem" ], - emit => '. mov%XXM %S2, %AM', - latency => 2, + reg_req => { in => [ "gp", "gp", "none", "xmm" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. mov%XXM %S3, %AM', + latency => 0, units => [ "SSE" ], mode => "mode_M", }, CvtSI2SS => { op_flags => "L|F", - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] }, + ins => [ "base", "index", "mem", "val" ], emit => '. cvtsi2ss %D0, %AM', latency => 2, units => [ "SSE" ], @@ -1181,8 +1499,9 @@ CvtSI2SS => { CvtSI2SD => { op_flags => "L|F", - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm" ] }, - emit => '. cvtsi2sd %unop', + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm" ] }, + ins => [ "base", "index", "mem", "val" ], + emit => '. cvtsi2sd %unop3', latency => 2, units => [ "SSE" ], mode => $mode_xmm @@ -1201,29 +1520,6 @@ l_SSEtoX87 => { arity => 3, }, -GetST0 => { - op_flags => "L|F", - irn_flags => "I", - state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none" ] }, - emit => '. fstp%XM %AM', - latency => 4, - units => [ "SSE" ], - mode => "mode_M", -}, - -SetST0 => { - op_flags => "L|F", - irn_flags => "I", - state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none" ], out => [ "vf0", "none" ] }, - ins => [ "base", "index", "mem" ], - emit => '. fld%XM %AM', - outs => [ "res", "M" ], - latency => 2, - units => [ "SSE" ], -}, - # CopyB CopyB => { @@ -1232,7 +1528,8 @@ CopyB => { reg_req => { in => [ "edi", "esi", "ecx", "none" ], out => [ "edi", "esi", "ecx", "none" ] }, outs => [ "DST", "SRC", "CNT", "M" ], units => [ "GP" ], - modified_flags => [ "DF" ] +# we don't care about this flag, so no need to mark this node +# modified_flags => [ "DF" ] }, CopyB_i => { @@ -1241,118 +1538,56 @@ CopyB_i => { reg_req => { in => [ "edi", "esi", "none" ], out => [ "edi", "esi", "none" ] }, outs => [ "DST", "SRC", "M" ], units => [ "GP" ], - modified_flags => [ "DF" ] +# we don't care about this flag, so no need to mark this node +# modified_flags => [ "DF" ] }, # Conversions Conv_I2I => { - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "in_r3", "none" ] }, - units => [ "GP" ], - mode => $mode_gp, - modified_flags => $status_flags + state => "exc_pinned", + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "gp", "none" ] }, + ins => [ "base", "index", "mem", "val" ], + units => [ "GP" ], + attr => "ir_mode *smaller_mode", + init_attr => "attr->ls_mode = smaller_mode;", + mode => $mode_gp, }, Conv_I2I8Bit => { - reg_req => { in => [ "gp", "gp", "eax ebx ecx edx", "none" ], out => [ "in_r3", "none" ] }, - units => [ "GP" ], - mode => $mode_gp, - modified_flags => $status_flags + state => "exc_pinned", + reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "gp", "none" ] }, + ins => [ "base", "index", "mem", "val" ], + units => [ "GP" ], + attr => "ir_mode *smaller_mode", + init_attr => "attr->ls_mode = smaller_mode;", + mode => $mode_gp, }, Conv_I2FP => { - reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "xmm", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "xmm", "none" ] }, + ins => [ "base", "index", "mem", "val" ], latency => 10, units => [ "SSE" ], mode => "mode_E", }, Conv_FP2I => { - reg_req => { in => [ "gp", "gp", "xmm", "none" ], out => [ "gp", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "gp", "none" ] }, + ins => [ "base", "index", "mem", "val" ], latency => 10, units => [ "SSE" ], mode => $mode_gp, }, Conv_FP2FP => { - reg_req => { in => [ "gp", "gp", "xmm", "none" ], out => [ "xmm", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "xmm", "none" ] }, + ins => [ "base", "index", "mem", "val" ], latency => 8, units => [ "SSE" ], mode => "mode_E", }, -CmpCMov => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "gp" ], out => [ "in_r4" ] }, - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -PsiCondCMov => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp" ], out => [ "in_r3" ] }, - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -xCmpCMov => { - irn_flags => "R", - reg_req => { in => [ "xmm", "xmm", "gp", "gp" ], out => [ "in_r4" ] }, - latency => 5, - units => [ "SSE" ], - mode => $mode_gp, -}, - -vfCmpCMov => { - irn_flags => "R", - reg_req => { in => [ "vfp", "vfp", "gp", "gp" ], out => [ "in_r4" ] }, - latency => 10, - units => [ "VFP" ], - mode => $mode_gp, -}, - -CmpSet => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "gp", "gp", "none" ], out => [ "eax ebx ecx edx" ] }, - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -PsiCondSet => { - irn_flags => "R", - reg_req => { in => [ "gp" ], out => [ "eax ebx ecx edx" ] }, - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -xCmpSet => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "xmm", "xmm", "none" ], out => [ "eax ebx ecx edx" ] }, - latency => 5, - units => [ "SSE" ], - mode => $mode_gp, -}, - -vfCmpSet => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "eax ebx ecx edx" ] }, - latency => 10, - units => [ "VFP" ], - mode => $mode_gp, -}, - -vfCMov => { - irn_flags => "R", - reg_req => { in => [ "vfp", "vfp", "vfp", "vfp" ], out => [ "vfp" ] }, - latency => 10, - units => [ "VFP" ], - mode => "mode_E", -}, - #----------------------------------------------------------# # _ _ _ __ _ _ # # (_) | | | | / _| | | | # @@ -1369,18 +1604,22 @@ vfCMov => { vfadd => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] }, + reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] }, + ins => [ "base", "index", "mem", "left", "right", "fpcw" ], latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, vfmul => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] }, + reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] }, + ins => [ "base", "index", "mem", "left", "right", "fpcw" ], latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, l_vfmul => { @@ -1391,10 +1630,12 @@ l_vfmul => { vfsub => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] }, + reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] }, + ins => [ "base", "index", "mem", "left", "right", "fpcw" ], latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, l_vfsub => { @@ -1403,10 +1644,12 @@ l_vfsub => { }, vfdiv => { - reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp", "none" ] }, + ins => [ "base", "index", "mem", "left", "right", "fpcw" ], outs => [ "res", "M" ], latency => 20, units => [ "VFP" ], + attr_type => "ia32_x87_attr_t", }, l_vfdiv => { @@ -1416,10 +1659,12 @@ l_vfdiv => { }, vfprem => { - reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "vfp" ] }, + reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp", "fpcw" ], out => [ "vfp" ] }, + ins => [ "base", "index", "mem", "left", "right", "fpcw" ], latency => 20, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, l_vfprem => { @@ -1430,41 +1675,21 @@ l_vfprem => { vfabs => { irn_flags => "R", reg_req => { in => [ "vfp"], out => [ "vfp" ] }, + ins => [ "value" ], latency => 2, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, vfchs => { irn_flags => "R", reg_req => { in => [ "vfp"], out => [ "vfp" ] }, + ins => [ "value" ], latency => 2, units => [ "VFP" ], mode => "mode_E", -}, - -vfsin => { - irn_flags => "R", - reg_req => { in => [ "vfp"], out => [ "vfp" ] }, - latency => 150, - units => [ "VFP" ], - mode => "mode_E", -}, - -vfcos => { - irn_flags => "R", - reg_req => { in => [ "vfp"], out => [ "vfp" ] }, - latency => 150, - units => [ "VFP" ], - mode => "mode_E", -}, - -vfsqrt => { - irn_flags => "R", - reg_req => { in => [ "vfp"], out => [ "vfp" ] }, - latency => 30, - units => [ "VFP" ], - mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, # virtual Load and Store @@ -1473,27 +1698,38 @@ vfld => { op_flags => "L|F", state => "exc_pinned", reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] }, + ins => [ "base", "index", "mem" ], outs => [ "res", "M" ], + attr => "ir_mode *load_mode", + init_attr => "attr->attr.ls_mode = load_mode;", latency => 2, units => [ "VFP" ], + attr_type => "ia32_x87_attr_t", }, vfst => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "vfp", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "vfp" ] }, + ins => [ "base", "index", "mem", "val" ], + attr => "ir_mode *store_mode", + init_attr => "attr->attr.ls_mode = store_mode;", latency => 2, units => [ "VFP" ], mode => "mode_M", + attr_type => "ia32_x87_attr_t", }, # Conversions vfild => { + state => "exc_pinned", reg_req => { in => [ "gp", "gp", "none" ], out => [ "vfp", "none" ] }, outs => [ "res", "M" ], + ins => [ "base", "index", "mem" ], latency => 4, units => [ "VFP" ], + attr_type => "ia32_x87_attr_t", }, l_vfild => { @@ -1503,14 +1739,18 @@ l_vfild => { }, vfist => { - reg_req => { in => [ "gp", "gp", "vfp", "fpcw", "none" ] }, + state => "exc_pinned", + reg_req => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] }, + ins => [ "base", "index", "mem", "val", "fpcw" ], latency => 4, units => [ "VFP" ], mode => "mode_M", + attr_type => "ia32_x87_attr_t", }, l_vfist => { cmp_attr => "return 1;", + state => "exc_pinned", arity => 3, mode => "mode_M", }, @@ -1524,6 +1764,7 @@ vfldz => { latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, vfld1 => { @@ -1532,6 +1773,7 @@ vfld1 => { latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, vfldpi => { @@ -1540,6 +1782,7 @@ vfldpi => { latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, vfldln2 => { @@ -1548,6 +1791,7 @@ vfldln2 => { latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, vfldlg2 => { @@ -1556,6 +1800,7 @@ vfldlg2 => { latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, vfldl2t => { @@ -1564,6 +1809,7 @@ vfldl2t => { latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, vfldl2e => { @@ -1572,27 +1818,35 @@ vfldl2e => { latency => 4, units => [ "VFP" ], mode => "mode_E", + attr_type => "ia32_x87_attr_t", }, -vfConst => { - op_flags => "c", - irn_flags => "R", -# init_attr => " set_ia32_ls_mode(res, mode);", - reg_req => { out => [ "vfp" ] }, +# other + +vFucomFnstsw => { +# we can't allow to rematerialize this node so we don't have +# accidently produce Phi(Fucom, Fucom(flipped)) +# irn_flags => "R", + reg_req => { in => [ "vfp", "vfp" ], out => [ "eax" ] }, + ins => [ "left", "right" ], + outs => [ "flags" ], + am => "source,binary", + attr => "int flipped", + init_attr => "attr->attr.data.cmp_flipped = flipped;", latency => 3, units => [ "VFP" ], - mode => "mode_E", + attr_type => "ia32_x87_attr_t", + mode => $mode_gp }, -# other - -vfCondJmp => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp", "vfp", "vfp", "none" ], out => [ "none", "none", "eax" ] }, - outs => [ "false", "true", "temp_reg_eax" ], - latency => 10, - units => [ "VFP" ], +Sahf => { + irn_flags => "R", + reg_req => { in => [ "eax" ], out => [ "eflags" ] }, + ins => [ "val" ], + outs => [ "flags" ], + emit => '. sahf', + units => [ "GP" ], + mode => $mode_flags, }, #------------------------------------------------------------------------# @@ -1611,13 +1865,15 @@ fadd => { rd_constructor => "NONE", reg_req => { }, emit => '. fadd%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, faddp => { op_flags => "R", rd_constructor => "NONE", reg_req => { }, - emit => '. faddp %x87_binop', + emit => '. faddp%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fmul => { @@ -1625,13 +1881,15 @@ fmul => { rd_constructor => "NONE", reg_req => { }, emit => '. fmul%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fmulp => { op_flags => "R", rd_constructor => "NONE", reg_req => { }, - emit => '. fmulp %x87_binop',, + emit => '. fmulp%XM %x87_binop',, + attr_type => "ia32_x87_attr_t", }, fsub => { @@ -1639,6 +1897,7 @@ fsub => { rd_constructor => "NONE", reg_req => { }, emit => '. fsub%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fsubp => { @@ -1646,7 +1905,8 @@ fsubp => { rd_constructor => "NONE", reg_req => { }, # see note about gas bugs - emit => '. fsubrp %x87_binop', + emit => '. fsubrp%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fsubr => { @@ -1655,6 +1915,7 @@ fsubr => { irn_flags => "R", reg_req => { }, emit => '. fsubr%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fsubrp => { @@ -1663,7 +1924,8 @@ fsubrp => { irn_flags => "R", reg_req => { }, # see note about gas bugs - emit => '. fsubp %x87_binop', + emit => '. fsubp%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fprem => { @@ -1671,6 +1933,7 @@ fprem => { rd_constructor => "NONE", reg_req => { }, emit => '. fprem1', + attr_type => "ia32_x87_attr_t", }, # this node is just here, to keep the simulator running @@ -1680,6 +1943,7 @@ fpremp => { rd_constructor => "NONE", reg_req => { }, emit => '. fprem1', + attr_type => "ia32_x87_attr_t", }, fdiv => { @@ -1687,6 +1951,7 @@ fdiv => { rd_constructor => "NONE", reg_req => { }, emit => '. fdiv%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fdivp => { @@ -1694,7 +1959,8 @@ fdivp => { rd_constructor => "NONE", reg_req => { }, # see note about gas bugs - emit => '. fdivrp %x87_binop', + emit => '. fdivrp%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fdivr => { @@ -1702,6 +1968,7 @@ fdivr => { rd_constructor => "NONE", reg_req => { }, emit => '. fdivr%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fdivrp => { @@ -1709,7 +1976,8 @@ fdivrp => { rd_constructor => "NONE", reg_req => { }, # see note about gas bugs - emit => '. fdivp %x87_binop', + emit => '. fdivp%XM %x87_binop', + attr_type => "ia32_x87_attr_t", }, fabs => { @@ -1717,6 +1985,7 @@ fabs => { rd_constructor => "NONE", reg_req => { }, emit => '. fabs', + attr_type => "ia32_x87_attr_t", }, fchs => { @@ -1724,27 +1993,7 @@ fchs => { rd_constructor => "NONE", reg_req => { }, emit => '. fchs', -}, - -fsin => { - op_flags => "R", - rd_constructor => "NONE", - reg_req => { }, - emit => '. fsin', -}, - -fcos => { - op_flags => "R", - rd_constructor => "NONE", - reg_req => { }, - emit => '. fcos', -}, - -fsqrt => { - op_flags => "R", - rd_constructor => "NONE", - reg_req => { }, - emit => '. fsqrt $', + attr_type => "ia32_x87_attr_t", }, # x87 Load and Store @@ -1755,6 +2004,7 @@ fld => { state => "exc_pinned", reg_req => { }, emit => '. fld%XM %AM', + attr_type => "ia32_x87_attr_t", }, fst => { @@ -1764,6 +2014,7 @@ fst => { reg_req => { }, emit => '. fst%XM %AM', mode => "mode_M", + attr_type => "ia32_x87_attr_t", }, fstp => { @@ -1773,6 +2024,7 @@ fstp => { reg_req => { }, emit => '. fstp%XM %AM', mode => "mode_M", + attr_type => "ia32_x87_attr_t", }, # Conversions @@ -1781,23 +2033,28 @@ fild => { op_flags => "R", rd_constructor => "NONE", reg_req => { }, - emit => '. fild%XM %AM', + emit => '. fild%M %AM', + attr_type => "ia32_x87_attr_t", }, fist => { op_flags => "R", + state => "exc_pinned", rd_constructor => "NONE", reg_req => { }, - emit => '. fist%XM %AM', + emit => '. fist%M %AM', mode => "mode_M", + attr_type => "ia32_x87_attr_t", }, fistp => { op_flags => "R", + state => "exc_pinned", rd_constructor => "NONE", reg_req => { }, - emit => '. fistp%XM %AM', + emit => '. fistp%M %AM', mode => "mode_M", + attr_type => "ia32_x87_attr_t", }, # constants @@ -1807,6 +2064,7 @@ fldz => { irn_flags => "R", reg_req => { }, emit => '. fldz', + attr_type => "ia32_x87_attr_t", }, fld1 => { @@ -1814,6 +2072,7 @@ fld1 => { irn_flags => "R", reg_req => { }, emit => '. fld1', + attr_type => "ia32_x87_attr_t", }, fldpi => { @@ -1821,6 +2080,7 @@ fldpi => { irn_flags => "R", reg_req => { }, emit => '. fldpi', + attr_type => "ia32_x87_attr_t", }, fldln2 => { @@ -1828,6 +2088,7 @@ fldln2 => { irn_flags => "R", reg_req => { }, emit => '. fldln2', + attr_type => "ia32_x87_attr_t", }, fldlg2 => { @@ -1835,6 +2096,7 @@ fldlg2 => { irn_flags => "R", reg_req => { }, emit => '. fldlg2', + attr_type => "ia32_x87_attr_t", }, fldl2t => { @@ -1842,6 +2104,7 @@ fldl2t => { irn_flags => "R", reg_req => { }, emit => '. fldll2t', + attr_type => "ia32_x87_attr_t", }, fldl2e => { @@ -1849,6 +2112,7 @@ fldl2e => { irn_flags => "R", reg_req => { }, emit => '. fldl2e', + attr_type => "ia32_x87_attr_t", }, # fxch, fpush, fpop @@ -1860,6 +2124,7 @@ fxch => { reg_req => { }, cmp_attr => "return 1;", emit => '. fxch %X0', + attr_type => "ia32_x87_attr_t", }, fpush => { @@ -1867,6 +2132,7 @@ fpush => { reg_req => {}, cmp_attr => "return 1;", emit => '. fld %X0', + attr_type => "ia32_x87_attr_t", }, fpushCopy => { @@ -1874,45 +2140,65 @@ fpushCopy => { reg_req => { in => [ "vfp"], out => [ "vfp" ] }, cmp_attr => "return 1;", emit => '. fld %X0', + attr_type => "ia32_x87_attr_t", }, fpop => { - op_flags => "R|K", + op_flags => "K", reg_req => { }, cmp_attr => "return 1;", emit => '. fstp %X0', + attr_type => "ia32_x87_attr_t", }, -# compare - -fcomJmp => { - op_flags => "L|X|Y", +ffreep => { + op_flags => "K", reg_req => { }, + cmp_attr => "return 1;", + emit => '. ffreep %X0', + attr_type => "ia32_x87_attr_t", }, -fcompJmp => { - op_flags => "L|X|Y", +emms => { + op_flags => "K", reg_req => { }, + cmp_attr => "return 1;", + emit => '. emms', + attr_type => "ia32_x87_attr_t", }, -fcomppJmp => { - op_flags => "L|X|Y", +femms => { + op_flags => "K", reg_req => { }, + cmp_attr => "return 1;", + emit => '. femms', + attr_type => "ia32_x87_attr_t", }, -fcomrJmp => { - op_flags => "L|X|Y", +# compare + +FucomFnstsw => { + op_flags => "R", reg_req => { }, + emit => ". fucom %X1\n". + ". fnstsw", + attr_type => "ia32_x87_attr_t", }, -fcomrpJmp => { - op_flags => "L|X|Y", +FucompFnstsw => { + op_flags => "R", reg_req => { }, + emit => ". fucomp %X1\n". + ". fnstsw", + attr_type => "ia32_x87_attr_t", }, -fcomrppJmp => { - op_flags => "L|X|Y", +FucomppFnstsw => { + op_flags => "R", reg_req => { }, + emit => ". fucompp\n". + ". fnstsw", + attr_type => "ia32_x87_attr_t", }, @@ -1940,7 +2226,8 @@ xxLoad => { xxStore => { op_flags => "L|F", state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "xmm", "none" ] }, + reg_req => { in => [ "gp", "gp", "none", "xmm" ] }, + ins => [ "base", "index", "mem", "val" ], emit => '. movdqu %binop', units => [ "SSE" ], mode => "mode_M",