}
static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
- int pos = 0;
+ int pos = 0;
+ const ia32_irn_ops_t *ops = self;
+
+ DBG((ops->cg->mod, LEVEL_1, "ia32 assigned register %s to node %+F\n", reg->name, irn));
if (is_Proj(irn)) {
pos = ia32_translate_proj_pos(irn);
+/**
+ * This file implements the node emitter.
+ *
+ * $Id$
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "irop_t.h"
#include "irargs_t.h"
#include "irprog_t.h"
+#include "iredges_t.h"
#include "../besched.h"
#include "../benode_t.h"
const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
{
ir_node *X = arg->v_ptr;
- ir_mode *mode = is_ia32_Lea(X) ? get_irn_mode(X) : get_ia32_ls_mode(X);
+ ir_mode *mode = get_irn_mode(X);
+
+ if (mode == mode_T) {
+ mode = is_ia32_AddrModeS(X) || is_ia32_AddrModeD(X) ? get_ia32_ls_mode(X) : get_ia32_res_mode(X);
+ }
if (!X)
return lc_arg_append(app, occ, "(null)", 6);
* |_| |___/
**********************************/
+/**
+ * Emit movsb/w instructions to make mov count divideable by 4
+ */
static void emit_CopyB_prolog(FILE *F, int rem, int size) {
fprintf(F, "\t/* memcopy %d bytes*/\n", size);
fprintf(F, "\tcld\t\t\t\t/* copy direction forward*/\n");
}
}
+/**
+ * Emit rep movsd instruction for memcopy.
+ */
void emit_ia32_CopyB(const ir_node *irn, emit_env_t *emit_env) {
FILE *F = emit_env->out;
tarval *tv = get_ia32_Immop_tarval(irn);
fprintf(F, "\trep movsd\t\t\t\t/* memcopy */\n");
}
+/**
+ * Emits unrolled memcopy.
+ */
void emit_ia32_CopyB_i(const ir_node *irn, emit_env_t *emit_env) {
tarval *tv = get_ia32_Immop_tarval(irn);
int size = get_tarval_long(tv);
+/***************************
+ * _____
+ * / ____|
+ * | | ___ _ ____ __
+ * | | / _ \| '_ \ \ / /
+ * | |___| (_) | | | \ V /
+ * \_____\___/|_| |_|\_/
+ *
+ ***************************/
+
+/**
+ * Emit code for conversions (I, FP), (FP, I) and (FP, FP).
+ */
+static void emit_ia32_Conv(const ir_node *irn, emit_env_t *emit_env) {
+ FILE *F = emit_env->out;
+ const lc_arg_env_t *env = ia32_get_arg_env();
+ char *from, *to, buf[64];
+ ir_mode *src_mode, *tgt_mode;
+
+ src_mode = is_ia32_AddrModeS(irn) ? get_ia32_ls_mode(irn) : get_irn_mode(get_irn_n(irn, 2));
+ tgt_mode = get_ia32_res_mode(irn);
+
+ from = mode_is_float(src_mode) ? (get_mode_size_bits(src_mode) == 32 ? "ss" : "sd") : "si";
+ to = mode_is_float(tgt_mode) ? (get_mode_size_bits(tgt_mode) == 32 ? "ss" : "sd") : "si";
+
+ switch(get_ia32_op_type(irn)) {
+ case ia32_Normal:
+ lc_esnprintf(env, buf, sizeof(buf), "%1D, %3S", irn, irn);
+ break;
+ case ia32_AddrModeS:
+ lc_esnprintf(env, buf, sizeof(buf), "%1D, %s", irn, ia32_emit_am(irn));
+ break;
+ default:
+ assert(0 && "unsupported op type for Conv");
+ }
+
+ lc_efprintf(env, F, "\tcvt%s2%s %s\t\t\t/* %+F(%+F, %+F) */\n", from, to, buf, irn, src_mode, tgt_mode);
+}
+
+void emit_ia32_Conv_I2FP(const ir_node *irn, emit_env_t *emit_env) {
+ emit_ia32_Conv(irn, emit_env);
+}
+
+void emit_ia32_Conv_FP2I(const ir_node *irn, emit_env_t *emit_env) {
+ emit_ia32_Conv(irn, emit_env);
+}
+
+void emit_ia32_Conv_FP2FP(const ir_node *irn, emit_env_t *emit_env) {
+ emit_ia32_Conv(irn, emit_env);
+}
+
+
+
/*******************************************
* _ _
* | | | |
*
*******************************************/
+/**
+ * Emits a backend call
+ */
void emit_be_Call(const ir_node *irn, emit_env_t *emit_env) {
FILE *F = emit_env->out;
entity *ent = be_Call_get_entity(irn);
ir_fprintf(F, "\t\t\t/* %+F (be_Call) */\n", irn);
}
+/**
+ * Emits code to increase stack pointer.
+ */
void emit_be_IncSP(const ir_node *irn, emit_env_t *emit_env) {
FILE *F = emit_env->out;
unsigned offs = be_get_IncSP_offset(irn);
}
}
+/**
+ * Emits code to set stack pointer.
+ */
void emit_be_SetSP(const ir_node *irn, emit_env_t *emit_env) {
FILE *F = emit_env->out;
lc_efprintf(ia32_get_arg_env(), F, "\tmov %1D, %3S\t\t\t/* restore SP */\n", irn, irn);
}
+/**
+ * Emits code for Copy.
+ */
void emit_be_Copy(const ir_node *irn, emit_env_t *emit_env) {
FILE *F = emit_env->out;
lc_efprintf(ia32_get_arg_env(), F, "\tmov %1D, %1S\t\t\t/* %+F */\n", irn, irn, irn);
}
+/**
+ * Emits code for exchange.
+ */
void emit_be_Perm(const ir_node *irn, emit_env_t *emit_env) {
FILE *F = emit_env->out;
IA32_EMIT(SwitchJmp);
IA32_EMIT(CopyB);
IA32_EMIT(CopyB_i);
+ IA32_EMIT(Conv_I2FP);
+ IA32_EMIT(Conv_FP2I);
+ IA32_EMIT(Conv_FP2FP);
/* benode emitter */
BE_EMIT(Call);
ir_node *pred = get_Proj_pred(proj);
long nr = get_Proj_proj(proj);
- if (is_ia32_Load(pred)) {
+ if (is_ia32_Ld(pred)) {
if (nr == pn_Load_res)
return 0;
assert(0 && "unsupported Proj(Load) number");
}
- else if (is_ia32_Store(pred)) {
+ else if (is_ia32_St(pred)) {
return 0;
}
else if (is_ia32_CondJmp(pred)) {
attr->ls_mode = mode;
}
+/**
+ * Gets the mode of the result.
+ */
+ir_mode *get_ia32_res_mode(const ir_node *node) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ return attr->res_mode;
+}
+
+/**
+ * Sets the mode of the result.
+ */
+void set_ia32_res_mode(ir_node *node, ir_mode *mode) {
+ ia32_attr_t *attr = get_ia32_attr(node);
+ attr->res_mode = mode;
+}
+
/**
* Gets the frame entity assigned to this node;
*/
/* default compare operation to compare immediate ops */
int ia32_compare_immop_attr(ia32_attr_t *a, ia32_attr_t *b) {
if (a->data.tp == b->data.tp) {
- if (! a->cnst || ! b->cnst)
+ if (! (a->cnst && b->cnst))
return 1;
return strcmp(a->cnst, b->cnst);
*/
void set_ia32_ls_mode(ir_node *node, ir_mode *mode);
+/**
+ * Gets the mode of the result.
+ */
+ir_mode *get_ia32_res_mode(const ir_node *node);
+
+/**
+ * Sets the mode of the result.
+ */
+void set_ia32_res_mode(ir_node *node, ir_mode *mode);
+
/**
* Gets the frame entity assigned to this node;
*/
char *cnst; /**< points to the string representation of the constant value (either tv or sc) */
ir_mode *ls_mode; /**< the mode of the stored/loaded value */
+ ir_mode *res_mode; /**< the mode of the result */
entity *frame_ent; /**< the frame entity attached to this node */
# Conversions
-"Conv_I2I" => {
- "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3", "none" ] },
- "comment" => "construct Conv Int -> Int"
-},
-
"Conv_I2FP" => {
"reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "fp", "none" ] },
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"comment" => "construct Conv Int -> Floating Point"
},
"Conv_FP2I" => {
"reg_req" => { "in" => [ "gp", "gp", "fp", "none" ], "out" => [ "gp", "none" ] },
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
"comment" => "construct Conv Floating Point -> Int"
},
"Conv_FP2FP" => {
- "reg_req" => { "in" => [ "gp", "gp", "fp", "none" ], "out" => [ "in_r3", "none" ] },
- "comment" => "construct Conv Floating Point -> Floating Point"
+ "reg_req" => { "in" => [ "gp", "gp", "fp", "none" ], "out" => [ "fp", "none" ] },
+ "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n",
+ "comment" => "construct Conv Floating Point -> Floating Point",
},
); # end of %nodes
set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(new_op, mode);
+
if (is_op_commutative(get_irn_op(env->irn))) {
set_ia32_commutative(new_op);
}
set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(new_op, mode);
+
return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
}
set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(new_op, mode);
+
return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
}
set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(new_op, mode);
+
return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
}
else {
new_op = new_rd_ia32_Max(env->dbg, env->irg, env->block, op1, op2, env->mode);
set_ia32_am_support(new_op, ia32_am_None);
+#ifndef NDEBUG
+ set_ia32_orig_node(new_op, get_old_node_name(env));
+#endif /* NDEBUG */
}
return new_op;
set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(new_op, mode);
+
return new_rd_Proj(dbg, irg, block, new_op, mode, 0);
}
set_ia32_Immop_tarval(edx_node, get_tarval_null(mode_Iu));
}
- res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode);
+ res = new_rd_ia32_DivMod(dbg, irg, block, dividend, divisor, edx_node, mem, mode_T);
set_ia32_flavour(res, dm_flav);
set_ia32_n_res(res, 2);
set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(res, mode_Is);
+
return res;
}
set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(new_op, env->mode);
+
new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0);
}
else {
set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(res, mode);
+
res = new_rd_Proj(dbg, irg, block, res, mode, 0);
}
else {
#ifndef NDEBUG
set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(res, mode);
p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX);
p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX);
#ifndef NDEBUG
set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(res, mode);
res = new_rd_Proj(dbg, irg, block, res, mode, 0);
#ifndef NDEBUG
set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(res, mode);
res = new_rd_Proj(dbg, irg, block, res, mode, 0);
}
}
-#if 0
-/**
- * Checks of we can omit the Int -> Int Conv
- */
-static int ignore_int_conv(ir_mode *src_mode, ir_mode *tgt_mode) {
- int ignore = 0;
- int src_sign = mode_is_signed(src_mode);
- int tgt_sign = mode_is_signed(tgt_mode);
- int src_bits = get_mode_size_bits(src_mode);
- int tgt_bits = get_mode_size_bits(tgt_mode);
-
- /* ignore Convs small -> big if same signedness */
- ignore = (src_sign == tgt_sign) && (src_bits < tgt_bits) ? 1 : ignore;
-
- /* ignore Bool -> Int Conv */
- ignore = (src_mode == mode_b) ? 1 : ignore;
-
- /* ignore Int -> Int Convs if same bitsize */
- ignore = (src_bits == tgt_bits) ? 1 : ignore;
-
- return ignore;
-}
-#endif /* if 0 */
/**
* Transforms a Conv node.
#ifndef NDEBUG
set_ia32_orig_node(new_op, get_old_node_name(env));
#endif /* NDEBUG */
+ set_ia32_res_mode(new_op, tgt_mode);
+
+ set_ia32_am_support(new_op, ia32_am_Source);
new_op = new_rd_Proj(dbg, irg, block, new_op, tgt_mode, 0);
}