Commit 9fddaa0c0cabb610947146a79b4a9a38b0a216e5

Authored by bellard
1 parent 4a0fb71e

PowerPC merge: real time TB and decrementer - faster and simpler exception handling (Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@841 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
@@ -627,14 +627,15 @@ void cpu_single_step(CPUState *env, int enabled); @@ -627,14 +627,15 @@ void cpu_single_step(CPUState *env, int enabled);
627 if no page found. */ 627 if no page found. */
628 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr); 628 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
629 629
630 -#define CPU_LOG_TB_OUT_ASM (1 << 0)  
631 -#define CPU_LOG_TB_IN_ASM (1 << 1) 630 +#define CPU_LOG_TB_OUT_ASM (1 << 0)
  631 +#define CPU_LOG_TB_IN_ASM (1 << 1)
632 #define CPU_LOG_TB_OP (1 << 2) 632 #define CPU_LOG_TB_OP (1 << 2)
633 #define CPU_LOG_TB_OP_OPT (1 << 3) 633 #define CPU_LOG_TB_OP_OPT (1 << 3)
634 #define CPU_LOG_INT (1 << 4) 634 #define CPU_LOG_INT (1 << 4)
635 #define CPU_LOG_EXEC (1 << 5) 635 #define CPU_LOG_EXEC (1 << 5)
636 #define CPU_LOG_PCALL (1 << 6) 636 #define CPU_LOG_PCALL (1 << 6)
637 #define CPU_LOG_IOPORT (1 << 7) 637 #define CPU_LOG_IOPORT (1 << 7)
  638 +#define CPU_LOG_TB_CPU (1 << 8)
638 639
639 /* define log items */ 640 /* define log items */
640 typedef struct CPULogItem { 641 typedef struct CPULogItem {
cpu-exec.c
@@ -241,11 +241,25 @@ int cpu_exec(CPUState *env1) @@ -241,11 +241,25 @@ int cpu_exec(CPUState *env1)
241 #endif 241 #endif
242 } 242 }
243 #elif defined(TARGET_PPC) 243 #elif defined(TARGET_PPC)
  244 +#if 0
  245 + if ((interrupt_request & CPU_INTERRUPT_RESET)) {
  246 + cpu_ppc_reset(env);
  247 + }
  248 +#endif
  249 + if (msr_ee != 0) {
244 if ((interrupt_request & CPU_INTERRUPT_HARD)) { 250 if ((interrupt_request & CPU_INTERRUPT_HARD)) {
245 - do_queue_exception(EXCP_EXTERNAL);  
246 - if (check_exception_state(env)) 251 + /* Raise it */
  252 + env->exception_index = EXCP_EXTERNAL;
  253 + env->error_code = 0;
247 do_interrupt(env); 254 do_interrupt(env);
248 env->interrupt_request &= ~CPU_INTERRUPT_HARD; 255 env->interrupt_request &= ~CPU_INTERRUPT_HARD;
  256 + } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
  257 + /* Raise it */
  258 + env->exception_index = EXCP_DECR;
  259 + env->error_code = 0;
  260 + do_interrupt(env);
  261 + env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
  262 + }
249 } 263 }
250 #endif 264 #endif
251 if (interrupt_request & CPU_INTERRUPT_EXITTB) { 265 if (interrupt_request & CPU_INTERRUPT_EXITTB) {
@@ -757,7 +771,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, @@ -757,7 +771,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
757 /* we restore the process signal mask as the sigreturn should 771 /* we restore the process signal mask as the sigreturn should
758 do it (XXX: use sigsetjmp) */ 772 do it (XXX: use sigsetjmp) */
759 sigprocmask(SIG_SETMASK, old_set, NULL); 773 sigprocmask(SIG_SETMASK, old_set, NULL);
760 - do_queue_exception_err(env->exception_index, env->error_code); 774 + do_raise_exception_err(env->exception_index, env->error_code);
761 } else { 775 } else {
762 /* activate soft MMU for this block */ 776 /* activate soft MMU for this block */
763 cpu_resume_from_signal(env, puc); 777 cpu_resume_from_signal(env, puc);
@@ -1132,6 +1132,8 @@ CPULogItem cpu_log_items[] = { @@ -1132,6 +1132,8 @@ CPULogItem cpu_log_items[] = {
1132 "show interrupts/exceptions in short format" }, 1132 "show interrupts/exceptions in short format" },
1133 { CPU_LOG_EXEC, "exec", 1133 { CPU_LOG_EXEC, "exec",
1134 "show trace before each executed TB (lots of logs)" }, 1134 "show trace before each executed TB (lots of logs)" },
  1135 + { CPU_LOG_TB_CPU, "cpu",
  1136 + "show CPU state before bloc translation" },
1135 #ifdef TARGET_I386 1137 #ifdef TARGET_I386
1136 { CPU_LOG_PCALL, "pcall", 1138 { CPU_LOG_PCALL, "pcall",
1137 "show protected mode far calls/returns/exceptions" }, 1139 "show protected mode far calls/returns/exceptions" },
hw/ppc.c
@@ -28,6 +28,181 @@ void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device, @@ -28,6 +28,181 @@ void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
28 const char *kernel_filename, const char *kernel_cmdline, 28 const char *kernel_filename, const char *kernel_cmdline,
29 const char *initrd_filename); 29 const char *initrd_filename);
30 30
  31 +/*****************************************************************************/
  32 +/* PPC time base and decrementer emulation */
  33 +//#define DEBUG_TB
  34 +
  35 +struct ppc_tb_t {
  36 + /* Time base management */
  37 + int64_t tb_offset; /* Compensation */
  38 + uint32_t tb_freq; /* TB frequency */
  39 + /* Decrementer management */
  40 + uint64_t decr_next; /* Tick for next decr interrupt */
  41 + struct QEMUTimer *decr_timer;
  42 +};
  43 +
  44 +static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
  45 +{
  46 + /* TB time in tb periods */
  47 + return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
  48 + tb_env->tb_freq, ticks_per_sec);
  49 +}
  50 +
  51 +uint32_t cpu_ppc_load_tbl (CPUState *env)
  52 +{
  53 + ppc_tb_t *tb_env = env->tb_env;
  54 + uint64_t tb;
  55 +
  56 + tb = cpu_ppc_get_tb(tb_env);
  57 +#ifdef DEBUG_TB
  58 + {
  59 + static int last_time;
  60 + int now;
  61 + now = time(NULL);
  62 + if (last_time != now) {
  63 + last_time = now;
  64 + printf("%s: tb=0x%016lx %d %08lx\n",
  65 + __func__, tb, now, tb_env->tb_offset);
  66 + }
  67 + }
  68 +#endif
  69 +
  70 + return tb & 0xFFFFFFFF;
  71 +}
  72 +
  73 +uint32_t cpu_ppc_load_tbu (CPUState *env)
  74 +{
  75 + ppc_tb_t *tb_env = env->tb_env;
  76 + uint64_t tb;
  77 +
  78 + tb = cpu_ppc_get_tb(tb_env);
  79 +#ifdef DEBUG_TB
  80 + printf("%s: tb=0x%016lx\n", __func__, tb);
  81 +#endif
  82 + return tb >> 32;
  83 +}
  84 +
  85 +static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value)
  86 +{
  87 + tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
  88 + - qemu_get_clock(vm_clock);
  89 +#ifdef DEBUG_TB
  90 + printf("%s: tb=0x%016lx offset=%08x\n", __func__, value);
  91 +#endif
  92 +}
  93 +
  94 +void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
  95 +{
  96 + ppc_tb_t *tb_env = env->tb_env;
  97 +
  98 + cpu_ppc_store_tb(tb_env,
  99 + ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
  100 +}
  101 +
  102 +void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
  103 +{
  104 + ppc_tb_t *tb_env = env->tb_env;
  105 +
  106 + cpu_ppc_store_tb(tb_env,
  107 + ((uint64_t)cpu_ppc_load_tbu(env) << 32) | value);
  108 +}
  109 +
  110 +uint32_t cpu_ppc_load_decr (CPUState *env)
  111 +{
  112 + ppc_tb_t *tb_env = env->tb_env;
  113 + uint32_t decr;
  114 +
  115 + decr = muldiv64(tb_env->decr_next - qemu_get_clock(vm_clock),
  116 + tb_env->tb_freq, ticks_per_sec);
  117 +#ifdef DEBUG_TB
  118 + printf("%s: 0x%08x\n", __func__, decr);
  119 +#endif
  120 +
  121 + return decr;
  122 +}
  123 +
  124 +/* When decrementer expires,
  125 + * all we need to do is generate or queue a CPU exception
  126 + */
  127 +static inline void cpu_ppc_decr_excp (CPUState *env)
  128 +{
  129 + /* Raise it */
  130 +#ifdef DEBUG_TB
  131 + printf("raise decrementer exception\n");
  132 +#endif
  133 + cpu_interrupt(env, CPU_INTERRUPT_TIMER);
  134 +}
  135 +
  136 +static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
  137 + uint32_t value, int is_excp)
  138 +{
  139 + ppc_tb_t *tb_env = env->tb_env;
  140 + uint64_t now, next;
  141 +
  142 +#ifdef DEBUG_TB
  143 + printf("%s: 0x%08x => 0x%08x\n", __func__, decr, value);
  144 +#endif
  145 + now = qemu_get_clock(vm_clock);
  146 + next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
  147 + if (is_excp)
  148 + next += tb_env->decr_next - now;
  149 + if (next == now)
  150 + next++;
  151 + tb_env->decr_next = next;
  152 + /* Adjust timer */
  153 + qemu_mod_timer(tb_env->decr_timer, next);
  154 + /* If we set a negative value and the decrementer was positive,
  155 + * raise an exception.
  156 + */
  157 + if ((value & 0x80000000) && !(decr & 0x80000000))
  158 + cpu_ppc_decr_excp(env);
  159 +}
  160 +
  161 +void cpu_ppc_store_decr (CPUState *env, uint32_t value)
  162 +{
  163 + _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
  164 +}
  165 +
  166 +static void cpu_ppc_decr_cb (void *opaque)
  167 +{
  168 + _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
  169 +}
  170 +
  171 +/* Set up (once) timebase frequency (in Hz) */
  172 +ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
  173 +{
  174 + ppc_tb_t *tb_env;
  175 +
  176 + tb_env = qemu_mallocz(sizeof(ppc_tb_t));
  177 + if (tb_env == NULL)
  178 + return NULL;
  179 + env->tb_env = tb_env;
  180 + if (tb_env->tb_freq == 0 || 1) {
  181 + tb_env->tb_freq = freq;
  182 + /* Create new timer */
  183 + tb_env->decr_timer =
  184 + qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
  185 + /* There is a bug in 2.4 kernels:
  186 + * if a decrementer exception is pending when it enables msr_ee,
  187 + * it's not ready to handle it...
  188 + */
  189 + _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
  190 + }
  191 +
  192 + return tb_env;
  193 +}
  194 +
  195 +#if 0
  196 +/*****************************************************************************/
  197 +/* Handle system reset (for now, just stop emulation) */
  198 +void cpu_ppc_reset (CPUState *env)
  199 +{
  200 + printf("Reset asked... Stop emulation\n");
  201 + abort();
  202 +}
  203 +#endif
  204 +
  205 +/*****************************************************************************/
31 void ppc_init (int ram_size, int vga_ram_size, int boot_device, 206 void ppc_init (int ram_size, int vga_ram_size, int boot_device,
32 DisplayState *ds, const char **fd_filename, int snapshot, 207 DisplayState *ds, const char **fd_filename, int snapshot,
33 const char *kernel_filename, const char *kernel_cmdline, 208 const char *kernel_filename, const char *kernel_cmdline,
hw/ppc_prep.c
@@ -24,6 +24,9 @@ @@ -24,6 +24,9 @@
24 #include "vl.h" 24 #include "vl.h"
25 #include "m48t59.h" 25 #include "m48t59.h"
26 26
  27 +/* XXX: move all TB related stuff in ppc_prep.c and suppress ppc.c ? */
  28 +ppc_tb_t *cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq);
  29 +
27 //#define HARD_DEBUG_PPC_IO 30 //#define HARD_DEBUG_PPC_IO
28 //#define DEBUG_PPC_IO 31 //#define DEBUG_PPC_IO
29 32
@@ -663,7 +666,6 @@ static void VGA_printf (uint8_t *s) @@ -663,7 +666,6 @@ static void VGA_printf (uint8_t *s)
663 static void VGA_init (void) 666 static void VGA_init (void)
664 { 667 {
665 /* Basic VGA init, inspired by plex86 VGAbios */ 668 /* Basic VGA init, inspired by plex86 VGAbios */
666 - printf("Init VGA...\n");  
667 #if 1 669 #if 1
668 /* switch to color mode and enable CPU access 480 lines */ 670 /* switch to color mode and enable CPU access 480 lines */
669 PPC_io_writeb(PPC_IO_BASE + 0x3C2, 0xC3); 671 PPC_io_writeb(PPC_IO_BASE + 0x3C2, 0xC3);
@@ -725,7 +727,6 @@ void PPC_init_hw (/*CPUPPCState *env,*/ uint32_t mem_size, @@ -725,7 +727,6 @@ void PPC_init_hw (/*CPUPPCState *env,*/ uint32_t mem_size,
725 * if a decrementer exception is pending when it enables msr_ee, 727 * if a decrementer exception is pending when it enables msr_ee,
726 * it's not ready to handle it... 728 * it's not ready to handle it...
727 */ 729 */
728 - env->decr = 0xFFFFFFFF;  
729 p = phys_ram_base + kernel_addr; 730 p = phys_ram_base + kernel_addr;
730 #if !defined (USE_OPEN_FIRMWARE) 731 #if !defined (USE_OPEN_FIRMWARE)
731 /* Let's register the whole memory available only in supervisor mode */ 732 /* Let's register the whole memory available only in supervisor mode */
@@ -948,6 +949,8 @@ void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device, @@ -948,6 +949,8 @@ void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
948 } 949 }
949 } 950 }
950 951
  952 + cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL);
  953 +
951 /* init basic PC hardware */ 954 /* init basic PC hardware */
952 vga_initialize(ds, phys_ram_base + ram_size, ram_size, 955 vga_initialize(ds, phys_ram_base + ram_size, ram_size,
953 vga_ram_size, 0); 956 vga_ram_size, 0);
linux-user/main.c
@@ -504,6 +504,49 @@ void cpu_loop (CPUSPARCState *env) @@ -504,6 +504,49 @@ void cpu_loop (CPUSPARCState *env)
504 #endif 504 #endif
505 505
506 #ifdef TARGET_PPC 506 #ifdef TARGET_PPC
  507 +
  508 +static inline uint64_t cpu_ppc_get_tb (CPUState *env)
  509 +{
  510 + /* TO FIX */
  511 + return 0;
  512 +}
  513 +
  514 +uint32_t cpu_ppc_load_tbl (CPUState *env)
  515 +{
  516 + return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
  517 +}
  518 +
  519 +uint32_t cpu_ppc_load_tbu (CPUState *env)
  520 +{
  521 + return cpu_ppc_get_tb(env) >> 32;
  522 +}
  523 +
  524 +static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
  525 +{
  526 + /* TO FIX */
  527 +}
  528 +
  529 +void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
  530 +{
  531 + cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
  532 +}
  533 +
  534 +void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
  535 +{
  536 + cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
  537 +}
  538 +
  539 +uint32_t cpu_ppc_load_decr (CPUState *env)
  540 +{
  541 + /* TO FIX */
  542 + return -1;
  543 +}
  544 +
  545 +void cpu_ppc_store_decr (CPUState *env, uint32_t value)
  546 +{
  547 + /* TO FIX */
  548 +}
  549 +
507 void cpu_loop(CPUPPCState *env) 550 void cpu_loop(CPUPPCState *env)
508 { 551 {
509 target_siginfo_t info; 552 target_siginfo_t info;
@@ -812,7 +855,7 @@ void cpu_loop(CPUPPCState *env) @@ -812,7 +855,7 @@ void cpu_loop(CPUPPCState *env)
812 abort(); 855 abort();
813 case EXCP_MTMSR: 856 case EXCP_MTMSR:
814 /* We reloaded the msr, just go on */ 857 /* We reloaded the msr, just go on */
815 - if (msr_pr) { 858 + if (msr_pr == 0) {
816 fprintf(stderr, "Tried to go into supervisor mode !\n"); 859 fprintf(stderr, "Tried to go into supervisor mode !\n");
817 if (loglevel) 860 if (loglevel)
818 fprintf(logfile, "Tried to go into supervisor mode !\n"); 861 fprintf(logfile, "Tried to go into supervisor mode !\n");
@@ -842,12 +885,7 @@ void cpu_loop(CPUPPCState *env) @@ -842,12 +885,7 @@ void cpu_loop(CPUPPCState *env)
842 } 885 }
843 abort(); 886 abort();
844 } 887 }
845 - if (trapnr < EXCP_PPC_MAX)  
846 - env->exceptions &= ~(1 << trapnr);  
847 process_pending_signals(env); 888 process_pending_signals(env);
848 - if (env->exceptions != 0) {  
849 - check_exception_state(env);  
850 - }  
851 } 889 }
852 } 890 }
853 #endif 891 #endif
monitor.c
@@ -589,6 +589,24 @@ static int monitor_get_xer (struct MonitorDef *md) @@ -589,6 +589,24 @@ static int monitor_get_xer (struct MonitorDef *md)
589 (cpu_single_env->xer[XER_CA] << XER_CA) | 589 (cpu_single_env->xer[XER_CA] << XER_CA) |
590 (cpu_single_env->xer[XER_BC] << XER_BC); 590 (cpu_single_env->xer[XER_BC] << XER_BC);
591 } 591 }
  592 +
  593 +uint32_t cpu_ppc_load_decr (CPUState *env);
  594 +static int monitor_get_decr (struct MonitorDef *md)
  595 +{
  596 + return cpu_ppc_load_decr(cpu_single_env);
  597 +}
  598 +
  599 +uint32_t cpu_ppc_load_tbu (CPUState *env);
  600 +static int monitor_get_tbu (struct MonitorDef *md)
  601 +{
  602 + return cpu_ppc_load_tbu(cpu_single_env);
  603 +}
  604 +
  605 +uint32_t cpu_ppc_load_tbl (CPUState *env);
  606 +static int monitor_get_tbl (struct MonitorDef *md)
  607 +{
  608 + return cpu_ppc_load_tbl(cpu_single_env);
  609 +}
592 #endif 610 #endif
593 611
594 static MonitorDef monitor_defs[] = { 612 static MonitorDef monitor_defs[] = {
@@ -651,12 +669,12 @@ static MonitorDef monitor_defs[] = { @@ -651,12 +669,12 @@ static MonitorDef monitor_defs[] = {
651 { "nip|pc", offsetof(CPUState, nip) }, 669 { "nip|pc", offsetof(CPUState, nip) },
652 { "lr", offsetof(CPUState, lr) }, 670 { "lr", offsetof(CPUState, lr) },
653 { "ctr", offsetof(CPUState, ctr) }, 671 { "ctr", offsetof(CPUState, ctr) },
654 - { "decr", offsetof(CPUState, decr) }, 672 + { "decr", 0, &monitor_get_decr, },
655 { "ccr", 0, &monitor_get_ccr, }, 673 { "ccr", 0, &monitor_get_ccr, },
656 { "msr", 0, &monitor_get_msr, }, 674 { "msr", 0, &monitor_get_msr, },
657 { "xer", 0, &monitor_get_xer, }, 675 { "xer", 0, &monitor_get_xer, },
658 - { "tbu", offsetof(CPUState, tb[0]) },  
659 - { "tbl", offsetof(CPUState, tb[1]) }, 676 + { "tbu", 0, &monitor_get_tbu, },
  677 + { "tbl", 0, &monitor_get_tbl, },
660 { "sdr1", offsetof(CPUState, sdr1) }, 678 { "sdr1", offsetof(CPUState, sdr1) },
661 { "sr0", offsetof(CPUState, sr[0]) }, 679 { "sr0", offsetof(CPUState, sr[0]) },
662 { "sr1", offsetof(CPUState, sr[1]) }, 680 { "sr1", offsetof(CPUState, sr[1]) },
target-ppc/cpu.h
@@ -78,6 +78,8 @@ enum { @@ -78,6 +78,8 @@ enum {
78 #define PPC_750 (PPC_INTEGER | PPC_FLOAT | PPC_FLOW | PPC_MEM | \ 78 #define PPC_750 (PPC_INTEGER | PPC_FLOAT | PPC_FLOW | PPC_MEM | \
79 PPC_RES | PPC_CACHE | PPC_MISC | PPC_EXTERN | PPC_SEGMENT) 79 PPC_RES | PPC_CACHE | PPC_MISC | PPC_EXTERN | PPC_SEGMENT)
80 80
  81 +typedef struct ppc_tb_t ppc_tb_t;
  82 +
81 /* Supervisor mode registers */ 83 /* Supervisor mode registers */
82 /* Machine state register */ 84 /* Machine state register */
83 #define MSR_POW 18 85 #define MSR_POW 18
@@ -134,10 +136,6 @@ typedef struct CPUPPCState { @@ -134,10 +136,6 @@ typedef struct CPUPPCState {
134 /* special purpose registers */ 136 /* special purpose registers */
135 uint32_t lr; 137 uint32_t lr;
136 uint32_t ctr; 138 uint32_t ctr;
137 - /* Time base */  
138 - uint32_t tb[2];  
139 - /* decrementer */  
140 - uint32_t decr;  
141 /* BATs */ 139 /* BATs */
142 uint32_t DBAT[2][8]; 140 uint32_t DBAT[2][8];
143 uint32_t IBAT[2][8]; 141 uint32_t IBAT[2][8];
@@ -154,13 +152,6 @@ typedef struct CPUPPCState { @@ -154,13 +152,6 @@ typedef struct CPUPPCState {
154 int error_code; 152 int error_code;
155 int access_type; /* when a memory exception occurs, the access 153 int access_type; /* when a memory exception occurs, the access
156 type is stored here */ 154 type is stored here */
157 -#if 0 /* TODO */  
158 - uint32_t pending_exceptions; /* For external & decr exception,  
159 - * that can be delayed */  
160 -#else  
161 - uint32_t exceptions; /* exception queue */  
162 - uint32_t errors[32];  
163 -#endif  
164 int user_mode_only; /* user mode only simulation */ 155 int user_mode_only; /* user mode only simulation */
165 struct TranslationBlock *current_tb; /* currently executing TB */ 156 struct TranslationBlock *current_tb; /* currently executing TB */
166 /* soft mmu support */ 157 /* soft mmu support */
@@ -178,8 +169,13 @@ typedef struct CPUPPCState { @@ -178,8 +169,13 @@ typedef struct CPUPPCState {
178 /* ice debug support */ 169 /* ice debug support */
179 uint32_t breakpoints[MAX_BREAKPOINTS]; 170 uint32_t breakpoints[MAX_BREAKPOINTS];
180 int nb_breakpoints; 171 int nb_breakpoints;
181 - int brkstate;  
182 - int singlestep_enabled; 172 + int singlestep_enabled; /* XXX: should use CPU single step mode instead */
  173 +
  174 + /* Time base and decrementer */
  175 + ppc_tb_t *tb_env;
  176 +
  177 + /* Power management */
  178 + int power_mode;
183 179
184 /* user data */ 180 /* user data */
185 void *opaque; 181 void *opaque;
@@ -206,10 +202,15 @@ void _store_xer (CPUPPCState *env, uint32_t value); @@ -206,10 +202,15 @@ void _store_xer (CPUPPCState *env, uint32_t value);
206 uint32_t _load_msr (CPUPPCState *env); 202 uint32_t _load_msr (CPUPPCState *env);
207 void _store_msr (CPUPPCState *env, uint32_t value); 203 void _store_msr (CPUPPCState *env, uint32_t value);
208 204
209 -void PPC_init_hw (uint32_t mem_size,  
210 - uint32_t kernel_addr, uint32_t kernel_size,  
211 - uint32_t stack_addr, int boot_device,  
212 - const unsigned char *initrd_file); 205 +/* Time-base and decrementer management */
  206 +#ifndef NO_CPU_IO_DEFS
  207 +uint32_t cpu_ppc_load_tbl (CPUPPCState *env);
  208 +uint32_t cpu_ppc_load_tbu (CPUPPCState *env);
  209 +void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value);
  210 +void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value);
  211 +uint32_t cpu_ppc_load_decr (CPUPPCState *env);
  212 +void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value);
  213 +#endif
213 214
214 #define TARGET_PAGE_BITS 12 215 #define TARGET_PAGE_BITS 12
215 #include "cpu-all.h" 216 #include "cpu-all.h"
target-ppc/exec.h
@@ -119,12 +119,8 @@ static inline uint32_t rotl (uint32_t i, int n) @@ -119,12 +119,8 @@ static inline uint32_t rotl (uint32_t i, int n)
119 119
120 #endif /* !defined(CONFIG_USER_ONLY) */ 120 #endif /* !defined(CONFIG_USER_ONLY) */
121 121
122 -int check_exception_state (CPUState *env);  
123 -  
124 -void do_queue_exception_err (uint32_t exception, int error_code);  
125 -void do_queue_exception (uint32_t exception);  
126 -void do_process_exceptions (void);  
127 -void do_check_exception_state (void); 122 +void do_raise_exception_err (uint32_t exception, int error_code);
  123 +void do_raise_exception (uint32_t exception);
128 124
129 void do_load_cr (void); 125 void do_load_cr (void);
130 void do_store_cr (uint32_t mask); 126 void do_store_cr (uint32_t mask);
target-ppc/helper.c
@@ -27,49 +27,10 @@ @@ -27,49 +27,10 @@
27 //#define DEBUG_BATS 27 //#define DEBUG_BATS
28 //#define DEBUG_EXCEPTIONS 28 //#define DEBUG_EXCEPTIONS
29 29
30 -extern FILE *logfile, *stdout, *stderr;  
31 -void exit (int); 30 +extern FILE *stdout, *stderr;
32 void abort (void); 31 void abort (void);
33 32
34 -void cpu_loop_exit(void)  
35 -{  
36 - longjmp(env->jmp_env, 1);  
37 -}  
38 -  
39 -void do_process_exceptions (void)  
40 -{  
41 - cpu_loop_exit();  
42 -}  
43 -  
44 -int check_exception_state (CPUState *env)  
45 -{  
46 - int i;  
47 -  
48 - /* Process PPC exceptions */  
49 - for (i = 1; i < EXCP_PPC_MAX; i++) {  
50 - if (env->exceptions & (1 << i)) {  
51 - switch (i) {  
52 - case EXCP_EXTERNAL:  
53 - case EXCP_DECR:  
54 - if (msr_ee == 0)  
55 - return 0;  
56 - break;  
57 - case EXCP_PROGRAM:  
58 - if (env->errors[EXCP_PROGRAM] == EXCP_FP &&  
59 - msr_fe0 == 0 && msr_fe1 == 0)  
60 - return 0;  
61 - break;  
62 - default:  
63 - break;  
64 - }  
65 - env->exception_index = i;  
66 - env->error_code = env->errors[i];  
67 - return 1;  
68 - }  
69 - }  
70 -  
71 - return 0;  
72 -} 33 +/*****************************************************************************/
73 34
74 /*****************************************************************************/ 35 /*****************************************************************************/
75 /* PPC MMU emulation */ 36 /* PPC MMU emulation */
@@ -500,8 +461,7 @@ void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr) @@ -500,8 +461,7 @@ void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr)
500 cpu_restore_state(tb, env, pc, NULL); 461 cpu_restore_state(tb, env, pc, NULL);
501 } 462 }
502 } 463 }
503 - do_queue_exception_err(env->exception_index, env->error_code);  
504 - do_process_exceptions(); 464 + do_raise_exception_err(env->exception_index, env->error_code);
505 } 465 }
506 { 466 {
507 unsigned long tlb_addrr, tlb_addrw; 467 unsigned long tlb_addrr, tlb_addrw;
@@ -701,9 +661,6 @@ void do_interrupt (CPUState *env) @@ -701,9 +661,6 @@ void do_interrupt (CPUState *env)
701 uint32_t msr; 661 uint32_t msr;
702 int excp = env->exception_index; 662 int excp = env->exception_index;
703 663
704 - /* Dequeue PPC exceptions */  
705 - if (excp < EXCP_PPC_MAX)  
706 - env->exceptions &= ~(1 << excp);  
707 msr = _load_msr(env); 664 msr = _load_msr(env);
708 #if defined (DEBUG_EXCEPTIONS) 665 #if defined (DEBUG_EXCEPTIONS)
709 if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) 666 if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1)
@@ -812,7 +769,7 @@ void do_interrupt (CPUState *env) @@ -812,7 +769,7 @@ void do_interrupt (CPUState *env)
812 } 769 }
813 #endif 770 #endif
814 /* Requeue it */ 771 /* Requeue it */
815 - do_queue_exception(EXCP_EXTERNAL); 772 + do_raise_exception(EXCP_EXTERNAL);
816 return; 773 return;
817 } 774 }
818 goto store_next; 775 goto store_next;
@@ -864,7 +821,7 @@ void do_interrupt (CPUState *env) @@ -864,7 +821,7 @@ void do_interrupt (CPUState *env)
864 case EXCP_DECR: 821 case EXCP_DECR:
865 if (msr_ee == 0) { 822 if (msr_ee == 0) {
866 /* Requeue it */ 823 /* Requeue it */
867 - do_queue_exception(EXCP_DECR); 824 + do_raise_exception(EXCP_DECR);
868 return; 825 return;
869 } 826 }
870 goto store_next; 827 goto store_next;
@@ -937,4 +894,5 @@ void do_interrupt (CPUState *env) @@ -937,4 +894,5 @@ void do_interrupt (CPUState *env)
937 T0 = 0; 894 T0 = 0;
938 #endif 895 #endif
939 #endif 896 #endif
  897 + env->exception_index = -1;
940 } 898 }
target-ppc/op.c
@@ -208,32 +208,28 @@ PPC_OP(set_T2) @@ -208,32 +208,28 @@ PPC_OP(set_T2)
208 } 208 }
209 209
210 /* Generate exceptions */ 210 /* Generate exceptions */
211 -PPC_OP(queue_exception_err) 211 +PPC_OP(raise_exception_err)
212 { 212 {
213 - do_queue_exception_err(PARAM(1), PARAM(2)); 213 + do_raise_exception_err(PARAM(1), PARAM(2));
214 } 214 }
215 215
216 -PPC_OP(queue_exception) 216 +PPC_OP(raise_exception)
217 { 217 {
218 - do_queue_exception(PARAM(1)); 218 + do_raise_exception(PARAM(1));
219 } 219 }
220 220
221 -PPC_OP(process_exceptions) 221 +PPC_OP(update_nip)
222 { 222 {
223 env->nip = PARAM(1); 223 env->nip = PARAM(1);
224 - if (env->exceptions != 0) {  
225 - do_check_exception_state();  
226 - }  
227 } 224 }
228 225
229 PPC_OP(debug) 226 PPC_OP(debug)
230 { 227 {
231 env->nip = PARAM(1); 228 env->nip = PARAM(1);
232 - env->brkstate = 1;  
233 #if defined (DEBUG_OP) 229 #if defined (DEBUG_OP)
234 dump_state(); 230 dump_state();
235 #endif 231 #endif
236 - do_queue_exception(EXCP_DEBUG); 232 + do_raise_exception(EXCP_DEBUG);
237 RETURN(); 233 RETURN();
238 } 234 }
239 235
@@ -364,58 +360,38 @@ PPC_OP(store_ctr) @@ -364,58 +360,38 @@ PPC_OP(store_ctr)
364 RETURN(); 360 RETURN();
365 } 361 }
366 362
367 -/* Update time base */  
368 -PPC_OP(update_tb) 363 +PPC_OP(load_tbl)
369 { 364 {
370 - T0 = regs->tb[0];  
371 - T1 = T0;  
372 - T0 += PARAM(1);  
373 -#if defined (DEBUG_OP)  
374 - dump_update_tb(PARAM(1));  
375 -#endif  
376 - if (T0 < T1) {  
377 - T1 = regs->tb[1] + 1;  
378 - regs->tb[1] = T1;  
379 - }  
380 - regs->tb[0] = T0; 365 + T0 = cpu_ppc_load_tbl(regs);
381 RETURN(); 366 RETURN();
382 } 367 }
383 368
384 -PPC_OP(load_tb) 369 +PPC_OP(load_tbu)
385 { 370 {
386 - T0 = regs->tb[PARAM(1)]; 371 + T0 = cpu_ppc_load_tbu(regs);
387 RETURN(); 372 RETURN();
388 } 373 }
389 374
390 -PPC_OP(store_tb) 375 +PPC_OP(store_tbl)
391 { 376 {
392 - regs->tb[PARAM(1)] = T0;  
393 -#if defined (DEBUG_OP)  
394 - dump_store_tb(PARAM(1));  
395 -#endif 377 + cpu_ppc_store_tbl(regs, T0);
396 RETURN(); 378 RETURN();
397 } 379 }
398 380
399 -/* Update decrementer */  
400 -PPC_OP(update_decr) 381 +PPC_OP(store_tbu)
401 { 382 {
402 - T0 = regs->decr;  
403 - T1 = T0;  
404 - T0 -= PARAM(1);  
405 - regs->decr = T0;  
406 - if (PARAM(1) > T1) {  
407 - do_queue_exception(EXCP_DECR);  
408 - } 383 + cpu_ppc_store_tbu(regs, T0);
409 RETURN(); 384 RETURN();
410 } 385 }
411 386
412 -PPC_OP(store_decr) 387 +PPC_OP(load_decr)
413 { 388 {
414 - T1 = regs->decr;  
415 - regs->decr = T0;  
416 - if (Ts0 < 0 && Ts1 > 0) {  
417 - do_queue_exception(EXCP_DECR); 389 + T0 = cpu_ppc_load_decr(regs);
418 } 390 }
  391 +
  392 +PPC_OP(store_decr)
  393 +{
  394 + cpu_ppc_store_decr(regs, T0);
419 RETURN(); 395 RETURN();
420 } 396 }
421 397
@@ -1471,17 +1447,14 @@ PPC_OP(fneg) @@ -1471,17 +1447,14 @@ PPC_OP(fneg)
1471 /* Return from interrupt */ 1447 /* Return from interrupt */
1472 PPC_OP(rfi) 1448 PPC_OP(rfi)
1473 { 1449 {
  1450 + regs->nip = regs->spr[SRR0] & ~0x00000003;
1474 T0 = regs->spr[SRR1] & ~0xFFFF0000; 1451 T0 = regs->spr[SRR1] & ~0xFFFF0000;
1475 do_store_msr(); 1452 do_store_msr();
1476 - do_tlbia();  
1477 #if defined (DEBUG_OP) 1453 #if defined (DEBUG_OP)
1478 dump_rfi(); 1454 dump_rfi();
1479 #endif 1455 #endif
1480 - regs->nip = regs->spr[SRR0] & ~0x00000003;  
1481 - do_queue_exception(EXCP_RFI);  
1482 - if (env->exceptions != 0) {  
1483 - do_check_exception_state();  
1484 - } 1456 + // do_tlbia();
  1457 + do_raise_exception(EXCP_RFI);
1485 RETURN(); 1458 RETURN();
1486 } 1459 }
1487 1460
@@ -1493,7 +1466,7 @@ PPC_OP(tw) @@ -1493,7 +1466,7 @@ PPC_OP(tw)
1493 (Ts0 == Ts1 && (PARAM(1) & 0x04)) || 1466 (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1494 (T0 < T1 && (PARAM(1) & 0x02)) || 1467 (T0 < T1 && (PARAM(1) & 0x02)) ||
1495 (T0 > T1 && (PARAM(1) & 0x01))) 1468 (T0 > T1 && (PARAM(1) & 0x01)))
1496 - do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP); 1469 + do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1497 RETURN(); 1470 RETURN();
1498 } 1471 }
1499 1472
@@ -1504,7 +1477,7 @@ PPC_OP(twi) @@ -1504,7 +1477,7 @@ PPC_OP(twi)
1504 (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) || 1477 (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1505 (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) || 1478 (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1506 (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01))) 1479 (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
1507 - do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP); 1480 + do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1508 RETURN(); 1481 RETURN();
1509 } 1482 }
1510 1483
target-ppc/op_helper.c
@@ -31,31 +31,38 @@ @@ -31,31 +31,38 @@
31 31
32 /*****************************************************************************/ 32 /*****************************************************************************/
33 /* Exceptions processing helpers */ 33 /* Exceptions processing helpers */
34 -void do_queue_exception_err (uint32_t exception, int error_code) 34 +void cpu_loop_exit(void)
35 { 35 {
36 - /* Queue real PPC exceptions */  
37 - if (exception < EXCP_PPC_MAX) {  
38 - env->exceptions |= 1 << exception;  
39 - env->errors[exception] = error_code;  
40 - } else {  
41 - /* Preserve compatibility with qemu core */  
42 - env->exceptions |= 1;  
43 - env->exception_index = exception;  
44 - env->error_code = error_code;  
45 - } 36 + longjmp(env->jmp_env, 1);
46 } 37 }
47 38
48 -void do_queue_exception (uint32_t exception) 39 +void do_raise_exception_err (uint32_t exception, int error_code)
49 { 40 {
50 - do_queue_exception_err(exception, 0);  
51 -}  
52 -  
53 -void do_check_exception_state (void)  
54 -{  
55 - if ((env->exceptions & 1) == 1 || check_exception_state(env)) {  
56 - env->exceptions &= ~1; 41 +#if 0
  42 + printf("Raise exception %3x code : %d\n", exception, error_code);
  43 +#endif
  44 + switch (exception) {
  45 + case EXCP_EXTERNAL:
  46 + case EXCP_DECR:
  47 + printf("DECREMENTER & EXTERNAL exceptions should be hard interrupts !\n");
  48 + if (msr_ee == 0)
  49 + return;
  50 + break;
  51 + case EXCP_PROGRAM:
  52 + if (error_code == EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
  53 + return;
  54 + break;
  55 + default:
  56 + break;
  57 +}
  58 + env->exception_index = exception;
  59 + env->error_code = error_code;
57 cpu_loop_exit(); 60 cpu_loop_exit();
58 } 61 }
  62 +
  63 +void do_raise_exception (uint32_t exception)
  64 +{
  65 + do_raise_exception_err(exception, 0);
59 } 66 }
60 67
61 /*****************************************************************************/ 68 /*****************************************************************************/
@@ -125,13 +132,6 @@ void do_store_msr (void) @@ -125,13 +132,6 @@ void do_store_msr (void)
125 /* Flush all tlb when changing translation mode or privilege level */ 132 /* Flush all tlb when changing translation mode or privilege level */
126 do_tlbia(); 133 do_tlbia();
127 } 134 }
128 -#if 0  
129 - if ((T0 >> MSR_IP) & 0x01) {  
130 - printf("Halting CPU. Stop emulation\n");  
131 - do_queue_exception(EXCP_HLT);  
132 - cpu_loop_exit();  
133 - }  
134 -#endif  
135 msr_pow = (T0 >> MSR_POW) & 0x03; 135 msr_pow = (T0 >> MSR_POW) & 0x03;
136 msr_ile = (T0 >> MSR_ILE) & 0x01; 136 msr_ile = (T0 >> MSR_ILE) & 0x01;
137 msr_ee = (T0 >> MSR_EE) & 0x01; 137 msr_ee = (T0 >> MSR_EE) & 0x01;
target-ppc/op_mem.h
@@ -97,8 +97,7 @@ PPC_OP(glue(lswx, MEMSUFFIX)) @@ -97,8 +97,7 @@ PPC_OP(glue(lswx, MEMSUFFIX))
97 if (T1 > 0) { 97 if (T1 > 0) {
98 if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) || 98 if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) ||
99 (PARAM(1) < PARAM(3) && (PARAM(1) + T1) > PARAM(3))) { 99 (PARAM(1) < PARAM(3) && (PARAM(1) + T1) > PARAM(3))) {
100 - do_queue_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);  
101 - do_process_exceptions(); 100 + do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
102 } else { 101 } else {
103 glue(do_lsw, MEMSUFFIX)(PARAM(1)); 102 glue(do_lsw, MEMSUFFIX)(PARAM(1));
104 } 103 }
@@ -138,8 +137,7 @@ PPC_LDF_OP(fs, ldfl); @@ -138,8 +137,7 @@ PPC_LDF_OP(fs, ldfl);
138 PPC_OP(glue(lwarx, MEMSUFFIX)) 137 PPC_OP(glue(lwarx, MEMSUFFIX))
139 { 138 {
140 if (T0 & 0x03) { 139 if (T0 & 0x03) {
141 - do_queue_exception(EXCP_ALIGN);  
142 - do_process_exceptions(); 140 + do_raise_exception(EXCP_ALIGN);
143 } else { 141 } else {
144 T1 = glue(ldl, MEMSUFFIX)((void *)T0); 142 T1 = glue(ldl, MEMSUFFIX)((void *)T0);
145 regs->reserve = T0; 143 regs->reserve = T0;
@@ -151,8 +149,7 @@ PPC_OP(glue(lwarx, MEMSUFFIX)) @@ -151,8 +149,7 @@ PPC_OP(glue(lwarx, MEMSUFFIX))
151 PPC_OP(glue(stwcx, MEMSUFFIX)) 149 PPC_OP(glue(stwcx, MEMSUFFIX))
152 { 150 {
153 if (T0 & 0x03) { 151 if (T0 & 0x03) {
154 - do_queue_exception(EXCP_ALIGN);  
155 - do_process_exceptions(); 152 + do_raise_exception(EXCP_ALIGN);
156 } else { 153 } else {
157 if (regs->reserve != T0) { 154 if (regs->reserve != T0) {
158 env->crf[0] = xer_ov; 155 env->crf[0] = xer_ov;
target-ppc/translate.c
@@ -30,6 +30,7 @@ @@ -30,6 +30,7 @@
30 //#define DO_SINGLE_STEP 30 //#define DO_SINGLE_STEP
31 //#define DO_STEP_FLUSH 31 //#define DO_STEP_FLUSH
32 //#define DEBUG_DISAS 32 //#define DEBUG_DISAS
  33 +//#define PPC_DEBUG_DISAS
33 34
34 enum { 35 enum {
35 #define DEF(s, n, copy_size) INDEX_op_ ## s, 36 #define DEF(s, n, copy_size) INDEX_op_ ## s,
@@ -135,10 +136,6 @@ typedef struct DisasContext { @@ -135,10 +136,6 @@ typedef struct DisasContext {
135 uint32_t nip; 136 uint32_t nip;
136 uint32_t opcode; 137 uint32_t opcode;
137 uint32_t exception; 138 uint32_t exception;
138 - /* Time base offset */  
139 - uint32_t tb_offset;  
140 - /* Decrementer offset */  
141 - uint32_t decr_offset;  
142 /* Execution mode */ 139 /* Execution mode */
143 #if !defined(CONFIG_USER_ONLY) 140 #if !defined(CONFIG_USER_ONLY)
144 int supervisor; 141 int supervisor;
@@ -156,21 +153,26 @@ typedef struct opc_handler_t { @@ -156,21 +153,26 @@ typedef struct opc_handler_t {
156 void (*handler)(DisasContext *ctx); 153 void (*handler)(DisasContext *ctx);
157 } opc_handler_t; 154 } opc_handler_t;
158 155
159 -#define RET_EXCP(excp, error) \ 156 +#define RET_EXCP(ctx, excp, error) \
160 do { \ 157 do { \
161 - gen_op_queue_exception_err(excp, error); \  
162 - ctx->exception = excp; \  
163 - return; \ 158 + if ((ctx)->exception == EXCP_NONE) { \
  159 + gen_op_update_nip((ctx)->nip); \
  160 + } \
  161 + gen_op_raise_exception_err((excp), (error)); \
  162 + ctx->exception = (excp); \
164 } while (0) 163 } while (0)
165 164
166 -#define RET_INVAL() \  
167 -RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL) 165 +#define RET_INVAL(ctx) \
  166 +RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
  167 +
  168 +#define RET_PRIVOPC(ctx) \
  169 +RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
168 170
169 -#define RET_PRIVOPC() \  
170 -RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC) 171 +#define RET_PRIVREG(ctx) \
  172 +RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
171 173
172 -#define RET_PRIVREG() \  
173 -RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG) 174 +#define RET_MTMSR(ctx) \
  175 +RET_EXCP((ctx), EXCP_MTMSR, 0)
174 176
175 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \ 177 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
176 static void gen_##name (DisasContext *ctx); \ 178 static void gen_##name (DisasContext *ctx); \
@@ -312,29 +314,26 @@ GEN_OPCODE_MARK(start); @@ -312,29 +314,26 @@ GEN_OPCODE_MARK(start);
312 /* Invalid instruction */ 314 /* Invalid instruction */
313 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE) 315 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
314 { 316 {
315 - RET_INVAL(); 317 + RET_INVAL(ctx);
316 } 318 }
317 319
318 /* Special opcode to stop emulation */ 320 /* Special opcode to stop emulation */
319 GEN_HANDLER(stop, 0x06, 0x00, 0xFF, 0x03FFFFC1, PPC_COMMON) 321 GEN_HANDLER(stop, 0x06, 0x00, 0xFF, 0x03FFFFC1, PPC_COMMON)
320 { 322 {
321 - gen_op_queue_exception(EXCP_HLT);  
322 - ctx->exception = EXCP_HLT; 323 + RET_EXCP(ctx, EXCP_HLT, 0);
323 } 324 }
324 325
325 /* Special opcode to call open-firmware */ 326 /* Special opcode to call open-firmware */
326 GEN_HANDLER(of_enter, 0x06, 0x01, 0xFF, 0x03FFFFC1, PPC_COMMON) 327 GEN_HANDLER(of_enter, 0x06, 0x01, 0xFF, 0x03FFFFC1, PPC_COMMON)
327 { 328 {
328 - gen_op_queue_exception(EXCP_OFCALL);  
329 - ctx->exception = EXCP_OFCALL; 329 + RET_EXCP(ctx, EXCP_OFCALL, 0);
330 } 330 }
331 331
332 /* Special opcode to call RTAS */ 332 /* Special opcode to call RTAS */
333 GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON) 333 GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON)
334 { 334 {
335 printf("RTAS entry point !\n"); 335 printf("RTAS entry point !\n");
336 - gen_op_queue_exception(EXCP_RTASCALL);  
337 - ctx->exception = EXCP_RTASCALL; 336 + RET_EXCP(ctx, EXCP_RTASCALL, 0);
338 } 337 }
339 338
340 static opc_handler_t invalid_handler = { 339 static opc_handler_t invalid_handler = {
@@ -1010,7 +1009,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ @@ -1010,7 +1009,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1010 uint32_t simm = SIMM(ctx->opcode); \ 1009 uint32_t simm = SIMM(ctx->opcode); \
1011 if (rA(ctx->opcode) == 0 || \ 1010 if (rA(ctx->opcode) == 0 || \
1012 rA(ctx->opcode) == rD(ctx->opcode)) { \ 1011 rA(ctx->opcode) == rD(ctx->opcode)) { \
1013 - RET_INVAL(); \ 1012 + RET_INVAL(ctx); \
  1013 + return; \
1014 } \ 1014 } \
1015 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1015 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1016 if (simm != 0) \ 1016 if (simm != 0) \
@@ -1025,7 +1025,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ @@ -1025,7 +1025,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1025 { \ 1025 { \
1026 if (rA(ctx->opcode) == 0 || \ 1026 if (rA(ctx->opcode) == 0 || \
1027 rA(ctx->opcode) == rD(ctx->opcode)) { \ 1027 rA(ctx->opcode) == rD(ctx->opcode)) { \
1028 - RET_INVAL(); \ 1028 + RET_INVAL(ctx); \
  1029 + return; \
1029 } \ 1030 } \
1030 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1031 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1031 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1032 gen_op_load_gpr_T1(rB(ctx->opcode)); \
@@ -1086,7 +1087,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ @@ -1086,7 +1087,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1086 { \ 1087 { \
1087 uint32_t simm = SIMM(ctx->opcode); \ 1088 uint32_t simm = SIMM(ctx->opcode); \
1088 if (rA(ctx->opcode) == 0) { \ 1089 if (rA(ctx->opcode) == 0) { \
1089 - RET_INVAL(); \ 1090 + RET_INVAL(ctx); \
  1091 + return; \
1090 } \ 1092 } \
1091 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1093 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1092 if (simm != 0) \ 1094 if (simm != 0) \
@@ -1100,7 +1102,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ @@ -1100,7 +1102,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1100 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ 1102 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1101 { \ 1103 { \
1102 if (rA(ctx->opcode) == 0) { \ 1104 if (rA(ctx->opcode) == 0) { \
1103 - RET_INVAL(); \ 1105 + RET_INVAL(ctx); \
  1106 + return; \
1104 } \ 1107 } \
1105 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1108 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1106 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1109 gen_op_load_gpr_T1(rB(ctx->opcode)); \
@@ -1236,7 +1239,8 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER) @@ -1236,7 +1239,8 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1236 nr = nb / 4; 1239 nr = nb / 4;
1237 if (((start + nr) > 32 && start <= ra && (start + nr - 32) > ra) || 1240 if (((start + nr) > 32 && start <= ra && (start + nr - 32) > ra) ||
1238 ((start + nr) <= 32 && start <= ra && (start + nr) > ra)) { 1241 ((start + nr) <= 32 && start <= ra && (start + nr) > ra)) {
1239 - RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX); 1242 + RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
  1243 + return;
1240 } 1244 }
1241 if (ra == 0) { 1245 if (ra == 0) {
1242 gen_op_set_T0(0); 1246 gen_op_set_T0(0);
@@ -1376,7 +1380,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ @@ -1376,7 +1380,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1376 uint32_t simm = SIMM(ctx->opcode); \ 1380 uint32_t simm = SIMM(ctx->opcode); \
1377 if (rA(ctx->opcode) == 0 || \ 1381 if (rA(ctx->opcode) == 0 || \
1378 rA(ctx->opcode) == rD(ctx->opcode)) { \ 1382 rA(ctx->opcode) == rD(ctx->opcode)) { \
1379 - RET_INVAL(); \ 1383 + RET_INVAL(ctx); \
  1384 + return; \
1380 } \ 1385 } \
1381 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1386 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1382 if (simm != 0) \ 1387 if (simm != 0) \
@@ -1391,7 +1396,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ @@ -1391,7 +1396,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1391 { \ 1396 { \
1392 if (rA(ctx->opcode) == 0 || \ 1397 if (rA(ctx->opcode) == 0 || \
1393 rA(ctx->opcode) == rD(ctx->opcode)) { \ 1398 rA(ctx->opcode) == rD(ctx->opcode)) { \
1394 - RET_INVAL(); \ 1399 + RET_INVAL(ctx); \
  1400 + return; \
1395 } \ 1401 } \
1396 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1402 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1397 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1403 gen_op_load_gpr_T1(rB(ctx->opcode)); \
@@ -1448,7 +1454,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ @@ -1448,7 +1454,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1448 { \ 1454 { \
1449 uint32_t simm = SIMM(ctx->opcode); \ 1455 uint32_t simm = SIMM(ctx->opcode); \
1450 if (rA(ctx->opcode) == 0) { \ 1456 if (rA(ctx->opcode) == 0) { \
1451 - RET_INVAL(); \ 1457 + RET_INVAL(ctx); \
  1458 + return; \
1452 } \ 1459 } \
1453 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1460 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1454 if (simm != 0) \ 1461 if (simm != 0) \
@@ -1462,7 +1469,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ @@ -1462,7 +1469,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1462 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ 1469 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1463 { \ 1470 { \
1464 if (rA(ctx->opcode) == 0) { \ 1471 if (rA(ctx->opcode) == 0) { \
1465 - RET_INVAL(); \ 1472 + RET_INVAL(ctx); \
  1473 + return; \
1466 } \ 1474 } \
1467 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1475 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1468 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1476 gen_op_load_gpr_T1(rB(ctx->opcode)); \
@@ -1502,7 +1510,7 @@ GEN_STFS(fs, 0x14); @@ -1502,7 +1510,7 @@ GEN_STFS(fs, 0x14);
1502 /* stfiwx */ 1510 /* stfiwx */
1503 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT) 1511 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
1504 { 1512 {
1505 - RET_INVAL(); 1513 + RET_INVAL(ctx);
1506 } 1514 }
1507 1515
1508 /*** Branch ***/ 1516 /*** Branch ***/
@@ -1512,9 +1520,6 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) @@ -1512,9 +1520,6 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1512 { 1520 {
1513 uint32_t li = s_ext24(LI(ctx->opcode)), target; 1521 uint32_t li = s_ext24(LI(ctx->opcode)), target;
1514 1522
1515 - gen_op_update_tb(ctx->tb_offset);  
1516 - gen_op_update_decr(ctx->decr_offset);  
1517 - gen_op_process_exceptions(ctx->nip - 4);  
1518 if (AA(ctx->opcode) == 0) 1523 if (AA(ctx->opcode) == 0)
1519 target = ctx->nip + li - 4; 1524 target = ctx->nip + li - 4;
1520 else 1525 else
@@ -1538,10 +1543,6 @@ static inline void gen_bcond(DisasContext *ctx, int type) @@ -1538,10 +1543,6 @@ static inline void gen_bcond(DisasContext *ctx, int type)
1538 uint32_t mask; 1543 uint32_t mask;
1539 uint32_t li; 1544 uint32_t li;
1540 1545
1541 - gen_op_update_tb(ctx->tb_offset);  
1542 - gen_op_update_decr(ctx->decr_offset);  
1543 - gen_op_process_exceptions(ctx->nip - 4);  
1544 -  
1545 if ((bo & 0x4) == 0) 1546 if ((bo & 0x4) == 0)
1546 gen_op_dec_ctr(); 1547 gen_op_dec_ctr();
1547 switch(type) { 1548 switch(type) {
@@ -1683,14 +1684,15 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER) @@ -1683,14 +1684,15 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
1683 GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW) 1684 GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1684 { 1685 {
1685 #if defined(CONFIG_USER_ONLY) 1686 #if defined(CONFIG_USER_ONLY)
1686 - RET_PRIVOPC(); 1687 + RET_PRIVOPC(ctx);
1687 #else 1688 #else
1688 /* Restore CPU state */ 1689 /* Restore CPU state */
1689 if (!ctx->supervisor) { 1690 if (!ctx->supervisor) {
1690 - RET_PRIVOPC(); 1691 + RET_PRIVOPC(ctx);
  1692 + return;
1691 } 1693 }
1692 gen_op_rfi(); 1694 gen_op_rfi();
1693 - ctx->exception = EXCP_RFI; 1695 + RET_EXCP(ctx, EXCP_RFI, 0);
1694 #endif 1696 #endif
1695 } 1697 }
1696 1698
@@ -1698,11 +1700,10 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW) @@ -1698,11 +1700,10 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1698 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW) 1700 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
1699 { 1701 {
1700 #if defined(CONFIG_USER_ONLY) 1702 #if defined(CONFIG_USER_ONLY)
1701 - gen_op_queue_exception(EXCP_SYSCALL_USER); 1703 + RET_EXCP(ctx, EXCP_SYSCALL_USER, 0);
1702 #else 1704 #else
1703 - gen_op_queue_exception(EXCP_SYSCALL); 1705 + RET_EXCP(ctx, EXCP_SYSCALL, 0);
1704 #endif 1706 #endif
1705 - ctx->exception = EXCP_SYSCALL;  
1706 } 1707 }
1707 1708
1708 /*** Trap ***/ 1709 /*** Trap ***/
@@ -1770,10 +1771,11 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC) @@ -1770,10 +1771,11 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
1770 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC) 1771 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
1771 { 1772 {
1772 #if defined(CONFIG_USER_ONLY) 1773 #if defined(CONFIG_USER_ONLY)
1773 - RET_PRIVREG(); 1774 + RET_PRIVREG(ctx);
1774 #else 1775 #else
1775 if (!ctx->supervisor) { 1776 if (!ctx->supervisor) {
1776 - RET_PRIVREG(); 1777 + RET_PRIVREG(ctx);
  1778 + return;
1777 } 1779 }
1778 gen_op_load_msr(); 1780 gen_op_load_msr();
1779 gen_op_store_T0_gpr(rD(ctx->opcode)); 1781 gen_op_store_T0_gpr(rD(ctx->opcode));
@@ -1792,11 +1794,11 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC) @@ -1792,11 +1794,11 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
1792 #endif 1794 #endif
1793 { 1795 {
1794 case -1: 1796 case -1:
1795 - RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);  
1796 - break; 1797 + RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
  1798 + return;
1797 case 0: 1799 case 0:
1798 - RET_PRIVREG();  
1799 - break; 1800 + RET_PRIVREG(ctx);
  1801 + return;
1800 default: 1802 default:
1801 break; 1803 break;
1802 } 1804 }
@@ -1910,19 +1912,13 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC) @@ -1910,19 +1912,13 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
1910 gen_op_load_sdr1(); 1912 gen_op_load_sdr1();
1911 break; 1913 break;
1912 case V_TBL: 1914 case V_TBL:
1913 - gen_op_update_tb(ctx->tb_offset);  
1914 - ctx->tb_offset = 0;  
1915 - /* TBL is still in T0 */ 1915 + gen_op_load_tbl();
1916 break; 1916 break;
1917 case V_TBU: 1917 case V_TBU:
1918 - gen_op_update_tb(ctx->tb_offset);  
1919 - ctx->tb_offset = 0;  
1920 - gen_op_load_tb(1); 1918 + gen_op_load_tbu();
1921 break; 1919 break;
1922 case DECR: 1920 case DECR:
1923 - gen_op_update_decr(ctx->decr_offset);  
1924 - ctx->decr_offset = 0;  
1925 - /* decr is still in T0 */ 1921 + gen_op_load_decr();
1926 break; 1922 break;
1927 default: 1923 default:
1928 gen_op_load_spr(sprn); 1924 gen_op_load_spr(sprn);
@@ -1939,18 +1935,16 @@ GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC) @@ -1939,18 +1935,16 @@ GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC)
1939 /* We need to update the time base before reading it */ 1935 /* We need to update the time base before reading it */
1940 switch (sprn) { 1936 switch (sprn) {
1941 case V_TBL: 1937 case V_TBL:
1942 - gen_op_update_tb(ctx->tb_offset);  
1943 /* TBL is still in T0 */ 1938 /* TBL is still in T0 */
  1939 + gen_op_load_tbl();
1944 break; 1940 break;
1945 case V_TBU: 1941 case V_TBU:
1946 - gen_op_update_tb(ctx->tb_offset);  
1947 - gen_op_load_tb(1); 1942 + gen_op_load_tbu();
1948 break; 1943 break;
1949 default: 1944 default:
1950 - RET_INVAL();  
1951 - break; 1945 + RET_INVAL(ctx);
  1946 + return;
1952 } 1947 }
1953 - ctx->tb_offset = 0;  
1954 gen_op_store_T0_gpr(rD(ctx->opcode)); 1948 gen_op_store_T0_gpr(rD(ctx->opcode));
1955 } 1949 }
1956 1950
@@ -1965,15 +1959,16 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC) @@ -1965,15 +1959,16 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC)
1965 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) 1959 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
1966 { 1960 {
1967 #if defined(CONFIG_USER_ONLY) 1961 #if defined(CONFIG_USER_ONLY)
1968 - RET_PRIVREG(); 1962 + RET_PRIVREG(ctx);
1969 #else 1963 #else
1970 if (!ctx->supervisor) { 1964 if (!ctx->supervisor) {
1971 - RET_PRIVREG(); 1965 + RET_PRIVREG(ctx);
  1966 + return;
1972 } 1967 }
1973 gen_op_load_gpr_T0(rS(ctx->opcode)); 1968 gen_op_load_gpr_T0(rS(ctx->opcode));
1974 gen_op_store_msr(); 1969 gen_op_store_msr();
1975 /* Must stop the translation as machine state (may have) changed */ 1970 /* Must stop the translation as machine state (may have) changed */
1976 - ctx->exception = EXCP_MTMSR; 1971 + RET_MTMSR(ctx);
1977 #endif 1972 #endif
1978 } 1973 }
1979 1974
@@ -1995,10 +1990,10 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) @@ -1995,10 +1990,10 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
1995 #endif 1990 #endif
1996 { 1991 {
1997 case -1: 1992 case -1:
1998 - RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR); 1993 + RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
1999 break; 1994 break;
2000 case 0: 1995 case 0:
2001 - RET_PRIVREG(); 1996 + RET_PRIVREG(ctx);
2002 break; 1997 break;
2003 default: 1998 default:
2004 break; 1999 break;
@@ -2147,16 +2142,13 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) @@ -2147,16 +2142,13 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
2147 gen_op_tlbia(); 2142 gen_op_tlbia();
2148 break; 2143 break;
2149 case O_TBL: 2144 case O_TBL:
2150 - gen_op_store_tb(0);  
2151 - ctx->tb_offset = 0; 2145 + gen_op_store_tbl();
2152 break; 2146 break;
2153 case O_TBU: 2147 case O_TBU:
2154 - gen_op_store_tb(1);  
2155 - ctx->tb_offset = 0; 2148 + gen_op_store_tbu();
2156 break; 2149 break;
2157 case DECR: 2150 case DECR:
2158 gen_op_store_decr(); 2151 gen_op_store_decr();
2159 - ctx->decr_offset = 0;  
2160 break; 2152 break;
2161 default: 2153 default:
2162 gen_op_store_spr(sprn); 2154 gen_op_store_spr(sprn);
@@ -2186,10 +2178,11 @@ GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE) @@ -2186,10 +2178,11 @@ GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
2186 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE) 2178 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
2187 { 2179 {
2188 #if defined(CONFIG_USER_ONLY) 2180 #if defined(CONFIG_USER_ONLY)
2189 - RET_PRIVOPC(); 2181 + RET_PRIVOPC(ctx);
2190 #else 2182 #else
2191 if (!ctx->supervisor) { 2183 if (!ctx->supervisor) {
2192 - RET_PRIVOPC(); 2184 + RET_PRIVOPC(ctx);
  2185 + return;
2193 } 2186 }
2194 if (rA(ctx->opcode) == 0) { 2187 if (rA(ctx->opcode) == 0) {
2195 gen_op_load_gpr_T0(rB(ctx->opcode)); 2188 gen_op_load_gpr_T0(rB(ctx->opcode));
@@ -2274,10 +2267,11 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE_OPT) @@ -2274,10 +2267,11 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE_OPT)
2274 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT) 2267 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
2275 { 2268 {
2276 #if defined(CONFIG_USER_ONLY) 2269 #if defined(CONFIG_USER_ONLY)
2277 - RET_PRIVREG(); 2270 + RET_PRIVREG(ctx);
2278 #else 2271 #else
2279 if (!ctx->supervisor) { 2272 if (!ctx->supervisor) {
2280 - RET_PRIVREG(); 2273 + RET_PRIVREG(ctx);
  2274 + return;
2281 } 2275 }
2282 gen_op_load_sr(SR(ctx->opcode)); 2276 gen_op_load_sr(SR(ctx->opcode));
2283 gen_op_store_T0_gpr(rD(ctx->opcode)); 2277 gen_op_store_T0_gpr(rD(ctx->opcode));
@@ -2288,10 +2282,11 @@ GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT) @@ -2288,10 +2282,11 @@ GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
2288 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT) 2282 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
2289 { 2283 {
2290 #if defined(CONFIG_USER_ONLY) 2284 #if defined(CONFIG_USER_ONLY)
2291 - RET_PRIVREG(); 2285 + RET_PRIVREG(ctx);
2292 #else 2286 #else
2293 if (!ctx->supervisor) { 2287 if (!ctx->supervisor) {
2294 - RET_PRIVREG(); 2288 + RET_PRIVREG(ctx);
  2289 + return;
2295 } 2290 }
2296 gen_op_load_gpr_T1(rB(ctx->opcode)); 2291 gen_op_load_gpr_T1(rB(ctx->opcode));
2297 gen_op_load_srin(); 2292 gen_op_load_srin();
@@ -2303,14 +2298,18 @@ GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT) @@ -2303,14 +2298,18 @@ GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
2303 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT) 2298 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
2304 { 2299 {
2305 #if defined(CONFIG_USER_ONLY) 2300 #if defined(CONFIG_USER_ONLY)
2306 - RET_PRIVREG(); 2301 + RET_PRIVREG(ctx);
2307 #else 2302 #else
2308 if (!ctx->supervisor) { 2303 if (!ctx->supervisor) {
2309 - RET_PRIVREG(); 2304 + RET_PRIVREG(ctx);
  2305 + return;
2310 } 2306 }
2311 gen_op_load_gpr_T0(rS(ctx->opcode)); 2307 gen_op_load_gpr_T0(rS(ctx->opcode));
2312 gen_op_store_sr(SR(ctx->opcode)); 2308 gen_op_store_sr(SR(ctx->opcode));
  2309 +#if 0
2313 gen_op_tlbia(); 2310 gen_op_tlbia();
  2311 + RET_MTMSR(ctx);
  2312 +#endif
2314 #endif 2313 #endif
2315 } 2314 }
2316 2315
@@ -2318,10 +2317,11 @@ GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT) @@ -2318,10 +2317,11 @@ GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
2318 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) 2317 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
2319 { 2318 {
2320 #if defined(CONFIG_USER_ONLY) 2319 #if defined(CONFIG_USER_ONLY)
2321 - RET_PRIVREG(); 2320 + RET_PRIVREG(ctx);
2322 #else 2321 #else
2323 if (!ctx->supervisor) { 2322 if (!ctx->supervisor) {
2324 - RET_PRIVREG(); 2323 + RET_PRIVREG(ctx);
  2324 + return;
2325 } 2325 }
2326 gen_op_load_gpr_T0(rS(ctx->opcode)); 2326 gen_op_load_gpr_T0(rS(ctx->opcode));
2327 gen_op_load_gpr_T1(rB(ctx->opcode)); 2327 gen_op_load_gpr_T1(rB(ctx->opcode));
@@ -2336,10 +2336,13 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) @@ -2336,10 +2336,13 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
2336 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT) 2336 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT)
2337 { 2337 {
2338 #if defined(CONFIG_USER_ONLY) 2338 #if defined(CONFIG_USER_ONLY)
2339 - RET_PRIVOPC(); 2339 + RET_PRIVOPC(ctx);
2340 #else 2340 #else
2341 if (!ctx->supervisor) { 2341 if (!ctx->supervisor) {
2342 - RET_PRIVOPC(); 2342 + if (loglevel)
  2343 + fprintf(logfile, "%s: ! supervisor\n", __func__);
  2344 + RET_PRIVOPC(ctx);
  2345 + return;
2343 } 2346 }
2344 gen_op_tlbia(); 2347 gen_op_tlbia();
2345 #endif 2348 #endif
@@ -2349,10 +2352,11 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT) @@ -2349,10 +2352,11 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT)
2349 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM) 2352 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
2350 { 2353 {
2351 #if defined(CONFIG_USER_ONLY) 2354 #if defined(CONFIG_USER_ONLY)
2352 - RET_PRIVOPC(); 2355 + RET_PRIVOPC(ctx);
2353 #else 2356 #else
2354 if (!ctx->supervisor) { 2357 if (!ctx->supervisor) {
2355 - RET_PRIVOPC(); 2358 + RET_PRIVOPC(ctx);
  2359 + return;
2356 } 2360 }
2357 gen_op_load_gpr_T0(rB(ctx->opcode)); 2361 gen_op_load_gpr_T0(rB(ctx->opcode));
2358 gen_op_tlbie(); 2362 gen_op_tlbie();
@@ -2363,10 +2367,11 @@ GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM) @@ -2363,10 +2367,11 @@ GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
2363 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM) 2367 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM)
2364 { 2368 {
2365 #if defined(CONFIG_USER_ONLY) 2369 #if defined(CONFIG_USER_ONLY)
2366 - RET_PRIVOPC(); 2370 + RET_PRIVOPC(ctx);
2367 #else 2371 #else
2368 if (!ctx->supervisor) { 2372 if (!ctx->supervisor) {
2369 - RET_PRIVOPC(); 2373 + RET_PRIVOPC(ctx);
  2374 + return;
2370 } 2375 }
2371 /* This has no effect: it should ensure that all previous 2376 /* This has no effect: it should ensure that all previous
2372 * tlbie have completed 2377 * tlbie have completed
@@ -2916,7 +2921,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) @@ -2916,7 +2921,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
2916 fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' '); 2921 fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
2917 } 2922 }
2918 fprintf(f, " ] "); 2923 fprintf(f, " ] ");
2919 - fprintf(f, "TB: 0x%08x %08x\n", env->tb[1], env->tb[0]); 2924 + fprintf(f, "TB: 0x%08x %08x\n", cpu_ppc_load_tbu(env),
  2925 + cpu_ppc_load_tbl(env));
2920 for (i = 0; i < 16; i++) { 2926 for (i = 0; i < 16; i++) {
2921 if ((i & 3) == 0) 2927 if ((i & 3) == 0)
2922 fprintf(f, "FPR%02d:", i); 2928 fprintf(f, "FPR%02d:", i);
@@ -2924,8 +2930,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) @@ -2924,8 +2930,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
2924 if ((i & 3) == 3) 2930 if ((i & 3) == 3)
2925 fprintf(f, "\n"); 2931 fprintf(f, "\n");
2926 } 2932 }
2927 - fprintf(f, "SRR0 0x%08x SRR1 0x%08x DECR=0x%08x excp:0x%08x\n",  
2928 - env->spr[SRR0], env->spr[SRR1], env->decr, env->exceptions); 2933 + fprintf(f, "SRR0 0x%08x SRR1 0x%08x DECR=0x%08x\n",
  2934 + env->spr[SRR0], env->spr[SRR1], cpu_ppc_load_decr(env));
2929 fprintf(f, "reservation 0x%08x\n", env->reserve); 2935 fprintf(f, "reservation 0x%08x\n", env->reserve);
2930 fflush(f); 2936 fflush(f);
2931 } 2937 }
@@ -2952,7 +2958,6 @@ CPUPPCState *cpu_ppc_init(void) @@ -2952,7 +2958,6 @@ CPUPPCState *cpu_ppc_init(void)
2952 // env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */ 2958 // env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */
2953 // env->spr[PVR] = 0x00070100; /* IBM 750FX */ 2959 // env->spr[PVR] = 0x00070100; /* IBM 750FX */
2954 #endif 2960 #endif
2955 - env->decr = 0xFFFFFFFF;  
2956 if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0) 2961 if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0)
2957 return NULL; 2962 return NULL;
2958 init_spr_rights(env->spr[PVR]); 2963 init_spr_rights(env->spr[PVR]);
@@ -2976,14 +2981,13 @@ void cpu_ppc_close(CPUPPCState *env) @@ -2976,14 +2981,13 @@ void cpu_ppc_close(CPUPPCState *env)
2976 } 2981 }
2977 2982
2978 /*****************************************************************************/ 2983 /*****************************************************************************/
2979 -void raise_exception_err (int exception_index, int error_code);  
2980 int print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr, 2984 int print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
2981 int dialect); 2985 int dialect);
2982 2986
2983 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, 2987 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2984 int search_pc) 2988 int search_pc)
2985 { 2989 {
2986 - DisasContext ctx; 2990 + DisasContext ctx, *ctxp = &ctx;
2987 opc_handler_t **table, *handler; 2991 opc_handler_t **table, *handler;
2988 uint32_t pc_start; 2992 uint32_t pc_start;
2989 uint16_t *gen_opc_end; 2993 uint16_t *gen_opc_end;
@@ -2994,8 +2998,6 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -2994,8 +2998,6 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2994 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 2998 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2995 gen_opparam_ptr = gen_opparam_buf; 2999 gen_opparam_ptr = gen_opparam_buf;
2996 ctx.nip = pc_start; 3000 ctx.nip = pc_start;
2997 - ctx.tb_offset = 0;  
2998 - ctx.decr_offset = 0;  
2999 ctx.tb = tb; 3001 ctx.tb = tb;
3000 ctx.exception = EXCP_NONE; 3002 ctx.exception = EXCP_NONE;
3001 #if defined(CONFIG_USER_ONLY) 3003 #if defined(CONFIG_USER_ONLY)
@@ -3023,26 +3025,22 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -3023,26 +3025,22 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3023 gen_opc_instr_start[lj] = 1; 3025 gen_opc_instr_start[lj] = 1;
3024 } 3026 }
3025 } 3027 }
3026 -#if defined DEBUG_DISAS  
3027 - if (loglevel > 0) { 3028 +#if defined PPC_DEBUG_DISAS
  3029 + if (loglevel & CPU_LOG_TB_IN_ASM) {
3028 fprintf(logfile, "----------------\n"); 3030 fprintf(logfile, "----------------\n");
3029 fprintf(logfile, "nip=%08x super=%d ir=%d\n", 3031 fprintf(logfile, "nip=%08x super=%d ir=%d\n",
3030 ctx.nip, 1 - msr_pr, msr_ir); 3032 ctx.nip, 1 - msr_pr, msr_ir);
3031 } 3033 }
3032 #endif 3034 #endif
3033 ctx.opcode = ldl_code((void *)ctx.nip); 3035 ctx.opcode = ldl_code((void *)ctx.nip);
3034 -#if defined DEBUG_DISAS  
3035 - if (loglevel > 0) { 3036 +#if defined PPC_DEBUG_DISAS
  3037 + if (loglevel & CPU_LOG_TB_IN_ASM) {
3036 fprintf(logfile, "translate opcode %08x (%02x %02x %02x)\n", 3038 fprintf(logfile, "translate opcode %08x (%02x %02x %02x)\n",
3037 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode), 3039 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
3038 opc3(ctx.opcode)); 3040 opc3(ctx.opcode));
3039 } 3041 }
3040 #endif 3042 #endif
3041 ctx.nip += 4; 3043 ctx.nip += 4;
3042 - ctx.tb_offset++;  
3043 - /* Check decrementer exception */  
3044 - if (++ctx.decr_offset == env->decr + 1)  
3045 - ctx.exception = EXCP_DECR;  
3046 table = ppc_opcodes; 3044 table = ppc_opcodes;
3047 handler = table[opc1(ctx.opcode)]; 3045 handler = table[opc1(ctx.opcode)];
3048 if (is_indirect_opcode(handler)) { 3046 if (is_indirect_opcode(handler)) {
@@ -3098,26 +3096,17 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -3098,26 +3096,17 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3098 (ctx.nip & 0xFC) != 0x04) && 3096 (ctx.nip & 0xFC) != 0x04) &&
3099 ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI && 3097 ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI &&
3100 ctx.exception != EXCP_TRAP)) { 3098 ctx.exception != EXCP_TRAP)) {
3101 -#if !defined(CONFIG_USER_ONLY)  
3102 - gen_op_queue_exception(EXCP_TRACE);  
3103 -#endif  
3104 - if (ctx.exception == EXCP_NONE) {  
3105 - ctx.exception = EXCP_TRACE;  
3106 - } 3099 + RET_EXCP(ctxp, EXCP_TRACE, 0);
3107 } 3100 }
3108 /* if we reach a page boundary, stop generation */ 3101 /* if we reach a page boundary, stop generation */
3109 if ((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) { 3102 if ((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) {
3110 - if (ctx.exception == EXCP_NONE) {  
3111 - gen_op_b((long)ctx.tb, ctx.nip);  
3112 - ctx.exception = EXCP_BRANCH;  
3113 - } 3103 + RET_EXCP(ctxp, EXCP_BRANCH, 0);
3114 } 3104 }
3115 } 3105 }
3116 - /* In case of branch, this has already been done *BEFORE* the branch */  
3117 - if (ctx.exception != EXCP_BRANCH && ctx.exception != EXCP_RFI) {  
3118 - gen_op_update_tb(ctx.tb_offset);  
3119 - gen_op_update_decr(ctx.decr_offset);  
3120 - gen_op_process_exceptions(ctx.nip); 3106 + if (ctx.exception == EXCP_NONE) {
  3107 + gen_op_b((unsigned long)ctx.tb, ctx.nip);
  3108 + } else if (ctx.exception != EXCP_BRANCH) {
  3109 + gen_op_set_T0(0);
3121 } 3110 }
3122 #if 1 3111 #if 1
3123 /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump 3112 /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
@@ -3144,15 +3133,16 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -3144,15 +3133,16 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3144 } 3133 }
3145 env->access_type = ACCESS_INT; 3134 env->access_type = ACCESS_INT;
3146 #ifdef DEBUG_DISAS 3135 #ifdef DEBUG_DISAS
3147 - if (loglevel > 0) { 3136 + if (loglevel & CPU_LOG_TB_CPU) {
3148 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception); 3137 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
3149 cpu_ppc_dump_state(env, logfile, 0); 3138 cpu_ppc_dump_state(env, logfile, 0);
  3139 + }
  3140 + if (loglevel & CPU_LOG_TB_IN_ASM) {
3150 fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start)); 3141 fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start));
3151 -#if defined(CONFIG_USER_ONLY)  
3152 disas(logfile, (void *)pc_start, ctx.nip - pc_start, 0, 0); 3142 disas(logfile, (void *)pc_start, ctx.nip - pc_start, 0, 0);
3153 -#endif  
3154 fprintf(logfile, "\n"); 3143 fprintf(logfile, "\n");
3155 - 3144 + }
  3145 + if (loglevel & CPU_LOG_TB_OP) {
3156 fprintf(logfile, "OP:\n"); 3146 fprintf(logfile, "OP:\n");
3157 dump_ops(gen_opc_buf, gen_opparam_buf); 3147 dump_ops(gen_opc_buf, gen_opparam_buf);
3158 fprintf(logfile, "\n"); 3148 fprintf(logfile, "\n");