Commit 5d7e28e8 authored by Tobias Rapp's avatar Tobias Rapp
Browse files

amd64: Changed SSE op naming, added Load and general bug fixing

parent 6f0cb0fb
......@@ -161,10 +161,10 @@ static void emit_register_insn_mode(const arch_register_t *reg,
be_emit_string(name);
}
static void emit_register_mode(const arch_register_t *reg, ir_mode *mode,
static void emit_register_mode(const arch_register_t *reg,
amd64_insn_mode_t insn_mode)
{
if (mode_is_float(mode)) {
if (reg->reg_class == &amd64_reg_classes[CLASS_amd64_xmm]) {
emit_register(reg);
} else {
emit_register_insn_mode(reg, insn_mode);
......@@ -265,7 +265,6 @@ static void amd64_emit_addr(const ir_node *const node,
static void amd64_emit_am(const ir_node *const node, bool indirect_star)
{
const amd64_addr_attr_t *const attr = get_amd64_addr_attr_const(node);
ir_mode *mode = get_irn_mode(node);
switch ((amd64_op_mode_t)attr->base.op_mode) {
case AMD64_OP_REG_IMM: {
......@@ -275,7 +274,7 @@ static void amd64_emit_am(const ir_node *const node, bool indirect_star)
amd64_emit_immediate32(&binop_attr->u.immediate);
be_emit_cstring(", ");
const arch_register_t *reg = arch_get_irn_register_in(node, 0);
emit_register_mode(reg, mode, binop_attr->base.insn_mode);
emit_register_mode(reg, binop_attr->base.insn_mode);
return;
}
case AMD64_OP_REG_REG: {
......@@ -283,9 +282,9 @@ static void amd64_emit_am(const ir_node *const node, bool indirect_star)
= (const amd64_addr_attr_t*)attr;
const arch_register_t *reg0 = arch_get_irn_register_in(node, 0);
const arch_register_t *reg1 = arch_get_irn_register_in(node, 1);
emit_register_mode(reg1, mode, addr_attr->insn_mode);
emit_register_mode(reg1, addr_attr->insn_mode);
be_emit_cstring(", ");
emit_register_mode(reg0, mode, addr_attr->insn_mode);
emit_register_mode(reg0, addr_attr->insn_mode);
return;
}
case AMD64_OP_ADDR_REG: {
......@@ -295,7 +294,7 @@ static void amd64_emit_am(const ir_node *const node, bool indirect_star)
be_emit_cstring(", ");
const arch_register_t *reg
= arch_get_irn_register_in(node, binop_attr->u.reg_input);
emit_register_mode(reg, mode, binop_attr->base.insn_mode);
emit_register_mode(reg, binop_attr->base.insn_mode);
return;
}
case AMD64_OP_ADDR_IMM:
......@@ -309,7 +308,7 @@ static void amd64_emit_am(const ir_node *const node, bool indirect_star)
/* FALLTHROUGH */
case AMD64_OP_REG: {
const arch_register_t *reg = arch_get_irn_register_in(node, 0);
emit_register_mode(reg, mode, attr->insn_mode);
emit_register_mode(reg, attr->insn_mode);
return;
}
case AMD64_OP_UNOP_IMM32:
......@@ -323,7 +322,7 @@ static void amd64_emit_am(const ir_node *const node, bool indirect_star)
case AMD64_OP_RAX_REG: {
const arch_register_t *reg = arch_get_irn_register_in(node, 1);
emit_register_mode(reg, mode, attr->insn_mode);
emit_register_mode(reg, attr->insn_mode);
return;
}
......@@ -356,21 +355,20 @@ static amd64_insn_mode_t get_amd64_insn_mode(const ir_node *node)
static void emit_shiftop(const ir_node *const node)
{
amd64_shift_attr_t const *const attr = get_amd64_shift_attr_const(node);
ir_mode *mode = get_irn_mode(node);
switch (attr->base.op_mode) {
case AMD64_OP_SHIFT_IMM: {
be_emit_irprintf("$0x%X, ", attr->immediate);
const arch_register_t *reg = arch_get_irn_register_in(node, 0);
emit_register_mode(reg, mode, attr->insn_mode);
emit_register_mode(reg, attr->insn_mode);
return;
}
case AMD64_OP_SHIFT_REG: {
const arch_register_t *reg0 = arch_get_irn_register_in(node, 0);
const arch_register_t *reg1 = arch_get_irn_register_in(node, 1);
emit_register_mode(reg1, mode, INSN_MODE_8);
emit_register_mode(reg1, INSN_MODE_8);
be_emit_cstring(", ");
emit_register_mode(reg0, mode, attr->insn_mode);
emit_register_mode(reg0, attr->insn_mode);
return;
}
default:
......@@ -499,22 +497,15 @@ emit_R:
if (mod & EMIT_IGNORE_MODE) {
emit_register(reg);
} else if (mod & EMIT_FORCE_32) {
ir_mode *mode = get_irn_mode(node);
emit_register_mode(reg, mode, INSN_MODE_32);
emit_register_mode(reg, INSN_MODE_32);
} else if (mod & EMIT_CONV_DEST) {
ir_mode *mode = get_irn_mode(node);
amd64_insn_mode_t src_mode = get_amd64_insn_mode(node);
amd64_insn_mode_t dest_mode = src_mode == INSN_MODE_64
? INSN_MODE_64 : INSN_MODE_32;
emit_register_mode(reg, mode, dest_mode);
emit_register_mode(reg, dest_mode);
} else {
ir_mode *mode = get_irn_mode(node);
if (mode_is_float(mode)) {
emit_register(reg);
} else {
amd64_insn_mode_t insn_mode = get_amd64_insn_mode(node);
emit_register_mode(reg, mode, insn_mode);
}
amd64_insn_mode_t insn_mode = get_amd64_insn_mode(node);
emit_register_mode(reg, insn_mode);
}
break;
}
......
......@@ -53,7 +53,7 @@ static bool try_swap_inputs(ir_node *node)
{
/* commutative operation, just switch the inputs */
if (is_amd64_Add(node) || is_amd64_And(node) || is_amd64_Or(node)
|| is_amd64_Xor(node) || is_amd64_IMul(node)) {
|| is_amd64_Xor(node) || is_amd64_IMul(node) || is_amd64_xAdds(node)) {
/* TODO: support Cmp input swapping */
ir_node *in0 = get_irn_n(node, 0);
ir_node *in1 = get_irn_n(node, 1);
......
......@@ -49,7 +49,7 @@ static inline bool amd64_has_addr_attr(const ir_node *node)
|| attr->op_mode == AMD64_OP_RAX_ADDR
|| attr->op_mode == AMD64_OP_RAX_REG)
&& (get_irn_op(node) != op_amd64_Xor0)
&& (get_irn_op(node) != op_amd64_Xorp0);
&& (get_irn_op(node) != op_amd64_xXorp0);
}
static inline amd64_addr_attr_t *get_amd64_addr_attr(ir_node *node)
......
......@@ -482,19 +482,29 @@ Return => {
# SSE
Adds => {
xAdds => {
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { out => [ "xmm", "none" ] },
outs => [ "res", "M" ],
reg_req => { out => [ "xmm", "none", "none" ] },
outs => [ "res", "none", "M" ],
arity => "variable",
attr_type => "amd64_binop_addr_attr_t",
attr => "const amd64_binop_addr_attr_t *attr_init",
emit => "adds%MX %AM",
mode => $mode_xmm,
# mode => $mode_xmm,
},
Stores => {
xMovs => {
state => "exc_pinned",
reg_req => { out => [ "xmm", "none", "none" ] },
outs => [ "res", "unused", "M" ],
arity => "variable",
attr_type => "amd64_addr_attr_t",
attr => "amd64_insn_mode_t insn_mode, amd64_op_mode_t op_mode, amd64_addr_t addr",
emit => "movs%MX %AM, %D0",
},
xStores => {
op_flags => [ "uses_memory" ],
state => "exc_pinned",
reg_req => { out => [ "none" ] },
......@@ -503,29 +513,28 @@ Stores => {
attr_type => "amd64_binop_addr_attr_t",
attr => "const amd64_binop_addr_attr_t *attr_init",
mode => "mode_M",
emit => "movs%MX %S0, %A",
emit => "movs%MX %^S0, %A",
},
Subs => {
xSubs => {
irn_flags => [ "rematerializable" ],
state => "exc_pinned",
reg_req => { out => [ "xmm", "none" ] },
outs => [ "res", "M" ],
reg_req => { out => [ "xmm", "none", "none" ] },
outs => [ "res", "none", "M" ],
arity => "variable",
attr_type => "amd64_binop_addr_attr_t",
attr => "const amd64_binop_addr_attr_t *attr_init",
emit => "subs%MX %S1, %D0",
mode => $mode_xmm,
},
Xorp0 => {
xXorp0 => {
op_flags => [ "constlike" ],
irn_flags => [ "rematerializable" ],
reg_req => { out => [ "xmm" ] },
outs => [ "res" ],
fixed => "amd64_op_mode_t op_mode = AMD64_OP_REG_REG;",
emit => "xorpd %D0, %D0",
emit => "xorpd %^D0, %^D0",
mode => $mode_xmm,
},
......
......@@ -167,6 +167,12 @@ static const arch_register_req_t *xmm_reg_mem_reqs[] = {
&arch_no_requirement,
};
static const arch_register_req_t *xmm_xmm_mem_reqs[] = {
&amd64_requirement_xmm,
&amd64_requirement_xmm,
&arch_no_requirement,
};
static const arch_register_req_t *reg_reg_reg_mem_reqs[] = {
&amd64_requirement_gp,
&amd64_requirement_gp,
......@@ -181,6 +187,13 @@ static const arch_register_req_t *xmm_reg_reg_mem_reqs[] = {
&arch_no_requirement,
};
static const arch_register_req_t *xmm_xmm_xmm_mem_reqs[] = {
&amd64_requirement_xmm,
&amd64_requirement_xmm,
&amd64_requirement_xmm,
&arch_no_requirement,
};
static const arch_register_req_t *reg_reg_flags_reqs[] = {
&amd64_requirement_gp,
&amd64_requirement_gp,
......@@ -318,7 +331,7 @@ static ir_node *gen_Const(ir_node *node)
if (!mode_needs_gp_reg(mode)) {
if (tarval_is_null(tv)) {
return new_bd_amd64_Xorp0(dbgi, block);
return new_bd_amd64_xXorp0(dbgi, block);
}
panic("amd64: float constant not supported yet");
......@@ -583,6 +596,7 @@ static void match_binop(amd64_args_t *args, ir_node *block,
memset(args, 0, sizeof(*args));
bool use_am;
bool use_xmm = mode_is_float(mode);
bool use_immediate = flags & match_immediate;
bool mode_neutral = flags & match_mode_neutral;
......@@ -604,6 +618,7 @@ static void match_binop(amd64_args_t *args, ir_node *block,
if (use_immediate
&& match_immediate_32(&args->attr.u.immediate, op2, false, mode_neutral)) {
assert(!use_xmm && "Can't (yet) match binop with xmm immediate");
/* fine, we found an immediate */
args->attr.base.base.op_mode = AMD64_OP_REG_IMM;
args->in[args->arity++] = be_transform_node(op1);
......@@ -618,11 +633,13 @@ static void match_binop(amd64_args_t *args, ir_node *block,
ir_node *ptr = get_Load_ptr(load);
perform_address_matching(ptr, &(args->arity), args->in, addr);
args->reqs = reg_mem_reqs;
args->reqs = use_xmm ? xmm_mem_reqs : reg_mem_reqs;
if (addr->base_input != NO_INPUT && addr->index_input != NO_INPUT) {
args->reqs = reg_reg_reg_mem_reqs;
args->reqs = use_xmm ? xmm_xmm_xmm_mem_reqs
: reg_reg_reg_mem_reqs;
} else if(addr->base_input != NO_INPUT || addr->index_input != NO_INPUT) {
args->reqs = reg_reg_mem_reqs;
args->reqs = use_xmm ? xmm_xmm_mem_reqs
: reg_reg_mem_reqs;
}
ir_node *new_mem = be_transform_node(get_Load_mem(load));
int mem_input = args->arity++;
......@@ -637,11 +654,7 @@ static void match_binop(amd64_args_t *args, ir_node *block,
args->in[args->arity++] = be_transform_node(op2);
args->attr.base.base.op_mode = AMD64_OP_REG_REG;
if (mode_is_float(mode)) {
args->reqs = xmm_xmm_reqs;
} else {
args->reqs = reg_reg_reqs;
}
args->reqs = use_xmm ? xmm_xmm_reqs : reg_reg_reqs;
}
}
......@@ -668,7 +681,7 @@ static ir_node *gen_binop_am(ir_node *node, ir_node *op1, ir_node *op2,
if (mode_is_float(mode)) {
arch_set_irn_register_req_out(new_node, 0,
&amd64_requirement_xmm_same_0);
return new_node;
return new_r_Proj(new_node, mode_D, pn_amd64_xAdds_res);
} else {
arch_set_irn_register_req_out(new_node, 0,
&amd64_requirement_gp_same_0);
......@@ -869,7 +882,7 @@ static ir_node *gen_Add(ir_node *const node)
ir_node *load, *op;
if (mode_is_float(mode)) {
return gen_binop_am(node, op1, op2, new_bd_amd64_Adds,
return gen_binop_am(node, op1, op2, new_bd_amd64_xAdds,
match_commutative | match_am);
}
......@@ -892,7 +905,7 @@ static ir_node *gen_Sub(ir_node *const node)
ir_mode *const mode = get_irn_mode(node);
if (mode_is_float(mode)) {
return gen_binop_am(node, op1, op2, new_bd_amd64_Subs, match_am);
return gen_binop_am(node, op1, op2, new_bd_amd64_xSubs, match_am);
} else {
/* do not match AM yet until we have a sub->neg+add rule
* in amd64_finish */
......@@ -1915,7 +1928,7 @@ static ir_node *gen_Store(ir_node *node)
ir_node *new_store;
if (mode_is_float(mode)) {
new_store = new_bd_amd64_Stores(dbgi, block, arity, in, &attr);
new_store = new_bd_amd64_xStores(dbgi, block, arity, in, &attr);
} else {
new_store = new_bd_amd64_Store(dbgi, block, arity, in, &attr);
}
......@@ -1976,11 +1989,10 @@ ir_node *amd64_new_reload(ir_node *value, ir_node *spill, ir_node *before)
static ir_node *gen_Load(ir_node *node)
{
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *block = be_transform_node(get_nodes_block(node));
ir_mode *mode = get_Load_mode(node);
if (mode_is_float(mode)) {
panic("Float not supported yet");
}
ir_node *ptr = get_Load_ptr(node);
......@@ -1991,29 +2003,34 @@ static ir_node *gen_Load(ir_node *node)
perform_address_matching(ptr, &arity, in, &addr);
bool use_xmm = mode_is_float(mode);
const arch_register_req_t **reqs = mem_reqs;
if (addr.base_input != NO_INPUT && addr.index_input != NO_INPUT) {
reqs = reg_reg_mem_reqs;
reqs = use_xmm ? xmm_xmm_mem_reqs : reg_reg_mem_reqs;
} else if(addr.base_input != NO_INPUT || addr.index_input != NO_INPUT) {
reqs = reg_mem_reqs;
reqs = use_xmm ? xmm_mem_reqs : reg_mem_reqs;
}
ir_node *mem = get_Load_mem(node);
ir_node *new_mem = be_transform_node(mem);
in[arity++] = new_mem;
in[arity++] = new_mem;
assert((size_t)arity <= ARRAY_SIZE(in));
assert(mode_needs_gp_reg(mode) && "unsupported mode for Load");
amd64_insn_mode_t insn_mode = get_insn_mode_from_mode(mode);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *new_load;
if (get_mode_size_bits(mode) < 64 && mode_is_signed(mode)) {
if (use_xmm) {
new_load = new_bd_amd64_xMovs(dbgi, block, arity, in,
insn_mode, AMD64_OP_ADDR, addr);
} else if (get_mode_size_bits(mode) < 64 && mode_is_signed(mode)) {
new_load = new_bd_amd64_Movs(dbgi, block, arity, in,
insn_mode, AMD64_OP_ADDR, addr);
} else {
new_load = new_bd_amd64_Mov(dbgi, block, arity, in,
insn_mode, AMD64_OP_ADDR, addr);
}
arch_set_irn_register_reqs_in(new_load, reqs);
set_irn_pinned(new_load, get_irn_pinned(node));
......@@ -2026,7 +2043,7 @@ static ir_node *gen_Unknown(ir_node *node)
ir_node *block = be_transform_node(get_nodes_block(node));
if (mode_is_float(get_irn_mode(node))) {
return new_bd_amd64_Xorp0(NULL, block);
return new_bd_amd64_xXorp0(NULL, block);
} else {
return new_bd_amd64_Xor0(NULL, block);
}
......@@ -2056,6 +2073,13 @@ static ir_node *gen_Proj_Load(ir_node *node)
/* renumber the proj */
switch (get_amd64_irn_opcode(new_load)) {
case iro_amd64_xMovs:
if (proj == pn_Load_res) {
return new_rd_Proj(dbgi, new_load, mode_D, pn_amd64_xMovs_res);
} else if (proj == pn_Load_M) {
return new_rd_Proj(dbgi, new_load, mode_M, pn_amd64_xMovs_M);
}
break;
case iro_amd64_Movs:
case iro_amd64_Mov:
assert((int)pn_amd64_Movs_res == (int)pn_amd64_Mov_res);
......
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