/**
* This file implements the node emitter.
- *
+ * @author Christian Wuerdig
* $Id$
*/
* |_| |_|
*************************************************************/
+static INLINE int be_is_unknown_reg(const arch_register_t *reg) {
+ return \
+ REGS_ARE_EQUAL(reg, &ia32_gp_regs[REG_GP_UKNWN]) || \
+ REGS_ARE_EQUAL(reg, &ia32_xmm_regs[REG_XMM_UKNWN]) || \
+ REGS_ARE_EQUAL(reg, &ia32_vfp_regs[REG_VFP_UKNWN]);
+}
+
/**
* returns true if a node has x87 registers
*/
-static int has_x87_register(const ir_node *n) {
+static INLINE int has_x87_register(const ir_node *n) {
return is_irn_machine_user(n, 0);
}
return env;
}
-static char *ia32_get_reg_name_for_mode(ia32_emit_env_t *env, ir_mode *mode, const arch_register_t *reg) {
+static const char *ia32_get_reg_name_for_mode(ia32_emit_env_t *env, ir_mode *mode, const arch_register_t *reg) {
switch(get_mode_size_bits(mode)) {
case 8:
return ia32_get_mapped_reg_name(env->isa->regs_8bit, reg);
is_ia32_Store8Bit(n) || \
is_ia32_CondJmp(n) || \
is_ia32_xCondJmp(n) || \
+ is_ia32_CmpSet(n) || \
+ is_ia32_xCmpSet(n) || \
is_ia32_SwitchJmp(n)))
if (! buf) {
switch(get_ia32_op_type(n)) {
case ia32_Normal:
- if (is_ia32_ImmConst(n) || is_ia32_ImmSymConst(n)) {
+ if (is_ia32_ImmConst(n)) {
lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%3S, %s", n, get_ia32_cnst(n));
}
+ else if (is_ia32_ImmSymConst(n)) {
+ lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%3S, OFFSET FLAT:%s", n, get_ia32_cnst(n));
+ }
else {
const arch_register_t *in1 = get_in_reg(n, 2);
const arch_register_t *in2 = get_in_reg(n, 3);
get_ia32_cnst(n)); /* tell the assembler to store it's address. */
}
else {
- const arch_register_t *in1 = get_in_reg(n, 2);
- ir_mode *mode = get_ia32_res_mode(n);
- const char *in_name;
+ const arch_register_t *in1 = get_in_reg(n, get_irn_arity(n) == 5 ? 3 : 2);
+ ir_mode *mode = get_ia32_res_mode(n);
+ const char *in_name;
mode = mode ? mode : get_ia32_ls_mode(n);
in_name = ia32_get_reg_name_for_mode(env, mode, in1);
assert(0 && "unsupported op type");
}
-#undef PRODUCES_RESULT
-
return buf;
}
lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%C", n);
}
else {
- lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D", n);
+ if (is_ia32_MulS(n) || is_ia32_Mulh(n)) {
+ /* MulS and Mulh implicitly multiply by EAX */
+ lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%4S", n);
+ }
+ else
+ lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%1D", n);
}
break;
case ia32_AddrModeD:
snprintf(buf, SNPRINTF_BUF_LEN, "%s", ia32_emit_am(n, env));
break;
+ case ia32_AddrModeS:
+ /*
+ Mulh is emitted via emit_unop
+ imul [MEM] means EDX:EAX <- EAX * [MEM]
+ */
+ assert((is_ia32_Mulh(n) || is_ia32_MulS(n)) && "Only MulS and Mulh can have AM source as unop");
+ lc_esnprintf(ia32_get_arg_env(), buf, SNPRINTF_BUF_LEN, "%s", ia32_emit_am(n, env));
+ break;
default:
assert(0 && "unsupported op type");
}
int had_output = 0;
char *s;
const char *p;
- int size;
static struct obstack *obst = NULL;
ir_mode *mode = get_ia32_ls_mode(n);
/* obstack_free with NULL results in an uninitialized obstack */
obstack_init(obst);
- p = pointer_size(mode, has_x87_register(n));
+ p = pointer_size(mode, has_x87_register(n) || is_ia32_GetST0(n) || is_ia32_SetST0(n));
if (p)
obstack_printf(obst, "%s ", p);
if (had_output)
obstack_printf(obst, "] ");
- size = obstack_object_size(obst);
- s = obstack_finish(obst);
- s[size - 1] = '\0';
+ obstack_1grow(obst, '\0');
+ s = obstack_finish(obst);
return s;
}
{ "ne", pn_Cmp_Lg }, /* != */
{ "ordered", pn_Cmp_Leg }, /* Floating point: ordered */
{ "unordered", pn_Cmp_Uo }, /* FLoting point: unordered */
- { "unordered or ==", pn_Cmp_Ue }, /* Floating point: unordered or == */
- { "unordered or <", pn_Cmp_Ul }, /* Floating point: unordered or < */
- { "unordered or <=", pn_Cmp_Ule }, /* Floating point: unordered or <= */
- { "unordered or >", pn_Cmp_Ug }, /* Floating point: unordered or > */
- { "unordered or >=", pn_Cmp_Uge }, /* Floating point: unordered or >= */
- { "unordered or !=", pn_Cmp_Ne }, /* Floating point: unordered or != */
+ { "e", pn_Cmp_Ue }, /* Floating point: unordered or == */
+ { "b", pn_Cmp_Ul }, /* Floating point: unordered or < */
+ { "be", pn_Cmp_Ule }, /* Floating point: unordered or <= */
+ { "a", pn_Cmp_Ug }, /* Floating point: unordered or > */
+ { "ae", pn_Cmp_Uge }, /* Floating point: unordered or >= */
+ { "ne", pn_Cmp_Ne }, /* Floating point: unordered or != */
{ NULL, pn_Cmp_True }, /* always true */
};
{ "ne", pn_Cmp_Lg }, /* != */
{ "ordered", pn_Cmp_Leg }, /* Floating point: ordered */
{ "unordered", pn_Cmp_Uo }, /* FLoting point: unordered */
- { "unordered or ==", pn_Cmp_Ue }, /* Floating point: unordered or == */
- { "unordered or <", pn_Cmp_Ul }, /* Floating point: unordered or < */
- { "unordered or <=", pn_Cmp_Ule }, /* Floating point: unordered or <= */
- { "unordered or >", pn_Cmp_Ug }, /* Floating point: unordered or > */
- { "unordered or >=", pn_Cmp_Uge }, /* Floating point: unordered or >= */
- { "unordered or !=", pn_Cmp_Ne }, /* Floating point: unordered or != */
+ { "e", pn_Cmp_Ue }, /* Floating point: unordered or == */
+ { "b", pn_Cmp_Ul }, /* Floating point: unordered or < */
+ { "be", pn_Cmp_Ule }, /* Floating point: unordered or <= */
+ { "a", pn_Cmp_Ug }, /* Floating point: unordered or > */
+ { "ae", pn_Cmp_Uge }, /* Floating point: unordered or >= */
+ { "ne", pn_Cmp_Ne }, /* Floating point: unordered or != */
{ NULL, pn_Cmp_True }, /* always true */
};
char buf[SNPRINTF_BUF_LEN];
char cmd_buf[SNPRINTF_BUF_LEN];
char cmnt_buf[SNPRINTF_BUF_LEN];
+ int is_unsigned;
/* get both Proj's */
proj1 = get_proj(irn, pn_Cond_true);
}
/* the first Proj must always be created */
+ is_unsigned = mode_is_float(mode) || ! mode_is_signed(mode);
if (get_Proj_proj(proj1) == pn_Cond_true) {
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "j%s %s",
- get_cmp_suffix(get_ia32_pncode(irn), !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
+ get_cmp_suffix(get_ia32_pncode(irn), is_unsigned),
get_cfop_target(proj1, buf));
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* cmp(a, b) == TRUE */");
}
else {
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "j%s %s",
- get_cmp_suffix(get_negated_pnc(get_ia32_pncode(irn), mode),
- !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
+ get_cmp_suffix(get_negated_pnc(get_ia32_pncode(irn), mode), is_unsigned),
get_cfop_target(proj1, buf));
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* cmp(a, b) == FALSE */");
}
finish_CondJmp(F, irn, get_ia32_res_mode(irn));
}
+/**
+ * Emits code for conditional SSE floating point jump with two variables.
+ */
+static void emit_ia32_xCondJmp(ir_node *irn, ia32_emit_env_t *env) {
+ FILE *F = env->out;
+ char cmd_buf[SNPRINTF_BUF_LEN];
+ char cmnt_buf[SNPRINTF_BUF_LEN];
+
+ lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "ucomis%M %s", irn, ia32_emit_binop(irn, env));
+ lc_esnprintf(ia32_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* %+F */", irn);
+ IA32_DO_EMIT(irn);
+ finish_CondJmp(F, irn, mode_F);
+
+}
+
/**
* Emits code for conditional x87 floating point jump with two variables.
*/
if (reverse)
set_ia32_pncode(irn, (long)get_negated_pnc(get_ia32_pncode(irn), mode_Is));
- snprintf(cmd_buf, SNPRINTF_BUF_LEN, "%s %s", instr, reg);
+ snprintf(cmd_buf, SNPRINTF_BUF_LEN, "%s %%%s", instr, reg);
lc_esnprintf(ia32_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* %+F */", irn);
IA32_DO_EMIT(irn);
-// lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "fnstsw %3D", irn);
lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "fnstsw %%ax", irn);
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* Store x87 FPU Control Word */");
IA32_DO_EMIT(irn);
finish_CondJmp(F, irn, mode_Is);
}
+static void CMov_emitter(ir_node *irn, ia32_emit_env_t *env) {
+ FILE *F = env->out;
+ const lc_arg_env_t *arg_env = ia32_get_arg_env();
+ ir_mode *mode = get_irn_mode(get_irn_n(irn, 0));
+ int is_unsigned = mode_is_float(mode) || ! mode_is_signed(mode);
+ const char *cmp_suffix = get_cmp_suffix(get_ia32_pncode(irn), is_unsigned);
+ int is_PsiCondCMov = is_ia32_PsiCondCMov(irn);
+
+ char cmd_buf[SNPRINTF_BUF_LEN];
+ char cmnt_buf[SNPRINTF_BUF_LEN];
+ const arch_register_t *in1, *in2, *out;
+
+ out = arch_get_irn_register(env->arch_env, irn);
+ in1 = arch_get_irn_register(env->arch_env, get_irn_n(irn, 2 - is_PsiCondCMov));
+ in2 = arch_get_irn_register(env->arch_env, get_irn_n(irn, 3 - is_PsiCondCMov));
+
+ /* we have to emit the cmp first, because the destination register */
+ /* could be one of the compare registers */
+ if (is_ia32_CmpCMov(irn)) {
+ lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "cmp %1S, %2S", irn, irn);
+ }
+ else if (is_ia32_xCmpCMov(irn)) {
+ lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "ucomis%M %1S, %2S", get_irn_n(irn, 0), irn, irn);
+ }
+ else if (is_PsiCondCMov) {
+ /* omit compare because flags are already set by And/Or */
+ snprintf(cmd_buf, SNPRINTF_BUF_LEN, " ");
+ }
+ else {
+ assert(0 && "unsupported CMov");
+ }
+ snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* Psi condition */" );
+ IA32_DO_EMIT(irn);
+
+ if (REGS_ARE_EQUAL(out, in2)) {
+ /* best case: default in == out -> do nothing */
+ }
+ else if (REGS_ARE_EQUAL(out, in1)) {
+ /* true in == out -> need complement compare and exchange true and default in */
+ ir_node *t = get_irn_n(irn, 2);
+ set_irn_n(irn, 2, get_irn_n(irn, 3));
+ set_irn_n(irn, 3, t);
+
+ cmp_suffix = get_cmp_suffix(get_inversed_pnc(get_ia32_pncode(irn)), is_unsigned);
+
+ }
+ else {
+ /* out is different from in: need copy default -> out */
+ lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "mov %1D, %4S", irn, irn);
+ lc_esnprintf(arg_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* copy default -> out */" );
+ IA32_DO_EMIT(irn);
+ }
+
+ lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "cmov%s %1D, %3S", cmp_suffix, irn, irn);
+ lc_esnprintf(arg_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* condition is true case */" );
+ IA32_DO_EMIT(irn);
+}
+
+static void emit_ia32_CmpCMov(ir_node *irn, ia32_emit_env_t *env) {
+ CMov_emitter(irn, env);
+}
+
+static void emit_ia32_PsiCondCMov(ir_node *irn, ia32_emit_env_t *env) {
+ CMov_emitter(irn, env);
+}
+
+static void emit_ia32_xCmpCMov(ir_node *irn, ia32_emit_env_t *env) {
+ CMov_emitter(irn, env);
+}
+
+static void Set_emitter(ir_node *irn, ir_mode *mode, ia32_emit_env_t *env) {
+ FILE *F = env->out;
+ const lc_arg_env_t *arg_env = ia32_get_arg_env();
+ int is_unsigned = mode_is_float(mode) || ! mode_is_signed(mode);
+ const char *cmp_suffix = get_cmp_suffix(get_ia32_pncode(irn), is_unsigned);
+ const char *reg8bit;
+
+ char cmd_buf[SNPRINTF_BUF_LEN];
+ char cmnt_buf[SNPRINTF_BUF_LEN];
+ const arch_register_t *out;
+
+ out = arch_get_irn_register(env->arch_env, irn);
+ reg8bit = ia32_get_mapped_reg_name(env->isa->regs_8bit, out);
+
+ if (is_ia32_CmpSet(irn)) {
+ lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "cmp %s", ia32_emit_binop(irn, env));
+ }
+ else if (is_ia32_xCmpSet(irn)) {
+ lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "ucomis%M %s", get_irn_n(irn, 2), ia32_emit_binop(irn, env));
+ }
+ else if (is_ia32_PsiCondSet(irn)) {
+ /* omit compare because flags are already set by And/Or */
+ snprintf(cmd_buf, SNPRINTF_BUF_LEN, " ");
+ }
+ else {
+ assert(0 && "unsupported Set");
+ }
+ snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* calculate Psi condition */" );
+ IA32_DO_EMIT(irn);
+
+ /* use mov to clear target because it doesn't affect the eflags */
+ snprintf(cmd_buf, SNPRINTF_BUF_LEN, "mov %%%s, 0", arch_register_get_name(out));
+ snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* clear target as set modifies only lower 8 bit */");
+ IA32_DO_EMIT(irn);
+
+ snprintf(cmd_buf, SNPRINTF_BUF_LEN, "set%s %%%s", cmp_suffix, reg8bit);
+ snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* set 1 iff true, 0 otherweise */" );
+ IA32_DO_EMIT(irn);
+}
+
+static void emit_ia32_CmpSet(ir_node *irn, ia32_emit_env_t *env) {
+ Set_emitter(irn, get_irn_mode(get_irn_n(irn, 2)), env);
+}
+
+static void emit_ia32_PsiCondSet(ir_node *irn, ia32_emit_env_t *env) {
+ Set_emitter(irn, get_irn_mode(get_irn_n(irn, 0)), env);
+}
+
+static void emit_ia32_xCmpSet(ir_node *irn, ia32_emit_env_t *env) {
+ Set_emitter(irn, get_irn_mode(get_irn_n(irn, 2)), env);
+}
+
+static void emit_ia32_xCmp(ir_node *irn, ia32_emit_env_t *env) {
+ FILE *F = env->out;
+ const lc_arg_env_t *arg_env = ia32_get_arg_env();
+ int sse_pnc = -1;
+ char cmd_buf[SNPRINTF_BUF_LEN];
+ char cmnt_buf[SNPRINTF_BUF_LEN];
+
+ switch (get_ia32_pncode(irn)) {
+ case pn_Cmp_Leg: /* odered */
+ sse_pnc = 7;
+ break;
+ case pn_Cmp_Uo: /* unordered */
+ sse_pnc = 3;
+ break;
+ case pn_Cmp_Ue: /* == */
+ sse_pnc = 0;
+ break;
+ case pn_Cmp_Ul: /* < */
+ sse_pnc = 1;
+ break;
+ case pn_Cmp_Ule: /* <= */
+ sse_pnc = 2;
+ break;
+ case pn_Cmp_Ug: /* > */
+ sse_pnc = 6;
+ break;
+ case pn_Cmp_Uge: /* >= */
+ sse_pnc = 5;
+ break;
+ case pn_Cmp_Ne: /* != */
+ sse_pnc = 4;
+ break;
+ }
+
+ assert(sse_pnc >= 0 && "unsupported floating point compare");
+
+ lc_esnprintf(arg_env, cmd_buf, SNPRINTF_BUF_LEN, "cmps%M %s, %d", irn, ia32_emit_binop(irn, env), sse_pnc);
+ lc_esnprintf(arg_env, cmnt_buf, SNPRINTF_BUF_LEN, "/* SSE compare with result in %1D */", irn);
+ IA32_DO_EMIT(irn);
+}
+
/*********************************************************
* _ _ _
* (_) | (_)
/* fill the table structure */
tbl.label = xmalloc(SNPRINTF_BUF_LEN);
- tbl.label = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, "JMPTBL_");
+ tbl.label = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, ".TBL_");
tbl.defProj = NULL;
tbl.num_branches = get_irn_n_edges(irn);
tbl.branches = xcalloc(tbl.num_branches, sizeof(tbl.branches[0]));
/**
* Emit movsb/w instructions to make mov count divideable by 4
*/
-static void emit_CopyB_prolog(FILE *F, int rem, int size) {
+static void emit_CopyB_prolog(FILE *F, const ir_node *irn, int rem) {
char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
- fprintf(F, "\t/* memcopy %d bytes*/\n", size);
+ ir_fprintf(F, "\t/* memcopy prolog %+F */\n", irn);
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "cld");
- snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* copy direction forward*/");
- IA32_DO_EMIT(NULL);
+ snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* copy direction forward */");
switch(rem) {
case 1:
+ IA32_DO_EMIT(NULL);
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "movsb");
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* memcopy remainder 1 */");
break;
case 2:
+ IA32_DO_EMIT(NULL);
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "movsw");
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* memcopy remainder 2 */");
break;
case 3:
+ IA32_DO_EMIT(NULL);
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "movsb");
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* memcopy remainder 3 */");
IA32_DO_EMIT(NULL);
* Emit rep movsd instruction for memcopy.
*/
static void emit_ia32_CopyB(const ir_node *irn, ia32_emit_env_t *emit_env) {
- FILE *F = emit_env->out;
- tarval *tv = get_ia32_Immop_tarval(irn);
- int rem = get_tarval_long(tv);
- ir_node *size_node = get_irn_n(irn, 2);
- int size;
+ FILE *F = emit_env->out;
+ tarval *tv = get_ia32_Immop_tarval(irn);
+ int rem = get_tarval_long(tv);
char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
- /* beware: size_node could be a be_Copy to fulfill constraints for ecx */
- size_node = be_is_Copy(size_node) ? be_get_Copy_op(size_node) : size_node;
- size = get_tarval_long(get_ia32_Immop_tarval(size_node));
-
- emit_CopyB_prolog(F, rem, size);
+ emit_CopyB_prolog(F, irn, rem);
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "rep movsd");
snprintf(cmnt_buf, SNPRINTF_BUF_LEN, "/* memcopy */");
FILE *F = emit_env->out;
char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
- emit_CopyB_prolog(F, size & 0x3, size);
+ emit_CopyB_prolog(F, irn, size & 0x3);
size >>= 2;
while (size--) {
assert(0 && "unsupported Conv_I2I");
}
- switch(get_ia32_op_type(irn)) {
+ switch(get_ia32_op_type(irn)) {
case ia32_Normal:
in_reg = get_in_reg(irn, 2);
out_reg = get_out_reg(irn, 0);
snprintf(cmd_buf, SNPRINTF_BUF_LEN, "call %s", get_entity_ld_name(ent));
}
else {
- lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "%1D", get_irn_n(irn, be_pos_Call_ptr));
+ lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "call %1D", get_irn_n(irn, be_pos_Call_ptr));
}
lc_esnprintf(ia32_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* %+F (be_Call) */", irn);
}
/**
- * Emits code for Copy.
+ * Emits code for Copy/CopyKeep.
*/
-static void emit_be_Copy(const ir_node *irn, ia32_emit_env_t *emit_env) {
- FILE *F = emit_env->out;
+static void Copy_emitter(const ir_node *irn, ir_node *op, ia32_emit_env_t *emit_env) {
+ FILE *F = emit_env->out;
const arch_env_t *aenv = emit_env->arch_env;
char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
- if (REGS_ARE_EQUAL(arch_get_irn_register(aenv, irn), arch_get_irn_register(aenv, be_get_Copy_op(irn))))
+ if (REGS_ARE_EQUAL(arch_get_irn_register(aenv, irn), arch_get_irn_register(aenv, op)) ||
+ be_is_unknown_reg(arch_get_irn_register(aenv, op)))
return;
if (mode_is_float(get_irn_mode(irn)))
IA32_DO_EMIT(irn);
}
+static void emit_be_Copy(const ir_node *irn, ia32_emit_env_t *emit_env) {
+ Copy_emitter(irn, be_get_Copy_op(irn), emit_env);
+}
+
+static void emit_be_CopyKeep(const ir_node *irn, ia32_emit_env_t *emit_env) {
+ Copy_emitter(irn, be_get_CopyKeep_op(irn), emit_env);
+}
+
/**
* Emits code for exchange.
*/
static void emit_be_Perm(const ir_node *irn, ia32_emit_env_t *emit_env) {
FILE *F = emit_env->out;
char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN];
+ const arch_register_t *in1, *in2;
+ const arch_register_class_t *cls1, *cls2;
+
+ in1 = arch_get_irn_register(emit_env->arch_env, get_irn_n(irn, 0));
+ in2 = arch_get_irn_register(emit_env->arch_env, get_irn_n(irn, 1));
+
+ cls1 = arch_register_get_class(in1);
+ cls2 = arch_register_get_class(in2);
+
+ assert(cls1 == cls2 && "Register class mismatch at Perm");
+
+ if (cls1 == &ia32_reg_classes[CLASS_ia32_gp]) {
+ lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "xchg %1S, %2S", irn, irn);
+ }
+ else if (cls1 == &ia32_reg_classes[CLASS_ia32_xmm]) {
+ lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN,
+ "pxor %1S, %2S\n\tpxor %2S, %1S\n\tpxor %1S, %2S", irn, irn, irn, irn, irn, irn);
+ }
+ else if (cls1 == &ia32_reg_classes[CLASS_ia32_vfp]) {
+ assert(0 && "Perm with vfp should not happen");
+ }
+ else if (cls1 == &ia32_reg_classes[CLASS_ia32_st]) {
+ assert(0 && "Perm with st(X) should not happen");
+ }
- lc_esnprintf(ia32_get_arg_env(), cmd_buf, SNPRINTF_BUF_LEN, "xchg %1S, %2S", irn, irn);
lc_esnprintf(ia32_get_arg_env(), cmnt_buf, SNPRINTF_BUF_LEN, "/* %+F(%1A, %2A) */", irn, irn, irn);
IA32_DO_EMIT(irn);
}
* Emits code for Constant loading.
*/
static void emit_ia32_Const(const ir_node *n, ia32_emit_env_t *env) {
- FILE *F = env->out;
- char cmd_buf[256], cmnt_buf[256];
- const lc_arg_env_t *arg_env = ia32_get_arg_env();
+ FILE *F = env->out;
+ char cmd_buf[256], cmnt_buf[256];
+ const lc_arg_env_t *arg_env = ia32_get_arg_env();
- if (get_ia32_Immop_tarval(n) == get_tarval_null(get_irn_mode(n))) {
+ if (get_ia32_Immop_tarval(n) == get_tarval_null(get_irn_mode(n))) {
const char *instr = "xor";
if (env->isa->opt_arch == arch_pentium_4) {
/* P4 prefers sub r, r, others xor r, r */
instr = "sub";
}
- lc_esnprintf(arg_env, cmd_buf, 256, "%s %1D, %1D ", instr, n, n);
- lc_esnprintf(arg_env, cmnt_buf, 256, "/* optimized mov 0 to register */");
- }
- else {
- if (get_ia32_op_type(n) == ia32_SymConst) {
- lc_esnprintf(arg_env, cmd_buf, 256, "mov %1D, OFFSET FLAT:%C ", n, n);
- lc_esnprintf(arg_env, cmnt_buf, 256, "/* Move address of SymConst into register */");
- }
+ lc_esnprintf(arg_env, cmd_buf, 256, "%s %1D, %1D ", instr, n, n);
+ lc_esnprintf(arg_env, cmnt_buf, 256, "/* optimized mov 0 to register */");
+ }
+ else {
+ if (get_ia32_op_type(n) == ia32_SymConst) {
+ lc_esnprintf(arg_env, cmd_buf, 256, "mov %1D, OFFSET FLAT:%C ", n, n);
+ lc_esnprintf(arg_env, cmnt_buf, 256, "/* Move address of SymConst into register */");
+ }
else {
- lc_esnprintf(arg_env, cmd_buf, 256, "mov %1D, %C ", n, n);
- lc_esnprintf(arg_env, cmnt_buf, 256, "/* Mov Const into register */");
+ lc_esnprintf(arg_env, cmd_buf, 256, "mov %1D, %C ", n, n);
+ lc_esnprintf(arg_env, cmnt_buf, 256, "/* Mov Const into register */");
}
- }
- lc_efprintf(arg_env, F, "\t%-35s %-60s /* %+F (%+G) */\n", cmd_buf, cmnt_buf, n, n);
+ }
+ lc_efprintf(arg_env, F, "\t%-35s %-60s /* %+F (%+G) */\n", cmd_buf, cmnt_buf, n, n);
}
static void emit_be_Return(const ir_node *n, ia32_emit_env_t *env) {
- FILE *F = env->out;
- const lc_arg_env_t *arg_env = ia32_get_arg_env();
+ FILE *F = env->out;
+ const lc_arg_env_t *arg_env = ia32_get_arg_env();
- lc_efprintf(arg_env, F, "\t%-35s %-60s /* %+F (%+G) */\n", "ret", "/* be_Return */", n, n);
+ lc_efprintf(arg_env, F, "\t%-35s %-60s /* %+F (%+G) */\n", "ret", "/* be_Return */", n, n);
}
IA32_EMIT(TestJmp);
IA32_EMIT(CJmp);
IA32_EMIT(CJmpAM);
+ IA32_EMIT(CmpCMov);
+ IA32_EMIT(PsiCondCMov);
+ IA32_EMIT(CmpSet);
+ IA32_EMIT(PsiCondSet);
IA32_EMIT(SwitchJmp);
IA32_EMIT(CopyB);
IA32_EMIT(CopyB_i);
IA32_EMIT(Conv_I2I);
IA32_EMIT(Conv_I2I8Bit);
IA32_EMIT(Const);
+ IA32_EMIT(xCmp);
+ IA32_EMIT(xCmpSet);
+ IA32_EMIT(xCmpCMov);
+ IA32_EMIT(xCondJmp);
IA32_EMIT2(fcomJmp, x87CondJmp);
IA32_EMIT2(fcompJmp, x87CondJmp);
IA32_EMIT2(fcomppJmp, x87CondJmp);
BE_EMIT(IncSP);
BE_EMIT(SetSP);
BE_EMIT(Copy);
+ BE_EMIT(CopyKeep);
BE_EMIT(Perm);
BE_EMIT(Return);