X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_spec.pl;h=dc0c49d8e41c5c6c1f9a6b28b54bef0bbae8a38d;hb=90f2e217df8deecb71f08af6bb28f9decd6795b0;hp=9abf467684cdb40bcb74be46d59047070fcda706;hpb=eea84fd02289643ae5f86ecee59908a651729f68;p=libfirm diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 9abf46768..dc0c49d8e 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -110,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 }, @@ -131,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 }, @@ -168,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" ], @@ -247,47 +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);", - SB1 => "${arch}_emit_8bit_source_register(env, node, 1);", - SB2 => "${arch}_emit_8bit_source_register(env, node, 2);", - SB3 => "${arch}_emit_8bit_source_register(env, node, 3);", - SW0 => "${arch}_emit_16bit_source_register(env, node, 0);", - SI0 => "${arch}_emit_source_register_or_immediate(env, node, 0);", - SI1 => "${arch}_emit_source_register_or_immediate(env, node, 1);", - SI2 => "${arch}_emit_source_register_or_immediate(env, node, 2);", - SI3 => "${arch}_emit_source_register_or_immediate(env, node, 3);", - 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);", - 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);", - unop0 => "${arch}_emit_unop(env, node, 0);", - unop1 => "${arch}_emit_unop(env, node, 1);", - unop2 => "${arch}_emit_unop(env, node, 2);", - unop3 => "${arch}_emit_unop(env, node, 3);", - unop4 => "${arch}_emit_unop(env, node, 4);", - unop5 => "${arch}_emit_unop(env, node, 5);", - DAM0 => "${arch}_emit_am_or_dest_register(env, node, 0);", - DAM1 => "${arch}_emit_am_or_dest_register(env, node, 1);", - 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);", ); #--------------------------------------------------# @@ -363,6 +311,7 @@ $custom_init_attr_func = \&ia32_custom_init_attr; $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", @@ -415,7 +364,7 @@ ProduceVal => { Add => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4", "none", "flags" ] }, + 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", @@ -434,8 +383,18 @@ AddMem => { modified_flags => $status_flags }, +AddMem8Bit => { + irn_flags => "R", + 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" ] }, + 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", @@ -455,21 +414,6 @@ l_Adc => { ins => [ "left", "right", "eflags" ], }, -Add64Bit => { - irn_flags => "R", - arity => 4, - reg_req => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] }, - emit => ' -. movl %S0, %D0 -. movl %S1, %D1 -. addl %SI2, %D0 -. adcl %SI3, %D1 -', - outs => [ "low_res", "high_res" ], - units => [ "GP" ], - modified_flags => $status_flags -}, - Mul => { # we should not rematrialize this node. It produces 2 results and has # very strict constrains @@ -494,7 +438,7 @@ l_Mul => { IMul => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] }, + 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", @@ -527,7 +471,7 @@ l_IMul => { And => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] }, + 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', @@ -546,9 +490,19 @@ AndMem => { 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", "none", "gp", "gp" ], out => [ "in_r4" ] }, + 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', @@ -567,9 +521,19 @@ OrMem => { 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", "none", "gp", "gp" ], out => [ "in_r4" ] }, + 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', @@ -588,11 +552,21 @@ XorMem => { 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 +}, + # not commutative operations Sub => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "in_r4" ] }, + 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', @@ -611,9 +585,19 @@ SubMem => { modified_flags => $status_flags }, +SubMem8Bit => { + irn_flags => "R", + 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" ], out => [ "in_r4 !in_r5" ] }, - ins => [ "base", "index", "mem", "left", "right" ], + 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" ], @@ -621,19 +605,14 @@ Sbb => { modified_flags => $status_flags }, -Sub64Bit => { - irn_flags => "R", - arity => 4, - reg_req => { in => [ "gp", "gp", "gp", "gp" ], out => [ "!in", "!in" ] }, - emit => ' -. movl %S0, %D0 -. movl %S1, %D1 -. subl %SI2, %D0 -. sbbl %SI3, %D1 -', - outs => [ "low_res", "high_res" ], - units => [ "GP" ], - modified_flags => $status_flags +l_Sub => { + reg_req => { in => [ "none", "none" ], out => [ "none" ] }, + ins => [ "left", "right" ], +}, + +l_Sbb => { + reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] }, + ins => [ "left", "right", "eflags" ], }, IDiv => { @@ -951,55 +930,106 @@ NotMem => { # other operations -CmpJmp => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "none", "none"] }, +Cmp => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] }, ins => [ "base", "index", "mem", "left", "right" ], - outs => [ "false", "true" ], - attr => "long pnc", + outs => [ "eflags" ], am => "source,binary", - init_attr => "attr->pn_code = pnc;", - latency => 3, - units => [ "BRANCH" ], + 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 }, -CmpJmp8Bit => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "none", "none"] }, +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 => [ "false", "true" ], - attr => "long pnc", + outs => [ "eflags" ], am => "source,binary", - init_attr => "attr->pn_code = pnc;", - latency => 3, - units => [ "BRANCH" ], + 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 }, -TestJmp => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "none", "none" ] }, +Test => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ] , out => [ "flags" ] }, ins => [ "base", "index", "mem", "left", "right" ], - outs => [ "false", "true" ], - attr => "long pnc", + outs => [ "eflags" ], am => "source,binary", - init_attr => "attr->pn_code = pnc;", - latency => 3, - units => [ "BRANCH" ], + 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, }, -TestJmp8Bit => { +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, +}, + +Jcc => { state => "pinned", op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "none", "none" ] }, - ins => [ "base", "index", "mem", "left", "right" ], + reg_req => { in => [ "eflags" ], out => [ "none", "none" ] }, + ins => [ "eflags" ], outs => [ "false", "true" ], - attr => "long pnc", - am => "source,binary", + attr => "pn_Cmp pnc", init_attr => "attr->pn_code = pnc;", - latency => 3, + latency => 2, units => [ "BRANCH" ], }, @@ -1010,6 +1040,7 @@ SwitchJmp => { latency => 3, units => [ "BRANCH" ], mode => "mode_T", + modified_flags => $status_flags }, IJmp => { @@ -1029,6 +1060,8 @@ Const => { 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 => { @@ -1128,8 +1161,7 @@ FnstCW => { }, Cltd => { - # we should not rematrialize this node. It produces 2 results and has - # very strict constrains + # we should not rematrialize this node. It has very strict constraints. reg_req => { in => [ "eax", "edx" ], out => [ "edx" ] }, ins => [ "val", "globbered" ], emit => '. cltd', @@ -1198,6 +1230,9 @@ Lea => { latency => 2, units => [ "GP" ], mode => $mode_gp, +# 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 => { @@ -1299,7 +1334,7 @@ xZero => { xAdd => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] }, + 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, @@ -1309,7 +1344,7 @@ xAdd => { xMul => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] }, + 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, @@ -1319,7 +1354,7 @@ xMul => { xMax => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] }, + 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, @@ -1329,7 +1364,7 @@ xMax => { xMin => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] }, + 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, @@ -1339,7 +1374,7 @@ xMin => { xAnd => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] }, + 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, @@ -1349,7 +1384,7 @@ xAnd => { xOr => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] }, + 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" ], @@ -1358,7 +1393,7 @@ xOr => { xXor => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4" ] }, + 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, @@ -1400,25 +1435,19 @@ xDiv => { # other operations -xCmp => { +Ucomi => { irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "in_r4 !in_r5" ] }, + 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", -}, - -xCmpJmp => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "none", "none" ] }, - ins => [ "base", "index", "mem", "left", "right" ], - outs => [ "false", "true" ], - attr => "long pnc", - init_attr => "attr->pn_code = pnc;", - latency => 5, - units => [ "SSE" ], + mode => $mode_flags, + modified_flags => 1, }, # Load / Store @@ -1517,24 +1546,22 @@ CopyB_i => { Conv_I2I => { state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "gp" ], out => [ "in_r4", "none" ] }, + 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, - modified_flags => $status_flags }, Conv_I2I8Bit => { state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx" ], out => [ "in_r4", "none" ] }, + 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, - modified_flags => $status_flags }, Conv_I2FP => { @@ -1561,140 +1588,6 @@ Conv_FP2FP => { mode => "mode_E", }, -CmpCMov => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ], - attr => "pn_Cmp pn_code", - init_attr => "attr->pn_code = pn_code;", - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -CmpCMov8Bit => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ], - attr => "pn_Cmp pn_code", - init_attr => "attr->pn_code = pn_code;", - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -TestCMov => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ], - attr => "pn_Cmp pn_code", - init_attr => "attr->pn_code = pn_code;", - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -TestCMov8Bit => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp", "gp", "gp" ], out => [ "in_r7" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ], - attr => "pn_Cmp pn_code", - init_attr => "attr->pn_code = pn_code;", - 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 => [ "gp", "gp", "none", "vfp", "vfp", "gp", "gp" ], out => [ "in_r7" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right", "val_true", "val_false" ], - latency => 10, - units => [ "VFP", "GP" ], - mode => $mode_gp, - attr_type => "ia32_x87_attr_t", -}, - -CmpSet => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "eax ebx ecx edx" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right" ], - attr => "pn_Cmp pn_code", - init_attr => "attr->pn_code = pn_code;", - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -CmpSet8Bit => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "eax ebx ecx edx" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right" ], - attr => "pn_Cmp pn_code", - init_attr => "attr->pn_code = pn_code;", - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -TestSet => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "gp", "gp" ], out => [ "eax ebx ecx edx" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right" ], - attr => "pn_Cmp pn_code", - init_attr => "attr->pn_code = pn_code;", - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -TestSet8Bit => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "eax ebx ecx edx", "eax ebx ecx edx" ], out => [ "eax ebx ecx edx" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right" ], - attr => "pn_Cmp pn_code", - init_attr => "attr->pn_code = pn_code;", - latency => 2, - units => [ "GP" ], - mode => $mode_gp, -}, - -xCmpSet => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "xmm", "xmm" ], out => [ "eax ebx ecx edx" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right" ], - latency => 5, - units => [ "SSE" ], - mode => $mode_gp, -}, - -vfCmpSet => { - irn_flags => "R", - reg_req => { in => [ "gp", "gp", "none", "vfp", "vfp" ], out => [ "eax ebx ecx edx" ] }, - ins => [ "base", "index", "mem", "cmp_left", "cmp_right" ], - latency => 10, - units => [ "VFP" ], - mode => $mode_gp, - attr_type => "ia32_x87_attr_t", -}, - -vfCMov => { - irn_flags => "R", - reg_req => { in => [ "vfp", "vfp", "vfp", "vfp" ], out => [ "vfp" ] }, - latency => 10, - units => [ "VFP" ], - mode => "mode_E", - attr_type => "ia32_x87_attr_t", -}, - #----------------------------------------------------------# # _ _ _ __ _ _ # # (_) | | | | / _| | | | # @@ -1930,17 +1823,30 @@ vfldl2e => { # other -vfCmpJmp => { - state => "pinned", - op_flags => "L|X|Y", - reg_req => { in => [ "vfp", "vfp" ], out => [ "none", "none", "eax" ] }, +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 => [ "false", "true", "temp_reg_eax" ], - attr => "long pnc", - init_attr => "attr->attr.pn_code = pnc;", - latency => 10, + outs => [ "flags" ], + am => "source,binary", + attr => "int flipped", + init_attr => "attr->attr.data.cmp_flipped = flipped;", + latency => 3, units => [ "VFP" ], attr_type => "ia32_x87_attr_t", + mode => $mode_gp +}, + +Sahf => { + irn_flags => "R", + reg_req => { in => [ "eax" ], out => [ "eflags" ] }, + ins => [ "val" ], + outs => [ "flags" ], + emit => '. sahf', + units => [ "GP" ], + mode => $mode_flags, }, #------------------------------------------------------------------------# @@ -2271,39 +2177,27 @@ femms => { # compare -fcomJmp => { - op_flags => "L|X|Y", - reg_req => { }, - attr_type => "ia32_x87_attr_t", -}, - -fcompJmp => { - op_flags => "L|X|Y", - reg_req => { }, - attr_type => "ia32_x87_attr_t", -}, - -fcomppJmp => { - op_flags => "L|X|Y", - reg_req => { }, - attr_type => "ia32_x87_attr_t", -}, - -fcomrJmp => { - op_flags => "L|X|Y", +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", },