diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index bb9540f..70ac481 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -58,6 +58,7 @@ typedef struct OpenRISCCPUClass {
 } OpenRISCCPUClass;
 
 #define NB_MMU_MODES    3
+#define TARGET_INSN_START_EXTRA_WORDS 1
 
 enum {
     MMU_NOMMU_IDX = 0,
@@ -275,7 +276,6 @@ typedef struct CPUOpenRISCTLBContext {
 typedef struct CPUOpenRISCState {
     target_ulong gpr[32];     /* General registers */
     target_ulong pc;          /* Program counter */
-    target_ulong npc;         /* Next PC */
     target_ulong ppc;         /* Prev PC */
     target_ulong jmp_pc;      /* Jump PC */
 
diff --git a/target-openrisc/gdbstub.c b/target-openrisc/gdbstub.c
index 31ea013..2a4821f 100644
--- a/target-openrisc/gdbstub.c
+++ b/target-openrisc/gdbstub.c
@@ -34,8 +34,8 @@ int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
         case 32:    /* PPC */
             return gdb_get_reg32(mem_buf, env->ppc);
 
-        case 33:    /* NPC */
-            return gdb_get_reg32(mem_buf, env->npc);
+        case 33:    /* NPC (equals PC) */
+            return gdb_get_reg32(mem_buf, env->pc);
 
         case 34:    /* SR */
             return gdb_get_reg32(mem_buf, cpu_get_sr(env));
@@ -68,8 +68,13 @@ int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
             env->ppc = tmp;
             break;
 
-        case 33: /* NPC */
-            env->npc = tmp;
+        case 33: /* NPC (equals PC) */
+            /* If setting PC to something different,
+               also clear delayed branch status.  */
+            if (env->pc != tmp) {
+                env->pc = tmp;
+                env->flags = 0;
+            }
             break;
 
         case 34: /* SR */
diff --git a/target-openrisc/interrupt_helper.c b/target-openrisc/interrupt_helper.c
index 68d1598..00817d8 100644
--- a/target-openrisc/interrupt_helper.c
+++ b/target-openrisc/interrupt_helper.c
@@ -32,7 +32,6 @@ void HELPER(rfe)(CPUOpenRISCState *env)
                          (cpu->env.esr & (SR_SM | SR_IME | SR_DME));
 #endif
     cpu->env.pc = cpu->env.epcr;
-    cpu->env.npc = cpu->env.epcr;
     cpu_set_sr(&cpu->env, cpu->env.esr);
     cpu->env.lock_addr = -1;
 
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
index 17b0c77..a984929 100644
--- a/target-openrisc/machine.c
+++ b/target-openrisc/machine.c
@@ -26,8 +26,8 @@
 
 static const VMStateDescription vmstate_env = {
     .name = "env",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32_ARRAY(gpr, CPUOpenRISCState, 32),
         VMSTATE_UINT32(sr, CPUOpenRISCState),
@@ -36,7 +36,6 @@ static const VMStateDescription vmstate_env = {
         VMSTATE_UINT32(esr, CPUOpenRISCState),
         VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
         VMSTATE_UINT32(pc, CPUOpenRISCState),
-        VMSTATE_UINT32(npc, CPUOpenRISCState),
         VMSTATE_UINT32(ppc, CPUOpenRISCState),
         VMSTATE_END_OF_LIST()
     }
diff --git a/target-openrisc/sys_helper.c b/target-openrisc/sys_helper.c
index 1530558..1103a7b 100644
--- a/target-openrisc/sys_helper.c
+++ b/target-openrisc/sys_helper.c
@@ -27,20 +27,26 @@
 
 void HELPER(mtspr)(CPUOpenRISCState *env, uint32_t spr, target_ulong rb)
 {
+    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
 #ifndef CONFIG_USER_ONLY
     int idx;
 #endif
 
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
-
     switch (spr) {
     case TO_SPR(0, 0): /* VR */
         env->vr = rb;
         break;
 
     case TO_SPR(0, 16): /* NPC */
-        env->npc = rb;
+        cpu_restore_state(cs, GETPC());
+        /* ??? Mirror or1ksim in not trashing delayed branch state
+           when "jumping" to the current instruction.  */
+        if (env->pc != rb) {
+            env->pc = rb;
+            env->flags = 0;
+            cpu_loop_exit(cs);
+        }
         break;
 
     case TO_SPR(0, 17): /* SR */
@@ -181,8 +187,9 @@ void HELPER(mtspr)(CPUOpenRISCState *env, uint32_t spr, target_ulong rb)
 
 target_ulong HELPER(mfspr)(CPUOpenRISCState *env, uint32_t spr)
 {
-#ifndef CONFIG_USER_ONLY
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
+#ifndef CONFIG_USER_ONLY
     int idx;
 #endif
 
@@ -202,13 +209,15 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, uint32_t spr)
     case TO_SPR(0, 4): /* IMMUCFGR */
         return env->immucfgr;
 
-    case TO_SPR(0, 16): /* NPC */
-        return env->npc;
+    case TO_SPR(0, 16): /* NPC (equals PC) */
+        cpu_restore_state(cs, GETPC());
+        return env->pc;
 
     case TO_SPR(0, 17): /* SR */
         return cpu_get_sr(env);
 
     case TO_SPR(0, 18): /* PPC */
+        cpu_restore_state(cs, GETPC());
         return env->ppc;
 
     case TO_SPR(0, 32): /* EPCR */
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 7804edd..70aadbc 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -40,7 +40,7 @@
 
 typedef struct DisasContext {
     TranslationBlock *tb;
-    target_ulong pc, ppc, npc;
+    target_ulong pc;
     uint32_t tb_flags, synced_flags, flags;
     uint32_t is_jmp;
     uint32_t mem_idx;
@@ -53,7 +53,6 @@ static TCGv cpu_sr;
 static TCGv cpu_R[32];
 static TCGv cpu_pc;
 static TCGv jmp_pc;            /* l.jr/l.jalr temp pc */
-static TCGv cpu_npc;
 static TCGv cpu_ppc;
 static TCGv cpu_sr_f;           /* bf/bnf, F flag taken */
 static TCGv cpu_sr_cy;          /* carry (unsigned overflow) */
@@ -83,8 +82,6 @@ void openrisc_translate_init(void)
                                        "flags");
     cpu_pc = tcg_global_mem_new(cpu_env,
                                 offsetof(CPUOpenRISCState, pc), "pc");
-    cpu_npc = tcg_global_mem_new(cpu_env,
-                                 offsetof(CPUOpenRISCState, npc), "npc");
     cpu_ppc = tcg_global_mem_new(cpu_env,
                                  offsetof(CPUOpenRISCState, ppc), "ppc");
     jmp_pc = tcg_global_mem_new(cpu_env,
@@ -1504,7 +1501,6 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     dc->tb = tb;
 
     dc->is_jmp = DISAS_NEXT;
-    dc->ppc = pc_start;
     dc->pc = pc_start;
     dc->flags = cpu->env.cpucfgr;
     dc->mem_idx = cpu_mmu_index(&cpu->env, false);
@@ -1530,7 +1526,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     gen_tb_start(tb);
 
     do {
-        tcg_gen_insn_start(dc->pc);
+        tcg_gen_insn_start(dc->pc, num_insns != 0);
         num_insns++;
 
         if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
@@ -1548,12 +1544,9 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
-        dc->ppc = dc->pc - 4;
-        dc->npc = dc->pc + 4;
-        tcg_gen_movi_tl(cpu_ppc, dc->ppc);
-        tcg_gen_movi_tl(cpu_npc, dc->npc);
         disas_openrisc_insn(dc, cpu);
-        dc->pc = dc->npc;
+        dc->pc = dc->pc + 4;
+
         /* delay slot */
         if (dc->delayed_branch) {
             dc->delayed_branch--;
@@ -1561,10 +1554,8 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
                 dc->tb_flags &= ~D_FLAG;
                 gen_sync_flags(dc);
                 tcg_gen_mov_tl(cpu_pc, jmp_pc);
-                tcg_gen_mov_tl(cpu_npc, jmp_pc);
-                tcg_gen_movi_tl(jmp_pc, 0);
-                tcg_gen_exit_tb(0);
-                dc->is_jmp = DISAS_JUMP;
+                tcg_gen_discard_tl(jmp_pc);
+                dc->is_jmp = DISAS_UPDATE;
                 break;
             }
         }
@@ -1578,14 +1569,13 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end();
     }
+
+    tcg_gen_movi_tl(cpu_ppc, dc->pc - 4);
     if (dc->is_jmp == DISAS_NEXT) {
         dc->is_jmp = DISAS_UPDATE;
         tcg_gen_movi_tl(cpu_pc, dc->pc);
     }
     if (unlikely(cs->singlestep_enabled)) {
-        if (dc->is_jmp == DISAS_NEXT) {
-            tcg_gen_movi_tl(cpu_pc, dc->pc);
-        }
         gen_exception(dc, EXCP_DEBUG);
     } else {
         switch (dc->is_jmp) {
@@ -1641,4 +1631,7 @@ void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
                           target_ulong *data)
 {
     env->pc = data[0];
+    if (data[1]) {
+        env->ppc = env->pc - 4;
+    }
 }
