X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_spec.pl;h=ebffcad201e8842e759011d9714d8a4377ca89dd;hb=bba15007f36643c7c6f9281c8be00d8511bfb4f9;hp=35e8d99145eec4d74025a0df23b5caa832e11a55;hpb=294649280c357adf3afa6d66918ff36ca739e943;p=libfirm diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 35e8d9914..ebffcad20 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -4,145 +4,77 @@ $arch = "ia32"; -# The node description is done as a perl hash initializer with the -# following structure: -# -# %nodes = ( -# -# => { -# op_flags => "N|L|C|X|I|F|Y|H|c|K|n", -# irn_flags => "R|N" -# arity => "0|1|2|3 ... |variable|dynamic|any", -# state => "floats|pinned|mem_pinned|exc_pinned", -# args => [ -# { type => "type 1", name => "name 1" }, -# { type => "type 2", name => "name 2" }, -# ... -# ], -# comment => "any comment for constructor", -# reg_req => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] }, -# cmp_attr => "c source code for comparing node attributes", -# outs => { "out1", "out2" } # optional, creates pn_op_out1, ... consts -# ins => { "in1", "in2" } # optional, creates n_op_in1, ... consts -# mode => "mode_Iu" # optional, predefines the mode -# emit => "emit code with templates", -# attr => "additional attribute arguments for constructor", -# init_attr => "emit attribute initialization template", -# hash_func => "name of the hash function for this operation", -# latency => "latency of this operation (can be float)" -# attr_type => "name of the attribute struct", -# modified_flags => [ "CF", ... ] # optional, list of modified flags -# }, -# -# ... # (all nodes you need to describe) -# -# ); # close the %nodes initializer - -# state: state of the operation, OPTIONAL (default is "floats") -# -# arity: arity of the operation, MUST NOT BE OMITTED -# -# args: the OPTIONAL arguments of the node constructor (debug, irg and block -# are always the first 3 arguments and are always autmatically -# created) -# If this key is missing the following arguments will be created: -# for i = 1 .. arity: ir_node *op_i -# ir_mode *mode -# -# outs: if a node defines more than one output, the names of the projections -# nodes having outs having automatically the mode mode_T -# example: [ "frame", "stack", "M" ] -# -# comment: OPTIONAL comment for the node constructor -# -# rd_constructor: for every operation there will be a -# new_rd__ function with the arguments from above -# which creates the ir_node corresponding to the defined operation -# you can either put the complete source code of this function here -# -# This key is OPTIONAL. If omitted, the following constructor will -# be created: -# if (!op__) assert(0); -# for i = 1 to arity -# set in[i] = op_i -# done -# res = new_ir_node(db, irg, block, op__, mode, arity, in) -# return res -# -# NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3 -# - # register types: -# 0 - no special type -# 1 - caller save (register must be saved by the caller of a function) -# 2 - callee save (register must be saved by the called function) -# 4 - ignore (do not automatically assign this register) -# 8 - emitter can choose an arbitrary register of this class -# 16 - the register is a virtual one -# 32 - register represents a state +$normal = 0; # no special type +$caller_save = 1; # caller save (register must be saved by the caller of a function) +$callee_save = 2; # callee save (register must be saved by the called function) +$ignore = 4; # ignore (do not assign this register) +$arbitrary = 8; # emitter can choose an arbitrary register of this class +$virtual = 16; # the register is a virtual one +$state = 32; # register represents a state # NOTE: Last entry of each class is the largest Firm-Mode a register can hold %reg_classes = ( gp => [ - { name => "edx", type => 1 }, - { name => "ecx", type => 1 }, - { name => "eax", type => 1 }, - { name => "ebx", type => 2 }, - { name => "esi", type => 2 }, - { name => "edi", type => 2 }, - { name => "ebp", type => 2 }, - { name => "esp", type => 4 }, - { name => "gp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes + { name => "edx", type => $caller_save }, + { name => "ecx", type => $caller_save }, + { name => "eax", type => $caller_save }, + { name => "ebx", type => $callee_save }, + { name => "esi", type => $callee_save }, + { name => "edi", type => $callee_save }, + { name => "ebp", type => $callee_save }, + { name => "esp", type => $ignore }, + { name => "gp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes { mode => "mode_Iu" } ], mmx => [ - { name => "mm0", type => 4 }, - { name => "mm1", type => 4 }, - { name => "mm2", type => 4 }, - { name => "mm3", type => 4 }, - { name => "mm4", type => 4 }, - { name => "mm5", type => 4 }, - { name => "mm6", type => 4 }, - { name => "mm7", type => 4 }, + { name => "mm0", type => $ignore }, + { name => "mm1", type => $ignore }, + { name => "mm2", type => $ignore }, + { name => "mm3", type => $ignore }, + { name => "mm4", type => $ignore }, + { name => "mm5", type => $ignore }, + { name => "mm6", type => $ignore }, + { name => "mm7", type => $ignore }, { mode => "mode_E", flags => "manual_ra" } ], xmm => [ - { name => "xmm0", type => 1 }, - { name => "xmm1", type => 1 }, - { name => "xmm2", type => 1 }, - { name => "xmm3", type => 1 }, - { name => "xmm4", type => 1 }, - { name => "xmm5", type => 1 }, - { name => "xmm6", type => 1 }, - { name => "xmm7", type => 1 }, - { name => "xmm_NOREG", type => 4 | 16 }, # we need a dummy register for NoReg nodes + { name => "xmm0", type => $caller_save }, + { name => "xmm1", type => $caller_save }, + { name => "xmm2", type => $caller_save }, + { name => "xmm3", type => $caller_save }, + { name => "xmm4", type => $caller_save }, + { name => "xmm5", type => $caller_save }, + { name => "xmm6", type => $caller_save }, + { name => "xmm7", type => $caller_save }, + { name => "xmm_NOREG", type => $ignore | $virtual }, # we need a dummy register for NoReg nodes { mode => "mode_E" } ], vfp => [ - { name => "vf0", type => 1 }, - { name => "vf1", type => 1 }, - { name => "vf2", type => 1 }, - { name => "vf3", type => 1 }, - { name => "vf4", type => 1 }, - { name => "vf5", type => 1 }, - { name => "vf6", type => 1 }, - { name => "vf7", type => 1 }, - { name => "vfp_NOREG", type => 4 | 8 | 16 }, # we need a dummy register for NoReg nodes + { name => "vf0", type => $caller_save }, + { name => "vf1", type => $caller_save }, + { name => "vf2", type => $caller_save }, + { name => "vf3", type => $caller_save }, + { name => "vf4", type => $caller_save }, + { name => "vf5", type => $caller_save }, + { name => "vf6", type => $caller_save }, + { name => "vf7", type => $caller_save }, + { name => "vfp_NOREG", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for NoReg nodes { mode => "mode_E" } ], st => [ - { name => "st0", realname => "st", type => 4 }, - { name => "st1", realname => "st(1)", type => 4 }, - { name => "st2", realname => "st(2)", type => 4 }, - { name => "st3", realname => "st(3)", type => 4 }, - { name => "st4", realname => "st(4)", type => 4 }, - { name => "st5", realname => "st(5)", type => 4 }, - { name => "st6", realname => "st(6)", type => 4 }, - { name => "st7", realname => "st(7)", type => 4 }, + { name => "st0", realname => "st", type => $ignore }, + { name => "st1", realname => "st(1)", type => $ignore }, + { name => "st2", realname => "st(2)", type => $ignore }, + { name => "st3", realname => "st(3)", type => $ignore }, + { name => "st4", realname => "st(4)", type => $ignore }, + { name => "st5", realname => "st(5)", type => $ignore }, + { name => "st6", realname => "st(6)", type => $ignore }, + { name => "st7", realname => "st(7)", type => $ignore }, { mode => "mode_E", flags => "manual_ra" } ], fp_cw => [ # the floating point control word - { name => "fpcw", type => 4|32 }, - { mode => "mode_fpcw", flags => "manual_ra|state" } + { name => "fpcw", type => $ignore | $state }, + { mode => "ia32_mode_fpcw", flags => "manual_ra|state" } ], flags => [ { name => "eflags", type => 0 }, @@ -245,7 +177,10 @@ $custom_init_attr_func = \&ia32_custom_init_attr; "\tinit_ia32_call_attributes(res, pop, call_tp);", ia32_condcode_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n". - "\tinit_ia32_condcode_attributes(res, pnc);", + "\tinit_ia32_condcode_attributes(res, condition_code);", + ia32_switch_attr_t => + "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n". + "\tinit_ia32_switch_attributes(res, default_pn);", ia32_copyb_attr_t => "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n". "\tinit_ia32_copyb_attributes(res, size);", @@ -261,10 +196,11 @@ $custom_init_attr_func = \&ia32_custom_init_attr; ); %compare_attr = ( - ia32_asm_attr_t => "ia32_compare_asm_attr", + ia32_asm_attr_t => "ia32_compare_asm_attr", ia32_attr_t => "ia32_compare_nodes_attr", ia32_call_attr_t => "ia32_compare_call_attr", ia32_condcode_attr_t => "ia32_compare_condcode_attr", + ia32_switch_attr_t => "ia32_compare_switch_attr", ia32_copyb_attr_t => "ia32_compare_copyb_attr", ia32_immediate_attr_t => "ia32_compare_immediate_attr", ia32_x87_attr_t => "ia32_compare_x87_attr", @@ -277,7 +213,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"; +$mode_fpcw = "ia32_mode_fpcw"; $status_flags = [ "CF", "PF", "AF", "ZF", "SF", "OF" ]; $status_flags_wo_cf = [ "PF", "AF", "ZF", "SF", "OF" ]; $fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM", @@ -288,6 +224,7 @@ $fpcw_flags = [ "FP_IM", "FP_DM", "FP_ZM", "FP_OM", "FP_UM", "FP_PM", Immediate => { state => "pinned", op_flags => [ "constlike" ], + irn_flags => [ "not_scheduled" ], reg_req => { out => [ "gp_NOREG:I" ] }, attr => "ir_entity *symconst, int symconst_sign, int no_pic_adjust, long offset", attr_type => "ia32_immediate_attr_t", @@ -999,9 +936,8 @@ Cmp => { outs => [ "eflags", "unused", "M" ], am => "source,binary", emit => '. cmp%M %binop', - attr => "int ins_permuted, int cmp_unsigned", - init_attr => "attr->data.ins_permuted = ins_permuted;\n". - "\tattr->data.cmp_unsigned = cmp_unsigned;\n", + attr => "bool ins_permuted", + init_attr => "attr->data.ins_permuted = ins_permuted;", latency => 1, units => [ "GP" ], mode => $mode_flags, @@ -1017,15 +953,28 @@ Cmp8Bit => { outs => [ "eflags", "unused", "M" ], am => "source,binary", emit => '. cmpb %binop', - attr => "int ins_permuted, int cmp_unsigned", - init_attr => "attr->data.ins_permuted = ins_permuted;\n". - "\tattr->data.cmp_unsigned = cmp_unsigned;\n", + attr => "bool ins_permuted", + init_attr => "attr->data.ins_permuted = ins_permuted;", latency => 1, units => [ "GP" ], mode => $mode_flags, modified_flags => $status_flags }, +XorHighLow => { + irn_flags => [ "rematerializable" ], + state => "exc_pinned", + reg_req => { in => [ "eax ebx ecx edx" ], + out => [ "in_r1", "flags" ] }, + emit => '. xorb %SH0, %SB0', + ins => [ "value" ], + outs => [ "res", "flags" ], + units => [ "GP" ], + latency => 1, + mode => $mode_gp, + modified_flags => $status_flags, +}, + Test => { irn_flags => [ "rematerializable" ], state => "exc_pinned", @@ -1035,9 +984,8 @@ Test => { outs => [ "eflags", "unused", "M" ], am => "source,binary", emit => '. test%M %binop', - attr => "int ins_permuted, int cmp_unsigned", - init_attr => "attr->data.ins_permuted = ins_permuted;\n". - "\tattr->data.cmp_unsigned = cmp_unsigned;\n", + attr => "bool ins_permuted", + init_attr => "attr->data.ins_permuted = ins_permuted;", latency => 1, units => [ "GP" ], mode => $mode_flags, @@ -1053,9 +1001,8 @@ Test8Bit => { outs => [ "eflags", "unused", "M" ], am => "source,binary", emit => '. testb %binop', - attr => "int ins_permuted, int cmp_unsigned", - init_attr => "attr->data.ins_permuted = ins_permuted;\n". - "\tattr->data.cmp_unsigned = cmp_unsigned;\n", + attr => "bool ins_permuted", + init_attr => "attr->data.ins_permuted = ins_permuted;", latency => 1, units => [ "GP" ], mode => $mode_flags, @@ -1068,11 +1015,11 @@ Setcc => { ins => [ "eflags" ], outs => [ "res" ], attr_type => "ia32_condcode_attr_t", - attr => "pn_Cmp pnc", + attr => "ia32_condition_code_t condition_code", # The way we handle Setcc with float nodes (potentially) destroys the flags # (when we emit the setX; setp; orb and the setX;setnp;andb sequences) init_attr => "set_ia32_ls_mode(res, mode_Bu);\n" - . "\tif ((pnc & ia32_pn_Cmp_float) && ((pnc & 0xf) != pn_Cmp_Uo) && ((pnc & 0xf) != pn_Cmp_Leg)) {\n" + . "\tif (condition_code & ia32_cc_additional_float_cases) {\n" . "\t\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);\n" . "\t\t/* attr->latency = 3; */\n" . "\t}\n", @@ -1087,7 +1034,7 @@ SetccMem => { reg_req => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] }, ins => [ "base", "index", "mem","eflags" ], attr_type => "ia32_condcode_attr_t", - attr => "pn_Cmp pnc", + attr => "ia32_condition_code_t condition_code", init_attr => "set_ia32_ls_mode(res, mode_Bu);\n", emit => '. set%CMP3 %AM', latency => 1, @@ -1106,7 +1053,7 @@ CMovcc => { outs => [ "res", "flags", "M" ], am => "source,binary", attr_type => "ia32_condcode_attr_t", - attr => "pn_Cmp pnc", + attr => "ia32_condition_code_t condition_code", latency => 1, units => [ "GP" ], mode => $mode_gp, @@ -1119,7 +1066,7 @@ Jcc => { ins => [ "eflags" ], outs => [ "false", "true" ], attr_type => "ia32_condcode_attr_t", - attr => "pn_Cmp pnc", + attr => "ia32_condition_code_t condition_code", latency => 2, units => [ "BRANCH" ], }, @@ -1129,8 +1076,8 @@ SwitchJmp => { op_flags => [ "labeled", "cfopcode", "forking" ], reg_req => { in => [ "gp" ] }, mode => "mode_T", - attr_type => "ia32_condcode_attr_t", - attr => "long pnc", + attr_type => "ia32_switch_attr_t", + attr => "long default_pn", latency => 3, units => [ "BRANCH" ], modified_flags => $status_flags, @@ -1192,6 +1139,7 @@ GetEIP => { NoReg_GP => { state => "pinned", op_flags => [ "constlike", "dump_noblock", "dump_noinput" ], + irn_flags => [ "not_scheduled" ], reg_req => { out => [ "gp_NOREG:I" ] }, units => [], emit => "", @@ -1202,6 +1150,7 @@ NoReg_GP => { NoReg_VFP => { state => "pinned", op_flags => [ "constlike", "dump_noblock", "dump_noinput" ], + irn_flags => [ "not_scheduled" ], reg_req => { out => [ "vfp_NOREG:I" ] }, units => [], emit => "", @@ -1213,6 +1162,7 @@ NoReg_VFP => { NoReg_XMM => { state => "pinned", op_flags => [ "constlike", "dump_noblock", "dump_noinput" ], + irn_flags => [ "not_scheduled" ], reg_req => { out => [ "xmm_NOREG:I" ] }, units => [], emit => "", @@ -1223,6 +1173,7 @@ NoReg_XMM => { ChangeCW => { state => "pinned", op_flags => [ "constlike" ], + irn_flags => [ "not_scheduled" ], reg_req => { out => [ "fpcw:I" ] }, mode => $mode_fpcw, latency => 3, @@ -1369,6 +1320,17 @@ PopEbp => { units => [ "GP" ], }, +CopyEbpEsp => { + state => "exc_pinned", + reg_req => { in => [ "ebp" ], out => [ "esp:I|S" ] }, + ins => [ "ebp" ], + outs => [ "esp" ], + emit => '. movl %S0, %D0', + latency => 1, + units => [ "GP" ], + mode => $mode_gp, +}, + PopMem => { state => "exc_pinned", reg_req => { in => [ "gp", "gp", "none", "esp" ], out => [ "none", "none", "none", "esp:I|S" ] }, @@ -1393,6 +1355,7 @@ Leave => { outs => [ "frame", "stack" ], latency => 3, units => [ "GP" ], + state => "exc_pinned", }, AddSP => { @@ -1432,6 +1395,8 @@ LdTls => { irn_flags => [ "rematerializable" ], reg_req => { out => [ "gp" ] }, units => [ "GP" ], + emit => ". movl %%gs:0, %D0", + mode => $mode_gp, latency => 1, }, @@ -1912,7 +1877,7 @@ Ucomi => { ins => [ "base", "index", "mem", "left", "right" ], outs => [ "flags" ], am => "source,binary", - attr => "int ins_permuted", + attr => "bool ins_permuted", init_attr => "attr->data.ins_permuted = ins_permuted;", emit => ' .ucomi%XXM %binop', latency => 3, @@ -2321,7 +2286,7 @@ vFucomFnstsw => { reg_req => { in => [ "vfp", "vfp" ], out => [ "eax" ] }, ins => [ "left", "right" ], outs => [ "flags" ], - attr => "int ins_permuted", + attr => "bool ins_permuted", init_attr => "attr->attr.data.ins_permuted = ins_permuted;", latency => 3, units => [ "VFP" ], @@ -2334,7 +2299,7 @@ vFucomi => { reg_req => { in => [ "vfp", "vfp" ], out => [ "eflags" ] }, ins => [ "left", "right" ], outs => [ "flags" ], - attr => "int ins_permuted", + attr => "bool ins_permuted", init_attr => "attr->attr.data.ins_permuted = ins_permuted;", latency => 3, units => [ "VFP" ], @@ -2347,7 +2312,7 @@ vFtstFnstsw => { reg_req => { in => [ "vfp" ], out => [ "eax" ] }, ins => [ "left" ], outs => [ "flags" ], - attr => "int ins_permuted", + attr => "bool ins_permuted", init_attr => "attr->attr.data.ins_permuted = ins_permuted;", latency => 3, units => [ "VFP" ],