qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-ppc] [PATCH 16/32] ppc: Rework NIP updates vs. exception gener


From: David Gibson
Subject: Re: [Qemu-ppc] [PATCH 16/32] ppc: Rework NIP updates vs. exception generation
Date: Wed, 27 Jul 2016 12:19:39 +1000
User-agent: Mutt/1.6.2 (2016-07-01)

On Wed, Jul 27, 2016 at 08:21:10AM +1000, Benjamin Herrenschmidt wrote:
> We make env->nip almost always point to the faulting instruction,
> thus avoiding a mess of "store_current" vs "store_next" in the
> exception handling. The syscall exception knows to move the PC by
> 4 and that's really about it.
> 
> This actually fixes a number of cases where the translator was
> setting env->nip to ctx->nip - 4 (ie. the *current* instruction)
> but the program check exception handler would branch to
> "store_current" which applies another -4 offset.
> 
> Signed-off-by: Benjamin Herrenschmidt <address@hidden>

I'm having a fair bit of trouble wrapping my head around this.  Still
comments on a couple of small matters.

> ---
>  linux-user/main.c        |  12 ++--
>  target-ppc/excp_helper.c | 148 
> ++++++++++++++++++-----------------------------
>  target-ppc/translate.c   |  59 +++++++++++--------
>  3 files changed, 96 insertions(+), 123 deletions(-)
> 
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 462e820..1d149dc 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -1814,7 +1814,7 @@ void cpu_loop(CPUPPCState *env)
>                            env->error_code);
>                  break;
>              }
> -            info._sifields._sigfault._addr = env->nip - 4;
> +            info._sifields._sigfault._addr = env->nip;
>              queue_signal(env, info.si_signo, &info);
>              break;
>          case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  
> */
> @@ -1822,7 +1822,7 @@ void cpu_loop(CPUPPCState *env)
>              info.si_signo = TARGET_SIGILL;
>              info.si_errno = 0;
>              info.si_code = TARGET_ILL_COPROC;
> -            info._sifields._sigfault._addr = env->nip - 4;
> +            info._sifields._sigfault._addr = env->nip;
>              queue_signal(env, info.si_signo, &info);
>              break;
>          case POWERPC_EXCP_SYSCALL:  /* System call exception                 
> */
> @@ -1834,7 +1834,7 @@ void cpu_loop(CPUPPCState *env)
>              info.si_signo = TARGET_SIGILL;
>              info.si_errno = 0;
>              info.si_code = TARGET_ILL_COPROC;
> -            info._sifields._sigfault._addr = env->nip - 4;
> +            info._sifields._sigfault._addr = env->nip;
>              queue_signal(env, info.si_signo, &info);
>              break;
>          case POWERPC_EXCP_DECR:     /* Decrementer exception                 
> */
> @@ -1862,7 +1862,7 @@ void cpu_loop(CPUPPCState *env)
>              info.si_signo = TARGET_SIGILL;
>              info.si_errno = 0;
>              info.si_code = TARGET_ILL_COPROC;
> -            info._sifields._sigfault._addr = env->nip - 4;
> +            info._sifields._sigfault._addr = env->nip;
>              queue_signal(env, info.si_signo, &info);
>              break;
>          case POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      
> */
> @@ -1926,7 +1926,7 @@ void cpu_loop(CPUPPCState *env)
>              info.si_signo = TARGET_SIGILL;
>              info.si_errno = 0;
>              info.si_code = TARGET_ILL_COPROC;
> -            info._sifields._sigfault._addr = env->nip - 4;
> +            info._sifields._sigfault._addr = env->nip;
>              queue_signal(env, info.si_signo, &info);
>              break;
>          case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       
> */
> @@ -2001,9 +2001,9 @@ void cpu_loop(CPUPPCState *env)
>                               env->gpr[5], env->gpr[6], env->gpr[7],
>                               env->gpr[8], 0, 0);
>              if (ret == -TARGET_ERESTARTSYS) {
> -                env->nip -= 4;
>                  break;
>              }
> +            env->nip += 4;
>              if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
>                  /* Returning from a successful sigreturn syscall.
>                     Avoid corrupting register state.  */
> diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
> index 563c7bc..570d188 100644
> --- a/target-ppc/excp_helper.c
> +++ b/target-ppc/excp_helper.c
> @@ -198,7 +198,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>          default:
>              goto excp_invalid;
>          }
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_MCHECK:    /* Machine check exception                  
> */
>          if (msr_me == 0) {
>              /* Machine check exception is not enabled.
> @@ -209,7 +209,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>              if (qemu_log_separate()) {
>                  qemu_log("Machine check while not allowed. "
>                          "Entering checkstop state\n");
> -            }
> +             }

Looks like an accidental whitespace change.

>              cs->halted = 1;
>              cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
>          }
> @@ -235,16 +235,16 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>          default:
>              break;
>          }
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_DSI:       /* Data storage exception                   
> */
>          LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
>                   "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_ISI:       /* Instruction storage exception            
> */
>          LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
>                   "\n", msr, env->nip);
>          msr |= env->error_code;
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_EXTERNAL:  /* External input                           
> */
>          cs = CPU(cpu);
>  
> @@ -258,13 +258,14 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>              /* IACK the IRQ on delivery */
>              env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
>          }
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_ALIGN:     /* Alignment exception                      
> */
>          /* XXX: this is false */
>          /* Get rS/rD and rA from faulting opcode */
> -        env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
> +        /* Broken for LE mode */
> +        env->spr[SPR_DSISR] |= (cpu_ldl_code(env, env->nip)
>                                  & 0x03FF0000) >> 16;
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_PROGRAM:   /* Program exception                        
> */
>          switch (env->error_code & ~0xF) {
>          case POWERPC_EXCP_FP:
> @@ -280,15 +281,11 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>               * precise in the MSR.
>               */
>              msr |= 0x00100000;
> -            goto store_next;
> +            break;
>          case POWERPC_EXCP_INVAL:
>              LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
>              msr |= 0x00080000;
>              env->spr[SPR_BOOKE_ESR] = ESR_PIL;
> -            /* Some invalids will have the PC in the right place already */
> -            if (env->error_code & POWERPC_EXCP_INVAL_LSWX) {
> -                goto store_next;
> -            }
>              break;
>          case POWERPC_EXCP_PRIV:
>              msr |= 0x00040000;
> @@ -304,23 +301,16 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>                        env->error_code);
>              break;
>          }
> -        goto store_current;
> -    case POWERPC_EXCP_HV_EMU:
> -        srr0 = SPR_HSRR0;
> -        srr1 = SPR_HSRR1;
> -        new_msr |= (target_ulong)MSR_HVB;
> -        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
> -        /* Some invalids will have the PC in the right place already */
> -        if (env->error_code == (POWERPC_EXCP_INVAL|POWERPC_EXCP_INVAL_LSWX)) 
> {
> -                goto store_next;
> -        }
> -        goto store_current;
> -    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     
> */
> -        goto store_current;
> +        break;
>      case POWERPC_EXCP_SYSCALL:   /* System call exception                    
> */
>          dump_syscall(env);
>          lev = env->error_code;
>  
> +        /* We need to correct the NIP which in this case is supposed
> +         * to point to the next instruction
> +         */
> +        env->nip += 4;
> +
>          /* "PAPR mode" built-in hypercall emulation */
>          if ((lev == 1) && cpu_ppc_hypercall) {
>              cpu_ppc_hypercall(cpu);
> @@ -329,15 +319,15 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>          if (lev == 1) {
>              new_msr |= (target_ulong)MSR_HVB;
>          }
> -        goto store_next;
> +        break;
> +    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     
> */
>      case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          
> */
> -        goto store_current;
>      case POWERPC_EXCP_DECR:      /* Decrementer exception                    
> */
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           
> */
>          /* FIT on 4xx */
>          LOG_EXCP("FIT exception\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 
> */
>          LOG_EXCP("WDT exception\n");
>          switch (excp_model) {
> @@ -348,11 +338,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>          default:
>              break;
>          }
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_DTLB:      /* Data TLB error                           
> */
> -        goto store_next;
>      case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    
> */
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          
> */
>          switch (excp_model) {
>          case POWERPC_EXCP_BOOKE:
> @@ -367,33 +356,33 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>          }
>          /* XXX: TODO */
>          cpu_abort(cs, "Debug exception is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  
> */
>          env->spr[SPR_BOOKE_ESR] = ESR_SPV;
> -        goto store_current;
> +        break;
>      case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "Embedded floating point data exception "
>                    "is not implemented yet !\n");
>          env->spr[SPR_BOOKE_ESR] = ESR_SPV;
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "Embedded floating point round exception "
>                    "is not implemented yet !\n");
>          env->spr[SPR_BOOKE_ESR] = ESR_SPV;
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   
> */
>          /* XXX: TODO */
>          cpu_abort(cs,
>                    "Performance counter exception is not implemented yet 
> !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              
> */
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     
> */
>          srr0 = SPR_BOOKE_CSRR0;
>          srr1 = SPR_BOOKE_CSRR1;
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_RESET:     /* System reset exception                   
> */
>          if (msr_pow) {
>              /* indicate that we resumed from power save mode */
> @@ -404,65 +393,42 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>  
>          new_msr |= (target_ulong)MSR_HVB;
>          ail = 0;
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_DSEG:      /* Data segment exception                   
> */
> -        goto store_next;
>      case POWERPC_EXCP_ISEG:      /* Instruction segment exception            
> */
> -        goto store_next;
> -    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         
> */
> -        srr0 = SPR_HSRR0;
> -        srr1 = SPR_HSRR1;
> -        new_msr |= (target_ulong)MSR_HVB;
> -        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
> -        goto store_next;
>      case POWERPC_EXCP_TRACE:     /* Trace exception                          
> */
> -        goto store_next;
> +        break;
> +    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         
> */
>      case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        
> */
> -        srr0 = SPR_HSRR0;
> -        srr1 = SPR_HSRR1;
> -        new_msr |= (target_ulong)MSR_HVB;
> -        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
> -        goto store_next;
>      case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception 
> */
> -        srr0 = SPR_HSRR0;
> -        srr1 = SPR_HSRR1;
> -        new_msr |= (target_ulong)MSR_HVB;
> -        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
> -        goto store_next;
>      case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        
> */
> -        srr0 = SPR_HSRR0;
> -        srr1 = SPR_HSRR1;
> -        new_msr |= (target_ulong)MSR_HVB;
> -        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
> -        goto store_next;
>      case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception 
> */
> +    case POWERPC_EXCP_HV_EMU:
>          srr0 = SPR_HSRR0;
>          srr1 = SPR_HSRR1;
>          new_msr |= (target_ulong)MSR_HVB;
>          new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_VPU:       /* Vector unavailable exception             
> */
> -        goto store_current;
>      case POWERPC_EXCP_VSXU:       /* VSX unavailable exception               
> */
> -        goto store_current;
>      case POWERPC_EXCP_FU:         /* Facility unavailable exception          
> */
> -        goto store_current;
> +        break;
>      case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    
> */
>          LOG_EXCP("PIT exception\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_IO:        /* IO error exception                       
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_RUNM:      /* Run mode exception                       
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "602 emulation trap exception "
>                    "is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              
> */
>          switch (excp_model) {
>          case POWERPC_EXCP_602:
> @@ -577,71 +543,67 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
> excp_model, int excp)
>              cpu_abort(cs, "Invalid data store TLB miss exception\n");
>              break;
>          }
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_FPA:       /* Floating-point assist exception          
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "Floating point assist exception "
>                    "is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_DABR:      /* Data address breakpoint                  
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "DABR exception is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "IABR exception is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_SMI:       /* System management interrupt              
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "SMI exception is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_THERM:     /* Thermal interrupt                        
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "Thermal management exception "
>                    "is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   
> */
>          /* XXX: TODO */
>          cpu_abort(cs,
>                    "Performance counter exception is not implemented yet 
> !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_VPUA:      /* Vector assist exception                  
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     
> */
>          /* XXX: TODO */
>          cpu_abort(cs,
>                    "970 soft-patch exception is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_MAINT:     /* Maintenance exception                    
> */
>          /* XXX: TODO */
>          cpu_abort(cs,
>                    "970 maintenance exception is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "Maskable external exception "
>                    "is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         
> */
>          /* XXX: TODO */
>          cpu_abort(cs, "Non maskable external exception "
>                    "is not implemented yet !\n");
> -        goto store_next;
> +        break;
>      default:
>      excp_invalid:
>          cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
>          break;
> -    store_current:
> -        /* save current instruction location */
> -        env->spr[srr0] = env->nip - 4;
> -        break;
> -    store_next:
> -        /* save next instruction location */
> -        env->spr[srr0] = env->nip;
> -        break;
>      }
> +
> +    /* Save PC */
> +    env->spr[srr0] = env->nip;
> +
>      /* Save MSR */
>      env->spr[srr1] = msr;
>  
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index c4f8916..84bcb09 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -276,8 +276,12 @@ void gen_update_current_nip(void *opaque)
>  static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t 
> error)
>  {
>      TCGv_i32 t0, t1;
> +
> +    /* These are all synchronous exceptions, we set the PC back to
> +     * the faulting instruction
> +     */
>      if (ctx->exception == POWERPC_EXCP_NONE) {
> -        gen_update_nip(ctx, ctx->nip);
> +        gen_update_nip(ctx, ctx->nip - 4);
>      }
>      t0 = tcg_const_i32(excp);
>      t1 = tcg_const_i32(error);
> @@ -290,8 +294,12 @@ static void gen_exception_err(DisasContext *ctx, 
> uint32_t excp, uint32_t error)
>  static void gen_exception(DisasContext *ctx, uint32_t excp)
>  {
>      TCGv_i32 t0;
> +
> +    /* These are all synchronous exceptions, we set the PC back to
> +     * the faulting instruction
> +     */
>      if (ctx->exception == POWERPC_EXCP_NONE) {
> -        gen_update_nip(ctx, ctx->nip);
> +        gen_update_nip(ctx, ctx->nip - 4);
>      }
>      t0 = tcg_const_i32(excp);
>      gen_helper_raise_exception(cpu_env, t0);
> @@ -299,13 +307,28 @@ static void gen_exception(DisasContext *ctx, uint32_t 
> excp)
>      ctx->exception = (excp);
>  }
>  
> +static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
> +                              target_ulong nip)
> +{
> +    TCGv_i32 t0;
> +
> +    gen_update_nip(ctx, nip);
> +    t0 = tcg_const_i32(excp);
> +    gen_helper_raise_exception(cpu_env, t0);
> +    tcg_temp_free_i32(t0);
> +    ctx->exception = (excp);
> +}
> +
>  static void gen_debug_exception(DisasContext *ctx)
>  {
>      TCGv_i32 t0;
>  
> +    /* These are all synchronous exceptions, we set the PC back to
> +     * the faulting instruction
> +     */
>      if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
>          (ctx->exception != POWERPC_EXCP_SYNC)) {
> -        gen_update_nip(ctx, ctx->nip);
> +        gen_update_nip(ctx, ctx->nip - 4);
>      }
>      t0 = tcg_const_i32(EXCP_DEBUG);
>      gen_helper_raise_exception(cpu_env, t0);
> @@ -1437,7 +1460,7 @@ static void gen_pause(DisasContext *ctx)
>      tcg_temp_free_i32(t0);
>  
>      /* Stop translation, this gives other CPUs a chance to run */
> -    gen_exception_err(ctx, EXCP_HLT, 1);
> +    gen_exception_nip(ctx, EXCP_HLT, ctx->nip);
>  }
>  #endif /* defined(TARGET_PPC64) */
>  
> @@ -2697,12 +2720,6 @@ static void gen_lswi(DisasContext *ctx)
>          nb = 32;
>      nr = (nb + 3) / 4;
>      if (unlikely(lsw_reg_in_range(start, nr, ra))) {
> -        /* The handler expects the PC to point to *this* instruction,
> -         * so setting ctx->exception here prevents it from being
> -         * improperly updated again by gen_inval_exception
> -         */
> -        gen_update_nip(ctx, ctx->nip - 4);
> -        ctx->exception = POWERPC_EXCP_HV_EMU;
>          gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
>          return;
>      }
> @@ -2845,10 +2862,7 @@ static void gen_conditional_store(DisasContext *ctx, 
> TCGv EA,
>      tcg_gen_movi_tl(t0, (size << 5) | reg);
>      tcg_gen_st_tl(t0, cpu_env, offsetof(CPUPPCState, reserve_info));
>      tcg_temp_free(t0);
> -    gen_update_nip(ctx, ctx->nip-4);
> -    ctx->exception = POWERPC_EXCP_BRANCH;
> -    gen_exception(ctx, POWERPC_EXCP_STCX);
> -    ctx->exception = save_exception;
> +    gen_exception_err(ctx, POWERPC_EXCP_STCX, 0);
>  }
>  #else
>  static void gen_conditional_store(DisasContext *ctx, TCGv EA,
> @@ -2987,7 +3001,7 @@ static void gen_wait(DisasContext *ctx)
>                     -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
>      tcg_temp_free_i32(t0);
>      /* Stop translation, as the CPU is supposed to sleep from now */
> -    gen_exception_err(ctx, EXCP_HLT, 1);
> +    gen_exception_nip(ctx, EXCP_HLT, ctx->nip);
>  }
>  
>  #if defined(TARGET_PPC64)
> @@ -3090,10 +3104,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int 
> n, target_ulong dest)
>                  (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
>                  (ctx->exception == POWERPC_EXCP_BRANCH ||
>                   ctx->exception == POWERPC_EXCP_TRACE)) {
> -                target_ulong tmp = ctx->nip;
> -                ctx->nip = dest;
> -                gen_exception(ctx, POWERPC_EXCP_TRACE);
> -                ctx->nip = tmp;
> +                gen_exception_nip(ctx, POWERPC_EXCP_TRACE, dest);
>              }
>              if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
>                  gen_debug_exception(ctx);
> @@ -3362,7 +3373,7 @@ static void gen_tw(DisasContext *ctx)
>  {
>      TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
>      /* Update the nip since this might generate a trap exception */
> -    gen_update_nip(ctx, ctx->nip);
> +    gen_update_nip(ctx, ctx->nip - 4);

twi etc will generally resume from the next instruction if they trap,
yes?  In which case I'm a bit confused by the nip - 4.  But possibly I
just haven't correctly followed all the nip update logic changed by
this patch.

>      gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], 
> cpu_gpr[rB(ctx->opcode)],
>                    t0);
>      tcg_temp_free_i32(t0);
> @@ -3374,7 +3385,7 @@ static void gen_twi(DisasContext *ctx)
>      TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
>      TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
>      /* Update the nip since this might generate a trap exception */
> -    gen_update_nip(ctx, ctx->nip);
> +    gen_update_nip(ctx, ctx->nip - 4);
>      gen_helper_tw(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
>      tcg_temp_free(t0);
>      tcg_temp_free_i32(t1);
> @@ -3386,7 +3397,7 @@ static void gen_td(DisasContext *ctx)
>  {
>      TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
>      /* Update the nip since this might generate a trap exception */
> -    gen_update_nip(ctx, ctx->nip);
> +    gen_update_nip(ctx, ctx->nip - 4);
>      gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], 
> cpu_gpr[rB(ctx->opcode)],
>                    t0);
>      tcg_temp_free_i32(t0);
> @@ -3398,7 +3409,7 @@ static void gen_tdi(DisasContext *ctx)
>      TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
>      TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
>      /* Update the nip since this might generate a trap exception */
> -    gen_update_nip(ctx, ctx->nip);
> +    gen_update_nip(ctx, ctx->nip - 4);
>      gen_helper_td(cpu_env, cpu_gpr[rA(ctx->opcode)], t0, t1);
>      tcg_temp_free(t0);
>      tcg_temp_free_i32(t1);
> @@ -6757,7 +6768,7 @@ void gen_intermediate_code(CPUPPCState *env, struct 
> TranslationBlock *tb)
>                       ctx.exception != POWERPC_SYSCALL &&
>                       ctx.exception != POWERPC_EXCP_TRAP &&
>                       ctx.exception != POWERPC_EXCP_BRANCH)) {
> -            gen_exception(ctxp, POWERPC_EXCP_TRACE);
> +            gen_exception_nip(ctxp, POWERPC_EXCP_TRACE, ctx.nip);
>          } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
>                              (cs->singlestep_enabled) ||
>                              singlestep ||

-- 
David Gibson                    | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
                                | _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]