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 <blauwir...@gmail.com> wrote: > On Mon, Jun 18, 2012 at 1:03 AM, Jia Liu <pro...@gmail.com> wrote: >> Add OpenRISC system instruction support. >> >> Signed-off-by: Jia Liu <pro...@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 <pro...@gmail.com> >> + * Zhizhou Zhang <eto...@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.