panic("NIY");
} else {
assert(arch_register_get_class(in) == &ia32_reg_classes[CLASS_ia32_gp]);
- bemit8(0x89);
- bemit_modrr(out, in);
+ bemit8(0x8B);
+ bemit_modrr(in, out);
}
}
BINOP(and, 0x23, 0x25, 0x81, 4)
BINOP(sub, 0x2B, 0x2D, 0x81, 5)
BINOP(xor, 0x33, 0x35, 0x81, 6)
-BINOP(cmp, 0x3B, 0x3D, 0x81, 7)
BINOP(test, 0x85, 0xA9, 0xF7, 0)
#define BINOPMEM(op, ext) \
SHIFT(shr, 5)
SHIFT(sar, 7)
+static void bemit_shld(const ir_node *node)
+{
+ const arch_register_t *in = get_in_reg(node, n_ia32_ShlD_val_low);
+ const arch_register_t *out = get_out_reg(node, pn_ia32_ShlD_res);
+ ir_node *count = get_irn_n(node, n_ia32_ShlD_count);
+ bemit8(0x0F);
+ if (is_ia32_Immediate(count)) {
+ bemit8(0xA4);
+ bemit_modrr(out, in);
+ bemit8(get_ia32_immediate_attr_const(count)->offset);
+ } else {
+ bemit8(0xA5);
+ bemit_modrr(out, in);
+ }
+}
+
+static void bemit_shrd(const ir_node *node)
+{
+ const arch_register_t *in = get_in_reg(node, n_ia32_ShrD_val_low);
+ const arch_register_t *out = get_out_reg(node, pn_ia32_ShrD_res);
+ ir_node *count = get_irn_n(node, n_ia32_ShrD_count);
+ bemit8(0x0F);
+ if (is_ia32_Immediate(count)) {
+ bemit8(0xAC);
+ bemit_modrr(out, in);
+ bemit8(get_ia32_immediate_attr_const(count)->offset);
+ } else {
+ bemit8(0xAD);
+ bemit_modrr(out, in);
+ }
+}
+
+static void bemit_cmov(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 *out = arch_irn_get_register(node, pn_ia32_res);
+ pn_Cmp pnc = get_ia32_condcode(node);
+ const arch_register_t *in_true;
+ const arch_register_t *in_false;
+
+ pnc = determine_final_pnc(node, n_ia32_CMov_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));
+
+ /* should be same constraint fullfilled? */
+ if (out == in_false) {
+ /* yes -> nothing to do */
+ } else if (out == in_true) {
+ assert(get_ia32_op_type(node) == ia32_Normal);
+ ins_permuted = !ins_permuted;
+ in_true = in_false;
+ } else {
+ /* we need a mov */
+ bemit8(0x8B); // mov %in_false, %out
+ bemit_modrr(in_false, out);
+ }
+
+ if (ins_permuted)
+ pnc = ia32_get_negated_pnc(pnc);
+
+ /* TODO: handling of Nans isn't correct yet */
+
+ bemit8(0x0F);
+ bemit8(0x40 + pnc2cc(pnc));
+ if (get_ia32_op_type(node) == ia32_Normal) {
+ bemit_modrr(in_true, out);
+ } else {
+ bemit_mod_am(reg_gp_map[out->index], node);
+ }
+}
+
+static void bemit_cmp(const ir_node *node)
+{
+ unsigned ls_size = get_mode_size_bits(get_ia32_ls_mode(node));
+ ir_node *right;
+
+ if (ls_size == 16)
+ bemit8(0x66);
+
+ right = get_irn_n(node, n_ia32_binary_right);
+ if (is_ia32_Immediate(right)) {
+ /* Use in-reg, because some instructions (cmp, test) have no out-reg. */
+ const ir_node *op = get_irn_n(node, n_ia32_binary_right);
+ const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(op);
+ unsigned size;
+
+ if (attr->symconst != NULL) {
+ size = 4;
+ } else {
+ /* check for sign extension */
+ size = get_signed_imm_size(attr->offset);
+ }
+
+ switch (size) {
+ case 1:
+ bemit8(0x81 | SIGNEXT_IMM);
+ /* cmp has this special mode */
+ if (get_ia32_op_type(node) == ia32_AddrModeS) {
+ bemit_mod_am(7, node);
+ } else {
+ const arch_register_t *reg = get_in_reg(node, n_ia32_binary_left);
+ bemit_modru(reg, 7);
+ }
+ bemit8((unsigned char)attr->offset);
+ return;
+ case 2:
+ case 4:
+ /* check for eax variant: this variant is shorter for 32bit immediates only */
+ if (get_ia32_op_type(node) == ia32_AddrModeS) {
+ bemit8(0x81);
+ bemit_mod_am(7, node);
+ } else {
+ const arch_register_t *reg = get_in_reg(node, n_ia32_binary_left);
+ if (reg->index == REG_EAX) {
+ bemit8(0x3D);
+ } else {
+ bemit8(0x81);
+ bemit_modru(reg, 7);
+ }
+ }
+ if (ls_size == 16) {
+ bemit16(attr->offset);
+ } else {
+ bemit_entity(attr->symconst, attr->sc_sign, attr->offset, false);
+ }
+ return;
+ }
+ panic("invalid imm size?!?");
+ } else {
+ const arch_register_t *out = get_in_reg(node, n_ia32_binary_left);
+ bemit8(0x3B);
+ if (get_ia32_op_type(node) == ia32_Normal) {
+ const arch_register_t *op2 = get_in_reg(node, n_ia32_binary_right);
+ bemit_modrr(op2, out);
+ } else {
+ bemit_mod_am(reg_gp_map[out->index], node);
+ }
+ }
+}
+
static void bemit_cmp8bit(const ir_node *node)
{
ir_node *right = get_irn_n(node, n_ia32_binary_right);
}
}
+static void bemit_test8bit(const ir_node *node)
+{
+ ir_node *right = get_irn_n(node, n_ia32_Test8Bit_right);
+ if (is_ia32_Immediate(right)) {
+ if (get_ia32_op_type(node) == ia32_Normal) {
+ const arch_register_t *out = get_in_reg(node, n_ia32_Test8Bit_left);
+ if (out->index == REG_EAX) {
+ bemit8(0xA8);
+ } else {
+ bemit8(0xF6);
+ bemit_modru(out, 0);
+ }
+ } else {
+ bemit8(0xF6);
+ bemit_mod_am(0, node);
+ }
+ bemit8(get_ia32_immediate_attr_const(right)->offset);
+ } else {
+ bemit8(0x84);
+ const arch_register_t *out = get_in_reg(node, n_ia32_Test8Bit_left);
+ if (get_ia32_op_type(node) == ia32_Normal) {
+ const arch_register_t *in = get_in_reg(node, n_ia32_Test8Bit_right);
+ bemit_modrr(out, in);
+ } else {
+ bemit_mod_am(reg_gp_map[out->index], node);
+ }
+ }
+}
+
static void bemit_imul(const ir_node *node)
{
ir_node *right = get_irn_n(node, n_ia32_IMul_right);
bemit_modru(get_out_reg(node, pn_ia32_Set_res), 2);
}
+static void bemit_ldtls(const ir_node *node)
+{
+ const arch_register_t *out = get_out_reg(node, 0);
+
+ bemit8(0x65); // gs:
+ if (out->index == REG_EAX) {
+ bemit8(0xA1); // movl 0, %eax
+ } else {
+ bemit8(0x8B); // movl 0, %reg
+ bemit8(MOD_IND | ENC_REG(out->index) | ENC_RM(0x05));
+ }
+ bemit32(0);
+}
+
/**
* Emit a Lea.
*/
//EMIT_SINGLEOP(aaa, 0x37)
//EMIT_SINGLEOP(aas, 0x3F)
//EMIT_SINGLEOP(nop, 0x90)
-EMIT_SINGLEOP(cwtl, 0x98)
-EMIT_SINGLEOP(cltd, 0x99)
+EMIT_SINGLEOP(cwtl, 0x98)
+EMIT_SINGLEOP(cltd, 0x99)
//EMIT_SINGLEOP(fwait, 0x9B)
-EMIT_SINGLEOP(sahf, 0x9E)
+EMIT_SINGLEOP(sahf, 0x9E)
//EMIT_SINGLEOP(popf, 0x9D)
-EMIT_SINGLEOP(int3, 0xCC)
+EMIT_SINGLEOP(leave, 0xC9)
+EMIT_SINGLEOP(int3, 0xCC)
//EMIT_SINGLEOP(iret, 0xCF)
//EMIT_SINGLEOP(xlat, 0xD7)
//EMIT_SINGLEOP(lock, 0xF0)
-EMIT_SINGLEOP(rep, 0xF3)
+EMIT_SINGLEOP(rep, 0xF3)
//EMIT_SINGLEOP(halt, 0xF4)
-EMIT_SINGLEOP(cmc, 0xF5)
-EMIT_SINGLEOP(stc, 0xF9)
+EMIT_SINGLEOP(cmc, 0xF5)
+EMIT_SINGLEOP(stc, 0xF9)
//EMIT_SINGLEOP(cli, 0xFA)
//EMIT_SINGLEOP(sti, 0xFB)
//EMIT_SINGLEOP(std, 0xFD)
bemit_fbinopp(node, 0xF8);
}
+static void bemit_fdivr(const ir_node *node)
+{
+ bemit_fbinop(node, 7, 6);
+}
+
static void bemit_fdivrp(const ir_node *node)
{
bemit_fbinopp(node, 0xF0);
switch (get_mode_size_bits(get_ia32_ls_mode(node))) {
case 16:
bemit8(0xDF); // fists
- return;
+ break;
case 32:
bemit8(0xDB); // fistl
- return;
+ break;
default:
panic("invalid mode size");
bemit_fbinop(node, 5, 4);
}
+static void bemit_fsubrp(const ir_node *node)
+{
+ bemit_fbinopp(node, 0xE0);
+}
+
static void bemit_fnstcw(const ir_node *node)
{
bemit8(0xD9); // fnstcw
bemit_fnstsw();
}
-static void bemit_fucomfnstsw(const ir_node *node)
+static void bemit_fucomi(const ir_node *node)
{
- (void)node;
+ const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
+ bemit8(0xDB); // fucomi
+ bemit8(0xE8 + attr->x87[1]->index);
+}
+
+static void bemit_fucomip(const ir_node *node)
+{
+ const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
+ bemit8(0xDF); // fucomip
+ bemit8(0xE8 + attr->x87[1]->index);
+}
+static void bemit_fucomfnstsw(const ir_node *node)
+{
const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
bemit8(0xDD); // fucom
bemit8(0xE0 + attr->x87[1]->index);
static void bemit_fucompfnstsw(const ir_node *node)
{
- (void)node;
-
const ia32_x87_attr_t *attr = get_ia32_x87_attr_const(node);
bemit8(0xDD); // fucomp
bemit8(0xE8 + attr->x87[1]->index);
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_Call, bemit_call);
register_emitter(op_ia32_Cltd, bemit_cltd);
register_emitter(op_ia32_Cmc, bemit_cmc);
register_emitter(op_ia32_FnstCW, bemit_fnstcw);
register_emitter(op_ia32_FtstFnstsw, bemit_ftstfnstsw);
register_emitter(op_ia32_FucomFnstsw, bemit_fucomfnstsw);
+ register_emitter(op_ia32_Fucomi, bemit_fucomi);
register_emitter(op_ia32_FucompFnstsw, bemit_fucompfnstsw);
+ register_emitter(op_ia32_Fucompi, bemit_fucomip);
register_emitter(op_ia32_FucomppFnstsw, bemit_fucomppfnstsw);
register_emitter(op_ia32_IDiv, bemit_idiv);
register_emitter(op_ia32_IJmp, bemit_ijmp);
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_LdTls, bemit_ldtls);
register_emitter(op_ia32_Lea, bemit_lea);
+ register_emitter(op_ia32_Leave, bemit_leave);
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_Sbb, bemit_sbb);
register_emitter(op_ia32_Set, bemit_set);
register_emitter(op_ia32_Shl, bemit_shl);
+ register_emitter(op_ia32_ShlD, bemit_shld);
register_emitter(op_ia32_ShlMem, bemit_shlmem);
register_emitter(op_ia32_Shr, bemit_shr);
+ register_emitter(op_ia32_ShrD, bemit_shrd);
register_emitter(op_ia32_ShrMem, bemit_shrmem);
register_emitter(op_ia32_Stc, bemit_stc);
register_emitter(op_ia32_Store, bemit_store);
register_emitter(op_ia32_SubMem8Bit, bemit_submem8bit);
register_emitter(op_ia32_SubSP, bemit_subsp);
register_emitter(op_ia32_Test, bemit_test);
+ register_emitter(op_ia32_Test8Bit, bemit_test8bit);
register_emitter(op_ia32_Xor, bemit_xor);
register_emitter(op_ia32_Xor0, bemit_xor0);
register_emitter(op_ia32_XorMem, bemit_xormem);
register_emitter(op_ia32_fchs, bemit_fchs);
register_emitter(op_ia32_fdiv, bemit_fdiv);
register_emitter(op_ia32_fdivp, bemit_fdivp);
+ register_emitter(op_ia32_fdivr, bemit_fdivr);
register_emitter(op_ia32_fdivrp, bemit_fdivrp);
register_emitter(op_ia32_fild, bemit_fild);
register_emitter(op_ia32_fist, bemit_fist);
register_emitter(op_ia32_fsub, bemit_fsub);
register_emitter(op_ia32_fsubp, bemit_fsubp);
register_emitter(op_ia32_fsubr, bemit_fsubr);
+ register_emitter(op_ia32_fsubrp, bemit_fsubrp);
register_emitter(op_ia32_fxch, bemit_fxch);
/* ignore the following nodes */