From 2060dcfae09901d9f7685830da4199ca957672bc Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Mon, 21 Sep 2009 20:31:57 +0000 Subject: [PATCH] fix binary emitter for cmp with addressmode and immediate [r26581] --- ir/be/ia32/ia32_emitter.c | 109 +++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index d1650d6a2..098011757 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -2416,55 +2416,6 @@ static unsigned get_signed_imm_size(int offset) } } -/** - * Emit a binop with a immediate operand. - * - * @param node the node to emit - * @param opcode_eax the opcode for the op eax, imm variant - * @param opcode the opcode for the reg, imm variant - * @param ruval the opcode extension for opcode - */ -static void bemit_binop_with_imm( - const ir_node *node, - unsigned char opcode_ax, - unsigned char opcode, unsigned char ruval) -{ - /* Use in-reg, because some instructions (cmp, test) have no out-reg. */ - const arch_register_t *reg = get_in_reg(node, n_ia32_binary_left); - 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; - - /* Some instructions (test) have no short form with 32bit value + 8bit - * immediate. */ - if (attr->symconst != NULL || opcode & SIGNEXT_IMM) - size = 4; - else { - /* check for sign extension */ - size = get_signed_imm_size(attr->offset); - } - - switch (size) { - case 1: - bemit8(opcode | SIGNEXT_IMM); - bemit_modru(reg, ruval); - bemit8((unsigned char)attr->offset); - return; - case 2: - case 4: - /* check for eax variant: this variant is shorter for 32bit immediates only */ - if (reg->index == REG_EAX) { - bemit8(opcode_ax); - } else { - bemit8(opcode); - bemit_modru(reg, ruval); - } - bemit_entity(attr->symconst, attr->sc_sign, attr->offset, false); - return; - } - panic("invalid imm size?!?"); -} - /** * Emit an address mode. * @@ -2562,6 +2513,66 @@ static void bemit_mod_am(unsigned reg, const ir_node *node) } } +/** + * Emit a binop with a immediate operand. + * + * @param node the node to emit + * @param opcode_eax the opcode for the op eax, imm variant + * @param opcode the opcode for the reg, imm variant + * @param ruval the opcode extension for opcode + */ +static void bemit_binop_with_imm( + const ir_node *node, + unsigned char opcode_ax, + unsigned char opcode, unsigned char ruval) +{ + /* 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; + + /* Some instructions (test) have no short form with 32bit value + 8bit + * immediate. */ + if (attr->symconst != NULL || opcode & SIGNEXT_IMM) { + size = 4; + } else { + /* check for sign extension */ + size = get_signed_imm_size(attr->offset); + } + + switch (size) { + case 1: + bemit8(opcode | SIGNEXT_IMM); + /* cmp has this special mode */ + if (get_ia32_op_type(node) == ia32_AddrModeS) { + bemit_mod_am(ruval, node); + } else { + const arch_register_t *reg = get_in_reg(node, n_ia32_binary_left); + bemit_modru(reg, ruval); + } + 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(opcode); + bemit_mod_am(ruval, node); + } else { + const arch_register_t *reg = get_in_reg(node, n_ia32_binary_left); + if (reg->index == REG_EAX) { + bemit8(opcode_ax); + } else { + bemit8(opcode); + bemit_modru(reg, ruval); + } + } + bemit_entity(attr->symconst, attr->sc_sign, attr->offset, false); + return; + } + panic("invalid imm size?!?"); +} + /** * Emits a binop. */ -- 2.20.1