X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_spec.pl;h=968b36443d7da36a61ca4e82f72532d362aa945f;hb=72fca46dfebc45e1c8466d0b7035a68b9d1495fe;hp=68d3b6f7a4d47979fab06b36c4ce1654b5bdd818;hpb=d11d8b4831db166f01b115a218e26e17091f898f;p=libfirm diff --git a/ir/be/arm/arm_spec.pl b/ir/be/arm/arm_spec.pl index 68d3b6f7a..968b36443 100644 --- a/ir/be/arm/arm_spec.pl +++ b/ir/be/arm/arm_spec.pl @@ -1,804 +1,643 @@ # Creation: 2006/02/13 # $Id$ -# This is a template specification for the Firm-Backend # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...) $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" -# "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" -# }, -# -# ... # (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 -# -# 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 # -# comment: OPTIONAL comment for the node constructor +# Modes # -# 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 +$mode_gp = "mode_Iu"; +$mode_flags = "mode_Bu"; +$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) +$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" => "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", "realname" => "r13", "type" => 6 }, # this is our stack pointer - { "name" => "lr", "realname" => "r14", "type" => 3 }, # this is our return address - { "name" => "pc", "realname" => "r15", "type" => 6 }, # this is our program counter - { "mode" => "mode_Iu" } - ], - "fpa" => [ - { "name" => "f0", "type" => 1 }, - { "name" => "f1", "type" => 1 }, - { "name" => "f2", "type" => 1 }, - { "name" => "f3", "type" => 1 }, - { "name" => "f4", "type" => 2 }, - { "name" => "f5", "type" => 2 }, - { "name" => "f6", "type" => 2 }, - { "name" => "f7", "type" => 2 }, - { "mode" => "mode_E" } - ] -); # %reg_classes + gp => [ + { name => "r0", type => $caller_save }, + { name => "r1", type => $caller_save }, + { name => "r2", type => $caller_save }, + { name => "r3", type => $caller_save }, + { name => "r4", type => $callee_save }, + { name => "r5", type => $callee_save }, + { name => "r6", type => $callee_save }, + { name => "r7", type => $callee_save }, + { name => "r8", type => $callee_save }, + { name => "r9", type => $callee_save }, + { name => "r10", type => $callee_save }, + { name => "r11", type => $callee_save }, + { name => "r12", type => $ignore }, # reserved for linker/immediate fixups + { name => "sp", type => $ignore }, # this is our stack pointer + { name => "lr", type => $callee_save | $caller_save }, # this is our return address + { name => "pc", type => $ignore }, # this is our program counter + { mode => $mode_gp } + ], + fpa => [ + { name => "f0", type => $caller_save }, + { name => "f1", type => $caller_save }, + { name => "f2", type => $caller_save }, + { name => "f3", type => $caller_save }, + { name => "f4", type => $caller_save }, + { name => "f5", type => $caller_save }, + { name => "f6", type => $caller_save }, + { name => "f7", type => $caller_save }, + { mode => $mode_fpa } + ], + flags => [ + { name => "fl", type => 0 }, + { mode => $mode_flags, flags => "manual_ra" } + ], +); %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);", + M => "${arch}_emit_mode(node);", + LM => "${arch}_emit_load_mode(node);", + SM => "${arch}_emit_store_mode(node);", + SO => "${arch}_emit_shifter_operand(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);", + D0 => "${arch}_emit_dest_register(node, 0);", + D1 => "${arch}_emit_dest_register(node, 1);", + D2 => "${arch}_emit_dest_register(node, 2);", + O => "${arch}_emit_offset(node);", ); -#--------------------------------------------------# -# _ # -# (_) # -# _ __ _____ __ _ _ __ ___ _ __ ___ # -# | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| # -# | | | | __/\ 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, exec_units, n_res);", + arm_SymConst_attr_t => + "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n". + "\tinit_arm_SymConst_attributes(res, entity);", + arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);", + arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);", + arm_fpaConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);", + arm_load_store_attr_t => + "\tinit_arm_attributes(res, flags, in_reqs, exec_units, 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, flags, in_reqs, exec_units, n_res);\n", + arm_cmp_attr_t => + "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n", + arm_CopyB_attr_t => + "\tinit_arm_attributes(res, flags, in_reqs, exec_units, 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_fpaConst_attr_t => "cmp_attr_arm_fpaConst", + 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", +); + +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 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 shift_modifier, unsigned shift_immediate", + custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);", + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + }, +); + +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 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 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" ], + }, +); + +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 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 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" ], + }, +); -$default_cmp_attr = "NULL"; %nodes = ( -#-----------------------------------------------------------------# -# _ _ _ # -# (_) | | | | # -# _ _ __ | |_ ___ __ _ ___ _ __ _ __ ___ __| | ___ ___ # -# | | '_ \| __/ _ \/ _` |/ _ \ '__| | '_ \ / _ \ / _` |/ _ \/ __| # -# | | | | | || __/ (_| | __/ | | | | | (_) | (_| | __/\__ \ # -# |_|_| |_|\__\___|\__, |\___|_| |_| |_|\___/ \__,_|\___||___/ # -# __/ | # -# |___/ # -#-----------------------------------------------------------------# - -# commutative operations - -"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' -}, - -"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' -}, - -"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', - "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', - "outs" => [ "low", "high" ], -}, - -"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' -}, - -"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;' -}, - -"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' -}, - -"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' -}, - -# 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;' -}, - -"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', -}, - -"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' -}, - -"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;' -}, - -"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' -}, - -"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', -}, - -"Abs" => { - "irn_flags" => "R", - "comment" => "construct Abs: Abs(a) = |a|", - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "emit" => +Add => { + irn_flags => "R", + emit => '. add %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Mul => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] }, + emit =>'. mul %D0, %S0, %S1', + mode => $mode_gp, +}, + +Smull => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] }, + emit =>'. smull %D0, %D1, %S0, %S1', + outs => [ "low", "high" ], +}, + +Umull => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] }, + emit =>'. umull %D0, %D1, %S0, %S1', + outs => [ "low", "high" ], + mode => $mode_gp, +}, + +Mla => { + irn_flags => "R", + reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] }, + emit =>'. mla %D0, %S0, %S1, %S2', + mode => $mode_gp, +}, + +And => { + irn_flags => "R", + emit => '. and %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Or => { + irn_flags => "R", + emit => '. orr %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Eor => { + irn_flags => "R", + emit => '. eor %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Bic => { + irn_flags => "R", + emit => '. bic %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Sub => { + irn_flags => "R", + emit => '. sub %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Rsb => { + irn_flags => "R", + emit => '. rsb %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Mov => { + irn_flags => "R", + arity => "variable", + emit => '. mov %D0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%unop_shifter_operand_constructors, +}, + +Mvn => { + irn_flags => "R", + attr_type => "arm_shifter_operand_t", + arity => "variable", + emit => '. mvn %D0, %SO', + mode => $mode_gp, + constructors => \%unop_shifter_operand_constructors, +}, + +# Deprecated - we should construct the movs and rsbmi directly... +Abs => { + irn_flags => "R", + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + emit => '. movs %S0, %S0, #0 -. rsbmi %D0, %S0, #0' -}, +. rsbmi %D0, %S0, #0', + mode => $mode_gp, +}, + +# this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd +EmptyReg => { + op_flags => "c", + irn_flags => "R", + reg_req => { out => [ "gp" ] }, + emit => '. /* %D0 now available for calculations */', + cmp_attr => 'return 1;', + mode => $mode_gp, +}, + +CopyB => { + op_flags => "F|H", + state => "pinned", + attr => "unsigned size", + attr_type => "arm_CopyB_attr_t", + reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] }, + outs => [ "M" ], +}, + +FrameAddr => { + op_flags => "c", + irn_flags => "R", + attr => "ir_entity *entity", + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + ins => [ "base" ], + attr_type => "arm_SymConst_attr_t", + mode => $mode_gp, +}, + +SymConst => { + op_flags => "c", + irn_flags => "R", + attr => "ir_entity *entity", + reg_req => { out => [ "gp" ] }, + attr_type => "arm_SymConst_attr_t", + mode => $mode_gp, +}, + +Cmp => { + irn_flags => "R|F", + emit => '. cmp %S0, %SO', + mode => $mode_flags, + attr_type => "arm_cmp_attr_t", + constructors => \%cmp_shifter_operand_constructors, +}, + +Tst => { + irn_flags => "R|F", + emit => '. tst %S0, %SO', + mode => $mode_flags, + attr_type => "arm_cmp_attr_t", + constructors => \%cmp_shifter_operand_constructors, +}, + +B => { + op_flags => "L|X|Y", + state => "pinned", + mode => "mode_T", + reg_req => { in => [ "flags" ], out => [ "none", "none" ] }, + attr => "int proj_num", + attr_type => "arm_CondJmp_attr_t", + init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", +}, + +Jmp => { + state => "pinned", + op_flags => "X", + irn_flags => "J", + reg_req => { out => [ "none" ] }, + mode => "mode_X", +}, + +SwitchJmp => { + op_flags => "L|X|Y", + state => "pinned", + 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", +}, + +Ldr => { + op_flags => "L|F", + state => "exc_pinned", + ins => [ "ptr", "mem" ], + outs => [ "res", "M" ], + reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] }, + emit => '. ldr%LM %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", +}, -# other operations +Str => { + op_flags => "L|F", + state => "exc_pinned", + ins => [ "ptr", "val", "mem" ], + outs => [ "mem" ], + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + emit => '. str%SM %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", + state => "exc_pinned", + reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] }, + emit => '. stmfd %S0!, {%S1, %S2, %S3, %S4}', + outs => [ "ptr", "M" ], +}, + +LoadStackM3Epilogue => { + op_flags => "L|F", + irn_flags => "R", + state => "exc_pinned", + 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" ], +}, + + + +fpaAdf => { + irn_flags => "R", + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit => '. adf%M %D0, %S0, %S1', +}, -"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;' -}, +fpaMuf => { + irn_flags => "R", + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit =>'. muf%M %D0, %S0, %S1', +}, -"Copy" => { - "comment" => "implements a register copy", - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, -}, - -"CopyB" => { - "op_flags" => "F|H", - "state" => "pinned", - "comment" => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)", - "reg_req" => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] }, -}, - -"SymConst" => { - "op_flags" => "c", - "irn_flags" => "R", - "comment" => "represents a symbolic constant", - "attr" => "ident *id", - "init_attr" => ' attr->symconst_id = id;', - "reg_req" => { "out" => [ "gp" ] }, - "cmp_attr" => -' /* should be identical but ...*/ - return attr_a->symconst_id == attr_b->symconst_id;' -}, - -"CondJmp" => { - "op_flags" => "L|X|Y", - "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL", - "cmp_attr" => " return arm_comp_condJmp(attr_a, attr_b);\n", - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] }, -}, - -"SwitchJmp" => { - "op_flags" => "L|X|Y", - "comment" => "construct switch", - "reg_req" => { "in" => [ "gp" ], "out" => [ "none" ] }, - "cmp_attr" => " return 0;\n", -}, - -# 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" ], -}, - -"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" ], -}, - -"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" ], -}, - -"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" ], -}, - -"Loadhs" => { - "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" => '. ldrsh %D0, [%S0, #0]', - "outs" => [ "res", "M" ], -}, - -"Storeb" => { - "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" => '. strb %S1, [%S0, #0]', - "outs" => [ "M" ], -}, - -"Storebs" => { - "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" => '. strsb %S1, [%S0, #0]', - "outs" => [ "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]', - "outs" => [ "M" ], -}, - -"Storehs" => { - "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" => '. strhs %S1, [%S0, #0]', - "outs" => [ "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]', - "outs" => [ "M" ], -}, - -"StoreStackM4Inc" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "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}', - "outs" => [ "ptr", "M" ], -}, - -"LoadStackM3" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "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}', - "outs" => [ "res0", "res1", "res2", "M" ], +fpaFml => { + irn_flags => "R", + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit =>'. fml%M %D0, %S0, %S1', }, - -#---------------------------------------------------# -# __ _ # -# / _| | | # -# | |_ _ __ __ _ _ __ ___ __| | ___ ___ # -# | _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __| # -# | | | |_) | (_| | | | | | (_) | (_| | __/\__ \ # -# |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/ # -# | | # -# |_| # -#---------------------------------------------------# - -# 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', +fpaMax => { + irn_flags => "R", + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit =>'. fmax %S0, %S1, %D0', }, -"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', +fpaMin => { + irn_flags => "R", + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit =>'. fmin %S0, %S1, %D0', }, -"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', +fpaSuf => { + irn_flags => "R", + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit => '. suf%M %D0, %S0, %S1' }, -"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', +fpaRsf => { + irn_flags => "R", + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit => '. rsf%M %D0, %S0, %S1' }, -# not commutative operations +fpaDvf => { + 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" ], +}, -"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' +fpaRdf => { + 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" ], }, -"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' +fpaFdv => { + 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" ], }, -"fpaDiv" => { - "comment" => "construct FPA Div: Div(a, b) = a / b", - "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - "emit" =>'. dvf%M %D0, %S0, %S1', +fpaFrd => { + 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', + outs => [ "res", "M" ], }, -"fpaRdv" => { - "comment" => "construct FPA reverse Div: Div(a, b) = b / a", - "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - "emit" =>'. rdf%M %D0, %S0, %S1', +fpaMvf => { + irn_flags => "R", + reg_req => { in => [ "fpa" ], out => [ "fpa" ] }, + emit => '. mvf%M %S0, %D0', }, -"fpaFDiv" => { - "comment" => "construct FPA Fast Div: Div(a, b) = a / b", - "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - "emit" =>'. fdv%M %D0, %S0, %S1', +fpaMnf => { + irn_flags => "R", + reg_req => { in => [ "fpa" ], out => [ "fpa" ] }, + emit => '. mnf%M %S0, %D0', }, -"fpaFRdv" => { - "comment" => "construct FPA Fast reverse Div: Div(a, b) = b / a", - "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - "emit" =>'. frd%M %D0, %S0, %S1', +fpaAbs => { + irn_flags => "R", + reg_req => { in => [ "fpa" ], out => [ "fpa" ] }, + emit => '. abs%M %D0, %S0', }, -"fpaMov" => { - "irn_flags" => "R", - "comment" => "construct FPA Move: b = a", - "reg_req" => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, - "emit" => '. mvf%M %S0, %D0', +fpaFlt => { + irn_flags => "R", + reg_req => { in => ["gp"], out => [ "fpa" ] }, + emit => '. flt%M %D0, %S0', }, -"fpaMnv" => { - "irn_flags" => "R", - "comment" => "construct FPA Move Negated: b = -a", - "reg_req" => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, - "emit" => '. mnf%M %S0, %D0', +fpaFix => { + irn_flags => "R", + reg_req => { in => ["fpa"], out => [ "gp" ] }, + emit => '. fix %D0, %S0', }, -"fpaAbs" => { - "irn_flags" => "R", - "comment" => "construct FPA Absolute value: fAbsd(a) = |a|", - "reg_req" => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, - "emit" => '. abs%M %D0, %S0', +fpaCmfBra => { + op_flags => "L|X|Y", + state => "pinned", + 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", }, -# other operations +fpaCnfBra => { + op_flags => "L|X|Y", + state => "pinned", + 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", +}, -"fpaConst" => { - "op_flags" => "c", - "irn_flags" => "R", - "comment" => "represents a FPA constant", - "attr" => "tarval *val", - "init_attr" => 'attr->value = val;', - "reg_req" => { "out" => [ "fpa" ] }, - "emit" => '. fmov %D0, %C', - "cmp_attr" => 'return attr_a->value != attr_b->value;', +fpaCmfeBra => { + op_flags => "L|X|Y", + state => "pinned", + 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", }, -"fpaFlt" => { - "irn_flags" => "R", - "comment" => "construct a FPA integer->float conversion", - "reg_req" => { "in" => ["gp"], "out" => [ "fpa" ] }, - "emit" => '. flt%M %D0, %S0', +fpaCnfeBra => { + op_flags => "L|X|Y", + state => "pinned", + 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", }, -"fpaFix" => { - "irn_flags" => "R", - "comment" => "construct a FPA float->integer conversion", - "reg_req" => { "in" => ["fpa"], "out" => [ "gp" ] }, - "emit" => '. fix %D0, %S0', +fpaLdf => { + op_flags => "L|F", + irn_flags => "R", + state => "exc_pinned", + 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]', + outs => [ "res", "M" ], }, -# Load / Store +fpaStf => { + op_flags => "L|F", + irn_flags => "R", + state => "exc_pinned", + 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]', + mode => "mode_M", +}, -"fpaLdf" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "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, #0]', - "outs" => [ "res", "M" ], +fpaDbl2GP => { + op_flags => "L|F", + irn_flags => "R", + reg_req => { in => [ "fpa", "none" ], out => [ "gp", "gp", "none" ] }, + outs => [ "low", "high", "M" ], }, -"fpaStf" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "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, #0], %S0', - "outs" => [ "M" ], +AddSP => { + reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] }, + emit => '. add %D0, %S0, %S1', + outs => [ "stack", "M" ], }, -"fpaDbl2GP" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct fp double to 2 gp register transfer", - "reg_req" => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp", "none" ] }, - "outs" => [ "low", "high", "M" ], +SubSPandCopy => { + reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] }, + ins => [ "stack", "size", "mem" ], + emit => ". sub %D0, %S0, %S1\n". + ". mov sp, %D1", + outs => [ "stack", "addr", "M" ], }, - -#---------------------------------------------------# -# __ _ # -# / _| | | # -# __ _| |_ _ __ _ __ ___ __| | ___ ___ # -# \ \ / / _| '_ \ | '_ \ / _ \ / _` |/ _ \/ __| # -# \ V /| | | |_) | | | | | (_) | (_| | __/\__ \ # -# \_/ |_| | .__/ |_| |_|\___/ \__,_|\___||___/ # -# | | # -# |_| # -#---------------------------------------------------# +LdTls => { + irn_flags => "R", + reg_req => { out => [ "gp" ] }, +}, + + +# +# floating point constants +# +fpaConst => { + op_flags => "c", + irn_flags => "R", + attr => "tarval *tv", + init_attr => "attr->tv = tv;", + mode => "get_tarval_mode(tv)", + reg_req => { out => [ "fpa" ] }, + attr_type => "arm_fpaConst_attr_t", +} ); # end of %nodes