X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_spec.pl;h=f4746d44cb62973892962fc2c5f7541710ef7d3d;hb=31fc92ec27c0274f5f24c515094afd40a04ab1a9;hp=68d3b6f7a4d47979fab06b36c4ce1654b5bdd818;hpb=d11d8b4831db166f01b115a218e26e17091f898f;p=libfirm diff --git a/ir/be/arm/arm_spec.pl b/ir/be/arm/arm_spec.pl index 68d3b6f7a..f4746d44c 100644 --- a/ir/be/arm/arm_spec.pl +++ b/ir/be/arm/arm_spec.pl @@ -1,804 +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"; -$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") +# Modes # -# 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 -# -# 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", "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" }, + { 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 = ( - 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);", + 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);", ); -#--------------------------------------------------# -# _ # -# (_) # -# _ __ _____ __ _ _ __ ___ _ __ ___ # -# | '_ \ / _ \ \ /\ / / | | '__| / _ \| '_ \/ __| # -# | | | | __/\ V V / | | | | (_) | |_) \__ \ # -# |_| |_|\___| \_/\_/ |_|_| \___/| .__/|___/ # -# | | # -# |_| # -#--------------------------------------------------# - -$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" => -'. movs %S0, %S0, #0 -. rsbmi %D0, %S0, #0' -}, - -# other operations - -"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" ] }, -}, - -"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" ], -}, - - -#---------------------------------------------------# -# __ _ # -# / _| | | # -# | |_ _ __ __ _ _ __ ___ __| | ___ ___ # -# | _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __| # -# | | | |_) | (_| | | | | | (_) | (_| | __/\__ \ # -# |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/ # -# | | # -# |_| # -#---------------------------------------------------# - -# 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", - "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - "emit" =>'. dvf%M %D0, %S0, %S1', -}, - -"fpaRdv" => { - "comment" => "construct FPA reverse Div: Div(a, b) = b / a", - "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - "emit" =>'. rdf%M %D0, %S0, %S1', -}, - -"fpaFDiv" => { - "comment" => "construct FPA Fast Div: Div(a, b) = a / b", - "reg_req" => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] }, - "emit" =>'. fdv%M %D0, %S0, %S1', -}, - -"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', -}, - -"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', -}, +$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);", +); -"fpaAbs" => { - "irn_flags" => "R", - "comment" => "construct FPA Absolute value: fAbsd(a) = |a|", - "reg_req" => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, - "emit" => '. abs%M %D0, %S0', -}, +%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", +); -# other operations +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" ] }, + }, +); -"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;', -}, +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" ], + }, +); -"fpaFlt" => { - "irn_flags" => "R", - "comment" => "construct a FPA integer->float conversion", - "reg_req" => { "in" => ["gp"], "out" => [ "fpa" ] }, - "emit" => '. flt%M %D0, %S0', -}, +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" ], + }, +); -"fpaFix" => { - "irn_flags" => "R", - "comment" => "construct a FPA float->integer conversion", - "reg_req" => { "in" => ["fpa"], "out" => [ "gp" ] }, - "emit" => '. fix %D0, %S0', -}, -# Load / Store +%nodes = ( -"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" ], +Add => { + irn_flags => [ "rematerializable" ], + emit => '. add %D0, %S0, %SO', + mode => $mode_gp, + attr_type => "arm_shifter_operand_t", + constructors => \%binop_shifter_operand_constructors, }, -"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" ], +Mul => { + irn_flags => [ "rematerializable" ], + reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] }, + emit =>'. mul %D0, %S0, %S1', + mode => $mode_gp, }, -"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" ], +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", }, - -#---------------------------------------------------# -# __ _ # -# / _| | | # -# __ _| |_ _ __ _ __ ___ __| | ___ ___ # -# \ \ / / _| '_ \ | '_ \ / _ \ / _` |/ _ \/ __| # -# \ V /| | | |_) | | | | | (_) | (_| | __/\__ \ # -# \_/ |_| | .__/ |_| |_|\___/ \__,_|\___||___/ # -# | | # -# |_| # -#---------------------------------------------------# +# +# 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