be_emit_char('p');
return;
}
+
if (pnc & ia32_pn_Cmp_float || pnc & ia32_pn_Cmp_unsigned) {
str = cmp2condition_u[pnc & 7];
} else {
case 'R': {
const arch_register_t *reg = va_arg(ap, const arch_register_t*);
- emit_register(reg, NULL);
+ emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
break;
}
if (pnc & ia32_pn_Cmp_float) {
/* Some floating point comparisons require a test of the parity flag,
* which indicates that the result is unordered */
- switch (pnc & 15) {
- case pn_Cmp_Uo: {
- ia32_emitf(proj_true, "\tjp %L\n");
- break;
- }
+ switch (pnc & 0x0f) {
+ case pn_Cmp_Uo: {
+ ia32_emitf(proj_true, "\tjp %L\n");
+ break;
+ }
- case pn_Cmp_Leg:
- ia32_emitf(proj_true, "\tjnp %L\n");
- break;
+ case pn_Cmp_Leg:
+ ia32_emitf(proj_true, "\tjnp %L\n");
+ break;
- case pn_Cmp_Eq:
- case pn_Cmp_Lt:
- case pn_Cmp_Le:
- /* we need a local label if the false proj is a fallthrough
- * as the falseblock might have no label emitted then */
- if (can_be_fallthrough(proj_false)) {
- need_parity_label = 1;
- ia32_emitf(proj_false, "\tjp 1f\n");
- } else {
- ia32_emitf(proj_false, "\tjp %L\n");
- }
- goto emit_jcc;
+ case pn_Cmp_Eq:
+ case pn_Cmp_Lt:
+ case pn_Cmp_Le:
+ /* we need a local label if the false proj is a fallthrough
+ * as the falseblock might have no label emitted then */
+ if (can_be_fallthrough(proj_false)) {
+ need_parity_label = 1;
+ ia32_emitf(proj_false, "\tjp 1f\n");
+ } else {
+ ia32_emitf(proj_false, "\tjp %L\n");
+ }
+ goto emit_jcc;
- case pn_Cmp_Ug:
- case pn_Cmp_Uge:
- case pn_Cmp_Ne:
- ia32_emitf(proj_true, "\tjp %L\n");
- goto emit_jcc;
+ case pn_Cmp_Ug:
+ case pn_Cmp_Uge:
+ case pn_Cmp_Ne:
+ ia32_emitf(proj_true, "\tjp %L\n");
+ goto emit_jcc;
- default:
- goto emit_jcc;
+ default:
+ goto emit_jcc;
}
} else {
emit_jcc:
}
}
-static void emit_ia32_CMov(const ir_node *node)
+/**
+ * Emits an ia32 Setcc. This is mostly easy but some floating point compares
+ * are tricky.
+ */
+static void emit_ia32_Setcc(const ir_node *node)
+{
+ const arch_register_t *dreg = get_out_reg(node, pn_ia32_Setcc_res);
+
+ pn_Cmp pnc = get_ia32_condcode(node);
+ pnc = determine_final_pnc(node, n_ia32_Setcc_eflags, pnc);
+ if (pnc & ia32_pn_Cmp_float) {
+ switch (pnc & 0x0f) {
+ case pn_Cmp_Uo:
+ ia32_emitf(node, "\tsetp %#R\n", dreg);
+ break;
+
+ case pn_Cmp_Leg:
+ ia32_emitf(node, "\tsetnp %#R\n", dreg);
+ break;
+
+ case pn_Cmp_Eq:
+ case pn_Cmp_Lt:
+ case pn_Cmp_Le:
+ case pn_Cmp_Ug:
+ case pn_Cmp_Uge:
+ case pn_Cmp_Ne:
+ panic("No handling for set with parity bit yet in ia32_Setcc");
+
+ default:
+ break;
+ }
+ }
+ ia32_emitf(node, "\tset%P %#R\n", pnc, dreg);
+}
+
+static void emit_ia32_CMovcc(const ir_node *node)
{
const ia32_attr_t *attr = get_ia32_attr_const(node);
int ins_permuted = attr->data.ins_permuted;
const arch_register_t *in_true;
const arch_register_t *in_false;
- pnc = determine_final_pnc(node, n_ia32_CMov_eflags, pnc);
+ pnc = determine_final_pnc(node, n_ia32_CMovcc_eflags, pnc);
- in_true = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_true));
- in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_false));
+ in_true = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_true));
+ in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_false));
/* should be same constraint fullfilled? */
if (out == in_false) {
/* other ia32 emitter functions */
IA32_EMIT2(Conv_I2I8Bit, Conv_I2I);
IA32_EMIT(Asm);
- IA32_EMIT(CMov);
+ IA32_EMIT(CMovcc);
IA32_EMIT(Call);
IA32_EMIT(Const);
IA32_EMIT(Conv_FP2FP);
IA32_EMIT(GetEIP);
IA32_EMIT(IMul);
IA32_EMIT(Jcc);
+ IA32_EMIT(Setcc);
IA32_EMIT(LdTls);
IA32_EMIT(Minus64Bit);
IA32_EMIT(SwitchJmp);
}
}
-static void bemit_cmov(const ir_node *node)
+static void bemit_cmovcc(const ir_node *node)
{
const ia32_attr_t *attr = get_ia32_attr_const(node);
int ins_permuted = attr->data.ins_permuted;
const arch_register_t *in_true;
const arch_register_t *in_false;
- pnc = determine_final_pnc(node, n_ia32_CMov_eflags, pnc);
+ pnc = determine_final_pnc(node, n_ia32_CMovcc_eflags, pnc);
- in_true = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_true));
- in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMov_val_false));
+ in_true = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_true));
+ in_false = arch_get_irn_register(get_irn_n(node, n_ia32_CMovcc_val_false));
/* should be same constraint fullfilled? */
if (out == in_false) {
UNOPMEM(incmem, 0xFE, 0)
UNOPMEM(decmem, 0xFE, 1)
-static void bemit_set(const ir_node *node)
+static void bemit_setcc(const ir_node *node)
{
pn_Cmp pnc;
bemit8(0x0F);
pnc = get_ia32_condcode(node);
- pnc = determine_final_pnc(node, n_ia32_Set_eflags, pnc);
- if (get_ia32_attr_const(node)->data.ins_permuted)
- pnc = ia32_get_negated_pnc(pnc);
+ pnc = determine_final_pnc(node, n_ia32_Setcc_eflags, pnc);
+
+ /* TODO: all the special casing for float compares is missing */
+ if (pnc & ia32_pn_Cmp_float)
+ panic("binary setcc from float compare not implemented yet");
bemit8(0x90 + pnc2cc(pnc));
- bemit_modru(get_out_reg(node, pn_ia32_Set_res), 2);
+ bemit_modru(get_out_reg(node, pn_ia32_Setcc_res), 2);
}
static void bemit_ldtls(const ir_node *node)
register_emitter(op_ia32_AndMem, bemit_andmem);
register_emitter(op_ia32_AndMem8Bit, bemit_andmem8bit);
register_emitter(op_ia32_Breakpoint, bemit_int3);
- register_emitter(op_ia32_CMov, bemit_cmov);
+ register_emitter(op_ia32_CMovcc, bemit_cmovcc);
register_emitter(op_ia32_Call, bemit_call);
register_emitter(op_ia32_Cltd, bemit_cltd);
register_emitter(op_ia32_Cmc, bemit_cmc);
register_emitter(op_ia32_Sar, bemit_sar);
register_emitter(op_ia32_SarMem, bemit_sarmem);
register_emitter(op_ia32_Sbb, bemit_sbb);
- register_emitter(op_ia32_Set, bemit_set);
+ register_emitter(op_ia32_Setcc, bemit_setcc);
register_emitter(op_ia32_Shl, bemit_shl);
register_emitter(op_ia32_ShlD, bemit_shld);
register_emitter(op_ia32_ShlMem, bemit_shlmem);
case iro_ia32_Lea:
case iro_ia32_Conv_I2I:
case iro_ia32_Conv_I2I8Bit:
- case iro_ia32_CMov:
+ case iro_ia32_CMovcc:
return 0;
default:
/* dump pn code */
if (is_ia32_SwitchJmp(n)) {
fprintf(F, "pn_code = %ld\n", get_ia32_condcode(n));
- } else if (is_ia32_CMov(n) || is_ia32_Set(n) || is_ia32_Jcc(n)) {
+ } else if (is_ia32_CMovcc(n) || is_ia32_Setcc(n) || is_ia32_Jcc(n)) {
ia32_attr_t *attr = get_ia32_attr(n);
long pnc = get_ia32_condcode(n);
fprintf(F, "pn_code = 0x%lX (%s)\n", pnc, get_pnc_string(pnc & pn_Cmp_True));
modified_flags => $status_flags
},
-Set => {
+Setcc => {
#irn_flags => "R",
reg_req => { in => [ "eflags" ], out => [ "eax ebx ecx edx" ] },
ins => [ "eflags" ],
outs => [ "res" ],
attr_type => "ia32_condcode_attr_t",
- attr => "pn_Cmp pnc, int ins_permuted",
- init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
- "\tset_ia32_ls_mode(res, mode_Bu);\n",
- emit => '. set%CMP0 %DB0',
+ attr => "pn_Cmp pnc",
+ init_attr => "set_ia32_ls_mode(res, mode_Bu);\n",
latency => 1,
units => [ "GP" ],
mode => $mode_gp,
},
-SetMem => {
+SetccMem => {
#irn_flags => "R",
state => "exc_pinned",
reg_req => { in => [ "gp", "gp", "none", "eflags" ], out => [ "none" ] },
ins => [ "base", "index", "mem","eflags" ],
attr_type => "ia32_condcode_attr_t",
- attr => "pn_Cmp pnc, int ins_permuted",
- init_attr => "attr->attr.data.ins_permuted = ins_permuted;\n".
- "\tset_ia32_ls_mode(res, mode_Bu);\n",
+ attr => "pn_Cmp pnc",
+ init_attr => "set_ia32_ls_mode(res, mode_Bu);\n",
emit => '. set%CMP3 %AM',
latency => 1,
units => [ "GP" ],
mode => 'mode_M',
},
-CMov => {
+CMovcc => {
#irn_flags => "R",
# (note: leave the false,true order intact to make it compatible with other
# ia32_binary ops)
*/
static ir_node *gen_Not(ir_node *node)
{
- ir_node *op = get_Not_op(node);
+ ir_node *op = get_Not_op(node);
assert(get_irn_mode(node) != mode_b); /* should be lowered already */
assert (! mode_is_float(get_irn_mode(node)));
static ir_node *try_create_SetMem(ir_node *node, ir_node *ptr, ir_node *mem)
{
- ir_mode *mode = get_irn_mode(node);
- ir_node *mux_true = get_Mux_true(node);
- ir_node *mux_false = get_Mux_false(node);
- ir_node *cond;
- ir_node *new_mem;
- dbg_info *dbgi;
- ir_node *block;
- ir_node *new_block;
- ir_node *flags;
- ir_node *new_node;
- int negated;
- pn_Cmp pnc;
- ia32_address_t addr;
+ ir_mode *mode = get_irn_mode(node);
+ ir_node *mux_true = get_Mux_true(node);
+ ir_node *mux_false = get_Mux_false(node);
+ ir_node *cond;
+ ir_node *new_mem;
+ dbg_info *dbgi;
+ ir_node *block;
+ ir_node *new_block;
+ ir_node *flags;
+ ir_node *new_node;
+ bool negated;
+ pn_Cmp pnc;
+ ia32_address_t addr;
if (get_mode_size_bits(mode) != 8)
return NULL;
if (is_Const_1(mux_true) && is_Const_0(mux_false)) {
- negated = 0;
+ negated = false;
} else if (is_Const_0(mux_true) && is_Const_1(mux_false)) {
- negated = 1;
+ negated = true;
} else {
return NULL;
}
+ cond = get_Mux_sel(node);
+ flags = get_flags_node(cond, &pnc);
+ /* we can't handle the float special cases with SetM */
+ if (pnc & ia32_pn_Cmp_float)
+ return NULL;
+ if (negated)
+ pnc = get_negated_pnc(pnc, pnc & ia32_pn_Cmp_float ? mode_F : mode_Is);
+
build_address_ptr(&addr, ptr, mem);
dbgi = get_irn_dbg_info(node);
block = get_nodes_block(node);
new_block = be_transform_node(block);
- cond = get_Mux_sel(node);
- flags = get_flags_node(cond, &pnc);
new_mem = be_transform_node(mem);
- new_node = new_bd_ia32_SetMem(dbgi, new_block, addr.base,
- addr.index, addr.mem, flags, pnc, negated);
+ new_node = new_bd_ia32_SetccMem(dbgi, new_block, addr.base,
+ addr.index, addr.mem, flags, pnc);
set_address(new_node, &addr);
set_ia32_op_type(new_node, ia32_AddrModeD);
set_ia32_ls_mode(new_node, mode);
case iro_Mux:
new_node = try_create_SetMem(val, ptr, mem);
break;
+
case iro_Minus:
op1 = get_Minus_op(val);
new_node = dest_am_unop(val, op1, mem, ptr, mode, new_bd_ia32_NegMem);
match_arguments(&am, block, val_false, val_true, flags,
match_commutative | match_am | match_16bit_am | match_mode_neutral);
- new_node = new_bd_ia32_CMov(dbgi, new_block, addr->base, addr->index,
- addr->mem, am.new_op1, am.new_op2, new_flags,
- am.ins_permuted, pnc);
+ new_node = new_bd_ia32_CMovcc(dbgi, new_block, addr->base, addr->index,
+ addr->mem, am.new_op1, am.new_op2, new_flags,
+ am.ins_permuted, pnc);
set_am_attributes(new_node, &am);
SET_IA32_ORIG_NODE(new_node, node);
* Creates a ia32 Setcc instruction.
*/
static ir_node *create_set_32bit(dbg_info *dbgi, ir_node *new_block,
- ir_node *flags, pn_Cmp pnc, ir_node *orig_node,
- int ins_permuted)
+ ir_node *flags, pn_Cmp pnc, ir_node *orig_node)
{
ir_mode *mode = get_irn_mode(orig_node);
ir_node *new_node;
- new_node = new_bd_ia32_Set(dbgi, new_block, flags, pnc, ins_permuted);
+ new_node = new_bd_ia32_Setcc(dbgi, new_block, flags, pnc);
SET_IA32_ORIG_NODE(new_node, orig_node);
/* we might need to conv the result up */
unsigned scale;
flags = get_flags_node(cond, &pnc);
- new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, /*is_permuted=*/0);
+ new_node = create_set_32bit(dbgi, new_block, flags, pnc, node);
if (ia32_cg_config.use_sse2) {
/* cannot load from different mode on SSE */
if (is_Const(mux_true) && is_Const(mux_false)) {
/* both are const, good */
if (is_Const_1(mux_true) && is_Const_0(mux_false)) {
- new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, /*is_premuted=*/0);
+ new_node = create_set_32bit(dbgi, new_block, flags, pnc, node);
} else if (is_Const_0(mux_true) && is_Const_1(mux_false)) {
- new_node = create_set_32bit(dbgi, new_block, flags, pnc, node, /*is_premuted=*/1);
+ pnc = get_negated_pnc(pnc, pnc & ia32_pn_Cmp_float ? mode_F : mode_Is);
+ new_node = create_set_32bit(dbgi, new_block, flags, pnc, node);
} else {
/* Not that simple. */
goto need_cmov;
flag = new_r_Proj(block, real, mode_b, pn_ia32_flags);
/* sete */
- set = new_bd_ia32_Set(dbgi, block, flag, pn_Cmp_Eq, 0);
+ set = new_bd_ia32_Setcc(dbgi, block, flag, pn_Cmp_Eq);
SET_IA32_ORIG_NODE(set, node);
/* conv to 32bit */
cmp = fix_mem_proj(cmp, &am);
/* setp */
- new_node = new_bd_ia32_Set(dbgi, new_block, cmp, ia32_pn_Cmp_parity, 0);
+ new_node = new_bd_ia32_Setcc(dbgi, new_block, cmp, ia32_pn_Cmp_parity);
SET_IA32_ORIG_NODE(new_node, node);
/* conv to 32bit */
int reg_index_1 = arch_register_get_index(op1);
int reg_index_2 = arch_register_get_index(op2);
unsigned live = vfp_live_args_after(sim, n, 0);
- int permuted = attr->attr.data.ins_permuted;
- int xchg = 0;
- int pops = 0;
+ bool permuted = attr->attr.data.ins_permuted;
+ bool xchg = false;
+ int pops = 0;
DB((dbg, LEVEL_1, ">>> %+F %s, %s\n", n,
arch_register_get_name(op1), arch_register_get_name(op2)));
} else if (op2_idx == 0) {
/* res = op X tos */
permuted = !permuted;
- xchg = 1;
+ xchg = true;
} else {
/* bring the first one to tos */
x87_create_fxch(state, n, op1_idx);
op2_idx = 0;
}
/* res = op X tos, pop */
- pops = 1;
+ pops = 1;
permuted = !permuted;
- xchg = 1;
+ xchg = true;
} else {
/* both operands are dead here, check first for identity. */
if (op1_idx == op2_idx) {
}
/* res = op X tos, pop, pop */
permuted = !permuted;
- xchg = 1;
- pops = 2;
+ xchg = true;
+ pops = 2;
} else {
/* if one is already the TOS, we need two fxch */
if (op1_idx == 0) {
x87_create_fxch(state, n, op2_idx);
op2_idx = 0;
/* res = op X tos, pop, pop */
- pops = 2;
+ pops = 2;
permuted = !permuted;
- xchg = 1;
+ xchg = true;
} else if (op2_idx == 0) {
/* second one is TOS, move to st(1) */
x87_create_fxch(state, n, 1);