X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fbe%2Fia32%2Fia32_emitter.c;h=757c0392a4beaadc22952d01965045da2d28fb0b;hb=7a84c10295219975b2cd73b28a168b18e13894ec;hp=9fd943937ad98f0358e6a0a0e8998b2d9760896a;hpb=ae1f22bc196de900b07b51634992f06caaa01832;p=libfirm diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 9fd943937..757c0392a 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -2634,8 +2634,8 @@ static void bemit_copy(const ir_node *copy) 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); } } @@ -2701,7 +2701,6 @@ BINOP(sbb, 0x1B, 0x1D, 0x81, 3) 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) \ @@ -2820,6 +2819,148 @@ SHIFT(shl, 4) 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); @@ -2849,6 +2990,35 @@ static void bemit_cmp8bit(const ir_node *node) } } +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); @@ -2944,19 +3114,20 @@ static void bemit_ ## op(const ir_node *node) { \ //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) @@ -3600,10 +3771,22 @@ static void bemit_ftstfnstsw(const ir_node *node) 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); @@ -3612,8 +3795,6 @@ static void bemit_fucomfnstsw(const ir_node *node) 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); @@ -3668,6 +3849,7 @@ static void ia32_register_binary_emitters(void) 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); @@ -3685,7 +3867,9 @@ static void ia32_register_binary_emitters(void) 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); @@ -3697,6 +3881,7 @@ static void ia32_register_binary_emitters(void) 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); @@ -3721,8 +3906,10 @@ static void ia32_register_binary_emitters(void) 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); @@ -3732,6 +3919,7 @@ static void ia32_register_binary_emitters(void) 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);