On 6/10/21 9:29 PM, Richard Henderson wrote:
On 6/9/21 6:43 PM, LIU Zhiwei wrote:
1)First a multiply instruction, if the source value big enough, it
will return a result with some bits not zero in MSW 32-bit.
Multiply is fine. Input bits outside the low 32 cannot appear in the
low 32 of the output. Multiply-high-part on the other hand will
require sign- or zero-extension of inputs.
2)If next instruction is a divide instruction, the MSW 32-bit will
influence the divide instruction result.
Yes, division requires extension too.
So I think use *_tl can't satisfy the need to run 32-bit program on
qemu-riscv64.
I said some operations will require extra work -- I gave right-shift
as an example.
You just have to be careful about deciding what extra work to do. I am
suggesting that truncation to *_i32 is almost always not the correct
answer.
Perhaps make it easier by changing gen_get_gpr and gen_set_gpr:
/* Return sign-extended version of gpr. */
static void get_gpr_s(DisasContext *ctx, TCGv t, int reg_num)
{
if (reg_num == 0) {
tcg_gen_movi_tl(t, 0);
} else if (is_32bit(ctx)) {
tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]);
} else {
tcg_gen_mov_tl(t, cpu_gpr[reg_num]);
}
}
/* Return zero-extended version of gpr. */
static void get_gpr_u(DisasContext *ctx, TCGv t, int reg_num);
{
if (reg_num == 0) {
tcg_gen_movi_tl(t, 0);
} else if (is_32bit(ctx)) {
tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]);
} else {
tcg_gen_mov_tl(t, cpu_gpr[reg_num]);
}
}
/* Return gpr with undefined high bits (which will be ignored). */
static void get_gpr_x(TCGv t, int reg_num);
{
if (reg_num == 0) {
tcg_gen_movi_tl(t, 0);
} else {
tcg_gen_mov_tl(t, cpu_gpr[reg_num]);
}
}
And similarly for set.
It's very instructive. Thanks.
I once thought we have to split the registers in CPURISCVSTATE into two
parts, gpr32 or gpr64.
Now I think we can still use most currently work with a small
cost(tcg_gen_ext32s_i64 has more cost than tcg_gen_mov_i32)
I will have a try later. Thanks again.
Best Regards,
Zhiwei
r~