target/openrisc: Represent MACHI:MACLO as a single unit
Significantly simplifies the implementation of the use of MAC. Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
24fc5c0feb
commit
6f7332ba71
|
@ -277,8 +277,7 @@ typedef struct CPUOpenRISCState {
|
||||||
target_ulong ppc; /* Prev PC */
|
target_ulong ppc; /* Prev PC */
|
||||||
target_ulong jmp_pc; /* Jump PC */
|
target_ulong jmp_pc; /* Jump PC */
|
||||||
|
|
||||||
target_ulong machi; /* Multiply register MACHI */
|
uint64_t mac; /* Multiply registers MACHI:MACLO */
|
||||||
target_ulong maclo; /* Multiply register MACLO */
|
|
||||||
|
|
||||||
target_ulong fpmaddhi; /* Multiply and add float register FPMADDHI */
|
target_ulong fpmaddhi; /* Multiply and add float register FPMADDHI */
|
||||||
target_ulong fpmaddlo; /* Multiply and add float register FPMADDLO */
|
target_ulong fpmaddlo; /* Multiply and add float register FPMADDLO */
|
||||||
|
|
|
@ -47,8 +47,8 @@ static const VMStateInfo vmstate_sr = {
|
||||||
|
|
||||||
static const VMStateDescription vmstate_env = {
|
static const VMStateDescription vmstate_env = {
|
||||||
.name = "env",
|
.name = "env",
|
||||||
.version_id = 2,
|
.version_id = 3,
|
||||||
.minimum_version_id = 2,
|
.minimum_version_id = 3,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32),
|
VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32),
|
||||||
VMSTATE_UINTTL(pc, CPUOpenRISCState),
|
VMSTATE_UINTTL(pc, CPUOpenRISCState),
|
||||||
|
@ -82,6 +82,7 @@ static const VMStateDescription vmstate_env = {
|
||||||
VMSTATE_UINT32(immucfgr, CPUOpenRISCState),
|
VMSTATE_UINT32(immucfgr, CPUOpenRISCState),
|
||||||
VMSTATE_UINT32(esr, CPUOpenRISCState),
|
VMSTATE_UINT32(esr, CPUOpenRISCState),
|
||||||
VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
|
VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
|
||||||
|
VMSTATE_UINT64(mac, CPUOpenRISCState),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -120,6 +120,12 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
|
||||||
case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
|
case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */
|
||||||
case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
|
case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
|
||||||
break;
|
break;
|
||||||
|
case TO_SPR(5, 1): /* MACLO */
|
||||||
|
env->mac = deposit64(env->mac, 0, 32, rb);
|
||||||
|
break;
|
||||||
|
case TO_SPR(5, 2): /* MACHI */
|
||||||
|
env->mac = deposit64(env->mac, 32, 32, rb);
|
||||||
|
break;
|
||||||
case TO_SPR(9, 0): /* PICMR */
|
case TO_SPR(9, 0): /* PICMR */
|
||||||
env->picmr |= rb;
|
env->picmr |= rb;
|
||||||
break;
|
break;
|
||||||
|
@ -245,6 +251,13 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
|
||||||
case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
|
case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TO_SPR(5, 1): /* MACLO */
|
||||||
|
return (uint32_t)env->mac;
|
||||||
|
break;
|
||||||
|
case TO_SPR(5, 2): /* MACHI */
|
||||||
|
return env->mac >> 32;
|
||||||
|
break;
|
||||||
|
|
||||||
case TO_SPR(9, 0): /* PICMR */
|
case TO_SPR(9, 0): /* PICMR */
|
||||||
return env->picmr;
|
return env->picmr;
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ static TCGv cpu_sr_ov; /* signed overflow */
|
||||||
static TCGv cpu_lock_addr;
|
static TCGv cpu_lock_addr;
|
||||||
static TCGv cpu_lock_value;
|
static TCGv cpu_lock_value;
|
||||||
static TCGv_i32 fpcsr;
|
static TCGv_i32 fpcsr;
|
||||||
static TCGv machi, maclo;
|
static TCGv_i64 cpu_mac; /* MACHI:MACLO */
|
||||||
static TCGv fpmaddhi, fpmaddlo;
|
static TCGv fpmaddhi, fpmaddlo;
|
||||||
static TCGv_i32 env_flags;
|
static TCGv_i32 env_flags;
|
||||||
#include "exec/gen-icount.h"
|
#include "exec/gen-icount.h"
|
||||||
|
@ -105,12 +105,9 @@ void openrisc_translate_init(void)
|
||||||
fpcsr = tcg_global_mem_new_i32(cpu_env,
|
fpcsr = tcg_global_mem_new_i32(cpu_env,
|
||||||
offsetof(CPUOpenRISCState, fpcsr),
|
offsetof(CPUOpenRISCState, fpcsr),
|
||||||
"fpcsr");
|
"fpcsr");
|
||||||
machi = tcg_global_mem_new(cpu_env,
|
cpu_mac = tcg_global_mem_new_i64(cpu_env,
|
||||||
offsetof(CPUOpenRISCState, machi),
|
offsetof(CPUOpenRISCState, mac),
|
||||||
"machi");
|
"mac");
|
||||||
maclo = tcg_global_mem_new(cpu_env,
|
|
||||||
offsetof(CPUOpenRISCState, maclo),
|
|
||||||
"maclo");
|
|
||||||
fpmaddhi = tcg_global_mem_new(cpu_env,
|
fpmaddhi = tcg_global_mem_new(cpu_env,
|
||||||
offsetof(CPUOpenRISCState, fpmaddhi),
|
offsetof(CPUOpenRISCState, fpmaddhi),
|
||||||
"fpmaddhi");
|
"fpmaddhi");
|
||||||
|
@ -365,6 +362,58 @@ static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
|
||||||
gen_ove_cy(dc);
|
gen_ove_cy(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_mac(DisasContext *dc, TCGv srca, TCGv srcb)
|
||||||
|
{
|
||||||
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
tcg_gen_ext_tl_i64(t1, srca);
|
||||||
|
tcg_gen_ext_tl_i64(t2, srcb);
|
||||||
|
tcg_gen_mul_i64(t1, t1, t2);
|
||||||
|
|
||||||
|
/* Note that overflow is only computed during addition stage. */
|
||||||
|
tcg_gen_xor_i64(t2, cpu_mac, t1);
|
||||||
|
tcg_gen_add_i64(cpu_mac, cpu_mac, t1);
|
||||||
|
tcg_gen_xor_i64(t1, t1, cpu_mac);
|
||||||
|
tcg_gen_andc_i64(t1, t1, t2);
|
||||||
|
tcg_temp_free_i64(t2);
|
||||||
|
|
||||||
|
#if TARGET_LONG_BITS == 32
|
||||||
|
tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
|
||||||
|
#else
|
||||||
|
tcg_gen_mov_i64(cpu_sr_ov, t1);
|
||||||
|
#endif
|
||||||
|
tcg_temp_free_i64(t1);
|
||||||
|
|
||||||
|
gen_ove_ov(dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_msb(DisasContext *dc, TCGv srca, TCGv srcb)
|
||||||
|
{
|
||||||
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
tcg_gen_ext_tl_i64(t1, srca);
|
||||||
|
tcg_gen_ext_tl_i64(t2, srcb);
|
||||||
|
tcg_gen_mul_i64(t1, t1, t2);
|
||||||
|
|
||||||
|
/* Note that overflow is only computed during subtraction stage. */
|
||||||
|
tcg_gen_xor_i64(t2, cpu_mac, t1);
|
||||||
|
tcg_gen_sub_i64(cpu_mac, cpu_mac, t1);
|
||||||
|
tcg_gen_xor_i64(t1, t1, cpu_mac);
|
||||||
|
tcg_gen_and_i64(t1, t1, t2);
|
||||||
|
tcg_temp_free_i64(t2);
|
||||||
|
|
||||||
|
#if TARGET_LONG_BITS == 32
|
||||||
|
tcg_gen_extrh_i64_i32(cpu_sr_ov, t1);
|
||||||
|
#else
|
||||||
|
tcg_gen_mov_i64(cpu_sr_ov, t1);
|
||||||
|
#endif
|
||||||
|
tcg_temp_free_i64(t1);
|
||||||
|
|
||||||
|
gen_ove_ov(dc);
|
||||||
|
}
|
||||||
|
|
||||||
static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs)
|
static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs)
|
||||||
{
|
{
|
||||||
TCGv ea = tcg_temp_new();
|
TCGv ea = tcg_temp_new();
|
||||||
|
@ -628,23 +677,9 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
|
||||||
|
|
||||||
case 0x13: /* l.maci */
|
case 0x13: /* l.maci */
|
||||||
LOG_DIS("l.maci r%d, %d\n", ra, I16);
|
LOG_DIS("l.maci r%d, %d\n", ra, I16);
|
||||||
{
|
t0 = tcg_const_tl(I16);
|
||||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
gen_mac(dc, cpu_R[ra], t0);
|
||||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
tcg_temp_free(t0);
|
||||||
TCGv_i32 dst = tcg_temp_new_i32();
|
|
||||||
TCGv ttmp = tcg_const_tl(I16);
|
|
||||||
tcg_gen_mul_tl(dst, cpu_R[ra], ttmp);
|
|
||||||
tcg_gen_ext_i32_i64(t1, dst);
|
|
||||||
tcg_gen_concat_i32_i64(t2, maclo, machi);
|
|
||||||
tcg_gen_add_i64(t2, t2, t1);
|
|
||||||
tcg_gen_extrl_i64_i32(maclo, t2);
|
|
||||||
tcg_gen_shri_i64(t2, t2, 32);
|
|
||||||
tcg_gen_extrl_i64_i32(machi, t2);
|
|
||||||
tcg_temp_free_i32(dst);
|
|
||||||
tcg_temp_free(ttmp);
|
|
||||||
tcg_temp_free_i64(t1);
|
|
||||||
tcg_temp_free_i64(t2);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x09: /* l.rfe */
|
case 0x09: /* l.rfe */
|
||||||
|
@ -873,40 +908,12 @@ static void dec_mac(DisasContext *dc, uint32_t insn)
|
||||||
switch (op0) {
|
switch (op0) {
|
||||||
case 0x0001: /* l.mac */
|
case 0x0001: /* l.mac */
|
||||||
LOG_DIS("l.mac r%d, r%d\n", ra, rb);
|
LOG_DIS("l.mac r%d, r%d\n", ra, rb);
|
||||||
{
|
gen_mac(dc, cpu_R[ra], cpu_R[rb]);
|
||||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
|
||||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
|
||||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
|
||||||
tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]);
|
|
||||||
tcg_gen_ext_i32_i64(t1, t0);
|
|
||||||
tcg_gen_concat_i32_i64(t2, maclo, machi);
|
|
||||||
tcg_gen_add_i64(t2, t2, t1);
|
|
||||||
tcg_gen_extrl_i64_i32(maclo, t2);
|
|
||||||
tcg_gen_shri_i64(t2, t2, 32);
|
|
||||||
tcg_gen_extrl_i64_i32(machi, t2);
|
|
||||||
tcg_temp_free_i32(t0);
|
|
||||||
tcg_temp_free_i64(t1);
|
|
||||||
tcg_temp_free_i64(t2);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0002: /* l.msb */
|
case 0x0002: /* l.msb */
|
||||||
LOG_DIS("l.msb r%d, r%d\n", ra, rb);
|
LOG_DIS("l.msb r%d, r%d\n", ra, rb);
|
||||||
{
|
gen_msb(dc, cpu_R[ra], cpu_R[rb]);
|
||||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
|
||||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
|
||||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
|
||||||
tcg_gen_mul_tl(t0, cpu_R[ra], cpu_R[rb]);
|
|
||||||
tcg_gen_ext_i32_i64(t1, t0);
|
|
||||||
tcg_gen_concat_i32_i64(t2, maclo, machi);
|
|
||||||
tcg_gen_sub_i64(t2, t2, t1);
|
|
||||||
tcg_gen_extrl_i64_i32(maclo, t2);
|
|
||||||
tcg_gen_shri_i64(t2, t2, 32);
|
|
||||||
tcg_gen_extrl_i64_i32(machi, t2);
|
|
||||||
tcg_temp_free_i32(t0);
|
|
||||||
tcg_temp_free_i64(t1);
|
|
||||||
tcg_temp_free_i64(t2);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -969,9 +976,8 @@ static void dec_M(DisasContext *dc, uint32_t insn)
|
||||||
|
|
||||||
case 0x1: /* l.macrc */
|
case 0x1: /* l.macrc */
|
||||||
LOG_DIS("l.macrc r%d\n", rd);
|
LOG_DIS("l.macrc r%d\n", rd);
|
||||||
tcg_gen_mov_tl(cpu_R[rd], maclo);
|
tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac);
|
||||||
tcg_gen_movi_tl(maclo, 0x0);
|
tcg_gen_movi_i64(cpu_mac, 0);
|
||||||
tcg_gen_movi_tl(machi, 0x0);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue