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[] = {
&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[] = {
&amd64_registers[REG_RAX],
&amd64_registers[REG_RDX],
};
static const arch_register_t* const float_result_regs[] = {
&amd64_registers[REG_XMM0],
};
static const unsigned caller_saves[] = {
REG_RAX,
REG_RCX,
......@@ -49,6 +64,14 @@ static const unsigned caller_saves[] = {
REG_R9,
REG_R10,
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)];
......@@ -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);
/* determine how parameters are passed */
size_t n_params = get_method_n_params(function_type);
size_t regnum = 0;
reg_or_stackslot_t *params = XMALLOCNZ(reg_or_stackslot_t, n_params);
size_t n_params = get_method_n_params(function_type);
size_t param_regnum = 0;
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_float_param_regs = ARRAY_SIZE(float_param_regs);
unsigned stack_offset = 0;
for (size_t i = 0; i < n_params; ++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,
int bits = get_mode_size_bits(mode);
reg_or_stackslot_t *param = &params[i];
if (regnum < n_param_regs) {
const arch_register_t *reg = param_regs[regnum];
if (mode_is_float(mode) && float_param_regnum < n_float_param_regs) {
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->req = reg->single_req;
param->reg_offset = regnum;
++regnum;
param->reg_offset = param_regnum;
++param_regnum;
} else {
param->type = param_type;
param->offset = stack_offset;
......@@ -125,36 +157,48 @@ amd64_cconv_t *amd64_decide_calling_convention(ir_type *function_type,
stack_offset += MAX(bits / 8, AMD64_REGISTER_SIZE);
continue;
}
}
unsigned n_param_regs_used = regnum;
unsigned n_param_regs_used = param_regnum + float_param_regnum;
/* determine how results are passed */
size_t n_results = get_method_n_ress(function_type);
unsigned n_reg_results = 0;
reg_or_stackslot_t *results = XMALLOCNZ(reg_or_stackslot_t, n_results);
unsigned res_regnum = 0;
unsigned res_float_regnum = 0;
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) {
ir_type *result_type = get_method_res_type(function_type, i);
ir_mode *result_mode = get_type_mode(result_type);
reg_or_stackslot_t *result = &results[i];
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 {
if (res_regnum >= n_result_regs) {
panic("Too many results");
} else {
const arch_register_t *reg = result_regs[res_regnum++];
result->req = reg->single_req;
result->reg_offset = i;
result->req = reg->single_req;
result->reg_offset = i;
rbitset_clear(caller_saves, reg->global_index);
++n_reg_results;
}
}
}
amd64_cconv_t *cconv = XMALLOCZ(amd64_cconv_t);
amd64_cconv_t *cconv = XMALLOCZ(amd64_cconv_t);
cconv->parameters = params;
cconv->param_stack_size = stack_offset;
cconv->n_param_regs = n_param_regs_used;
......
......@@ -58,6 +58,20 @@ static void amd64_emit_insn_mode_suffix(amd64_insn_mode_t mode)
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)
{
switch (reg->index) {
......@@ -480,30 +494,36 @@ emit_R:
? INSN_MODE_64 : INSN_MODE_32;
emit_register_insn_mode(reg, dest_mode);
} else {
amd64_insn_mode_t insn_mode = get_amd64_insn_mode(node);
emit_register_insn_mode(reg, insn_mode);
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_insn_mode(reg, insn_mode);
}
}
break;
}
case 'M': {
amd64_insn_mode_t insn_mode;
if (*fmt == 'S') {
++fmt;
const amd64_shift_attr_t *attr
= get_amd64_shift_attr_const(node);
insn_mode = attr->insn_mode;
amd64_emit_insn_mode_suffix(attr->insn_mode);
} else if (*fmt == 'M') {
++fmt;
const amd64_movimm_attr_t *attr
= 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 {
amd64_addr_attr_t const *const attr
= 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;
}
......
......@@ -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_RAX_ADDR
|| 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)
......
$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 = (
gp => [
{ name => "rax", dwarf => 0 },
......@@ -18,19 +24,25 @@ $arch = "amd64";
{ name => "r13", dwarf => 13 },
{ name => "r14", dwarf => 14 },
{ name => "r15", dwarf => 15 },
{ mode => "mode_Lu" }
{ mode => $mode_gp }
],
flags => [
{ 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 {
my $constr = shift;
my $node = shift;
......@@ -457,4 +469,16 @@ Return => {
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)
ir_node *block = be_transform_node(get_nodes_block(node));
dbg_info *dbgi = get_irn_dbg_info(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);
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);
amd64_insn_mode_t imode = val > UINT32_MAX ? INSN_MODE_64 : INSN_MODE_32;
return new_bd_amd64_MovImm(dbgi, block, imode, val, NULL);
......
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