Commit 50361736 authored by Christian Würdig's avatar Christian Würdig
Browse files

added new attribute res_mode

added conversions
parent 8d0f57e3
......@@ -152,7 +152,10 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re
}
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
......@@ -13,6 +19,7 @@
#include "irop_t.h"
#include "irargs_t.h"
#include "irprog_t.h"
#include "iredges_t.h"
#include "../besched.h"
#include "../benode_t.h"
......@@ -322,7 +329,11 @@ static int ia32_get_mode_suffix(lc_appendable_t *app,
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);
......@@ -718,6 +729,9 @@ void emit_Proj(const ir_node *irn, emit_env_t *env) {
* |_| |___/
**********************************/
/**
* 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");
......@@ -736,6 +750,9 @@ static void emit_CopyB_prolog(FILE *F, int rem, int size) {
}
}
/**
* 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);
......@@ -747,6 +764,9 @@ void emit_ia32_CopyB(const ir_node *irn, emit_env_t *emit_env) {
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);
......@@ -762,6 +782,59 @@ void emit_ia32_CopyB_i(const ir_node *irn, emit_env_t *emit_env) {
/***************************
* _____
* / ____|
* | | ___ _ ____ __
* | | / _ \| '_ \ \ / /
* | |___| (_) | | | \ 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);
}
/*******************************************
* _ _
* | | | |
......@@ -772,6 +845,9 @@ void emit_ia32_CopyB_i(const ir_node *irn, emit_env_t *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);
......@@ -788,6 +864,9 @@ void emit_be_Call(const ir_node *irn, emit_env_t *emit_env) {
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);
......@@ -802,18 +881,27 @@ void emit_be_IncSP(const ir_node *irn, emit_env_t *emit_env) {
}
}
/**
* 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;
......@@ -851,6 +939,9 @@ static void ia32_register_emitters(void) {
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);
......
......@@ -201,12 +201,12 @@ long ia32_translate_proj_pos(const ir_node *proj) {
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)) {
......
......@@ -655,6 +655,22 @@ void set_ia32_ls_mode(ir_node *node, ir_mode *mode) {
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;
*/
......@@ -1045,7 +1061,7 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_regi
/* 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);
......
......@@ -154,6 +154,16 @@ ir_mode *get_ia32_ls_mode(const ir_node *node);
*/
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;
*/
......
......@@ -79,6 +79,7 @@ typedef struct _ia32_attr_t {
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 */
......
......@@ -551,24 +551,22 @@ $arch = "ia32";
# 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
......@@ -268,6 +268,8 @@ static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2,
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);
}
......@@ -345,6 +347,8 @@ static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node
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);
}
......@@ -383,6 +387,8 @@ static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_
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);
}
......@@ -503,6 +509,8 @@ static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
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);
}
......@@ -648,6 +656,9 @@ static ir_node *gen_Max(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
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;
......@@ -795,6 +806,8 @@ static ir_node *gen_Sub(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) {
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);
}
......@@ -847,7 +860,7 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir
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);
......@@ -873,6 +886,8 @@ static ir_node *generate_DivMod(ia32_transform_env_t *env, ir_node *dividend, ir
set_ia32_orig_node(res, get_old_node_name(env));
#endif /* NDEBUG */
set_ia32_res_mode(res, mode_Is);
return res;
}
......@@ -1075,6 +1090,8 @@ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) {
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 {
......@@ -1139,6 +1156,8 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
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 {
......@@ -1146,6 +1165,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
#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);
......@@ -1154,6 +1174,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
#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);
......@@ -1161,6 +1182,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) {
#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);
}
......@@ -1374,29 +1396,6 @@ static ir_node *gen_Mux(ia32_transform_env_t *env) {
}
#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.
......@@ -1452,6 +1451,9 @@ static ir_node *gen_Conv(ia32_transform_env_t *env, ir_node *op) {
#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);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment