X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_spec.pl;h=932f064a8029766d343f6e20fd40432aed09c61f;hb=e7ba741cdd9599ce05d7989bff60a1c6137ee0b5;hp=0fcb9ffbb6bcd94fd046d9736214de2b2c727ebb;hpb=021dd42c11eca475bae9fb4176a6b8f02f471c43;p=libfirm diff --git a/ir/be/arm/arm_spec.pl b/ir/be/arm/arm_spec.pl index 0fcb9ffbb..932f064a8 100644 --- a/ir/be/arm/arm_spec.pl +++ b/ir/be/arm/arm_spec.pl @@ -5,12 +5,10 @@ # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...) $arch = "arm"; - -# $comment_string = 'WIRHABENKEINEKOMMENTARE'; -$comment_string = '/*'; +$new_emit_syntax = 1; # the number of additional opcodes you want to register -$additional_opcodes = 0; +#$additional_opcodes = 0; # The node description is done as a perl hash initializer with the # following structure: @@ -18,20 +16,24 @@ $additional_opcodes = 0; # %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" }, +# op_flags => "N|L|C|X|I|F|Y|H|c|K", +# irn_flags => "R|N|I|S" +# arity => "0|1|2|3 ... |variable|dynamic|any", +# state => "floats|pinned|mem_pinned|exc_pinned", +# args => [ +# { type => "type 1", name => "name 1" }, +# { type => "type 2", name => "name 2" }, # ... # ], -# "comment" => "any comment for constructor", -# "reg_req" => { "in" => [ "reg_class|register" ], "out" => [ "reg_class|register|in_rX" ] }, -# "cmp_attr" => "c source code for comparing node attributes", -# "emit" => "emit code with templates", -# "rd_constructor" => "c source code which constructs an ir_node" +# comment => "any comment for constructor", +# reg_req => { in => [ "reg_class|register" ], out => [ "reg_class|register|in_rX" ] }, +# cmp_attr => "c source code for comparing node attributes", +# emit => "emit code with templates", +# attr => "attitional attribute arguments for constructor" +# init_attr => "emit attribute initialization template" +# rd_constructor => "c source code which constructs an ir_node" +# latency => "latency of this operation (can be float)" +# attr_type => "name of the attribute struct", # }, # # ... # (all nodes you need to describe) @@ -56,6 +58,7 @@ $additional_opcodes = 0; # R rematerializeable # N not spillable # I ignore for register allocation +# S modifies stack pointer # # state: state of the operation, OPTIONAL (default is "floats") # @@ -68,6 +71,13 @@ $additional_opcodes = 0; # for i = 1 .. arity: ir_node *op_i # ir_mode *mode # +# outs: if a node defines more than one output, the names of the projections +# nodes having outs having automatically the mode mode_T +# One can also annotate some flags for each out, additional to irn_flags. +# They are separated from name with a colon ':', and concatenated by pipe '|' +# Only I and S are available at the moment (same meaning as in irn_flags). +# example: [ "frame:I", "stack:I|S", "M" ] +# # comment: OPTIONAL comment for the node constructor # # rd_constructor: for every operation there will be a @@ -85,49 +95,75 @@ $additional_opcodes = 0; # return res # # NOTE: rd_constructor and args are only optional if and only if arity is 0,1,2 or 3 +# +# latency: the latency of the operation, default is 1 +# + +# +# Modes +# +$mode_gp = "mode_Iu"; +$mode_fpa = "mode_E"; # register types: # 0 - no special type # 1 - caller save (register must be saved by the caller of a function) # 2 - callee save (register must be saved by the called function) # 4 - ignore (do not assign this register) +# 8 - emitter can choose an arbitrary register of this class +# 16 - the register is a virtual one +# 32 - register represents a state # NOTE: Last entry of each class is the largest Firm-Mode a register can hold %reg_classes = ( - "general_purpose" => [ - { "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" => "r13", "type" => 6 }, # this is our stack pointer - { "name" => "r14", "type" => 3 }, # this is our return address - { "name" => "r15", "type" => 6 }, # this is our program counter - { "name" => "rxx", "type" => 6 }, # dummy register for no_mem - { "name" => "MURX", "type" => 6 }, # this is our workaround-register - { "mode" => "mode_P" } - ], - "floating_point" => [ - { "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" } - ] + gp => [ + { "name" => "r0", "type" => 1 }, + { "name" => "r1", "type" => 1 }, + { "name" => "r2", "type" => 1 }, + { "name" => "r3", "type" => 1 }, + { "name" => "r4", "type" => 2 }, + { "name" => "r5", "type" => 2 }, + { "name" => "r6", "type" => 2 }, + { "name" => "r7", "type" => 2 }, + { "name" => "r8", "type" => 2 }, + { "name" => "r9", "type" => 2 }, + { "name" => "r10", "type" => 2 }, + { "name" => "r11", "type" => 2 }, + { "name" => "r12", "type" => 6 }, # reserved for linker + { "name" => "sp", "type" => 6 }, # this is our stack pointer + { "name" => "lr", "type" => 3 }, # this is our return address + { "name" => "pc", "type" => 6 }, # this is our program counter + { name => "gp_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes + { "mode" => $mode_gp } + ], + fpa => [ + { "name" => "f0", "type" => 1 }, + { "name" => "f1", "type" => 1 }, + { "name" => "f2", "type" => 1 }, + { "name" => "f3", "type" => 1 }, + { "name" => "f4", "type" => 1 }, + { "name" => "f5", "type" => 1 }, + { "name" => "f6", "type" => 1 }, + { "name" => "f7", "type" => 1 }, + { name => "fpa_UKNWN", type => 4 | 8 | 16 }, # we need a dummy register for Unknown nodes + { "mode" => $mode_fpa } + ] ); # %reg_classes +%emit_templates = ( + M => "${arch}_emit_mode(env, node);", + X => "${arch}_emit_shift(env, node);", + S0 => "${arch}_emit_source_register(env, node, 0);", + S1 => "${arch}_emit_source_register(env, node, 1);", + S2 => "${arch}_emit_source_register(env, node, 2);", + S3 => "${arch}_emit_source_register(env, node, 3);", + S4 => "${arch}_emit_source_register(env, node, 4);", + D0 => "${arch}_emit_dest_register(env, node, 0);", + D1 => "${arch}_emit_dest_register(env, node, 1);", + D2 => "${arch}_emit_dest_register(env, node, 2);", + C => "${arch}_emit_immediate(env, node);", + O => "${arch}_emit_offset(env, mode);", +); + #--------------------------------------------------# # _ # # (_) # @@ -139,8 +175,72 @@ $additional_opcodes = 0; # |_| # #--------------------------------------------------# +$default_attr_type = "arm_attr_t"; +$default_copy_attr = "arm_copy_attr"; + +%init_attr = ( + arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);", + arm_SymConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);", + arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);", + arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);", +); + +%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", +); + +#%operands = ( +# +#Immediate => { +# comment => "blup di dup", +# irn_flags => "R", +# emit => ". [%S0]-10", +# reg_req => { }, +# attr => "tarval *tv", +# init_attr => "(void) attri;", +# # op_flags => O +# # cmp => "return 1;" +#}, +# +#ShfOp_I => { +# irn_flags => "R", +# emit => ". ...", +# reg_req => { in => [ "gp" ] }, +# attr => "tarval *tv", +# init_attr => "(void) tv;", +#}, +# +#ShfOp => { +# irn_flags => "R", +# emit => ". ...", +# reg_req => { in => [ "gp", "gp" ] }, +#}, +# +#); + %nodes = ( +Unknown_GP => { + state => "pinned", + op_flags => "c", + irn_flags => "I", + reg_req => { out => [ "gp_UKNWN" ] }, + emit => "", + mode => $mode_gp, +}, + +Unknown_FPA => { + state => "pinned", + op_flags => "c", + irn_flags => "I", + reg_req => { out => [ "fpa_UKNWN" ] }, + emit => "", + mode => $mode_fpa, +}, + #-----------------------------------------------------------------# # _ _ _ # # (_) | | | | # @@ -154,680 +254,812 @@ $additional_opcodes = 0; # commutative operations -"Add" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. ADD %D1, %S1, %S2\t\t\t/* Add(%S1, %S2) -> %D1, (%A1, %A2) */' +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", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. ADD %D1, %S1, %C\t\t\t/* Add(%C, %S1) -> %D1, (%A1, const) */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; - - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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" => [ "general_purpose", "general_purpose" ], "out" => [ "!in_r1" ] }, - "emit" =>'. MUL %D1, %S1, %S2\t\t\t/* Mul(%S1, %S2) -> %D1, (%A1, %A2) */' +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' }, -"And" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct And: And(a, b) = And(b, a) = a AND b", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. AND %D1, %S1, %S2\t\t/* And(%S1, %S2) -> %D1, (%A1, %A2) */' +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" ], }, -"And_i" => { - "irn_flags" => "R", - "comment" => "construct And: And(a, const) = And(const, a) = a AND const", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. AND %D1, %S1, %C\t\t\t/* And(%C, %S1) -> %D1, (%A1, const) */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; - - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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" ], }, -"Or" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. ORR %D1, %S1, %S2\t\t/* Or(%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 %D0, %S0, %S1, %S2' }, -"Or_i" => { - "irn_flags" => "R", - "comment" => "construct Or: Or(a, const) = Or(const, a) = a OR const", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. ORR %D1, %S1, %C\t\t\t/* Or(%C, %S1) -> %D1, (%A1, const) */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; +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' +}, - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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_Shl_i" => { - "irn_flags" => "R", - "comment" => "construct Or with immediate shifter operand", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. ORR %D1, %S1, %S2 LSL %C\t\t\t/* Or_Shl_i(%S1, %S2 << %C) -> %D1, (%A1, const) */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; +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' +}, - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. EOR %D1, %S1, %S2\t\t\t/* Xor(%S1, %S2) -> %D1, (%A1, %A2) */' +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", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. EOR %D1, %S1, %C\t\t\t/* Xor(%C, %S1) -> %D1, (%A1, const) */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; - - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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 -"Sub" => { - "irn_flags" => "R", - "comment" => "construct Sub: Sub(a, b) = a - b", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. SUB %D1, %S1, %S2\t\t\t/* Sub(%S1, %S2) -> %D1, (%A1, %A2) */' +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' }, -"Sub_i" => { - "irn_flags" => "R", - "comment" => "construct Sub: Sub(a, const) = a - const", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. SUB %D1, %S1, %C\t\t\t/* Sub(%S1, %C) -> %D1, (%A1, const) */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; - - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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;' }, -"Shl" => { - "irn_flags" => "R", - "comment" => "construct Shl: Shl(a, b) = a << b", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. MOV %D1, %S1, LSL %S2\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */' +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' }, -"Shl_i" => { - "irn_flags" => "R", - "comment" => "construct Shl: Shl(a, const) = a << const", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. MOV %D1, %S1, LSL %C\t\t\t/* Shl(%S1, %C) -> %D1, (%A1, const) */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; - - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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', }, -"Shr" => { - "irn_flags" => "R", - "comment" => "construct Shr: Shr(a, b) = a >> b", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. MOV %D1, %S1, LSR %S2\t\t\t/* Shr(%S1, %S2) -> %D1, (%A1, %A2) */' +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' }, -"Shr_i" => { - "irn_flags" => "R", - "comment" => "construct Shr: Shr(a, const) = a >> const", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. MOV %D1, %S1, LSR %C\t\t\t/* Shr(%S1, %C) -> %D1, (%A1, const) */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; - - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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;' }, -"Shrs" => { - "irn_flags" => "R", - "comment" => "construct Shrs: Shrs(a, b) = a >> b", - "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "in_r1" ] }, - "emit" => '. MOV %D1, %S1, ASR %S2\t\t\t\t\t/* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */' +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' }, -"Shrs_i" => { - "irn_flags" => "R", - "comment" => "construct Shrs: Shrs(a, const) = a >> const", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. MOV %D1, %S1, ASR %C\t\t\t/* Shrs(%S1, %C) -> %D1, (%A1, const) */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; +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' +}, - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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' }, -#"Div" => { -# "irn_flags" => "R", -# "comment" => "construct Div: Div(a, b) = a / b", -# "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" =>'. div %S1, %S2, %D1\t\t\t/* div(%S1, %S2) -> %D1, (%A1, %A2) */' -#}, -# -#"Div_i" => { -# "irn_flags" => "R", -# "comment" => "construct Div: Div(a, const) = a / const", -# "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" => '. div %S1, %C, %D1\t\t\t/* signed div(%C, %S1) -> %D1, (%A1, const) */' -#}, -# -#"Mod" => { -# "irn_flags" => "R", -# "comment" => "construct Mod: Mod(a, b) = a % b", -# "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" =>'. mod %S1, %S2, %D1\t\t\t/* mod(%S1, %S2) -> %D1, (%A1, %A2) */' -#}, -# -#"Mod_i" => { -# "irn_flags" => "R", -# "comment" => "construct mod: Mod(a, const) = a % const", -# "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" => '. mod %S1, %C, %D1\t\t\t/* mod(%C, %S1) -> %D1, (%A1, const) */' -#}, -# -#"DivMod" => { -# "irn_flags" => "R", -# "comment" => "construct DivMod: DivMod(a, b) = a / b", -# "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" =>'. div %S1, %S2, %D1\t\t\t/* div(%S1, %S2) -> %D1, (%A1, %A2) */' -#}, -# -#"Div_i" => { -# "irn_flags" => "R", -# "comment" => "construct DivMod: DivMod(a, const) = a / const", -# "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" => '. div %S1, %C, %D1\t\t\t/* signed div(%C, %S1) -> %D1, (%A1, const) */' +#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' #}, -#"RotR" => { -# "irn_flags" => "R", -# "comment" => "construct RotR: RotR(a, b) = a ROTR b", -# "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" => '. MOV %D1, %S1, ROR %S2\t\t\t/* RotR(%S1, %S2) -> %D1, (%A1, %A2) */' -## "emit" => '. ror %S1, %S2, %D1\t\t\t/* 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 %S0, %S1, %D0' #}, -#"RotL" => { -# "irn_flags" => "R", -# "comment" => "construct RotL: RotL(a, b) = a ROTL b", -# "reg_req" => { "in" => [ "general_purpose", "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" => '. rol %S1, %S2, %D1\t\t\t/* 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 %S0, %C, %D0' #}, -#"RotL_i" => { -# "irn_flags" => "R", -# "comment" => "construct RotL: RotL(a, const) = a ROTL const", -# "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" => '. rol %S1, %C, %D1\t\t\t/* 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 %D0, %S0%X' +}, -"Minus" => { - "irn_flags" => "R", - "comment" => "construct Minus: Minus(a) = -a", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. RSB %D1, %S1, #0\t\t\t/* Neg(%S1) -> %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 %D0, %C', + cmp_attr => 'return attr_a->value != attr_b->value;' }, -#"Inc" => { -# "irn_flags" => "R", -# "comment" => "construct Increment: Inc(a) = a++", -# "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" => '. inc %S1, %D1\t\t\t/* Inc(%S1) -> %D1, (%A1) */' -#}, -# -#"Dec" => { -# "irn_flags" => "R", -# "comment" => "construct Decrement: Dec(a) = a--", -# "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, -# "emit" => '. dec %S1, %D1\t\t\t/* Dec(%S1) -> %D1, (%A1) */' -#}, +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' +}, -"Not" => { - "arity" => 1, -# "remat" => 1, - "irn_flags" => "R", - "comment" => "construct Not: Not(a) = !a", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => '. MVN %D1, %S1\t\t\t/* Not(%S1) -> %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 %D0, %C', }, -"Abs" => { - "irn_flags" => "R", - "comment" => "construct Abs: Abs(a) = |a|", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, - "emit" => -'. MOVS %S1, %S1, #0\t\t\t/* set condition flag */\n -. RSBMI %D1, %S1, #0\t\t\t/* Neg(%S1) -> %D1, (%A1) */' +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" => "just to get an emptz register for calculations", - "reg_req" => { "out" => [ "general_purpose" ] }, - "emit" => '. /* %D1 now available for calculations */', - "cmp_attr" => 'return 1;' +# +# this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd +# +EmptyReg => { + op_flags => "c", + irn_flags => "R", + comment => "allocate an empty register for calculations", + reg_req => { "out" => [ "gp" ] }, + emit => '. /* %D0 now available for calculations */', + cmp_attr => 'return 1;' }, -"Copy" => { - "comment" => "implements a register copy", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "general_purpose" ] }, +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" => [ "!r13", "!r13", "general_purpose", "general_purpose", "general_purpose", "none" ], "out" => [ "none" ] }, +CopyB => { + op_flags => "F|H", + state => "pinned", + comment => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)", + attr => "tarval *tv", + init_attr => 'attr->value = tv;', + reg_req => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] }, + outs => [ "M" ], }, -"Const" => { - "irn_flags" => "R", - "comment" => "represents an integer constant", - "reg_req" => { "out" => [ "general_purpose" ] }, - "emit" => '. MOV %D1, %C \t\t\t/* Mov Const into register */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; +SymConst => { + op_flags => "c", + irn_flags => "R", + comment => "represents a symbolic constant", + attr => "ident *id", + init_attr => "\tset_arm_symconst_id(res, id);", + reg_req => { "out" => [ "gp" ] }, + attr_type => "arm_SymConst_attr_t", +}, - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +CmpBra => { + op_flags => "L|X|Y", + state => "pinned", + comment => "construct conditional branch: CMP A, B && JMPxx LABEL", + mode => "mode_T", + attr => "int proj_num", + init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", + reg_req => { "in" => [ "gp", "gp" ], "out" => [ "none", "none"] }, + attr_type => "arm_CondJmp_attr_t", }, -"Const_Neg" => { - "irn_flags" => "R", - "comment" => "represents a negated integer constant", - "reg_req" => { "out" => [ "general_purpose" ] }, - "emit" => '. MVN %D1, %C \t\t\t/* Mov negated Const into register */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; +SwitchJmp => { + op_flags => "L|X|Y", + state => "pinned", + comment => "construct switch", + mode => "mode_T", + attr => "int n_projs, long def_proj_num", + init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n". + "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);", + reg_req => { "in" => [ "gp" ], "out" => [ "none" ] }, + attr_type => "arm_SwitchJmp_attr_t", +}, + +# Load / Store - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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" ], }, -"SymConst" => { - "op_flags" => "c", - "irn_flags" => "R", - "comment" => "represents a symbolic constant", - "reg_req" => { "out" => [ "general_purpose" ] }, -# "emit" => '. LDR %D1, %C\t\t\t/* Mov Const into register */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; +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" ], +}, - return get_tarval_long(attr_a->value) != get_tarval_long(attr_b->value); -' +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" ], }, -"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" => [ "general_purpose", "general_purpose" ], "out" => [ "none", "none"] }, +Loadh => { + op_flags => "L|F", + irn_flags => "R", + state => "exc_pinned", + comment => "construct Load: Load(ptr, mem) = LD ptr -> reg", + reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] }, + emit => '. ldrh %D0, [%S0, #0]', + outs => [ "res", "M" ], }, -"SwitchJmp" => { - "op_flags" => "L|X|Y", - "comment" => "construct switch", - "reg_req" => { "in" => [ "general_purpose" ], "out" => [ "none" ] }, - "cmp_attr" => " return 0;\n", +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" ], }, -# Load / Store +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]', + mode => "mode_M", +}, + +Storeh => { + op_flags => "L|F", + irn_flags => "R", + state => "exc_pinned", + comment => "construct Store: Store(ptr, val, mem) = ST ptr,val", + reg_req => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] }, + emit => '. strh %S1, [%S0, #0]', + mode => "mode_M", +}, -"Load" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] }, - "emit" => '. LDR %D1, [%S1, #0]\t\t\t/* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDR %D1, %S1, %O\t\t\t/* 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" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] }, - "emit" => '. LDRB %D1, [%S1, #0]\t\t\t/* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRB %D1, %S1, %O\t\t\t/* 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" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] }, - "emit" => '. LDRSB %D1, [%S1, #0]\t\t\t/* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRSB %D1, %S1, %O\t\t\t/* Load((%S1)) -> %D1, (%A1) */' +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]', + mode => "mode_M", }, -"Loadh" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] }, - "emit" => '. LDRH %D1, [%S1, #0]\t\t\t/* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRH %D1, %S1, %O\t\t\t/* Load((%S1)) -> %D1, (%A1) */' +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" ], }, -"Loadhs" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "general_purpose" ] }, - "emit" => '. LDRSH %D1, [%S1, #0]\t\t\t/* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRSH %D1, %S1, %O\t\t\t/* Load((%S1)) -> %D1, (%A1) */' +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" ], }, -"Storeb" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "general_purpose", "general_purpose", "none" ] }, - "emit" => '. STRB %S2, [%S1, #0]\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' + +#---------------------------------------------------# +# __ _ # +# / _| | | # +# | |_ _ __ __ _ _ __ ___ __| | ___ ___ # +# | _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __| # +# | | | |_) | (_| | | | | | (_) | (_| | __/\__ \ # +# |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/ # +# | | # +# |_| # +#---------------------------------------------------# + +# commutative operations + +fpaAdf => { + 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', }, -"Storebs" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "general_purpose", "general_purpose", "none" ] }, - "emit" => '. STRSB %S2, [%S1, #0]\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' +fpaAdf_i => { + op_flags => "C", + irn_flags => "R", + comment => "construct FPA Add: Add(a, b) = Add(b, a) = a + b", + attr => "tarval *tv", + init_attr => 'ARM_SET_FPA_IMM(attr); attr->value = tv;', + cmp_attr => 'return attr_a->value != attr_b->value;', + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. adf%M %D0, %S0, %C', }, -"Storeh" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "general_purpose", "general_purpose", "none" ] }, - "emit" => '. STRH %S2, [%S1, #0]\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' +fpaMuf => { + op_flags => "C", + irn_flags => "R", + 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', }, -"Storehs" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "general_purpose", "general_purpose", "none" ] }, - "emit" => '. STRSH%S2, [%S1, #0]\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' +fpaMuf_i => { + op_flags => "C", + irn_flags => "R", + comment => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b", + attr => "tarval *tv", + init_attr => 'ARM_SET_FPA_IMM(attr); attr->value = tv;', + cmp_attr => 'return attr_a->value != attr_b->value;', + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. muf%M %D0, %S0, %C', }, -"Store" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "general_purpose", "general_purpose", "none" ] }, - "emit" => '. STR %S2, [%S1, #0]\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1)\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' +fpaFml => { + op_flags => "C", + irn_flags => "R", + 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', }, -"StoreStackM4Inc" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "r13", "general_purpose", "general_purpose", "general_purpose", "general_purpose", "none" ], "out" => [ "general_purpose", "none" ] }, - "emit" => '. STMFD %S1!, {%S2, %S3, %S4, %S5}\t\t\t/* Store multiple on Stack*/' +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', }, -"LoadStackM3" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "r13", "none" ], "out" => [ "general_purpose", "general_purpose", "general_purpose", "none" ] }, - "emit" => '. LDMFD %S1, {%D1, %D2, %D3}\t\t\t/* Load multiple from Stack */' +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 +fpaSuf => { + 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' +}, +fpaSuf_i => { + irn_flags => "R", + comment => "construct FPA Sub: Sub(a, b) = a - b", + attr => "tarval *tv", + init_attr => 'ARM_SET_FPA_IMM(attr); attr->value = tv;', + cmp_attr => 'return attr_a->value != attr_b->value;', + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. suf%M %D0, %S0, %C' +}, +fpaRsf => { + 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' +}, +fpaRsf_i => { + irn_flags => "R", + comment => "construct FPA reverse Sub: Sub(a, b) = b - a", + attr => "tarval *tv", + init_attr => 'ARM_SET_FPA_IMM(attr); attr->value = tv;', + cmp_attr => 'return attr_a->value != attr_b->value;', + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. rsf%M %D0, %S0, %C' +}, +fpaDvf => { + comment => "construct FPA Div: Div(a, b) = a / b", + 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" ], +}, +fpaDvf_i => { + comment => "construct FPA Div: Div(a, b) = a / b", + attr => "ir_mode *op_mode, tarval *tv", + init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->value = tv;', + cmp_attr => 'return attr_a->value != attr_b->value;', + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] }, + emit =>'. dvf%M %D0, %S0, %C', + outs => [ "res", "M" ], +}, -#--------------------------------------------------------# -# __ _ _ _ # -# / _| | | | | | # -# | |_| | ___ __ _| |_ _ __ ___ __| | ___ ___ # -# | _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| # -# | | | | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ # -# |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ # -#--------------------------------------------------------# +fpaRdf => { + comment => "construct FPA reverse Div: Div(a, b) = b / a", + attr => "ir_mode *op_mode", + init_attr => "attr->op_mode = op_mode;", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, + emit =>'. rdf%M %D0, %S0, %S1', + outs => [ "res", "M" ], +}, -# commutative operations +fpaRdf_i => { + comment => "construct FPA reverse Div: Div(a, b) = b / a", + attr => "ir_mode *op_mode, tarval *tv", + init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->value = tv;', + cmp_attr => 'return attr_a->value != attr_b->value;', + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] }, + emit =>'. rdf%M %D0, %S0, %S1', + outs => [ "res", "M" ], +}, -"fAddd" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct DP FP Add: Add(a, b) = Add(b, a) = a + b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" => '. FADDD %D1, %S1, %S2\t\t\t/* FP Add(%S1, %S2) -> %D1 */' +fpaFdv => { + comment => "construct FPA Fast Div: Div(a, b) = a / b", + 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" ], }, -"fAdds" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct SP FP Add: Add(a, b) = Add(b, a) = a + b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" => '. FADDS %D1, %S1, %S2\t\t\t/* FP Add(%S1, %S2) -> %D1 */' +fpaFdv_i => { + comment => "construct FPA Fast Div: Div(a, b) = a / b", + attr => "ir_mode *op_mode, tarval *tv", + init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->value = tv;', + cmp_attr => 'return attr_a->value != attr_b->value;', + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] }, + emit =>'. fdv%M %D0, %S0, %C', + outs => [ "res", "M" ], }, -"fMuls" => { - "op_flags" => "C", - "comment" => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" =>'. FMULS %D1, %S1, %S2\t\t\t/* FP Mul(%S1, %S2) -> %D1 */' +fpaFrd => { + comment => "construct FPA Fast reverse Div: Div(a, b) = b / a", + attr => "ir_mode *op_mode", + init_attr => "attr->op_mode = op_mode;", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, + emit =>'. frd%M %D0, %S0, %S1', + outs => [ "res", "M" ], }, -"fMuld" => { - "op_flags" => "C", - "comment" => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" =>'. FMULD %D1, %S1, %S2\t\t\t/* FP Mul(%S1, %S2) -> %D1 */' +fpaFrd_i => { + comment => "construct FPA Fast reverse Div: Div(a, b) = b / a", + attr => "ir_mode *op_mode, tarval *tv", + init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->value = tv;', + cmp_attr => 'return attr_a->value != attr_b->value;', + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] }, + emit =>'. frd%M %D0, %S0, %C', + outs => [ "res", "M" ], }, -"fDivs" => { - "comment" => "construct FP Div: Div(a, b) = a / b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" =>'. FDIVS %D1, %S1, %S2\t\t\t/* FP Div(%S1, %S2) -> %D1 */' +fpaMvf => { + irn_flags => "R", + comment => "construct FPA Move: b = a", + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. mvf%M %S0, %D0', }, -"fDivd" => { - "comment" => "construct FP Div: Div(a, b) = a / b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" =>'. FDIVD %D1, %S1, %S2\t\t\t/* FP Div(%S1, %S2) -> %D1 */' +fpaMvf_i => { + irn_flags => "R", + comment => "represents a float constant", + attr => "tarval *tv", + init_attr => 'ARM_SET_FPA_IMM(attr); attr->value = tv;', + reg_req => { "out" => [ "fpa" ] }, + mode => "get_tarval_mode(tv)", + emit => '. mvf %D0, %C', + cmp_attr => 'return attr_a->value != attr_b->value;' }, -"fDiv" => { - "comment" => "construct FP Div: Div(a, b) = a / b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" =>'. FDIV %D1, %S1, %S2\t\t\t/* FP Div(%S1, %S2) -> %D1 */' +fpaMnf => { + irn_flags => "R", + comment => "construct FPA Move Negated: b = -a", + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. mnf%M %S0, %D0', }, -"fMax" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" =>'. fmax %S1, %S2, %D1\t\t\t/* FP Max(%S1, %S2) -> %D1 */' +fpaMnf_i => { + irn_flags => "R", + comment => "represents a float constant", + attr => "tarval *tv", + init_attr => 'ARM_SET_FPA_IMM(attr); attr->value = tv;', + reg_req => { "out" => [ "fpa" ] }, + mode => "get_tarval_mode(tv)", + emit => '. mnf %D0, %C', + cmp_attr => 'return attr_a->value != attr_b->value;' }, -"fMin" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" =>'. fmin %S1, %S2, %D1\t\t\t/* FP Min(%S1, %S2) -> %D1 */' +fpaAbs => { + irn_flags => "R", + comment => "construct FPA Absolute value: fAbsd(a) = |a|", + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. abs%M %D0, %S0', }, -# not commutative operations +# other operations -"fSubs" => { - "irn_flags" => "R", - "comment" => "construct FP Sub: Sub(a, b) = a - b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" => '. FSUBS %D1, %S1, %S2\t\t\t/* FP Sub(%S1, %S2) -> %D1 */' +fpaFlt => { + irn_flags => "R", + comment => "construct a FPA integer->float conversion", + reg_req => { "in" => ["gp"], "out" => [ "fpa" ] }, + emit => '. flt%M %D0, %S0', }, -"fSubd" => { - "irn_flags" => "R", - "comment" => "construct FP Sub: Sub(a, b) = a - b", - "reg_req" => { "in" => [ "floating_point", "floating_point" ], "out" => [ "floating_point" ] }, - "emit" => '. FSUBD %D1, %S1, %S2\t\t\t/* FP Sub(%S1, %S2) -> %D1 */' +fpaFix => { + irn_flags => "R", + comment => "construct a FPA float->integer conversion", + reg_req => { "in" => ["fpa"], "out" => [ "gp" ] }, + emit => '. fix %D0, %S0', }, -"fMinus" => { - "irn_flags" => "R", - "comment" => "construct FP Minus: Minus(a) = -a", - "reg_req" => { "in" => [ "floating_point" ], "out" => [ "floating_point" ] }, - "emit" => '. fneg %S1, %D1\t\t\t/* FP Minus(%S1) -> %D1 */' +fpaCmfBra => { + op_flags => "L|X|Y", + state => "pinned", + comment => "construct floating point Compare and Branch: CMF A, B && JMPxx LABEL", + mode => "mode_T", + attr => "int proj_num", + init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] }, + attr_type => "arm_CondJmp_attr_t", }, -"fAbss" => { - "irn_flags" => "R", - "comment" => "construct FP Absolute value: fAbss(a) = |a|", - "reg_req" => { "in" => [ "floating_point" ], "out" => [ "floating_point" ] }, - "emit" => '. FABSS %D1, %S1\t\t\t/* FP Abss(%S1) -> %D1 */' +fpaCnfBra => { + op_flags => "L|X|Y", + state => "pinned", + comment => "construct floating point Compare negative and Branch: CMF A, -B && JMPxx LABEL", + mode => "mode_T", + attr => "int proj_num", + init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] }, + attr_type => "arm_CondJmp_attr_t", }, -"fAbsd" => { - "irn_flags" => "R", - "comment" => "construct FP Absolute value: fAbsd(a) = |a|", - "reg_req" => { "in" => [ "floating_point" ], "out" => [ "floating_point" ] }, - "emit" => '. FABSD %D1, %S1\t\t\t/* FP Absd(%S1) -> %D1 */' +fpaCmfeBra => { + op_flags => "L|X|Y", + state => "pinned", + comment => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL", + mode => "mode_T", + attr => "int proj_num", + init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] }, + attr_type => "arm_CondJmp_attr_t", }, -# other operations +fpaCnfeBra => { + op_flags => "L|X|Y", + state => "pinned", + comment => "construct floating point Compare and Branch: CMF A, -B && JMPxx LABEL", + mode => "mode_T", + attr => "int proj_num", + init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "none", "none"] }, + attr_type => "arm_CondJmp_attr_t", +}, -"fConst" => { - "op_flags" => "c", - "irn_flags" => "R", - "comment" => "represents a FP constant", - "reg_req" => { "out" => [ "floating_point" ] }, - "emit" => '. FMOV %D1, %C\t\t\t/* Mov fConst into register */', - "cmp_attr" => -' if (attr_a->value == NULL || attr_b->value == NULL) - return 1; +# Load / Store - return get_tarval_double(attr_a->value) != get_tarval_double(attr_b->value);' +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]', + outs => [ "res", "M" ], }, -"fConvD2S" => { - "irn_flags" => "R", - "comment" => "convert double to single", - "reg_req" => { "in" => [ "floating_point" ], "out" => [ "floating_point" ] }, - "emit" => '. FCVTSD %D1, %S1\t\t\t/* Convert double to single */', +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, [%S0]', + mode => "mode_M", }, -"fConvS2D" => { - "irn_flags" => "R", - "comment" => "convert single to double", - "reg_req" => { "in" => [ "floating_point" ], "out" => [ "floating_point" ] }, - "emit" => '. FCVTDS %D1, %S1\t\t\t/* Convert single to double */', +fpaDbl2GP => { + op_flags => "L|F", + irn_flags => "R", + comment => "construct fp double to 2 gp register transfer", + reg_req => { "in" => [ "fpa", "none" ], "out" => [ "gp", "gp", "none" ] }, + outs => [ "low", "high", "M" ], }, +AddSP => { + irn_flags => "I", + comment => "construct Add to stack pointer", + reg_req => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] }, + emit => '. add %D0, %S0, %S1', + outs => [ "stack:S", "M" ], +}, -# Load / Store +SubSP => { + irn_flags => "I", + comment => "construct Sub from stack pointer", + reg_req => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] }, + emit => '. sub %D0, %S0, %S1', + outs => [ "stack:S", "M" ], +}, -"fLoads" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct FP Load: Load(ptr, mem) = LD ptr", - "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "floating_point" ] }, - "emit" => '. FLDS %D1, %S1\t\t\t/* Load((%S1)) -> %D1 */' -# "emit" => '. fmov %O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1 */' -}, - -"fLoadd" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct FP Load: Load(ptr, mem) = LD ptr", - "reg_req" => { "in" => [ "general_purpose", "none" ], "out" => [ "floating_point" ] }, - "emit" => '. FLDD %D1, %S1\t\t\t/* Load((%S1)) -> %D1 */' -# "emit" => '. fmov %O(%S1), %D1\t\t\t/* Load((%S1)) -> %D1 */' -}, - -"fStores" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "general_purpose", "floating_point", "none" ] }, - "emit" => '. FSTS %S2, %S1\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' -}, - -"fStored" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "general_purpose", "floating_point", "none" ] }, - "emit" => '. FSTD %S2, %S1\t\t\t/* Store(%S2) -> (%S1), (%A1, %A2) */' +LdTls => { + irn_flags => "R", + comment => "load the TLS address", + reg_req => { out => [ "gp" ] }, }, + +# +# floating point constants +# +fpaConst => { + op_flags => "c", + irn_flags => "R", + comment => "construct a floating point constant", + attr => "tarval *tv", + init_attr => "attr->value = tv;", + mode => "get_tarval_mode(tv)", + reg_req => { "out" => [ "fpa" ] }, +} + +#---------------------------------------------------# +# __ _ # +# / _| | | # +# __ _| |_ _ __ _ __ ___ __| | ___ ___ # +# \ \ / / _| '_ \ | '_ \ / _ \ / _` |/ _ \/ __| # +# \ V /| | | |_) | | | | | (_) | (_| | __/\__ \ # +# \_/ |_| | .__/ |_| |_|\___/ \__,_|\___||___/ # +# | | # +# |_| # +#---------------------------------------------------# + ); # end of %nodes