Commit 60a4bc30 authored by Matthias Braun's avatar Matthias Braun
Browse files

amd64: fix load/store of non-64bit modes

parent 53d7886c
......@@ -82,24 +82,73 @@ static void amd64_emit_mode_suffix(const ir_mode *mode)
be_emit_char(c);
}
static void emit_8bit_register(const arch_register_t *reg)
static const char *get_8bit_name(const arch_register_t *reg)
{
be_emit_char('%');
be_emit_char(reg->name[1]);
be_emit_char('l');
switch (reg->index) {
case REG_GP_RAX: return "al";
case REG_GP_RBX: return "bl";
case REG_GP_RCX: return "cl";
case REG_GP_RDX: return "dl";
case REG_GP_RSP: return "spl";
case REG_GP_RBP: return "bpl";
case REG_GP_RSI: return "sil";
case REG_GP_RDI: return "dil";
case REG_GP_R8: return "r8b";
case REG_GP_R9: return "r9b";
case REG_GP_R10: return "r10b";
case REG_GP_R11: return "r11b";
case REG_GP_R12: return "r12b";
case REG_GP_R13: return "r13b";
case REG_GP_R14: return "r14b";
case REG_GP_R15: return "r15b";
}
panic("unexpected register number");
}
static void emit_16bit_register(const arch_register_t *reg)
static const char *get_16bit_name(const arch_register_t *reg)
{
be_emit_char('%');
be_emit_string(reg->name + 1);
switch (reg->index) {
case REG_GP_RAX: return "ax";
case REG_GP_RBX: return "bx";
case REG_GP_RCX: return "cx";
case REG_GP_RDX: return "dx";
case REG_GP_RSP: return "sp";
case REG_GP_RBP: return "bp";
case REG_GP_RSI: return "si";
case REG_GP_RDI: return "di";
case REG_GP_R8: return "r8w";
case REG_GP_R9: return "r9w";
case REG_GP_R10: return "r10w";
case REG_GP_R11: return "r11w";
case REG_GP_R12: return "r12w";
case REG_GP_R13: return "r13w";
case REG_GP_R14: return "r14w";
case REG_GP_R15: return "r15w";
}
panic("unexpected register number");
}
static void emit_32bit_register(const arch_register_t *reg)
static const char *get_32bit_name(const arch_register_t *reg)
{
be_emit_char('%');
be_emit_char('e');
be_emit_string(reg->name + 1);
switch (reg->index) {
case REG_GP_RAX: return "eax";
case REG_GP_RBX: return "ebx";
case REG_GP_RCX: return "ecx";
case REG_GP_RDX: return "edx";
case REG_GP_RSP: return "esp";
case REG_GP_RBP: return "ebp";
case REG_GP_RSI: return "esi";
case REG_GP_RDI: return "edi";
case REG_GP_R8: return "r8d";
case REG_GP_R9: return "r9d";
case REG_GP_R10: return "r10d";
case REG_GP_R11: return "r11d";
case REG_GP_R12: return "r12d";
case REG_GP_R13: return "r13d";
case REG_GP_R14: return "r14d";
case REG_GP_R15: return "r15d";
}
panic("unexpected register number");
}
static void emit_register(const arch_register_t *reg)
......@@ -110,24 +159,33 @@ static void emit_register(const arch_register_t *reg)
static void emit_register_mode(const arch_register_t *reg, const ir_mode *mode)
{
const char *name;
switch (get_mode_size_bits(mode)) {
case 8: emit_8bit_register(reg); return;
case 16: emit_16bit_register(reg); return;
case 32: emit_32bit_register(reg); return;
case 64: emit_register(reg); return;
case 8: name = get_8bit_name(reg); break;
case 16: name = get_16bit_name(reg); break;
case 32: name = get_32bit_name(reg); break;
case 64: name = reg->name; break;
default:
panic("invalid mode");
}
panic("invalid mode");
be_emit_char('%');
be_emit_string(name);
}
static void emit_register_insn_mode(const arch_register_t *reg,
amd64_insn_mode_t mode)
{
const char *name;
switch (mode) {
case INSN_MODE_8: emit_8bit_register(reg); return;
case INSN_MODE_16: emit_16bit_register(reg); return;
case INSN_MODE_32: emit_32bit_register(reg); return;
case INSN_MODE_64: emit_register(reg); return;
case INSN_MODE_8: name = get_8bit_name(reg); break;
case INSN_MODE_16: name = get_16bit_name(reg); break;
case INSN_MODE_32: name = get_32bit_name(reg); break;
case INSN_MODE_64: name = reg->name; break;
default:
panic("invalid mode");
}
be_emit_char('%');
be_emit_string(name);
}
typedef enum amd64_emit_mod_t {
......@@ -242,7 +300,11 @@ emit_R:
case 'M': {
amd64_attr_t const *const attr = get_amd64_attr_const(node);
amd64_emit_insn_mode_suffix(attr->data.insn_mode);
if (mod & EMIT_RESPECT_LS) {
amd64_emit_mode_suffix(attr->ls_mode);
} else {
amd64_emit_insn_mode_suffix(attr->data.insn_mode);
}
break;
}
......@@ -412,6 +474,19 @@ static void emit_amd64_Jcc(const ir_node *irn)
}
}
static void emit_amd64_LoadZ(const ir_node *node)
{
const amd64_attr_t *attr = get_amd64_attr_const(node);
switch (attr->data.insn_mode) {
case INSN_MODE_8: amd64_emitf(node, "movzbq %O(%^S0), %^D0"); break;
case INSN_MODE_16: amd64_emitf(node, "movzwq %O(%^S0), %^D0"); break;
case INSN_MODE_32:
case INSN_MODE_64: amd64_emitf(node, "mov%M %O(%^S0), %D0"); break;
default:
panic("invalid insn mode");
}
}
/**
* Emits code for a call.
*/
......@@ -520,6 +595,7 @@ static void amd64_register_emitters(void)
be_set_emitter(op_amd64_FrameAddr, emit_amd64_FrameAddr);
be_set_emitter(op_amd64_Jcc, emit_amd64_Jcc);
be_set_emitter(op_amd64_Jmp, emit_amd64_Jmp);
be_set_emitter(op_amd64_LoadZ, emit_amd64_LoadZ);
be_set_emitter(op_amd64_SwitchJmp, emit_amd64_SwitchJmp);
be_set_emitter(op_amd64_SymConst, emit_amd64_SymConst);
be_set_emitter(op_be_Call, emit_be_Call);
......
......@@ -29,6 +29,7 @@
#include "besched.h"
#include "debug.h"
#include "error.h"
#include "amd64_nodes_attr.h"
#include "gen_amd64_new_nodes.h"
#include "irgwalk.h"
......
......@@ -13,6 +13,7 @@
#include <stdlib.h>
#include "error.h"
#include "irprog_t.h"
#include "irgraph_t.h"
#include "irnode_t.h"
......
......@@ -277,16 +277,30 @@ Jcc => {
mode => "mode_T",
},
Load => {
LoadZ => {
op_flags => [ "uses_memory" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "none" ],
out => [ "gp", "none" ] },
ins => [ "ptr", "mem" ],
outs => [ "res", "M" ],
attr => "ir_entity *entity",
attr => "amd64_insn_mode_t insn_mode, ir_entity *entity",
attr_type => "amd64_SymConst_attr_t",
emit => "mov %O(%S0), %D0"
init_attr => "attr->base.data.insn_mode = insn_mode;",
emit => "mov%M %O(%^S0), %D0"
},
LoadS => {
op_flags => [ "uses_memory" ],
state => "exc_pinned",
reg_req => { in => [ "gp", "none" ],
out => [ "gp", "none" ] },
ins => [ "ptr", "mem" ],
outs => [ "res", "M" ],
attr => "amd64_insn_mode_t insn_mode, ir_entity *entity",
attr_type => "amd64_SymConst_attr_t",
init_attr => "attr->base.data.insn_mode = insn_mode;",
emit => "movs%Mq %O(%^S0), %^D0"
},
FrameAddr => {
......@@ -305,10 +319,11 @@ Store => {
reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
ins => [ "ptr", "val", "mem" ],
outs => [ "M" ],
attr => "ir_entity *entity",
attr => "amd64_insn_mode_t insn_mode, ir_entity *entity",
attr_type => "amd64_SymConst_attr_t",
init_attr => "attr->base.data.insn_mode = insn_mode;",
mode => "mode_M",
emit => "mov %S1, %O(%S0)"
emit => "mov%M %S1, %O(%^S0)"
},
SwitchJmp => {
......
......@@ -269,6 +269,17 @@ static ir_node *gen_Conv(ir_node *node)
}
}
static amd64_insn_mode_t get_insn_mode_from_mode(const ir_mode *mode)
{
switch (get_mode_size_bits(mode)) {
case 8: return INSN_MODE_8;
case 16: return INSN_MODE_16;
case 32: return INSN_MODE_32;
case 64: return INSN_MODE_64;
}
panic("unexpected mode");
}
/**
* Transforms a Store.
*
......@@ -285,13 +296,14 @@ static ir_node *gen_Store(ir_node *node)
ir_node *new_val = be_transform_node(val);
ir_mode *mode = get_irn_mode(val);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *new_store = NULL;
ir_node *new_store;
if (mode_is_float(mode)) {
panic("Float not supported yet");
} else {
assert(mode_is_data(mode) && "unsupported mode for Store");
new_store = new_bd_amd64_Store(dbgi, block, new_ptr, new_val, new_mem, 0);
assert(mode_needs_gp_reg(mode) && "unsupported mode for Store");
amd64_insn_mode_t insn_mode = get_insn_mode_from_mode(mode);
new_store = new_bd_amd64_Store(dbgi, block, new_ptr, new_val, new_mem, insn_mode, NULL);
}
set_irn_pinned(new_store, get_irn_pinned(node));
return new_store;
......@@ -311,13 +323,18 @@ static ir_node *gen_Load(ir_node *node)
ir_node *new_mem = be_transform_node(mem);
ir_mode *mode = get_Load_mode(node);
dbg_info *dbgi = get_irn_dbg_info(node);
ir_node *new_load = NULL;
ir_node *new_load;
if (mode_is_float(mode)) {
panic("Float not supported yet");
} else {
assert(mode_is_data(mode) && "unsupported mode for Load");
new_load = new_bd_amd64_Load(dbgi, block, new_ptr, new_mem, 0);
assert(mode_needs_gp_reg(mode) && "unsupported mode for Load");
amd64_insn_mode_t insn_mode = get_insn_mode_from_mode(mode);
if (get_mode_size_bits(mode) < 64 && mode_is_signed(mode)) {
new_load = new_bd_amd64_LoadS(dbgi, block, new_ptr, new_mem, insn_mode, NULL);
} else {
new_load = new_bd_amd64_LoadZ(dbgi, block, new_ptr, new_mem, insn_mode, NULL);
}
}
set_irn_pinned(new_load, get_irn_pinned(node));
......@@ -336,12 +353,20 @@ static ir_node *gen_Proj_Load(ir_node *node)
/* renumber the proj */
switch (get_amd64_irn_opcode(new_load)) {
case iro_amd64_Load:
case iro_amd64_LoadS:
/* handle all gp loads equal: they have the same proj numbers. */
if (proj == pn_Load_res) {
return new_rd_Proj(dbgi, new_load, mode_Lu, pn_amd64_LoadS_res);
} else if (proj == pn_Load_M) {
return new_rd_Proj(dbgi, new_load, mode_M, pn_amd64_LoadS_M);
}
break;
case iro_amd64_LoadZ:
/* handle all gp loads equal: they have the same proj numbers. */
if (proj == pn_Load_res) {
return new_rd_Proj(dbgi, new_load, mode_Lu, pn_amd64_Load_res);
return new_rd_Proj(dbgi, new_load, mode_Lu, pn_amd64_LoadZ_res);
} else if (proj == pn_Load_M) {
return new_rd_Proj(dbgi, new_load, mode_M, pn_amd64_Load_M);
return new_rd_Proj(dbgi, new_load, mode_M, pn_amd64_LoadZ_M);
}
break;
default:
......
......@@ -52,7 +52,7 @@ static ir_entity *amd64_get_frame_entity(const ir_node *node)
const amd64_SymConst_attr_t *attr = get_amd64_SymConst_attr_const(node);
return attr->entity;
} else if (is_amd64_Load(node)) {
} else if (is_amd64_LoadS(node) || is_amd64_LoadZ(node)) {
const amd64_SymConst_attr_t *attr = get_amd64_SymConst_attr_const(node);
return attr->entity;
}
......@@ -76,7 +76,7 @@ static void amd64_set_frame_offset(ir_node *irn, int offset)
amd64_SymConst_attr_t *attr = get_amd64_SymConst_attr(irn);
attr->fp_offset += offset;
} else if (is_amd64_Load(irn)) {
} else if (is_amd64_LoadS(irn) || is_amd64_LoadZ(irn)) {
amd64_SymConst_attr_t *attr = get_amd64_SymConst_attr(irn);
attr->fp_offset += offset;
......@@ -128,16 +128,13 @@ static void transform_Reload(ir_node *node)
ir_node *mem = get_irn_n(node, n_be_Reload_mem);
ir_mode *mode = get_irn_mode(node);
ir_entity *entity = be_get_frame_entity(node);
const arch_register_t *reg;
ir_node *proj;
ir_node *load;
load = new_bd_amd64_Load(dbgi, block, ptr, mem, entity);
ir_node *load = new_bd_amd64_LoadZ(dbgi, block, ptr, mem, INSN_MODE_64, entity);
sched_replace(node, load);
proj = new_rd_Proj(dbgi, load, mode, pn_amd64_Load_res);
ir_node *proj = new_rd_Proj(dbgi, load, mode, pn_amd64_LoadZ_res);
reg = arch_get_irn_register(node);
const arch_register_t *reg = arch_get_irn_register(node);
arch_set_irn_register(proj, reg);
exchange(node, proj);
......@@ -151,11 +148,9 @@ static void transform_Spill(ir_node *node)
ir_node *ptr = get_irg_frame(irg);
ir_node *mem = get_irg_no_mem(irg);
ir_node *val = get_irn_n(node, n_be_Spill_val);
//ir_mode *mode = get_irn_mode(val);
ir_entity *entity = be_get_frame_entity(node);
ir_node *store;
store = new_bd_amd64_Store(dbgi, block, ptr, val, mem, entity);
ir_node *store = new_bd_amd64_Store(dbgi, block, ptr, val, mem, INSN_MODE_64, entity);
sched_replace(node, store);
exchange(node, store);
......
Supports Markdown
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