X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_spec.pl;h=9201aeb163a13b8c4cec24389f244110ae4bc3d5;hb=792661421a71bcfa9b64da8c6b655e826e94d2c1;hp=5a3d2a13f2f504f88bfd4ae5c62eb7152709059a;hpb=e87ac5865f7932014b7434960085b0bc04dbf6bb;p=libfirm diff --git a/ir/be/arm/arm_spec.pl b/ir/be/arm/arm_spec.pl index 5a3d2a13f..9201aeb16 100644 --- a/ir/be/arm/arm_spec.pl +++ b/ir/be/arm/arm_spec.pl @@ -1,959 +1,548 @@ -# Creation: 2006/02/13 -# $Id$ -# This is a template specification for the Firm-Backend - -# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...) +# Arm Architecure Specification +# Author: Matthias Braun, Michael Beck, Oliver Richter, Tobias Gneist $arch = "arm"; -$new_emit_syntax = 1; - -# the number of additional opcodes you want to register -#$additional_opcodes = 0; - -# 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", -# irn_flags => "R|N|I|S" -# 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", -# emit => "emit code with templates", -# attr => "attitional attribute arguments for constructor" -# init_attr => "emit attribute initialization template" -# rd_constructor => "c source code which constructs an ir_node" -# latency => "latency of this operation (can be float)" -# attr_type => "name of the attribute struct", -# }, -# -# ... # (all nodes you need to describe) -# -# ); # close the %nodes initializer - -# op_flags: flags for the operation, OPTIONAL (default is "N") -# the op_flags correspond to the firm irop_flags: -# N irop_flag_none -# L irop_flag_labeled -# C irop_flag_commutative -# X irop_flag_cfopcode -# I irop_flag_ip_cfopcode -# F irop_flag_fragile -# Y irop_flag_forking -# H irop_flag_highlevel -# c irop_flag_constlike -# K irop_flag_keep -# -# irn_flags: special node flags, OPTIONAL (default is 0) -# following irn_flags are supported: -# R rematerializeable -# N not spillable -# I ignore for register allocation -# S modifies stack pointer -# -# state: state of the operation, OPTIONAL (default is "floats") -# -# 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 -# One can also annotate some flags for each out, additional to irn_flags. -# They are separated from name with a colon ':', and concatenated by pipe '|' -# Only I and S are available at the moment (same meaning as in irn_flags). -# example: [ "frame:I", "stack:I|S", "M" ] -# -# 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 -# -# latency: the latency of the operation, default is 1 -# # # Modes # -$mode_gp = "mode_Iu"; -$mode_fpa = "mode_E"; - -# 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 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 +$mode_gp = "mode_Iu"; +$mode_flags = "mode_Bu"; +$mode_fp = "mode_F"; + # NOTE: Last entry of each class is the largest Firm-Mode a register can hold %reg_classes = ( gp => [ - { "name" => "r0", "type" => 1 }, - { "name" => "r1", "type" => 1 }, - { "name" => "r2", "type" => 1 }, - { "name" => "r3", "type" => 1 }, - { "name" => "r4", "type" => 2 }, - { "name" => "r5", "type" => 2 }, - { "name" => "r6", "type" => 2 }, - { "name" => "r7", "type" => 2 }, - { "name" => "r8", "type" => 2 }, - { "name" => "r9", "type" => 2 }, - { "name" => "r10", "type" => 2 }, - { "name" => "r11", "type" => 2 }, - { "name" => "r12", "type" => 6 }, # reserved for linker - { "name" => "sp", "type" => 6 }, # this is our stack pointer - { "name" => "lr", "type" => 3 }, # this is our return address - { "name" => "pc", "type" => 6 }, # this is our program counter - { name => "gp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes - { "mode" => $mode_gp } + { name => "r0", dwarf => 0 }, + { name => "r1", dwarf => 1 }, + { name => "r2", dwarf => 2 }, + { name => "r3", dwarf => 3 }, + { name => "r4", dwarf => 4 }, + { name => "r5", dwarf => 5 }, + { name => "r6", dwarf => 6 }, + { name => "r7", dwarf => 7 }, + { name => "r8", dwarf => 8 }, + { name => "r9", dwarf => 9 }, + { name => "r10", dwarf => 10 }, + { name => "r11", dwarf => 11 }, + { name => "r12", dwarf => 12 }, + { name => "sp", dwarf => 13 }, + { name => "lr", dwarf => 14 }, + { name => "pc", dwarf => 15 }, + { mode => $mode_gp } + ], + fpa => [ + { name => "f0", dwarf => 96 }, + { name => "f1", dwarf => 97 }, + { name => "f2", dwarf => 98 }, + { name => "f3", dwarf => 99 }, + { name => "f4", dwarf => 100 }, + { name => "f5", dwarf => 101 }, + { name => "f6", dwarf => 102 }, + { name => "f7", dwarf => 103 }, + { mode => $mode_fp } + ], + flags => [ + { name => "fl" }, + { mode => $mode_flags, flags => "manual_ra" } ], - fpa => [ - { "name" => "f0", "type" => 1 }, - { "name" => "f1", "type" => 1 }, - { "name" => "f2", "type" => 1 }, - { "name" => "f3", "type" => 1 }, - { "name" => "f4", "type" => 1 }, - { "name" => "f5", "type" => 1 }, - { "name" => "f6", "type" => 1 }, - { "name" => "f7", "type" => 1 }, - { name => "fpa_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes - { "mode" => $mode_fpa } - ] -); # %reg_classes - -%emit_templates = ( - M => "${arch}_emit_mode(env, node);", - X => "${arch}_emit_shift(env, node);", - 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);", - D0 => "${arch}_emit_dest_register(env, node, 0);", - D1 => "${arch}_emit_dest_register(env, node, 1);", - D2 => "${arch}_emit_dest_register(env, node, 2);", - C => "${arch}_emit_immediate(env, node);", - O => "${arch}_emit_offset(env, mode);", ); -#--------------------------------------------------# -# _ # -# (_) # -# _ __ _____ __ _ _ __ ___ _ __ ___ # -# | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| # -# | | | | __/\ V V / | | | | (_) | |_) \__ \ # -# |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ # -# | | # -# |_| # -#--------------------------------------------------# - $default_attr_type = "arm_attr_t"; $default_copy_attr = "arm_copy_attr"; %init_attr = ( - arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);", - arm_SymConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);", - arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);", - arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);", + arm_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);", + arm_SymConst_attr_t => + "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n". + "\tinit_arm_SymConst_attributes(res, entity, symconst_offset);", + arm_CondJmp_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);", + arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);", + arm_fConst_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);", + arm_load_store_attr_t => + "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n". + "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);", + arm_shifter_operand_t => + "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n", + arm_cmp_attr_t => + "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n", + arm_farith_attr_t => + "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n". + "\tinit_arm_farith_attributes(res, op_mode);", + arm_CopyB_attr_t => + "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n". + "\tinit_arm_CopyB_attributes(res, size);", ); %compare_attr = ( - arm_attr_t => "cmp_attr_arm", - arm_SymConst_attr_t => "cmp_attr_arm_SymConst", - arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp", - arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp", + arm_attr_t => "cmp_attr_arm", + arm_SymConst_attr_t => "cmp_attr_arm_SymConst", + arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp", + arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp", + arm_fConst_attr_t => "cmp_attr_arm_fConst", + arm_load_store_attr_t => "cmp_attr_arm_load_store", + arm_shifter_operand_t => "cmp_attr_arm_shifter_operand", + arm_CopyB_attr_t => "cmp_attr_arm_CopyB", + arm_cmp_attr_t => "cmp_attr_arm_cmp", + arm_farith_attr_t => "cmp_attr_arm_farith", ); -#%operands = ( -# -#Immediate => { -# comment => "blup di dup", -# irn_flags => "R", -# emit => ". [%S0]-10", -# reg_req => { }, -# attr => "tarval *tv", -# init_attr => "(void) attri;", -# # op_flags => O -# # cmp => "return 1;" -#}, -# -#ShfOp_I => { -# irn_flags => "R", -# emit => ". ...", -# reg_req => { in => [ "gp" ] }, -# attr => "tarval *tv", -# init_attr => "(void) tv;", -#}, -# -#ShfOp => { -# irn_flags => "R", -# emit => ". ...", -# reg_req => { in => [ "gp", "gp" ] }, -#}, -# -#); +my %unop_shifter_operand_constructors = ( + imm => { + attr => "unsigned char immediate_value, unsigned char immediate_rot", + custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);", + reg_req => { in => [], out => [ "gp" ] }, + }, + reg => { + custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);", + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + }, + reg_shift_reg => { + attr => "arm_shift_modifier_t shift_modifier", + custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);", + reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, + }, + reg_shift_imm => { + attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate", + custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);", + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + }, +); -%nodes = ( +my %binop_shifter_operand_constructors = ( + imm => { + attr => "unsigned char immediate_value, unsigned char immediate_rot", + custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);", + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + ins => [ "left" ], + }, + reg => { + custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);", + reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, + ins => [ "left", "right" ], + }, + reg_shift_reg => { + attr => "arm_shift_modifier_t shift_modifier", + custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);", + reg_req => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] }, + ins => [ "left", "right", "shift" ], + }, + reg_shift_imm => { + attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate", + custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);", + reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] }, + ins => [ "left", "right" ], + }, +); -Unknown_GP => { - state => "pinned", - op_flags => "c", - irn_flags => "I", - reg_req => { out => [ "gp_UKNWN" ] }, - emit => "", - mode => $mode_gp, -}, +my %cmp_shifter_operand_constructors = ( + imm => { + attr => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned", + custominit => + "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n". + "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);", + reg_req => { in => [ "gp" ], out => [ "flags" ] }, + ins => [ "left" ], + }, + reg => { + attr => "bool ins_permuted, bool is_unsigned", + custominit => + "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n". + "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);", + reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] }, + ins => [ "left", "right" ], + }, + reg_shift_reg => { + attr => "arm_shift_modifier_t shift_modifier, bool ins_permuted, bool is_unsigned", + custominit => + "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n". + "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);", + reg_req => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] }, + ins => [ "left", "right", "shift" ], + }, + reg_shift_imm => { + attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned", + custominit => + "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n". + "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);", + reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] }, + ins => [ "left", "right" ], + }, +); -Unknown_FPA => { - state => "pinned", - op_flags => "c", - irn_flags => "I", - reg_req => { out => [ "fpa_UKNWN" ] }, - emit => "", - mode => $mode_fpa, -}, - -#-----------------------------------------------------------------# -# _ _ _ # -# (_) | | | | # -# _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ # -# | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| # -# | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ # -# |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ # -# __/ | # -# |___/ # -#-----------------------------------------------------------------# - -# commutative operations + +%nodes = ( Add => { - op_flags => "C", - irn_flags => "R", - comment => "construct Add: Add(a, b) = Add(b, a) = a + b", - attr => "arm_shift_modifier mod, tarval *shf", - init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - emit => '. add %D0, %S0, %S1%X' -}, - -Add_i => { - irn_flags => "R", - comment => "construct Add: Add(a, const) = Add(const, a) = a + const", - attr => "tarval *tv", - init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - cmp_attr => 'return attr_a->value != attr_b->value;', - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - emit => '. add %D0, %S0, %C' + irn_flags => [ "rematerializable" ], + emit => 'add %D0, %S0, %O', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, }, Mul => { - #op_flags => "C", - irn_flags => "R", - comment => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] }, - emit =>'. mul %D0, %S0, %S1' + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] }, + emit => 'mul %D0, %S0, %S1', + mode => $mode_gp, }, Smull => { - #op_flags => "C", - irn_flags => "R", - comment => "construct signed 64bit Mul: Mul(a, b) = Mul(b, a) = a * b", - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] }, - emit =>'. smull %D0, %D1, %S0, %S1', + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] }, + emit => 'smull %D0, %D1, %S0, %S1', outs => [ "low", "high" ], }, Umull => { - #op_flags => "C", - irn_flags => "R", - comment => "construct unsigned 64bit Mul: Mul(a, b) = Mul(b, a) = a * b", - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp", "gp" ] }, - emit =>'. umull %D0, %D1, %S0, %S1', + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] }, + emit =>'umull %D0, %D1, %S0, %S1', outs => [ "low", "high" ], + mode => $mode_gp, }, Mla => { - #op_flags => "C", - irn_flags => "R", - comment => "construct Mla: Mla(a, b, c) = a * b + c", - reg_req => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] }, - emit =>'. mla %D0, %S0, %S1, %S2' + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] }, + emit =>'mla %D0, %S0, %S1, %S2', + mode => $mode_gp, }, And => { - op_flags => "C", - irn_flags => "R", - comment => "construct And: And(a, b) = And(b, a) = a AND b", - attr => "arm_shift_modifier mod, tarval *shf", - init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - emit => '. and %D0, %S0, %S1%X' -}, - -And_i => { - irn_flags => "R", - comment => "construct And: And(a, const) = And(const, a) = a AND const", - attr => "tarval *tv", - init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - emit => '. and %D0, %S0, %C', - cmp_attr => 'return attr_a->value != attr_b->value;' + irn_flags => [ "rematerializable" ], + emit => 'and %D0, %S0, %O', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, }, Or => { - op_flags => "C", - irn_flags => "R", - comment => "construct Or: Or(a, b) = Or(b, a) = a OR b", - attr => "arm_shift_modifier mod, tarval *shf", - init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - emit => '. orr %D0, %S0, %S1%X' -}, - -Or_i => { - irn_flags => "R", - comment => "construct Or: Or(a, const) = Or(const, a) = a OR const", - attr => "tarval *tv", - init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - cmp_attr => 'return attr_a->value != attr_b->value;', - emit => '. orr %D0, %S0, %C' + irn_flags => [ "rematerializable" ], + emit => 'orr %D0, %S0, %O', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, }, Eor => { - op_flags => "C", - irn_flags => "R", - comment => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b", - attr => "arm_shift_modifier mod, tarval *shf", - init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - emit => '. eor %D0, %S0, %S1%X' -}, - -Eor_i => { - irn_flags => "R", - comment => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const", - attr => "tarval *tv", - init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - cmp_attr => 'return attr_a->value != attr_b->value;', - emit => '. eor %D0, %S0, %C' + irn_flags => [ "rematerializable" ], + emit => 'eor %D0, %S0, %O', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, }, -# not commutative operations - Bic => { - irn_flags => "R", - comment => "construct Bic: Bic(a, b) = a AND ~b", - attr => "arm_shift_modifier mod, tarval *shf", - init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - emit => '. bic %D0, %S0, %S1%X' -}, - -Bic_i => { - irn_flags => "R", - comment => "construct Bic: Bic(a, const) = a AND ~const", - attr => "tarval *tv", - init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - emit => '. bic %D0, %S0, %C', - cmp_attr => 'return attr_a->value != attr_b->value;' + irn_flags => [ "rematerializable" ], + emit => 'bic %D0, %S0, %O', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, }, Sub => { - irn_flags => "R", - comment => "construct Sub: Sub(a, b) = a - b", - attr => "arm_shift_modifier mod, tarval *shf", - init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - emit => '. sub %D0, %S0, %S1%X' -}, - -Sub_i => { - irn_flags => "R", - comment => "construct Sub: Sub(a, const) = a - const", - attr => "tarval *tv", - init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - cmp_attr => 'return attr_a->value != attr_b->value;', - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - emit => '. sub %D0, %S0, %C', + irn_flags => [ "rematerializable" ], + emit => 'sub %D0, %S0, %O', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, }, Rsb => { - irn_flags => "R", - comment => "construct Rsb: Rsb(a, b) = b - a", - attr => "arm_shift_modifier mod, tarval *shf", - init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - emit => '. rsb %D0, %S0, %S1%X' -}, - -Rsb_i => { - irn_flags => "R", - comment => "construct Rsb: Rsb(a, const) = const - a", - attr => "tarval *tv", - init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - emit => '. rsb %D0, %S0, %C', - cmp_attr => 'return attr_a->value != attr_b->value;' -}, - -Shl => { - irn_flags => "R", - comment => "construct Shl: Shl(a, b) = a << b", - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - emit => '. mov %D0, %S0, lsl %S1' -}, - -Shr => { - irn_flags => "R", - comment => "construct Shr: Shr(a, b) = a >> b", - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, - emit => '. mov %D0, %S0, lsr %S1' -}, - -Shrs => { - irn_flags => "R", - comment => "construct Shrs: Shrs(a, b) = a >> b", - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, - emit => '. mov %D0, %S0, asr %S1' -}, - -#RotR => { -# irn_flags => "R", -# comment => "construct RotR: RotR(a, b) = a ROTR b", -# reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, -# emit => '. mov %D0, %S0, ror %S1 /* RotR(%S0, %S1) -> %D0, (%A1, %A2) */' -## emit => '. ror %S0, %S1, %D0' -#}, - -#RotL => { -# irn_flags => "R", -# comment => "construct RotL: RotL(a, b) = a ROTL b", -# reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, -# emit => '. rol %S0, %S1, %D0' -#}, - -#RotL_i => { -# irn_flags => "R", -# comment => "construct RotL: RotL(a, const) = a ROTL const", -# reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, -# emit => '. rol %S0, %C, %D0' -#}, - -Mov => { - irn_flags => "R", - comment => "construct Mov: a = b", - attr => "arm_shift_modifier mod, tarval *shf", - init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - emit => '. mov %D0, %S0%X' + irn_flags => [ "rematerializable" ], + emit => 'rsb %D0, %S0, %O', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, }, -Mov_i => { - irn_flags => "R", - comment => "represents an integer constant", - attr => "tarval *tv", - init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - reg_req => { "out" => [ "gp" ] }, - emit => '. mov %D0, %C', - cmp_attr => 'return attr_a->value != attr_b->value;' +Mov => { + irn_flags => [ "rematerializable" ], + arity => "variable", + emit => 'mov %D0, %O', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%unop_shifter_operand_constructors, }, Mvn => { - irn_flags => "R", - comment => "construct Not: Not(a) = !a", - attr => "arm_shift_modifier mod, tarval *shf", - init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - emit => '. mvn %D0, %S0%X' + irn_flags => [ "rematerializable" ], + attr_type => "arm_shifter_operand_t", + arity => "variable", + emit => 'mvn %D0, %O', + mode => $mode_gp, + constructors => \%unop_shifter_operand_constructors, }, -Mvn_i => { - irn_flags => "R", - comment => "represents a negated integer constant", - attr => "tarval *tv", - init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - cmp_attr => 'return attr_a->value != attr_b->value;', - reg_req => { "out" => [ "gp" ] }, - emit => '. mvn %D0, %C', +Clz => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + emit => 'clz %D0, %S0', + mode => $mode_gp, }, -Abs => { - irn_flags => "R", - comment => "construct Abs: Abs(a) = |a|", - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, - emit => -'. movs %S0, %S0, #0 -. rsbmi %D0, %S0, #0' +# mov lr, pc\n mov pc, XXX -- This combination is used for calls to function +# pointers +LinkMovPC => { + state => "exc_pinned", + arity => "variable", + out_arity => "variable", + attr_type => "arm_shifter_operand_t", + attr => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot", + custominit => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n". + "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);", + emit => "mov lr, pc\n". + "mov pc, %O", +}, + +# mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function +# pointers +LinkLdrPC => { + state => "exc_pinned", + arity => "variable", + out_arity => "variable", + attr_type => "arm_load_store_attr_t", + attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", + custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);", + emit => "mov lr, pc\n". + "ldr pc, %O", +}, + +Bl => { + state => "exc_pinned", + arity => "variable", + out_arity => "variable", + attr_type => "arm_SymConst_attr_t", + attr => "ir_entity *entity, int symconst_offset", + custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);", + emit => 'bl %I', }, -# other operations - -# # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd -# EmptyReg => { - op_flags => "c", - irn_flags => "R", - comment => "allocate an empty register for calculations", - reg_req => { "out" => [ "gp" ] }, - emit => '. /* %D0 now available for calculations */', - cmp_attr => 'return 1;' -}, - -Copy => { - comment => "implements a register copy", - reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] }, + op_flags => [ "constlike" ], + irn_flags => [ "rematerializable" ], + reg_req => { out => [ "gp" ] }, + emit => '/* %D0 now available for calculations */', + cmp_attr => 'return 1;', + mode => $mode_gp, }, CopyB => { - op_flags => "F|H", state => "pinned", - comment => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)", - attr => "tarval *tv", - init_attr => 'attr->value = tv;', - reg_req => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] }, + attr => "unsigned size", + attr_type => "arm_CopyB_attr_t", + reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] }, outs => [ "M" ], }, -SymConst => { - op_flags => "c", - irn_flags => "R", - comment => "represents a symbolic constant", - attr => "ident *id", - init_attr => "\tset_arm_symconst_id(res, id);", - reg_req => { "out" => [ "gp" ] }, - attr_type => "arm_SymConst_attr_t", +FrameAddr => { + op_flags => [ "constlike" ], + irn_flags => [ "rematerializable" ], + attr => "ir_entity *entity, int symconst_offset", + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + ins => [ "base" ], + attr_type => "arm_SymConst_attr_t", + mode => $mode_gp, }, -CmpBra => { - op_flags => "L|X|Y", - state => "pinned", - comment => "construct conditional branch: CMP A, B && JMPxx LABEL", - mode => "mode_T", - attr => "int proj_num", - init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", - reg_req => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] }, - attr_type => "arm_CondJmp_attr_t", +SymConst => { + op_flags => [ "constlike" ], + irn_flags => [ "rematerializable" ], + attr => "ir_entity *entity, int symconst_offset", + reg_req => { out => [ "gp" ] }, + attr_type => "arm_SymConst_attr_t", + mode => $mode_gp, }, -SwitchJmp => { - op_flags => "L|X|Y", - state => "pinned", - comment => "construct switch", - mode => "mode_T", - attr => "int n_projs, long def_proj_num", - init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n". - "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);", - reg_req => { "in" => [ "gp" ], "out" => [ "none" ] }, - attr_type => "arm_SwitchJmp_attr_t", +Cmp => { + irn_flags => [ "rematerializable", "modify_flags" ], + emit => 'cmp %S0, %O', + mode => $mode_flags, + attr_type => "arm_cmp_attr_t", + constructors => \%cmp_shifter_operand_constructors, }, -# Load / Store - -Load => { - op_flags => "L|F", - irn_flags => "R", - state => "exc_pinned", - comment => "construct Load: Load(ptr, mem) = LD ptr -> reg", - reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] }, - emit => '. ldr %D0, [%S0, #0]', - outs => [ "res", "M" ], +Tst => { + irn_flags => [ "rematerializable", "modify_flags" ], + emit => 'tst %S0, %O', + mode => $mode_flags, + attr_type => "arm_cmp_attr_t", + constructors => \%cmp_shifter_operand_constructors, }, -Loadb => { - op_flags => "L|F", - irn_flags => "R", - state => "exc_pinned", - comment => "construct Load: Load(ptr, mem) = LD ptr -> reg", - reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] }, - emit => '. ldrb %D0, [%S0, #0]', - outs => [ "res", "M" ], +B => { + op_flags => [ "cfopcode", "forking" ], + state => "pinned", + mode => "mode_T", + reg_req => { in => [ "flags" ], out => [ "none", "none" ] }, + attr => "ir_relation relation", + attr_type => "arm_CondJmp_attr_t", + init_attr => "\tset_arm_CondJmp_relation(res, relation);", }, -Loadbs => { - op_flags => "L|F", - irn_flags => "R", - state => "exc_pinned", - comment => "construct Load: Load(ptr, mem) = LD ptr -> reg", - reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] }, - emit => '. ldrsb %D0, [%S0, #0]', - outs => [ "res", "M" ], +Jmp => { + state => "pinned", + op_flags => [ "cfopcode" ], + irn_flags => [ "simple_jump" ], + reg_req => { out => [ "none" ] }, + mode => "mode_X", }, -Loadh => { - op_flags => "L|F", - irn_flags => "R", - state => "exc_pinned", - comment => "construct Load: Load(ptr, mem) = LD ptr -> reg", - reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] }, - emit => '. ldrh %D0, [%S0, #0]', - outs => [ "res", "M" ], +SwitchJmp => { + op_flags => [ "cfopcode", "forking" ], + state => "pinned", + mode => "mode_T", + attr => "const ir_switch_table *table", + init_attr => "init_arm_SwitchJmp_attributes(res, table);", + reg_req => { in => [ "gp" ], out => [ "none" ] }, + out_arity => "variable", + attr_type => "arm_SwitchJmp_attr_t", }, -Loadhs => { - op_flags => "L|F", - irn_flags => "R", +Ldr => { + op_flags => [ "uses_memory" ], state => "exc_pinned", - comment => "construct Load: Load(ptr, mem) = LD ptr -> reg", - reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] }, - emit => '. ldrsh %D0, [%S0, #0]', + ins => [ "ptr", "mem" ], outs => [ "res", "M" ], + reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] }, + emit => 'ldr%ML %D0, [%S0, #%o]', + attr_type => "arm_load_store_attr_t", + attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", }, -Storeb => { - op_flags => "L|F", - irn_flags => "R", +Str => { + op_flags => [ "uses_memory" ], state => "exc_pinned", - comment => "construct Store: Store(ptr, val, mem) = ST ptr,val", - reg_req => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] }, - emit => '. strb %S1, [%S0, #0]', - mode => "mode_M", -}, - -Storeh => { - op_flags => "L|F", - irn_flags => "R", - state => "exc_pinned", - comment => "construct Store: Store(ptr, val, mem) = ST ptr,val", - reg_req => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] }, - emit => '. strh %S1, [%S0, #0]', - mode => "mode_M", -}, - -Store => { - op_flags => "L|F", - irn_flags => "R", - state => "exc_pinned", - comment => "construct Store: Store(ptr, val, mem) = ST ptr,val", - reg_req => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] }, - emit => '. str %S1, [%S0, #0]', + ins => [ "ptr", "val", "mem" ], + outs => [ "M" ], + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + emit => 'str%MS %S1, [%S0, #%o]', mode => "mode_M", + attr_type => "arm_load_store_attr_t", + attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", }, StoreStackM4Inc => { - op_flags => "L|F", - irn_flags => "R", + op_flags => [ "uses_memory" ], + irn_flags => [ "rematerializable" ], state => "exc_pinned", - comment => "construct Store: Store(ptr, val, mem) = ST ptr,val", - reg_req => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "gp", "none" ] }, - emit => '. stmfd %S0!, {%S1, %S2, %S3, %S4}', + reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] }, + emit => 'stmfd %S0!, {%S1, %S2, %S3, %S4}', outs => [ "ptr", "M" ], }, -LoadStackM3 => { - op_flags => "L|F", - irn_flags => "R", +LoadStackM3Epilogue => { + op_flags => [ "uses_memory" ], + irn_flags => [ "rematerializable" ], state => "exc_pinned", - comment => "construct Load: Load(ptr, mem) = LD ptr -> reg", - reg_req => { "in" => [ "sp", "none" ], "out" => [ "gp", "gp", "gp", "none" ] }, - emit => '. ldmfd %S0, {%D0, %D1, %D2}', + reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] }, + emit => 'ldmfd %S0, {%D0, %D1, %D2}', outs => [ "res0", "res1", "res2", "M" ], }, -#---------------------------------------------------# -# __ _ # -# / _| | | # -# | |_ _ __ __ _ _ __ ___ __| | ___ ___ # -# | _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __| # -# | | | |_) | (_| | | | | | (_) | (_| | __/\__ \ # -# |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/ # -# | | # -# |_| # -#---------------------------------------------------# - -# commutative operations - -fpaAdd => { - op_flags => "C", - irn_flags => "R", - comment => "construct FPA Add: Add(a, b) = Add(b, a) = a + b", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - emit => '. adf%M %D0, %S0, %S1', -}, - -fpaMul => { - op_flags => "C", - comment => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - emit =>'. muf%M %D0, %S0, %S1', -}, - -fpaFMul => { - op_flags => "C", - comment => "construct FPA Fast Mul: Mul(a, b) = Mul(b, a) = a * b", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - emit =>'. fml%M %D0, %S0, %S1', -}, - -fpaMax => { - op_flags => "C", - irn_flags => "R", - comment => "construct FPA Max: Max(a, b) = Max(b, a) = a > b ? a : b", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - emit =>'. fmax %S0, %S1, %D0', -}, - -fpaMin => { - op_flags => "C", - irn_flags => "R", - comment => "construct FPA Min: Min(a, b) = Min(b, a) = a < b ? a : b", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - emit =>'. fmin %S0, %S1, %D0', -}, - -# not commutative operations -fpaSub => { - irn_flags => "R", - comment => "construct FPA Sub: Sub(a, b) = a - b", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - emit => '. suf%M %D0, %S0, %S1' -}, - -fpaRsb => { - irn_flags => "R", - comment => "construct FPA reverse Sub: Sub(a, b) = b - a", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - emit => '. rsf%M %D0, %S0, %S1' -}, - -fpaDiv => { - comment => "construct FPA Div: Div(a, b) = a / b", +Adf => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit => 'adf%MA %D0, %S0, %S1', + attr_type => "arm_farith_attr_t", attr => "ir_mode *op_mode", - init_attr => "attr->op_mode = op_mode;", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, - emit =>'. dvf%M %D0, %S0, %S1', - outs => [ "res", "M" ], + mode => $mode_fp, }, -fpaRdv => { - comment => "construct FPA reverse Div: Div(a, b) = b / a", +Muf => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit => 'muf%MA %D0, %S0, %S1', + attr_type => "arm_farith_attr_t", attr => "ir_mode *op_mode", - init_attr => "attr->op_mode = op_mode;", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, - emit =>'. rdf%M %D0, %S0, %S1', - outs => [ "res", "M" ], + mode => $mode_fp, }, -fpaFDiv => { - comment => "construct FPA Fast Div: Div(a, b) = a / b", +Suf => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit => 'suf%MA %D0, %S0, %S1', + attr_type => "arm_farith_attr_t", attr => "ir_mode *op_mode", - init_attr => "attr->op_mode = op_mode;", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, - emit =>'. fdv%M %D0, %S0, %S1', - outs => [ "res", "M" ], + mode => $mode_fp, }, -fpaFRdv => { - comment => "construct FPA Fast reverse Div: Div(a, b) = b / a", - attr => "ir_mode *op_mode", - init_attr => "attr->op_mode = op_mode;", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, - emit =>'. frd%M %D0, %S0, %S1', +Dvf => { + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] }, + emit => 'dvf%MA %D0, %S0, %S1', outs => [ "res", "M" ], + attr_type => "arm_farith_attr_t", + attr => "ir_mode *op_mode", + mode => $mode_fp, }, -fpaMov => { - irn_flags => "R", - comment => "construct FPA Move: b = a", - reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, - emit => '. mvf%M %S0, %D0', -}, - -fpaMnv => { - irn_flags => "R", - comment => "construct FPA Move Negated: b = -a", - reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, - emit => '. mnf%M %S0, %D0', -}, - -fpaAbs => { - irn_flags => "R", - comment => "construct FPA Absolute value: fAbsd(a) = |a|", - reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, - emit => '. abs%M %D0, %S0', -}, - -# other operations - -fpaFlt => { - irn_flags => "R", - comment => "construct a FPA integer->float conversion", - reg_req => { "in" => ["gp"], "out" => [ "fpa" ] }, - emit => '. flt%M %D0, %S0', -}, - -fpaFix => { - irn_flags => "R", - comment => "construct a FPA float->integer conversion", - reg_req => { "in" => ["fpa"], "out" => [ "gp" ] }, - emit => '. fix %D0, %S0', -}, - -fpaCmfBra => { - op_flags => "L|X|Y", - state => "pinned", - comment => "construct floating point Compare and Branch: CMF A, B && JMPxx LABEL", - mode => "mode_T", - attr => "int proj_num", - init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] }, - attr_type => "arm_CondJmp_attr_t", -}, - -fpaCnfBra => { - op_flags => "L|X|Y", - state => "pinned", - comment => "construct floating point Compare negative and Branch: CMF A, -B && JMPxx LABEL", - mode => "mode_T", - attr => "int proj_num", - init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] }, - attr_type => "arm_CondJmp_attr_t", +Mvf => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "fpa" ], out => [ "fpa" ] }, + emit => 'mvf%MA %S0, %D0', + attr_type => "arm_farith_attr_t", + attr => "ir_mode *op_mode", + mode => $mode_fp, }, -fpaCmfeBra => { - op_flags => "L|X|Y", - state => "pinned", - comment => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL", - mode => "mode_T", - attr => "int proj_num", - init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] }, - attr_type => "arm_CondJmp_attr_t", +FltX => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp" ], out => [ "fpa" ] }, + emit => 'flt%MA %D0, %S0', + attr_type => "arm_farith_attr_t", + attr => "ir_mode *op_mode", + mode => $mode_fp, }, -fpaCnfeBra => { - op_flags => "L|X|Y", - state => "pinned", - comment => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL", - mode => "mode_T", - attr => "int proj_num", - init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", - reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] }, - attr_type => "arm_CondJmp_attr_t", +Cmfe => { + irn_flags => [ "rematerializable", "modify_flags" ], + mode => $mode_flags, + attr_type => "arm_cmp_attr_t", + attr => "bool ins_permuted", + init_attr => "init_arm_cmp_attr(res, ins_permuted, false);", + reg_req => { in => [ "fpa", "fpa" ], out => [ "flags" ] }, + emit => 'cmfe %S0, %S1', }, -# Load / Store - -fpaLdf => { - op_flags => "L|F", - irn_flags => "R", +Ldf => { + op_flags => [ "uses_memory" ], state => "exc_pinned", - comment => "construct FPA Load: Load(ptr, mem) = LD ptr", - attr => "ir_mode *op_mode", - init_attr => "attr->op_mode = op_mode;", - reg_req => { "in" => [ "gp", "none" ], "out" => [ "fpa", "none" ] }, - emit => '. ldf%M %D0, [%S0]', + ins => [ "ptr", "mem" ], outs => [ "res", "M" ], + reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] }, + emit => 'ldf%MF %D0, [%S0, #%o]', + attr_type => "arm_load_store_attr_t", + attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", }, -fpaStf => { - op_flags => "L|F", - irn_flags => "R", +Stf => { + op_flags => [ "uses_memory" ], state => "exc_pinned", - comment => "construct Store: Store(ptr, val, mem) = ST ptr,val", - attr => "ir_mode *op_mode", - init_attr => "attr->op_mode = op_mode;", - reg_req => { "in" => [ "gp", "fpa", "none" ], "out" => [ "none" ] }, - emit => '. stf%M %S1, [%S0]', + ins => [ "ptr", "val", "mem" ], + outs => [ "M" ], mode => "mode_M", + reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] }, + emit => 'stf%MF %S1, [%S0, #%o]', + attr_type => "arm_load_store_attr_t", + attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", }, -fpaDbl2GP => { - op_flags => "L|F", - irn_flags => "R", - comment => "construct fp double to 2 gp register transfer", - reg_req => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp", "none" ] }, - outs => [ "low", "high", "M" ], -}, - -AddSP => { - irn_flags => "I", - comment => "construct Add to stack pointer", - reg_req => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] }, - emit => '. add %D0, %S0, %S1', - outs => [ "stack:S", "M" ], -}, - -SubSP => { - irn_flags => "I", - comment => "construct Sub from stack pointer", - reg_req => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] }, - emit => '. sub %D0, %S0, %S1', - outs => [ "stack:S", "M" ], -}, - -LdTls => { - irn_flags => "R", - comment => "load the TLS address", - reg_req => { out => [ "gp" ] }, -}, - - # # floating point constants # -fpaConst => { - op_flags => "c", - irn_flags => "R", - comment => "construct a floating point constant", - attr => "tarval *tv", - init_attr => "attr->value = tv;", +fConst => { + op_flags => [ "constlike" ], + irn_flags => [ "rematerializable" ], + attr => "ir_tarval *tv", + init_attr => "attr->tv = tv;", mode => "get_tarval_mode(tv)", - reg_req => { "out" => [ "fpa" ] }, + reg_req => { out => [ "fpa" ] }, + attr_type => "arm_fConst_attr_t", } -#---------------------------------------------------# -# __ _ # -# / _| | | # -# __ _| |_ _ __ _ __ ___ __| | ___ ___ # -# \ \ / / _| '_ \ | '_ \ / _ \ / _` |/ _ \/ __| # -# \ V /| | | |_) | | | | | (_) | (_| | __/\__ \ # -# \_/ |_| | .__/ |_| |_|\___/ \__,_|\___||___/ # -# | | # -# |_| # -#---------------------------------------------------# - ); # end of %nodes