Commit 72bd9213 authored by Matthias Braun's avatar Matthias Braun
Browse files

- bring arm backend back to shape: cleanup and fix lots of stuff

  disabled some broken transformers. (Queens, Quicksort and several other stuff from the
  testsuite work, but still lots of stuff broken)

[r26649]
parent 418806b2
......@@ -23,8 +23,6 @@
* @author Oliver Richter, Tobias Gneist, Michael Beck
* @version $Id$
*/
#define SILENCER
#include "config.h"
#include <limits.h>
......@@ -60,7 +58,6 @@
#include "../benode.h"
#define BLOCK_PREFIX ".L"
#define SNPRINTF_BUF_LEN 128
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
......@@ -439,7 +436,7 @@ static void emit_arm_CmpBra(const ir_node *irn) {
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);
}
......@@ -765,17 +762,27 @@ static void emit_arm_SwitchJmp(const ir_node *irn) {
/* 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 */
......@@ -893,7 +900,8 @@ static void emit_be_Reload(const ir_node *irn) {
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(", ");
......@@ -919,11 +927,61 @@ static void emit_be_Perm(const ir_node *irn) {
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 */
......@@ -976,9 +1034,9 @@ static void emit_arm_LdTls(const ir_node *irn) {
*
***********************************************************************************/
static void emit_silence(const ir_node *irn) {
static void emit_nothing(const ir_node *irn)
{
(void) irn;
/* Do nothing. */
}
/**
......@@ -989,7 +1047,8 @@ typedef void (emit_func)(const ir_node *irn);
/**
* 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;
}
......@@ -997,59 +1056,40 @@ static inline void set_emitter(ir_op *op, emit_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);
}
/**
......@@ -1063,8 +1103,8 @@ static void arm_emit_node(const ir_node *irn) {
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);
}
}
......
......@@ -363,7 +363,8 @@ arm_shift_modifier get_arm_shift_modifier(const ir_node *node) {
static void init_arm_attributes(ir_node *node, int flags,
const arch_register_req_t ** in_reqs,
const be_execution_unit_t ***execution_units,
int n_res) {
int n_res)
{
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
arm_attr_t *attr = get_arm_attr(node);
......@@ -380,6 +381,15 @@ static void init_arm_attributes(ir_node *node, int flags,
memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
}
void init_arm_load_store_attributes(ir_node *res, ir_entity *entity,
int entity_sign, long offset)
{
arm_load_store_attr_t *attr = get_irn_generic_attr(res);
attr->entity = entity;
attr->entity_sign = entity_sign;
attr->offset = offset;
}
/************************************************
* ___ _ _ _ *
* / _ \ _ __ | |_(_)_ __ ___ (_)_______ _ __ *
......@@ -473,6 +483,29 @@ static int cmp_attr_arm_fpaConst(ir_node *a, ir_node *b) {
return attr_a->tv != attr_b->tv;
}
arm_load_store_attr_t *get_arm_load_store_attr(ir_node *node)
{
return (arm_load_store_attr_t*) get_irn_generic_attr(node);
}
static int cmp_attr_arm_load_store(ir_node *a, ir_node *b)
{
const arm_load_store_attr_t *attr_a;
const arm_load_store_attr_t *attr_b;
if (cmp_attr_arm(a, b))
return 1;
attr_a = get_arm_load_store_attr(a);
attr_b = get_arm_load_store_attr(b);
if (attr_a->entity != attr_b->entity
|| attr_a->entity_sign != attr_b->entity_sign
|| attr_a->offset != attr_b->offset)
return 1;
return 0;
}
/** copies the ARM attributes of a node. */
static void arm_copy_attr(const ir_node *old_node, ir_node *new_node) {
ir_graph *irg = get_irn_irg(new_node);
......
......@@ -140,6 +140,9 @@ void set_arm_SwitchJmp_default_proj_num(ir_node *node, long default_proj_num);
*/
arm_shift_modifier get_arm_shift_modifier(const ir_node *node);
void init_arm_load_store_attributes(ir_node *res, ir_entity *entity,
int entity_sign, long offset);
/* Include the generated headers */
#include "gen_arm_new_nodes.h"
......
......@@ -111,6 +111,13 @@ typedef struct _arm_attr_t {
long imm_value; /**< immediate */
} arm_attr_t;
typedef struct arm_load_store_attr_t {
arm_attr_t attr;
ir_entity *entity;
long offset;
bool entity_sign : 1;
} arm_load_store_attr_t;
/** Attributes for a SymConst */
typedef struct _arm_SymConst_attr_t {
arm_attr_t attr; /**< base attributes */
......
......@@ -231,9 +231,10 @@ static void peephole_be_Spill(ir_node *node) {
panic("peephole_be_Spill: spill not supported for this mode");
}
} else if (mode_is_dataM(mode)) {
/* transform into Store */;
store = new_bd_arm_Store(dbg, block, ptr, value, get_irg_no_mem(irg));
sched_add_before(node, store);
/* transform into Store */;
store = new_bd_arm_Str(dbg, block, ptr, value, get_irg_no_mem(irg),
NULL, 0, 0);
sched_add_before(node, store);
} else {
panic("peephole_be_Spill: spill not supported for this mode");
}
......@@ -285,9 +286,9 @@ static void peephole_be_Reload(ir_node *node) {
}
} else if (mode_is_dataM(mode)) {
/* transform into Store */;
load = new_bd_arm_Load(dbg, block, ptr, mem);
load = new_bd_arm_Ldr(dbg, block, ptr, mem, NULL, 0, 0);
sched_add_before(node, load);
proj = new_rd_Proj(dbg, block, load, mode_Iu, pn_arm_Load_res);
proj = new_rd_Proj(dbg, block, load, mode_Iu, pn_arm_Ldr_res);
arch_set_irn_register(proj, reg);
} else {
panic("peephole_be_Spill: spill not supported for this mode");
......
......@@ -5,7 +5,6 @@
# 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;
......@@ -27,38 +26,38 @@ $state = 32; # register represents a state
# 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);",
......@@ -95,14 +94,18 @@ $default_copy_attr = "arm_copy_attr";
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 = (
......@@ -171,7 +174,6 @@ Add => {
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'
},
......@@ -181,7 +183,6 @@ Add_i => {
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'
},
......@@ -226,7 +227,6 @@ And => {
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'
},
......@@ -238,7 +238,6 @@ And_i => {
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 => {
......@@ -247,7 +246,6 @@ 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'
},
......@@ -258,7 +256,6 @@ Or_i => {
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'
},
......@@ -268,7 +265,6 @@ Eor => {
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'
},
......@@ -279,7 +275,6 @@ Eor_i => {
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'
},
......@@ -290,7 +285,6 @@ Bic => {
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'
},
......@@ -302,7 +296,6 @@ Bic_i => {
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 => {
......@@ -310,7 +303,6 @@ 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'
},
......@@ -320,7 +312,6 @@ Sub_i => {
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',
},
......@@ -330,7 +321,6 @@ Rsb => {
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'
},
......@@ -342,7 +332,6 @@ Rsb_i => {
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 => {
......@@ -392,7 +381,6 @@ Mov => {
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'
},
......@@ -404,7 +392,6 @@ Mov_i => {
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 => {
......@@ -412,7 +399,6 @@ 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'
},
......@@ -422,7 +408,6 @@ Mvn_i => {
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',
},
......@@ -461,7 +446,6 @@ CopyB => {
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" ],
},
......@@ -498,6 +482,14 @@ TstBra => {
attr_type => "arm_CondJmp_attr_t",
},
Jmp => {
state => "pinned",
op_flags => "X",
irn_flags => "J",
reg_req => { out => [ "none" ] },
mode => "mode_X",
},
SwitchJmp => {