Commit 5d79fe73 authored by Michael Beck's avatar Michael Beck
Browse files

Changed transformer to be like ia32: do a transform- and copy

added some more isntructions, some fixes
at least HelloWorld compiles again :-)

[r14532]
parent 7117b610
......@@ -20,7 +20,7 @@
/**
* @file
* @brief arm emitter
* @author Oliver Richter, Tobias Gneist
* @author Oliver Richter, Tobias Gneist, Michael Beck
* @version $Id$
*/
#define SILENCER
......@@ -823,6 +823,11 @@ static void emit_arm_fpaDbl2GP(arm_emit_env_t *env, const ir_node *irn) {
be_emit_finish_line_gas(env->emit, irn);
}
static void emit_arm_LdTls(arm_emit_env_t *env, const ir_node *irn) {
panic("TLS not supported for this target\n");
/* Er... our gcc does not support it... Install a newer toolchain. */
}
/***********************************************************************************
* _ __ _
* (_) / _| | |
......@@ -875,11 +880,11 @@ static void arm_register_emitters(void) {
ARM_EMIT(SwitchJmp);
ARM_EMIT(fpaDbl2GP);
ARM_EMIT(fpaConst);
ARM_EMIT(LdTls);
/* benode emitter */
BE_EMIT(Call);
BE_EMIT(IncSP);
// BE_EMIT(AddSP);
BE_EMIT(Copy);
BE_EMIT(Spill);
BE_EMIT(Reload);
......
......@@ -78,51 +78,6 @@ void arm_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set) {
}
const arch_register_t *arm_get_firm_reg(const ir_node *irn, set *reg_set) {
struct arm_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
const struct arm_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
return assoc->reg;
}
/**
* Translates the proj number into a "real" argument position for register
* requirements depended on the predecessor.
*/
long arm_translate_proj_pos(const ir_node *proj) {
ir_node *pred = get_Proj_pred(proj);
long nr = get_Proj_proj(proj);
if (is_irn_machine_op(pred)) {
switch (get_arm_irn_opcode(pred)) {
case iro_arm_Loadb:
case iro_arm_Loadbs:
case iro_arm_Loadh:
case iro_arm_Loadhs:
case iro_arm_Load:
case iro_arm_fpaLdf:
if (nr == pn_Load_res)
return 0;
assert(0 && "unsupported Proj(Load) number");
break;
case iro_arm_Storeb:
case iro_arm_Storebs:
case iro_arm_Storeh:
case iro_arm_Storehs:
case iro_arm_Store:
case iro_arm_fpaStf:
return 0;
case iro_arm_fpaDiv:
case iro_arm_fpaRdv:
if (nr == pn_Quot_res)
return 0;
assert(0 && "there should be no more Projs for a fDiv");
break;
default:
break;
}
}
// assert(0 && "unsupported Proj(X)");
return nr;
}
......@@ -19,8 +19,8 @@
/**
* @file
* @brief declarations for arm register allocation
* @author Oliver Richter, Tobias Gneist
* @brief declarations for ARM register allocation
* @author Oliver Richter, Tobias Gneist, Michael Beck
* @version $Id$
*/
#ifndef FIRM_BE_ARM_ARM_MAP_REGS_H
......@@ -38,6 +38,4 @@ int arm_cmp_irn_reg_assoc(const void *a, const void *b, size_t len);
void arm_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set);
const arch_register_t *arm_get_firm_reg(const ir_node *irn, set *reg_set);
long arm_translate_proj_pos(const ir_node *proj);
#endif
......@@ -416,6 +416,24 @@ const arch_register_t *get_arm_out_reg(const ir_node *node, int pos) {
return attr->slots[pos];
}
/**
* Sets the flags for the n'th out.
*/
void set_arm_out_flags(ir_node *node, arch_irn_flags_t flags, int pos) {
arm_attr_t *attr = get_arm_attr(node);
assert(pos < ARR_LEN(attr->out_flags) && "Invalid OUT position.");
attr->out_flags[pos] = flags;
}
/**
* Gets the flags for the n'th out.
*/
arch_irn_flags_t get_arm_out_flags(const ir_node *node, int pos) {
const arm_attr_t *attr = get_arm_attr_const(node);
assert(pos < ARR_LEN(attr->out_flags) && "Invalid OUT position.");
return attr->out_flags[pos];
}
/**
* Returns the number of results.
*/
......@@ -525,6 +543,9 @@ void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t **
attr->instr_fl = (ARM_COND_AL << 3) | ARM_SHF_NONE;
attr->value = NULL;
attr->out_flags = NEW_ARR_D(int, obst, n_res);
memset(attr->out_flags, 0, n_res * sizeof(attr->out_flags[0]));
attr->slots = NEW_ARR_D(const arch_register_t*, obst, n_res);
memset((arch_register_t **)attr->slots, 0, n_res * sizeof(attr->slots[0]));
}
......@@ -668,7 +689,38 @@ static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b) {
return 1;
}
/** 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);
struct obstack *obst = get_irg_obstack(irg);
const arm_attr_t *attr_old = get_arm_attr_const(old_node);
arm_attr_t *attr_new = get_arm_attr(new_node);
/* copy the attributes */
memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));
/* copy out flags */
attr_new->out_flags =
DUP_ARR_D(int, obst, attr_old->out_flags);
/* copy register assignments */
attr_new->slots =
DUP_ARR_D(arch_register_t*, obst, attr_old->slots);
}
/* Include the generated constructor functions */
#include "gen_arm_new_nodes.c.inl"
/**
* Registers the arm_copy_attr function for all ARM opcodes.
*/
void arm_register_copy_attr_func(void) {
int i;
for (i = get_irp_n_opcodes() - 1; i >= 0; --i) {
ir_op *op = get_irp_opcode(i);
if (is_arm_op(op))
op->ops.copy_attr = arm_copy_attr;
}
}
......@@ -140,6 +140,16 @@ int get_arm_n_res(const ir_node *node);
void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t ** in_reqs,
const arch_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units, int n_res, unsigned latency);
/**
* Sets the flags for the n'th out.
*/
void set_arm_out_flags(ir_node *node, arch_irn_flags_t flags, int pos);
/**
* Gets the flags for the n'th out.
*/
arch_irn_flags_t get_arm_out_flags(const ir_node *node, int pos);
/**
* Returns the tarval
*/
......@@ -196,6 +206,11 @@ arm_shift_modifier get_arm_shift_modifier(const ir_node *node);
*/
unsigned int arm_decode_imm_w_shift(tarval *tv);
/**
* Registers the arm_copy_attr function for all ARM opcodes.
*/
void arm_register_copy_attr_func(void);
/* Include the generated headers */
#include "gen_arm_new_nodes.h"
......
......@@ -82,16 +82,17 @@ typedef enum _arm_condition {
/** Generic ARM node attributes. */
typedef struct _arm_attr_t {
arch_irn_flags_t flags; /**< indicating if spillable, rematerializeable ... etc. */
arch_irn_flags_t flags; /**< indicating if spillable, rematerializeable ... etc. */
const arch_register_req_t **in_req; /**< register requirements for arguments */
const arch_register_req_t **out_req; /**< register requirements for results */
ir_mode *op_mode; /**< operation mode if different from node's mode */
unsigned instr_fl; /**< condition code, shift modifier */
tarval *value; /**< immediate */
ir_mode *op_mode; /**< operation mode if different from node's mode */
unsigned instr_fl; /**< condition code, shift modifier */
tarval *value; /**< immediate */
int *out_flags; /**< flags for each produced value */
const arch_register_t **slots; /**< register slots for assigned registers */
const arch_register_t **slots; /**< register slots for assigned registers */
} arm_attr_t;
/** Attributes for a SymConst */
......
......@@ -472,6 +472,9 @@ Abs => {
# other operations
#
# this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
#
EmptyReg => {
op_flags => "c",
irn_flags => "R",
......@@ -490,7 +493,10 @@ 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 => {
......@@ -586,16 +592,6 @@ Storeb => {
outs => [ "M" ],
},
Storebs => {
op_flags => "L|F",
irn_flags => "R",
state => "exc_pinned",
comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
reg_req => { "in" => [ "gp", "gp", "none" ], "out" => [ "none" ] },
emit => '. strsb %S1, [%S0, #0]',
outs => [ "M" ],
},
Storeh => {
op_flags => "L|F",
irn_flags => "R",
......@@ -606,16 +602,6 @@ Storeh => {
outs => [ "M" ],
},
Storehs => {
op_flags => "L|F",
irn_flags => "R",
state => "exc_pinned",
comment => "construct Store: Store(ptr, val, mem) = ST ptr,val",
reg_req => { "in" => [ "gp", "gp", "none" ], out => [ "none" ] },
emit => '. strhs %S1, [%S0, #0]',
outs => [ "M" ],
},
Store => {
op_flags => "L|F",
irn_flags => "R",
......@@ -716,26 +702,38 @@ fpaRsb => {
fpaDiv => {
comment => "construct FPA Div: Div(a, b) = a / b",
reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
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" ],
},
fpaRdv => {
comment => "construct FPA reverse Div: Div(a, b) = b / a",
reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
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" ],
},
fpaFDiv => {
comment => "construct FPA Fast Div: Div(a, b) = a / b",
reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
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" ],
},
fpaFRdv => {
comment => "construct FPA Fast reverse Div: Div(a, b) = b / a",
reg_req => { "in" => [ "fpa", "fpa" ], "out" => [ "fpa" ] },
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" ],
},
fpaMov => {
......@@ -810,6 +808,29 @@ fpaDbl2GP => {
outs => [ "low", "high", "M" ],
},
AddSP => {
irn_flags => "I",
comment => "construct Add to stack pointer",
reg_req => { in => [ "sp", "gp", "none" ], out => [ "in_r1", "none" ] },
emit => '. add %D0, %S0, %S1',
outs => [ "stack:S", "M" ],
},
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" ],
},
LdTls => {
irn_flags => "R",
comment => "load the TLS address",
reg_req => { out => [ "gp" ] },
},
#
# floating point constants
#
......
This diff is collapsed.
......@@ -26,9 +26,11 @@
#ifndef FIRM_BE_ARM_ARM_TRANSFORM_H
#define FIRM_BE_ARM_ARM_TRANSFORM_H
void arm_move_consts(ir_node *node, void *env);
/**
* Transform a Firm graph into an ARM graph.
*/
void arm_transform_graph(arm_code_gen_t *cg);
void arm_register_transformers(void);
void arm_transform_node(ir_node *node, void *env);
void arm_init_transform(void);
#endif
......@@ -36,6 +36,7 @@
#include "irprintf.h"
#include "ircons.h"
#include "irgmod.h"
#include "irgopt.h"
#include "lowering.h"
#include "bitset.h"
......@@ -91,30 +92,22 @@ arch_register_req_t *arm_get_irn_reg_req(const void *self, const ir_node *node,
FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
if (is_Block(node) || mode == mode_X || mode == mode_M) {
DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", node));
return arch_no_register_req;
}
if (mode == mode_T && pos < 0) {
DBG((mod, LEVEL_1, "ignoring request for OUT requirements at %+F\n", node));
return arch_no_register_req;
}
DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, node));
if (is_Proj(node)) {
/* in case of a proj, we need to get the correct OUT slot */
/* of the node corresponding to the proj number */
if (pos == -1) {
node_pos = arm_translate_proj_pos(node);
}
else {
node_pos = pos;
if(pos >= 0) {
return arch_no_register_req;
}
node = skip_Proj_const(node);
DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", node, node_pos));
node_pos = (pos == -1) ? get_Proj_proj(node) : pos;
node = skip_Proj_const(node);
}
/* get requirements for our own nodes */
......@@ -126,27 +119,23 @@ arch_register_req_t *arm_get_irn_reg_req(const void *self, const ir_node *node,
req = get_arm_out_req(node, node_pos);
}
DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", node, pos));
return req;
}
/* unknown should be tranformed by now */
/* unknown should be transformed by now */
assert(!is_Unknown(node));
DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", node));
return arch_no_register_req;
}
static void arm_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
int pos = 0;
if (is_Proj(irn)) {
if (get_irn_mode(irn) == mode_X) {
return;
}
if (get_irn_mode(irn) == mode_X) {
return;
}
pos = arm_translate_proj_pos(irn);
if (is_Proj(irn)) {
pos = get_Proj_proj(irn);
irn = skip_Proj(irn);
}
......@@ -172,7 +161,7 @@ static const arch_register_t *arm_get_irn_reg(const void *self, const ir_node *i
return NULL;
}
pos = arm_translate_proj_pos(irn);
pos = get_Proj_proj(irn);
irn = skip_Proj_const(irn);
}
......@@ -278,12 +267,21 @@ arm_irn_ops_t arm_irn_ops = {
static void arm_prepare_graph(void *self) {
arm_code_gen_t *cg = self;
arm_register_transformers();
irg_walk_blkwise_graph(cg->irg, NULL, arm_move_consts, cg);
irg_walk_blkwise_graph(cg->irg, NULL, arm_transform_node, cg);
}
/* transform nodes into assembler instructions */
arm_transform_graph(cg);
/* do local optimizations (mainly CSE) */
local_optimize_graph(cg->irg);
if (cg->dump)
be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
/* do code placement, to optimize the position of constants */
place_code(cg->irg);
if (cg->dump)
be_dump(cg->irg, "-place", dump_ir_block_graph_sched);
}
/**
* Called immediately before emit phase.
......@@ -525,6 +523,7 @@ static void arm_before_abi(void *self) {
irg_walk_graph(cg->irg, NULL, handle_calls, cg);
}
/* forward */
static void *arm_cg_init(be_irg_t *birg);
static const arch_code_generator_if_t arm_code_gen_if = {
......@@ -553,14 +552,15 @@ static void *arm_cg_init(be_irg_t *birg) {
}
cg = xmalloc(sizeof(*cg));
cg->impl = &arm_code_gen_if;
cg->irg = birg->irg;
cg->reg_set = new_set(arm_cmp_irn_reg_assoc, 1024);
cg->arch_env = birg->main_env->arch_env;
cg->isa = isa;
cg->birg = birg;
cg->int_tp = int_tp;
cg->have_fp = 0;
cg->impl = &arm_code_gen_if;
cg->irg = birg->irg;
cg->reg_set = new_set(arm_cmp_irn_reg_assoc, 1024);
cg->arch_env = birg->main_env->arch_env;
cg->isa = isa;
cg->birg = birg;
cg->int_tp = int_tp;
cg->have_fp_insn = 0;
cg->dump = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
FIRM_DBG_REGISTER(cg->mod, "firm.be.arm.cg");
......@@ -744,6 +744,7 @@ static void *arm_init(FILE *file_handle) {
be_emit_init_env(&isa->emit, file_handle);
arm_create_opcodes();
arm_register_copy_attr_func();
arm_handle_intrinsics();
/* we mark referenced global entities, so we can only emit those which
......@@ -782,7 +783,7 @@ static int arm_get_n_reg_class(const void *self) {
/* ARGH! is called BEFORE transform */
return 2;
return isa->cg->have_fp ? 2 : 1;
return isa->cg->have_fp_insn ? 2 : 1;
}
/**
......@@ -1174,6 +1175,8 @@ void be_init_arch_arm(void)
lc_opt_add_table(arm_grp, arm_options);
be_register_isa_if("arm", &arm_isa_if);
arm_init_transform();
}
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm);
......@@ -116,10 +116,10 @@ enum arm_fp_architectures {
};
/** Returns non-zero if FPA instructions should be issued. */
#define USE_FPA(cg) ((cg)->fpu_arch & ARM_FPU_FPA_EXT_V1)
#define USE_FPA(isa) ((isa)->fpu_arch & ARM_FPU_FPA_EXT_V1)
/** Returns non-zero if VFP instructions should be issued. */
#define USE_VFP(cg) ((cg)->fpu_arch & ARM_FPU_VFP_EXT_V1xD)
#define USE_VFP(isa) ((isa)->fpu_arch & ARM_FPU_VFP_EXT_V1xD)
/** Types of processor to generate code for. */
enum arm_processor_types {
......@@ -142,23 +142,24 @@ typedef struct _arm_code_gen_t {
arm_isa_t *isa; /**< the isa instance */
be_irg_t *birg; /**< The be-irg (contains additional information about the irg) */
ir_type *int_tp; /**< the int type, needed for Call conversion */
int have_fp; /**< non-zero, if fp hardware instructions are emitted */
int have_fp_insn; /**< non-zero, if fp hardware instructions are emitted */
char dump; /**< set to 1 if graphs should be dumped */
DEBUG_ONLY(firm_dbg_module_t *mod;) /**< debugging module */
} arm_code_gen_t;
struct _arm_isa_t {
arch_isa_t arch_isa; /**< must be derived from arch_isa_t */
int gen_reg_names; /**< use generic register names instead of SP, LR, PC */
int fpu_arch; /**< FPU architecture */
arm_code_gen_t *cg; /**< current code generator */
be_emit_env_t emit; /**< An emitter environment for the GAS emitter. */
arch_isa_t arch_isa; /**< must be derived from arch_isa_t */
int gen_reg_names; /**< use generic register names instead of SP, LR, PC */
int fpu_arch; /**< FPU architecture */
arm_code_gen_t *cg; /**< current code generator */
be_emit_env_t emit; /**< An emitter environment for the GAS emitter. */
};
typedef struct _arm_irn_ops_t {
const arch_irn_ops_if_t *impl;
arm_code_gen_t *cg;
arm_code_gen_t *cg;
} arm_irn_ops_t;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment