diff mbox

[v5,12/16] target-or32: Add system instructions

Message ID 1339981384-9117-13-git-send-email-proljc@gmail.com
State New
Headers show

Commit Message

Jia Liu June 18, 2012, 1:03 a.m. UTC
Add OpenRISC system instruction support.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 target-openrisc/Makefile.objs |    3 +-
 target-openrisc/helper.h      |    4 +
 target-openrisc/sys_helper.c  |  233 +++++++++++++++++++++++++++++++++++++++++
 target-openrisc/translate.c   |   20 ++++
 4 files changed, 259 insertions(+), 1 deletion(-)
 create mode 100644 target-openrisc/sys_helper.c

Comments

Blue Swirl June 18, 2012, 6:58 p.m. UTC | #1
On Mon, Jun 18, 2012 at 1:03 AM, Jia Liu <proljc@gmail.com> wrote:
> Add OpenRISC system instruction support.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  target-openrisc/Makefile.objs |    3 +-
>  target-openrisc/helper.h      |    4 +
>  target-openrisc/sys_helper.c  |  233 +++++++++++++++++++++++++++++++++++++++++
>  target-openrisc/translate.c   |   20 ++++
>  4 files changed, 259 insertions(+), 1 deletion(-)
>  create mode 100644 target-openrisc/sys_helper.c
>
> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
> index 0d72c33..9d13a5d 100644
> --- a/target-openrisc/Makefile.objs
> +++ b/target-openrisc/Makefile.objs
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_SOFTMMU) += machine.o
>  obj-y += cpu.o excp.o intrpt.o mmu.o translate.o
> -obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o mmu_helper.o
> +obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o \
> +         mmu_helper.o sys_helper.o
> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
> index 60870f2..04c63c5 100644
> --- a/target-openrisc/helper.h
> +++ b/target-openrisc/helper.h
> @@ -62,4 +62,8 @@ DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
>  /* interrupt */
>  DEF_HELPER_FLAGS_1(rfe, 0, void, env)
>
> +/* sys */
> +DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
> +DEF_HELPER_FLAGS_4(mfspr, 0, void, env, tl, tl, tl)
> +
>  #include "def-helper.h"
> diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
> new file mode 100644
> index 0000000..f1e4314
> --- /dev/null
> +++ b/target-openrisc/sys_helper.c
> @@ -0,0 +1,233 @@
> +/*
> + *  OpenRISC system instructions helper routines
> + *
> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
> + *                          Zhizhou Zhang <etouzh@gmail.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "cpu.h"
> +#include "helper.h"
> +
> +#define TO_SPR(group, number) (((group) << 11) + (number))
> +
> +void HELPER(mtspr)(CPUOpenRISCState * env,
> +                   target_ulong ra, target_ulong rb, target_ulong offset)
> +{
> +#if !defined(CONFIG_USER_ONLY)
> +    int spr = (ra | offset);
> +    int idx;
> +
> +    switch (spr) {
> +    case TO_SPR(0, 0): /* VR */
> +        env->vr = rb;
> +        break;
> +
> +    case TO_SPR(0, 16): /* NPC */
> +        env->npc = rb;
> +        break;
> +
> +    case TO_SPR(0, 17): /* SR */
> +        if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
> +            (rb & (SR_IME | SR_DME | SR_SM))) {
> +            tlb_flush(env, 1);
> +        }
> +        env->sr = rb;
> +        env->sr |= SR_FO;      /* FO is const equal to 1 */
> +        if (env->sr & SR_DME) {
> +            env->tlb->map_address_data = &get_phys_data;
> +        } else {
> +            env->tlb->map_address_data = &get_phys_nommu;
> +        }
> +
> +        if (env->sr & SR_IME) {
> +            env->tlb->map_address_code = &get_phys_code;
> +        } else {
> +            env->tlb->map_address_code = &get_phys_nommu;
> +        }
> +        break;
> +
> +    case TO_SPR(0, 18): /* PPC */
> +        env->ppc = rb;
> +        break;
> +
> +    case TO_SPR(0, 32): /* EPCR */
> +        env->epcr = rb;
> +        break;
> +
> +    case TO_SPR(0, 48): /* EEAR */
> +        env->eear = rb;
> +        break;
> +
> +    case TO_SPR(0, 64): /* ESR */
> +        env->esr = rb;
> +        break;
> +    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
> +        idx = spr - TO_SPR(1, 512);
> +        if (!(rb & 1)) {
> +            tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
> +        }
> +        env->tlb->dtlb[0][idx].mr = rb;
> +        break;
> +
> +    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
> +        idx = spr - TO_SPR(1, 640);
> +        env->tlb->dtlb[0][idx].tr = rb;
> +        break;
> +    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
> +    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
> +    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
> +    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
> +    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
> +    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
> +        break;
> +    case TO_SPR(2, 512) ... TO_SPR(2, 639):   /* ITLBW0MR 0-127 */
> +        idx = spr - TO_SPR(2, 512);
> +        if (!(rb & 1)) {
> +            tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
> +        }
> +        env->tlb->itlb[0][idx].mr = rb;
> +        break;
> +
> +    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
> +        idx = spr - TO_SPR(2, 640);
> +        env->tlb->itlb[0][idx].tr = rb;
> +        break;
> +    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
> +    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
> +    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
> +    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
> +        break;
> +    case TO_SPR(9, 0):  /* PICMR */
> +        cpu_openrisc_store_picmr(env, rb);
> +        break;
> +    case TO_SPR(9, 2):  /* PICSR */
> +        cpu_openrisc_store_picsr(env, rb);
> +        break;
> +    case TO_SPR(10, 0): /* TTMR */
> +        cpu_openrisc_store_compare(env, rb);
> +        break;
> +    case TO_SPR(10, 1): /* TTCR */
> +        cpu_openrisc_store_count(env, rb);
> +        break;
> +    default:
> +        break;
> +    }
> +#endif
> +}
> +
> +void HELPER(mfspr)(CPUOpenRISCState * env,
> +                   target_ulong rd, target_ulong ra, uint32_t offset)
> +{
> +#if !defined(CONFIG_USER_ONLY)
> +    int spr = env->gpr[ra] | offset;

[1]

> +    int idx;
> +
> +    switch (spr) {
> +    case TO_SPR(0, 0): /* VR */
> +        env->gpr[rd] = (env->vr & SPR_VR);
> +        break;
> +
> +    case TO_SPR(0, 1): /* UPR */
> +        env->gpr[rd] = env->upr;    /* TT, DM, IM, UP present */
> +        break;
> +
> +    case TO_SPR(0, 2): /* CPUCFGR */
> +        env->gpr[rd] = env->cpucfgr;
> +        break;
> +
> +    case TO_SPR(0, 3): /* DMMUCFGR */
> +        env->gpr[rd] = env->dmmucfgr;    /* 1Way, 64 entries */
> +        break;
> +    case TO_SPR(0, 4): /* IMMUCFGR */
> +        env->gpr[rd] = env->immucfgr;
> +        break;
> +
> +    case TO_SPR(0, 16): /* NPC */
> +        env->gpr[rd] = env->npc;
> +        break;
> +
> +    case TO_SPR(0, 17): /* SR */
> +        env->gpr[rd] = env->sr;
> +        break;
> +
> +    case TO_SPR(0, 18): /* PPC */
> +        env->gpr[rd] = env->ppc;
> +        break;
> +
> +    case TO_SPR(0, 32): /* EPCR */
> +        env->gpr[rd] = env->epcr;
> +        break;
> +
> +    case TO_SPR(0, 48): /* EEAR */
> +        env->gpr[rd] = env->eear;
> +        break;
> +
> +    case TO_SPR(0, 64): /* ESR */
> +        env->gpr[rd] = env->esr;
> +        break;
> +
> +    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
> +        idx = spr - TO_SPR(1, 512);
> +        env->gpr[rd] = env->tlb->dtlb[0][idx].mr;
> +        break;
> +
> +    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
> +        idx = spr - TO_SPR(1, 640);
> +        env->gpr[rd] = env->tlb->dtlb[0][idx].tr;
> +        break;
> +    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
> +    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
> +    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
> +    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
> +    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
> +    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
> +        break;
> +
> +    case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
> +        idx = spr - TO_SPR(2, 512);
> +        env->gpr[rd] = env->tlb->itlb[0][idx].mr;
> +        break;
> +
> +    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
> +        idx = spr - TO_SPR(2, 640);
> +        env->gpr[rd] = env->tlb->itlb[0][idx].tr;
> +        break;
> +    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
> +    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
> +    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
> +    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
> +        break;
> +    case TO_SPR(9, 0):  /* PICMR */
> +        env->gpr[rd] = env->picmr;
> +        break;
> +    case TO_SPR(9, 2):  /* PICSR */
> +        env->gpr[rd] = env->picsr;
> +        break;
> +    case TO_SPR(10, 0): /* TTMR */
> +        env->gpr[rd] = env->ttmr;
> +        break;
> +    case TO_SPR(10, 1): /* TTCR */
> +        env->gpr[rd] = cpu_openrisc_get_count(env);

[2]

> +        break;
> +    default:
> +        break;
> +    }
> +#endif
> +}
> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
> index d4f894b..11eb0a5 100644
> --- a/target-openrisc/translate.c
> +++ b/target-openrisc/translate.c
> @@ -1241,10 +1241,30 @@ static void dec_misc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
>
>     case 0x2d:   /*l.mfspr*/
>         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
> +        {
> +            TCGv_i32 ti = tcg_const_i32(I16);
> +            TCGv td = tcg_const_tl(rd);
> +            TCGv ta = tcg_const_tl(ra);
> +            gen_helper_mfspr(cpu_env, td, ta, ti);

The helper should a return target_ulong, so the line would become
gen_helper_mfspr(cpu_R[rd], cpu_env, td, cpu_R[ra], ti);

Then the register moves inside the mfspr helper could be avoided:
[1]
> +    int spr = env->gpr[ra] | offset;
int spr = ra | offset;

As an example [2]:
> +        env->gpr[rd] = cpu_openrisc_get_count(env);
return cpu_openrisc_get_count(env);

> +            tcg_temp_free_i32(ti);
> +            tcg_temp_free(td);
> +            tcg_temp_free(ta);
> +        }

Also here you could try later to avoid to compile sys_helper.c for
user emulator by surrounding the previous block by #ifndef
CONFIG_USER_ONLY/#endif (ditto for mtspr).

>         break;
>
>     case 0x30:  /*l.mtspr*/
>         LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
> +        {
> +            TCGv_i32 im = tcg_const_i32(tmp);
> +            TCGv ta = tcg_temp_new();
> +            TCGv tb = tcg_temp_new();
> +            tcg_gen_mov_tl(ta, cpu_R[ra]);
> +            tcg_gen_mov_tl(tb, cpu_R[rb]);
> +            gen_helper_mtspr(cpu_env, ta, tb, im);

Simply
gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);

> +            tcg_temp_free_i32(im);
> +            tcg_temp_free(ta);
> +            tcg_temp_free(tb);
> +        }
>         break;
>
>     case 0x34:   /*l.sd*/
> --
> 1.7.9.5
>
>
Jia Liu June 19, 2012, 8:02 a.m. UTC | #2
Hi Blue,

Thank you for review.
Is this code OK?

void HELPER(mtspr)(CPUOpenRISCState * env,
                   target_ulong ra, target_ulong rb, target_ulong offset)
{
#ifndef CONFIG_USER_ONLY
    int spr = (ra | offset);
    int idx;

    switch (spr) {
    case TO_SPR(0, 0): /* VR */
        env->vr = rb;
        break;

    case TO_SPR(0, 16): /* NPC */
        env->npc = rb;
        break;

    case TO_SPR(0, 17): /* SR */
        if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
            (rb & (SR_IME | SR_DME | SR_SM))) {
            tlb_flush(env, 1);
        }
        env->sr = rb;
        env->sr |= SR_FO;      /* FO is const equal to 1 */
        if (env->sr & SR_DME) {
            env->tlb->map_address_data = &get_phys_data;
        } else {
            env->tlb->map_address_data = &get_phys_nommu;
        }

        if (env->sr & SR_IME) {
            env->tlb->map_address_code = &get_phys_code;
        } else {
            env->tlb->map_address_code = &get_phys_nommu;
        }
        break;

    case TO_SPR(0, 18): /* PPC */
        env->ppc = rb;
        break;

    case TO_SPR(0, 32): /* EPCR */
        env->epcr = rb;
        break;

    case TO_SPR(0, 48): /* EEAR */
        env->eear = rb;
        break;

    case TO_SPR(0, 64): /* ESR */
        env->esr = rb;
        break;
    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
        idx = spr - TO_SPR(1, 512);
        if (!(rb & 1)) {
            tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
        }
        env->tlb->dtlb[0][idx].mr = rb;
        break;

    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
        idx = spr - TO_SPR(1, 640);
        env->tlb->dtlb[0][idx].tr = rb;
        break;
    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
        break;
    case TO_SPR(2, 512) ... TO_SPR(2, 639):   /* ITLBW0MR 0-127 */
        idx = spr - TO_SPR(2, 512);
        if (!(rb & 1)) {
            tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
        }
        env->tlb->itlb[0][idx].mr = rb;
        break;

    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
        idx = spr - TO_SPR(2, 640);
        env->tlb->itlb[0][idx].tr = rb;
        break;
    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
        break;
    case TO_SPR(9, 0):  /* PICMR */
        cpu_openrisc_store_picmr(env, rb);
        break;
    case TO_SPR(9, 2):  /* PICSR */
        cpu_openrisc_store_picsr(env, rb);
        break;
    case TO_SPR(10, 0): /* TTMR */
        cpu_openrisc_store_compare(env, rb);
        break;
    case TO_SPR(10, 1): /* TTCR */
        cpu_openrisc_store_count(env, rb);
        break;
    default:
        break;
    }
#endif
}

target_ulong HELPER(mfspr)(CPUOpenRISCState * env,
                           target_ulong rd, target_ulong ra, uint32_t offset)
{
#ifndef CONFIG_USER_ONLY
    int spr = (ra | offset);
    int idx;

    switch (spr) {
    case TO_SPR(0, 0): /* VR */
        return (env->vr & SPR_VR);

    case TO_SPR(0, 1): /* UPR */
        return (env->upr);    /* TT, DM, IM, UP present */

    case TO_SPR(0, 2): /* CPUCFGR */
        return (env->cpucfgr);

    case TO_SPR(0, 3): /* DMMUCFGR */
        return (env->dmmucfgr);    /* 1Way, 64 entries */

    case TO_SPR(0, 4): /* IMMUCFGR */
        return (env->immucfgr);

    case TO_SPR(0, 16): /* NPC */
        return (env->npc);

    case TO_SPR(0, 17): /* SR */
        return (env->sr);

    case TO_SPR(0, 18): /* PPC */
        return (env->ppc);

    case TO_SPR(0, 32): /* EPCR */
        return (env->epcr);

    case TO_SPR(0, 48): /* EEAR */
        return (env->eear);

    case TO_SPR(0, 64): /* ESR */
        return (env->esr);

    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
        idx = spr - TO_SPR(1, 512);
        return (env->tlb->dtlb[0][idx].mr);

    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
        idx = spr - TO_SPR(1, 640);
        return (env->tlb->dtlb[0][idx].tr);

    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
        break;

    case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
        idx = spr - TO_SPR(2, 512);
        return (env->tlb->itlb[0][idx].mr);

    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
        idx = spr - TO_SPR(2, 640);
        return (env->tlb->itlb[0][idx].tr);

    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
        break;

    case TO_SPR(9, 0):  /* PICMR */
        return (env->picmr);

    case TO_SPR(9, 2):  /* PICSR */
        return (env->picsr);

    case TO_SPR(10, 0): /* TTMR */
        return (env->ttmr);

    case TO_SPR(10, 1): /* TTCR */
        return cpu_openrisc_get_count(env);

    default:
        break;
    }
#endif
    return rd;
}


    case 0x2d:   /*l.mfspr*/
        LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
        {
            TCGv_i32 ti = tcg_const_i32(I16);
            gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
            tcg_temp_free_i32(ti);
        }
        break;

    case 0x30:  /*l.mtspr*/
        LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
        {
            TCGv_i32 im = tcg_const_i32(tmp);
            gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
            tcg_temp_free_i32(im);
        }
        break;


On Tue, Jun 19, 2012 at 2:58 AM, Blue Swirl <blauwirbel@gmail.com> wrote:
> On Mon, Jun 18, 2012 at 1:03 AM, Jia Liu <proljc@gmail.com> wrote:
>> Add OpenRISC system instruction support.
>>
>> Signed-off-by: Jia Liu <proljc@gmail.com>
>> ---
>>  target-openrisc/Makefile.objs |    3 +-
>>  target-openrisc/helper.h      |    4 +
>>  target-openrisc/sys_helper.c  |  233 +++++++++++++++++++++++++++++++++++++++++
>>  target-openrisc/translate.c   |   20 ++++
>>  4 files changed, 259 insertions(+), 1 deletion(-)
>>  create mode 100644 target-openrisc/sys_helper.c
>>
>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
>> index 0d72c33..9d13a5d 100644
>> --- a/target-openrisc/Makefile.objs
>> +++ b/target-openrisc/Makefile.objs
>> @@ -1,3 +1,4 @@
>>  obj-$(CONFIG_SOFTMMU) += machine.o
>>  obj-y += cpu.o excp.o intrpt.o mmu.o translate.o
>> -obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o mmu_helper.o
>> +obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o \
>> +         mmu_helper.o sys_helper.o
>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
>> index 60870f2..04c63c5 100644
>> --- a/target-openrisc/helper.h
>> +++ b/target-openrisc/helper.h
>> @@ -62,4 +62,8 @@ DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
>>  /* interrupt */
>>  DEF_HELPER_FLAGS_1(rfe, 0, void, env)
>>
>> +/* sys */
>> +DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
>> +DEF_HELPER_FLAGS_4(mfspr, 0, void, env, tl, tl, tl)
>> +
>>  #include "def-helper.h"
>> diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
>> new file mode 100644
>> index 0000000..f1e4314
>> --- /dev/null
>> +++ b/target-openrisc/sys_helper.c
>> @@ -0,0 +1,233 @@
>> +/*
>> + *  OpenRISC system instructions helper routines
>> + *
>> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>> + *                          Zhizhou Zhang <etouzh@gmail.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "cpu.h"
>> +#include "helper.h"
>> +
>> +#define TO_SPR(group, number) (((group) << 11) + (number))
>> +
>> +void HELPER(mtspr)(CPUOpenRISCState * env,
>> +                   target_ulong ra, target_ulong rb, target_ulong offset)
>> +{
>> +#if !defined(CONFIG_USER_ONLY)
>> +    int spr = (ra | offset);
>> +    int idx;
>> +
>> +    switch (spr) {
>> +    case TO_SPR(0, 0): /* VR */
>> +        env->vr = rb;
>> +        break;
>> +
>> +    case TO_SPR(0, 16): /* NPC */
>> +        env->npc = rb;
>> +        break;
>> +
>> +    case TO_SPR(0, 17): /* SR */
>> +        if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
>> +            (rb & (SR_IME | SR_DME | SR_SM))) {
>> +            tlb_flush(env, 1);
>> +        }
>> +        env->sr = rb;
>> +        env->sr |= SR_FO;      /* FO is const equal to 1 */
>> +        if (env->sr & SR_DME) {
>> +            env->tlb->map_address_data = &get_phys_data;
>> +        } else {
>> +            env->tlb->map_address_data = &get_phys_nommu;
>> +        }
>> +
>> +        if (env->sr & SR_IME) {
>> +            env->tlb->map_address_code = &get_phys_code;
>> +        } else {
>> +            env->tlb->map_address_code = &get_phys_nommu;
>> +        }
>> +        break;
>> +
>> +    case TO_SPR(0, 18): /* PPC */
>> +        env->ppc = rb;
>> +        break;
>> +
>> +    case TO_SPR(0, 32): /* EPCR */
>> +        env->epcr = rb;
>> +        break;
>> +
>> +    case TO_SPR(0, 48): /* EEAR */
>> +        env->eear = rb;
>> +        break;
>> +
>> +    case TO_SPR(0, 64): /* ESR */
>> +        env->esr = rb;
>> +        break;
>> +    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>> +        idx = spr - TO_SPR(1, 512);
>> +        if (!(rb & 1)) {
>> +            tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
>> +        }
>> +        env->tlb->dtlb[0][idx].mr = rb;
>> +        break;
>> +
>> +    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>> +        idx = spr - TO_SPR(1, 640);
>> +        env->tlb->dtlb[0][idx].tr = rb;
>> +        break;
>> +    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>> +    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>> +    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>> +    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>> +    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>> +    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>> +        break;
>> +    case TO_SPR(2, 512) ... TO_SPR(2, 639):   /* ITLBW0MR 0-127 */
>> +        idx = spr - TO_SPR(2, 512);
>> +        if (!(rb & 1)) {
>> +            tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
>> +        }
>> +        env->tlb->itlb[0][idx].mr = rb;
>> +        break;
>> +
>> +    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>> +        idx = spr - TO_SPR(2, 640);
>> +        env->tlb->itlb[0][idx].tr = rb;
>> +        break;
>> +    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>> +    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>> +    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>> +    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>> +        break;
>> +    case TO_SPR(9, 0):  /* PICMR */
>> +        cpu_openrisc_store_picmr(env, rb);
>> +        break;
>> +    case TO_SPR(9, 2):  /* PICSR */
>> +        cpu_openrisc_store_picsr(env, rb);
>> +        break;
>> +    case TO_SPR(10, 0): /* TTMR */
>> +        cpu_openrisc_store_compare(env, rb);
>> +        break;
>> +    case TO_SPR(10, 1): /* TTCR */
>> +        cpu_openrisc_store_count(env, rb);
>> +        break;
>> +    default:
>> +        break;
>> +    }
>> +#endif
>> +}
>> +
>> +void HELPER(mfspr)(CPUOpenRISCState * env,
>> +                   target_ulong rd, target_ulong ra, uint32_t offset)
>> +{
>> +#if !defined(CONFIG_USER_ONLY)
>> +    int spr = env->gpr[ra] | offset;
>
> [1]
>
>> +    int idx;
>> +
>> +    switch (spr) {
>> +    case TO_SPR(0, 0): /* VR */
>> +        env->gpr[rd] = (env->vr & SPR_VR);
>> +        break;
>> +
>> +    case TO_SPR(0, 1): /* UPR */
>> +        env->gpr[rd] = env->upr;    /* TT, DM, IM, UP present */
>> +        break;
>> +
>> +    case TO_SPR(0, 2): /* CPUCFGR */
>> +        env->gpr[rd] = env->cpucfgr;
>> +        break;
>> +
>> +    case TO_SPR(0, 3): /* DMMUCFGR */
>> +        env->gpr[rd] = env->dmmucfgr;    /* 1Way, 64 entries */
>> +        break;
>> +    case TO_SPR(0, 4): /* IMMUCFGR */
>> +        env->gpr[rd] = env->immucfgr;
>> +        break;
>> +
>> +    case TO_SPR(0, 16): /* NPC */
>> +        env->gpr[rd] = env->npc;
>> +        break;
>> +
>> +    case TO_SPR(0, 17): /* SR */
>> +        env->gpr[rd] = env->sr;
>> +        break;
>> +
>> +    case TO_SPR(0, 18): /* PPC */
>> +        env->gpr[rd] = env->ppc;
>> +        break;
>> +
>> +    case TO_SPR(0, 32): /* EPCR */
>> +        env->gpr[rd] = env->epcr;
>> +        break;
>> +
>> +    case TO_SPR(0, 48): /* EEAR */
>> +        env->gpr[rd] = env->eear;
>> +        break;
>> +
>> +    case TO_SPR(0, 64): /* ESR */
>> +        env->gpr[rd] = env->esr;
>> +        break;
>> +
>> +    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>> +        idx = spr - TO_SPR(1, 512);
>> +        env->gpr[rd] = env->tlb->dtlb[0][idx].mr;
>> +        break;
>> +
>> +    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>> +        idx = spr - TO_SPR(1, 640);
>> +        env->gpr[rd] = env->tlb->dtlb[0][idx].tr;
>> +        break;
>> +    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>> +    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>> +    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>> +    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>> +    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>> +    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>> +        break;
>> +
>> +    case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
>> +        idx = spr - TO_SPR(2, 512);
>> +        env->gpr[rd] = env->tlb->itlb[0][idx].mr;
>> +        break;
>> +
>> +    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>> +        idx = spr - TO_SPR(2, 640);
>> +        env->gpr[rd] = env->tlb->itlb[0][idx].tr;
>> +        break;
>> +    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>> +    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>> +    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>> +    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>> +        break;
>> +    case TO_SPR(9, 0):  /* PICMR */
>> +        env->gpr[rd] = env->picmr;
>> +        break;
>> +    case TO_SPR(9, 2):  /* PICSR */
>> +        env->gpr[rd] = env->picsr;
>> +        break;
>> +    case TO_SPR(10, 0): /* TTMR */
>> +        env->gpr[rd] = env->ttmr;
>> +        break;
>> +    case TO_SPR(10, 1): /* TTCR */
>> +        env->gpr[rd] = cpu_openrisc_get_count(env);
>
> [2]
>
>> +        break;
>> +    default:
>> +        break;
>> +    }
>> +#endif
>> +}
>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
>> index d4f894b..11eb0a5 100644
>> --- a/target-openrisc/translate.c
>> +++ b/target-openrisc/translate.c
>> @@ -1241,10 +1241,30 @@ static void dec_misc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
>>
>>     case 0x2d:   /*l.mfspr*/
>>         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>> +        {
>> +            TCGv_i32 ti = tcg_const_i32(I16);
>> +            TCGv td = tcg_const_tl(rd);
>> +            TCGv ta = tcg_const_tl(ra);
>> +            gen_helper_mfspr(cpu_env, td, ta, ti);
>
> The helper should a return target_ulong, so the line would become
> gen_helper_mfspr(cpu_R[rd], cpu_env, td, cpu_R[ra], ti);
>
> Then the register moves inside the mfspr helper could be avoided:
> [1]
>> +    int spr = env->gpr[ra] | offset;
> int spr = ra | offset;
>
> As an example [2]:
>> +        env->gpr[rd] = cpu_openrisc_get_count(env);
> return cpu_openrisc_get_count(env);
>
>> +            tcg_temp_free_i32(ti);
>> +            tcg_temp_free(td);
>> +            tcg_temp_free(ta);
>> +        }
>
> Also here you could try later to avoid to compile sys_helper.c for
> user emulator by surrounding the previous block by #ifndef
> CONFIG_USER_ONLY/#endif (ditto for mtspr).
>
>>         break;
>>
>>     case 0x30:  /*l.mtspr*/
>>         LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>> +        {
>> +            TCGv_i32 im = tcg_const_i32(tmp);
>> +            TCGv ta = tcg_temp_new();
>> +            TCGv tb = tcg_temp_new();
>> +            tcg_gen_mov_tl(ta, cpu_R[ra]);
>> +            tcg_gen_mov_tl(tb, cpu_R[rb]);
>> +            gen_helper_mtspr(cpu_env, ta, tb, im);
>
> Simply
> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>
>> +            tcg_temp_free_i32(im);
>> +            tcg_temp_free(ta);
>> +            tcg_temp_free(tb);
>> +        }
>>         break;
>>
>>     case 0x34:   /*l.sd*/
>> --
>> 1.7.9.5
>>
>>

Regards,
Jia.
Blue Swirl June 19, 2012, 6:25 p.m. UTC | #3
On Tue, Jun 19, 2012 at 8:02 AM, Jia Liu <proljc@gmail.com> wrote:
> Hi Blue,
>
> Thank you for review.
> Is this code OK?
>
> void HELPER(mtspr)(CPUOpenRISCState * env,
>                   target_ulong ra, target_ulong rb, target_ulong offset)
> {
> #ifndef CONFIG_USER_ONLY
>    int spr = (ra | offset);
>    int idx;
>
>    switch (spr) {
>    case TO_SPR(0, 0): /* VR */
>        env->vr = rb;
>        break;
>
>    case TO_SPR(0, 16): /* NPC */
>        env->npc = rb;
>        break;
>
>    case TO_SPR(0, 17): /* SR */
>        if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
>            (rb & (SR_IME | SR_DME | SR_SM))) {
>            tlb_flush(env, 1);
>        }
>        env->sr = rb;
>        env->sr |= SR_FO;      /* FO is const equal to 1 */
>        if (env->sr & SR_DME) {
>            env->tlb->map_address_data = &get_phys_data;
>        } else {
>            env->tlb->map_address_data = &get_phys_nommu;
>        }
>
>        if (env->sr & SR_IME) {
>            env->tlb->map_address_code = &get_phys_code;
>        } else {
>            env->tlb->map_address_code = &get_phys_nommu;
>        }
>        break;
>
>    case TO_SPR(0, 18): /* PPC */
>        env->ppc = rb;
>        break;
>
>    case TO_SPR(0, 32): /* EPCR */
>        env->epcr = rb;
>        break;
>
>    case TO_SPR(0, 48): /* EEAR */
>        env->eear = rb;
>        break;
>
>    case TO_SPR(0, 64): /* ESR */
>        env->esr = rb;
>        break;
>    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>        idx = spr - TO_SPR(1, 512);
>        if (!(rb & 1)) {
>            tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
>        }
>        env->tlb->dtlb[0][idx].mr = rb;
>        break;
>
>    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>        idx = spr - TO_SPR(1, 640);
>        env->tlb->dtlb[0][idx].tr = rb;
>        break;
>    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>        break;
>    case TO_SPR(2, 512) ... TO_SPR(2, 639):   /* ITLBW0MR 0-127 */
>        idx = spr - TO_SPR(2, 512);
>        if (!(rb & 1)) {
>            tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
>        }
>        env->tlb->itlb[0][idx].mr = rb;
>        break;
>
>    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>        idx = spr - TO_SPR(2, 640);
>        env->tlb->itlb[0][idx].tr = rb;
>        break;
>    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>        break;
>    case TO_SPR(9, 0):  /* PICMR */
>        cpu_openrisc_store_picmr(env, rb);
>        break;
>    case TO_SPR(9, 2):  /* PICSR */
>        cpu_openrisc_store_picsr(env, rb);
>        break;
>    case TO_SPR(10, 0): /* TTMR */
>        cpu_openrisc_store_compare(env, rb);
>        break;
>    case TO_SPR(10, 1): /* TTCR */
>        cpu_openrisc_store_count(env, rb);
>        break;
>    default:
>        break;
>    }
> #endif
> }

OK

>
> target_ulong HELPER(mfspr)(CPUOpenRISCState * env,
>                           target_ulong rd, target_ulong ra, uint32_t offset)
> {
> #ifndef CONFIG_USER_ONLY
>    int spr = (ra | offset);
>    int idx;
>
>    switch (spr) {
>    case TO_SPR(0, 0): /* VR */
>        return (env->vr & SPR_VR);

Parentheses are not necessary.

>
>    case TO_SPR(0, 1): /* UPR */
>        return (env->upr);    /* TT, DM, IM, UP present */
>
>    case TO_SPR(0, 2): /* CPUCFGR */
>        return (env->cpucfgr);
>
>    case TO_SPR(0, 3): /* DMMUCFGR */
>        return (env->dmmucfgr);    /* 1Way, 64 entries */
>
>    case TO_SPR(0, 4): /* IMMUCFGR */
>        return (env->immucfgr);
>
>    case TO_SPR(0, 16): /* NPC */
>        return (env->npc);
>
>    case TO_SPR(0, 17): /* SR */
>        return (env->sr);
>
>    case TO_SPR(0, 18): /* PPC */
>        return (env->ppc);
>
>    case TO_SPR(0, 32): /* EPCR */
>        return (env->epcr);
>
>    case TO_SPR(0, 48): /* EEAR */
>        return (env->eear);
>
>    case TO_SPR(0, 64): /* ESR */
>        return (env->esr);
>
>    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>        idx = spr - TO_SPR(1, 512);
>        return (env->tlb->dtlb[0][idx].mr);
>
>    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>        idx = spr - TO_SPR(1, 640);
>        return (env->tlb->dtlb[0][idx].tr);
>
>    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>        break;
>
>    case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
>        idx = spr - TO_SPR(2, 512);
>        return (env->tlb->itlb[0][idx].mr);
>
>    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>        idx = spr - TO_SPR(2, 640);
>        return (env->tlb->itlb[0][idx].tr);
>
>    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>        break;
>
>    case TO_SPR(9, 0):  /* PICMR */
>        return (env->picmr);
>
>    case TO_SPR(9, 2):  /* PICSR */
>        return (env->picsr);
>
>    case TO_SPR(10, 0): /* TTMR */
>        return (env->ttmr);
>
>    case TO_SPR(10, 1): /* TTCR */
>        return cpu_openrisc_get_count(env);
>
>    default:
>        break;
>    }
> #endif
>    return rd;

Is this correct, maybe 0 would be a nice value for unknown SPRs, or is
rd the default value?

If you later need to add tracepoints (or debug printfs) for the return
value, it may be useful to structure the code like this:
target_ulong ret = 0;

switch() {
case x:
  ret = y;
  break;
case z:
  ret = 42;
  break;
...
}
/* later something like trace_spr_read(ret); */
return ret;

> }
>
>
>    case 0x2d:   /*l.mfspr*/
>        LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>        {
>            TCGv_i32 ti = tcg_const_i32(I16);
>            gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>            tcg_temp_free_i32(ti);
>        }
>        break;
>
>    case 0x30:  /*l.mtspr*/
>        LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>        {
>            TCGv_i32 im = tcg_const_i32(tmp);
>            gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>            tcg_temp_free_i32(im);
>        }
>        break;

OK

>
>
> On Tue, Jun 19, 2012 at 2:58 AM, Blue Swirl <blauwirbel@gmail.com> wrote:
>> On Mon, Jun 18, 2012 at 1:03 AM, Jia Liu <proljc@gmail.com> wrote:
>>> Add OpenRISC system instruction support.
>>>
>>> Signed-off-by: Jia Liu <proljc@gmail.com>
>>> ---
>>>  target-openrisc/Makefile.objs |    3 +-
>>>  target-openrisc/helper.h      |    4 +
>>>  target-openrisc/sys_helper.c  |  233 +++++++++++++++++++++++++++++++++++++++++
>>>  target-openrisc/translate.c   |   20 ++++
>>>  4 files changed, 259 insertions(+), 1 deletion(-)
>>>  create mode 100644 target-openrisc/sys_helper.c
>>>
>>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
>>> index 0d72c33..9d13a5d 100644
>>> --- a/target-openrisc/Makefile.objs
>>> +++ b/target-openrisc/Makefile.objs
>>> @@ -1,3 +1,4 @@
>>>  obj-$(CONFIG_SOFTMMU) += machine.o
>>>  obj-y += cpu.o excp.o intrpt.o mmu.o translate.o
>>> -obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o mmu_helper.o
>>> +obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o \
>>> +         mmu_helper.o sys_helper.o
>>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
>>> index 60870f2..04c63c5 100644
>>> --- a/target-openrisc/helper.h
>>> +++ b/target-openrisc/helper.h
>>> @@ -62,4 +62,8 @@ DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
>>>  /* interrupt */
>>>  DEF_HELPER_FLAGS_1(rfe, 0, void, env)
>>>
>>> +/* sys */
>>> +DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
>>> +DEF_HELPER_FLAGS_4(mfspr, 0, void, env, tl, tl, tl)
>>> +
>>>  #include "def-helper.h"
>>> diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
>>> new file mode 100644
>>> index 0000000..f1e4314
>>> --- /dev/null
>>> +++ b/target-openrisc/sys_helper.c
>>> @@ -0,0 +1,233 @@
>>> +/*
>>> + *  OpenRISC system instructions helper routines
>>> + *
>>> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>>> + *                          Zhizhou Zhang <etouzh@gmail.com>
>>> + *
>>> + * This library is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU Lesser General Public
>>> + * License as published by the Free Software Foundation; either
>>> + * version 2 of the License, or (at your option) any later version.
>>> + *
>>> + * This library is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> + * Lesser General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU Lesser General Public
>>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include "cpu.h"
>>> +#include "helper.h"
>>> +
>>> +#define TO_SPR(group, number) (((group) << 11) + (number))
>>> +
>>> +void HELPER(mtspr)(CPUOpenRISCState * env,
>>> +                   target_ulong ra, target_ulong rb, target_ulong offset)
>>> +{
>>> +#if !defined(CONFIG_USER_ONLY)
>>> +    int spr = (ra | offset);
>>> +    int idx;
>>> +
>>> +    switch (spr) {
>>> +    case TO_SPR(0, 0): /* VR */
>>> +        env->vr = rb;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 16): /* NPC */
>>> +        env->npc = rb;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 17): /* SR */
>>> +        if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
>>> +            (rb & (SR_IME | SR_DME | SR_SM))) {
>>> +            tlb_flush(env, 1);
>>> +        }
>>> +        env->sr = rb;
>>> +        env->sr |= SR_FO;      /* FO is const equal to 1 */
>>> +        if (env->sr & SR_DME) {
>>> +            env->tlb->map_address_data = &get_phys_data;
>>> +        } else {
>>> +            env->tlb->map_address_data = &get_phys_nommu;
>>> +        }
>>> +
>>> +        if (env->sr & SR_IME) {
>>> +            env->tlb->map_address_code = &get_phys_code;
>>> +        } else {
>>> +            env->tlb->map_address_code = &get_phys_nommu;
>>> +        }
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 18): /* PPC */
>>> +        env->ppc = rb;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 32): /* EPCR */
>>> +        env->epcr = rb;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 48): /* EEAR */
>>> +        env->eear = rb;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 64): /* ESR */
>>> +        env->esr = rb;
>>> +        break;
>>> +    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>> +        idx = spr - TO_SPR(1, 512);
>>> +        if (!(rb & 1)) {
>>> +            tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
>>> +        }
>>> +        env->tlb->dtlb[0][idx].mr = rb;
>>> +        break;
>>> +
>>> +    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>> +        idx = spr - TO_SPR(1, 640);
>>> +        env->tlb->dtlb[0][idx].tr = rb;
>>> +        break;
>>> +    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>>> +    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>>> +    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>>> +    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>>> +    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>>> +    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>>> +        break;
>>> +    case TO_SPR(2, 512) ... TO_SPR(2, 639):   /* ITLBW0MR 0-127 */
>>> +        idx = spr - TO_SPR(2, 512);
>>> +        if (!(rb & 1)) {
>>> +            tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
>>> +        }
>>> +        env->tlb->itlb[0][idx].mr = rb;
>>> +        break;
>>> +
>>> +    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>> +        idx = spr - TO_SPR(2, 640);
>>> +        env->tlb->itlb[0][idx].tr = rb;
>>> +        break;
>>> +    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>>> +    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>>> +    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>>> +    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>>> +        break;
>>> +    case TO_SPR(9, 0):  /* PICMR */
>>> +        cpu_openrisc_store_picmr(env, rb);
>>> +        break;
>>> +    case TO_SPR(9, 2):  /* PICSR */
>>> +        cpu_openrisc_store_picsr(env, rb);
>>> +        break;
>>> +    case TO_SPR(10, 0): /* TTMR */
>>> +        cpu_openrisc_store_compare(env, rb);
>>> +        break;
>>> +    case TO_SPR(10, 1): /* TTCR */
>>> +        cpu_openrisc_store_count(env, rb);
>>> +        break;
>>> +    default:
>>> +        break;
>>> +    }
>>> +#endif
>>> +}
>>> +
>>> +void HELPER(mfspr)(CPUOpenRISCState * env,
>>> +                   target_ulong rd, target_ulong ra, uint32_t offset)
>>> +{
>>> +#if !defined(CONFIG_USER_ONLY)
>>> +    int spr = env->gpr[ra] | offset;
>>
>> [1]
>>
>>> +    int idx;
>>> +
>>> +    switch (spr) {
>>> +    case TO_SPR(0, 0): /* VR */
>>> +        env->gpr[rd] = (env->vr & SPR_VR);
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 1): /* UPR */
>>> +        env->gpr[rd] = env->upr;    /* TT, DM, IM, UP present */
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 2): /* CPUCFGR */
>>> +        env->gpr[rd] = env->cpucfgr;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 3): /* DMMUCFGR */
>>> +        env->gpr[rd] = env->dmmucfgr;    /* 1Way, 64 entries */
>>> +        break;
>>> +    case TO_SPR(0, 4): /* IMMUCFGR */
>>> +        env->gpr[rd] = env->immucfgr;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 16): /* NPC */
>>> +        env->gpr[rd] = env->npc;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 17): /* SR */
>>> +        env->gpr[rd] = env->sr;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 18): /* PPC */
>>> +        env->gpr[rd] = env->ppc;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 32): /* EPCR */
>>> +        env->gpr[rd] = env->epcr;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 48): /* EEAR */
>>> +        env->gpr[rd] = env->eear;
>>> +        break;
>>> +
>>> +    case TO_SPR(0, 64): /* ESR */
>>> +        env->gpr[rd] = env->esr;
>>> +        break;
>>> +
>>> +    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>> +        idx = spr - TO_SPR(1, 512);
>>> +        env->gpr[rd] = env->tlb->dtlb[0][idx].mr;
>>> +        break;
>>> +
>>> +    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>> +        idx = spr - TO_SPR(1, 640);
>>> +        env->gpr[rd] = env->tlb->dtlb[0][idx].tr;
>>> +        break;
>>> +    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>>> +    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>>> +    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>>> +    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>>> +    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>>> +    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>>> +        break;
>>> +
>>> +    case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
>>> +        idx = spr - TO_SPR(2, 512);
>>> +        env->gpr[rd] = env->tlb->itlb[0][idx].mr;
>>> +        break;
>>> +
>>> +    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>> +        idx = spr - TO_SPR(2, 640);
>>> +        env->gpr[rd] = env->tlb->itlb[0][idx].tr;
>>> +        break;
>>> +    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>>> +    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>>> +    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>>> +    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>>> +        break;
>>> +    case TO_SPR(9, 0):  /* PICMR */
>>> +        env->gpr[rd] = env->picmr;
>>> +        break;
>>> +    case TO_SPR(9, 2):  /* PICSR */
>>> +        env->gpr[rd] = env->picsr;
>>> +        break;
>>> +    case TO_SPR(10, 0): /* TTMR */
>>> +        env->gpr[rd] = env->ttmr;
>>> +        break;
>>> +    case TO_SPR(10, 1): /* TTCR */
>>> +        env->gpr[rd] = cpu_openrisc_get_count(env);
>>
>> [2]
>>
>>> +        break;
>>> +    default:
>>> +        break;
>>> +    }
>>> +#endif
>>> +}
>>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
>>> index d4f894b..11eb0a5 100644
>>> --- a/target-openrisc/translate.c
>>> +++ b/target-openrisc/translate.c
>>> @@ -1241,10 +1241,30 @@ static void dec_misc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
>>>
>>>     case 0x2d:   /*l.mfspr*/
>>>         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>> +        {
>>> +            TCGv_i32 ti = tcg_const_i32(I16);
>>> +            TCGv td = tcg_const_tl(rd);
>>> +            TCGv ta = tcg_const_tl(ra);
>>> +            gen_helper_mfspr(cpu_env, td, ta, ti);
>>
>> The helper should a return target_ulong, so the line would become
>> gen_helper_mfspr(cpu_R[rd], cpu_env, td, cpu_R[ra], ti);
>>
>> Then the register moves inside the mfspr helper could be avoided:
>> [1]
>>> +    int spr = env->gpr[ra] | offset;
>> int spr = ra | offset;
>>
>> As an example [2]:
>>> +        env->gpr[rd] = cpu_openrisc_get_count(env);
>> return cpu_openrisc_get_count(env);
>>
>>> +            tcg_temp_free_i32(ti);
>>> +            tcg_temp_free(td);
>>> +            tcg_temp_free(ta);
>>> +        }
>>
>> Also here you could try later to avoid to compile sys_helper.c for
>> user emulator by surrounding the previous block by #ifndef
>> CONFIG_USER_ONLY/#endif (ditto for mtspr).
>>
>>>         break;
>>>
>>>     case 0x30:  /*l.mtspr*/
>>>         LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>> +        {
>>> +            TCGv_i32 im = tcg_const_i32(tmp);
>>> +            TCGv ta = tcg_temp_new();
>>> +            TCGv tb = tcg_temp_new();
>>> +            tcg_gen_mov_tl(ta, cpu_R[ra]);
>>> +            tcg_gen_mov_tl(tb, cpu_R[rb]);
>>> +            gen_helper_mtspr(cpu_env, ta, tb, im);
>>
>> Simply
>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>
>>> +            tcg_temp_free_i32(im);
>>> +            tcg_temp_free(ta);
>>> +            tcg_temp_free(tb);
>>> +        }
>>>         break;
>>>
>>>     case 0x34:   /*l.sd*/
>>> --
>>> 1.7.9.5
>>>
>>>
>
> Regards,
> Jia.
Jia Liu June 20, 2012, 12:17 a.m. UTC | #4
Hi Blue,

On Wed, Jun 20, 2012 at 2:25 AM, Blue Swirl <blauwirbel@gmail.com> wrote:
> On Tue, Jun 19, 2012 at 8:02 AM, Jia Liu <proljc@gmail.com> wrote:
>> Hi Blue,
>>
>> Thank you for review.
>> Is this code OK?
>>
>> void HELPER(mtspr)(CPUOpenRISCState * env,
>>                   target_ulong ra, target_ulong rb, target_ulong offset)
>> {
>> #ifndef CONFIG_USER_ONLY
>>    int spr = (ra | offset);
>>    int idx;
>>
>>    switch (spr) {
>>    case TO_SPR(0, 0): /* VR */
>>        env->vr = rb;
>>        break;
>>
>>    case TO_SPR(0, 16): /* NPC */
>>        env->npc = rb;
>>        break;
>>
>>    case TO_SPR(0, 17): /* SR */
>>        if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
>>            (rb & (SR_IME | SR_DME | SR_SM))) {
>>            tlb_flush(env, 1);
>>        }
>>        env->sr = rb;
>>        env->sr |= SR_FO;      /* FO is const equal to 1 */
>>        if (env->sr & SR_DME) {
>>            env->tlb->map_address_data = &get_phys_data;
>>        } else {
>>            env->tlb->map_address_data = &get_phys_nommu;
>>        }
>>
>>        if (env->sr & SR_IME) {
>>            env->tlb->map_address_code = &get_phys_code;
>>        } else {
>>            env->tlb->map_address_code = &get_phys_nommu;
>>        }
>>        break;
>>
>>    case TO_SPR(0, 18): /* PPC */
>>        env->ppc = rb;
>>        break;
>>
>>    case TO_SPR(0, 32): /* EPCR */
>>        env->epcr = rb;
>>        break;
>>
>>    case TO_SPR(0, 48): /* EEAR */
>>        env->eear = rb;
>>        break;
>>
>>    case TO_SPR(0, 64): /* ESR */
>>        env->esr = rb;
>>        break;
>>    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>        idx = spr - TO_SPR(1, 512);
>>        if (!(rb & 1)) {
>>            tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
>>        }
>>        env->tlb->dtlb[0][idx].mr = rb;
>>        break;
>>
>>    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>        idx = spr - TO_SPR(1, 640);
>>        env->tlb->dtlb[0][idx].tr = rb;
>>        break;
>>    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>>    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>>    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>>    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>>    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>>    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>>        break;
>>    case TO_SPR(2, 512) ... TO_SPR(2, 639):   /* ITLBW0MR 0-127 */
>>        idx = spr - TO_SPR(2, 512);
>>        if (!(rb & 1)) {
>>            tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
>>        }
>>        env->tlb->itlb[0][idx].mr = rb;
>>        break;
>>
>>    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>        idx = spr - TO_SPR(2, 640);
>>        env->tlb->itlb[0][idx].tr = rb;
>>        break;
>>    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>>    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>>    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>>    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>>        break;
>>    case TO_SPR(9, 0):  /* PICMR */
>>        cpu_openrisc_store_picmr(env, rb);
>>        break;
>>    case TO_SPR(9, 2):  /* PICSR */
>>        cpu_openrisc_store_picsr(env, rb);
>>        break;
>>    case TO_SPR(10, 0): /* TTMR */
>>        cpu_openrisc_store_compare(env, rb);
>>        break;
>>    case TO_SPR(10, 1): /* TTCR */
>>        cpu_openrisc_store_count(env, rb);
>>        break;
>>    default:
>>        break;
>>    }
>> #endif
>> }
>
> OK
>
>>
>> target_ulong HELPER(mfspr)(CPUOpenRISCState * env,
>>                           target_ulong rd, target_ulong ra, uint32_t offset)
>> {
>> #ifndef CONFIG_USER_ONLY
>>    int spr = (ra | offset);
>>    int idx;
>>
>>    switch (spr) {
>>    case TO_SPR(0, 0): /* VR */
>>        return (env->vr & SPR_VR);
>
> Parentheses are not necessary.
>

all deleted. Thanks.

>>
>>    case TO_SPR(0, 1): /* UPR */
>>        return (env->upr);    /* TT, DM, IM, UP present */
>>
>>    case TO_SPR(0, 2): /* CPUCFGR */
>>        return (env->cpucfgr);
>>
>>    case TO_SPR(0, 3): /* DMMUCFGR */
>>        return (env->dmmucfgr);    /* 1Way, 64 entries */
>>
>>    case TO_SPR(0, 4): /* IMMUCFGR */
>>        return (env->immucfgr);
>>
>>    case TO_SPR(0, 16): /* NPC */
>>        return (env->npc);
>>
>>    case TO_SPR(0, 17): /* SR */
>>        return (env->sr);
>>
>>    case TO_SPR(0, 18): /* PPC */
>>        return (env->ppc);
>>
>>    case TO_SPR(0, 32): /* EPCR */
>>        return (env->epcr);
>>
>>    case TO_SPR(0, 48): /* EEAR */
>>        return (env->eear);
>>
>>    case TO_SPR(0, 64): /* ESR */
>>        return (env->esr);
>>
>>    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>        idx = spr - TO_SPR(1, 512);
>>        return (env->tlb->dtlb[0][idx].mr);
>>
>>    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>        idx = spr - TO_SPR(1, 640);
>>        return (env->tlb->dtlb[0][idx].tr);
>>
>>    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>>    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>>    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>>    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>>    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>>    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>>        break;
>>
>>    case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
>>        idx = spr - TO_SPR(2, 512);
>>        return (env->tlb->itlb[0][idx].mr);
>>
>>    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>        idx = spr - TO_SPR(2, 640);
>>        return (env->tlb->itlb[0][idx].tr);
>>
>>    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>>    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>>    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>>    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>>        break;
>>
>>    case TO_SPR(9, 0):  /* PICMR */
>>        return (env->picmr);
>>
>>    case TO_SPR(9, 2):  /* PICSR */
>>        return (env->picsr);
>>
>>    case TO_SPR(10, 0): /* TTMR */
>>        return (env->ttmr);
>>
>>    case TO_SPR(10, 1): /* TTCR */
>>        return cpu_openrisc_get_count(env);
>>
>>    default:
>>        break;
>>    }
>> #endif
>>    return rd;
>
> Is this correct, maybe 0 would be a nice value for unknown SPRs, or is
> rd the default value?
>

It is rd.
for rd is passed in, if rd unchanged, just keep it back.

But, I added a comment here, so, it now look like

    /* for rd is passed in, if rd unchanged, just keep it back.  */
    return rd;


> If you later need to add tracepoints (or debug printfs) for the return
> value, it may be useful to structure the code like this:
> target_ulong ret = 0;
>
> switch() {
> case x:
>  ret = y;
>  break;
> case z:
>  ret = 42;
>  break;
> ...
> }
> /* later something like trace_spr_read(ret); */
> return ret;
>

I've added this in a comment for the future use, thank you very much.

>> }
>>
>>
>>    case 0x2d:   /*l.mfspr*/
>>        LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>        {
>>            TCGv_i32 ti = tcg_const_i32(I16);
>>            gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti);
>>            tcg_temp_free_i32(ti);
>>        }
>>        break;
>>
>>    case 0x30:  /*l.mtspr*/
>>        LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>        {
>>            TCGv_i32 im = tcg_const_i32(tmp);
>>            gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>            tcg_temp_free_i32(im);
>>        }
>>        break;
>
> OK
>
>>
>>
>> On Tue, Jun 19, 2012 at 2:58 AM, Blue Swirl <blauwirbel@gmail.com> wrote:
>>> On Mon, Jun 18, 2012 at 1:03 AM, Jia Liu <proljc@gmail.com> wrote:
>>>> Add OpenRISC system instruction support.
>>>>
>>>> Signed-off-by: Jia Liu <proljc@gmail.com>
>>>> ---
>>>>  target-openrisc/Makefile.objs |    3 +-
>>>>  target-openrisc/helper.h      |    4 +
>>>>  target-openrisc/sys_helper.c  |  233 +++++++++++++++++++++++++++++++++++++++++
>>>>  target-openrisc/translate.c   |   20 ++++
>>>>  4 files changed, 259 insertions(+), 1 deletion(-)
>>>>  create mode 100644 target-openrisc/sys_helper.c
>>>>
>>>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
>>>> index 0d72c33..9d13a5d 100644
>>>> --- a/target-openrisc/Makefile.objs
>>>> +++ b/target-openrisc/Makefile.objs
>>>> @@ -1,3 +1,4 @@
>>>>  obj-$(CONFIG_SOFTMMU) += machine.o
>>>>  obj-y += cpu.o excp.o intrpt.o mmu.o translate.o
>>>> -obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o mmu_helper.o
>>>> +obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o \
>>>> +         mmu_helper.o sys_helper.o
>>>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
>>>> index 60870f2..04c63c5 100644
>>>> --- a/target-openrisc/helper.h
>>>> +++ b/target-openrisc/helper.h
>>>> @@ -62,4 +62,8 @@ DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
>>>>  /* interrupt */
>>>>  DEF_HELPER_FLAGS_1(rfe, 0, void, env)
>>>>
>>>> +/* sys */
>>>> +DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
>>>> +DEF_HELPER_FLAGS_4(mfspr, 0, void, env, tl, tl, tl)
>>>> +
>>>>  #include "def-helper.h"
>>>> diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
>>>> new file mode 100644
>>>> index 0000000..f1e4314
>>>> --- /dev/null
>>>> +++ b/target-openrisc/sys_helper.c
>>>> @@ -0,0 +1,233 @@
>>>> +/*
>>>> + *  OpenRISC system instructions helper routines
>>>> + *
>>>> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>>>> + *                          Zhizhou Zhang <etouzh@gmail.com>
>>>> + *
>>>> + * This library is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU Lesser General Public
>>>> + * License as published by the Free Software Foundation; either
>>>> + * version 2 of the License, or (at your option) any later version.
>>>> + *
>>>> + * This library is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> + * Lesser General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU Lesser General Public
>>>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>>>> + */
>>>> +
>>>> +#include "cpu.h"
>>>> +#include "helper.h"
>>>> +
>>>> +#define TO_SPR(group, number) (((group) << 11) + (number))
>>>> +
>>>> +void HELPER(mtspr)(CPUOpenRISCState * env,
>>>> +                   target_ulong ra, target_ulong rb, target_ulong offset)
>>>> +{
>>>> +#if !defined(CONFIG_USER_ONLY)
>>>> +    int spr = (ra | offset);
>>>> +    int idx;
>>>> +
>>>> +    switch (spr) {
>>>> +    case TO_SPR(0, 0): /* VR */
>>>> +        env->vr = rb;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 16): /* NPC */
>>>> +        env->npc = rb;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 17): /* SR */
>>>> +        if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
>>>> +            (rb & (SR_IME | SR_DME | SR_SM))) {
>>>> +            tlb_flush(env, 1);
>>>> +        }
>>>> +        env->sr = rb;
>>>> +        env->sr |= SR_FO;      /* FO is const equal to 1 */
>>>> +        if (env->sr & SR_DME) {
>>>> +            env->tlb->map_address_data = &get_phys_data;
>>>> +        } else {
>>>> +            env->tlb->map_address_data = &get_phys_nommu;
>>>> +        }
>>>> +
>>>> +        if (env->sr & SR_IME) {
>>>> +            env->tlb->map_address_code = &get_phys_code;
>>>> +        } else {
>>>> +            env->tlb->map_address_code = &get_phys_nommu;
>>>> +        }
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 18): /* PPC */
>>>> +        env->ppc = rb;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 32): /* EPCR */
>>>> +        env->epcr = rb;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 48): /* EEAR */
>>>> +        env->eear = rb;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 64): /* ESR */
>>>> +        env->esr = rb;
>>>> +        break;
>>>> +    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>>> +        idx = spr - TO_SPR(1, 512);
>>>> +        if (!(rb & 1)) {
>>>> +            tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
>>>> +        }
>>>> +        env->tlb->dtlb[0][idx].mr = rb;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>>> +        idx = spr - TO_SPR(1, 640);
>>>> +        env->tlb->dtlb[0][idx].tr = rb;
>>>> +        break;
>>>> +    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>>>> +    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>>>> +    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>>>> +    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>>>> +    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>>>> +    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>>>> +        break;
>>>> +    case TO_SPR(2, 512) ... TO_SPR(2, 639):   /* ITLBW0MR 0-127 */
>>>> +        idx = spr - TO_SPR(2, 512);
>>>> +        if (!(rb & 1)) {
>>>> +            tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
>>>> +        }
>>>> +        env->tlb->itlb[0][idx].mr = rb;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>>> +        idx = spr - TO_SPR(2, 640);
>>>> +        env->tlb->itlb[0][idx].tr = rb;
>>>> +        break;
>>>> +    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>>>> +    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>>>> +    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>>>> +    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>>>> +        break;
>>>> +    case TO_SPR(9, 0):  /* PICMR */
>>>> +        cpu_openrisc_store_picmr(env, rb);
>>>> +        break;
>>>> +    case TO_SPR(9, 2):  /* PICSR */
>>>> +        cpu_openrisc_store_picsr(env, rb);
>>>> +        break;
>>>> +    case TO_SPR(10, 0): /* TTMR */
>>>> +        cpu_openrisc_store_compare(env, rb);
>>>> +        break;
>>>> +    case TO_SPR(10, 1): /* TTCR */
>>>> +        cpu_openrisc_store_count(env, rb);
>>>> +        break;
>>>> +    default:
>>>> +        break;
>>>> +    }
>>>> +#endif
>>>> +}
>>>> +
>>>> +void HELPER(mfspr)(CPUOpenRISCState * env,
>>>> +                   target_ulong rd, target_ulong ra, uint32_t offset)
>>>> +{
>>>> +#if !defined(CONFIG_USER_ONLY)
>>>> +    int spr = env->gpr[ra] | offset;
>>>
>>> [1]
>>>
>>>> +    int idx;
>>>> +
>>>> +    switch (spr) {
>>>> +    case TO_SPR(0, 0): /* VR */
>>>> +        env->gpr[rd] = (env->vr & SPR_VR);
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 1): /* UPR */
>>>> +        env->gpr[rd] = env->upr;    /* TT, DM, IM, UP present */
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 2): /* CPUCFGR */
>>>> +        env->gpr[rd] = env->cpucfgr;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 3): /* DMMUCFGR */
>>>> +        env->gpr[rd] = env->dmmucfgr;    /* 1Way, 64 entries */
>>>> +        break;
>>>> +    case TO_SPR(0, 4): /* IMMUCFGR */
>>>> +        env->gpr[rd] = env->immucfgr;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 16): /* NPC */
>>>> +        env->gpr[rd] = env->npc;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 17): /* SR */
>>>> +        env->gpr[rd] = env->sr;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 18): /* PPC */
>>>> +        env->gpr[rd] = env->ppc;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 32): /* EPCR */
>>>> +        env->gpr[rd] = env->epcr;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 48): /* EEAR */
>>>> +        env->gpr[rd] = env->eear;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(0, 64): /* ESR */
>>>> +        env->gpr[rd] = env->esr;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
>>>> +        idx = spr - TO_SPR(1, 512);
>>>> +        env->gpr[rd] = env->tlb->dtlb[0][idx].mr;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
>>>> +        idx = spr - TO_SPR(1, 640);
>>>> +        env->gpr[rd] = env->tlb->dtlb[0][idx].tr;
>>>> +        break;
>>>> +    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
>>>> +    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
>>>> +    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
>>>> +    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
>>>> +    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
>>>> +    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
>>>> +        idx = spr - TO_SPR(2, 512);
>>>> +        env->gpr[rd] = env->tlb->itlb[0][idx].mr;
>>>> +        break;
>>>> +
>>>> +    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
>>>> +        idx = spr - TO_SPR(2, 640);
>>>> +        env->gpr[rd] = env->tlb->itlb[0][idx].tr;
>>>> +        break;
>>>> +    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
>>>> +    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
>>>> +    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
>>>> +    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
>>>> +        break;
>>>> +    case TO_SPR(9, 0):  /* PICMR */
>>>> +        env->gpr[rd] = env->picmr;
>>>> +        break;
>>>> +    case TO_SPR(9, 2):  /* PICSR */
>>>> +        env->gpr[rd] = env->picsr;
>>>> +        break;
>>>> +    case TO_SPR(10, 0): /* TTMR */
>>>> +        env->gpr[rd] = env->ttmr;
>>>> +        break;
>>>> +    case TO_SPR(10, 1): /* TTCR */
>>>> +        env->gpr[rd] = cpu_openrisc_get_count(env);
>>>
>>> [2]
>>>
>>>> +        break;
>>>> +    default:
>>>> +        break;
>>>> +    }
>>>> +#endif
>>>> +}
>>>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
>>>> index d4f894b..11eb0a5 100644
>>>> --- a/target-openrisc/translate.c
>>>> +++ b/target-openrisc/translate.c
>>>> @@ -1241,10 +1241,30 @@ static void dec_misc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
>>>>
>>>>     case 0x2d:   /*l.mfspr*/
>>>>         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
>>>> +        {
>>>> +            TCGv_i32 ti = tcg_const_i32(I16);
>>>> +            TCGv td = tcg_const_tl(rd);
>>>> +            TCGv ta = tcg_const_tl(ra);
>>>> +            gen_helper_mfspr(cpu_env, td, ta, ti);
>>>
>>> The helper should a return target_ulong, so the line would become
>>> gen_helper_mfspr(cpu_R[rd], cpu_env, td, cpu_R[ra], ti);
>>>
>>> Then the register moves inside the mfspr helper could be avoided:
>>> [1]
>>>> +    int spr = env->gpr[ra] | offset;
>>> int spr = ra | offset;
>>>
>>> As an example [2]:
>>>> +        env->gpr[rd] = cpu_openrisc_get_count(env);
>>> return cpu_openrisc_get_count(env);
>>>
>>>> +            tcg_temp_free_i32(ti);
>>>> +            tcg_temp_free(td);
>>>> +            tcg_temp_free(ta);
>>>> +        }
>>>
>>> Also here you could try later to avoid to compile sys_helper.c for
>>> user emulator by surrounding the previous block by #ifndef
>>> CONFIG_USER_ONLY/#endif (ditto for mtspr).
>>>
>>>>         break;
>>>>
>>>>     case 0x30:  /*l.mtspr*/
>>>>         LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
>>>> +        {
>>>> +            TCGv_i32 im = tcg_const_i32(tmp);
>>>> +            TCGv ta = tcg_temp_new();
>>>> +            TCGv tb = tcg_temp_new();
>>>> +            tcg_gen_mov_tl(ta, cpu_R[ra]);
>>>> +            tcg_gen_mov_tl(tb, cpu_R[rb]);
>>>> +            gen_helper_mtspr(cpu_env, ta, tb, im);
>>>
>>> Simply
>>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im);
>>>
>>>> +            tcg_temp_free_i32(im);
>>>> +            tcg_temp_free(ta);
>>>> +            tcg_temp_free(tb);
>>>> +        }
>>>>         break;
>>>>
>>>>     case 0x34:   /*l.sd*/
>>>> --
>>>> 1.7.9.5
>>>>
>>>>
>>
>> Regards,
>> Jia.
diff mbox

Patch

diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 0d72c33..9d13a5d 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -1,3 +1,4 @@ 
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-y += cpu.o excp.o intrpt.o mmu.o translate.o
-obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o mmu_helper.o
+obj-y += excp_helper.o fpu_helper.o int_helper.o intrpt_helper.o \
+         mmu_helper.o sys_helper.o
diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h
index 60870f2..04c63c5 100644
--- a/target-openrisc/helper.h
+++ b/target-openrisc/helper.h
@@ -62,4 +62,8 @@  DEF_HELPER_FLAGS_1(fl1, 0, tl, tl)
 /* interrupt */
 DEF_HELPER_FLAGS_1(rfe, 0, void, env)
 
+/* sys */
+DEF_HELPER_FLAGS_4(mtspr, 0, void, env, tl, tl, tl)
+DEF_HELPER_FLAGS_4(mfspr, 0, void, env, tl, tl, tl)
+
 #include "def-helper.h"
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
new file mode 100644
index 0000000..f1e4314
--- /dev/null
+++ b/target-openrisc/sys_helper.c
@@ -0,0 +1,233 @@ 
+/*
+ *  OpenRISC system instructions helper routines
+ *
+ *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *                          Zhizhou Zhang <etouzh@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+
+#define TO_SPR(group, number) (((group) << 11) + (number))
+
+void HELPER(mtspr)(CPUOpenRISCState * env,
+                   target_ulong ra, target_ulong rb, target_ulong offset)
+{
+#if !defined(CONFIG_USER_ONLY)
+    int spr = (ra | offset);
+    int idx;
+
+    switch (spr) {
+    case TO_SPR(0, 0): /* VR */
+        env->vr = rb;
+        break;
+
+    case TO_SPR(0, 16): /* NPC */
+        env->npc = rb;
+        break;
+
+    case TO_SPR(0, 17): /* SR */
+        if ((env->sr & (SR_IME | SR_DME | SR_SM)) ^
+            (rb & (SR_IME | SR_DME | SR_SM))) {
+            tlb_flush(env, 1);
+        }
+        env->sr = rb;
+        env->sr |= SR_FO;      /* FO is const equal to 1 */
+        if (env->sr & SR_DME) {
+            env->tlb->map_address_data = &get_phys_data;
+        } else {
+            env->tlb->map_address_data = &get_phys_nommu;
+        }
+
+        if (env->sr & SR_IME) {
+            env->tlb->map_address_code = &get_phys_code;
+        } else {
+            env->tlb->map_address_code = &get_phys_nommu;
+        }
+        break;
+
+    case TO_SPR(0, 18): /* PPC */
+        env->ppc = rb;
+        break;
+
+    case TO_SPR(0, 32): /* EPCR */
+        env->epcr = rb;
+        break;
+
+    case TO_SPR(0, 48): /* EEAR */
+        env->eear = rb;
+        break;
+
+    case TO_SPR(0, 64): /* ESR */
+        env->esr = rb;
+        break;
+    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+        idx = spr - TO_SPR(1, 512);
+        if (!(rb & 1)) {
+            tlb_flush_page(env, env->tlb->dtlb[0][idx].mr & TARGET_PAGE_MASK);
+        }
+        env->tlb->dtlb[0][idx].mr = rb;
+        break;
+
+    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
+        idx = spr - TO_SPR(1, 640);
+        env->tlb->dtlb[0][idx].tr = rb;
+        break;
+    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
+    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
+    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
+    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
+    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
+    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
+        break;
+    case TO_SPR(2, 512) ... TO_SPR(2, 639):   /* ITLBW0MR 0-127 */
+        idx = spr - TO_SPR(2, 512);
+        if (!(rb & 1)) {
+            tlb_flush_page(env, env->tlb->itlb[0][idx].mr & TARGET_PAGE_MASK);
+        }
+        env->tlb->itlb[0][idx].mr = rb;
+        break;
+
+    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
+        idx = spr - TO_SPR(2, 640);
+        env->tlb->itlb[0][idx].tr = rb;
+        break;
+    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
+    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
+    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
+    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
+        break;
+    case TO_SPR(9, 0):  /* PICMR */
+        cpu_openrisc_store_picmr(env, rb);
+        break;
+    case TO_SPR(9, 2):  /* PICSR */
+        cpu_openrisc_store_picsr(env, rb);
+        break;
+    case TO_SPR(10, 0): /* TTMR */
+        cpu_openrisc_store_compare(env, rb);
+        break;
+    case TO_SPR(10, 1): /* TTCR */
+        cpu_openrisc_store_count(env, rb);
+        break;
+    default:
+        break;
+    }
+#endif
+}
+
+void HELPER(mfspr)(CPUOpenRISCState * env,
+                   target_ulong rd, target_ulong ra, uint32_t offset)
+{
+#if !defined(CONFIG_USER_ONLY)
+    int spr = env->gpr[ra] | offset;
+    int idx;
+
+    switch (spr) {
+    case TO_SPR(0, 0): /* VR */
+        env->gpr[rd] = (env->vr & SPR_VR);
+        break;
+
+    case TO_SPR(0, 1): /* UPR */
+        env->gpr[rd] = env->upr;    /* TT, DM, IM, UP present */
+        break;
+
+    case TO_SPR(0, 2): /* CPUCFGR */
+        env->gpr[rd] = env->cpucfgr;
+        break;
+
+    case TO_SPR(0, 3): /* DMMUCFGR */
+        env->gpr[rd] = env->dmmucfgr;    /* 1Way, 64 entries */
+        break;
+    case TO_SPR(0, 4): /* IMMUCFGR */
+        env->gpr[rd] = env->immucfgr;
+        break;
+
+    case TO_SPR(0, 16): /* NPC */
+        env->gpr[rd] = env->npc;
+        break;
+
+    case TO_SPR(0, 17): /* SR */
+        env->gpr[rd] = env->sr;
+        break;
+
+    case TO_SPR(0, 18): /* PPC */
+        env->gpr[rd] = env->ppc;
+        break;
+
+    case TO_SPR(0, 32): /* EPCR */
+        env->gpr[rd] = env->epcr;
+        break;
+
+    case TO_SPR(0, 48): /* EEAR */
+        env->gpr[rd] = env->eear;
+        break;
+
+    case TO_SPR(0, 64): /* ESR */
+        env->gpr[rd] = env->esr;
+        break;
+
+    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+        idx = spr - TO_SPR(1, 512);
+        env->gpr[rd] = env->tlb->dtlb[0][idx].mr;
+        break;
+
+    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
+        idx = spr - TO_SPR(1, 640);
+        env->gpr[rd] = env->tlb->dtlb[0][idx].tr;
+        break;
+    case TO_SPR(1, 768) ... TO_SPR(1, 895):   /* DTLBW1MR 0-127 */
+    case TO_SPR(1, 896) ... TO_SPR(1, 1023):  /* DTLBW1TR 0-127 */
+    case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */
+    case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */
+    case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */
+    case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */
+        break;
+
+    case TO_SPR(2, 512) ... TO_SPR(2, 639): /* ITLBW0MR 0-127 */
+        idx = spr - TO_SPR(2, 512);
+        env->gpr[rd] = env->tlb->itlb[0][idx].mr;
+        break;
+
+    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
+        idx = spr - TO_SPR(2, 640);
+        env->gpr[rd] = env->tlb->itlb[0][idx].tr;
+        break;
+    case TO_SPR(2, 768) ... TO_SPR(2, 895):   /* ITLBW1MR 0-127 */
+    case TO_SPR(2, 896) ... TO_SPR(2, 1023):  /* ITLBW1TR 0-127 */
+    case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */
+    case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 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 */
+        break;
+    case TO_SPR(9, 0):  /* PICMR */
+        env->gpr[rd] = env->picmr;
+        break;
+    case TO_SPR(9, 2):  /* PICSR */
+        env->gpr[rd] = env->picsr;
+        break;
+    case TO_SPR(10, 0): /* TTMR */
+        env->gpr[rd] = env->ttmr;
+        break;
+    case TO_SPR(10, 1): /* TTCR */
+        env->gpr[rd] = cpu_openrisc_get_count(env);
+        break;
+    default:
+        break;
+    }
+#endif
+}
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index d4f894b..11eb0a5 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1241,10 +1241,30 @@  static void dec_misc(DisasContext *dc, CPUOpenRISCState *env, uint32_t insn)
 
     case 0x2d:   /*l.mfspr*/
         LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16);
+        {
+            TCGv_i32 ti = tcg_const_i32(I16);
+            TCGv td = tcg_const_tl(rd);
+            TCGv ta = tcg_const_tl(ra);
+            gen_helper_mfspr(cpu_env, td, ta, ti);
+            tcg_temp_free_i32(ti);
+            tcg_temp_free(td);
+            tcg_temp_free(ta);
+        }
         break;
 
     case 0x30:  /*l.mtspr*/
         LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11);
+        {
+            TCGv_i32 im = tcg_const_i32(tmp);
+            TCGv ta = tcg_temp_new();
+            TCGv tb = tcg_temp_new();
+            tcg_gen_mov_tl(ta, cpu_R[ra]);
+            tcg_gen_mov_tl(tb, cpu_R[rb]);
+            gen_helper_mtspr(cpu_env, ta, tb, im);
+            tcg_temp_free_i32(im);
+            tcg_temp_free(ta);
+            tcg_temp_free(tb);
+        }
         break;
 
     case 0x34:   /*l.sd*/