Message ID | 1342154108-798-12-git-send-email-proljc@gmail.com |
---|---|
State | New |
Headers | show |
On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote: > Add OpenRISC system instructions. > > Signed-off-by: Jia Liu <proljc@gmail.com> > --- > target-openrisc/Makefile.objs | 2 +- > target-openrisc/cpu.h | 3 + > target-openrisc/helper.h | 4 + > target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++ > target-openrisc/translate.c | 10 ++ > 5 files changed, 305 insertions(+), 1 deletion(-) > create mode 100644 target-openrisc/sys_helper.c > > diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs > index 926fc2f..44dc539 100644 > --- a/target-openrisc/Makefile.objs > +++ b/target-openrisc/Makefile.objs > @@ -1,4 +1,4 @@ > obj-$(CONFIG_SOFTMMU) += machine.o > obj-y += cpu.o exception.o interrupt.o mmu.o translate.o > obj-y += exception_helper.o fpu_helper.o int_helper.o \ > - interrupt_helper.o mmu_helper.o > + interrupt_helper.o mmu_helper.o sys_helper.o > diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h > index df07eaf..6506665 100644 > --- a/target-openrisc/cpu.h > +++ b/target-openrisc/cpu.h > @@ -80,6 +80,9 @@ enum { > (reg) |= ((v & 0x1f) << 2);\ > } while (0) > > +/* Version Register */ > +#define SPR_VR 0xFFFF003F > + > /* Internal flags, delay slot flag */ > #define D_FLAG 1 > > diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h > index 6eb259a..836a70b 100644 > --- a/target-openrisc/helper.h > +++ b/target-openrisc/helper.h > @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 0, tl, env, 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, tl, 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..7ff8e15 > --- /dev/null > +++ b/target-openrisc/sys_helper.c > @@ -0,0 +1,287 @@ > +/* > + * 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) > +{ > +#ifndef CONFIG_USER_ONLY > + int spr = (ra | offset); > + int idx; > + > + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); > + > + 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->cpu_openrisc_map_address_data = > + &cpu_openrisc_get_phys_data; > + } else { > + env->tlb->cpu_openrisc_map_address_data = > + &cpu_openrisc_get_phys_nommu; > + } > + > + if (env->sr & SR_IME) { > + env->tlb->cpu_openrisc_map_address_code = > + &cpu_openrisc_get_phys_code; > + } else { > + env->tlb->cpu_openrisc_map_address_code = > + &cpu_openrisc_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 */ > + env->picmr |= rb; > + break; > + case TO_SPR(9, 2): /* PICSR */ > + env->picsr &= ~rb; > + break; > + case TO_SPR(10, 0): /* TTMR */ > + { > + int ip = env->ttmr & TTMR_IP; > + > + if (rb & TTMR_IP) { /* Keep IP bit. */ > + env->ttmr = (rb & ~TTMR_IP) + ip; > + } else { /* Clear IP bit. */ > + env->ttmr = rb & ~TTMR_IP; > + env->interrupt_request &= ~CPU_INTERRUPT_TIMER; > + } > + > + cpu_openrisc_count_update(cpu); > + > + switch (env->ttmr & TTMR_M) { > + case TIMER_NONE: > + cpu_openrisc_count_stop(cpu); > + break; > + case TIMER_INTR: > + cpu_openrisc_count_start(cpu); > + break; > + case TIMER_SHOT: > + cpu_openrisc_count_start(cpu); > + break; > + case TIMER_CONT: > + cpu_openrisc_count_start(cpu); > + break; > + default: > + break; > + } > + } > + break; > + > + case TO_SPR(10, 1): /* TTCR */ > + env->ttcr = rb; > + if (env->ttmr & TIMER_NONE) { > + return; > + } > + cpu_openrisc_count_start(cpu); > + 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; > + > + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); > + > + 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 */ > + cpu_openrisc_count_update(cpu); > + return env->ttcr; > + > + default: > + break; > + } > +#endif > + > +/*If we 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;*/ > + > + /* for rd is passed in, if rd unchanged, just keep it back. */ > + return rd; > +} > diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c > index ed25604..8069edb 100644 > --- a/target-openrisc/translate.c > +++ b/target-openrisc/translate.c > @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, 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); > + 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; openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode, but I don't see where it is enforced.
Hi Max On Fri, Jul 13, 2012 at 5:27 PM, Max Filippov <jcmvbkbc@gmail.com> wrote: > On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote: >> Add OpenRISC system instructions. >> >> Signed-off-by: Jia Liu <proljc@gmail.com> >> --- >> target-openrisc/Makefile.objs | 2 +- >> target-openrisc/cpu.h | 3 + >> target-openrisc/helper.h | 4 + >> target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++ >> target-openrisc/translate.c | 10 ++ >> 5 files changed, 305 insertions(+), 1 deletion(-) >> create mode 100644 target-openrisc/sys_helper.c >> >> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs >> index 926fc2f..44dc539 100644 >> --- a/target-openrisc/Makefile.objs >> +++ b/target-openrisc/Makefile.objs >> @@ -1,4 +1,4 @@ >> obj-$(CONFIG_SOFTMMU) += machine.o >> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o >> obj-y += exception_helper.o fpu_helper.o int_helper.o \ >> - interrupt_helper.o mmu_helper.o >> + interrupt_helper.o mmu_helper.o sys_helper.o >> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h >> index df07eaf..6506665 100644 >> --- a/target-openrisc/cpu.h >> +++ b/target-openrisc/cpu.h >> @@ -80,6 +80,9 @@ enum { >> (reg) |= ((v & 0x1f) << 2);\ >> } while (0) >> >> +/* Version Register */ >> +#define SPR_VR 0xFFFF003F >> + >> /* Internal flags, delay slot flag */ >> #define D_FLAG 1 >> >> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h >> index 6eb259a..836a70b 100644 >> --- a/target-openrisc/helper.h >> +++ b/target-openrisc/helper.h >> @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 0, tl, env, 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, tl, 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..7ff8e15 >> --- /dev/null >> +++ b/target-openrisc/sys_helper.c >> @@ -0,0 +1,287 @@ >> +/* >> + * 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) >> +{ >> +#ifndef CONFIG_USER_ONLY >> + int spr = (ra | offset); >> + int idx; >> + >> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); >> + >> + 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->cpu_openrisc_map_address_data = >> + &cpu_openrisc_get_phys_data; >> + } else { >> + env->tlb->cpu_openrisc_map_address_data = >> + &cpu_openrisc_get_phys_nommu; >> + } >> + >> + if (env->sr & SR_IME) { >> + env->tlb->cpu_openrisc_map_address_code = >> + &cpu_openrisc_get_phys_code; >> + } else { >> + env->tlb->cpu_openrisc_map_address_code = >> + &cpu_openrisc_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 */ >> + env->picmr |= rb; >> + break; >> + case TO_SPR(9, 2): /* PICSR */ >> + env->picsr &= ~rb; >> + break; >> + case TO_SPR(10, 0): /* TTMR */ >> + { >> + int ip = env->ttmr & TTMR_IP; >> + >> + if (rb & TTMR_IP) { /* Keep IP bit. */ >> + env->ttmr = (rb & ~TTMR_IP) + ip; >> + } else { /* Clear IP bit. */ >> + env->ttmr = rb & ~TTMR_IP; >> + env->interrupt_request &= ~CPU_INTERRUPT_TIMER; >> + } >> + >> + cpu_openrisc_count_update(cpu); >> + >> + switch (env->ttmr & TTMR_M) { >> + case TIMER_NONE: >> + cpu_openrisc_count_stop(cpu); >> + break; >> + case TIMER_INTR: >> + cpu_openrisc_count_start(cpu); >> + break; >> + case TIMER_SHOT: >> + cpu_openrisc_count_start(cpu); >> + break; >> + case TIMER_CONT: >> + cpu_openrisc_count_start(cpu); >> + break; >> + default: >> + break; >> + } >> + } >> + break; >> + >> + case TO_SPR(10, 1): /* TTCR */ >> + env->ttcr = rb; >> + if (env->ttmr & TIMER_NONE) { >> + return; >> + } >> + cpu_openrisc_count_start(cpu); >> + 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; >> + >> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); >> + >> + 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 */ >> + cpu_openrisc_count_update(cpu); >> + return env->ttcr; >> + >> + default: >> + break; >> + } >> +#endif >> + >> +/*If we 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;*/ >> + >> + /* for rd is passed in, if rd unchanged, just keep it back. */ >> + return rd; >> +} >> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c >> index ed25604..8069edb 100644 >> --- a/target-openrisc/translate.c >> +++ b/target-openrisc/translate.c >> @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, 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); >> + 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; > > openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode, > but I don't see where it is enforced. > Thank you for mind me, it is the new code. Is it OK? #ifndef CONFIG_USER_ONLY 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; #endif > -- > Thanks. > -- Max Regards, Jia
On Sat, Jul 14, 2012 at 11:12 AM, Jia Liu <proljc@gmail.com> wrote: > Hi Max > > On Fri, Jul 13, 2012 at 5:27 PM, Max Filippov <jcmvbkbc@gmail.com> wrote: >> On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote: >>> Add OpenRISC system instructions. >>> >>> Signed-off-by: Jia Liu <proljc@gmail.com> >>> --- >>> target-openrisc/Makefile.objs | 2 +- >>> target-openrisc/cpu.h | 3 + >>> target-openrisc/helper.h | 4 + >>> target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++ >>> target-openrisc/translate.c | 10 ++ >>> 5 files changed, 305 insertions(+), 1 deletion(-) >>> create mode 100644 target-openrisc/sys_helper.c >>> >>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs >>> index 926fc2f..44dc539 100644 >>> --- a/target-openrisc/Makefile.objs >>> +++ b/target-openrisc/Makefile.objs >>> @@ -1,4 +1,4 @@ >>> obj-$(CONFIG_SOFTMMU) += machine.o >>> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o >>> obj-y += exception_helper.o fpu_helper.o int_helper.o \ >>> - interrupt_helper.o mmu_helper.o >>> + interrupt_helper.o mmu_helper.o sys_helper.o >>> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h >>> index df07eaf..6506665 100644 >>> --- a/target-openrisc/cpu.h >>> +++ b/target-openrisc/cpu.h >>> @@ -80,6 +80,9 @@ enum { >>> (reg) |= ((v & 0x1f) << 2);\ >>> } while (0) >>> >>> +/* Version Register */ >>> +#define SPR_VR 0xFFFF003F >>> + >>> /* Internal flags, delay slot flag */ >>> #define D_FLAG 1 >>> >>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h >>> index 6eb259a..836a70b 100644 >>> --- a/target-openrisc/helper.h >>> +++ b/target-openrisc/helper.h >>> @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 0, tl, env, 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, tl, 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..7ff8e15 >>> --- /dev/null >>> +++ b/target-openrisc/sys_helper.c >>> @@ -0,0 +1,287 @@ >>> +/* >>> + * 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) >>> +{ >>> +#ifndef CONFIG_USER_ONLY >>> + int spr = (ra | offset); >>> + int idx; >>> + >>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); >>> + >>> + 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->cpu_openrisc_map_address_data = >>> + &cpu_openrisc_get_phys_data; >>> + } else { >>> + env->tlb->cpu_openrisc_map_address_data = >>> + &cpu_openrisc_get_phys_nommu; >>> + } >>> + >>> + if (env->sr & SR_IME) { >>> + env->tlb->cpu_openrisc_map_address_code = >>> + &cpu_openrisc_get_phys_code; >>> + } else { >>> + env->tlb->cpu_openrisc_map_address_code = >>> + &cpu_openrisc_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 */ >>> + env->picmr |= rb; >>> + break; >>> + case TO_SPR(9, 2): /* PICSR */ >>> + env->picsr &= ~rb; >>> + break; >>> + case TO_SPR(10, 0): /* TTMR */ >>> + { >>> + int ip = env->ttmr & TTMR_IP; >>> + >>> + if (rb & TTMR_IP) { /* Keep IP bit. */ >>> + env->ttmr = (rb & ~TTMR_IP) + ip; >>> + } else { /* Clear IP bit. */ >>> + env->ttmr = rb & ~TTMR_IP; >>> + env->interrupt_request &= ~CPU_INTERRUPT_TIMER; >>> + } >>> + >>> + cpu_openrisc_count_update(cpu); >>> + >>> + switch (env->ttmr & TTMR_M) { >>> + case TIMER_NONE: >>> + cpu_openrisc_count_stop(cpu); >>> + break; >>> + case TIMER_INTR: >>> + cpu_openrisc_count_start(cpu); >>> + break; >>> + case TIMER_SHOT: >>> + cpu_openrisc_count_start(cpu); >>> + break; >>> + case TIMER_CONT: >>> + cpu_openrisc_count_start(cpu); >>> + break; >>> + default: >>> + break; >>> + } >>> + } >>> + break; >>> + >>> + case TO_SPR(10, 1): /* TTCR */ >>> + env->ttcr = rb; >>> + if (env->ttmr & TIMER_NONE) { >>> + return; >>> + } >>> + cpu_openrisc_count_start(cpu); >>> + 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; >>> + >>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); >>> + >>> + 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 */ >>> + cpu_openrisc_count_update(cpu); >>> + return env->ttcr; >>> + >>> + default: >>> + break; >>> + } >>> +#endif >>> + >>> +/*If we 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;*/ >>> + >>> + /* for rd is passed in, if rd unchanged, just keep it back. */ >>> + return rd; >>> +} >>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c >>> index ed25604..8069edb 100644 >>> --- a/target-openrisc/translate.c >>> +++ b/target-openrisc/translate.c >>> @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, 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); >>> + 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; >> >> openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode, >> but I don't see where it is enforced. >> > > Thank you for mind me, it is the new code. Is it OK? I don't think so, please check for example target-ppc/translate.c:4192 on how supervisor only mfsr is handled there. > > #ifndef CONFIG_USER_ONLY > 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; > #endif > > >> -- >> Thanks. >> -- Max > > Regards, > Jia >
Hi Blue, On Sat, Jul 14, 2012 at 9:19 PM, Blue Swirl <blauwirbel@gmail.com> wrote: > On Sat, Jul 14, 2012 at 11:12 AM, Jia Liu <proljc@gmail.com> wrote: >> Hi Max >> >> On Fri, Jul 13, 2012 at 5:27 PM, Max Filippov <jcmvbkbc@gmail.com> wrote: >>> On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote: >>>> Add OpenRISC system instructions. >>>> >>>> Signed-off-by: Jia Liu <proljc@gmail.com> >>>> --- >>>> target-openrisc/Makefile.objs | 2 +- >>>> target-openrisc/cpu.h | 3 + >>>> target-openrisc/helper.h | 4 + >>>> target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++ >>>> target-openrisc/translate.c | 10 ++ >>>> 5 files changed, 305 insertions(+), 1 deletion(-) >>>> create mode 100644 target-openrisc/sys_helper.c >>>> >>>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs >>>> index 926fc2f..44dc539 100644 >>>> --- a/target-openrisc/Makefile.objs >>>> +++ b/target-openrisc/Makefile.objs >>>> @@ -1,4 +1,4 @@ >>>> obj-$(CONFIG_SOFTMMU) += machine.o >>>> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o >>>> obj-y += exception_helper.o fpu_helper.o int_helper.o \ >>>> - interrupt_helper.o mmu_helper.o >>>> + interrupt_helper.o mmu_helper.o sys_helper.o >>>> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h >>>> index df07eaf..6506665 100644 >>>> --- a/target-openrisc/cpu.h >>>> +++ b/target-openrisc/cpu.h >>>> @@ -80,6 +80,9 @@ enum { >>>> (reg) |= ((v & 0x1f) << 2);\ >>>> } while (0) >>>> >>>> +/* Version Register */ >>>> +#define SPR_VR 0xFFFF003F >>>> + >>>> /* Internal flags, delay slot flag */ >>>> #define D_FLAG 1 >>>> >>>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h >>>> index 6eb259a..836a70b 100644 >>>> --- a/target-openrisc/helper.h >>>> +++ b/target-openrisc/helper.h >>>> @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 0, tl, env, 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, tl, 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..7ff8e15 >>>> --- /dev/null >>>> +++ b/target-openrisc/sys_helper.c >>>> @@ -0,0 +1,287 @@ >>>> +/* >>>> + * 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) >>>> +{ >>>> +#ifndef CONFIG_USER_ONLY >>>> + int spr = (ra | offset); >>>> + int idx; >>>> + >>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); >>>> + >>>> + 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->cpu_openrisc_map_address_data = >>>> + &cpu_openrisc_get_phys_data; >>>> + } else { >>>> + env->tlb->cpu_openrisc_map_address_data = >>>> + &cpu_openrisc_get_phys_nommu; >>>> + } >>>> + >>>> + if (env->sr & SR_IME) { >>>> + env->tlb->cpu_openrisc_map_address_code = >>>> + &cpu_openrisc_get_phys_code; >>>> + } else { >>>> + env->tlb->cpu_openrisc_map_address_code = >>>> + &cpu_openrisc_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 */ >>>> + env->picmr |= rb; >>>> + break; >>>> + case TO_SPR(9, 2): /* PICSR */ >>>> + env->picsr &= ~rb; >>>> + break; >>>> + case TO_SPR(10, 0): /* TTMR */ >>>> + { >>>> + int ip = env->ttmr & TTMR_IP; >>>> + >>>> + if (rb & TTMR_IP) { /* Keep IP bit. */ >>>> + env->ttmr = (rb & ~TTMR_IP) + ip; >>>> + } else { /* Clear IP bit. */ >>>> + env->ttmr = rb & ~TTMR_IP; >>>> + env->interrupt_request &= ~CPU_INTERRUPT_TIMER; >>>> + } >>>> + >>>> + cpu_openrisc_count_update(cpu); >>>> + >>>> + switch (env->ttmr & TTMR_M) { >>>> + case TIMER_NONE: >>>> + cpu_openrisc_count_stop(cpu); >>>> + break; >>>> + case TIMER_INTR: >>>> + cpu_openrisc_count_start(cpu); >>>> + break; >>>> + case TIMER_SHOT: >>>> + cpu_openrisc_count_start(cpu); >>>> + break; >>>> + case TIMER_CONT: >>>> + cpu_openrisc_count_start(cpu); >>>> + break; >>>> + default: >>>> + break; >>>> + } >>>> + } >>>> + break; >>>> + >>>> + case TO_SPR(10, 1): /* TTCR */ >>>> + env->ttcr = rb; >>>> + if (env->ttmr & TIMER_NONE) { >>>> + return; >>>> + } >>>> + cpu_openrisc_count_start(cpu); >>>> + 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; >>>> + >>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); >>>> + >>>> + 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 */ >>>> + cpu_openrisc_count_update(cpu); >>>> + return env->ttcr; >>>> + >>>> + default: >>>> + break; >>>> + } >>>> +#endif >>>> + >>>> +/*If we 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;*/ >>>> + >>>> + /* for rd is passed in, if rd unchanged, just keep it back. */ >>>> + return rd; >>>> +} >>>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c >>>> index ed25604..8069edb 100644 >>>> --- a/target-openrisc/translate.c >>>> +++ b/target-openrisc/translate.c >>>> @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, 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); >>>> + 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; >>> >>> openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode, >>> but I don't see where it is enforced. >>> >> >> Thank you for mind me, it is the new code. Is it OK? > > I don't think so, please check for example target-ppc/translate.c:4192 > on how supervisor only mfsr is handled there. > Thank you for comment, Blue. is this code OK? case 0x2d: /* l.mfspr */ LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); { #if defined(CONFIG_USER_ONLY) gen_illegal_exception(dc); #else 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); #endif } break; case 0x30: /* l.mtspr */ LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); { #if defined(CONFIG_USER_ONLY) gen_illegal_exception(dc); #else TCGv_i32 im = tcg_const_i32(tmp); gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); tcg_temp_free_i32(im); #endif } break; >> >> #ifndef CONFIG_USER_ONLY >> 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; >> #endif >> >> >>> -- >>> Thanks. >>> -- Max >> >> Regards, >> Jia >> Regards, Jia
On Sat, Jul 14, 2012 at 5:39 PM, Jia Liu <proljc@gmail.com> wrote: > Hi Blue, > > On Sat, Jul 14, 2012 at 9:19 PM, Blue Swirl <blauwirbel@gmail.com> wrote: >> On Sat, Jul 14, 2012 at 11:12 AM, Jia Liu <proljc@gmail.com> wrote: >>> Hi Max >>> >>> On Fri, Jul 13, 2012 at 5:27 PM, Max Filippov <jcmvbkbc@gmail.com> wrote: >>>> On Fri, Jul 13, 2012 at 8:35 AM, Jia Liu <proljc@gmail.com> wrote: >>>>> Add OpenRISC system instructions. >>>>> >>>>> Signed-off-by: Jia Liu <proljc@gmail.com> >>>>> --- >>>>> target-openrisc/Makefile.objs | 2 +- >>>>> target-openrisc/cpu.h | 3 + >>>>> target-openrisc/helper.h | 4 + >>>>> target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++ >>>>> target-openrisc/translate.c | 10 ++ >>>>> 5 files changed, 305 insertions(+), 1 deletion(-) >>>>> create mode 100644 target-openrisc/sys_helper.c >>>>> >>>>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs >>>>> index 926fc2f..44dc539 100644 >>>>> --- a/target-openrisc/Makefile.objs >>>>> +++ b/target-openrisc/Makefile.objs >>>>> @@ -1,4 +1,4 @@ >>>>> obj-$(CONFIG_SOFTMMU) += machine.o >>>>> obj-y += cpu.o exception.o interrupt.o mmu.o translate.o >>>>> obj-y += exception_helper.o fpu_helper.o int_helper.o \ >>>>> - interrupt_helper.o mmu_helper.o >>>>> + interrupt_helper.o mmu_helper.o sys_helper.o >>>>> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h >>>>> index df07eaf..6506665 100644 >>>>> --- a/target-openrisc/cpu.h >>>>> +++ b/target-openrisc/cpu.h >>>>> @@ -80,6 +80,9 @@ enum { >>>>> (reg) |= ((v & 0x1f) << 2);\ >>>>> } while (0) >>>>> >>>>> +/* Version Register */ >>>>> +#define SPR_VR 0xFFFF003F >>>>> + >>>>> /* Internal flags, delay slot flag */ >>>>> #define D_FLAG 1 >>>>> >>>>> diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h >>>>> index 6eb259a..836a70b 100644 >>>>> --- a/target-openrisc/helper.h >>>>> +++ b/target-openrisc/helper.h >>>>> @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 0, tl, env, 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, tl, 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..7ff8e15 >>>>> --- /dev/null >>>>> +++ b/target-openrisc/sys_helper.c >>>>> @@ -0,0 +1,287 @@ >>>>> +/* >>>>> + * 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) >>>>> +{ >>>>> +#ifndef CONFIG_USER_ONLY >>>>> + int spr = (ra | offset); >>>>> + int idx; >>>>> + >>>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); >>>>> + >>>>> + 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->cpu_openrisc_map_address_data = >>>>> + &cpu_openrisc_get_phys_data; >>>>> + } else { >>>>> + env->tlb->cpu_openrisc_map_address_data = >>>>> + &cpu_openrisc_get_phys_nommu; >>>>> + } >>>>> + >>>>> + if (env->sr & SR_IME) { >>>>> + env->tlb->cpu_openrisc_map_address_code = >>>>> + &cpu_openrisc_get_phys_code; >>>>> + } else { >>>>> + env->tlb->cpu_openrisc_map_address_code = >>>>> + &cpu_openrisc_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 */ >>>>> + env->picmr |= rb; >>>>> + break; >>>>> + case TO_SPR(9, 2): /* PICSR */ >>>>> + env->picsr &= ~rb; >>>>> + break; >>>>> + case TO_SPR(10, 0): /* TTMR */ >>>>> + { >>>>> + int ip = env->ttmr & TTMR_IP; >>>>> + >>>>> + if (rb & TTMR_IP) { /* Keep IP bit. */ >>>>> + env->ttmr = (rb & ~TTMR_IP) + ip; >>>>> + } else { /* Clear IP bit. */ >>>>> + env->ttmr = rb & ~TTMR_IP; >>>>> + env->interrupt_request &= ~CPU_INTERRUPT_TIMER; >>>>> + } >>>>> + >>>>> + cpu_openrisc_count_update(cpu); >>>>> + >>>>> + switch (env->ttmr & TTMR_M) { >>>>> + case TIMER_NONE: >>>>> + cpu_openrisc_count_stop(cpu); >>>>> + break; >>>>> + case TIMER_INTR: >>>>> + cpu_openrisc_count_start(cpu); >>>>> + break; >>>>> + case TIMER_SHOT: >>>>> + cpu_openrisc_count_start(cpu); >>>>> + break; >>>>> + case TIMER_CONT: >>>>> + cpu_openrisc_count_start(cpu); >>>>> + break; >>>>> + default: >>>>> + break; >>>>> + } >>>>> + } >>>>> + break; >>>>> + >>>>> + case TO_SPR(10, 1): /* TTCR */ >>>>> + env->ttcr = rb; >>>>> + if (env->ttmr & TIMER_NONE) { >>>>> + return; >>>>> + } >>>>> + cpu_openrisc_count_start(cpu); >>>>> + 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; >>>>> + >>>>> + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); >>>>> + >>>>> + 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 */ >>>>> + cpu_openrisc_count_update(cpu); >>>>> + return env->ttcr; >>>>> + >>>>> + default: >>>>> + break; >>>>> + } >>>>> +#endif >>>>> + >>>>> +/*If we 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;*/ >>>>> + >>>>> + /* for rd is passed in, if rd unchanged, just keep it back. */ >>>>> + return rd; >>>>> +} >>>>> diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c >>>>> index ed25604..8069edb 100644 >>>>> --- a/target-openrisc/translate.c >>>>> +++ b/target-openrisc/translate.c >>>>> @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, 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); >>>>> + 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; >>>> >>>> openrisc ISA says that l.mtspr/l.mfspr are only accessible in supervisor mode, >>>> but I don't see where it is enforced. >>>> >>> >>> Thank you for mind me, it is the new code. Is it OK? >> >> I don't think so, please check for example target-ppc/translate.c:4192 >> on how supervisor only mfsr is handled there. >> > > Thank you for comment, Blue. > > is this code OK? Shouldn't there also be an exception in softmmu mode if the CPU is not in supervisor mode? > > case 0x2d: /* l.mfspr */ > LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); > { > #if defined(CONFIG_USER_ONLY) > gen_illegal_exception(dc); > #else > 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); > #endif > } > break; > > case 0x30: /* l.mtspr */ > LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); > { > #if defined(CONFIG_USER_ONLY) > gen_illegal_exception(dc); > #else > TCGv_i32 im = tcg_const_i32(tmp); > gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); > tcg_temp_free_i32(im); > #endif > } > break; > >>> >>> #ifndef CONFIG_USER_ONLY >>> 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; >>> #endif >>> >>> >>>> -- >>>> Thanks. >>>> -- Max >>> >>> Regards, >>> Jia >>> > > Regards, > Jia
Hi Max On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote: >>> I don't think so, please check for example target-ppc/translate.c:4192 >>> on how supervisor only mfsr is handled there. >>> >> >> Thank you for comment, Blue. >> >> is this code OK? > > Shouldn't there also be an exception in softmmu mode > if the CPU is not in supervisor mode? > Sorry, I... May you give me more comment? I'm not sure about this. >> >> case 0x2d: /* l.mfspr */ >> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); >> { >> #if defined(CONFIG_USER_ONLY) >> gen_illegal_exception(dc); >> #else >> 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); >> #endif >> } >> break; >> >> case 0x30: /* l.mtspr */ >> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); >> { >> #if defined(CONFIG_USER_ONLY) >> gen_illegal_exception(dc); >> #else >> TCGv_i32 im = tcg_const_i32(tmp); >> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); >> tcg_temp_free_i32(im); >> #endif >> } >> break; >> > > -- > Thanks. > -- Max Regards, Jia.
On Sat, Jul 14, 2012 at 2:08 PM, Jia Liu <proljc@gmail.com> wrote: > Hi Max > > On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote: >>>> I don't think so, please check for example target-ppc/translate.c:4192 >>>> on how supervisor only mfsr is handled there. >>>> >>> >>> Thank you for comment, Blue. >>> >>> is this code OK? >> >> Shouldn't there also be an exception in softmmu mode >> if the CPU is not in supervisor mode? >> > > Sorry, I... > May you give me more comment? I'm not sure about this. If a user tries to execute a supervisor instruction (only allowed for kernel level code, not applications), the instruction won't be executed but an exception will be raised. This is the PPC mfsr instruction part of target-ppc/translate.c: /* mfsr */ static void gen_mfsr(DisasContext *ctx) { #if defined(CONFIG_USER_ONLY) gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); #else TCGv t0; if (unlikely(!ctx->mem_idx)) { Here the MMU mode is checked for user mode. I'd use more explicit check ctx->mmu_idx == MMU_USER_IDX. gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); return; } t0 = tcg_const_tl(SR(ctx->opcode)); gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); tcg_temp_free(t0); #endif } > >>> >>> case 0x2d: /* l.mfspr */ >>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); >>> { >>> #if defined(CONFIG_USER_ONLY) >>> gen_illegal_exception(dc); >>> #else >>> 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); >>> #endif >>> } >>> break; >>> >>> case 0x30: /* l.mtspr */ >>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); >>> { >>> #if defined(CONFIG_USER_ONLY) >>> gen_illegal_exception(dc); >>> #else >>> TCGv_i32 im = tcg_const_i32(tmp); >>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); >>> tcg_temp_free_i32(im); >>> #endif >>> } >>> break; >>> >> >> -- >> Thanks. >> -- Max > > Regards, > Jia.
Hi Blue On Sat, Jul 14, 2012 at 10:42 PM, Blue Swirl <blauwirbel@gmail.com> wrote: > On Sat, Jul 14, 2012 at 2:08 PM, Jia Liu <proljc@gmail.com> wrote: >> Hi Max >> >> On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote: >>>>> I don't think so, please check for example target-ppc/translate.c:4192 >>>>> on how supervisor only mfsr is handled there. >>>>> >>>> >>>> Thank you for comment, Blue. >>>> >>>> is this code OK? >>> >>> Shouldn't there also be an exception in softmmu mode >>> if the CPU is not in supervisor mode? >>> >> >> Sorry, I... >> May you give me more comment? I'm not sure about this. > > If a user tries to execute a supervisor instruction (only allowed for > kernel level code, not applications), the instruction won't be > executed but an exception will be raised. > > This is the PPC mfsr instruction part of target-ppc/translate.c: > /* mfsr */ > static void gen_mfsr(DisasContext *ctx) > { > #if defined(CONFIG_USER_ONLY) > gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); > #else > TCGv t0; > if (unlikely(!ctx->mem_idx)) { > > Here the MMU mode is checked for user mode. I'd use more explicit > check ctx->mmu_idx == MMU_USER_IDX. > > gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); > return; > } > t0 = tcg_const_tl(SR(ctx->opcode)); > gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); > tcg_temp_free(t0); > #endif > } > Thank you very much for this nice example. Is this code OK? case 0x2d: /* l.mfspr */ LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); { #if defined(CONFIG_USER_ONLY) gen_illegal_exception(dc); #else TCGv_i32 ti = tcg_const_i32(I16); if (dc->mem_idx == MMU_USER_IDX) { gen_illegal_exception(dc); return; } gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti); tcg_temp_free_i32(ti); #endif } break; case 0x30: /* l.mtspr */ LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); { #if defined(CONFIG_USER_ONLY) gen_illegal_exception(dc); #else TCGv_i32 im = tcg_const_i32(tmp); if (dc->mem_idx == MMU_USER_IDX) { gen_illegal_exception(dc); return; } gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); tcg_temp_free_i32(im); #endif } break; >> >>>> >>>> case 0x2d: /* l.mfspr */ >>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); >>>> { >>>> #if defined(CONFIG_USER_ONLY) >>>> gen_illegal_exception(dc); >>>> #else >>>> 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); >>>> #endif >>>> } >>>> break; >>>> >>>> case 0x30: /* l.mtspr */ >>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); >>>> { >>>> #if defined(CONFIG_USER_ONLY) >>>> gen_illegal_exception(dc); >>>> #else >>>> TCGv_i32 im = tcg_const_i32(tmp); >>>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); >>>> tcg_temp_free_i32(im); >>>> #endif >>>> } >>>> break; >>>> >>> >>> -- >>> Thanks. >>> -- Max >> >> Regards, >> Jia. Regards, Jia
On Sun, Jul 15, 2012 at 12:39 AM, Jia Liu <proljc@gmail.com> wrote: > Hi Blue > > On Sat, Jul 14, 2012 at 10:42 PM, Blue Swirl <blauwirbel@gmail.com> wrote: >> On Sat, Jul 14, 2012 at 2:08 PM, Jia Liu <proljc@gmail.com> wrote: >>> Hi Max >>> >>> On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote: >>>>>> I don't think so, please check for example target-ppc/translate.c:4192 >>>>>> on how supervisor only mfsr is handled there. >>>>>> >>>>> >>>>> Thank you for comment, Blue. >>>>> >>>>> is this code OK? >>>> >>>> Shouldn't there also be an exception in softmmu mode >>>> if the CPU is not in supervisor mode? >>>> >>> >>> Sorry, I... >>> May you give me more comment? I'm not sure about this. >> >> If a user tries to execute a supervisor instruction (only allowed for >> kernel level code, not applications), the instruction won't be >> executed but an exception will be raised. >> >> This is the PPC mfsr instruction part of target-ppc/translate.c: >> /* mfsr */ >> static void gen_mfsr(DisasContext *ctx) >> { >> #if defined(CONFIG_USER_ONLY) >> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); >> #else >> TCGv t0; >> if (unlikely(!ctx->mem_idx)) { >> >> Here the MMU mode is checked for user mode. I'd use more explicit >> check ctx->mmu_idx == MMU_USER_IDX. >> >> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); >> return; >> } >> t0 = tcg_const_tl(SR(ctx->opcode)); >> gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); >> tcg_temp_free(t0); >> #endif >> } >> > > Thank you very much for this nice example. > Is this code OK? > case 0x2d: /* l.mfspr */ > LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); > { > #if defined(CONFIG_USER_ONLY) > gen_illegal_exception(dc); > #else > TCGv_i32 ti = tcg_const_i32(I16); > if (dc->mem_idx == MMU_USER_IDX) { > gen_illegal_exception(dc); > return; > } > gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti); > tcg_temp_free_i32(ti); > #endif > } > break; > > case 0x30: /* l.mtspr */ > LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); > { > #if defined(CONFIG_USER_ONLY) > gen_illegal_exception(dc); Maybe return? > #else > TCGv_i32 im = tcg_const_i32(tmp); > if (dc->mem_idx == MMU_USER_IDX) { > gen_illegal_exception(dc); > return; > } > gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); > tcg_temp_free_i32(im); > #endif > } > break; Otherwise looks OK. Perhaps there are other supervisor mode only instructions which need this kind of checks? > > >>> >>>>> >>>>> case 0x2d: /* l.mfspr */ >>>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); >>>>> { >>>>> #if defined(CONFIG_USER_ONLY) >>>>> gen_illegal_exception(dc); >>>>> #else >>>>> 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); >>>>> #endif >>>>> } >>>>> break; >>>>> >>>>> case 0x30: /* l.mtspr */ >>>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); >>>>> { >>>>> #if defined(CONFIG_USER_ONLY) >>>>> gen_illegal_exception(dc); >>>>> #else >>>>> TCGv_i32 im = tcg_const_i32(tmp); >>>>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); >>>>> tcg_temp_free_i32(im); >>>>> #endif >>>>> } >>>>> break; >>>>> >>>> >>>> -- >>>> Thanks. >>>> -- Max >>> >>> Regards, >>> Jia. > > Regards, > Jia
Hi Blue, On Sun, Jul 15, 2012 at 3:54 PM, Blue Swirl <blauwirbel@gmail.com> wrote: > On Sun, Jul 15, 2012 at 12:39 AM, Jia Liu <proljc@gmail.com> wrote: >> Hi Blue >> >> On Sat, Jul 14, 2012 at 10:42 PM, Blue Swirl <blauwirbel@gmail.com> wrote: >>> On Sat, Jul 14, 2012 at 2:08 PM, Jia Liu <proljc@gmail.com> wrote: >>>> Hi Max >>>> >>>> On Sat, Jul 14, 2012 at 9:49 PM, Max Filippov <jcmvbkbc@gmail.com> wrote: >>>>>>> I don't think so, please check for example target-ppc/translate.c:4192 >>>>>>> on how supervisor only mfsr is handled there. >>>>>>> >>>>>> >>>>>> Thank you for comment, Blue. >>>>>> >>>>>> is this code OK? >>>>> >>>>> Shouldn't there also be an exception in softmmu mode >>>>> if the CPU is not in supervisor mode? >>>>> >>>> >>>> Sorry, I... >>>> May you give me more comment? I'm not sure about this. >>> >>> If a user tries to execute a supervisor instruction (only allowed for >>> kernel level code, not applications), the instruction won't be >>> executed but an exception will be raised. >>> >>> This is the PPC mfsr instruction part of target-ppc/translate.c: >>> /* mfsr */ >>> static void gen_mfsr(DisasContext *ctx) >>> { >>> #if defined(CONFIG_USER_ONLY) >>> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); >>> #else >>> TCGv t0; >>> if (unlikely(!ctx->mem_idx)) { >>> >>> Here the MMU mode is checked for user mode. I'd use more explicit >>> check ctx->mmu_idx == MMU_USER_IDX. >>> >>> gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); >>> return; >>> } >>> t0 = tcg_const_tl(SR(ctx->opcode)); >>> gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], cpu_env, t0); >>> tcg_temp_free(t0); >>> #endif >>> } >>> >> >> Thank you very much for this nice example. >> Is this code OK? >> case 0x2d: /* l.mfspr */ >> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); >> { >> #if defined(CONFIG_USER_ONLY) >> gen_illegal_exception(dc); >> #else >> TCGv_i32 ti = tcg_const_i32(I16); >> if (dc->mem_idx == MMU_USER_IDX) { >> gen_illegal_exception(dc); >> return; >> } >> gen_helper_mfspr(cpu_R[rd], cpu_env, cpu_R[rd], cpu_R[ra], ti); >> tcg_temp_free_i32(ti); >> #endif >> } >> break; >> >> case 0x30: /* l.mtspr */ >> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); >> { >> #if defined(CONFIG_USER_ONLY) >> gen_illegal_exception(dc); > > Maybe return? Thank you! I think return is a better way. > >> #else >> TCGv_i32 im = tcg_const_i32(tmp); >> if (dc->mem_idx == MMU_USER_IDX) { >> gen_illegal_exception(dc); >> return; >> } >> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); >> tcg_temp_free_i32(im); >> #endif >> } >> break; > > > Otherwise looks OK. Perhaps there are other supervisor mode only > instructions which need this kind of checks? > I'll make a check, thank you. >> >> >>>> >>>>>> >>>>>> case 0x2d: /* l.mfspr */ >>>>>> LOG_DIS("l.mfspr r%d, r%d, %d\n", rd, ra, I16); >>>>>> { >>>>>> #if defined(CONFIG_USER_ONLY) >>>>>> gen_illegal_exception(dc); >>>>>> #else >>>>>> 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); >>>>>> #endif >>>>>> } >>>>>> break; >>>>>> >>>>>> case 0x30: /* l.mtspr */ >>>>>> LOG_DIS("l.mtspr %d, r%d, r%d, %d\n", I5, ra, rb, I11); >>>>>> { >>>>>> #if defined(CONFIG_USER_ONLY) >>>>>> gen_illegal_exception(dc); >>>>>> #else >>>>>> TCGv_i32 im = tcg_const_i32(tmp); >>>>>> gen_helper_mtspr(cpu_env, cpu_R[ra], cpu_R[rb], im); >>>>>> tcg_temp_free_i32(im); >>>>>> #endif >>>>>> } >>>>>> break; >>>>>> >>>>> >>>>> -- >>>>> Thanks. >>>>> -- Max >>>> >>>> Regards, >>>> Jia. >> >> Regards, >> Jia Regards, Jia
diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs index 926fc2f..44dc539 100644 --- a/target-openrisc/Makefile.objs +++ b/target-openrisc/Makefile.objs @@ -1,4 +1,4 @@ obj-$(CONFIG_SOFTMMU) += machine.o obj-y += cpu.o exception.o interrupt.o mmu.o translate.o obj-y += exception_helper.o fpu_helper.o int_helper.o \ - interrupt_helper.o mmu_helper.o + interrupt_helper.o mmu_helper.o sys_helper.o diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index df07eaf..6506665 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -80,6 +80,9 @@ enum { (reg) |= ((v & 0x1f) << 2);\ } while (0) +/* Version Register */ +#define SPR_VR 0xFFFF003F + /* Internal flags, delay slot flag */ #define D_FLAG 1 diff --git a/target-openrisc/helper.h b/target-openrisc/helper.h index 6eb259a..836a70b 100644 --- a/target-openrisc/helper.h +++ b/target-openrisc/helper.h @@ -63,4 +63,8 @@ DEF_HELPER_FLAGS_3(mul32, 0, tl, env, 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, tl, 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..7ff8e15 --- /dev/null +++ b/target-openrisc/sys_helper.c @@ -0,0 +1,287 @@ +/* + * 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) +{ +#ifndef CONFIG_USER_ONLY + int spr = (ra | offset); + int idx; + + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); + + 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->cpu_openrisc_map_address_data = + &cpu_openrisc_get_phys_data; + } else { + env->tlb->cpu_openrisc_map_address_data = + &cpu_openrisc_get_phys_nommu; + } + + if (env->sr & SR_IME) { + env->tlb->cpu_openrisc_map_address_code = + &cpu_openrisc_get_phys_code; + } else { + env->tlb->cpu_openrisc_map_address_code = + &cpu_openrisc_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 */ + env->picmr |= rb; + break; + case TO_SPR(9, 2): /* PICSR */ + env->picsr &= ~rb; + break; + case TO_SPR(10, 0): /* TTMR */ + { + int ip = env->ttmr & TTMR_IP; + + if (rb & TTMR_IP) { /* Keep IP bit. */ + env->ttmr = (rb & ~TTMR_IP) + ip; + } else { /* Clear IP bit. */ + env->ttmr = rb & ~TTMR_IP; + env->interrupt_request &= ~CPU_INTERRUPT_TIMER; + } + + cpu_openrisc_count_update(cpu); + + switch (env->ttmr & TTMR_M) { + case TIMER_NONE: + cpu_openrisc_count_stop(cpu); + break; + case TIMER_INTR: + cpu_openrisc_count_start(cpu); + break; + case TIMER_SHOT: + cpu_openrisc_count_start(cpu); + break; + case TIMER_CONT: + cpu_openrisc_count_start(cpu); + break; + default: + break; + } + } + break; + + case TO_SPR(10, 1): /* TTCR */ + env->ttcr = rb; + if (env->ttmr & TIMER_NONE) { + return; + } + cpu_openrisc_count_start(cpu); + 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; + + OpenRISCCPU *cpu = OPENRISC_CPU(ENV_GET_CPU(env)); + + 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 */ + cpu_openrisc_count_update(cpu); + return env->ttcr; + + default: + break; + } +#endif + +/*If we 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;*/ + + /* for rd is passed in, if rd unchanged, just keep it back. */ + return rd; +} diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index ed25604..8069edb 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -995,10 +995,20 @@ static void dec_misc(DisasContext *dc, 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); + 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; /* not used yet, open it when we need or64. */
Add OpenRISC system instructions. Signed-off-by: Jia Liu <proljc@gmail.com> --- target-openrisc/Makefile.objs | 2 +- target-openrisc/cpu.h | 3 + target-openrisc/helper.h | 4 + target-openrisc/sys_helper.c | 287 +++++++++++++++++++++++++++++++++++++++++ target-openrisc/translate.c | 10 ++ 5 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 target-openrisc/sys_helper.c