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 627 if no page found. */
628 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 632 #define CPU_LOG_TB_OP (1 << 2)
633 633 #define CPU_LOG_TB_OP_OPT (1 << 3)
634 634 #define CPU_LOG_INT (1 << 4)
635 635 #define CPU_LOG_EXEC (1 << 5)
636 636 #define CPU_LOG_PCALL (1 << 6)
637 637 #define CPU_LOG_IOPORT (1 << 7)
  638 +#define CPU_LOG_TB_CPU (1 << 8)
638 639  
639 640 /* define log items */
640 641 typedef struct CPULogItem {
... ...
cpu-exec.c
... ... @@ -241,11 +241,25 @@ int cpu_exec(CPUState *env1)
241 241 #endif
242 242 }
243 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 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 254 do_interrupt(env);
248 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 264 #endif
251 265 if (interrupt_request & CPU_INTERRUPT_EXITTB) {
... ... @@ -757,7 +771,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
757 771 /* we restore the process signal mask as the sigreturn should
758 772 do it (XXX: use sigsetjmp) */
759 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 775 } else {
762 776 /* activate soft MMU for this block */
763 777 cpu_resume_from_signal(env, puc);
... ...
... ... @@ -1132,6 +1132,8 @@ CPULogItem cpu_log_items[] = {
1132 1132 "show interrupts/exceptions in short format" },
1133 1133 { CPU_LOG_EXEC, "exec",
1134 1134 "show trace before each executed TB (lots of logs)" },
  1135 + { CPU_LOG_TB_CPU, "cpu",
  1136 + "show CPU state before bloc translation" },
1135 1137 #ifdef TARGET_I386
1136 1138 { CPU_LOG_PCALL, "pcall",
1137 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 28 const char *kernel_filename, const char *kernel_cmdline,
29 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 206 void ppc_init (int ram_size, int vga_ram_size, int boot_device,
32 207 DisplayState *ds, const char **fd_filename, int snapshot,
33 208 const char *kernel_filename, const char *kernel_cmdline,
... ...
hw/ppc_prep.c
... ... @@ -24,6 +24,9 @@
24 24 #include "vl.h"
25 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 30 //#define HARD_DEBUG_PPC_IO
28 31 //#define DEBUG_PPC_IO
29 32  
... ... @@ -663,7 +666,6 @@ static void VGA_printf (uint8_t *s)
663 666 static void VGA_init (void)
664 667 {
665 668 /* Basic VGA init, inspired by plex86 VGAbios */
666   - printf("Init VGA...\n");
667 669 #if 1
668 670 /* switch to color mode and enable CPU access 480 lines */
669 671 PPC_io_writeb(PPC_IO_BASE + 0x3C2, 0xC3);
... ... @@ -725,7 +727,6 @@ void PPC_init_hw (/*CPUPPCState *env,*/ uint32_t mem_size,
725 727 * if a decrementer exception is pending when it enables msr_ee,
726 728 * it's not ready to handle it...
727 729 */
728   - env->decr = 0xFFFFFFFF;
729 730 p = phys_ram_base + kernel_addr;
730 731 #if !defined (USE_OPEN_FIRMWARE)
731 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 949 }
949 950 }
950 951  
  952 + cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL);
  953 +
951 954 /* init basic PC hardware */
952 955 vga_initialize(ds, phys_ram_base + ram_size, ram_size,
953 956 vga_ram_size, 0);
... ...
linux-user/main.c
... ... @@ -504,6 +504,49 @@ void cpu_loop (CPUSPARCState *env)
504 504 #endif
505 505  
506 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 550 void cpu_loop(CPUPPCState *env)
508 551 {
509 552 target_siginfo_t info;
... ... @@ -812,7 +855,7 @@ void cpu_loop(CPUPPCState *env)
812 855 abort();
813 856 case EXCP_MTMSR:
814 857 /* We reloaded the msr, just go on */
815   - if (msr_pr) {
  858 + if (msr_pr == 0) {
816 859 fprintf(stderr, "Tried to go into supervisor mode !\n");
817 860 if (loglevel)
818 861 fprintf(logfile, "Tried to go into supervisor mode !\n");
... ... @@ -842,12 +885,7 @@ void cpu_loop(CPUPPCState *env)
842 885 }
843 886 abort();
844 887 }
845   - if (trapnr < EXCP_PPC_MAX)
846   - env->exceptions &= ~(1 << trapnr);
847 888 process_pending_signals(env);
848   - if (env->exceptions != 0) {
849   - check_exception_state(env);
850   - }
851 889 }
852 890 }
853 891 #endif
... ...
monitor.c
... ... @@ -589,6 +589,24 @@ static int monitor_get_xer (struct MonitorDef *md)
589 589 (cpu_single_env->xer[XER_CA] << XER_CA) |
590 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 610 #endif
593 611  
594 612 static MonitorDef monitor_defs[] = {
... ... @@ -651,12 +669,12 @@ static MonitorDef monitor_defs[] = {
651 669 { "nip|pc", offsetof(CPUState, nip) },
652 670 { "lr", offsetof(CPUState, lr) },
653 671 { "ctr", offsetof(CPUState, ctr) },
654   - { "decr", offsetof(CPUState, decr) },
  672 + { "decr", 0, &monitor_get_decr, },
655 673 { "ccr", 0, &monitor_get_ccr, },
656 674 { "msr", 0, &monitor_get_msr, },
657 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 678 { "sdr1", offsetof(CPUState, sdr1) },
661 679 { "sr0", offsetof(CPUState, sr[0]) },
662 680 { "sr1", offsetof(CPUState, sr[1]) },
... ...
target-ppc/cpu.h
... ... @@ -78,6 +78,8 @@ enum {
78 78 #define PPC_750 (PPC_INTEGER | PPC_FLOAT | PPC_FLOW | PPC_MEM | \
79 79 PPC_RES | PPC_CACHE | PPC_MISC | PPC_EXTERN | PPC_SEGMENT)
80 80  
  81 +typedef struct ppc_tb_t ppc_tb_t;
  82 +
81 83 /* Supervisor mode registers */
82 84 /* Machine state register */
83 85 #define MSR_POW 18
... ... @@ -134,10 +136,6 @@ typedef struct CPUPPCState {
134 136 /* special purpose registers */
135 137 uint32_t lr;
136 138 uint32_t ctr;
137   - /* Time base */
138   - uint32_t tb[2];
139   - /* decrementer */
140   - uint32_t decr;
141 139 /* BATs */
142 140 uint32_t DBAT[2][8];
143 141 uint32_t IBAT[2][8];
... ... @@ -154,13 +152,6 @@ typedef struct CPUPPCState {
154 152 int error_code;
155 153 int access_type; /* when a memory exception occurs, the access
156 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 155 int user_mode_only; /* user mode only simulation */
165 156 struct TranslationBlock *current_tb; /* currently executing TB */
166 157 /* soft mmu support */
... ... @@ -178,8 +169,13 @@ typedef struct CPUPPCState {
178 169 /* ice debug support */
179 170 uint32_t breakpoints[MAX_BREAKPOINTS];
180 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 180 /* user data */
185 181 void *opaque;
... ... @@ -206,10 +202,15 @@ void _store_xer (CPUPPCState *env, uint32_t value);
206 202 uint32_t _load_msr (CPUPPCState *env);
207 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 215 #define TARGET_PAGE_BITS 12
215 216 #include "cpu-all.h"
... ...
target-ppc/exec.h
... ... @@ -119,12 +119,8 @@ static inline uint32_t rotl (uint32_t i, int n)
119 119  
120 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 125 void do_load_cr (void);
130 126 void do_store_cr (uint32_t mask);
... ...
target-ppc/helper.c
... ... @@ -27,49 +27,10 @@
27 27 //#define DEBUG_BATS
28 28 //#define DEBUG_EXCEPTIONS
29 29  
30   -extern FILE *logfile, *stdout, *stderr;
31   -void exit (int);
  30 +extern FILE *stdout, *stderr;
32 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 36 /* PPC MMU emulation */
... ... @@ -500,8 +461,7 @@ void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr)
500 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 467 unsigned long tlb_addrr, tlb_addrw;
... ... @@ -701,9 +661,6 @@ void do_interrupt (CPUState *env)
701 661 uint32_t msr;
702 662 int excp = env->exception_index;
703 663  
704   - /* Dequeue PPC exceptions */
705   - if (excp < EXCP_PPC_MAX)
706   - env->exceptions &= ~(1 << excp);
707 664 msr = _load_msr(env);
708 665 #if defined (DEBUG_EXCEPTIONS)
709 666 if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1)
... ... @@ -812,7 +769,7 @@ void do_interrupt (CPUState *env)
812 769 }
813 770 #endif
814 771 /* Requeue it */
815   - do_queue_exception(EXCP_EXTERNAL);
  772 + do_raise_exception(EXCP_EXTERNAL);
816 773 return;
817 774 }
818 775 goto store_next;
... ... @@ -864,7 +821,7 @@ void do_interrupt (CPUState *env)
864 821 case EXCP_DECR:
865 822 if (msr_ee == 0) {
866 823 /* Requeue it */
867   - do_queue_exception(EXCP_DECR);
  824 + do_raise_exception(EXCP_DECR);
868 825 return;
869 826 }
870 827 goto store_next;
... ... @@ -937,4 +894,5 @@ void do_interrupt (CPUState *env)
937 894 T0 = 0;
938 895 #endif
939 896 #endif
  897 + env->exception_index = -1;
940 898 }
... ...
target-ppc/op.c
... ... @@ -208,32 +208,28 @@ PPC_OP(set_T2)
208 208 }
209 209  
210 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 223 env->nip = PARAM(1);
224   - if (env->exceptions != 0) {
225   - do_check_exception_state();
226   - }
227 224 }
228 225  
229 226 PPC_OP(debug)
230 227 {
231 228 env->nip = PARAM(1);
232   - env->brkstate = 1;
233 229 #if defined (DEBUG_OP)
234 230 dump_state();
235 231 #endif
236   - do_queue_exception(EXCP_DEBUG);
  232 + do_raise_exception(EXCP_DEBUG);
237 233 RETURN();
238 234 }
239 235  
... ... @@ -364,58 +360,38 @@ PPC_OP(store_ctr)
364 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 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 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 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 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 395 RETURN();
420 396 }
421 397  
... ... @@ -1471,17 +1447,14 @@ PPC_OP(fneg)
1471 1447 /* Return from interrupt */
1472 1448 PPC_OP(rfi)
1473 1449 {
  1450 + regs->nip = regs->spr[SRR0] & ~0x00000003;
1474 1451 T0 = regs->spr[SRR1] & ~0xFFFF0000;
1475 1452 do_store_msr();
1476   - do_tlbia();
1477 1453 #if defined (DEBUG_OP)
1478 1454 dump_rfi();
1479 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 1458 RETURN();
1486 1459 }
1487 1460  
... ... @@ -1493,7 +1466,7 @@ PPC_OP(tw)
1493 1466 (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
1494 1467 (T0 < T1 && (PARAM(1) & 0x02)) ||
1495 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 1470 RETURN();
1498 1471 }
1499 1472  
... ... @@ -1504,7 +1477,7 @@ PPC_OP(twi)
1504 1477 (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
1505 1478 (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
1506 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 1481 RETURN();
1509 1482 }
1510 1483  
... ...
target-ppc/op_helper.c
... ... @@ -31,31 +31,38 @@
31 31  
32 32 /*****************************************************************************/
33 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 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 132 /* Flush all tlb when changing translation mode or privilege level */
126 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 135 msr_pow = (T0 >> MSR_POW) & 0x03;
136 136 msr_ile = (T0 >> MSR_ILE) & 0x01;
137 137 msr_ee = (T0 >> MSR_EE) & 0x01;
... ...
target-ppc/op_mem.h
... ... @@ -97,8 +97,7 @@ PPC_OP(glue(lswx, MEMSUFFIX))
97 97 if (T1 > 0) {
98 98 if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) ||
99 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 101 } else {
103 102 glue(do_lsw, MEMSUFFIX)(PARAM(1));
104 103 }
... ... @@ -138,8 +137,7 @@ PPC_LDF_OP(fs, ldfl);
138 137 PPC_OP(glue(lwarx, MEMSUFFIX))
139 138 {
140 139 if (T0 & 0x03) {
141   - do_queue_exception(EXCP_ALIGN);
142   - do_process_exceptions();
  140 + do_raise_exception(EXCP_ALIGN);
143 141 } else {
144 142 T1 = glue(ldl, MEMSUFFIX)((void *)T0);
145 143 regs->reserve = T0;
... ... @@ -151,8 +149,7 @@ PPC_OP(glue(lwarx, MEMSUFFIX))
151 149 PPC_OP(glue(stwcx, MEMSUFFIX))
152 150 {
153 151 if (T0 & 0x03) {
154   - do_queue_exception(EXCP_ALIGN);
155   - do_process_exceptions();
  152 + do_raise_exception(EXCP_ALIGN);
156 153 } else {
157 154 if (regs->reserve != T0) {
158 155 env->crf[0] = xer_ov;
... ...
target-ppc/translate.c
... ... @@ -30,6 +30,7 @@
30 30 //#define DO_SINGLE_STEP
31 31 //#define DO_STEP_FLUSH
32 32 //#define DEBUG_DISAS
  33 +//#define PPC_DEBUG_DISAS
33 34  
34 35 enum {
35 36 #define DEF(s, n, copy_size) INDEX_op_ ## s,
... ... @@ -135,10 +136,6 @@ typedef struct DisasContext {
135 136 uint32_t nip;
136 137 uint32_t opcode;
137 138 uint32_t exception;
138   - /* Time base offset */
139   - uint32_t tb_offset;
140   - /* Decrementer offset */
141   - uint32_t decr_offset;
142 139 /* Execution mode */
143 140 #if !defined(CONFIG_USER_ONLY)
144 141 int supervisor;
... ... @@ -156,21 +153,26 @@ typedef struct opc_handler_t {
156 153 void (*handler)(DisasContext *ctx);
157 154 } opc_handler_t;
158 155  
159   -#define RET_EXCP(excp, error) \
  156 +#define RET_EXCP(ctx, excp, error) \
160 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 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 177 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
176 178 static void gen_##name (DisasContext *ctx); \
... ... @@ -312,29 +314,26 @@ GEN_OPCODE_MARK(start);
312 314 /* Invalid instruction */
313 315 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
314 316 {
315   - RET_INVAL();
  317 + RET_INVAL(ctx);
316 318 }
317 319  
318 320 /* Special opcode to stop emulation */
319 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 326 /* Special opcode to call open-firmware */
326 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 332 /* Special opcode to call RTAS */
333 333 GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON)
334 334 {
335 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 339 static opc_handler_t invalid_handler = {
... ... @@ -1010,7 +1009,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1010 1009 uint32_t simm = SIMM(ctx->opcode); \
1011 1010 if (rA(ctx->opcode) == 0 || \
1012 1011 rA(ctx->opcode) == rD(ctx->opcode)) { \
1013   - RET_INVAL(); \
  1012 + RET_INVAL(ctx); \
  1013 + return; \
1014 1014 } \
1015 1015 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1016 1016 if (simm != 0) \
... ... @@ -1025,7 +1025,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1025 1025 { \
1026 1026 if (rA(ctx->opcode) == 0 || \
1027 1027 rA(ctx->opcode) == rD(ctx->opcode)) { \
1028   - RET_INVAL(); \
  1028 + RET_INVAL(ctx); \
  1029 + return; \
1029 1030 } \
1030 1031 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1031 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 1087 { \
1087 1088 uint32_t simm = SIMM(ctx->opcode); \
1088 1089 if (rA(ctx->opcode) == 0) { \
1089   - RET_INVAL(); \
  1090 + RET_INVAL(ctx); \
  1091 + return; \
1090 1092 } \
1091 1093 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1092 1094 if (simm != 0) \
... ... @@ -1100,7 +1102,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1100 1102 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1101 1103 { \
1102 1104 if (rA(ctx->opcode) == 0) { \
1103   - RET_INVAL(); \
  1105 + RET_INVAL(ctx); \
  1106 + return; \
1104 1107 } \
1105 1108 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1106 1109 gen_op_load_gpr_T1(rB(ctx->opcode)); \
... ... @@ -1236,7 +1239,8 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1236 1239 nr = nb / 4;
1237 1240 if (((start + nr) > 32 && start <= ra && (start + nr - 32) > ra) ||
1238 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 1245 if (ra == 0) {
1242 1246 gen_op_set_T0(0);
... ... @@ -1376,7 +1380,8 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1376 1380 uint32_t simm = SIMM(ctx->opcode); \
1377 1381 if (rA(ctx->opcode) == 0 || \
1378 1382 rA(ctx->opcode) == rD(ctx->opcode)) { \
1379   - RET_INVAL(); \
  1383 + RET_INVAL(ctx); \
  1384 + return; \
1380 1385 } \
1381 1386 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1382 1387 if (simm != 0) \
... ... @@ -1391,7 +1396,8 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1391 1396 { \
1392 1397 if (rA(ctx->opcode) == 0 || \
1393 1398 rA(ctx->opcode) == rD(ctx->opcode)) { \
1394   - RET_INVAL(); \
  1399 + RET_INVAL(ctx); \
  1400 + return; \
1395 1401 } \
1396 1402 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1397 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 1454 { \
1449 1455 uint32_t simm = SIMM(ctx->opcode); \
1450 1456 if (rA(ctx->opcode) == 0) { \
1451   - RET_INVAL(); \
  1457 + RET_INVAL(ctx); \
  1458 + return; \
1452 1459 } \
1453 1460 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1454 1461 if (simm != 0) \
... ... @@ -1462,7 +1469,8 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1462 1469 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1463 1470 { \
1464 1471 if (rA(ctx->opcode) == 0) { \
1465   - RET_INVAL(); \
  1472 + RET_INVAL(ctx); \
  1473 + return; \
1466 1474 } \
1467 1475 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1468 1476 gen_op_load_gpr_T1(rB(ctx->opcode)); \
... ... @@ -1502,7 +1510,7 @@ GEN_STFS(fs, 0x14);
1502 1510 /* stfiwx */
1503 1511 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
1504 1512 {
1505   - RET_INVAL();
  1513 + RET_INVAL(ctx);
1506 1514 }
1507 1515  
1508 1516 /*** Branch ***/
... ... @@ -1512,9 +1520,6 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1512 1520 {
1513 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 1523 if (AA(ctx->opcode) == 0)
1519 1524 target = ctx->nip + li - 4;
1520 1525 else
... ... @@ -1538,10 +1543,6 @@ static inline void gen_bcond(DisasContext *ctx, int type)
1538 1543 uint32_t mask;
1539 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 1546 if ((bo & 0x4) == 0)
1546 1547 gen_op_dec_ctr();
1547 1548 switch(type) {
... ... @@ -1683,14 +1684,15 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
1683 1684 GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1684 1685 {
1685 1686 #if defined(CONFIG_USER_ONLY)
1686   - RET_PRIVOPC();
  1687 + RET_PRIVOPC(ctx);
1687 1688 #else
1688 1689 /* Restore CPU state */
1689 1690 if (!ctx->supervisor) {
1690   - RET_PRIVOPC();
  1691 + RET_PRIVOPC(ctx);
  1692 + return;
1691 1693 }
1692 1694 gen_op_rfi();
1693   - ctx->exception = EXCP_RFI;
  1695 + RET_EXCP(ctx, EXCP_RFI, 0);
1694 1696 #endif
1695 1697 }
1696 1698  
... ... @@ -1698,11 +1700,10 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1698 1700 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
1699 1701 {
1700 1702 #if defined(CONFIG_USER_ONLY)
1701   - gen_op_queue_exception(EXCP_SYSCALL_USER);
  1703 + RET_EXCP(ctx, EXCP_SYSCALL_USER, 0);
1702 1704 #else
1703   - gen_op_queue_exception(EXCP_SYSCALL);
  1705 + RET_EXCP(ctx, EXCP_SYSCALL, 0);
1704 1706 #endif
1705   - ctx->exception = EXCP_SYSCALL;
1706 1707 }
1707 1708  
1708 1709 /*** Trap ***/
... ... @@ -1770,10 +1771,11 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
1770 1771 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
1771 1772 {
1772 1773 #if defined(CONFIG_USER_ONLY)
1773   - RET_PRIVREG();
  1774 + RET_PRIVREG(ctx);
1774 1775 #else
1775 1776 if (!ctx->supervisor) {
1776   - RET_PRIVREG();
  1777 + RET_PRIVREG(ctx);
  1778 + return;
1777 1779 }
1778 1780 gen_op_load_msr();
1779 1781 gen_op_store_T0_gpr(rD(ctx->opcode));
... ... @@ -1792,11 +1794,11 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
1792 1794 #endif
1793 1795 {
1794 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 1799 case 0:
1798   - RET_PRIVREG();
1799   - break;
  1800 + RET_PRIVREG(ctx);
  1801 + return;
1800 1802 default:
1801 1803 break;
1802 1804 }
... ... @@ -1910,19 +1912,13 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
1910 1912 gen_op_load_sdr1();
1911 1913 break;
1912 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 1916 break;
1917 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 1919 break;
1922 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 1922 break;
1927 1923 default:
1928 1924 gen_op_load_spr(sprn);
... ... @@ -1939,18 +1935,16 @@ GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC)
1939 1935 /* We need to update the time base before reading it */
1940 1936 switch (sprn) {
1941 1937 case V_TBL:
1942   - gen_op_update_tb(ctx->tb_offset);
1943 1938 /* TBL is still in T0 */
  1939 + gen_op_load_tbl();
1944 1940 break;
1945 1941 case V_TBU:
1946   - gen_op_update_tb(ctx->tb_offset);
1947   - gen_op_load_tb(1);
  1942 + gen_op_load_tbu();
1948 1943 break;
1949 1944 default:
1950   - RET_INVAL();
1951   - break;
  1945 + RET_INVAL(ctx);
  1946 + return;
1952 1947 }
1953   - ctx->tb_offset = 0;
1954 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 1959 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
1966 1960 {
1967 1961 #if defined(CONFIG_USER_ONLY)
1968   - RET_PRIVREG();
  1962 + RET_PRIVREG(ctx);
1969 1963 #else
1970 1964 if (!ctx->supervisor) {
1971   - RET_PRIVREG();
  1965 + RET_PRIVREG(ctx);
  1966 + return;
1972 1967 }
1973 1968 gen_op_load_gpr_T0(rS(ctx->opcode));
1974 1969 gen_op_store_msr();
1975 1970 /* Must stop the translation as machine state (may have) changed */
1976   - ctx->exception = EXCP_MTMSR;
  1971 + RET_MTMSR(ctx);
1977 1972 #endif
1978 1973 }
1979 1974  
... ... @@ -1995,10 +1990,10 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
1995 1990 #endif
1996 1991 {
1997 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 1994 break;
2000 1995 case 0:
2001   - RET_PRIVREG();
  1996 + RET_PRIVREG(ctx);
2002 1997 break;
2003 1998 default:
2004 1999 break;
... ... @@ -2147,16 +2142,13 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
2147 2142 gen_op_tlbia();
2148 2143 break;
2149 2144 case O_TBL:
2150   - gen_op_store_tb(0);
2151   - ctx->tb_offset = 0;
  2145 + gen_op_store_tbl();
2152 2146 break;
2153 2147 case O_TBU:
2154   - gen_op_store_tb(1);
2155   - ctx->tb_offset = 0;
  2148 + gen_op_store_tbu();
2156 2149 break;
2157 2150 case DECR:
2158 2151 gen_op_store_decr();
2159   - ctx->decr_offset = 0;
2160 2152 break;
2161 2153 default:
2162 2154 gen_op_store_spr(sprn);
... ... @@ -2186,10 +2178,11 @@ GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
2186 2178 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
2187 2179 {
2188 2180 #if defined(CONFIG_USER_ONLY)
2189   - RET_PRIVOPC();
  2181 + RET_PRIVOPC(ctx);
2190 2182 #else
2191 2183 if (!ctx->supervisor) {
2192   - RET_PRIVOPC();
  2184 + RET_PRIVOPC(ctx);
  2185 + return;
2193 2186 }
2194 2187 if (rA(ctx->opcode) == 0) {
2195 2188 gen_op_load_gpr_T0(rB(ctx->opcode));
... ... @@ -2274,10 +2267,11 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE_OPT)
2274 2267 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
2275 2268 {
2276 2269 #if defined(CONFIG_USER_ONLY)
2277   - RET_PRIVREG();
  2270 + RET_PRIVREG(ctx);
2278 2271 #else
2279 2272 if (!ctx->supervisor) {
2280   - RET_PRIVREG();
  2273 + RET_PRIVREG(ctx);
  2274 + return;
2281 2275 }
2282 2276 gen_op_load_sr(SR(ctx->opcode));
2283 2277 gen_op_store_T0_gpr(rD(ctx->opcode));
... ... @@ -2288,10 +2282,11 @@ GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
2288 2282 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
2289 2283 {
2290 2284 #if defined(CONFIG_USER_ONLY)
2291   - RET_PRIVREG();
  2285 + RET_PRIVREG(ctx);
2292 2286 #else
2293 2287 if (!ctx->supervisor) {
2294   - RET_PRIVREG();
  2288 + RET_PRIVREG(ctx);
  2289 + return;
2295 2290 }
2296 2291 gen_op_load_gpr_T1(rB(ctx->opcode));
2297 2292 gen_op_load_srin();
... ... @@ -2303,14 +2298,18 @@ GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
2303 2298 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
2304 2299 {
2305 2300 #if defined(CONFIG_USER_ONLY)
2306   - RET_PRIVREG();
  2301 + RET_PRIVREG(ctx);
2307 2302 #else
2308 2303 if (!ctx->supervisor) {
2309   - RET_PRIVREG();
  2304 + RET_PRIVREG(ctx);
  2305 + return;
2310 2306 }
2311 2307 gen_op_load_gpr_T0(rS(ctx->opcode));
2312 2308 gen_op_store_sr(SR(ctx->opcode));
  2309 +#if 0
2313 2310 gen_op_tlbia();
  2311 + RET_MTMSR(ctx);
  2312 +#endif
2314 2313 #endif
2315 2314 }
2316 2315  
... ... @@ -2318,10 +2317,11 @@ GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
2318 2317 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
2319 2318 {
2320 2319 #if defined(CONFIG_USER_ONLY)
2321   - RET_PRIVREG();
  2320 + RET_PRIVREG(ctx);
2322 2321 #else
2323 2322 if (!ctx->supervisor) {
2324   - RET_PRIVREG();
  2323 + RET_PRIVREG(ctx);
  2324 + return;
2325 2325 }
2326 2326 gen_op_load_gpr_T0(rS(ctx->opcode));
2327 2327 gen_op_load_gpr_T1(rB(ctx->opcode));
... ... @@ -2336,10 +2336,13 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
2336 2336 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT)
2337 2337 {
2338 2338 #if defined(CONFIG_USER_ONLY)
2339   - RET_PRIVOPC();
  2339 + RET_PRIVOPC(ctx);
2340 2340 #else
2341 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 2347 gen_op_tlbia();
2345 2348 #endif
... ... @@ -2349,10 +2352,11 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT)
2349 2352 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
2350 2353 {
2351 2354 #if defined(CONFIG_USER_ONLY)
2352   - RET_PRIVOPC();
  2355 + RET_PRIVOPC(ctx);
2353 2356 #else
2354 2357 if (!ctx->supervisor) {
2355   - RET_PRIVOPC();
  2358 + RET_PRIVOPC(ctx);
  2359 + return;
2356 2360 }
2357 2361 gen_op_load_gpr_T0(rB(ctx->opcode));
2358 2362 gen_op_tlbie();
... ... @@ -2363,10 +2367,11 @@ GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
2363 2367 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM)
2364 2368 {
2365 2369 #if defined(CONFIG_USER_ONLY)
2366   - RET_PRIVOPC();
  2370 + RET_PRIVOPC(ctx);
2367 2371 #else
2368 2372 if (!ctx->supervisor) {
2369   - RET_PRIVOPC();
  2373 + RET_PRIVOPC(ctx);
  2374 + return;
2370 2375 }
2371 2376 /* This has no effect: it should ensure that all previous
2372 2377 * tlbie have completed
... ... @@ -2916,7 +2921,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
2916 2921 fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
2917 2922 }
2918 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 2926 for (i = 0; i < 16; i++) {
2921 2927 if ((i & 3) == 0)
2922 2928 fprintf(f, "FPR%02d:", i);
... ... @@ -2924,8 +2930,8 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
2924 2930 if ((i & 3) == 3)
2925 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 2935 fprintf(f, "reservation 0x%08x\n", env->reserve);
2930 2936 fflush(f);
2931 2937 }
... ... @@ -2952,7 +2958,6 @@ CPUPPCState *cpu_ppc_init(void)
2952 2958 // env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */
2953 2959 // env->spr[PVR] = 0x00070100; /* IBM 750FX */
2954 2960 #endif
2955   - env->decr = 0xFFFFFFFF;
2956 2961 if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0)
2957 2962 return NULL;
2958 2963 init_spr_rights(env->spr[PVR]);
... ... @@ -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 2984 int print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
2981 2985 int dialect);
2982 2986  
2983 2987 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2984 2988 int search_pc)
2985 2989 {
2986   - DisasContext ctx;
  2990 + DisasContext ctx, *ctxp = &ctx;
2987 2991 opc_handler_t **table, *handler;
2988 2992 uint32_t pc_start;
2989 2993 uint16_t *gen_opc_end;
... ... @@ -2994,8 +2998,6 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2994 2998 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2995 2999 gen_opparam_ptr = gen_opparam_buf;
2996 3000 ctx.nip = pc_start;
2997   - ctx.tb_offset = 0;
2998   - ctx.decr_offset = 0;
2999 3001 ctx.tb = tb;
3000 3002 ctx.exception = EXCP_NONE;
3001 3003 #if defined(CONFIG_USER_ONLY)
... ... @@ -3023,26 +3025,22 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3023 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 3030 fprintf(logfile, "----------------\n");
3029 3031 fprintf(logfile, "nip=%08x super=%d ir=%d\n",
3030 3032 ctx.nip, 1 - msr_pr, msr_ir);
3031 3033 }
3032 3034 #endif
3033 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 3038 fprintf(logfile, "translate opcode %08x (%02x %02x %02x)\n",
3037 3039 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
3038 3040 opc3(ctx.opcode));
3039 3041 }
3040 3042 #endif
3041 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 3044 table = ppc_opcodes;
3047 3045 handler = table[opc1(ctx.opcode)];
3048 3046 if (is_indirect_opcode(handler)) {
... ... @@ -3098,26 +3096,17 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
3098 3096 (ctx.nip & 0xFC) != 0x04) &&
3099 3097 ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI &&
3100 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 3101 /* if we reach a page boundary, stop generation */
3109 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 3111 #if 1
3123 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 3133 }
3145 3134 env->access_type = ACCESS_INT;
3146 3135 #ifdef DEBUG_DISAS
3147   - if (loglevel > 0) {
  3136 + if (loglevel & CPU_LOG_TB_CPU) {
3148 3137 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
3149 3138 cpu_ppc_dump_state(env, logfile, 0);
  3139 + }
  3140 + if (loglevel & CPU_LOG_TB_IN_ASM) {
3150 3141 fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start));
3151   -#if defined(CONFIG_USER_ONLY)
3152 3142 disas(logfile, (void *)pc_start, ctx.nip - pc_start, 0, 0);
3153   -#endif
3154 3143 fprintf(logfile, "\n");
3155   -
  3144 + }
  3145 + if (loglevel & CPU_LOG_TB_OP) {
3156 3146 fprintf(logfile, "OP:\n");
3157 3147 dump_ops(gen_opc_buf, gen_opparam_buf);
3158 3148 fprintf(logfile, "\n");
... ...