Commit 9fddaa0c0cabb610947146a79b4a9a38b0a216e5
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
Showing
14 changed files
with
463 additions
and
297 deletions
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); | ... | ... |
exec.c
... | ... | @@ -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"); | ... | ... |