Commit 623357f4 authored by Matthias Braun's avatar Matthias Braun
Browse files

implement some cases of =A asm-constraint

parent cd07ee0e
......@@ -511,7 +511,7 @@ ir_node *ia32_gen_ASM(ir_node *node)
for (out_idx = 0; out_idx < n_out_constraints; ++out_idx) {
const ir_asm_constraint *constraint = &out_constraints[out_idx];
const char *c = get_id_str(constraint->constraint);
unsigned pos = constraint->pos;
unsigned pos = constraint->pos;
constraint_t parsed_constraint;
const arch_register_req_t *req;
......@@ -520,6 +520,12 @@ ir_node *ia32_gen_ASM(ir_node *node)
out_reg_reqs, out_idx);
out_reg_reqs[out_idx] = req;
/* multiple constraints for same pos. This can happen for example when
* a =A constraint gets lowered to two constraints: =a and =d for the
* same pos */
if (register_map[pos].valid)
continue;
register_map[pos].use_input = 0;
register_map[pos].valid = 1;
register_map[pos].memory = 0;
......
......@@ -1939,30 +1939,106 @@ static void lower_Mux(ir_node *mux, ir_mode *mode, lower_env_t *env)
*/
static void lower_ASM(ir_node *asmn, ir_mode *mode, lower_env_t *env)
{
ir_mode *his = env->high_signed;
ir_mode *hiu = env->high_unsigned;
ir_mode *high_signed = env->high_signed;
ir_mode *high_unsigned = env->high_unsigned;
int n_outs = get_ASM_n_output_constraints(asmn);
ir_asm_constraint *output_constraints = get_ASM_output_constraints(asmn);
ir_asm_constraint *input_constraints = get_ASM_input_constraints(asmn);
unsigned n_64bit_outs = 0;
int i;
ir_node *n;
(void)mode;
for (i = get_irn_arity(asmn) - 1; i >= 0; --i) {
ir_mode *op_mode = get_irn_mode(get_irn_n(asmn, i));
if (op_mode == his || op_mode == hiu) {
panic("lowering ASM unimplemented");
ir_node *op = get_irn_n(asmn, i);
ir_mode *op_mode = get_irn_mode(op);
if (op_mode == high_signed || op_mode == high_unsigned) {
panic("lowering ASM 64bit input unimplemented");
}
}
for (n = asmn;;) {
ir_mode *proj_mode;
for (i = 0; i < n_outs; ++i) {
const ir_asm_constraint *constraint = &output_constraints[i];
if (constraint->mode == high_signed || constraint->mode == high_unsigned) {
const char *constr = get_id_str(constraint->constraint);
++n_64bit_outs;
/* TODO: How to do this architecture neutral? This is very
* i386 specific... */
if (constr[0] != '=' || constr[1] != 'A') {
panic("lowering ASM 64bit output only supports '=A' currently");
}
}
}
n = (ir_node*)get_irn_link(n);
if (n == NULL)
break;
if (n_64bit_outs == 0)
return;
proj_mode = get_irn_mode(n);
if (proj_mode == his || proj_mode == hiu) {
panic("lowering ASM unimplemented");
{
dbg_info *dbgi = get_irn_dbg_info(asmn);
ir_node *block = get_nodes_block(asmn);
int arity = get_irn_arity(asmn);
ir_node **in = get_irn_in(asmn) + 1;
int n_outs = get_ASM_n_output_constraints(asmn);
int new_n_outs = 0;
int n_clobber = get_ASM_n_clobbers(asmn);
long *proj_map = ALLOCAN(long, n_outs);
ident **clobbers = get_ASM_clobbers(asmn);
ident *asm_text = get_ASM_text(asmn);
ir_asm_constraint *new_outputs
= ALLOCAN(ir_asm_constraint, n_outs+n_64bit_outs);
ir_node *new_asm;
for (i = 0; i < n_outs; ++i) {
const ir_asm_constraint *constraint = &output_constraints[i];
if (constraint->mode == high_signed || constraint->mode == high_unsigned) {
new_outputs[new_n_outs].pos = constraint->pos;
new_outputs[new_n_outs].constraint = new_id_from_str("=a");
new_outputs[new_n_outs].mode = env->low_unsigned;
proj_map[i] = new_n_outs;
++new_n_outs;
new_outputs[new_n_outs].pos = constraint->pos;
new_outputs[new_n_outs].constraint = new_id_from_str("=d");
if (constraint->mode == high_signed)
new_outputs[new_n_outs].mode = env->low_signed;
else
new_outputs[new_n_outs].mode = env->low_unsigned;
++new_n_outs;
} else {
new_outputs[new_n_outs] = *constraint;
proj_map[i] = new_n_outs;
++new_n_outs;
}
}
assert(new_n_outs == n_outs+(int)n_64bit_outs);
new_asm = new_rd_ASM(dbgi, block, arity, in, input_constraints,
new_n_outs, new_outputs, n_clobber, clobbers,
asm_text);
for (n = asmn;;) {
long pn;
ir_mode *proj_mode;
n = (ir_node*)get_irn_link(n);
if (n == NULL)
break;
proj_mode = get_irn_mode(n);
pn = get_Proj_proj(n);
if (pn < n_outs)
pn = proj_map[pn];
else
pn = new_n_outs + pn - n_outs;
if (proj_mode == high_signed || proj_mode == high_unsigned) {
ir_mode *high_mode
= proj_mode == high_signed ? env->low_signed : env->low_unsigned;
ir_node *np_low = new_r_Proj(new_asm, env->low_unsigned, pn);
ir_node *np_high = new_r_Proj(new_asm, high_mode, pn+1);
set_lowered(env, n, np_low, np_high);
} else {
ir_node *np = new_r_Proj(new_asm, proj_mode, pn);
exchange(n, np);
}
}
}
}
......
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