X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_spec.pl;h=f4746d44cb62973892962fc2c5f7541710ef7d3d;hb=ce6161a7e42a48f7422b7babcc64d8ace18e2687;hp=90d5fe909d69ad4b5a829c5e657091f2dab485d9;hpb=d3a2b29742fce2a95aed605fbbe83f4c8ac3a28b;p=libfirm diff --git a/ir/be/arm/arm_spec.pl b/ir/be/arm/arm_spec.pl index 90d5fe909..f4746d44c 100644 --- a/ir/be/arm/arm_spec.pl +++ b/ir/be/arm/arm_spec.pl @@ -1,706 +1,570 @@ # Creation: 2006/02/13 +# Arm Architecure Specification +# Author: Matthias Braun, Michael Beck, Oliver Richter, Tobias Gneist # $Id$ -# This is a template specification for the Firm-Backend - -# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...) $arch = "arm"; -# $comment_string = 'WIRHABENKEINEKOMMENTARE'; -$comment_string = '/*'; - -# 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", -# "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 +# Modes # -# 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 -# -# 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 +$mode_gp = "mode_Iu"; +$mode_flags = "mode_Bu"; +$mode_fp = "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) # 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" => "rxx", "type" => 6 }, # dummy register for no_mem - { "mode" => "mode_Iu" } - ], - "fp" => [ - { "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 }, - { "name" => "fxx", "type" => 6 }, # dummy register for no_mem - { "mode" => "mode_D" } - ] -); # %reg_classes - -#--------------------------------------------------# -# _ # -# (_) # -# _ __ _____ __ _ _ __ ___ _ __ ___ # -# | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| # -# | | | | __/\ V V / | | | | (_) | |_) \__ \ # -# |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ # -# | | # -# |_| # -#--------------------------------------------------# - -%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 %D1, %S1, %S2%X0 /* Add(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"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 %D1, %S1, %C /* Add(%C, %S1) -> %D1, (%A1, const) */' -}, - -"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 %D1, %S1, %S2 /* Mul(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"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 %D1, %S1, %S2, %S3 /* Mla(%S1, %S2, %S3) -> %D1, (%A1, %A2, %A3) */' -}, - -"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 %D1, %S1, %S2%X0 /* And(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"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 %D1, %S1, %C /* And(%C, %S1) -> %D1, (%A1, const) */', - "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 %D1, %S1, %S2%X0 /* Or(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"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 %D1, %S1, %C /* Or(%C, %S1) -> %D1, (%A1, const) */' -}, - -"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 %D1, %S1, %S2%X0 /* Xor(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"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 %D1, %S1, %C /* Xor(%C, %S1) -> %D1, (%A1, const) */' -}, - -# 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 %D1, %S1, %S2%X0 /* AndNot(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"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 %D1, %S1, %C /* AndNot(%C, %S1) -> %D1, (%A1, const) */', - "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 %D1, %S1, %S2%X0 /* Sub(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"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 %D1, %S1, %C /* Sub(%S1, %C) -> %D1, (%A1, const) */', -}, - -"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 %D1, %S1, %S2%X0 /* Rsb(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"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 %D1, %S1, %C /* Rsb(%S1, %C) -> %D1, (%A1, const) */', - "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 %D1, %S1, LSL %S2\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Shr" => { - "irn_flags" => "R", - "comment" => "construct Shr: Shr(a, b) = a >> b", - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, - "emit" => '. MOV %D1, %S1, LSR %S2 /* Shr(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Shrs" => { - "irn_flags" => "R", - "comment" => "construct Shrs: Shrs(a, b) = a >> b", - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, - "emit" => '. MOV %D1, %S1, ASR %S2\t\t /* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -#"RotR" => { -# "irn_flags" => "R", -# "comment" => "construct RotR: RotR(a, b) = a ROTR b", -# "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, -# "emit" => '. MOV %D1, %S1, ROR %S2 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */' -## "emit" => '. ror %S1, %S2, %D1 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */' -#}, - -#"RotL" => { -# "irn_flags" => "R", -# "comment" => "construct RotL: RotL(a, b) = a ROTL b", -# "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, -# "emit" => '. rol %S1, %S2, %D1 /* RotL(%S1, %S2) -> %D1, (%A1, %A2) */' -#}, - -#"RotL_i" => { -# "irn_flags" => "R", -# "comment" => "construct RotL: RotL(a, const) = a ROTL const", -# "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, -# "emit" => '. rol %S1, %C, %D1 /* RotL(%S1, %C) -> %D1, (%A1, const) */' -#}, - -"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 %D1, %S1%X0\t/* Mov(%S1%X0) -> %D1, (%A1) */' -}, - -"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 %D1, %C /* Mov Const into register */', - "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 %D1, %S1%X0 /* ~(%S1%X0) -> %D1, (%A1) */' -}, - -"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 %D1, %C /* Mov ~Const into register */', -}, - -"Abs" => { - "irn_flags" => "R", - "comment" => "construct Abs: Abs(a) = |a|", - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "emit" => -'. MOVS %S1, %S1, #0 /* set condition flag */\n -. RSBMI %D1, %S1, #0 /* Neg(%S1) -> %D1, (%A1) */' -}, - -# other operations - -"EmptyReg" => { - "op_flags" => "c", - "irn_flags" => "R", - "comment" => "just to get an empty register for calculations", - "reg_req" => { "out" => [ "gp" ] }, - "emit" => '. /* %D1 now available for calculations */', - "cmp_attr" => 'return 1;' -}, - -"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" => "const char *label", - "init_attr" => ' attr->symconst_label = label;', - "reg_req" => { "out" => [ "gp" ] }, -# "emit" => '. LDR %D1, %C /* Mov Const into register */', - "cmp_attr" => -' /* should be identical but ...*/ - return strcmp(attr_a->symconst_label, attr_b->symconst_label);' -}, - -"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" ] }, - "emit" => '. LDR %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDR %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' -}, - -"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" ] }, - "emit" => '. LDRB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' -}, - -"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" ] }, - "emit" => '. LDRSB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRSB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' -}, - -"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" ] }, - "emit" => '. LDRH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' -}, - -"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" ] }, - "emit" => '. LDRSH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRSH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' -}, - -"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" ] }, - "emit" => '. STRB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' -}, - -"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" ] }, - "emit" => '. STRSB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' -}, - -"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" ] }, - "emit" => '. STRH %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' -}, - -"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" ] }, - "emit" => '. STRSH%S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' -}, - -"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" ] }, - "emit" => '. STR %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' -}, - -"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 %S1!, {%S2, %S3, %S4, %S5} /* Store multiple on Stack*/' -}, - -"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 %S1, {%D1, %D2, %D3} /* Load multiple from Stack */' -}, - + gp => [ + { name => "r0" }, + { name => "r1" }, + { name => "r2" }, + { name => "r3" }, + { name => "r4" }, + { name => "r5" }, + { name => "r6" }, + { name => "r7" }, + { name => "r8" }, + { name => "r9" }, + { name => "r10" }, + { name => "r11" }, + { name => "r12" }, + { name => "sp" }, + { name => "lr" }, + { name => "pc" }, + { mode => $mode_gp } + ], + fpa => [ + { name => "f0" }, + { name => "f1" }, + { name => "f2" }, + { name => "f3" }, + { name => "f4" }, + { name => "f5" }, + { name => "f6" }, + { name => "f7" }, + { mode => $mode_fp } + ], + flags => [ + { name => "fl" }, + { mode => $mode_flags, flags => "manual_ra" } + ], +); + +%emit_templates = ( + FM => "${arch}_emit_float_load_store_mode(node);", + AM => "${arch}_emit_float_arithmetic_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);", + SC => "${arch}_emit_symconst(node);", + 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);", +); + +$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, symconst_offset);", + 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_fConst_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_farith_attr_t => + "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n". + "\tinit_arm_farith_attributes(res, op_mode);", + 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_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", +); + +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" ] }, + }, +); + +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" ], + }, +); + +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" ], + }, +); +%nodes = ( - - - - -#--------------------------------------------------------# -# __ _ _ _ # -# / _| | | | | | # -# | |_| | ___ __ _| |_ _ __ ___ __| | ___ ___ # -# | _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| # -# | | | | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ # -# |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ # -#--------------------------------------------------------# - -# commutative operations - -"fAdd" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct FP Add: Add(a, b) = Add(b, a) = a + b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" => '. FADD%Mx %D1, %S1, %S2 /* FP Add(%S1, %S2) -> %D1 */' -}, - -"fMul" => { - "op_flags" => "C", - "comment" => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" =>'. FMUL%Mx %D1, %S1, %S2 /* FP Mul(%S1, %S2) -> %D1 */' -}, - -"fDiv" => { - "comment" => "construct FP Div: Div(a, b) = a / b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" =>'. FDIV%Mx %D1, %S1, %S2 /* FP Div(%S1, %S2) -> %D1 */' -}, - -"fMax" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" =>'. fmax %S1, %S2, %D1 /* FP Max(%S1, %S2) -> %D1 */' -}, - -"fMin" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" =>'. fmin %S1, %S2, %D1 /* FP Min(%S1, %S2) -> %D1 */' -}, - -# not commutative operations - -"fSub" => { - "irn_flags" => "R", - "comment" => "construct FP Sub: Sub(a, b) = a - b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" => '. FSUB%Mx %D1, %S1, %S2 /* FP Sub(%S1, %S2) -> %D1 */' -}, - -"fNeg" => { - "irn_flags" => "R", - "comment" => "construct FP Neg: Neg(a) = -a", - "reg_req" => { "in" => [ "fp" ], "out" => [ "fp" ] }, - "emit" => '. fneg %S1, %D1 /* FP Neg(%S1) -> %D1 */' -}, - -"fAbs" => { - "irn_flags" => "R", - "comment" => "construct FP Absolute value: fAbsd(a) = |a|", - "reg_req" => { "in" => [ "fp" ], "out" => [ "fp" ] }, - "emit" => '. FABS%Mx %D1, %S1 /* FP Absd(%S1) -> %D1 */' -}, - -# other operations - -"fConst" => { - "op_flags" => "c", - "irn_flags" => "R", - "comment" => "represents a FP constant", - "attr" => "tarval *val", - "init_attr" => 'attr->value = val;', - "reg_req" => { "out" => [ "fp" ] }, - "emit" => '. FMOV %D1, %C /* Mov fConst into register */', - "cmp_attr" => 'return attr_a->value != attr_b->value;' -}, - -"fConvD2S" => { - "irn_flags" => "R", - "comment" => "convert double to single", - "reg_req" => { "in" => [ "fp" ], "out" => [ "fp" ] }, - "emit" => '. FCVTSD %D1, %S1 /* Convert double to single */', +Add => { + irn_flags => [ "rematerializable" ], + emit => '. add %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, }, -"fConvS2D" => { - "irn_flags" => "R", - "comment" => "convert single to double", - "reg_req" => { "in" => [ "fp" ], "out" => [ "fp" ] }, - "emit" => '. FCVTDS %D1, %S1 /* Convert single to double */', +Mul => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] }, + emit =>'. mul %D0, %S0, %S1', + mode => $mode_gp, }, - -# Load / Store - -"fLoad" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct FP Load: Load(ptr, mem) = LD ptr", - "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "fp" ] }, - "emit" => '. FLD%Mx %D1, %S1 /* Load((%S1)) -> %D1 */' +Smull => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] }, + emit =>'. smull %D0, %D1, %S0, %S1', + outs => [ "low", "high" ], +}, + +Umull => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] }, + emit =>'. umull %D0, %D1, %S0, %S1', + outs => [ "low", "high" ], + mode => $mode_gp, +}, + +Mla => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] }, + emit =>'. mla %D0, %S0, %S1, %S2', + mode => $mode_gp, +}, + +And => { + irn_flags => [ "rematerializable" ], + emit => '. and %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Or => { + irn_flags => [ "rematerializable" ], + emit => '. orr %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Eor => { + irn_flags => [ "rematerializable" ], + emit => '. eor %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Bic => { + irn_flags => [ "rematerializable" ], + emit => '. bic %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Sub => { + irn_flags => [ "rematerializable" ], + emit => '. sub %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Rsb => { + irn_flags => [ "rematerializable" ], + emit => '. rsb %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, +}, + +Mov => { + irn_flags => [ "rematerializable" ], + arity => "variable", + emit => '. mov %D0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%unop_shifter_operand_constructors, +}, + +Mvn => { + irn_flags => [ "rematerializable" ], + attr_type => "arm_shifter_operand_t", + arity => "variable", + emit => '. mvn %D0, %SO', + mode => $mode_gp, + constructors => \%unop_shifter_operand_constructors, +}, + +Clz => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp" ], out => [ "gp" ] }, + emit =>'. clz %D0, %S0', + mode => $mode_gp, +}, + +# 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_irn_add_flags(res, arch_irn_flags_modify_flags);", + emit => ". mov lr, pc\n". + ". mov pc, %SO", +}, + +# 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_irn_add_flags(res, arch_irn_flags_modify_flags);", + emit => ". mov lr, pc\n". + ". ldr pc, %SO", +}, + +Bl => { + state => "exc_pinned", + arity => "variable", + out_arity => "variable", + attr_type => "arm_SymConst_attr_t", + attr => "ir_entity *entity, int symconst_offset", + custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);", + emit => '. bl %SC', +}, + +# this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd +EmptyReg => { + 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 => [ "fragile" ], + 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 => [ "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, +}, + +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, +}, + +Cmp => { + irn_flags => [ "rematerializable", "modify_flags" ], + emit => '. cmp %S0, %SO', + mode => $mode_flags, + attr_type => "arm_cmp_attr_t", + constructors => \%cmp_shifter_operand_constructors, +}, + +Tst => { + irn_flags => [ "rematerializable", "modify_flags" ], + emit => '. tst %S0, %SO', + mode => $mode_flags, + attr_type => "arm_cmp_attr_t", + constructors => \%cmp_shifter_operand_constructors, +}, + +B => { + op_flags => [ "labeled", "cfopcode", "forking" ], + state => "pinned", + mode => "mode_T", + reg_req => { in => [ "flags" ], out => [ "none", "none" ] }, + attr => "pn_Cmp pnc", + attr_type => "arm_CondJmp_attr_t", + init_attr => "\tset_arm_CondJmp_pnc(res, pnc);", +}, + +Jmp => { + state => "pinned", + op_flags => [ "cfopcode" ], + irn_flags => [ "simple_jump" ], + reg_req => { out => [ "none" ] }, + mode => "mode_X", +}, + +SwitchJmp => { + op_flags => [ "labeled", "cfopcode", "forking" ], + 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);\n". + "\tinfo->out_infos = NULL;", + reg_req => { in => [ "gp" ], out => [ "none" ] }, + attr_type => "arm_SwitchJmp_attr_t", +}, + +Ldr => { + op_flags => [ "labeled", "fragile" ], + 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", +}, + +Str => { + op_flags => [ "labeled", "fragile" ], + state => "exc_pinned", + ins => [ "ptr", "val", "mem" ], + outs => [ "M" ], + 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 => [ "labeled", "fragile" ], + irn_flags => [ "rematerializable" ], + 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 => [ "labeled", "fragile" ], + irn_flags => [ "rematerializable" ], + 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" ], +}, + + + +Adf => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit => '. adf%AM %D0, %S0, %S1', + attr_type => "arm_farith_attr_t", + attr => "ir_mode *op_mode", + mode => $mode_fp, +}, + +Muf => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit =>'. muf%AM %D0, %S0, %S1', + attr_type => "arm_farith_attr_t", + attr => "ir_mode *op_mode", + mode => $mode_fp, +}, + +Suf => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] }, + emit => '. suf%AM %D0, %S0, %S1', + attr_type => "arm_farith_attr_t", + attr => "ir_mode *op_mode", + mode => $mode_fp, +}, + +Dvf => { + reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] }, + emit =>'. dvf%AM %D0, %S0, %S1', + outs => [ "res", "M" ], + attr_type => "arm_farith_attr_t", + attr => "ir_mode *op_mode", + mode => $mode_fp, +}, + +Mvf => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "fpa" ], out => [ "fpa" ] }, + emit => '. mvf%AM %S0, %D0', + attr_type => "arm_farith_attr_t", + attr => "ir_mode *op_mode", + mode => $mode_fp, +}, + +FltX => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp" ], out => [ "fpa" ] }, + emit => '. flt%AM %D0, %S0', + attr_type => "arm_farith_attr_t", + attr => "ir_mode *op_mode", + mode => $mode_fp, +}, + +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', +}, + +Ldf => { + op_flags => [ "labeled", "fragile" ], + state => "exc_pinned", + ins => [ "ptr", "mem" ], + outs => [ "res", "M" ], + reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] }, + emit => '. ldf%FM %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", +}, + +Stf => { + op_flags => [ "labeled", "fragile" ], + state => "exc_pinned", + ins => [ "ptr", "val", "mem" ], + outs => [ "M" ], + mode => "mode_M", + reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] }, + emit => '. stf%FM %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", }, -"fStore" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "gp", "fp", "none" ] }, - "emit" => '. FST%Mx %S2, %S1 /* Store(%S2) -> (%S1), (%A1, %A2) */' -}, +# +# floating point constants +# +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" ] }, + attr_type => "arm_fConst_attr_t", +} ); # end of %nodes