summary refs log tree commit diff stats
path: root/target-openrisc
diff options
context:
space:
mode:
Diffstat (limited to 'target-openrisc')
-rw-r--r--target-openrisc/cpu.h1
-rw-r--r--target-openrisc/interrupt.c25
-rw-r--r--target-openrisc/mmu.c4
-rw-r--r--target-openrisc/sys_helper.c54
-rw-r--r--target-openrisc/translate.c95
5 files changed, 89 insertions, 90 deletions
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 8fd0bc0bf0..0f9efdf6de 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -373,6 +373,7 @@ void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
 /* hw/openrisc_timer.c */
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
 void cpu_openrisc_count_update(OpenRISCCPU *cpu);
+void cpu_openrisc_timer_update(OpenRISCCPU *cpu);
 void cpu_openrisc_count_start(OpenRISCCPU *cpu);
 void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
 
diff --git a/target-openrisc/interrupt.c b/target-openrisc/interrupt.c
index 16ef4b3e79..2153e7ea7e 100644
--- a/target-openrisc/interrupt.c
+++ b/target-openrisc/interrupt.c
@@ -30,26 +30,15 @@ void openrisc_cpu_do_interrupt(CPUState *cs)
     OpenRISCCPU *cpu = OPENRISC_CPU(cs);
     CPUOpenRISCState *env = &cpu->env;
 #ifndef CONFIG_USER_ONLY
-    if (env->flags & D_FLAG) { /* Delay Slot insn */
+
+    env->epcr = env->pc;
+    if (env->flags & D_FLAG) {
         env->flags &= ~D_FLAG;
         env->sr |= SR_DSX;
-        if (env->exception_index == EXCP_TICK    ||
-            env->exception_index == EXCP_INT     ||
-            env->exception_index == EXCP_SYSCALL ||
-            env->exception_index == EXCP_FPE) {
-            env->epcr = env->jmp_pc;
-        } else {
-            env->epcr = env->pc - 4;
-        }
-    } else {
-        if (env->exception_index == EXCP_TICK    ||
-            env->exception_index == EXCP_INT     ||
-            env->exception_index == EXCP_SYSCALL ||
-            env->exception_index == EXCP_FPE) {
-            env->epcr = env->npc;
-        } else {
-            env->epcr = env->pc;
-        }
+        env->epcr -= 4;
+    }
+    if (env->exception_index == EXCP_SYSCALL) {
+        env->epcr += 4;
     }
 
     /* For machine-state changed between user-mode and supervisor mode,
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
index 22d7cbec18..dd487bd0d1 100644
--- a/target-openrisc/mmu.c
+++ b/target-openrisc/mmu.c
@@ -32,7 +32,7 @@ int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
                                 int *prot, target_ulong address, int rw)
 {
     *physical = address;
-    *prot = PAGE_READ | PAGE_WRITE;
+    *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
     return TLBRET_MATCH;
 }
 
@@ -187,7 +187,7 @@ int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
 
     if (ret == TLBRET_MATCH) {
         tlb_set_page(env, address & TARGET_PAGE_MASK,
-                     physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
+                     physical & TARGET_PAGE_MASK, prot,
                      mmu_idx, TARGET_PAGE_SIZE);
         ret = 0;
     } else if (ret < 0) {
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index cccbc0e939..be06c4565b 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -81,7 +81,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     case TO_SPR(0, 64): /* ESR */
         env->esr = rb;
         break;
-    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+    case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* 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);
@@ -89,7 +89,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         env->tlb->dtlb[0][idx].mr = rb;
         break;
 
-    case TO_SPR(1, 640) ... TO_SPR(1, 767): /* DTLBW0TR 0-127 */
+    case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
         idx = spr - TO_SPR(1, 640);
         env->tlb->dtlb[0][idx].tr = rb;
         break;
@@ -100,7 +100,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
     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 */
+    case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1):   /* 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);
@@ -108,7 +108,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         env->tlb->itlb[0][idx].mr = rb;
         break;
 
-    case TO_SPR(2, 640) ... TO_SPR(2, 767): /* ITLBW0TR 0-127 */
+    case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
         idx = spr - TO_SPR(2, 640);
         env->tlb->itlb[0][idx].tr = rb;
         break;
@@ -127,33 +127,31 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         break;
     case TO_SPR(10, 0): /* TTMR */
         {
+            if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) {
+                switch (rb & TTMR_M) {
+                case TIMER_NONE:
+                    cpu_openrisc_count_stop(cpu);
+                    break;
+                case TIMER_INTR:
+                case TIMER_SHOT:
+                case TIMER_CONT:
+                    cpu_openrisc_count_start(cpu);
+                    break;
+                default:
+                    break;
+                }
+            }
+
             int ip = env->ttmr & TTMR_IP;
 
             if (rb & TTMR_IP) {    /* Keep IP bit.  */
-                env->ttmr = (rb & ~TTMR_IP) + ip;
+                env->ttmr = (rb & ~TTMR_IP) | ip;
             } else {    /* Clear IP bit.  */
                 env->ttmr = rb & ~TTMR_IP;
                 cs->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;
-            }
+            cpu_openrisc_timer_update(cpu);
         }
         break;
 
@@ -162,7 +160,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         if (env->ttmr & TIMER_NONE) {
             return;
         }
-        cpu_openrisc_count_start(cpu);
+        cpu_openrisc_timer_update(cpu);
         break;
     default:
 
@@ -214,11 +212,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
     case TO_SPR(0, 64): /* ESR */
         return env->esr;
 
-    case TO_SPR(1, 512) ... TO_SPR(1, 639): /* DTLBW0MR 0-127 */
+    case TO_SPR(1, 512) ... TO_SPR(1, 512+DTLB_SIZE-1): /* 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 */
+    case TO_SPR(1, 640) ... TO_SPR(1, 640+DTLB_SIZE-1): /* DTLBW0TR 0-127 */
         idx = spr - TO_SPR(1, 640);
         return env->tlb->dtlb[0][idx].tr;
 
@@ -230,11 +228,11 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
     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 */
+    case TO_SPR(2, 512) ... TO_SPR(2, 512+ITLB_SIZE-1): /* 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 */
+    case TO_SPR(2, 640) ... TO_SPR(2, 640+ITLB_SIZE-1): /* ITLBW0TR 0-127 */
         idx = spr - TO_SPR(2, 640);
         return env->tlb->itlb[0][idx].tr;
 
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 8908a2e32b..91c60ebaae 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -209,42 +209,49 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
 static void gen_jump(DisasContext *dc, uint32_t imm, uint32_t reg, uint32_t op0)
 {
     target_ulong tmp_pc;
-    int lab = gen_new_label();
-    TCGv sr_f = tcg_temp_new();
     /* N26, 26bits imm */
     tmp_pc = sign_extend((imm<<2), 26) + dc->pc;
-    tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
 
-    if (op0 == 0x00) {    /* l.j */
+    switch (op0) {
+    case 0x00:     /* l.j */
         tcg_gen_movi_tl(jmp_pc, tmp_pc);
-    } else if (op0 == 0x01) {    /* l.jal */
+        break;
+    case 0x01:     /* l.jal */
         tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
         tcg_gen_movi_tl(jmp_pc, tmp_pc);
-    } else if (op0 == 0x03) {    /* l.bnf */
-        tcg_gen_movi_tl(jmp_pc, dc->pc+8);
-        tcg_gen_brcondi_i32(TCG_COND_EQ, sr_f, SR_F, lab);
-        tcg_gen_movi_tl(jmp_pc, tmp_pc);
-        gen_set_label(lab);
-    } else if (op0 == 0x04) {    /* l.bf */
-        tcg_gen_movi_tl(jmp_pc, dc->pc+8);
-        tcg_gen_brcondi_i32(TCG_COND_NE, sr_f, SR_F, lab);
-        tcg_gen_movi_tl(jmp_pc, tmp_pc);
-        gen_set_label(lab);
-    } else if (op0 == 0x11) {    /* l.jr */
+        break;
+    case 0x03:     /* l.bnf */
+    case 0x04:     /* l.bf  */
+        {
+            int lab = gen_new_label();
+            TCGv sr_f = tcg_temp_new();
+            tcg_gen_movi_tl(jmp_pc, dc->pc+8);
+            tcg_gen_andi_tl(sr_f, cpu_sr, SR_F);
+            tcg_gen_brcondi_i32(op0 == 0x03 ? TCG_COND_EQ : TCG_COND_NE,
+                                sr_f, SR_F, lab);
+            tcg_gen_movi_tl(jmp_pc, tmp_pc);
+            gen_set_label(lab);
+            tcg_temp_free(sr_f);
+        }
+        break;
+    case 0x11:     /* l.jr */
         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
-    } else if (op0 == 0x12) {    /* l.jalr */
+        break;
+    case 0x12:     /* l.jalr */
         tcg_gen_movi_tl(cpu_R[9], (dc->pc + 8));
         tcg_gen_mov_tl(jmp_pc, cpu_R[reg]);
-    } else {
+        break;
+    default:
         gen_illegal_exception(dc);
+        break;
     }
 
-    tcg_temp_free(sr_f);
     dc->delayed_branch = 2;
     dc->tb_flags |= D_FLAG;
     gen_sync_flags(dc);
 }
 
+
 static void dec_calc(DisasContext *dc, uint32_t insn)
 {
     uint32_t op0, op1, op2;
@@ -904,29 +911,33 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
     case 0x27:    /* l.addi */
         LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
         {
-            int lab = gen_new_label();
-            TCGv_i64 ta = tcg_temp_new_i64();
-            TCGv_i64 td = tcg_temp_local_new_i64();
-            TCGv_i32 res = tcg_temp_local_new_i32();
-            TCGv_i32 sr_ove = tcg_temp_local_new_i32();
-            tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
-            tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
-            tcg_gen_trunc_i64_i32(res, td);
-            tcg_gen_shri_i64(td, td, 32);
-            tcg_gen_andi_i64(td, td, 0x3);
-            /* Jump to lab when no overflow.  */
-            tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
-            tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
-            tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
-            tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
-            tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
-            gen_exception(dc, EXCP_RANGE);
-            gen_set_label(lab);
-            tcg_gen_mov_i32(cpu_R[rd], res);
-            tcg_temp_free_i64(ta);
-            tcg_temp_free_i64(td);
-            tcg_temp_free_i32(res);
-            tcg_temp_free_i32(sr_ove);
+            if (I16 == 0) {
+                tcg_gen_mov_tl(cpu_R[rd], cpu_R[ra]);
+            } else {
+                int lab = gen_new_label();
+                TCGv_i64 ta = tcg_temp_new_i64();
+                TCGv_i64 td = tcg_temp_local_new_i64();
+                TCGv_i32 res = tcg_temp_local_new_i32();
+                TCGv_i32 sr_ove = tcg_temp_local_new_i32();
+                tcg_gen_extu_i32_i64(ta, cpu_R[ra]);
+                tcg_gen_addi_i64(td, ta, sign_extend(I16, 16));
+                tcg_gen_trunc_i64_i32(res, td);
+                tcg_gen_shri_i64(td, td, 32);
+                tcg_gen_andi_i64(td, td, 0x3);
+                /* Jump to lab when no overflow.  */
+                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x0, lab);
+                tcg_gen_brcondi_i64(TCG_COND_EQ, td, 0x3, lab);
+                tcg_gen_ori_i32(cpu_sr, cpu_sr, (SR_OV | SR_CY));
+                tcg_gen_andi_i32(sr_ove, cpu_sr, SR_OVE);
+                tcg_gen_brcondi_i32(TCG_COND_NE, sr_ove, SR_OVE, lab);
+                gen_exception(dc, EXCP_RANGE);
+                gen_set_label(lab);
+                tcg_gen_mov_i32(cpu_R[rd], res);
+                tcg_temp_free_i64(ta);
+                tcg_temp_free_i64(td);
+                tcg_temp_free_i32(res);
+                tcg_temp_free_i32(sr_ove);
+            }
         }
         break;