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