Commit 93cd212d authored by Matthias Braun's avatar Matthias Braun
Browse files

Changed handling of address mode:

- Source and Destination address mode are now constructed during the normal
  transform phase and not as a separate phase
- Remove the old ImmOp stuff
- introduce 8, 16bit cmps, tests
- still some nodes miss SourceAM handling, but generally we should be as good/better than the old code, so I'm comitting now

[r15642]
parent 25097d47
......@@ -355,8 +355,6 @@ static void ia32_set_frame_offset(const void *self, ir_node *irn, int bias) {
const ia32_irn_ops_t *ops = self;
if (get_ia32_frame_ent(irn)) {
ia32_am_flavour_t am_flav;
if (is_ia32_Pop(irn)) {
int omit_fp = be_abi_omit_fp(ops->cg->birg->abi);
if (omit_fp) {
......@@ -367,10 +365,6 @@ static void ia32_set_frame_offset(const void *self, ir_node *irn, int bias) {
}
}
am_flav = get_ia32_am_flavour(irn);
am_flav |= ia32_O;
set_ia32_am_flavour(irn, am_flav);
add_ia32_am_offs_int(irn, bias);
}
}
......@@ -613,7 +607,7 @@ static int ia32_get_op_estimated_cost(const void *self, const ir_node *irn)
cost += 150;
}
else if (is_ia32_CopyB_i(irn)) {
int size = get_tarval_long(get_ia32_Immop_tarval(irn));
int size = get_ia32_pncode(irn);
cost = 20 + (int)ceil((4/3) * size);
if (ARCH_INTEL(ops->cg->arch))
cost += 150;
......@@ -666,6 +660,11 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in
if (get_ia32_op_type(irn) != ia32_Normal)
return NULL;
/* TODO: adjust for new immediates... */
ir_fprintf(stderr, "TODO: fix get_inverse for new immediates (%+F)\n",
irn);
return NULL;
irg = get_irn_irg(irn);
block = get_nodes_block(irn);
mode = get_irn_mode(irn);
......@@ -681,6 +680,7 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in
switch (get_ia32_irn_opcode(irn)) {
case iro_ia32_Add:
#if 0
if (get_ia32_immop_type(irn) == ia32_ImmConst) {
/* we have an add with a const here */
/* invers == add with negated const */
......@@ -702,8 +702,10 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in
inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, (ir_node*) irn, get_irn_n(irn, i ^ 1), nomem);
inverse->costs += 2;
}
#endif
break;
case iro_ia32_Sub:
#if 0
if (get_ia32_immop_type(irn) != ia32_ImmNone) {
/* we have a sub with a const/symconst here */
/* invers == add with this const */
......@@ -721,8 +723,10 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in
}
inverse->costs += 1;
}
#endif
break;
case iro_ia32_Xor:
#if 0
if (get_ia32_immop_type(irn) != ia32_ImmNone) {
/* xor with const: inverse = xor */
inverse->nodes[0] = new_rd_ia32_Xor(dbg, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem);
......@@ -734,14 +738,15 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in
inverse->nodes[0] = new_rd_ia32_Xor(dbg, irg, block, noreg, noreg, (ir_node *) irn, get_irn_n(irn, i), nomem);
inverse->costs += 1;
}
#endif
break;
case iro_ia32_Not: {
inverse->nodes[0] = new_rd_ia32_Not(dbg, irg, block, noreg, noreg, (ir_node*) irn, nomem);
inverse->nodes[0] = new_rd_ia32_Not(dbg, irg, block, (ir_node*) irn);
inverse->costs += 1;
break;
}
case iro_ia32_Neg: {
inverse->nodes[0] = new_rd_ia32_Neg(dbg, irg, block, noreg, noreg, (ir_node*) irn, nomem);
inverse->nodes[0] = new_rd_ia32_Neg(dbg, irg, block, (ir_node*) irn);
inverse->costs += 1;
break;
}
......@@ -834,7 +839,6 @@ static void ia32_perform_memory_operand(const void *self, ir_node *irn,
}
set_ia32_op_type(irn, ia32_AddrModeS);
set_ia32_am_flavour(irn, ia32_B);
set_ia32_ls_mode(irn, get_irn_mode(get_irn_n(irn, i)));
set_ia32_use_frame(irn);
set_ia32_need_stackent(irn);
......@@ -972,7 +976,7 @@ static void transform_to_Load(ia32_code_gen_t *cg, ir_node *node) {
if (mode_is_float(spillmode)) {
if (USE_SSE2(cg))
new_op = new_rd_ia32_xLoad(dbg, irg, block, ptr, noreg, mem);
new_op = new_rd_ia32_xLoad(dbg, irg, block, ptr, noreg, mem, spillmode);
else
new_op = new_rd_ia32_vfld(dbg, irg, block, ptr, noreg, mem, spillmode);
}
......@@ -984,7 +988,6 @@ static void transform_to_Load(ia32_code_gen_t *cg, ir_node *node) {
new_op = new_rd_ia32_Load(dbg, irg, block, ptr, noreg, mem);
set_ia32_op_type(new_op, ia32_AddrModeS);
set_ia32_am_flavour(new_op, ia32_B);
set_ia32_ls_mode(new_op, spillmode);
set_ia32_frame_ent(new_op, ent);
set_ia32_use_frame(new_op);
......@@ -1055,7 +1058,6 @@ static void transform_to_Store(ia32_code_gen_t *cg, ir_node *node) {
}
set_ia32_op_type(store, ia32_AddrModeD);
set_ia32_am_flavour(store, ia32_B);
set_ia32_ls_mode(store, mode);
set_ia32_frame_ent(store, ent);
set_ia32_use_frame(store);
......@@ -1082,7 +1084,6 @@ static ir_node *create_push(ia32_code_gen_t *cg, ir_node *node, ir_node *schedpo
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);
sched_add_before(schedpoint, push);
......@@ -1101,7 +1102,6 @@ static ir_node *create_pop(ia32_code_gen_t *cg, ir_node *node, ir_node *schedpoi
set_ia32_frame_ent(pop, ent);
set_ia32_use_frame(pop);
set_ia32_op_type(pop, ia32_AddrModeD);
set_ia32_am_flavour(pop, ia32_am_OB);
set_ia32_ls_mode(pop, mode_Is);
sched_add_before(schedpoint, pop);
......
......@@ -181,14 +181,19 @@ static
int produces_result(const ir_node *node) {
return
!is_ia32_CmpSet(node) &&
!is_ia32_CondJmp(node) &&
!is_ia32_CmpSet8Bit(node) &&
!is_ia32_CmpJmp(node) &&
!is_ia32_CmpJmp8Bit(node) &&
!is_ia32_St(node) &&
!is_ia32_SwitchJmp(node) &&
!is_ia32_TestJmp(node) &&
!is_ia32_TestJmp8Bit(node) &&
!is_ia32_xCmpSet(node) &&
!is_ia32_xCondJmp(node) &&
!is_ia32_xCmpJmp(node) &&
!is_ia32_CmpCMov(node) &&
!is_ia32_CmpCMov8Bit(node) &&
!is_ia32_TestCMov(node) &&
!is_ia32_TestCMov8Bit(node) &&
!is_ia32_CmpSet(node) && /* this is correct, the Cmp has no result */
!is_ia32_TestSet(node);
}
......@@ -250,29 +255,6 @@ void ia32_emit_source_register(ia32_emit_env_t *env, const ir_node *node, int po
be_emit_string(env, reg_name);
}
void ia32_emit_8bit_source_register(ia32_emit_env_t *env, const ir_node *node, int pos)
{
const arch_register_t *reg = get_in_reg(env, node, pos);
const char *reg_name = arch_register_get_name(reg);
assert(pos < get_irn_arity(node));
be_emit_char(env, '%');
be_emit_char(env, reg_name[1]);
be_emit_char(env, 'l');
}
void ia32_emit_16bit_source_register(ia32_emit_env_t *env, const ir_node *node, int pos)
{
const arch_register_t *reg = get_in_reg(env, node, pos);
const char *reg_name = arch_register_get_name(reg);
assert(pos < get_irn_arity(node));
be_emit_char(env, '%');
be_emit_string(env, &reg_name[1]);
}
void ia32_emit_dest_register(ia32_emit_env_t *env, const ir_node *node, int pos) {
const arch_register_t *reg = get_out_reg(env, node, pos);
const char *reg_name = arch_register_get_name(reg);
......@@ -298,34 +280,6 @@ void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos)
be_emit_string(env, attr->x87[pos]->name);
}
void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node)
{
tarval *tv;
ir_entity *ent;
ident *id;
be_emit_char(env, '$');
switch(get_ia32_immop_type(node)) {
case ia32_ImmConst:
tv = get_ia32_Immop_tarval(node);
be_emit_tarval(env, tv);
return;
case ia32_ImmSymConst:
ent = get_ia32_Immop_symconst(node);
set_entity_backend_marked(ent, 1);
id = get_entity_ld_ident(ent);
be_emit_ident(env, id);
return;
case ia32_ImmNone:
break;
}
assert(0);
be_emit_string(env, "BAD");
return;
}
static
void ia32_emit_mode_suffix_mode(ia32_emit_env_t *env, const ir_mode *mode)
{
......@@ -431,11 +385,63 @@ void ia32_emit_function_size(ia32_emit_env_t *env, const char *name)
static
void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_8bit_source_register(ia32_emit_env_t *env, const ir_node *node,
int pos)
{
const arch_register_t *reg;
const char *reg_name;
ir_node *in;
in = get_irn_n(node, pos);
if(is_ia32_Immediate(in)) {
emit_ia32_Immediate(env, in);
return;
}
reg = get_in_reg(env, node, pos);
reg_name = arch_register_get_name(reg);
be_emit_char(env, '%');
be_emit_char(env, reg_name[1]);
be_emit_char(env, 'l');
}
void ia32_emit_16bit_source_register(ia32_emit_env_t *env, const ir_node *node,
int pos)
{
const arch_register_t *reg;
const char *reg_name;
ir_node *in;
in = get_irn_n(node, pos);
if(is_ia32_Immediate(in)) {
emit_ia32_Immediate(env, in);
return;
}
reg = get_in_reg(env, node, pos);
reg_name = arch_register_get_name(reg);
be_emit_char(env, '%');
be_emit_string(env, &reg_name[1]);
be_emit_char(env, 'x');
}
void ia32_emit_source_register_or_immediate(ia32_emit_env_t *env,
const ir_node *node, int pos)
{
ir_node *in = get_irn_n(node, pos);
if(is_ia32_Immediate(in)) {
emit_ia32_Immediate(env, in);
} else {
ia32_emit_source_register(env, node, pos);
}
}
/**
* Emits registers and/or address mode of a binary operation.
*/
void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
int right_pos;
const ir_node *right_op = get_irn_n(node, 3);
switch(get_ia32_op_type(node)) {
......@@ -445,10 +451,6 @@ void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 2);
break;
} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
ia32_emit_immediate(env, node);
be_emit_cstring(env, ", ");
ia32_emit_source_register(env, node, 2);
} else {
const arch_register_t *in1 = get_in_reg(env, node, 2);
const arch_register_t *in2 = get_in_reg(env, node, 3);
......@@ -460,11 +462,6 @@ void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
out = out ? out : in1;
in_name = arch_register_get_name(in);
if (is_ia32_emit_cl(node)) {
assert(in == &ia32_gp_regs[REG_ECX]);
in_name = "cl";
}
be_emit_char(env, '%');
be_emit_string(env, in_name);
be_emit_cstring(env, ", %");
......@@ -472,13 +469,7 @@ void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
}
break;
case ia32_AddrModeS:
if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
assert(!produces_result(node) &&
"Source AM with Const must not produce result");
ia32_emit_immediate(env, node);
be_emit_cstring(env, ", ");
ia32_emit_am(env, node);
} else if(is_ia32_Immediate(right_op)) {
if(is_ia32_Immediate(right_op)) {
assert(!produces_result(node) &&
"Source AM with Const must not produce result");
......@@ -496,34 +487,7 @@ void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
}
break;
case ia32_AddrModeD:
right_pos = get_irn_arity(node) >= 5 ? 3 : 2;
right_op = get_irn_n(node, right_pos);
if(is_ia32_Immediate(right_op)) {
emit_ia32_Immediate(env, right_op);
be_emit_cstring(env, ", ");
ia32_emit_am(env, node);
break;
} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
ia32_emit_immediate(env, node);
be_emit_cstring(env, ", ");
ia32_emit_am(env, node);
} else {
const arch_register_t *in1 = get_in_reg(env, node, right_pos);
ir_mode *mode = get_ia32_ls_mode(node);
const char *in_name;
in_name = ia32_get_reg_name_for_mode(env, mode, in1);
if (is_ia32_emit_cl(node)) {
assert(in1 == &ia32_gp_regs[REG_ECX]);
in_name = "cl";
}
be_emit_char(env, '%');
be_emit_string(env, in_name);
be_emit_cstring(env, ", ");
ia32_emit_am(env, node);
}
panic("DestMode can't be output by %%binop anymore");
break;
default:
assert(0 && "unsupported op type");
......@@ -536,10 +500,7 @@ void ia32_emit_binop(ia32_emit_env_t *env, const ir_node *node) {
void ia32_emit_x87_binop(ia32_emit_env_t *env, const ir_node *node) {
switch(get_ia32_op_type(node)) {
case ia32_Normal:
if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
// should not happen...
assert(0);
} else {
{
const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
const arch_register_t *in1 = x87_attr->x87[0];
const arch_register_t *in2 = x87_attr->x87[1];
......@@ -585,8 +546,6 @@ void ia32_emit_unop(ia32_emit_env_t *env, const ir_node *node, int pos) {
op = get_irn_n(node, pos);
if (is_ia32_Immediate(op)) {
emit_ia32_Immediate(env, op);
} else if (is_ia32_ImmConst(node) || is_ia32_ImmSymConst(node)) {
ia32_emit_immediate(env, node);
} else {
ia32_emit_source_register(env, node, pos);
}
......@@ -917,7 +876,7 @@ void CondJmp_emitter(ia32_emit_env_t *env, const ir_node *node) {
* Emits code for conditional jump with two variables.
*/
static
void emit_ia32_CondJmp(ia32_emit_env_t *env, const ir_node *node) {
void emit_ia32_CmpJmp(ia32_emit_env_t *env, const ir_node *node) {
CondJmp_emitter(env, node);
}
......@@ -948,7 +907,7 @@ void emit_ia32_TestJmp(ia32_emit_env_t *env, const ir_node *node) {
* Emits code for conditional SSE floating point jump with two variables.
*/
static
void emit_ia32_xCondJmp(ia32_emit_env_t *env, const ir_node *node) {
void emit_ia32_xCmpJmp(ia32_emit_env_t *env, const ir_node *node) {
be_emit_cstring(env, "\tucomi");
ia32_emit_xmm_mode_suffix(env, node);
be_emit_char(env, ' ');
......@@ -962,7 +921,7 @@ void emit_ia32_xCondJmp(ia32_emit_env_t *env, const ir_node *node) {
* Emits code for conditional x87 floating point jump with two variables.
*/
static
void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
void emit_ia32_x87CmpJmp(ia32_emit_env_t *env, const ir_node *node) {
const ia32_x87_attr_t *x87_attr = get_ia32_x87_attr_const(node);
const char *reg = x87_attr->x87[1]->name;
long pnc = get_ia32_pncode(node);
......@@ -1024,10 +983,10 @@ void CMov_emitter(ia32_emit_env_t *env, const ir_node *node)
in1 = arch_get_irn_register(env->arch_env, get_irn_n(node, 2));
in2 = arch_get_irn_register(env->arch_env, get_irn_n(node, 3));
} else {
if (is_ia32_CmpCMov(node)) {
if (is_ia32_CmpCMov(node) || is_ia32_CmpCMov8Bit(node)) {
be_emit_cstring(env, "\tcmp ");
} else {
assert(is_ia32_TestCMov(node));
assert(is_ia32_TestCMov(node) || is_ia32_TestCMov8Bit(node));
be_emit_cstring(env, "\ttest ");
}
ia32_emit_binop(env, node);
......@@ -1103,11 +1062,13 @@ void Set_emitter(ia32_emit_env_t *env, const ir_node *node)
ia32_emit_binop(env, node);
} else {
if (is_ia32_CmpSet(node)) {
be_emit_cstring(env, "\tcmp ");
be_emit_cstring(env, "\tcmp");
} else {
assert(is_ia32_TestSet(node));
be_emit_cstring(env, "\ttest ");
be_emit_cstring(env, "\ttest");
}
ia32_emit_mode_suffix(env, node);
be_emit_char(env, ' ');
ia32_emit_binop(env, node);
}
be_emit_finish_line_gas(env, node);
......@@ -1595,8 +1556,7 @@ void emit_CopyB_prolog(ia32_emit_env_t *env, int rem) {
*/
static
void emit_ia32_CopyB(ia32_emit_env_t *env, const ir_node *node) {
tarval *tv = get_ia32_Immop_tarval(node);
int rem = get_tarval_long(tv);
int rem = get_ia32_pncode(node);
emit_CopyB_prolog(env, rem);
......@@ -1609,8 +1569,7 @@ void emit_ia32_CopyB(ia32_emit_env_t *env, const ir_node *node) {
*/
static
void emit_ia32_CopyB_i(ia32_emit_env_t *env, const ir_node *node) {
tarval *tv = get_ia32_Immop_tarval(node);
int size = get_tarval_long(tv);
int size = get_ia32_pncode(node);
emit_CopyB_prolog(env, size & 0x3);
......@@ -1928,34 +1887,26 @@ void emit_be_Perm(ia32_emit_env_t *env, const ir_node *node) {
*/
static
void emit_ia32_Const(ia32_emit_env_t *env, const ir_node *node) {
ia32_immop_type_t imm_tp = get_ia32_immop_type(node);
const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);
if (imm_tp == ia32_ImmSymConst) {
be_emit_cstring(env, "\tmovl ");
ia32_emit_immediate(env, node);
/* a zero? */
if(attr->symconst == NULL && attr->offset == 0) {
if (env->isa->opt_arch == arch_pentium_4) {
/* P4 prefers sub r, r, others xor r, r */
be_emit_cstring(env, "\tsubl ");
} else {
be_emit_cstring(env, "\txorl ");
}
ia32_emit_dest_register(env, node, 0);
be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
tarval *tv = get_ia32_Immop_tarval(node);
assert(get_irn_mode(node) == mode_Iu);
/* beware: in some rare cases mode is mode_b which has no tarval_null() */
if (tarval_is_null(tv)) {
if (env->isa->opt_arch == arch_pentium_4) {
/* P4 prefers sub r, r, others xor r, r */
be_emit_cstring(env, "\tsubl ");
} else {
be_emit_cstring(env, "\txorl ");
}
ia32_emit_dest_register(env, node, 0);
be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
} else {
be_emit_cstring(env, "\tmovl ");
ia32_emit_immediate(env, node);
be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
}
be_emit_cstring(env, "\tmovl ");
emit_ia32_Immediate(env, node);
be_emit_cstring(env, ", ");
ia32_emit_dest_register(env, node, 0);
}
be_emit_finish_line_gas(env, node);
}
......@@ -2016,12 +1967,18 @@ void ia32_register_emitters(void) {
/* other ia32 emitter functions */
IA32_EMIT(Asm);
IA32_EMIT(CondJmp);
IA32_EMIT(CmpJmp);
IA32_EMIT2(CmpJmp8Bit, CmpJmp);
IA32_EMIT(TestJmp);
IA32_EMIT2(TestJmp8Bit, TestJmp);
IA32_EMIT(CmpCMov);
IA32_EMIT2(CmpCMov8Bit, CmpCMov);
IA32_EMIT(TestCMov);
IA32_EMIT2(TestCMov8Bit, TestCMov);
IA32_EMIT(CmpSet);
IA32_EMIT2(CmpSet8Bit, CmpSet);
IA32_EMIT(TestSet);
IA32_EMIT2(TestSet8Bit, TestSet);
IA32_EMIT(SwitchJmp);
IA32_EMIT(CopyB);
IA32_EMIT(CopyB_i);
......@@ -2035,13 +1992,13 @@ void ia32_register_emitters(void) {
IA32_EMIT(xCmp);
IA32_EMIT(xCmpSet);
IA32_EMIT(xCmpCMov);
IA32_EMIT(xCondJmp);
IA32_EMIT2(fcomJmp, x87CondJmp);
IA32_EMIT2(fcompJmp, x87CondJmp);
IA32_EMIT2(fcomppJmp, x87CondJmp);
IA32_EMIT2(fcomrJmp, x87CondJmp);
IA32_EMIT2(fcomrpJmp, x87CondJmp);
IA32_EMIT2(fcomrppJmp, x87CondJmp);
IA32_EMIT(xCmpJmp);
IA32_EMIT2(fcomJmp, x87CmpJmp);
IA32_EMIT2(fcompJmp, x87CmpJmp);
IA32_EMIT2(fcomppJmp, x87CmpJmp);
IA32_EMIT2(fcomrJmp, x87CmpJmp);
IA32_EMIT2(fcomrpJmp, x87CmpJmp);
IA32_EMIT2(fcomrppJmp, x87CmpJmp);
/* benode emitter */
BE_EMIT(Call);
......
......@@ -48,6 +48,8 @@ void ia32_emit_16bit_source_register(ia32_emit_env_t *env, const ir_node *node,
void ia32_emit_dest_register(ia32_emit_env_t *env, const ir_node *node, int pos);
void ia32_emit_x87_name(ia32_emit_env_t *env, const ir_node *node, int pos);
void ia32_emit_immediate(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_source_register_or_immediate(ia32_emit_env_t *env,
const ir_node *node, int pos);
void ia32_emit_mode_suffix(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_x87_mode_suffix(ia32_emit_env_t *env, const ir_node *node);
void ia32_emit_xmm_mode_suffix(ia32_emit_env_t *env, const ir_node *node);
......
......@@ -64,8 +64,11 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
const arch_register_t *in1_reg, *in2_reg, *out_reg, **slots;
int i, arity;
/* Return if AM node or not a Sub or xSub */
if (!(is_ia32_Sub(irn) || is_ia32_xSub(irn)) || get_ia32_op_type(irn) != ia32_Normal)
/* Return if not a Sub or xSub */
if (!is_ia32_Sub(irn) && !is_ia32_xSub(irn))
return;
/* fix_am will solve this for AddressMode variants */
if(get_ia32_op_type(irn) != ia32_Normal)
return;
noreg = ia32_new_NoReg_gp(cg);
......@@ -77,6 +80,8 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
in2_reg = arch_get_irn_register(cg->arch_env, in2);
out_reg = get_ia32_out_reg(irn, 0);
assert(get_irn_mode(irn) != mode_T);
irg = cg->irg;
block = get_nodes_block(irn);
......@@ -96,7 +101,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
set_ia32_op_type(res, ia32_AddrModeS);
set_ia32_ls_mode(res, get_ia32_ls_mode(irn));
} else {
res = new_rd_ia32_Neg(dbg, irg, block, noreg, noreg, in2, nomem);
res = new_rd_ia32_Neg(dbg, irg, block, in2);
}
arch_set_irn_register(cg->arch_env, res, in2_reg);
......@@ -108,8 +113,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
res = new_rd_ia32_xAdd(dbg, irg, block, noreg, noreg, res, in1, nomem);
set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
set_ia32_ls_mode(res, get_ia32_ls_mode(irn));
}
else {
} else {
res = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, res, in1, nomem);
set_ia32_am_support(res, ia32_am_Full, ia32_am_binary);
set_ia32_commutative(res);
......@@ -136,122 +140,181 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) {
DBG_OPT_SUB2NEGADD(irn, res);
}
static INLINE int is_noreg(ia32_code_gen_t *cg, const ir_node *node)
{
return node == cg->noreg_gp;
}
static ir_node *create_immediate_from_int(ia32_code_gen_t *cg, int val)
{
ir_graph *irg = current_ir_graph;
ir_node *start_block = get_irg_start_block(irg);
ir_node *immediate = new_rd_ia32_Immediate(NULL, irg, start_block, NULL,
0, val);
arch_set_irn_register(cg->arch_env, immediate, &ia32_gp_regs[REG_GP_NOREG]);
return immediate;
}
static ir_node *create_immediate_from_am(ia32_code_gen_t *cg,
const ir_node *node)
{
ir_graph *irg = get_irn_irg(node);
ir_node *block = get_nodes_block(node);
int offset = get_ia32_am_offs_int(node);
int sc_sign = is_ia32_am_sc_sign(node);