/* jump table for switch generation */
typedef struct _jmp_tbl_t {
- ir_node *defProj; /**< default target */
- long min_value; /**< smallest switch case */
- long max_value; /**< largest switch case */
- long num_branches; /**< number of jumps */
- char *label; /**< label of the jump table */
- branch_t *branches; /**< jump array */
+ ir_node *defProj; /**< default target */
+ long min_value; /**< smallest switch case */
+ long max_value; /**< largest switch case */
+ long num_branches; /**< number of jumps */
+ char label[SNPRINTF_BUF_LEN]; /**< label of the jump table */
+ branch_t *branches; /**< jump array */
} jmp_tbl_t;
/**
const ir_edge_t *edge;
/* fill the table structure */
- tbl.label = XMALLOCN(char, SNPRINTF_BUF_LEN);
- tbl.label = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, ".TBL_");
+ get_unique_label(tbl.label, SNPRINTF_BUF_LEN, ".TBL_");
tbl.defProj = NULL;
tbl.num_branches = get_irn_n_edges(node) - 1;
tbl.branches = XMALLOCNZ(branch_t, tbl.num_branches);
ia32_emitf(tbl.branches[0].target, "\tjmp %L\n");
}
- if (tbl.label)
- free(tbl.label);
- if (tbl.branches)
- free(tbl.branches);
+ free(tbl.branches);
}
/**
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) \
}
}
+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);
//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)
bemit8(code + out->index);
}
+static void bemit_fabs(const ir_node *node)
+{
+ (void)node;
+
+ bemit8(0xD9);
+ bemit8(0xE1);
+}
+
static void bemit_fadd(const ir_node *node)
{
bemit_fbinop(node, 0, 0);
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_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_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_Xor0, bemit_xor0);
register_emitter(op_ia32_XorMem, bemit_xormem);
register_emitter(op_ia32_XorMem8Bit, bemit_xormem8bit);
+ register_emitter(op_ia32_fabs, bemit_fabs);
register_emitter(op_ia32_fadd, bemit_fadd);
register_emitter(op_ia32_faddp, bemit_faddp);
register_emitter(op_ia32_fchs, bemit_fchs);