Commit 6f7332ba authored by Richard Henderson's avatar Richard Henderson
Browse files

target/openrisc: Represent MACHI:MACLO as a single unit



Significantly simplifies the implementation of the use of MAC.

Reviewed-by: default avatarBastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent 24fc5c0f
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -277,8 +277,7 @@ typedef struct CPUOpenRISCState {
    target_ulong ppc;         /* Prev PC */
    target_ulong jmp_pc;      /* Jump PC */

    target_ulong machi;       /* Multiply register MACHI */
    target_ulong maclo;       /* Multiply register MACLO */
    uint64_t mac;             /* Multiply registers MACHI:MACLO */

    target_ulong fpmaddhi;    /* Multiply and add float register FPMADDHI */
    target_ulong fpmaddlo;    /* Multiply and add float register FPMADDLO */
+3 −2
Original line number Diff line number Diff line
@@ -47,8 +47,8 @@ static const VMStateInfo vmstate_sr = {

static const VMStateDescription vmstate_env = {
    .name = "env",
    .version_id = 2,
    .minimum_version_id = 2,
    .version_id = 3,
    .minimum_version_id = 3,
    .fields = (VMStateField[]) {
        VMSTATE_UINTTL_ARRAY(gpr, CPUOpenRISCState, 32),
        VMSTATE_UINTTL(pc, CPUOpenRISCState),
@@ -82,6 +82,7 @@ static const VMStateDescription vmstate_env = {
        VMSTATE_UINT32(immucfgr, CPUOpenRISCState),
        VMSTATE_UINT32(esr, CPUOpenRISCState),
        VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
        VMSTATE_UINT64(mac, CPUOpenRISCState),
        VMSTATE_END_OF_LIST()
    }
};
+13 −0
Original line number Diff line number Diff line
@@ -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, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
        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 */
        env->picmr |= rb;
        break;
@@ -245,6 +251,13 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
    case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */
        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 */
        return env->picmr;

+63 −57
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ static TCGv cpu_sr_ov; /* signed overflow */
static TCGv cpu_lock_addr;
static TCGv cpu_lock_value;
static TCGv_i32 fpcsr;
static TCGv machi, maclo;
static TCGv_i64 cpu_mac;        /* MACHI:MACLO */
static TCGv fpmaddhi, fpmaddlo;
static TCGv_i32 env_flags;
#include "exec/gen-icount.h"
@@ -105,12 +105,9 @@ void openrisc_translate_init(void)
    fpcsr = tcg_global_mem_new_i32(cpu_env,
                                   offsetof(CPUOpenRISCState, fpcsr),
                                   "fpcsr");
    machi = tcg_global_mem_new(cpu_env,
                               offsetof(CPUOpenRISCState, machi),
                               "machi");
    maclo = tcg_global_mem_new(cpu_env,
                               offsetof(CPUOpenRISCState, maclo),
                               "maclo");
    cpu_mac = tcg_global_mem_new_i64(cpu_env,
                                     offsetof(CPUOpenRISCState, mac),
                                     "mac");
    fpmaddhi = tcg_global_mem_new(cpu_env,
                                  offsetof(CPUOpenRISCState, fpmaddhi),
                                  "fpmaddhi");
@@ -365,6 +362,58 @@ static void gen_divu(DisasContext *dc, TCGv dest, TCGv srca, TCGv srcb)
    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)
{
    TCGv ea = tcg_temp_new();
@@ -628,23 +677,9 @@ static void dec_misc(DisasContext *dc, uint32_t insn)

    case 0x13:    /* l.maci */
        LOG_DIS("l.maci r%d, %d\n", ra, I16);
        {
            TCGv_i64 t1 = tcg_temp_new_i64();
            TCGv_i64 t2 = tcg_temp_new_i64();
            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);
        }
        t0 = tcg_const_tl(I16);
        gen_mac(dc, cpu_R[ra], t0);
        tcg_temp_free(t0);
        break;

    case 0x09:    /* l.rfe */
@@ -873,40 +908,12 @@ static void dec_mac(DisasContext *dc, uint32_t insn)
    switch (op0) {
    case 0x0001:    /* l.mac */
        LOG_DIS("l.mac r%d, r%d\n", ra, 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);
        }
        gen_mac(dc, cpu_R[ra], cpu_R[rb]);
        break;

    case 0x0002:    /* l.msb */
        LOG_DIS("l.msb r%d, r%d\n", ra, 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);
        }
        gen_msb(dc, cpu_R[ra], cpu_R[rb]);
        break;

    default:
@@ -969,9 +976,8 @@ static void dec_M(DisasContext *dc, uint32_t insn)

    case 0x1:    /* l.macrc */
        LOG_DIS("l.macrc  r%d\n", rd);
        tcg_gen_mov_tl(cpu_R[rd], maclo);
        tcg_gen_movi_tl(maclo, 0x0);
        tcg_gen_movi_tl(machi, 0x0);
        tcg_gen_trunc_i64_tl(cpu_R[rd], cpu_mac);
        tcg_gen_movi_i64(cpu_mac, 0);
        break;

    default: