* @author Oliver Richter, Tobias Gneist, Michael Beck
* @version $Id$
*/
-#define SILENCER
-
#include "config.h"
#include <limits.h>
#include "../benode.h"
#define BLOCK_PREFIX ".L"
-
#define SNPRINTF_BUF_LEN 128
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
be_emit_cstring(" */");
be_emit_finish_line_gas(proj_false);
} else {
- be_emit_cstring("b ");
+ be_emit_cstring("\tb ");
arm_emit_cfop_target(proj_false);
be_emit_finish_line_gas(proj_false);
}
/* emit_be */
/************************************************************************/
-static void emit_be_Call(const ir_node *irn) {
- ir_entity *ent = be_Call_get_entity(irn);
+static void arm_emit_entity(ir_entity *entity)
+{
+ set_entity_backend_marked(entity, 1);
+ be_emit_ident(get_entity_ld_ident(entity));
+}
+
+static void emit_be_Call(const ir_node *irn)
+{
+ ir_entity *entity = be_Call_get_entity(irn);
- be_emit_cstring("\tbl ");
- if (ent) {
- set_entity_backend_marked(ent, 1);
- be_emit_ident(get_entity_ld_ident(ent));
+ if (entity != NULL) {
+ be_emit_cstring("\tbl ");
+ arm_emit_entity(entity);
+ be_emit_finish_line_gas(irn);
} else {
+ be_emit_cstring("\tmov lr, pc");
+ be_emit_finish_line_gas(irn);
+ be_emit_cstring("\tmov pc, ");
arm_emit_source_register(irn, be_pos_Call_ptr);
+ be_emit_finish_line_gas(irn);
}
- be_emit_finish_line_gas(irn);
}
/** Emit an IncSP node */
be_emit_finish_line_gas(irn);
}
-static void emit_be_Perm(const ir_node *irn) {
+static void emit_be_Perm(const ir_node *irn)
+{
be_emit_cstring("\teor ");
arm_emit_source_register(irn, 0);
be_emit_cstring(", ");
be_emit_finish_line_gas(irn);
}
+static void emit_be_MemPerm(const ir_node *node)
+{
+ int i;
+ int memperm_arity;
+ int sp_change = 0;
+
+ /* TODO: this implementation is slower than necessary.
+ The longterm goal is however to avoid the memperm node completely */
+
+ memperm_arity = be_get_MemPerm_entity_arity(node);
+ if (memperm_arity > 12)
+ panic("memperm with more than 12 inputs not supported yet");
+
+ for (i = 0; i < memperm_arity; ++i) {
+ int offset;
+ ir_entity *entity = be_get_MemPerm_in_entity(node, i);
+
+ /* spill register */
+ be_emit_irprintf("\tstr r%d, [sp, #-4]!", i);
+ be_emit_finish_line_gas(node);
+ sp_change += 4;
+ /* load from entity */
+ offset = get_entity_offset(entity) + sp_change;
+ be_emit_irprintf("\tldr r%d, [sp, #%d]", i, offset);
+ be_emit_finish_line_gas(node);
+ }
+
+ for (i = memperm_arity-1; i >= 0; --i) {
+ int offset;
+ ir_entity *entity = be_get_MemPerm_out_entity(node, i);
+
+ /* store to new entity */
+ offset = get_entity_offset(entity) + sp_change;
+ be_emit_irprintf("\tstr r%d, [sp, #%d]", i, offset);
+ be_emit_finish_line_gas(node);
+ /* restore register */
+ be_emit_irprintf("\tldr r%d, [sp], #4", i);
+ sp_change -= 4;
+ be_emit_finish_line_gas(node);
+ }
+ assert(sp_change == 0);
+}
+
+static void emit_be_Return(const ir_node *node)
+{
+ be_emit_cstring("\tmov pc, lr");
+ be_emit_finish_line_gas(node);
+}
+
/************************************************************************/
/* emit */
/************************************************************************/
-static void emit_Jmp(const ir_node *node) {
+static void emit_arm_Jmp(const ir_node *node)
+{
ir_node *block, *next_block;
/* for now, the code works for scheduled and non-schedules blocks */
*
***********************************************************************************/
-static void emit_silence(const ir_node *irn) {
+static void emit_nothing(const ir_node *irn)
+{
(void) irn;
- /* Do nothing. */
}
/**
/**
* Set a node emitter. Make it a bit more type safe.
*/
-static inline void set_emitter(ir_op *op, emit_func arm_emit_node) {
+static inline void set_emitter(ir_op *op, emit_func arm_emit_node)
+{
op->ops.generic = (op_func)arm_emit_node;
}
* Enters the emitter functions for handled nodes into the generic
* pointer of an opcode.
*/
-static void arm_register_emitters(void) {
-
-#define ARM_EMIT(a) set_emitter(op_arm_##a, emit_arm_##a)
-#define EMIT(a) set_emitter(op_##a, emit_##a)
-#define BE_EMIT(a) set_emitter(op_be_##a, emit_be_##a)
-#define SILENCE(a) set_emitter(op_##a, emit_silence)
-
+static void arm_register_emitters(void)
+{
/* first clear the generic function pointer for all ops */
clear_irp_opcodes_generic_func();
/* register all emitter functions defined in spec */
arm_register_spec_emitters();
- /* other emitter functions */
- ARM_EMIT(CmpBra);
- ARM_EMIT(TstBra);
- ARM_EMIT(fpaCmfBra);
- ARM_EMIT(fpaCmfeBra);
- ARM_EMIT(CopyB);
-// ARM_EMIT(CopyB_i);
-// ARM_EMIT(Const);
- ARM_EMIT(SymConst);
- ARM_EMIT(SwitchJmp);
- ARM_EMIT(fpaDbl2GP);
- ARM_EMIT(fpaConst);
- ARM_EMIT(LdTls);
-
- /* benode emitter */
- BE_EMIT(Call);
- BE_EMIT(IncSP);
- BE_EMIT(Copy);
- BE_EMIT(Spill);
- BE_EMIT(Reload);
- BE_EMIT(Perm);
-
- /* firm emitter */
- EMIT(Jmp);
-
- /* noisy stuff */
-#ifdef SILENCER
- SILENCE(Proj);
- SILENCE(Phi);
- SILENCE(be_Keep);
- SILENCE(be_CopyKeep);
- SILENCE(be_Start);
- SILENCE(be_Barrier);
- SILENCE(be_Return);
-#endif
-
-#undef ARM_EMIT
-#undef BE_EMIT
-#undef EMIT
-#undef SILENCE
+ /* custom emitter */
+ set_emitter(op_arm_CmpBra, emit_arm_CmpBra);
+ set_emitter(op_arm_CopyB, emit_arm_CopyB);
+ set_emitter(op_arm_fpaCmfBra, emit_arm_fpaCmfBra);
+ set_emitter(op_arm_fpaCmfeBra, emit_arm_fpaCmfeBra);
+ set_emitter(op_arm_fpaConst, emit_arm_fpaConst);
+ set_emitter(op_arm_fpaDbl2GP, emit_arm_fpaDbl2GP);
+ set_emitter(op_arm_Jmp, emit_arm_Jmp);
+ set_emitter(op_arm_LdTls, emit_arm_LdTls);
+ set_emitter(op_arm_SwitchJmp, emit_arm_SwitchJmp);
+ set_emitter(op_arm_SymConst, emit_arm_SymConst);
+ set_emitter(op_arm_TstBra, emit_arm_TstBra);
+ set_emitter(op_be_Call, emit_be_Call);
+ set_emitter(op_be_Copy, emit_be_Copy);
+ set_emitter(op_be_IncSP, emit_be_IncSP);
+ set_emitter(op_be_MemPerm, emit_be_MemPerm);
+ set_emitter(op_be_Perm, emit_be_Perm);
+ set_emitter(op_be_Reload, emit_be_Reload);
+ set_emitter(op_be_Return, emit_be_Return);
+ set_emitter(op_be_Spill, emit_be_Spill);
+
+ /* no need to emit anything for the following nodes */
+ set_emitter(op_Phi, emit_nothing);
+ set_emitter(op_be_Keep, emit_nothing);
+ set_emitter(op_be_Start, emit_nothing);
+ set_emitter(op_be_Barrier, emit_nothing);
}
/**
be_dbg_set_dbg_info(get_irn_dbg_info(irn));
(*emit)(irn);
} else {
- be_emit_cstring("\t/* TODO */");
- be_emit_finish_line_gas(irn);
+ panic("Error: No emit handler for node %+F (graph %+F)\n",
+ irn, current_ir_graph);
}
}
# the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
$arch = "arm";
-$new_emit_syntax = 1;
# the number of additional opcodes you want to register
#$additional_opcodes = 0;
# NOTE: Last entry of each class is the largest Firm-Mode a register can hold
%reg_classes = (
gp => [
- { "name" => "r0", "type" => $caller_save },
- { "name" => "r1", "type" => $caller_save },
- { "name" => "r2", "type" => $caller_save },
- { "name" => "r3", "type" => $caller_save },
- { "name" => "r4", "type" => $callee_save },
- { "name" => "r5", "type" => $callee_save },
- { "name" => "r6", "type" => $callee_save },
- { "name" => "r7", "type" => $callee_save },
- { "name" => "r8", "type" => $callee_save },
- { "name" => "r9", "type" => $callee_save },
- { "name" => "r10", "type" => $callee_save },
- { "name" => "r11", "type" => $callee_save },
- { "name" => "r12", "type" => $ignore | $callee_save }, # reserved for linker
- { "name" => "sp", "type" => $ignore | $callee_save }, # this is our stack pointer
- { "name" => "lr", "type" => $callee_save | $caller_save }, # this is our return address
- { "name" => "pc", "type" => $ignore | $callee_save }, # this is our program counter
+ { name => "r0", type => $caller_save },
+ { name => "r1", type => $caller_save },
+ { name => "r2", type => $caller_save },
+ { name => "r3", type => $caller_save },
+ { name => "r4", type => $callee_save },
+ { name => "r5", type => $callee_save },
+ { name => "r6", type => $callee_save },
+ { name => "r7", type => $callee_save },
+ { name => "r8", type => $callee_save },
+ { name => "r9", type => $callee_save },
+ { name => "r10", type => $callee_save },
+ { name => "r11", type => $callee_save },
+ { name => "r12", type => $ignore | $callee_save }, # reserved for linker
+ { name => "sp", type => $ignore | $callee_save }, # this is our stack pointer
+ { name => "lr", type => $callee_save | $caller_save }, # this is our return address
+ { name => "pc", type => $ignore | $callee_save }, # this is our program counter
{ name => "gp_UKNWN", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for Unknown nodes
- { "mode" => $mode_gp }
+ { 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 }
+ { name => "f0", type => $caller_save },
+ { name => "f1", type => $caller_save },
+ { name => "f2", type => $caller_save },
+ { name => "f3", type => $caller_save },
+ { name => "f4", type => $caller_save },
+ { name => "f5", type => $caller_save },
+ { name => "f6", type => $caller_save },
+ { name => "f7", type => $caller_save },
+ { name => "fpa_UKNWN", type => $ignore | $arbitrary | $virtual }, # we need a dummy register for Unknown nodes
+ { mode => $mode_fpa }
]
-); # %reg_classes
+);
%emit_templates = (
M => "${arch}_emit_mode(node);",
arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
arm_fpaConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
+ arm_load_store_attr_t =>
+ "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
+ "\tinit_arm_load_store_attributes(res, entity, entity_sign, offset);",
);
%compare_attr = (
- arm_attr_t => "cmp_attr_arm",
- arm_SymConst_attr_t => "cmp_attr_arm_SymConst",
- arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp",
- arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
- arm_fpaConst_attr_t => "cmp_attr_arm_fpaConst",
+ arm_attr_t => "cmp_attr_arm",
+ arm_SymConst_attr_t => "cmp_attr_arm_SymConst",
+ arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp",
+ arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
+ arm_fpaConst_attr_t => "cmp_attr_arm_fpaConst",
+ arm_load_store_attr_t => "cmp_attr_arm_load_store",
);
#%operands = (
comment => "construct Add: Add(a, b) = Add(b, a) = a + b",
attr => "arm_shift_modifier mod, long shf",
init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
- cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
emit => '. add %D0, %S0, %S1%X'
},
comment => "construct Add: Add(a, const) = Add(const, a) = a + const",
attr => "long imm",
init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
emit => '. add %D0, %S0, %C'
},
comment => "construct And: And(a, b) = And(b, a) = a AND b",
attr => "arm_shift_modifier mod, long shf",
init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
- cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
emit => '. and %D0, %S0, %S1%X'
},
init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
emit => '. and %D0, %S0, %C',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
},
Or => {
comment => "construct Or: Or(a, b) = Or(b, a) = a OR b",
attr => "arm_shift_modifier mod, long shf",
init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
- cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
emit => '. orr %D0, %S0, %S1%X'
},
attr => "long imm",
init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
emit => '. orr %D0, %S0, %C'
},
comment => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b",
attr => "arm_shift_modifier mod, long shf",
init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
- cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
emit => '. eor %D0, %S0, %S1%X'
},
attr => "long imm",
init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
emit => '. eor %D0, %S0, %C'
},
comment => "construct Bic: Bic(a, b) = a AND ~b",
attr => "arm_shift_modifier mod, long shf",
init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
- cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
emit => '. bic %D0, %S0, %S1%X'
},
init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
emit => '. bic %D0, %S0, %C',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
},
Sub => {
comment => "construct Sub: Sub(a, b) = a - b",
attr => "arm_shift_modifier mod, long shf",
init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
- cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
emit => '. sub %D0, %S0, %S1%X'
},
comment => "construct Sub: Sub(a, const) = a - const",
attr => "long imm",
init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
emit => '. sub %D0, %S0, %C',
},
comment => "construct Rsb: Rsb(a, b) = b - a",
attr => "arm_shift_modifier mod, long shf",
init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
- cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
reg_req => { "in" => [ "gp", "gp" ], "out" => [ "gp" ] },
emit => '. rsb %D0, %S0, %S1%X'
},
init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
emit => '. rsb %D0, %S0, %C',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
},
Shl => {
comment => "construct Mov: a = b",
attr => "arm_shift_modifier mod, long shf",
init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
- cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
emit => '. mov %D0, %S0%X'
},
init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
reg_req => { "out" => [ "gp" ] },
emit => '. mov %D0, %C',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
},
Mvn => {
comment => "construct Not: Not(a) = !a",
attr => "arm_shift_modifier mod, long shf",
init_attr => 'ARM_SET_SHF_MOD(attr, mod); attr->imm_value = shf;',
- cmp_attr => 'return (attr_a->instr_fl != attr_b->instr_fl) || (attr_a->imm_value != attr_b->imm_value);',
reg_req => { "in" => [ "gp" ], "out" => [ "gp" ] },
emit => '. mvn %D0, %S0%X'
},
comment => "represents a negated integer constant",
attr => "long imm",
init_attr => 'ARM_SET_SHF_MOD(attr, ARM_SHF_IMM); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "out" => [ "gp" ] },
emit => '. mvn %D0, %C',
},
comment => "implements a memcopy: CopyB(dst, src, size, mem) == memcpy(dst, src, size)",
attr => "long imm",
init_attr => 'attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], "out" => [ "none" ] },
outs => [ "M" ],
},
attr_type => "arm_CondJmp_attr_t",
},
+Jmp => {
+ state => "pinned",
+ op_flags => "X",
+ irn_flags => "J",
+ reg_req => { out => [ "none" ] },
+ mode => "mode_X",
+},
+
SwitchJmp => {
op_flags => "L|X|Y",
state => "pinned",
# Load / Store
-Load => {
+Ldr => {
op_flags => "L|F",
- irn_flags => "R",
state => "exc_pinned",
- comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+ ins => [ "ptr", "mem" ],
+ outs => [ "res", "M" ],
reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
emit => '. ldr %D0, [%S0, #0]',
- outs => [ "res", "M" ],
+ attr_type => "arm_load_store_attr_t",
+ attr => "ir_entity *entity, int entity_sign, long offset",
},
-Loadb => {
+Ldrb => {
op_flags => "L|F",
- irn_flags => "R",
state => "exc_pinned",
- comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+ ins => [ "ptr", "mem" ],
+ outs => [ "res", "M" ],
reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
emit => '. ldrb %D0, [%S0, #0]',
- outs => [ "res", "M" ],
+ attr_type => "arm_load_store_attr_t",
+ attr => "ir_entity *entity, int entity_sign, long offset",
},
-Loadbs => {
+Ldrbs => {
op_flags => "L|F",
- irn_flags => "R",
state => "exc_pinned",
- comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+ ins => [ "ptr", "mem" ],
+ outs => [ "res", "M" ],
reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
emit => '. ldrsb %D0, [%S0, #0]',
- outs => [ "res", "M" ],
+ attr_type => "arm_load_store_attr_t",
+ attr => "ir_entity *entity, int entity_sign, long offset",
},
-Loadh => {
+Ldrh => {
op_flags => "L|F",
- irn_flags => "R",
state => "exc_pinned",
- comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+ ins => [ "ptr", "mem" ],
+ outs => [ "res", "M" ],
reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
emit => '. ldrh %D0, [%S0, #0]',
- outs => [ "res", "M" ],
+ attr_type => "arm_load_store_attr_t",
+ attr => "ir_entity *entity, int entity_sign, long offset",
},
-Loadhs => {
+Ldrhs => {
op_flags => "L|F",
- irn_flags => "R",
state => "exc_pinned",
- comment => "construct Load: Load(ptr, mem) = LD ptr -> reg",
+ ins => [ "ptr", "mem" ],
+ outs => [ "res", "M" ],
reg_req => { "in" => [ "gp", "none" ], "out" => [ "gp", "none" ] },
emit => '. ldrsh %D0, [%S0, #0]',
- outs => [ "res", "M" ],
+ attr_type => "arm_load_store_attr_t",
+ attr => "ir_entity *entity, int entity_sign, long offset",
},
-Storeb => {
+Strb => {
op_flags => "L|F",
- irn_flags => "R",
state => "exc_pinned",
- comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+ ins => [ "ptr", "val", "mem" ],
+ outs => [ "mem" ],
reg_req => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] },
emit => '. strb %S1, [%S0, #0]',
mode => "mode_M",
+ attr_type => "arm_load_store_attr_t",
+ attr => "ir_entity *entity, int entity_sign, long offset",
},
-Storeh => {
+Strh => {
op_flags => "L|F",
- irn_flags => "R",
state => "exc_pinned",
- comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+ ins => [ "ptr", "val", "mem" ],
+ outs => [ "mem" ],
reg_req => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
emit => '. strh %S1, [%S0, #0]',
mode => "mode_M",
+ attr_type => "arm_load_store_attr_t",
+ attr => "ir_entity *entity, int entity_sign, long offset",
},
-Store => {
+Str => {
op_flags => "L|F",
- irn_flags => "R",
state => "exc_pinned",
- comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
+ ins => [ "ptr", "val", "mem" ],
+ outs => [ "mem" ],
reg_req => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
emit => '. str %S1, [%S0, #0]',
mode => "mode_M",
+ attr_type => "arm_load_store_attr_t",
+ attr => "ir_entity *entity, int entity_sign, long offset",
},
StoreStackM4Inc => {
comment => "construct FPA Add: Add(a, b) = Add(b, a) = a + b",
attr => "long imm",
init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
emit => '. adf%M %D0, %S0, %C',
},
comment => "construct FPA Mul: Mul(a, b) = Mul(b, a) = a * b",
attr => "long imm",
init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
emit => '. muf%M %D0, %S0, %C',
},
comment => "construct FPA Sub: Sub(a, b) = a - b",
attr => "long imm",
init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
emit => '. suf%M %D0, %S0, %C'
},
comment => "construct FPA reverse Sub: Sub(a, b) = b - a",
attr => "long imm",
init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "fpa" ], "out" => [ "fpa" ] },
emit => '. rsf%M %D0, %S0, %C'
},
comment => "construct FPA Div: Div(a, b) = a / b",
attr => "ir_mode *op_mode, long imm",
init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
emit =>'. dvf%M %D0, %S0, %C',
outs => [ "res", "M" ],
comment => "construct FPA reverse Div: Div(a, b) = b / a",
attr => "ir_mode *op_mode, long imm",
init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
emit =>'. rdf%M %D0, %S0, %S1',
outs => [ "res", "M" ],
comment => "construct FPA Fast Div: Div(a, b) = a / b",
attr => "ir_mode *op_mode, long imm",
init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
emit =>'. fdv%M %D0, %S0, %C',
outs => [ "res", "M" ],
comment => "construct FPA Fast reverse Div: Div(a, b) = b / a",
attr => "ir_mode *op_mode, long imm",
init_attr => 'attr->op_mode = op_mode; ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;',
reg_req => { "in" => [ "fpa" ], "out" => [ "fpa", "none" ] },
emit =>'. frd%M %D0, %S0, %C',
outs => [ "res", "M" ],
init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
reg_req => { "out" => [ "fpa" ] },
emit => '. mvf%M %D0, %C',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
},
fpaMnf => {
init_attr => 'ARM_SET_FPA_IMM(attr); attr->imm_value = imm;',
reg_req => { "out" => [ "fpa" ] },
emit => '. mnf%M %D0, %C',
- cmp_attr => 'return attr_a->imm_value != attr_b->imm_value;'
},
fpaAbs => {
return new_bd_arm_Mla(dbg, block, new_op1, new_op2, new_op3, mode);
}
+#if 0
/* is the first a shifter */
v = is_shifter_operand(new_op1, &mod);
if (v) {
new_op2 = get_irn_n(new_op2, 0);
return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, mod, v);
}
+#endif
/* normal ADD */
return new_bd_arm_Add(dbg, block, new_op1, new_op2, mode, ARM_SHF_NONE, 0);
/* sign extended loads */
switch (get_mode_size_bits(mode)) {
case 8:
- new_load = new_bd_arm_Loadbs(dbg, block, new_ptr, new_mem);
+ new_load = new_bd_arm_Ldrbs(dbg, block, new_ptr, new_mem, NULL,
+ 0, 0);
break;
case 16:
- new_load = new_bd_arm_Loadhs(dbg, block, new_ptr, new_mem);
+ new_load = new_bd_arm_Ldrhs(dbg, block, new_ptr, new_mem, NULL,
+ 0, 0);
break;
case 32:
- new_load = new_bd_arm_Load(dbg, block, new_ptr, new_mem);
+ new_load = new_bd_arm_Ldr(dbg, block, new_ptr, new_mem, NULL,
+ 0, 0);
break;
default:
panic("mode size not supported");
/* zero extended loads */
switch (get_mode_size_bits(mode)) {
case 8:
- new_load = new_bd_arm_Loadb(dbg, block, new_ptr, new_mem);
+ new_load = new_bd_arm_Ldrb(dbg, block, new_ptr, new_mem, NULL,
+ 0, 0);
break;
case 16:
- new_load = new_bd_arm_Loadh(dbg, block, new_ptr, new_mem);
+ new_load = new_bd_arm_Ldrh(dbg, block, new_ptr, new_mem, NULL,
+ 0, 0);
break;
case 32:
- new_load = new_bd_arm_Load(dbg, block, new_ptr, new_mem);
+ new_load = new_bd_arm_Ldr(dbg, block, new_ptr, new_mem, NULL,
+ 0, 0);
break;
default:
panic("mode size not supported");
/* check for special case: the loaded value might not be used */
if (be_get_Proj_for_pn(node, pn_Load_res) == NULL) {
/* add a result proj and a Keep to produce a pseudo use */
- ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Load_res);
+ ir_node *proj = new_r_Proj(block, new_load, mode_Iu, pn_arm_Ldr_res);
be_new_Keep(block, 1, &proj);
}
*
* @return the created ARM Store node
*/
-static ir_node *gen_Store(ir_node *node) {
+static ir_node *gen_Store(ir_node *node)
+{
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *ptr = get_Store_ptr(node);
ir_node *new_ptr = be_transform_node(ptr);
assert(mode_is_data(mode) && "unsupported mode for Store");
switch (get_mode_size_bits(mode)) {
case 8:
- new_store = new_bd_arm_Storeb(dbg, block, new_ptr, new_val, new_mem);
+ new_store = new_bd_arm_Strb(dbg, block, new_ptr, new_val, new_mem,
+ NULL, 0, 0);
+ break;
case 16:
- new_store = new_bd_arm_Storeh(dbg, block, new_ptr, new_val, new_mem);
+ new_store = new_bd_arm_Strh(dbg, block, new_ptr, new_val, new_mem,
+ NULL, 0, 0);
+ break;
+ case 32:
+ new_store = new_bd_arm_Str(dbg, block, new_ptr, new_val, new_mem,
+ NULL, 0, 0);
+ break;
default:
- new_store = new_bd_arm_Store(dbg, block, new_ptr, new_val, new_mem);
+ panic("unsupported store size %d bits\n", get_mode_size_bits(mode));
}
}
set_irn_pinned(new_store, get_irn_pinned(node));
return new_store;
}
+static ir_node *gen_Jmp(ir_node *node)
+{
+ ir_node *block = get_nodes_block(node);
+ ir_node *new_block = be_transform_node(block);
+ dbg_info *dbgi = get_irn_dbg_info(node);
+
+ return new_bd_arm_Jmp(dbgi, new_block);
+}
+
/**
* Transforms a Cond.
*
/* renumber the proj */
switch (get_arm_irn_opcode(new_load)) {
- case iro_arm_Load:
- case iro_arm_Loadb:
- case iro_arm_Loadbs:
- case iro_arm_Loadh:
- case iro_arm_Loadhs:
+ case iro_arm_Ldr:
+ case iro_arm_Ldrb:
+ case iro_arm_Ldrbs:
+ case iro_arm_Ldrh:
+ case iro_arm_Ldrhs:
/* handle all gp loads equal: they have the same proj numbers. */
if (proj == pn_Load_res) {
- return new_rd_Proj(dbgi, block, new_load, mode_Iu, pn_arm_Load_res);
+ return new_rd_Proj(dbgi, block, new_load, mode_Iu, pn_arm_Ldr_res);
} else if (proj == pn_Load_M) {
- return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_Load_M);
+ return new_rd_Proj(dbgi, block, new_load, mode_M, pn_arm_Ldr_M);
}
break;
case iro_arm_fpaLdf:
/**
* Change some phi modes
*/
-static ir_node *gen_Phi(ir_node *node) {
+static ir_node *gen_Phi(ir_node *node)
+{
+ const arch_register_req_t *req;
ir_node *block = be_transform_node(get_nodes_block(node));
ir_graph *irg = current_ir_graph;
dbg_info *dbgi = get_irn_dbg_info(node);
assert(get_mode_size_bits(mode) <= 32);
/* all integer operations are on 32bit registers now */
mode = mode_Iu;
+ req = arm_reg_classes[CLASS_arm_gp].class_req;
+ } else {
+ req = arch_no_register_req;
}
/* phi nodes allow loops, so we use the old arguments for now
* and fix this later */
- phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node), get_irn_in(node) + 1);
+ phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node),
+ get_irn_in(node) + 1);
copy_node_attr(node, phi);
be_duplicate_deps(node, phi);
+ arch_set_out_register_req(phi, 0, req);
+
be_enqueue_preds(node);
return phi;
GEN(Load);
GEN(Store);
GEN(Cond);
+ GEN(Jmp);
BAD(ASM); /* unsupported yet */
GEN(CopyB);