reg_gp_map[REG_ESI] = 0x6;
reg_gp_map[REG_EDI] = 0x7;
- pnc_map_signed[pn_Cmp_False] = 0xFF;
pnc_map_signed[pn_Cmp_Eq] = 0x04;
pnc_map_signed[pn_Cmp_Lt] = 0x0C;
pnc_map_signed[pn_Cmp_Le] = 0x0E;
pnc_map_signed[pn_Cmp_Ge] = 0x0D;
pnc_map_signed[pn_Cmp_Lg] = 0x05;
- pnc_map_unsigned[pn_Cmp_False] = 0xFF;
pnc_map_unsigned[pn_Cmp_Eq] = 0x04;
pnc_map_unsigned[pn_Cmp_Lt] = 0x02;
pnc_map_unsigned[pn_Cmp_Le] = 0x06;
pnc_map_unsigned[pn_Cmp_Lg] = 0x05;
}
-#define GET_MODE(code) ((code) & 0xC0)
+static unsigned char pnc2cc(int pnc)
+{
+ unsigned char cc;
+ if (pnc == ia32_pn_Cmp_parity) {
+ cc = 0x0A;
+ } else if (pnc & ia32_pn_Cmp_float || pnc & ia32_pn_Cmp_unsigned) {
+ cc = pnc_map_unsigned[pnc & 0x07];
+ } else {
+ cc = pnc_map_signed[pnc & 0x07];
+ }
+ assert(cc != 0);
+ return cc;
+}
/** Sign extension bit values for binops */
enum SignExt {
emitsib = true;
} else {
modrm |= ENC_RM(base_enc);
- /* We are forced to emit an 8bit offset as EBP base without offset is a
- * special case for SIB without base register. */
- if (base_enc == 0x05 && emitoffs == 0) {
- modrm |= MOD_IND_BYTE_OFS;
- emitoffs = 8;
- }
+ }
+
+ /* We are forced to emit an 8bit offset as EBP base without offset is a
+ * special case for SIB without base register. */
+ if (base_enc == 0x05 && emitoffs == 0) {
+ modrm |= MOD_IND_BYTE_OFS;
+ emitoffs = 8;
}
modrm |= ENC_REG(reg);
bemit_unop(node, code, reg_gp_map[out->index], input);
}
+static void bemit_unop_mem(const ir_node *node, unsigned char code, unsigned char ext)
+{
+ bemit8(code);
+ bemit_mod_am(ext, node);
+}
+
static void bemit_immediate(const ir_node *node, bool relative)
{
const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(node);
}
}
+static void bemit_perm(const ir_node *node)
+{
+ const arch_register_t *in0 = arch_get_irn_register(get_irn_n(node, 0));
+ const arch_register_t *in1 = arch_get_irn_register(get_irn_n(node, 1));
+ const arch_register_class_t *cls0 = arch_register_get_class(in0);
+
+ assert(cls0 == arch_register_get_class(in1) && "Register class mismatch at Perm");
+
+ if (cls0 == &ia32_reg_classes[CLASS_ia32_gp]) {
+ if (in0->index == REG_EAX) {
+ bemit8(0x90 + reg_gp_map[in1->index]);
+ } else if (in1->index == REG_EAX) {
+ bemit8(0x90 + reg_gp_map[in0->index]);
+ } else {
+ bemit8(0x87);
+ bemit_modrr(in0, in1);
+ }
+ } else if (cls0 == &ia32_reg_classes[CLASS_ia32_xmm]) {
+ panic("unimplemented"); // TODO implement
+ //ia32_emitf(NULL, "\txorpd %R, %R\n", in1, in0);
+ //ia32_emitf(NULL, "\txorpd %R, %R\n", in0, in1);
+ //ia32_emitf(node, "\txorpd %R, %R\n", in1, in0);
+ } else if (cls0 == &ia32_reg_classes[CLASS_ia32_vfp]) {
+ /* is a NOP */
+ } else if (cls0 == &ia32_reg_classes[CLASS_ia32_st]) {
+ /* is a NOP */
+ } else {
+ panic("unexpected register class in be_Perm (%+F)", node);
+ }
+}
+
static void bemit_xor0(const ir_node *node)
{
const arch_register_t *out = get_out_reg(node, 0);
bemit8(0x40 + reg_gp_map[out->index]);
}
+#define UNOPMEM(op, code, ext) \
+static void bemit_##op(const ir_node *node) \
+{ \
+ bemit_unop_mem(node, code, ext); \
+}
+
+UNOPMEM(notmem, 0xF7, 2)
+UNOPMEM(negmem, 0xF7, 3)
+UNOPMEM(incmem, 0xFF, 0)
+UNOPMEM(decmem, 0xFF, 1)
+
+static void bemit_set(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);
+
+ bemit8(0x90 + pnc2cc(pnc));
+ bemit_modru(get_out_reg(node, pn_ia32_Set_res), 2);
+}
+
/**
* Emit a Lea.
*/
}
/**
- * Emit a single optcode.
+ * Emit a single opcode.
*/
#define EMIT_SINGLEOP(op, code) \
static void bemit_ ## op(const ir_node *node) { \
static void bemit_jcc(int pnc, const ir_node *dest_block)
{
- unsigned char cc;
-
- if (pnc == ia32_pn_Cmp_parity) {
- cc = 0x0A;
- } else {
- if (pnc & ia32_pn_Cmp_float || pnc & ia32_pn_Cmp_unsigned) {
- cc = pnc_map_unsigned[pnc & 0x07];
- } else {
- cc = pnc_map_signed[pnc & 0x07];
- }
- }
- assert(cc != 0xFF);
-
+ unsigned char cc = pnc2cc(pnc);
bemit8(0x0F);
bemit8(0x80 + cc);
bemit_jmp_destination(dest_block);
register_emitter(op_be_Copy, bemit_copy);
register_emitter(op_be_CopyKeep, bemit_copy);
register_emitter(op_be_IncSP, bemit_incsp);
+ register_emitter(op_be_Perm, bemit_perm);
register_emitter(op_be_Return, bemit_return);
register_emitter(op_ia32_Adc, bemit_adc);
register_emitter(op_ia32_Add, bemit_add);
register_emitter(op_ia32_Cmc, bemit_cmc);
register_emitter(op_ia32_Cmp, bemit_cmp);
register_emitter(op_ia32_Const, bemit_mov_const);
- register_emitter(op_ia32_Conv_I2I, bemit_conv_i2i);
register_emitter(op_ia32_Conv_I2I8Bit, bemit_conv_i2i);
+ register_emitter(op_ia32_Conv_I2I, bemit_conv_i2i);
register_emitter(op_ia32_Cwtl, bemit_cwtl);
register_emitter(op_ia32_Dec, bemit_dec);
+ register_emitter(op_ia32_DecMem, bemit_decmem);
register_emitter(op_ia32_Div, bemit_div);
register_emitter(op_ia32_IDiv, bemit_idiv);
register_emitter(op_ia32_IJmp, bemit_ijmp);
register_emitter(op_ia32_IMul1OP, bemit_imul1op);
register_emitter(op_ia32_IMul, bemit_imul);
register_emitter(op_ia32_Inc, bemit_inc);
+ register_emitter(op_ia32_IncMem, bemit_incmem);
register_emitter(op_ia32_Jcc, bemit_ia32_jcc);
register_emitter(op_ia32_Jmp, bemit_jump);
register_emitter(op_ia32_Lea, bemit_lea);
register_emitter(op_ia32_Load, bemit_load);
register_emitter(op_ia32_Mul, bemit_mul);
register_emitter(op_ia32_Neg, bemit_neg);
+ register_emitter(op_ia32_NegMem, bemit_negmem);
register_emitter(op_ia32_Not, bemit_not);
+ register_emitter(op_ia32_NotMem, bemit_notmem);
register_emitter(op_ia32_Or, bemit_or);
register_emitter(op_ia32_Pop, bemit_pop);
register_emitter(op_ia32_PopEbp, bemit_pop);
register_emitter(op_ia32_Sahf, bemit_sahf);
register_emitter(op_ia32_Sar, bemit_sar);
register_emitter(op_ia32_Sbb, bemit_sbb);
+ register_emitter(op_ia32_Set, bemit_set);
register_emitter(op_ia32_Shl, bemit_shl);
register_emitter(op_ia32_Shr, bemit_shr);
register_emitter(op_ia32_Stc, bemit_stc);
+ register_emitter(op_ia32_Store8Bit, bemit_store);
register_emitter(op_ia32_Store, bemit_store);
register_emitter(op_ia32_Sub, bemit_sub);
register_emitter(op_ia32_Test, bemit_test);
- register_emitter(op_ia32_Xor, bemit_xor);
register_emitter(op_ia32_Xor0, bemit_xor0);
+ register_emitter(op_ia32_Xor, bemit_xor);
/* ignore the following nodes */
register_emitter(op_ia32_ProduceVal, emit_Nothing);