X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Farm_spec.pl;h=c1d510cbe8b22a1ab6dabef4ea29202f6d3a95d8;hb=5d79fe73922ccec0217bad72eca772e0487b7c49;hp=90d5fe909d69ad4b5a829c5e657091f2dab485d9;hpb=d3a2b29742fce2a95aed605fbbe83f4c8ac3a28b;p=libfirm diff --git a/ir/be/arm/arm_spec.pl b/ir/be/arm/arm_spec.pl index 90d5fe909..c1d510cbe 100644 --- a/ir/be/arm/arm_spec.pl +++ b/ir/be/arm/arm_spec.pl @@ -5,9 +5,7 @@ # 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; @@ -18,20 +16,24 @@ $comment_string = '/*'; # %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 @@ $comment_string = '/*'; # 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 @@ $comment_string = '/*'; # 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,15 +95,21 @@ $comment_string = '/*'; # 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 +# # 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 = ( - "gp" => [ + gp => [ { "name" => "r0", "type" => 1 }, { "name" => "r1", "type" => 1 }, { "name" => "r2", "type" => 1 }, @@ -110,23 +126,36 @@ $comment_string = '/*'; { "name" => "sp", "type" => 6 }, # this is our stack pointer { "name" => "lr", "type" => 3 }, # this is our return address { "name" => "pc", "type" => 6 }, # this is our program counter - { "name" => "rxx", "type" => 6 }, # dummy register for no_mem { "mode" => "mode_Iu" } ], - "fp" => [ + 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 }, - { "name" => "fxx", "type" => 6 }, # dummy register for no_mem - { "mode" => "mode_D" } + { "name" => "f4", "type" => 1 }, + { "name" => "f5", "type" => 1 }, + { "name" => "f6", "type" => 1 }, + { "name" => "f7", "type" => 1 }, + { "mode" => "mode_E" } ] ); # %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);", +); + #--------------------------------------------------# # _ # # (_) # @@ -138,6 +167,22 @@ $comment_string = '/*'; # |_| # #--------------------------------------------------# +$default_attr_type = "arm_attr_t"; + +%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", +); + %nodes = ( #-----------------------------------------------------------------# @@ -153,554 +198,661 @@ $comment_string = '/*'; # commutative operations -"Add" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b", - "attr" => "arm_shift_modifier mod, tarval *shf", - "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - "emit" => '. ADD %D1, %S1, %S2%X0 /* Add(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Add_i" => { - "irn_flags" => "R", - "comment" => "construct Add: Add(a, const) = Add(const, a) = a + const", - "attr" => "tarval *tv", - "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - "cmp_attr" => 'return attr_a->value != attr_b->value;', - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "emit" => '. ADD %D1, %S1, %C /* Add(%C, %S1) -> %D1, (%A1, const) */' -}, - -"Mul" => { - #"op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "!in_r1" ] }, - "emit" =>'. MUL %D1, %S1, %S2 /* Mul(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Mla" => { - #"op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct Mla: Mla(a, b, c) = a * b + c", - "reg_req" => { "in" => [ "gp", "gp", "gp" ], "out" => [ "!in_r1" ] }, - "emit" =>'. MLA %D1, %S1, %S2, %S3 /* Mla(%S1, %S2, %S3) -> %D1, (%A1, %A2, %A3) */' -}, - -"And" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct And: And(a, b) = And(b, a) = a AND b", - "attr" => "arm_shift_modifier mod, tarval *shf", - "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - "emit" => '. AND %D1, %S1, %S2%X0 /* And(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"And_i" => { - "irn_flags" => "R", - "comment" => "construct And: And(a, const) = And(const, a) = a AND const", - "attr" => "tarval *tv", - "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "emit" => '. AND %D1, %S1, %C /* And(%C, %S1) -> %D1, (%A1, const) */', - "cmp_attr" => 'return attr_a->value != attr_b->value;' -}, - -"Or" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b", - "attr" => "arm_shift_modifier mod, tarval *shf", - "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - "emit" => '. ORR %D1, %S1, %S2%X0 /* Or(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Or_i" => { - "irn_flags" => "R", - "comment" => "construct Or: Or(a, const) = Or(const, a) = a OR const", - "attr" => "tarval *tv", - "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "cmp_attr" => 'return attr_a->value != attr_b->value;', - "emit" => '. ORR %D1, %S1, %C /* Or(%C, %S1) -> %D1, (%A1, const) */' -}, - -"Eor" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b", - "attr" => "arm_shift_modifier mod, tarval *shf", - "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - "emit" => '. EOR %D1, %S1, %S2%X0 /* Xor(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Eor_i" => { - "irn_flags" => "R", - "comment" => "construct Eor: Eor(a, const) = Eor(const, a) = a EOR const", - "attr" => "tarval *tv", - "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "cmp_attr" => 'return attr_a->value != attr_b->value;', - "emit" => '. EOR %D1, %S1, %C /* Xor(%C, %S1) -> %D1, (%A1, const) */' +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 %D1, %S1, %S2%X0 /* AndNot(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Bic_i" => { - "irn_flags" => "R", - "comment" => "construct Bic: Bic(a, const) = a AND ~const", - "attr" => "tarval *tv", - "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "emit" => '. BIC %D1, %S1, %C /* AndNot(%C, %S1) -> %D1, (%A1, const) */', - "cmp_attr" => 'return attr_a->value != attr_b->value;' -}, - -"Sub" => { - "irn_flags" => "R", - "comment" => "construct Sub: Sub(a, b) = a - b", - "attr" => "arm_shift_modifier mod, tarval *shf", - "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - "emit" => '. SUB %D1, %S1, %S2%X0 /* Sub(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Sub_i" => { - "irn_flags" => "R", - "comment" => "construct Sub: Sub(a, const) = a - const", - "attr" => "tarval *tv", - "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - "cmp_attr" => 'return attr_a->value != attr_b->value;', - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "emit" => '. SUB %D1, %S1, %C /* Sub(%S1, %C) -> %D1, (%A1, const) */', -}, - -"Rsb" => { - "irn_flags" => "R", - "comment" => "construct Rsb: Rsb(a, b) = b - a", - "attr" => "arm_shift_modifier mod, tarval *shf", - "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - "emit" => '. RSB %D1, %S1, %S2%X0 /* Rsb(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Rsb_i" => { - "irn_flags" => "R", - "comment" => "construct Rsb: Rsb(a, const) = const - a", - "attr" => "tarval *tv", - "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "emit" => '. RSB %D1, %S1, %C /* Rsb(%S1, %C) -> %D1, (%A1, const) */', - "cmp_attr" => 'return attr_a->value != attr_b->value;' -}, - -"Shl" => { - "irn_flags" => "R", - "comment" => "construct Shl: Shl(a, b) = a << b", - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, - "emit" => '. MOV %D1, %S1, LSL %S2\t/* Shl(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Shr" => { - "irn_flags" => "R", - "comment" => "construct Shr: Shr(a, b) = a >> b", - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, - "emit" => '. MOV %D1, %S1, LSR %S2 /* Shr(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -"Shrs" => { - "irn_flags" => "R", - "comment" => "construct Shrs: Shrs(a, b) = a >> b", - "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, - "emit" => '. MOV %D1, %S1, ASR %S2\t\t /* Shrs(%S1, %S2) -> %D1, (%A1, %A2) */' -}, - -#"RotR" => { -# "irn_flags" => "R", -# "comment" => "construct RotR: RotR(a, b) = a ROTR b", -# "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] }, -# "emit" => '. MOV %D1, %S1, ROR %S2 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */' -## "emit" => '. ror %S1, %S2, %D1 /* RotR(%S1, %S2) -> %D1, (%A1, %A2) */' +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 %S1, %S2, %D1 /* RotL(%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_i" => { -# "irn_flags" => "R", -# "comment" => "construct RotL: RotL(a, const) = a ROTL const", -# "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, -# "emit" => '. rol %S1, %C, %D1 /* RotL(%S1, %C) -> %D1, (%A1, const) */' +#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 %D1, %S1%X0\t/* Mov(%S1%X0) -> %D1, (%A1) */' -}, - -"Mov_i" => { - "irn_flags" => "R", - "comment" => "represents an integer constant", - "attr" => "tarval *tv", - "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - "reg_req" => { "out" => [ "gp" ] }, - "emit" => '. MOV %D1, %C /* Mov Const into register */', - "cmp_attr" => 'return attr_a->value != attr_b->value;' -}, - -"Mvn" => { - "irn_flags" => "R", - "comment" => "construct Not: Not(a) = !a", - "attr" => "arm_shift_modifier mod, tarval *shf", - "init_attr" => 'ARM_SET_SHF_MOD(attr, mod); attr->value = shf;', - "cmp_attr" => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->value != attr_b->value);', - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "emit" => '. MVN %D1, %S1%X0 /* ~(%S1%X0) -> %D1, (%A1) */' -}, - -"Mvn_i" => { - "irn_flags" => "R", - "comment" => "represents a negated integer constant", - "attr" => "tarval *tv", - "init_attr" => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->value = tv;', - "cmp_attr" => 'return attr_a->value != attr_b->value;', - "reg_req" => { "out" => [ "gp" ] }, - "emit" => '. MVN %D1, %C /* Mov ~Const into register */', -}, - -"Abs" => { - "irn_flags" => "R", - "comment" => "construct Abs: Abs(a) = |a|", - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, - "emit" => -'. MOVS %S1, %S1, #0 /* set condition flag */\n -. RSBMI %D1, %S1, #0 /* Neg(%S1) -> %D1, (%A1) */' +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" => "just to get an empty register for calculations", - "reg_req" => { "out" => [ "gp" ] }, - "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" => [ "gp" ], "out" => [ "gp" ] }, +}, + +CopyB => { + op_flags => "F|H", + state => "pinned", + comment => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)", + attr => "tarval *tv", + init_attr => 'attr->value = tv;', + reg_req => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] }, + outs => [ "M" ], +}, + +SymConst => { + op_flags => "c", + irn_flags => "R", + comment => "represents a symbolic constant", + attr => "ident *id", + init_attr => "\tset_arm_symconst_id(res, id);", + reg_req => { "out" => [ "gp" ] }, + attr_type => "arm_SymConst_attr_t", +}, + +CondJmp => { + op_flags => "L|X|Y", + comment => "construct conditional jump: 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", +}, + +SwitchJmp => { + op_flags => "L|X|Y", + 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", }, -"Copy" => { - "comment" => "implements a register copy", - "reg_req" => { "in" => [ "gp" ], "out" => [ "gp" ] }, -}, +# Load / Store -"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" ] }, -}, +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" ], +}, + +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" ], +}, + +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" ], +}, + + +#---------------------------------------------------# +# __ _ # +# / _| | | # +# | |_ _ __ __ _ _ __ ___ __| | ___ ___ # +# | _| '_ \ / _` | | '_ \ / _ \ / _` |/ _ \/ __| # +# | | | |_) | (_| | | | | | (_) | (_| | __/\__ \ # +# |_| | .__/ \__,_| |_| |_|\___/ \__,_|\___||___/ # +# | | # +# |_| # +#---------------------------------------------------# -"SymConst" => { - "op_flags" => "c", - "irn_flags" => "R", - "comment" => "represents a symbolic constant", - "attr" => "const char *label", - "init_attr" => ' attr->symconst_label = label;', - "reg_req" => { "out" => [ "gp" ] }, -# "emit" => '. LDR %D1, %C /* Mov Const into register */', - "cmp_attr" => -' /* should be identical but ...*/ - return strcmp(attr_a->symconst_label, attr_b->symconst_label);' -}, +# commutative operations -"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"] }, +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', }, -"SwitchJmp" => { - "op_flags" => "L|X|Y", - "comment" => "construct switch", - "reg_req" => { "in" => [ "gp" ], "out" => [ "none" ] }, - "cmp_attr" => " return 0;\n", +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', }, -# Load / Store - -"Load" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp" ] }, - "emit" => '. LDR %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDR %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' -}, - -"Loadb" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp" ] }, - "emit" => '. LDRB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' -}, - -"Loadbs" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp" ] }, - "emit" => '. LDRSB %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRSB %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' +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', }, -"Loadh" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp" ] }, - "emit" => '. LDRH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' +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', }, -"Loadhs" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "gp" ] }, - "emit" => '. LDRSH %D1, [%S1, #0] /* Load((%S1)) -> %D1, (%A1) */' -# "emit" => '. LDRSH %D1, %S1, %O /* Load((%S1)) -> %D1, (%A1) */' +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', }, -"Storeb" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "gp", "gp", "none" ] }, - "emit" => '. STRB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' -}, +# not commutative operations -"Storebs" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "gp", "gp", "none" ] }, - "emit" => '. STRSB %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' +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' }, -"Storeh" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "gp", "gp", "none" ] }, - "emit" => '. STRH %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' +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' }, -"Storehs" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "gp", "gp", "none" ] }, - "emit" => '. STRSH%S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' +fpaDiv => { + 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" ], }, -"Store" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "gp", "gp", "none" ] }, - "emit" => '. STR %S2, [%S1, #0] /* Store(%S2) -> (%S1), (%A1, %A2) */' -# "emit" => '. movl %S2, %O(%S1) /* Store(%S2) -> (%S1), (%A1, %A2) */' +fpaRdv => { + 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" ], }, -"StoreStackM4Inc" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "sp", "gp", "gp", "gp", "gp", "none" ], "out" => [ "gp", "none" ] }, - "emit" => '. STMFD %S1!, {%S2, %S3, %S4, %S5} /* Store multiple on Stack*/' +fpaFDiv => { + 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" ], }, -"LoadStackM3" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "reg_req" => { "in" => [ "sp", "none" ], "out" => [ "gp", "gp", "gp", "none" ] }, - "emit" => '. LDMFD %S1, {%D1, %D2, %D3} /* Load multiple from Stack */' +fpaFRdv => { + comment => "construct FPA Fast reverse Div: Div(a, b) = b / a", + attr => "ir_mode *op_mode", + init_attr => "attr->op_mode = op_mode;", + reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa", "none" ] }, + emit =>'. frd%M %D0, %S0, %S1', + outs => [ "res", "M" ], }, - - - - - - - -#--------------------------------------------------------# -# __ _ _ _ # -# / _| | | | | | # -# | |_| | ___ __ _| |_ _ __ ___ __| | ___ ___ # -# | _| |/ _ \ / _` | __| | '_ \ / _ \ / _` |/ _ \/ __| # -# | | | | (_) | (_| | |_ | | | | (_) | (_| | __/\__ \ # -# |_| |_|\___/ \__,_|\__| |_| |_|\___/ \__,_|\___||___/ # -#--------------------------------------------------------# - -# commutative operations - -"fAdd" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct FP Add: Add(a, b) = Add(b, a) = a + b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" => '. FADD%Mx %D1, %S1, %S2 /* FP Add(%S1, %S2) -> %D1 */' +fpaMov => { + irn_flags => "R", + comment => "construct FPA Move: b = a", + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. mvf%M %S0, %D0', }, -"fMul" => { - "op_flags" => "C", - "comment" => "construct FP Mul: Mul(a, b) = Mul(b, a) = a * b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" =>'. FMUL%Mx %D1, %S1, %S2 /* FP Mul(%S1, %S2) -> %D1 */' +fpaMnv => { + irn_flags => "R", + comment => "construct FPA Move Negated: b = -a", + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. mnf%M %S0, %D0', }, -"fDiv" => { - "comment" => "construct FP Div: Div(a, b) = a / b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" =>'. FDIV%Mx %D1, %S1, %S2 /* FP Div(%S1, %S2) -> %D1 */' +fpaAbs => { + irn_flags => "R", + comment => "construct FPA Absolute value: fAbsd(a) = |a|", + reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] }, + emit => '. abs%M %D0, %S0', }, -"fMax" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct FP Max: Max(a, b) = Max(b, a) = a > b ? a : b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" =>'. fmax %S1, %S2, %D1 /* FP Max(%S1, %S2) -> %D1 */' +# other operations + +fpaFlt => { + irn_flags => "R", + comment => "construct a FPA integer->float conversion", + reg_req => { "in" => ["gp"], "out" => [ "fpa" ] }, + emit => '. flt%M %D0, %S0', }, -"fMin" => { - "op_flags" => "C", - "irn_flags" => "R", - "comment" => "construct FP Min: Min(a, b) = Min(b, a) = a < b ? a : b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" =>'. fmin %S1, %S2, %D1 /* FP Min(%S1, %S2) -> %D1 */' +fpaFix => { + irn_flags => "R", + comment => "construct a FPA float->integer conversion", + reg_req => { "in" => ["fpa"], "out" => [ "gp" ] }, + emit => '. fix %D0, %S0', }, -# not commutative operations +# Load / Store -"fSub" => { - "irn_flags" => "R", - "comment" => "construct FP Sub: Sub(a, b) = a - b", - "reg_req" => { "in" => [ "fp", "fp" ], "out" => [ "fp" ] }, - "emit" => '. FSUB%Mx %D1, %S1, %S2 /* FP Sub(%S1, %S2) -> %D1 */' +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" ], }, -"fNeg" => { - "irn_flags" => "R", - "comment" => "construct FP Neg: Neg(a) = -a", - "reg_req" => { "in" => [ "fp" ], "out" => [ "fp" ] }, - "emit" => '. fneg %S1, %D1 /* FP Neg(%S1) -> %D1 */' +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" ], }, -"fAbs" => { - "irn_flags" => "R", - "comment" => "construct FP Absolute value: fAbsd(a) = |a|", - "reg_req" => { "in" => [ "fp" ], "out" => [ "fp" ] }, - "emit" => '. FABS%Mx %D1, %S1 /* FP Absd(%S1) -> %D1 */' +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" ], }, -# other operations - -"fConst" => { - "op_flags" => "c", - "irn_flags" => "R", - "comment" => "represents a FP constant", - "attr" => "tarval *val", - "init_attr" => 'attr->value = val;', - "reg_req" => { "out" => [ "fp" ] }, - "emit" => '. FMOV %D1, %C /* Mov fConst into register */', - "cmp_attr" => 'return attr_a->value != attr_b->value;' +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" ], }, -"fConvD2S" => { - "irn_flags" => "R", - "comment" => "convert double to single", - "reg_req" => { "in" => [ "fp" ], "out" => [ "fp" ] }, - "emit" => '. FCVTSD %D1, %S1 /* Convert double to single */', +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" ], }, -"fConvS2D" => { - "irn_flags" => "R", - "comment" => "convert single to double", - "reg_req" => { "in" => [ "fp" ], "out" => [ "fp" ] }, - "emit" => '. FCVTDS %D1, %S1 /* Convert single to double */', +LdTls => { + irn_flags => "R", + comment => "load the TLS address", + reg_req => { out => [ "gp" ] }, }, -# Load / Store - -"fLoad" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct FP Load: Load(ptr, mem) = LD ptr", - "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "fp" ] }, - "emit" => '. FLD%Mx %D1, %S1 /* Load((%S1)) -> %D1 */' -}, - -"fStore" => { - "op_flags" => "L|F", - "irn_flags" => "R", - "state" => "exc_pinned", - "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "reg_req" => { "in" => [ "gp", "fp", "none" ] }, - "emit" => '. FST%Mx %S2, %S1 /* Store(%S2) -> (%S1), (%A1, %A2) */' -}, +# +# floating point constants +# +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