Commit a10617f2 authored by Matthias Braun's avatar Matthias Braun
Browse files

- Properly support AM for push and pop nodes

- Fix Projs returning wrong register requirements for in positions
parent 657d38c5
......@@ -112,6 +112,11 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re
DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
if (is_Proj(irn)) {
if(pos >= 0) {
DBG((mod, LEVEL_1, "ignoring request IN requirements for node %+F\n", irn));
return NULL;
}
if (pos == -1) {
node_pos = ia32_translate_proj_pos(irn);
}
......@@ -381,10 +386,11 @@ static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap
ir_node *bl = get_irg_start_block(env->irg);
ir_node *curr_sp = be_abi_reg_map_get(reg_map, env->isa->sp);
ir_node *curr_bp = be_abi_reg_map_get(reg_map, env->isa->bp);
ir_node *noreg = be_abi_reg_map_get(reg_map, &ia32_gp_regs[REG_GP_NOREG]);
ir_node *push;
/* push ebp */
push = new_rd_ia32_Push(NULL, env->irg, bl, curr_sp, curr_bp, *mem);
push = new_rd_ia32_Push(NULL, env->irg, bl, noreg, noreg, curr_bp, curr_sp, *mem);
curr_sp = new_r_Proj(env->irg, bl, push, get_irn_mode(curr_sp), pn_ia32_Push_stack);
*mem = new_r_Proj(env->irg, bl, push, mode_M, pn_ia32_Push_M);
......@@ -450,13 +456,14 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_
*mem = new_r_Proj(current_ir_graph, bl, leave, mode_M, pn_ia32_Leave_M);
}
else {
ir_node *noreg = be_abi_reg_map_get(reg_map, &ia32_gp_regs[REG_GP_NOREG]);
ir_node *pop;
/* copy ebp to esp */
curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem);
/* pop ebp */
pop = new_rd_ia32_Pop(NULL, env->irg, bl, curr_sp, *mem);
pop = new_rd_ia32_Pop(NULL, env->irg, bl, noreg, noreg, curr_sp, *mem);
set_ia32_flags(pop, arch_irn_flags_ignore);
curr_bp = new_r_Proj(current_ir_graph, bl, pop, mode_bp, pn_ia32_Pop_res);
curr_sp = new_r_Proj(current_ir_graph, bl, pop, get_irn_mode(curr_sp), pn_ia32_Pop_stack);
......@@ -1084,42 +1091,42 @@ static void transform_to_Store(ia32_transform_env_t *env) {
exchange(irn, proj);
}
static ir_node *create_push(ia32_transform_env_t *env, ir_node *schedpoint, ir_node *sp, ir_node *mem, entity *ent, const char *offset) {
static ir_node *create_push(ia32_transform_env_t *env, ir_node *schedpoint, ir_node *sp, ir_node *mem, entity *ent) {
ir_node *noreg = ia32_new_NoReg_gp(env->cg);
ir_node *frame = get_irg_frame(env->irg);
ir_node *push = new_rd_ia32_Push(env->dbg, env->irg, env->block, sp, noreg, mem);
ir_node *push = new_rd_ia32_Push(env->dbg, env->irg, env->block, frame, noreg, noreg, sp, mem);
set_ia32_frame_ent(push, ent);
set_ia32_use_frame(push);
set_ia32_op_type(push, ia32_AddrModeS);
set_ia32_am_flavour(push, ia32_B);
set_ia32_ls_mode(push, mode_Is);
if(offset != NULL)
add_ia32_am_offs(push, offset);
sched_add_before(schedpoint, push);
return push;
}
static ir_node *create_pop(ia32_transform_env_t *env, ir_node *schedpoint, ir_node *sp, entity *ent, const char *offset) {
ir_node *pop = new_rd_ia32_Pop(env->dbg, env->irg, env->block, sp, new_NoMem());
static ir_node *create_pop(ia32_transform_env_t *env, ir_node *schedpoint, ir_node *sp, entity *ent) {
ir_node *noreg = ia32_new_NoReg_gp(env->cg);
ir_node *frame = get_irg_frame(env->irg);
ir_node *pop = new_rd_ia32_Pop(env->dbg, env->irg, env->block, frame, noreg, sp, new_NoMem());
set_ia32_frame_ent(pop, ent);
set_ia32_use_frame(pop);
set_ia32_op_type(pop, ia32_AddrModeD);
set_ia32_am_flavour(pop, ia32_B);
set_ia32_ls_mode(pop, mode_Is);
if(offset != NULL)
add_ia32_am_offs(pop, offset);
sched_add_before(schedpoint, pop);
return pop;
}
static ir_node* create_spproj(ia32_transform_env_t *env, ir_node *pred, int pos, ir_node *schedpoint, const ir_node *oldsp) {
ir_mode *spmode = get_irn_mode(oldsp);
const arch_register_t *spreg = arch_get_irn_register(env->cg->arch_env, oldsp);
static ir_node* create_spproj(ia32_transform_env_t *env, ir_node *pred, int pos, ir_node *schedpoint) {
ir_mode *spmode = mode_Iu;
const arch_register_t *spreg = &ia32_gp_regs[REG_ESP];
ir_node *sp;
sp = new_rd_Proj(env->dbg, env->irg, env->block, pred, spmode, pos);
......@@ -1129,15 +1136,15 @@ static ir_node* create_spproj(ia32_transform_env_t *env, ir_node *pred, int pos,
return sp;
}
/**
* Transform memperm, currently we do this the ugly way and produce
* push/pop into/from memory cascades. This is possible without using
* any registers.
*/
static void transform_MemPerm(ia32_transform_env_t *env) {
/*
* Transform memperm, currently we do this the ugly way and produce
* push/pop into/from memory cascades. This is possible without using
* any registers.
*/
ir_node *node = env->irn;
int i, arity;
ir_node *sp = get_irn_n(node, 0);
ir_node *sp = be_abi_get_ignore_irn(env->cg->birg->abi, &ia32_gp_regs[REG_ESP]);
const ir_edge_t *edge;
const ir_edge_t *next;
ir_node **pops;
......@@ -1155,12 +1162,13 @@ static void transform_MemPerm(ia32_transform_env_t *env) {
assert( (entbits == 32 || entbits == 64) && "spillslot on x86 should be 32 or 64 bit");
push = create_push(env, node, sp, mem, ent, NULL);
sp = create_spproj(env, push, 0, node, sp);
push = create_push(env, node, sp, mem, ent);
sp = create_spproj(env, push, 0, node);
if(entbits == 64) {
// add another push after the first one
push = create_push(env, node, sp, mem, ent, "4");
sp = create_spproj(env, push, 0, node, sp);
push = create_push(env, node, sp, mem, ent);
add_ia32_am_offs_int(push, 4);
sp = create_spproj(env, push, 0, node);
}
set_irn_n(node, i, new_Bad());
......@@ -1176,15 +1184,14 @@ static void transform_MemPerm(ia32_transform_env_t *env) {
assert( (entbits == 32 || entbits == 64) && "spillslot on x86 should be 32 or 64 bit");
pop = create_pop(env, node, sp, ent, NULL);
pop = create_pop(env, node, sp, ent);
if(entbits == 64) {
// add another pop after the first one
sp = create_spproj(env, pop, 1, node, sp);
pop = create_pop(env, node, sp, ent, "4");
sp = create_spproj(env, pop, 1, node);
pop = create_pop(env, node, sp, ent);
add_ia32_am_offs_int(pop, 4);
}
//if(i != 0) {
sp = create_spproj(env, pop, 1, node, sp);
//}
sp = create_spproj(env, pop, 1, node);
pops[i] = pop;
}
......
......@@ -558,19 +558,25 @@ const char *ia32_emit_unop(const ir_node *n, ia32_emit_env_t *env) {
switch(get_ia32_op_type(n)) {
case ia32_Normal:
if (is_ia32_ImmConst(n) || is_ia32_ImmSymConst(n)) {
if (is_ia32_ImmConst(n)) {
lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%C", n);
}
else if (is_ia32_ImmSymConst(n)) {
lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "OFFSET FLAT:%C", n);
}
else {
if (is_ia32_MulS(n) || is_ia32_Mulh(n)) {
/* MulS and Mulh implicitly multiply by EAX */
lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%4S", n);
}
else
} else if(is_ia32_Push(n)) {
lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%3S", n);
} else {
lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D", n);
}
}
break;
case ia32_AddrModeD:
assert(!is_ia32_Push(n));
snprintf(buf, SNPRINTF_BUF_LEN, "%s", ia32_emit_am(n, env));
break;
case ia32_AddrModeS:
......@@ -578,7 +584,7 @@ const char *ia32_emit_unop(const ir_node *n, ia32_emit_env_t *env) {
Mulh is emitted via emit_unop
imul [MEM] means EDX:EAX <- EAX * [MEM]
*/
assert((is_ia32_Mulh(n) || is_ia32_MulS(n)) && "Only MulS and Mulh can have AM source as unop");
assert((is_ia32_Mulh(n) || is_ia32_MulS(n) || is_ia32_Push(n)) && "Only MulS and Mulh can have AM source as unop");
lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%s", ia32_emit_am(n, env));
break;
default:
......
......@@ -544,7 +544,7 @@ char *get_ia32_am_offs(const ir_node *node) {
ia32_attr_t *attr = get_ia32_attr(node);
static char res[64];
snprintf(res, sizeof(res), "%+ld", attr->am_offs);
snprintf(res, sizeof(res), "%+d", attr->am_offs);
return res;
}
......@@ -552,7 +552,7 @@ char *get_ia32_am_offs(const ir_node *node) {
/**
* Gets the addressmode offset as long.
*/
long get_ia32_am_offs_long(const ir_node *node) {
int get_ia32_am_offs_int(const ir_node *node) {
ia32_attr_t *attr = get_ia32_attr(node);
return attr->am_offs;
}
......@@ -564,10 +564,13 @@ static void extend_ia32_am_offs(ir_node *node, char *offset, char op) {
ia32_attr_t *attr = get_ia32_attr(node);
int res, o;
if (! offset || strlen(offset) < 1)
if (offset == NULL || offset[0] == '\0')
return;
res = sscanf(offset, "%d", &o);
if (offset[0] == '-')
res = sscanf(offset, "%d", &o);
else
res = sscanf(offset, "%u", &o);
assert(res == 1);
if (op == '-')
......@@ -585,6 +588,11 @@ void add_ia32_am_offs(ir_node *node, const char *offset) {
extend_ia32_am_offs(node, (char *)offset, '+');
}
void add_ia32_am_offs_int(ir_node *node, int offset) {
ia32_attr_t *attr = get_ia32_attr(node);
attr->am_offs += offset;
}
/**
* Sub an offset for addrmode.
*/
......
......@@ -74,13 +74,15 @@ char *get_ia32_am_offs(const ir_node *node);
/**
* Gets the addressmode offset as long.
*/
long get_ia32_am_offs_long(const ir_node *node);
int get_ia32_am_offs_int(const ir_node *node);
/**
* Adds an offset for addrmode.
*/
void add_ia32_am_offs(ir_node *node, const char *offset);
void add_ia32_am_offs_int(ir_node *node, int offset);
/**
* Subs an offset for addrmode.
*/
......
......@@ -101,7 +101,7 @@ typedef struct _ia32_attr_t {
unsigned n_res:6; /**< number of results produced by this node */
} data;
long am_offs; /**< offsets for AddrMode */
int am_offs; /**< offsets for AddrMode */
ident *am_sc; /**< SymConst for AddrMode */
union {
......
......@@ -241,7 +241,7 @@ static void ia32_transform_const(ir_node *irn, void *env) {
tenv.irn = irn;
DEBUG_ONLY(tenv.mod = cg->mod;)
#if 1
#if 0
/* place const either in the smallest dominator of all its users or the original block */
if (cg->opt & IA32_OPT_PLACECNST)
tenv.block = node_users_smallest_common_dominator(irn, 1);
......@@ -562,6 +562,7 @@ static void ia32_create_Pushs(ir_node *irn, ia32_code_gen_t *cg) {
ir_node *push;
ir_node *val, *mem;
ir_node *store = stores[i];
ir_node *noreg = ia32_new_NoReg_gp(cg);
if(store == NULL || is_Bad(store))
break;
......@@ -571,7 +572,7 @@ static void ia32_create_Pushs(ir_node *irn, ia32_code_gen_t *cg) {
spreg = arch_get_irn_register(cg->arch_env, curr_sp);
// create a push
push = new_rd_ia32_Push(NULL, irg, block, curr_sp, val, mem);
push = new_rd_ia32_Push(NULL, irg, block, noreg, noreg, val, curr_sp, mem);
if(get_ia32_immop_type(store) != ia32_ImmNone) {
copy_ia32_Immop_attr(push, store);
}
......
......@@ -416,7 +416,7 @@ $comment_string = "/*";
"irn_flags" => "R",
"comment" => "construct Shl: Shl(a, b) = a << b",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
"reg_req" => { "in" => [ "gp", "gp", "gp", "ecx gp_NOREG", "none" ], "out" => [ "in_r3 !in_r4" ] },
"emit" => '. shl %ia32_emit_binop /* Shl(%A1, %A2) -> %D1 */',
"outs" => [ "res", "M" ],
},
......@@ -465,7 +465,7 @@ else {
"irn_flags" => "R",
"comment" => "construct Shr: Shr(a, b) = a >> b",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
"reg_req" => { "in" => [ "gp", "gp", "gp", "ecx gp_NOREG", "none" ], "out" => [ "in_r3 !in_r4" ] },
"emit" => '. shr %ia32_emit_binop /* Shr(%A1, %A2) -> %D1 */',
"outs" => [ "res", "M" ],
},
......@@ -514,7 +514,7 @@ else {
"irn_flags" => "R",
"comment" => "construct Shrs: Shrs(a, b) = a >> b",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] },
"reg_req" => { "in" => [ "gp", "gp", "gp", "ecx gp_NOREG", "none" ], "out" => [ "in_r3 !in_r4" ] },
"emit" => '. sar %ia32_emit_binop /* Shrs(%A1, %A2) -> %D1 */',
"outs" => [ "res", "M" ],
},
......@@ -700,7 +700,7 @@ else {
"state" => "exc_pinned",
"comment" => "construct 8Bit Store: Store(ptr, val, mem) = ST ptr,val",
"cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"reg_req" => { "in" => [ "gp", "gp", "eax ebx ecx edx", "none" ] },
"reg_req" => { "in" => [ "gp", "gp", "eax ebx ecx edx gp_NOREG", "none" ] },
"emit" => '. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */',
"outs" => [ "M" ],
"latency" => 3,
......@@ -717,23 +717,9 @@ else {
"Push" => {
# We don't set class modify_stack here (but we will do this on proj 0)
"comment" => "push a gp register on the stack",
"reg_req" => { "in" => [ "esp", "gp", "none" ], "out" => [ "esp" ] },
"emit" => '
if (get_ia32_id_cnst(n)) {
if (get_ia32_immop_type(n) == ia32_ImmConst) {
4. push %C /* Push const on stack */
} else {
4. push OFFSET FLAT:%C /* Push symconst on stack */
}
}
else if (get_ia32_op_type(n) == ia32_Normal) {
2. push %S2 /* Push(%A2) */
}
else {
2. push %ia32_emit_am /* Push memory to stack */
};
',
"comment" => "push on the stack",
"reg_req" => { "in" => [ "gp", "gp", "gp", "esp", "none" ], "out" => [ "esp" ] },
"emit" => '. push %ia32_emit_unop /* PUSH(%A1) */',
"outs" => [ "stack", "M" ],
"latency" => 3,
},
......@@ -741,15 +727,8 @@ else {
"Pop" => {
# We don't set class modify stack here (but we will do this on proj 1)
"comment" => "pop a gp register from the stack",
"reg_req" => { "in" => [ "esp", "none" ], "out" => [ "gp", "esp" ] },
"emit" => '
if (get_ia32_op_type(n) == ia32_Normal) {
2. pop %D1 /* Pop from stack into %D1 */
}
else {
2. pop %ia32_emit_am /* Pop from stack into memory */
}
',
"reg_req" => { "in" => [ "gp", "gp", "esp", "none" ], "out" => [ "gp", "esp" ] },
"emit" => '. pop %ia32_emit_unop /* POP(%A1) */',
"outs" => [ "res", "stack", "M" ],
"latency" => 4,
},
......
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