/*
- * Copyright (C) 1995-2011 University of Karlsruhe. All right reserved.
- *
* This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
+ * Copyright (C) 2012 University of Karlsruhe.
*/
/**
BINOP(and, 4)
BINOP(sub, 5)
BINOP(xor, 6)
+BINOP(cmp, 7)
-#define BINOPMEM(op, ext) \
-static void bemit_##op(const ir_node *node) \
-{ \
- ir_node *val; \
- unsigned size = get_mode_size_bits(get_ia32_ls_mode(node)); \
- if (size == 16) \
- bemit8(0x66); \
- val = get_irn_n(node, n_ia32_unary_op); \
- if (is_ia32_Immediate(val)) { \
- const ia32_immediate_attr_t *attr = get_ia32_immediate_attr_const(val); \
- int offset = attr->offset; \
- if (attr->symconst == NULL && get_signed_imm_size(offset) == 1) { \
- bemit8(0x83); \
- bemit_mod_am(ext, node); \
- bemit8(offset); \
- } else { \
- bemit8(0x81); \
- bemit_mod_am(ext, node); \
- if (size == 16) { \
- bemit16(offset); \
- } else { \
- bemit_entity(attr->symconst, attr->sc_sign, offset, false); \
- } \
- } \
- } else { \
- bemit8(ext << 3 | 1); \
- bemit_mod_am(reg_gp_map[arch_get_irn_register(val)->index], node); \
- } \
-} \
- \
-static void bemit_##op##8bit(const ir_node *node) \
-{ \
- ir_node *val = get_irn_n(node, n_ia32_unary_op); \
- if (is_ia32_Immediate(val)) { \
- bemit8(0x80); \
- bemit_mod_am(ext, node); \
- bemit8(get_ia32_immediate_attr_const(val)->offset); \
- } else { \
- bemit8(ext << 3); \
- bemit_mod_am(reg_gp_map[arch_get_irn_register(val)->index], node); \
- } \
+static void bemit_binop_mem(ir_node const *const node, unsigned const code)
+{
+ unsigned size = get_mode_size_bits(get_ia32_ls_mode(node));
+ if (size == 16)
+ bemit8(0x66);
+
+ unsigned op = size == 8 ? OP_8 : OP_16_32;
+ ir_node *const val = get_irn_n(node, n_ia32_unary_op);
+ if (is_ia32_Immediate(val)) {
+ ia32_immediate_attr_t const *const attr = get_ia32_immediate_attr_const(val);
+ /* Try to use the short form with 8bit sign extended immediate. */
+ if (op != OP_8 && !attr->symconst && get_signed_imm_size(attr->offset) == 1) {
+ op = OP_16_32_IMM8;
+ size = 8;
+ }
+
+ /* Emit the main opcode. */
+ bemit8(0x80 | op);
+ bemit_mod_am(code, node);
+
+ /* Emit the immediate. */
+ switch (size) {
+ case 8: bemit8(attr->offset); break;
+ case 16: bemit16(attr->offset); break;
+ case 32: bemit_entity(attr->symconst, attr->sc_sign, attr->offset, false); break;
+ }
+ } else {
+ bemit8(code << 3 | op);
+ bemit_mod_am(reg_gp_map[arch_get_irn_register(val)->index], node);
+ }
}
+#define BINOPMEM(op, code) \
+ static void bemit_##op(ir_node const *const node) \
+ { \
+ bemit_binop_mem(node, code); \
+ }
+
BINOPMEM(addmem, 0)
BINOPMEM(ormem, 1)
BINOPMEM(andmem, 4)
}
}
-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(0x80 | OP_16_32_IMM8);
- /* cmp has this special mode */
- if (get_ia32_op_type(node) == ia32_Normal) {
- const arch_register_t *reg = arch_get_irn_register_in(node, n_ia32_binary_left);
- bemit_modru(reg, 7);
- } else {
- bemit_mod_am(7, node);
- }
- 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_Normal) {
- const arch_register_t *reg = arch_get_irn_register_in(node, n_ia32_binary_left);
- if (reg->index == REG_GP_EAX) {
- bemit8(0x3D);
- } else {
- bemit8(0x81);
- bemit_modru(reg, 7);
- }
- } else {
- bemit8(0x81);
- bemit_mod_am(7, node);
- }
- 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 = arch_get_irn_register_in(node, n_ia32_binary_left);
- bemit8(0x3B);
- if (get_ia32_op_type(node) == ia32_Normal) {
- const arch_register_t *op2 = arch_get_irn_register_in(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);
- if (is_ia32_Immediate(right)) {
- if (get_ia32_op_type(node) == ia32_Normal) {
- const arch_register_t *out = arch_get_irn_register_in(node, n_ia32_Cmp_left);
- if (out->index == REG_GP_EAX) {
- bemit8(0x3C);
- } else {
- bemit8(0x80);
- bemit_modru(out, 7);
- }
- } else {
- bemit8(0x80);
- bemit_mod_am(7, node);
- }
- bemit8(get_ia32_immediate_attr_const(right)->offset);
- } else {
- const arch_register_t *out = arch_get_irn_register_in(node, n_ia32_Cmp_left);
- bemit8(0x3A);
- if (get_ia32_op_type(node) == ia32_Normal) {
- const arch_register_t *in = arch_get_irn_register_in(node, n_ia32_Cmp_right);
- bemit_modrr(out, in);
- } else {
- bemit_mod_am(reg_gp_map[out->index], node);
- }
- }
-}
-
static void bemit_test(ir_node const *const node)
{
unsigned const size = get_mode_size_bits(get_ia32_ls_mode(node));
be_set_emitter(op_ia32_Adc, bemit_adc);
be_set_emitter(op_ia32_Add, bemit_add);
be_set_emitter(op_ia32_AddMem, bemit_addmem);
- be_set_emitter(op_ia32_AddMem8Bit, bemit_addmem8bit);
be_set_emitter(op_ia32_And, bemit_and);
be_set_emitter(op_ia32_AndMem, bemit_andmem);
- be_set_emitter(op_ia32_AndMem8Bit, bemit_andmem8bit);
be_set_emitter(op_ia32_Asm, emit_ia32_Asm); // TODO implement binary emitter
be_set_emitter(op_ia32_Breakpoint, bemit_int3);
be_set_emitter(op_ia32_Bsf, bemit_bsf);
be_set_emitter(op_ia32_Cltd, bemit_cltd);
be_set_emitter(op_ia32_Cmc, bemit_cmc);
be_set_emitter(op_ia32_Cmp, bemit_cmp);
- be_set_emitter(op_ia32_Cmp8Bit, bemit_cmp8bit);
be_set_emitter(op_ia32_Const, bemit_mov_const);
be_set_emitter(op_ia32_Conv_I2I, bemit_conv_i2i);
- be_set_emitter(op_ia32_Conv_I2I8Bit, bemit_conv_i2i);
be_set_emitter(op_ia32_CopyB_i, bemit_copybi);
be_set_emitter(op_ia32_Cwtl, bemit_cwtl);
be_set_emitter(op_ia32_Dec, bemit_dec);
be_set_emitter(op_ia32_NotMem, bemit_notmem);
be_set_emitter(op_ia32_Or, bemit_or);
be_set_emitter(op_ia32_OrMem, bemit_ormem);
- be_set_emitter(op_ia32_OrMem8Bit, bemit_ormem8bit);
be_set_emitter(op_ia32_Pop, bemit_pop);
be_set_emitter(op_ia32_PopEbp, bemit_pop);
be_set_emitter(op_ia32_PopMem, bemit_popmem);
be_set_emitter(op_ia32_ShrMem, bemit_shrmem);
be_set_emitter(op_ia32_Stc, bemit_stc);
be_set_emitter(op_ia32_Store, bemit_store);
- be_set_emitter(op_ia32_Store8Bit, bemit_store);
be_set_emitter(op_ia32_Sub, bemit_sub);
be_set_emitter(op_ia32_SubMem, bemit_submem);
- be_set_emitter(op_ia32_SubMem8Bit, bemit_submem8bit);
be_set_emitter(op_ia32_SubSP, bemit_subsp);
be_set_emitter(op_ia32_SwitchJmp, bemit_switchjmp);
be_set_emitter(op_ia32_Test, bemit_test);
be_set_emitter(op_ia32_Xor, bemit_xor);
be_set_emitter(op_ia32_Xor0, bemit_xor0);
be_set_emitter(op_ia32_XorMem, bemit_xormem);
- be_set_emitter(op_ia32_XorMem8Bit, bemit_xormem8bit);
be_set_emitter(op_ia32_fabs, bemit_fabs);
be_set_emitter(op_ia32_fadd, bemit_fadd);
be_set_emitter(op_ia32_fchs, bemit_fchs);