tcg: Support cross-class moves without instruction support

PowerPC Altivec does not support direct moves between vector registers
and general registers.  So when tcg_out_mov fails, we can use the
backing memory for the temporary to perform the move.

Acked-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2019-03-16 17:48:32 +00:00
parent 78113e83e0
commit 240c08d099

View file

@ -3368,7 +3368,20 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp *op)
ots->indirect_base);
}
if (!tcg_out_mov(s, otype, ots->reg, ts->reg)) {
abort();
/*
* Cross register class move not supported.
* Store the source register into the destination slot
* and leave the destination temp as TEMP_VAL_MEM.
*/
assert(!ots->fixed_reg);
if (!ts->mem_allocated) {
temp_allocate_frame(s, ots);
}
tcg_out_st(s, ts->type, ts->reg,
ots->mem_base->reg, ots->mem_offset);
ots->mem_coherent = 1;
temp_free_or_dead(s, ots, -1);
return;
}
}
ots->val_type = TEMP_VAL_REG;
@ -3470,7 +3483,13 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
reg = tcg_reg_alloc(s, arg_ct->u.regs, i_allocated_regs,
o_preferred_regs, ts->indirect_base);
if (!tcg_out_mov(s, ts->type, reg, ts->reg)) {
abort();
/*
* Cross register class move not supported. Sync the
* temp back to its slot and load from there.
*/
temp_sync(s, ts, i_allocated_regs, 0, 0);
tcg_out_ld(s, ts->type, reg,
ts->mem_base->reg, ts->mem_offset);
}
}
new_args[i] = reg;
@ -3631,7 +3650,13 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op)
if (ts->reg != reg) {
tcg_reg_free(s, reg, allocated_regs);
if (!tcg_out_mov(s, ts->type, reg, ts->reg)) {
abort();
/*
* Cross register class move not supported. Sync the
* temp back to its slot and load from there.
*/
temp_sync(s, ts, allocated_regs, 0, 0);
tcg_out_ld(s, ts->type, reg,
ts->mem_base->reg, ts->mem_offset);
}
}
} else {