Commit 96ec0781 authored by Tobias Rapp's avatar Tobias Rapp
Browse files

amd64: Added SSE registers and first SSE node Xorp0

parent 59f25976
...@@ -34,11 +34,26 @@ static const arch_register_t* const param_regs[] = { ...@@ -34,11 +34,26 @@ static const arch_register_t* const param_regs[] = {
&amd64_registers[REG_R9], &amd64_registers[REG_R9],
}; };
static const arch_register_t* const float_param_regs[] = {
&amd64_registers[REG_XMM0],
&amd64_registers[REG_XMM1],
&amd64_registers[REG_XMM2],
&amd64_registers[REG_XMM3],
&amd64_registers[REG_XMM4],
&amd64_registers[REG_XMM5],
&amd64_registers[REG_XMM6],
&amd64_registers[REG_XMM7],
};
static const arch_register_t* const result_regs[] = { static const arch_register_t* const result_regs[] = {
&amd64_registers[REG_RAX], &amd64_registers[REG_RAX],
&amd64_registers[REG_RDX], &amd64_registers[REG_RDX],
}; };
static const arch_register_t* const float_result_regs[] = {
&amd64_registers[REG_XMM0],
};
static const unsigned caller_saves[] = { static const unsigned caller_saves[] = {
REG_RAX, REG_RAX,
REG_RCX, REG_RCX,
...@@ -49,6 +64,14 @@ static const unsigned caller_saves[] = { ...@@ -49,6 +64,14 @@ static const unsigned caller_saves[] = {
REG_R9, REG_R9,
REG_R10, REG_R10,
REG_R11, REG_R11,
REG_XMM0,
REG_XMM1,
REG_XMM2,
REG_XMM3,
REG_XMM4,
REG_XMM5,
REG_XMM6,
REG_XMM7,
}; };
static unsigned default_caller_saves[BITSET_SIZE_ELEMS(N_AMD64_REGISTERS)]; static unsigned default_caller_saves[BITSET_SIZE_ELEMS(N_AMD64_REGISTERS)];
...@@ -94,11 +117,14 @@ amd64_cconv_t *amd64_decide_calling_convention(ir_type *function_type, ...@@ -94,11 +117,14 @@ amd64_cconv_t *amd64_decide_calling_convention(ir_type *function_type,
rbitset_copy(callee_saves, default_callee_saves, N_AMD64_REGISTERS); rbitset_copy(callee_saves, default_callee_saves, N_AMD64_REGISTERS);
/* determine how parameters are passed */ /* determine how parameters are passed */
size_t n_params = get_method_n_params(function_type); size_t n_params = get_method_n_params(function_type);
size_t regnum = 0; size_t param_regnum = 0;
reg_or_stackslot_t *params = XMALLOCNZ(reg_or_stackslot_t, n_params); size_t float_param_regnum = 0;
reg_or_stackslot_t *params = XMALLOCNZ(reg_or_stackslot_t,
n_params);
size_t n_param_regs = ARRAY_SIZE(param_regs); size_t n_param_regs = ARRAY_SIZE(param_regs);
size_t n_float_param_regs = ARRAY_SIZE(float_param_regs);
unsigned stack_offset = 0; unsigned stack_offset = 0;
for (size_t i = 0; i < n_params; ++i) { for (size_t i = 0; i < n_params; ++i) {
ir_type *param_type = get_method_param_type(function_type,i); ir_type *param_type = get_method_param_type(function_type,i);
...@@ -111,12 +137,18 @@ amd64_cconv_t *amd64_decide_calling_convention(ir_type *function_type, ...@@ -111,12 +137,18 @@ amd64_cconv_t *amd64_decide_calling_convention(ir_type *function_type,
int bits = get_mode_size_bits(mode); int bits = get_mode_size_bits(mode);
reg_or_stackslot_t *param = &params[i]; reg_or_stackslot_t *param = &params[i];
if (regnum < n_param_regs) { if (mode_is_float(mode) && float_param_regnum < n_float_param_regs) {
const arch_register_t *reg = param_regs[regnum]; const arch_register_t *reg = float_param_regs[float_param_regnum];
param->reg = reg;
param->req = reg->single_req;
param->reg_offset = float_param_regnum;
++float_param_regnum;
} else if (param_regnum < n_param_regs) {
const arch_register_t *reg = param_regs[param_regnum];
param->reg = reg; param->reg = reg;
param->req = reg->single_req; param->req = reg->single_req;
param->reg_offset = regnum; param->reg_offset = param_regnum;
++regnum; ++param_regnum;
} else { } else {
param->type = param_type; param->type = param_type;
param->offset = stack_offset; param->offset = stack_offset;
...@@ -125,36 +157,48 @@ amd64_cconv_t *amd64_decide_calling_convention(ir_type *function_type, ...@@ -125,36 +157,48 @@ amd64_cconv_t *amd64_decide_calling_convention(ir_type *function_type,
stack_offset += MAX(bits / 8, AMD64_REGISTER_SIZE); stack_offset += MAX(bits / 8, AMD64_REGISTER_SIZE);
continue; continue;
} }
} }
unsigned n_param_regs_used = regnum;
unsigned n_param_regs_used = param_regnum + float_param_regnum;
/* determine how results are passed */ /* determine how results are passed */
size_t n_results = get_method_n_ress(function_type); size_t n_results = get_method_n_ress(function_type);
unsigned n_reg_results = 0; unsigned n_reg_results = 0;
reg_or_stackslot_t *results = XMALLOCNZ(reg_or_stackslot_t, n_results); reg_or_stackslot_t *results = XMALLOCNZ(reg_or_stackslot_t, n_results);
unsigned res_regnum = 0; unsigned res_regnum = 0;
unsigned res_float_regnum = 0;
size_t n_result_regs = ARRAY_SIZE(result_regs); size_t n_result_regs = ARRAY_SIZE(result_regs);
size_t n_float_result_regs = ARRAY_SIZE(float_result_regs);
for (size_t i = 0; i < n_results; ++i) { for (size_t i = 0; i < n_results; ++i) {
ir_type *result_type = get_method_res_type(function_type, i); ir_type *result_type = get_method_res_type(function_type, i);
ir_mode *result_mode = get_type_mode(result_type); ir_mode *result_mode = get_type_mode(result_type);
reg_or_stackslot_t *result = &results[i]; reg_or_stackslot_t *result = &results[i];
if (mode_is_float(result_mode)) { if (mode_is_float(result_mode)) {
panic("amd64: float return NIY"); if (res_float_regnum >= n_float_result_regs) {
panic("Too many floating points results");
} else {
const arch_register_t *reg = float_result_regs[res_float_regnum++];
result->req = reg->single_req;
result->reg_offset = i;
rbitset_clear(caller_saves, reg->global_index);
++n_reg_results;
}
} else { } else {
if (res_regnum >= n_result_regs) { if (res_regnum >= n_result_regs) {
panic("Too many results"); panic("Too many results");
} else { } else {
const arch_register_t *reg = result_regs[res_regnum++]; const arch_register_t *reg = result_regs[res_regnum++];
result->req = reg->single_req; result->req = reg->single_req;
result->reg_offset = i; result->reg_offset = i;
rbitset_clear(caller_saves, reg->global_index); rbitset_clear(caller_saves, reg->global_index);
++n_reg_results; ++n_reg_results;
} }
} }
} }
amd64_cconv_t *cconv = XMALLOCZ(amd64_cconv_t); amd64_cconv_t *cconv = XMALLOCZ(amd64_cconv_t);
cconv->parameters = params; cconv->parameters = params;
cconv->param_stack_size = stack_offset; cconv->param_stack_size = stack_offset;
cconv->n_param_regs = n_param_regs_used; cconv->n_param_regs = n_param_regs_used;
......
...@@ -58,6 +58,20 @@ static void amd64_emit_insn_mode_suffix(amd64_insn_mode_t mode) ...@@ -58,6 +58,20 @@ static void amd64_emit_insn_mode_suffix(amd64_insn_mode_t mode)
be_emit_char(c); be_emit_char(c);
} }
static void amd64_emit_xmm_mode_suffix(ir_mode *mode)
{
assert(mode_is_float(mode));
char c;
switch(get_mode_size_bits(mode)) {
case 32: c = 's'; break;
case 64: c = 'd'; break;
default:
panic("invalid floating point mode");
}
be_emit_char(c);
}
static const char *get_8bit_name(const arch_register_t *reg) static const char *get_8bit_name(const arch_register_t *reg)
{ {
switch (reg->index) { switch (reg->index) {
...@@ -480,30 +494,36 @@ emit_R: ...@@ -480,30 +494,36 @@ emit_R:
? INSN_MODE_64 : INSN_MODE_32; ? INSN_MODE_64 : INSN_MODE_32;
emit_register_insn_mode(reg, dest_mode); emit_register_insn_mode(reg, dest_mode);
} else { } else {
amd64_insn_mode_t insn_mode = get_amd64_insn_mode(node); ir_mode *mode = get_irn_mode(node);
emit_register_insn_mode(reg, insn_mode); if (mode_is_float(mode)) {
emit_register(reg);
} else {
amd64_insn_mode_t insn_mode = get_amd64_insn_mode(node);
emit_register_insn_mode(reg, insn_mode);
}
} }
break; break;
} }
case 'M': { case 'M': {
amd64_insn_mode_t insn_mode;
if (*fmt == 'S') { if (*fmt == 'S') {
++fmt; ++fmt;
const amd64_shift_attr_t *attr const amd64_shift_attr_t *attr
= get_amd64_shift_attr_const(node); = get_amd64_shift_attr_const(node);
insn_mode = attr->insn_mode; amd64_emit_insn_mode_suffix(attr->insn_mode);
} else if (*fmt == 'M') { } else if (*fmt == 'M') {
++fmt; ++fmt;
const amd64_movimm_attr_t *attr const amd64_movimm_attr_t *attr
= get_amd64_movimm_attr_const(node); = get_amd64_movimm_attr_const(node);
insn_mode = attr->insn_mode; amd64_emit_insn_mode_suffix(attr->insn_mode);
} else if (*fmt == 'X') {
++fmt;
amd64_emit_xmm_mode_suffix(get_irn_mode(node));
} else { } else {
amd64_addr_attr_t const *const attr amd64_addr_attr_t const *const attr
= get_amd64_addr_attr_const(node); = get_amd64_addr_attr_const(node);
insn_mode = attr->insn_mode; amd64_emit_insn_mode_suffix(attr->insn_mode);
} }
amd64_emit_insn_mode_suffix(insn_mode);
break; break;
} }
......
...@@ -48,7 +48,8 @@ static inline bool amd64_has_addr_attr(const ir_node *node) ...@@ -48,7 +48,8 @@ static inline bool amd64_has_addr_attr(const ir_node *node)
|| attr->op_mode == AMD64_OP_UNOP_REG || attr->op_mode == AMD64_OP_UNOP_REG
|| attr->op_mode == AMD64_OP_RAX_ADDR || attr->op_mode == AMD64_OP_RAX_ADDR
|| attr->op_mode == AMD64_OP_RAX_REG) || attr->op_mode == AMD64_OP_RAX_REG)
&& (get_irn_op(node) != op_amd64_Xor0); && (get_irn_op(node) != op_amd64_Xor0)
&& (get_irn_op(node) != op_amd64_Xorp0);
} }
static inline amd64_addr_attr_t *get_amd64_addr_attr(ir_node *node) static inline amd64_addr_attr_t *get_amd64_addr_attr(ir_node *node)
......
$arch = "amd64"; $arch = "amd64";
$mode_gp = "mode_Lu";
$mode_flags = "mode_Iu";
$mode_xmm = "mode_D"; #TODO 128bit fp-mode
$status_flags = "all"; # TODO
$all_flags = "all";
%reg_classes = ( %reg_classes = (
gp => [ gp => [
{ name => "rax", dwarf => 0 }, { name => "rax", dwarf => 0 },
...@@ -18,19 +24,25 @@ $arch = "amd64"; ...@@ -18,19 +24,25 @@ $arch = "amd64";
{ name => "r13", dwarf => 13 }, { name => "r13", dwarf => 13 },
{ name => "r14", dwarf => 14 }, { name => "r14", dwarf => 14 },
{ name => "r15", dwarf => 15 }, { name => "r15", dwarf => 15 },
{ mode => "mode_Lu" } { mode => $mode_gp }
], ],
flags => [ flags => [
{ name => "eflags", dwarf => 49 }, { name => "eflags", dwarf => 49 },
{ mode => "mode_Iu", flags => "manual_ra" } { mode => $mode_flags, flags => "manual_ra" }
], ],
xmm => [
{ name => "xmm0", dwarf => 17 },
{ name => "xmm1", dwarf => 18 },
{ name => "xmm2", dwarf => 19 },
{ name => "xmm3", dwarf => 20 },
{ name => "xmm4", dwarf => 21 },
{ name => "xmm5", dwarf => 22 },
{ name => "xmm6", dwarf => 23 },
{ name => "xmm7", dwarf => 24 },
{ mode => $mode_xmm }
]
); );
$mode_gp = "mode_Lu";
$mode_flags = "mode_Iu";
$status_flags = "all"; # TODO
$all_flags = "all";
sub amd64_custom_init_attr { sub amd64_custom_init_attr {
my $constr = shift; my $constr = shift;
my $node = shift; my $node = shift;
...@@ -457,4 +469,16 @@ Return => { ...@@ -457,4 +469,16 @@ Return => {
mode => "mode_X", mode => "mode_X",
}, },
# SSE
Xorp0 => {
op_flags => [ "constlike" ],
irn_flags => [ "rematerializable" ],
reg_req => { out => [ "xmm" ] },
outs => [ "res" ],
fixed => "amd64_op_mode_t op_mode = AMD64_OP_REG_REG;",
emit => "xorp%MX %D0, %D0",
mode => $mode_xmm,
},
); );
...@@ -257,9 +257,16 @@ static ir_node *gen_Const(ir_node *node) ...@@ -257,9 +257,16 @@ static ir_node *gen_Const(ir_node *node)
ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *block = be_transform_node(get_nodes_block(node));
dbg_info *dbgi = get_irn_dbg_info(node); dbg_info *dbgi = get_irn_dbg_info(node);
ir_mode *mode = get_irn_mode(node); ir_mode *mode = get_irn_mode(node);
if (!mode_needs_gp_reg(mode))
panic("amd64: float constant not supported yet");
ir_tarval *tv = get_Const_tarval(node); ir_tarval *tv = get_Const_tarval(node);
if (!mode_needs_gp_reg(mode)) {
if (tarval_is_null(tv)) {
return new_bd_amd64_Xorp0(dbgi, block);
}
panic("amd64: float constant not supported yet");
}
uint64_t val = get_tarval_uint64(tv); uint64_t val = get_tarval_uint64(tv);
amd64_insn_mode_t imode = val > UINT32_MAX ? INSN_MODE_64 : INSN_MODE_32; amd64_insn_mode_t imode = val > UINT32_MAX ? INSN_MODE_64 : INSN_MODE_32;
return new_bd_amd64_MovImm(dbgi, block, imode, val, NULL); return new_bd_amd64_MovImm(dbgi, block, imode, val, NULL);
......
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