Commit 9a64fbe4d89751524be0954f87dd514083295e99

Authored by bellard
1 parent efe160c5

PowerPC system emulation (Jocelyn Mayer) - modified patch to use new TLB api


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@528 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/cpu.h
@@ -25,6 +25,8 @@ @@ -25,6 +25,8 @@
25 25
26 #include "cpu-defs.h" 26 #include "cpu-defs.h"
27 27
  28 +//#define USE_OPEN_FIRMWARE
  29 +
28 /*** Sign extend constants ***/ 30 /*** Sign extend constants ***/
29 /* 8 to 32 bits */ 31 /* 8 to 32 bits */
30 static inline int32_t s_ext8 (uint8_t value) 32 static inline int32_t s_ext8 (uint8_t value)
@@ -54,56 +56,28 @@ static inline int32_t s_ext24 (uint32_t value) @@ -54,56 +56,28 @@ static inline int32_t s_ext24 (uint32_t value)
54 #include "config.h" 56 #include "config.h"
55 #include <setjmp.h> 57 #include <setjmp.h>
56 58
57 -/* Floting point status and control register */  
58 -#define FPSCR_FX 31  
59 -#define FPSCR_FEX 30  
60 -#define FPSCR_VX 29  
61 -#define FPSCR_OX 28  
62 -#define FPSCR_UX 27  
63 -#define FPSCR_ZX 26  
64 -#define FPSCR_XX 25  
65 -#define FPSCR_VXSNAN 24  
66 -#define FPSCR_VXISI 26  
67 -#define FPSCR_VXIDI 25  
68 -#define FPSCR_VXZDZ 21  
69 -#define FPSCR_VXIMZ 20 59 +/* Instruction types */
  60 +enum {
  61 + PPC_NONE = 0x0000,
  62 + PPC_INTEGER = 0x0001, /* CPU has integer operations instructions */
  63 + PPC_FLOAT = 0x0002, /* CPU has floating point operations instructions */
  64 + PPC_FLOW = 0x0004, /* CPU has flow control instructions */
  65 + PPC_MEM = 0x0008, /* CPU has virtual memory instructions */
  66 + PPC_RES = 0x0010, /* CPU has ld/st with reservation instructions */
  67 + PPC_CACHE = 0x0020, /* CPU has cache control instructions */
  68 + PPC_MISC = 0x0040, /* CPU has spr/msr access instructions */
  69 + PPC_EXTERN = 0x0080, /* CPU has external control instructions */
  70 + PPC_SEGMENT = 0x0100, /* CPU has memory segment instructions */
  71 + PPC_CACHE_OPT= 0x0200,
  72 + PPC_FLOAT_OPT= 0x0400,
  73 + PPC_MEM_OPT = 0x0800,
  74 +};
70 75
71 -#define FPSCR_VXVC 18  
72 -#define FPSCR_FR 17  
73 -#define FPSCR_FI 16  
74 -#define FPSCR_FPRF 11  
75 -#define FPSCR_VXSOFT 9  
76 -#define FPSCR_VXSQRT 8  
77 -#define FPSCR_VXCVI 7  
78 -#define FPSCR_OE 6  
79 -#define FPSCR_UE 5  
80 -#define FPSCR_ZE 4  
81 -#define FPSCR_XE 3  
82 -#define FPSCR_NI 2  
83 -#define FPSCR_RN 0  
84 -#define fpscr_fx env->fpscr[FPSCR_FX]  
85 -#define fpscr_fex env->fpscr[FPSCR_FEX]  
86 -#define fpscr_vx env->fpscr[FPSCR_VX]  
87 -#define fpscr_ox env->fpscr[FPSCR_OX]  
88 -#define fpscr_ux env->fpscr[FPSCR_UX]  
89 -#define fpscr_zx env->fpscr[FPSCR_ZX]  
90 -#define fpscr_xx env->fpscr[FPSCR_XX]  
91 -#define fpscr_vsxnan env->fpscr[FPSCR_VXSNAN]  
92 -#define fpscr_vxisi env->fpscr[FPSCR_VXISI]  
93 -#define fpscr_vxidi env->fpscr[FPSCR_VXIDI]  
94 -#define fpscr_vxzdz env->fpscr[FPSCR_VXZDZ]  
95 -#define fpscr_vximz env->fpscr[FPSCR_VXIMZ]  
96 -#define fpscr_fr env->fpscr[FPSCR_FR]  
97 -#define fpscr_fi env->fpscr[FPSCR_FI]  
98 -#define fpscr_fprf env->fpscr[FPSCR_FPRF]  
99 -#define fpscr_vxsoft env->fpscr[FPSCR_VXSOFT]  
100 -#define fpscr_vxsqrt env->fpscr[FPSCR_VXSQRT]  
101 -#define fpscr_oe env->fpscr[FPSCR_OE]  
102 -#define fpscr_ue env->fpscr[FPSCR_UE]  
103 -#define fpscr_ze env->fpscr[FPSCR_ZE]  
104 -#define fpscr_xe env->fpscr[FPSCR_XE]  
105 -#define fpscr_ni env->fpscr[FPSCR_NI]  
106 -#define fpscr_rn env->fpscr[FPSCR_RN] 76 +#define PPC_COMMON (PPC_INTEGER | PPC_FLOAT | PPC_FLOW | PPC_MEM | \
  77 + PPC_RES | PPC_CACHE | PPC_MISC | PPC_SEGMENT)
  78 +/* PPC 740/745/750/755 (aka G3) has external access instructions */
  79 +#define PPC_750 (PPC_INTEGER | PPC_FLOAT | PPC_FLOW | PPC_MEM | \
  80 + PPC_RES | PPC_CACHE | PPC_MISC | PPC_EXTERN | PPC_SEGMENT)
107 81
108 /* Supervisor mode registers */ 82 /* Supervisor mode registers */
109 /* Machine state register */ 83 /* Machine state register */
@@ -139,26 +113,16 @@ static inline int32_t s_ext24 (uint32_t value) @@ -139,26 +113,16 @@ static inline int32_t s_ext24 (uint32_t value)
139 #define msr_le env->msr[MSR_LE] 113 #define msr_le env->msr[MSR_LE]
140 114
141 /* Segment registers */ 115 /* Segment registers */
142 -typedef struct ppc_sr_t {  
143 - uint32_t t:1;  
144 - uint32_t ks:1;  
145 - uint32_t kp:1;  
146 - uint32_t n:1;  
147 - uint32_t res:4;  
148 - uint32_t vsid:24;  
149 -} ppc_sr_t;  
150 -  
151 typedef struct CPUPPCState { 116 typedef struct CPUPPCState {
152 /* general purpose registers */ 117 /* general purpose registers */
153 uint32_t gpr[32]; 118 uint32_t gpr[32];
154 /* floating point registers */ 119 /* floating point registers */
155 double fpr[32]; 120 double fpr[32];
156 /* segment registers */ 121 /* segment registers */
157 - ppc_sr_t sr[16];  
158 - /* special purpose registers */  
159 - uint32_t spr[1024]; 122 + uint32_t sdr1;
  123 + uint32_t sr[16];
160 /* XER */ 124 /* XER */
161 - uint8_t xer[32]; 125 + uint8_t xer[4];
162 /* Reservation address */ 126 /* Reservation address */
163 uint32_t reserve; 127 uint32_t reserve;
164 /* machine state register */ 128 /* machine state register */
@@ -166,11 +130,20 @@ typedef struct CPUPPCState { @@ -166,11 +130,20 @@ typedef struct CPUPPCState {
166 /* condition register */ 130 /* condition register */
167 uint8_t crf[8]; 131 uint8_t crf[8];
168 /* floating point status and control register */ 132 /* floating point status and control register */
169 - uint8_t fpscr[32]; 133 + uint8_t fpscr[8];
170 uint32_t nip; 134 uint32_t nip;
171 - /* CPU exception code */  
172 - uint32_t exception;  
173 - 135 + /* special purpose registers */
  136 + uint32_t lr;
  137 + uint32_t ctr;
  138 + /* Time base */
  139 + uint32_t tb[2];
  140 + /* decrementer */
  141 + uint32_t decr;
  142 + /* BATs */
  143 + uint32_t DBAT[2][8];
  144 + uint32_t IBAT[2][8];
  145 + /* all others */
  146 + uint32_t spr[1024];
174 /* qemu dedicated */ 147 /* qemu dedicated */
175 /* temporary float registers */ 148 /* temporary float registers */
176 double ft0; 149 double ft0;
@@ -180,9 +153,14 @@ typedef struct CPUPPCState { @@ -180,9 +153,14 @@ typedef struct CPUPPCState {
180 jmp_buf jmp_env; 153 jmp_buf jmp_env;
181 int exception_index; 154 int exception_index;
182 int error_code; 155 int error_code;
  156 + uint32_t exceptions; /* exception queue */
  157 + uint32_t errors[16];
183 int user_mode_only; /* user mode only simulation */ 158 int user_mode_only; /* user mode only simulation */
184 struct TranslationBlock *current_tb; /* currently executing TB */ 159 struct TranslationBlock *current_tb; /* currently executing TB */
185 - 160 + /* soft mmu support */
  161 + /* 0 = kernel, 1 = user */
  162 + CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
  163 + CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
186 /* user data */ 164 /* user data */
187 void *opaque; 165 void *opaque;
188 } CPUPPCState; 166 } CPUPPCState;
@@ -198,107 +176,99 @@ int cpu_ppc_signal_handler(int host_signum, struct siginfo *info, @@ -198,107 +176,99 @@ int cpu_ppc_signal_handler(int host_signum, struct siginfo *info,
198 void *puc); 176 void *puc);
199 177
200 void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags); 178 void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags);
  179 +void cpu_loop_exit(void);
  180 +void dump_stack (CPUPPCState *env);
  181 +uint32_t _load_xer (void);
  182 +void _store_xer (uint32_t value);
  183 +uint32_t _load_msr (void);
  184 +void _store_msr (uint32_t value);
  185 +void do_interrupt (CPUPPCState *env);
201 186
202 #define TARGET_PAGE_BITS 12 187 #define TARGET_PAGE_BITS 12
203 #include "cpu-all.h" 188 #include "cpu-all.h"
204 189
205 #define ugpr(n) (env->gpr[n]) 190 #define ugpr(n) (env->gpr[n])
206 -#define fpr(n) (env->fpr[n]) 191 +#define fprd(n) (env->fpr[n])
  192 +#define fprs(n) ((float)env->fpr[n])
  193 +#define fpru(n) ((uint32_t)env->fpr[n])
  194 +#define fpri(n) ((int32_t)env->fpr[n])
207 195
208 #define SPR_ENCODE(sprn) \ 196 #define SPR_ENCODE(sprn) \
209 (((sprn) >> 5) | (((sprn) & 0x1F) << 5)) 197 (((sprn) >> 5) | (((sprn) & 0x1F) << 5))
210 198
211 /* User mode SPR */ 199 /* User mode SPR */
212 #define spr(n) env->spr[n] 200 #define spr(n) env->spr[n]
213 -//#define XER spr[1]  
214 -#define XER env->xer  
215 #define XER_SO 31 201 #define XER_SO 31
216 #define XER_OV 30 202 #define XER_OV 30
217 #define XER_CA 29 203 #define XER_CA 29
218 #define XER_BC 0 204 #define XER_BC 0
219 -#define xer_so env->xer[XER_SO]  
220 -#define xer_ov env->xer[XER_OV]  
221 -#define xer_ca env->xer[XER_CA]  
222 -#define xer_bc env->xer[XER_BC] 205 +#define xer_so env->xer[3]
  206 +#define xer_ov env->xer[2]
  207 +#define xer_ca env->xer[1]
  208 +#define xer_bc env->xer[0]
223 209
224 -#define LR spr[SPR_ENCODE(8)]  
225 -#define CTR spr[SPR_ENCODE(9)] 210 +#define XER SPR_ENCODE(1)
  211 +#define LR SPR_ENCODE(8)
  212 +#define CTR SPR_ENCODE(9)
226 /* VEA mode SPR */ 213 /* VEA mode SPR */
227 -#define V_TBL spr[SPR_ENCODE(268)]  
228 -#define V_TBU spr[SPR_ENCODE(269)] 214 +#define V_TBL SPR_ENCODE(268)
  215 +#define V_TBU SPR_ENCODE(269)
229 /* supervisor mode SPR */ 216 /* supervisor mode SPR */
230 -#define DSISR spr[SPR_ENCODE(18)]  
231 -#define DAR spr[SPR_ENCODE(19)]  
232 -#define DEC spr[SPR_ENCODE(22)]  
233 -#define SDR1 spr[SPR_ENCODE(25)]  
234 -typedef struct ppc_sdr1_t {  
235 - uint32_t htaborg:16;  
236 - uint32_t res:7;  
237 - uint32_t htabmask:9;  
238 -} ppc_sdr1_t;  
239 -#define SRR0 spr[SPR_ENCODE(26)]  
240 -#define SRR0_MASK 0xFFFFFFFC  
241 -#define SRR1 spr[SPR_ENCODE(27)]  
242 -#define SPRG0 spr[SPR_ENCODE(272)]  
243 -#define SPRG1 spr[SPR_ENCODE(273)]  
244 -#define SPRG2 spr[SPR_ENCODE(274)]  
245 -#define SPRG3 spr[SPR_ENCODE(275)]  
246 -#define EAR spr[SPR_ENCODE(282)]  
247 -typedef struct ppc_ear_t {  
248 - uint32_t e:1;  
249 - uint32_t res:25;  
250 - uint32_t rid:6;  
251 -} ppc_ear_t;  
252 -#define TBL spr[SPR_ENCODE(284)]  
253 -#define TBU spr[SPR_ENCODE(285)]  
254 -#define PVR spr[SPR_ENCODE(287)]  
255 -typedef struct ppc_pvr_t {  
256 - uint32_t version:16;  
257 - uint32_t revision:16;  
258 -} ppc_pvr_t;  
259 -#define IBAT0U spr[SPR_ENCODE(528)]  
260 -#define IBAT0L spr[SPR_ENCODE(529)]  
261 -#define IBAT1U spr[SPR_ENCODE(530)]  
262 -#define IBAT1L spr[SPR_ENCODE(531)]  
263 -#define IBAT2U spr[SPR_ENCODE(532)]  
264 -#define IBAT2L spr[SPR_ENCODE(533)]  
265 -#define IBAT3U spr[SPR_ENCODE(534)]  
266 -#define IBAT3L spr[SPR_ENCODE(535)]  
267 -#define DBAT0U spr[SPR_ENCODE(536)]  
268 -#define DBAT0L spr[SPR_ENCODE(537)]  
269 -#define DBAT1U spr[SPR_ENCODE(538)]  
270 -#define DBAT1L spr[SPR_ENCODE(539)]  
271 -#define DBAT2U spr[SPR_ENCODE(540)]  
272 -#define DBAT2L spr[SPR_ENCODE(541)]  
273 -#define DBAT3U spr[SPR_ENCODE(542)]  
274 -#define DBAT3L spr[SPR_ENCODE(543)]  
275 -typedef struct ppc_ubat_t {  
276 - uint32_t bepi:15;  
277 - uint32_t res:4;  
278 - uint32_t bl:11;  
279 - uint32_t vs:1;  
280 - uint32_t vp:1;  
281 -} ppc_ubat_t;  
282 -typedef struct ppc_lbat_t {  
283 - uint32_t brpn:15;  
284 - uint32_t res0:10;  
285 - uint32_t w:1;  
286 - uint32_t i:1;  
287 - uint32_t m:1;  
288 - uint32_t g:1;  
289 - uint32_t res1:1;  
290 - uint32_t pp:2;  
291 -} ppc_lbat_t;  
292 -#define DABR spr[SPR_ENCODE(1013)] 217 +#define DSISR SPR_ENCODE(18)
  218 +#define DAR SPR_ENCODE(19)
  219 +#define DECR SPR_ENCODE(22)
  220 +#define SDR1 SPR_ENCODE(25)
  221 +#define SRR0 SPR_ENCODE(26)
  222 +#define SRR1 SPR_ENCODE(27)
  223 +#define SPRG0 SPR_ENCODE(272)
  224 +#define SPRG1 SPR_ENCODE(273)
  225 +#define SPRG2 SPR_ENCODE(274)
  226 +#define SPRG3 SPR_ENCODE(275)
  227 +#define SPRG4 SPR_ENCODE(276)
  228 +#define SPRG5 SPR_ENCODE(277)
  229 +#define SPRG6 SPR_ENCODE(278)
  230 +#define SPRG7 SPR_ENCODE(279)
  231 +#define ASR SPR_ENCODE(280)
  232 +#define EAR SPR_ENCODE(282)
  233 +#define O_TBL SPR_ENCODE(284)
  234 +#define O_TBU SPR_ENCODE(285)
  235 +#define PVR SPR_ENCODE(287)
  236 +#define IBAT0U SPR_ENCODE(528)
  237 +#define IBAT0L SPR_ENCODE(529)
  238 +#define IBAT1U SPR_ENCODE(530)
  239 +#define IBAT1L SPR_ENCODE(531)
  240 +#define IBAT2U SPR_ENCODE(532)
  241 +#define IBAT2L SPR_ENCODE(533)
  242 +#define IBAT3U SPR_ENCODE(534)
  243 +#define IBAT3L SPR_ENCODE(535)
  244 +#define DBAT0U SPR_ENCODE(536)
  245 +#define DBAT0L SPR_ENCODE(537)
  246 +#define DBAT1U SPR_ENCODE(538)
  247 +#define DBAT1L SPR_ENCODE(539)
  248 +#define DBAT2U SPR_ENCODE(540)
  249 +#define DBAT2L SPR_ENCODE(541)
  250 +#define DBAT3U SPR_ENCODE(542)
  251 +#define DBAT3L SPR_ENCODE(543)
  252 +#define IBAT4U SPR_ENCODE(560)
  253 +#define IBAT4L SPR_ENCODE(561)
  254 +#define IBAT5U SPR_ENCODE(562)
  255 +#define IBAT5L SPR_ENCODE(563)
  256 +#define IBAT6U SPR_ENCODE(564)
  257 +#define IBAT6L SPR_ENCODE(565)
  258 +#define IBAT7U SPR_ENCODE(566)
  259 +#define IBAT7L SPR_ENCODE(567)
  260 +#define DBAT4U SPR_ENCODE(568)
  261 +#define DBAT4L SPR_ENCODE(569)
  262 +#define DBAT5U SPR_ENCODE(570)
  263 +#define DBAT5L SPR_ENCODE(571)
  264 +#define DBAT6U SPR_ENCODE(572)
  265 +#define DBAT6L SPR_ENCODE(573)
  266 +#define DBAT7U SPR_ENCODE(574)
  267 +#define DBAT7L SPR_ENCODE(575)
  268 +#define DABR SPR_ENCODE(1013)
293 #define DABR_MASK 0xFFFFFFF8 269 #define DABR_MASK 0xFFFFFFF8
294 -typedef struct ppc_dabr_t {  
295 - uint32_t dab:29;  
296 - uint32_t bt:1;  
297 - uint32_t dw:1;  
298 - uint32_t dr:1;  
299 -} ppc_dabr_t;  
300 -#define FPECR spr[SPR_ENCODE(1022)]  
301 -#define PIR spr[SPR_ENCODE(1023)] 270 +#define FPECR SPR_ENCODE(1022)
  271 +#define PIR SPR_ENCODE(1023)
302 272
303 #define TARGET_PAGE_BITS 12 273 #define TARGET_PAGE_BITS 12
304 #include "cpu-all.h" 274 #include "cpu-all.h"
@@ -307,10 +277,30 @@ CPUPPCState *cpu_ppc_init(void); @@ -307,10 +277,30 @@ CPUPPCState *cpu_ppc_init(void);
307 int cpu_ppc_exec(CPUPPCState *s); 277 int cpu_ppc_exec(CPUPPCState *s);
308 void cpu_ppc_close(CPUPPCState *s); 278 void cpu_ppc_close(CPUPPCState *s);
309 void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags); 279 void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags);
  280 +void PPC_init_hw (CPUPPCState *env, uint32_t mem_size,
  281 + uint32_t kernel_addr, uint32_t kernel_size,
  282 + uint32_t stack_addr, int boot_device);
310 283
311 -/* Exeptions */ 284 +/* Memory access type :
  285 + * may be needed for precise access rights control and precise exceptions.
  286 + */
312 enum { 287 enum {
313 - EXCP_NONE = 0x00, 288 + /* 1 bit to define user level / supervisor access */
  289 + ACCESS_USER = 0x00,
  290 + ACCESS_SUPER = 0x01,
  291 + /* Type of instruction that generated the access */
  292 + ACCESS_CODE = 0x10, /* Code fetch access */
  293 + ACCESS_INT = 0x20, /* Integer load/store access */
  294 + ACCESS_FLOAT = 0x30, /* floating point load/store access */
  295 + ACCESS_RES = 0x40, /* load/store with reservation */
  296 + ACCESS_EXT = 0x50, /* external access */
  297 + ACCESS_CACHE = 0x60, /* Cache manipulation */
  298 +};
  299 +
  300 +/*****************************************************************************/
  301 +/* Exceptions */
  302 +enum {
  303 + EXCP_NONE = -1,
314 /* PPC hardware exceptions : exception vector / 0x100 */ 304 /* PPC hardware exceptions : exception vector / 0x100 */
315 EXCP_RESET = 0x01, /* System reset */ 305 EXCP_RESET = 0x01, /* System reset */
316 EXCP_MACHINE_CHECK = 0x02, /* Machine check exception */ 306 EXCP_MACHINE_CHECK = 0x02, /* Machine check exception */
@@ -326,55 +316,80 @@ enum { @@ -326,55 +316,80 @@ enum {
326 EXCP_SYSCALL = 0x0C, /* System call */ 316 EXCP_SYSCALL = 0x0C, /* System call */
327 EXCP_TRACE = 0x0D, /* Trace exception (optional) */ 317 EXCP_TRACE = 0x0D, /* Trace exception (optional) */
328 EXCP_FP_ASSIST = 0x0E, /* Floating-point assist (optional) */ 318 EXCP_FP_ASSIST = 0x0E, /* Floating-point assist (optional) */
329 -#if 0  
330 - /* Exeption subtypes for EXCP_DSI */  
331 - EXCP_DSI_TRANSLATE = 0x10301, /* Data address can't be translated */  
332 - EXCP_DSI_NOTSUP = 0x10302, /* Access type not supported */  
333 - EXCP_DSI_PROT = 0x10303, /* Memory protection violation */  
334 - EXCP_DSI_EXTERNAL = 0x10304, /* External access disabled */  
335 - EXCP_DSI_DABR = 0x10305, /* Data address breakpoint */  
336 - /* Exeption subtypes for EXCP_ISI */  
337 - EXCP_ISI_TRANSLATE = 0x10401, /* Code address can't be translated */  
338 - EXCP_ISI_NOTSUP = 0x10402, /* Access type not supported */  
339 - EXCP_ISI_PROT = 0x10403, /* Memory protection violation */  
340 - EXCP_ISI_GUARD = 0x10404, /* Fetch into guarded memory */  
341 - /* Exeption subtypes for EXCP_ALIGN */  
342 - EXCP_ALIGN_FP = 0x10601, /* FP alignment exception */  
343 - EXCP_ALIGN_LST = 0x10602, /* Unaligned memory load/store */  
344 - EXCP_ALIGN_LE = 0x10603, /* Unaligned little-endian access */  
345 - EXCP_ALIGN_PROT = 0x10604, /* Access cross protection boundary */  
346 - EXCP_ALIGN_BAT = 0x10605, /* Access cross a BAT/seg boundary */  
347 - EXCP_ALIGN_CACHE = 0x10606, /* Impossible dcbz access */  
348 - /* Exeption subtypes for EXCP_PROGRAM */ 319 + /* MPC740/745/750 & IBM 750 */
  320 + EXCP_PERF = 0x0F, /* Performance monitor */
  321 + EXCP_IABR = 0x13, /* Instruction address breakpoint */
  322 + EXCP_SMI = 0x14, /* System management interrupt */
  323 + EXCP_THRM = 0x15, /* Thermal management interrupt */
  324 + /* MPC755 */
  325 + EXCP_TLBMISS = 0x10, /* Instruction TLB miss */
  326 + EXCP_TLBMISS_DL = 0x11, /* Data TLB miss for load */
  327 + EXCP_TLBMISS_DS = 0x12, /* Data TLB miss for store */
  328 + EXCP_PPC_MAX = 0x16,
  329 + /* Qemu exception */
  330 + EXCP_OFCALL = 0x20, /* Call open-firmware emulator */
  331 + EXCP_RTASCALL = 0x21, /* Call RTAS emulator */
  332 + /* Special cases where we want to stop translation */
  333 + EXCP_MTMSR = 0x104, /* mtmsr instruction: */
  334 + /* may change privilege level */
  335 + EXCP_BRANCH = 0x108, /* branch instruction */
  336 + EXCP_RFI = 0x10C, /* return from interrupt */
  337 + EXCP_SYSCALL_USER = 0x110, /* System call in user mode only */
  338 +};
  339 +/* Error codes */
  340 +enum {
  341 + /* Exception subtypes for EXCP_DSI */
  342 + EXCP_DSI_TRANSLATE = 0x01, /* Data address can't be translated */
  343 + EXCP_DSI_NOTSUP = 0x02, /* Access type not supported */
  344 + EXCP_DSI_PROT = 0x03, /* Memory protection violation */
  345 + EXCP_DSI_EXTERNAL = 0x04, /* External access disabled */
  346 + EXCP_DSI_DABR = 0x05, /* Data address breakpoint */
  347 + /* flags for EXCP_DSI */
  348 + EXCP_DSI_DIRECT = 0x10,
  349 + EXCP_DSI_STORE = 0x20,
  350 + EXCP_ECXW = 0x40,
  351 + /* Exception subtypes for EXCP_ISI */
  352 + EXCP_ISI_TRANSLATE = 0x01, /* Code address can't be translated */
  353 + EXCP_ISI_NOEXEC = 0x02, /* Try to fetch from a data segment */
  354 + EXCP_ISI_GUARD = 0x03, /* Fetch from guarded memory */
  355 + EXCP_ISI_PROT = 0x04, /* Memory protection violation */
  356 + /* Exception subtypes for EXCP_ALIGN */
  357 + EXCP_ALIGN_FP = 0x01, /* FP alignment exception */
  358 + EXCP_ALIGN_LST = 0x02, /* Unaligned mult/extern load/store */
  359 + EXCP_ALIGN_LE = 0x03, /* Multiple little-endian access */
  360 + EXCP_ALIGN_PROT = 0x04, /* Access cross protection boundary */
  361 + EXCP_ALIGN_BAT = 0x05, /* Access cross a BAT/seg boundary */
  362 + EXCP_ALIGN_CACHE = 0x06, /* Impossible dcbz access */
  363 + /* Exception subtypes for EXCP_PROGRAM */
349 /* FP exceptions */ 364 /* FP exceptions */
350 - EXCP_FP_OX = 0x10701, /* FP overflow */  
351 - EXCP_FP_UX = 0x10702, /* FP underflow */  
352 - EXCP_FP_ZX = 0x10703, /* FP divide by zero */  
353 - EXCP_FP_XX = 0x10704, /* FP inexact */  
354 - EXCP_FP_VXNAN = 0x10705, /* FP invalid SNaN op */  
355 - EXCP_FP_VXISI = 0x10706, /* FP invalid infinite substraction */  
356 - EXCP_FP_VXIDI = 0x10707, /* FP invalid infinite divide */  
357 - EXCP_FP_VXZDZ = 0x10708, /* FP invalid zero divide */  
358 - EXCP_FP_VXIMZ = 0x10709, /* FP invalid infinite * zero */  
359 - EXCP_FP_VXVC = 0x1070A, /* FP invalid compare */  
360 - EXCP_FP_VXSOFT = 0x1070B, /* FP invalid operation */  
361 - EXCP_FP_VXSQRT = 0x1070C, /* FP invalid square root */  
362 - EXCP_FP_VXCVI = 0x1070D, /* FP invalid integer conversion */ 365 + EXCP_FP = 0x10,
  366 + EXCP_FP_OX = 0x01, /* FP overflow */
  367 + EXCP_FP_UX = 0x02, /* FP underflow */
  368 + EXCP_FP_ZX = 0x03, /* FP divide by zero */
  369 + EXCP_FP_XX = 0x04, /* FP inexact */
  370 + EXCP_FP_VXNAN = 0x05, /* FP invalid SNaN op */
  371 + EXCP_FP_VXISI = 0x06, /* FP invalid infinite substraction */
  372 + EXCP_FP_VXIDI = 0x07, /* FP invalid infinite divide */
  373 + EXCP_FP_VXZDZ = 0x08, /* FP invalid zero divide */
  374 + EXCP_FP_VXIMZ = 0x09, /* FP invalid infinite * zero */
  375 + EXCP_FP_VXVC = 0x0A, /* FP invalid compare */
  376 + EXCP_FP_VXSOFT = 0x0B, /* FP invalid operation */
  377 + EXCP_FP_VXSQRT = 0x0C, /* FP invalid square root */
  378 + EXCP_FP_VXCVI = 0x0D, /* FP invalid integer conversion */
363 /* Invalid instruction */ 379 /* Invalid instruction */
364 - EXCP_INVAL_INVAL = 0x10711, /* Invalid instruction */  
365 - EXCP_INVAL_LSWX = 0x10712, /* Invalid lswx instruction */  
366 - EXCP_INVAL_SPR = 0x10713, /* Invalid SPR access */  
367 - EXCP_INVAL_FP = 0x10714, /* Unimplemented mandatory fp instr */  
368 -#endif  
369 - EXCP_INVAL = 0x70, /* Invalid instruction */ 380 + EXCP_INVAL = 0x20,
  381 + EXCP_INVAL_INVAL = 0x01, /* Invalid instruction */
  382 + EXCP_INVAL_LSWX = 0x02, /* Invalid lswx instruction */
  383 + EXCP_INVAL_SPR = 0x03, /* Invalid SPR access */
  384 + EXCP_INVAL_FP = 0x04, /* Unimplemented mandatory fp instr */
370 /* Privileged instruction */ 385 /* Privileged instruction */
371 - EXCP_PRIV = 0x71, /* Privileged instruction */ 386 + EXCP_PRIV = 0x30,
  387 + EXCP_PRIV_OPC = 0x01,
  388 + EXCP_PRIV_REG = 0x02,
372 /* Trap */ 389 /* Trap */
373 - EXCP_TRAP = 0x72, /* Trap */  
374 - /* Special cases where we want to stop translation */  
375 - EXCP_MTMSR = 0x103, /* mtmsr instruction: */  
376 - /* may change privilege level */  
377 - EXCP_BRANCH = 0x104, /* branch instruction */ 390 + EXCP_TRAP = 0x40,
378 }; 391 };
379 392
  393 +/*****************************************************************************/
  394 +
380 #endif /* !defined (__CPU_PPC_H__) */ 395 #endif /* !defined (__CPU_PPC_H__) */
target-ppc/exec.h
@@ -41,126 +41,119 @@ register uint32_t T2 asm(AREG3); @@ -41,126 +41,119 @@ register uint32_t T2 asm(AREG3);
41 #include "cpu.h" 41 #include "cpu.h"
42 #include "exec-all.h" 42 #include "exec-all.h"
43 43
44 -static inline uint8_t ld8 (uint32_t EA) 44 +static inline uint32_t rotl (uint32_t i, int n)
45 { 45 {
46 - return *((uint8_t *)EA); 46 + return ((i << n) | (i >> (32 - n)));
47 } 47 }
48 48
49 -static inline uint16_t ld16 (uint32_t EA)  
50 -{  
51 - return __be16_to_cpu(*((uint16_t *)EA));  
52 -} 49 +/* XXX: move that to a generic header */
  50 +#if !defined(CONFIG_USER_ONLY)
53 51
54 -static inline uint16_t ld16r (uint32_t EA)  
55 -{  
56 - return __le16_to_cpu(*((uint16_t *)EA));  
57 -} 52 +#define ldul_user ldl_user
  53 +#define ldul_kernel ldl_kernel
58 54
59 -static inline uint32_t ld32 (uint32_t EA)  
60 -{  
61 - return __be32_to_cpu(*((uint32_t *)EA));  
62 -}  
63 -  
64 -static inline uint32_t ld32r (uint32_t EA)  
65 -{  
66 - return __le32_to_cpu(*((uint32_t *)EA));  
67 -} 55 +#define ACCESS_TYPE 0
  56 +#define MEMSUFFIX _kernel
  57 +#define DATA_SIZE 1
  58 +#include "softmmu_header.h"
68 59
69 -static inline uint64_t ld64 (uint32_t EA)  
70 -{  
71 - return __be64_to_cpu(*((uint64_t *)EA));  
72 -} 60 +#define DATA_SIZE 2
  61 +#include "softmmu_header.h"
73 62
74 -static inline uint64_t ld64r (uint32_t EA)  
75 -{  
76 - return __le64_to_cpu(*((uint64_t *)EA));  
77 -} 63 +#define DATA_SIZE 4
  64 +#include "softmmu_header.h"
78 65
79 -static inline void st8 (uint32_t EA, uint8_t data)  
80 -{  
81 - *((uint8_t *)EA) = data;  
82 -} 66 +#define DATA_SIZE 8
  67 +#include "softmmu_header.h"
  68 +#undef ACCESS_TYPE
  69 +#undef MEMSUFFIX
83 70
84 -static inline void st16 (uint32_t EA, uint16_t data)  
85 -{  
86 - *((uint16_t *)EA) = __cpu_to_be16(data);  
87 -} 71 +#define ACCESS_TYPE 1
  72 +#define MEMSUFFIX _user
  73 +#define DATA_SIZE 1
  74 +#include "softmmu_header.h"
88 75
89 -static inline void st16r (uint32_t EA, uint16_t data)  
90 -{  
91 - *((uint16_t *)EA) = __cpu_to_le16(data);  
92 -} 76 +#define DATA_SIZE 2
  77 +#include "softmmu_header.h"
93 78
94 -static inline void st32 (uint32_t EA, uint32_t data)  
95 -{  
96 - *((uint32_t *)EA) = __cpu_to_be32(data);  
97 -} 79 +#define DATA_SIZE 4
  80 +#include "softmmu_header.h"
98 81
99 -static inline void st32r (uint32_t EA, uint32_t data)  
100 -{  
101 - *((uint32_t *)EA) = __cpu_to_le32(data);  
102 -} 82 +#define DATA_SIZE 8
  83 +#include "softmmu_header.h"
  84 +#undef ACCESS_TYPE
  85 +#undef MEMSUFFIX
103 86
104 -static inline void st64 (uint32_t EA, uint64_t data)  
105 -{  
106 - *((uint64_t *)EA) = __cpu_to_be64(data);  
107 -} 87 +/* these access are slower, they must be as rare as possible */
  88 +#define ACCESS_TYPE 2
  89 +#define MEMSUFFIX _data
  90 +#define DATA_SIZE 1
  91 +#include "softmmu_header.h"
108 92
109 -static inline void st64r (uint32_t EA, uint64_t data)  
110 -{  
111 - *((uint64_t *)EA) = __cpu_to_le64(data);  
112 -} 93 +#define DATA_SIZE 2
  94 +#include "softmmu_header.h"
113 95
114 -static inline void set_CRn(int n, uint8_t value)  
115 -{  
116 - env->crf[n] = value;  
117 -} 96 +#define DATA_SIZE 4
  97 +#include "softmmu_header.h"
118 98
119 -static inline void set_carry (void)  
120 -{  
121 - xer_ca = 1;  
122 -} 99 +#define DATA_SIZE 8
  100 +#include "softmmu_header.h"
  101 +#undef ACCESS_TYPE
  102 +#undef MEMSUFFIX
123 103
124 -static inline void reset_carry (void)  
125 -{  
126 - xer_ca = 0;  
127 -} 104 +#define ldub(p) ldub_data(p)
  105 +#define ldsb(p) ldsb_data(p)
  106 +#define lduw(p) lduw_data(p)
  107 +#define ldsw(p) ldsw_data(p)
  108 +#define ldl(p) ldl_data(p)
  109 +#define ldq(p) ldq_data(p)
128 110
129 -static inline void set_overflow (void)  
130 -{  
131 - xer_so = 1;  
132 - xer_ov = 1;  
133 -} 111 +#define stb(p, v) stb_data(p, v)
  112 +#define stw(p, v) stw_data(p, v)
  113 +#define stl(p, v) stl_data(p, v)
  114 +#define stq(p, v) stq_data(p, v)
134 115
135 -static inline void reset_overflow (void)  
136 -{  
137 - xer_ov = 0;  
138 -} 116 +#endif /* !defined(CONFIG_USER_ONLY) */
139 117
140 -static inline uint32_t rotl (uint32_t i, int n)  
141 -{  
142 - return ((i << n) | (i >> (32 - n)));  
143 -} 118 +int check_exception_state (CPUState *env);
144 119
145 -void raise_exception (int exception_index);  
146 -void raise_exception_err (int exception_index, int error_code); 120 +void do_queue_exception_err (uint32_t exception, int error_code);
  121 +void do_queue_exception (uint32_t exception);
  122 +void do_process_exceptions (void);
  123 +void do_check_exception_state (void);
147 124
148 -uint32_t do_load_cr (void);  
149 -void do_store_cr (uint32_t crn, uint32_t value);  
150 -uint32_t do_load_xer (void);  
151 -void do_store_xer (uint32_t value);  
152 -uint32_t do_load_msr (void);  
153 -void do_store_msr (uint32_t msr_value); 125 +void do_load_cr (void);
  126 +void do_store_cr (uint32_t mask);
  127 +void do_load_xer (void);
  128 +void do_store_xer (void);
  129 +void do_load_msr (void);
  130 +void do_store_msr (void);
154 void do_load_fpscr (void); 131 void do_load_fpscr (void);
155 void do_store_fpscr (uint32_t mask); 132 void do_store_fpscr (uint32_t mask);
156 133
157 -int32_t do_sraw(int32_t Ta, uint32_t Tb);  
158 -void do_lmw (int reg, uint32_t src);  
159 -void do_stmw (int reg, uint32_t dest);  
160 -void do_lsw (uint32_t reg, int count, uint32_t src);  
161 -void do_stsw (uint32_t reg, int count, uint32_t dest); 134 +void do_sraw(void);
  135 +
  136 +void do_fctiw (void);
  137 +void do_fctiwz (void);
  138 +void do_fsqrt (void);
  139 +void do_fsqrts (void);
  140 +void do_fres (void);
  141 +void do_fsqrte (void);
  142 +void do_fsel (void);
  143 +void do_fcmpu (void);
  144 +void do_fcmpo (void);
  145 +void do_fabs (void);
  146 +void do_fnabs (void);
162 147
163 -void do_dcbz (void);  
164 void do_icbi (void); 148 void do_icbi (void);
  149 +void do_tlbia (void);
  150 +void do_tlbie (void);
  151 +
  152 +void dump_rfi (void);
  153 +void dump_store_sr (int srnum);
  154 +void dump_store_ibat (int ul, int nr);
  155 +void dump_store_dbat (int ul, int nr);
  156 +void dump_store_tb (int ul);
  157 +void dump_update_tb(uint32_t param);
165 158
166 #endif /* !defined (__PPC_H__) */ 159 #endif /* !defined (__PPC_H__) */
target-ppc/helper.c
@@ -17,56 +17,642 @@ @@ -17,56 +17,642 @@
17 * License along with this library; if not, write to the Free Software 17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 19 */
  20 +#include <sys/mman.h>
  21 +
20 #include "exec.h" 22 #include "exec.h"
  23 +#if defined (USE_OPEN_FIRMWARE)
  24 +#include "of.h"
  25 +#endif
  26 +
  27 +//#define DEBUG_MMU
  28 +//#define DEBUG_BATS
  29 +//#define DEBUG_EXCEPTIONS
  30 +
  31 +extern FILE *logfile, *stderr;
  32 +void exit (int);
  33 +void abort (void);
21 34
22 -extern FILE *logfile; 35 +int phys_ram_size;
  36 +int phys_ram_fd;
  37 +uint8_t *phys_ram_base;
23 38
24 void cpu_loop_exit(void) 39 void cpu_loop_exit(void)
25 { 40 {
26 longjmp(env->jmp_env, 1); 41 longjmp(env->jmp_env, 1);
27 } 42 }
28 43
29 -/* shortcuts to generate exceptions */  
30 -void raise_exception_err (int exception_index, int error_code) 44 +void do_process_exceptions (void)
31 { 45 {
32 - env->exception_index = exception_index;  
33 - env->error_code = error_code;  
34 -  
35 cpu_loop_exit(); 46 cpu_loop_exit();
36 } 47 }
37 48
38 -void raise_exception (int exception_index) 49 +int check_exception_state (CPUState *env)
39 { 50 {
40 - env->exception_index = exception_index;  
41 - env->error_code = 0; 51 + int i;
42 52
43 - cpu_loop_exit(); 53 + /* Process PPC exceptions */
  54 + for (i = 1; i < EXCP_PPC_MAX; i++) {
  55 + if (env->exceptions & (1 << i)) {
  56 + switch (i) {
  57 + case EXCP_EXTERNAL:
  58 + case EXCP_DECR:
  59 + if (msr_ee == 0)
  60 + return 0;
  61 + break;
  62 + case EXCP_PROGRAM:
  63 + if (env->errors[EXCP_PROGRAM] == EXCP_FP &&
  64 + msr_fe0 == 0 && msr_fe1 == 0)
  65 + return 0;
  66 + break;
  67 + default:
  68 + break;
  69 + }
  70 + env->exception_index = i;
  71 + env->error_code = env->errors[i];
  72 + return 1;
  73 + }
  74 + }
  75 +
  76 + return 0;
  77 +}
  78 +
  79 +/*****************************************************************************/
  80 +/* PPC MMU emulation */
  81 +/* Perform BAT hit & translation */
  82 +static int get_bat (CPUState *env, uint32_t *real, int *prot,
  83 + uint32_t virtual, int rw, int type)
  84 +{
  85 + uint32_t *BATlt, *BATut, *BATu, *BATl;
  86 + uint32_t base, BEPIl, BEPIu, bl;
  87 + int i;
  88 + int ret = -1;
  89 +
  90 +#if defined (DEBUG_BATS)
  91 + if (loglevel > 0) {
  92 + fprintf(logfile, "%s: %cBAT v 0x%08x\n", __func__,
  93 + type == ACCESS_CODE ? 'I' : 'D', virtual);
  94 + }
  95 + printf("%s: %cBAT v 0x%08x\n", __func__,
  96 + type == ACCESS_CODE ? 'I' : 'D', virtual);
  97 +#endif
  98 + switch (type) {
  99 + case ACCESS_CODE:
  100 + BATlt = env->IBAT[1];
  101 + BATut = env->IBAT[0];
  102 + break;
  103 + default:
  104 + BATlt = env->DBAT[1];
  105 + BATut = env->DBAT[0];
  106 + break;
  107 + }
  108 +#if defined (DEBUG_BATS)
  109 + if (loglevel > 0) {
  110 + fprintf(logfile, "%s...: %cBAT v 0x%08x\n", __func__,
  111 + type == ACCESS_CODE ? 'I' : 'D', virtual);
  112 + }
  113 + printf("%s...: %cBAT v 0x%08x\n", __func__,
  114 + type == ACCESS_CODE ? 'I' : 'D', virtual);
  115 +#endif
  116 + base = virtual & 0xFFFC0000;
  117 + for (i = 0; i < 4; i++) {
  118 + BATu = &BATut[i];
  119 + BATl = &BATlt[i];
  120 + BEPIu = *BATu & 0xF0000000;
  121 + BEPIl = *BATu & 0x0FFE0000;
  122 + bl = (*BATu & 0x00001FFC) << 15;
  123 +#if defined (DEBUG_BATS)
  124 + if (loglevel > 0) {
  125 + fprintf(logfile, "%s: %cBAT%d v 0x%08x BATu 0x%08x BATl 0x%08x\n",
  126 + __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
  127 + *BATu, *BATl);
  128 + } else {
  129 + printf("%s: %cBAT%d v 0x%08x BATu 0x%08x BATl 0x%08x\n",
  130 + __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
  131 + *BATu, *BATl);
  132 + }
  133 +#endif
  134 + if ((virtual & 0xF0000000) == BEPIu &&
  135 + ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
  136 + /* BAT matches */
  137 + if ((msr_pr == 0 && (*BATu & 0x00000002)) ||
  138 + (msr_pr == 1 && (*BATu & 0x00000001))) {
  139 + /* Get physical address */
  140 + *real = (*BATl & 0xF0000000) |
  141 + ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
  142 + (virtual & 0x0001FFFF);
  143 + if (*BATl & 0x00000001)
  144 + *prot = PROT_READ;
  145 + if (*BATl & 0x00000002)
  146 + *prot = PROT_WRITE | PROT_READ;
  147 +#if defined (DEBUG_BATS)
  148 + if (loglevel > 0) {
  149 + fprintf(logfile, "BAT %d match: r 0x%08x prot=%c%c\n",
  150 + i, *real, *prot & PROT_READ ? 'R' : '-',
  151 + *prot & PROT_WRITE ? 'W' : '-');
  152 + } else {
  153 + printf("BAT %d match: 0x%08x => 0x%08x prot=%c%c\n",
  154 + i, virtual, *real, *prot & PROT_READ ? 'R' : '-',
  155 + *prot & PROT_WRITE ? 'W' : '-');
  156 + }
  157 +#endif
  158 + ret = 0;
  159 + break;
  160 + }
  161 + }
  162 + }
  163 + if (ret < 0) {
  164 +#if defined (DEBUG_BATS)
  165 + printf("no BAT match for 0x%08x:\n", virtual);
  166 + for (i = 0; i < 4; i++) {
  167 + BATu = &BATut[i];
  168 + BATl = &BATlt[i];
  169 + BEPIu = *BATu & 0xF0000000;
  170 + BEPIl = *BATu & 0x0FFE0000;
  171 + bl = (*BATu & 0x00001FFC) << 15;
  172 + printf("%s: %cBAT%d v 0x%08x BATu 0x%08x BATl 0x%08x \n\t"
  173 + "0x%08x 0x%08x 0x%08x\n",
  174 + __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
  175 + *BATu, *BATl, BEPIu, BEPIl, bl);
  176 + }
  177 +#endif
  178 + env->spr[DAR] = virtual;
  179 + }
  180 + /* No hit */
  181 + return ret;
  182 +}
  183 +
  184 +/* PTE table lookup */
  185 +static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va,
  186 + int h, int key, int rw)
  187 +{
  188 + uint32_t pte0, pte1, keep = 0;
  189 + int i, good = -1, store = 0;
  190 + int ret = -1; /* No entry found */
  191 +
  192 + for (i = 0; i < 8; i++) {
  193 + pte0 = ldl_raw((void *)((uint32_t)phys_ram_base + base + (i * 8)));
  194 + pte1 = ldl_raw((void *)((uint32_t)phys_ram_base + base + (i * 8) + 4));
  195 +#if defined (DEBUG_MMU)
  196 + printf("Load pte from 0x%08x => 0x%08x 0x%08x\n", base + (i * 8),
  197 + pte0, pte1);
  198 +#endif
  199 + /* Check validity and table match */
  200 + if (pte0 & 0x80000000 && (h == ((pte0 >> 6) & 1))) {
  201 +#if defined (DEBUG_MMU)
  202 + printf("PTE is valid and table matches... compare 0x%08x:%08x\n",
  203 + pte0 & 0x7FFFFFBF, va);
  204 +#endif
  205 + /* Check vsid & api */
  206 + if ((pte0 & 0x7FFFFFBF) == va) {
  207 +#if defined (DEBUG_MMU)
  208 + printf("PTE match !\n");
  209 +#endif
  210 + if (good == -1) {
  211 + good = i;
  212 + keep = pte1;
  213 + } else {
  214 + /* All matches should have equal RPN, WIMG & PP */
  215 + if ((keep & 0xFFFFF07B) != (pte1 & 0xFFFFF07B)) {
  216 + printf("Bad RPN/WIMG/PP\n");
  217 + return -1;
  218 + }
  219 + }
  220 + /* Check access rights */
  221 + if (key == 0) {
  222 + *prot = PROT_READ;
  223 + if ((pte1 & 0x00000003) != 0x3)
  224 + *prot |= PROT_WRITE;
  225 + } else {
  226 + switch (pte1 & 0x00000003) {
  227 + case 0x0:
  228 + *prot = 0;
  229 + break;
  230 + case 0x1:
  231 + case 0x3:
  232 + *prot = PROT_READ;
  233 + break;
  234 + case 0x2:
  235 + *prot = PROT_READ | PROT_WRITE;
  236 + break;
  237 + }
  238 + }
  239 + if ((rw == 0 && *prot != 0) ||
  240 + (rw == 1 && (*prot & PROT_WRITE))) {
  241 +#if defined (DEBUG_MMU)
  242 + printf("PTE access granted !\n");
  243 +#endif
  244 + good = i;
  245 + keep = pte1;
  246 + ret = 0;
  247 + } else if (ret == -1) {
  248 + ret = -2; /* Access right violation */
  249 +#if defined (DEBUG_MMU)
  250 + printf("PTE access rejected\n");
  251 +#endif
  252 + }
  253 + }
  254 + }
  255 + }
  256 + if (good != -1) {
  257 + *RPN = keep & 0xFFFFF000;
  258 +#if defined (DEBUG_MMU)
  259 + printf("found PTE at addr 0x%08x prot=0x%01x ret=%d\n",
  260 + *RPN, *prot, ret);
  261 +#endif
  262 + /* Update page flags */
  263 + if (!(keep & 0x00000100)) {
  264 + keep |= 0x00000100;
  265 + store = 1;
  266 + }
  267 + if (rw) {
  268 + if (!(keep & 0x00000080)) {
  269 + keep |= 0x00000080;
  270 + store = 1;
  271 + }
  272 + }
  273 + if (store)
  274 + stl_raw((void *)(base + (good * 2) + 1), keep);
  275 + }
  276 +
  277 + return ret;
44 } 278 }
45 279
46 -/* Helpers for "fat" micro operations */  
47 -uint32_t do_load_cr (void) 280 +static inline uint32_t get_pgaddr (uint32_t sdr1, uint32_t hash, uint32_t mask)
48 { 281 {
49 - return (env->crf[0] << 28) |  
50 - (env->crf[1] << 24) |  
51 - (env->crf[2] << 20) |  
52 - (env->crf[3] << 16) |  
53 - (env->crf[4] << 12) |  
54 - (env->crf[5] << 8) |  
55 - (env->crf[6] << 4) |  
56 - (env->crf[7] << 0); 282 + return (sdr1 & 0xFFFF0000) | (hash & mask);
57 } 283 }
58 284
59 -void do_store_cr (uint32_t crn, uint32_t value) 285 +/* Perform segment based translation */
  286 +static int get_segment (CPUState *env, uint32_t *real, int *prot,
  287 + uint32_t virtual, int rw, int type)
60 { 288 {
61 - int i, sh; 289 + uint32_t pg_addr, sdr, ptem, vsid, pgidx;
  290 + uint32_t hash, mask;
  291 + uint32_t sr;
  292 + int key;
  293 + int ret = -1, ret2;
62 294
63 - for (i = 0, sh = 7; i < 8; i++, sh --) {  
64 - if (crn & (1 << sh))  
65 - env->crf[i] = (value >> (sh * 4)) & 0xF; 295 + sr = env->sr[virtual >> 28];
  296 +#if defined (DEBUG_MMU)
  297 + printf("Check segment v=0x%08x %d 0x%08x nip=0x%08x lr=0x%08x ir=%d dr=%d "
  298 + "pr=%d t=%d\n", virtual, virtual >> 28, sr, env->nip,
  299 + env->lr, msr_ir, msr_dr, msr_pr, type);
  300 +#endif
  301 + key = ((sr & 0x20000000) && msr_pr == 1) ||
  302 + ((sr & 0x40000000) && msr_pr == 0) ? 1 : 0;
  303 + if ((sr & 0x80000000) == 0) {
  304 +#if defined (DEBUG_MMU)
  305 + printf("pte segment: key=%d n=0x%08x\n", key, sr & 0x10000000);
  306 +#endif
  307 + /* Check if instruction fetch is allowed, if needed */
  308 + if (type != ACCESS_CODE || (sr & 0x10000000) == 0) {
  309 + /* Page address translation */
  310 + vsid = sr & 0x00FFFFFF;
  311 + pgidx = (virtual >> 12) & 0xFFFF;
  312 + sdr = env->spr[SDR1];
  313 + hash = ((vsid ^ pgidx) & 0x07FFFF) << 6;
  314 + mask = ((sdr & 0x000001FF) << 16) | 0xFFC0;
  315 + pg_addr = get_pgaddr(sdr, hash, mask);
  316 + ptem = (vsid << 7) | (pgidx >> 10);
  317 +#if defined (DEBUG_MMU)
  318 + printf("0 sdr1=0x%08x vsid=0x%06x api=0x%04x hash=0x%07x "
  319 + "pg_addr=0x%08x\n", sdr, vsid, pgidx, hash, pg_addr);
  320 +#endif
  321 + /* Primary table lookup */
  322 + ret = find_pte(real, prot, pg_addr, ptem, 0, key, rw);
  323 + if (ret < 0) {
  324 + /* Secondary table lookup */
  325 + hash = (~hash) & 0x01FFFFC0;
  326 + pg_addr = get_pgaddr(sdr, hash, mask);
  327 +#if defined (DEBUG_MMU)
  328 + printf("1 sdr1=0x%08x vsid=0x%06x api=0x%04x hash=0x%05x "
  329 + "pg_addr=0x%08x\n", sdr, vsid, pgidx, hash, pg_addr);
  330 +#endif
  331 + ret2 = find_pte(real, prot, pg_addr, ptem, 1, key, rw);
  332 + if (ret2 != -1)
  333 + ret = ret2;
  334 + }
  335 + if (ret != -1)
  336 + *real |= (virtual & 0x00000FFF);
  337 + if (ret == -2 && type == ACCESS_CODE && (sr & 0x10000000))
  338 + ret = -3;
  339 + } else {
  340 +#if defined (DEBUG_MMU)
  341 + printf("No access allowed\n");
  342 +#endif
  343 + }
  344 + } else {
  345 +#if defined (DEBUG_MMU)
  346 + printf("direct store...\n");
  347 +#endif
  348 + /* Direct-store segment : absolutely *BUGGY* for now */
  349 + switch (type) {
  350 + case ACCESS_INT:
  351 + /* Integer load/store : only access allowed */
  352 + break;
  353 + case ACCESS_CODE:
  354 + /* No code fetch is allowed in direct-store areas */
  355 + return -4;
  356 + case ACCESS_FLOAT:
  357 + /* Floating point load/store */
  358 + return -4;
  359 + case ACCESS_RES:
  360 + /* lwarx, ldarx or srwcx. */
  361 + return -4;
  362 + case ACCESS_CACHE:
  363 + /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
  364 + /* Should make the instruction do no-op.
  365 + * As it already do no-op, it's quite easy :-)
  366 + */
  367 + *real = virtual;
  368 + return 0;
  369 + case ACCESS_EXT:
  370 + /* eciwx or ecowx */
  371 + return -4;
  372 + default:
  373 + if (logfile) {
  374 + fprintf(logfile, "ERROR: instruction should not need "
  375 + "address translation\n");
  376 + }
  377 + printf("ERROR: instruction should not need "
  378 + "address translation\n");
  379 + return -4;
  380 + }
  381 + if ((rw == 1 || key != 1) && (rw == 0 || key != 0)) {
  382 + *real = virtual;
  383 + ret = 2;
  384 + } else {
  385 + ret = -2;
  386 + }
66 } 387 }
  388 +
  389 + return ret;
67 } 390 }
68 391
69 -uint32_t do_load_xer (void) 392 +int get_physical_address (CPUState *env, uint32_t *physical, int *prot,
  393 + uint32_t address, int rw, int access_type)
  394 +{
  395 + int ret;
  396 +
  397 + if (loglevel > 0) {
  398 + fprintf(logfile, "%s\n", __func__);
  399 + }
  400 + if ((access_type == ACCESS_CODE && msr_ir == 0) || msr_dr == 0) {
  401 + /* No address translation */
  402 + *physical = address;
  403 + *prot = PROT_READ | PROT_WRITE;
  404 + ret = 0;
  405 + } else {
  406 + /* Try to find a BAT */
  407 + ret = get_bat(env, physical, prot, address, rw, access_type);
  408 + if (ret < 0) {
  409 + /* We didn't match any BAT entry */
  410 + ret = get_segment(env, physical, prot, address, rw, access_type);
  411 + }
  412 + }
  413 +
  414 + return ret;
  415 +}
  416 +
  417 +
  418 +#if !defined(CONFIG_USER_ONLY)
  419 +
  420 +#define MMUSUFFIX _mmu
  421 +#define GETPC() (__builtin_return_address(0))
  422 +
  423 +#define SHIFT 0
  424 +#include "softmmu_template.h"
  425 +
  426 +#define SHIFT 1
  427 +#include "softmmu_template.h"
  428 +
  429 +#define SHIFT 2
  430 +#include "softmmu_template.h"
  431 +
  432 +#define SHIFT 3
  433 +#include "softmmu_template.h"
  434 +
  435 +/* try to fill the TLB and return an exception if error. If retaddr is
  436 + NULL, it means that the function was called in C code (i.e. not
  437 + from generated code or from helper.c) */
  438 +/* XXX: fix it to restore all registers */
  439 +void tlb_fill(unsigned long addr, int is_write, int flags, void *retaddr)
  440 +{
  441 + TranslationBlock *tb;
  442 + int ret, is_user;
  443 + unsigned long pc;
  444 + CPUState *saved_env;
  445 +
  446 + /* XXX: hack to restore env in all cases, even if not called from
  447 + generated code */
  448 + saved_env = env;
  449 + env = cpu_single_env;
  450 + is_user = flags & 0x01;
  451 + {
  452 + unsigned long tlb_addrr, tlb_addrw;
  453 + int index;
  454 + index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  455 + tlb_addrr = env->tlb_read[is_user][index].address;
  456 + tlb_addrw = env->tlb_write[is_user][index].address;
  457 +#if 0
  458 + printf("%s 1 %p %p idx=%d addr=0x%08lx tbl_addr=0x%08lx 0x%08lx "
  459 + "(0x%08lx 0x%08lx)\n", __func__, env,
  460 + &env->tlb_read[is_user][index], index, addr,
  461 + tlb_addrr, tlb_addrw, addr & TARGET_PAGE_MASK,
  462 + tlb_addrr & (TARGET_PAGE_MASK | TLB_INVALID_MASK));
  463 +#endif
  464 + }
  465 + ret = cpu_handle_mmu_fault(env, addr, is_write, flags, 1);
  466 + if (ret) {
  467 + if (retaddr) {
  468 + /* now we have a real cpu fault */
  469 + pc = (unsigned long)retaddr;
  470 + tb = tb_find_pc(pc);
  471 + if (tb) {
  472 + /* the PC is inside the translated code. It means that we have
  473 + a virtual CPU fault */
  474 + cpu_restore_state(tb, env, pc);
  475 + }
  476 + }
  477 + do_queue_exception_err(env->exception_index, env->error_code);
  478 + do_process_exceptions();
  479 + }
  480 + {
  481 + unsigned long tlb_addrr, tlb_addrw;
  482 + int index;
  483 + index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  484 + tlb_addrr = env->tlb_read[is_user][index].address;
  485 + tlb_addrw = env->tlb_write[is_user][index].address;
  486 +#if 0
  487 + printf("%s 2 %p %p idx=%d addr=0x%08lx tbl_addr=0x%08lx 0x%08lx "
  488 + "(0x%08lx 0x%08lx)\n", __func__, env,
  489 + &env->tlb_read[is_user][index], index, addr,
  490 + tlb_addrr, tlb_addrw, addr & TARGET_PAGE_MASK,
  491 + tlb_addrr & (TARGET_PAGE_MASK | TLB_INVALID_MASK));
  492 +#endif
  493 + }
  494 + env = saved_env;
  495 +}
  496 +
  497 +void cpu_ppc_init_mmu(CPUPPCState *env)
  498 +{
  499 + /* Nothing to do: all translation are disabled */
  500 +}
  501 +#endif
  502 +
  503 +/* Perform address translation */
  504 +int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
  505 + int flags, int is_softmmu)
  506 +{
  507 + uint32_t physical;
  508 + int prot;
  509 + int exception = 0, error_code = 0;
  510 + int is_user, access_type;
  511 + int ret = 0;
  512 +
  513 +// printf("%s 0\n", __func__);
  514 + is_user = flags & 0x01;
  515 + access_type = flags & ~0x01;
  516 + if (env->user_mode_only) {
  517 + /* user mode only emulation */
  518 + ret = -1;
  519 + goto do_fault;
  520 + }
  521 + ret = get_physical_address(env, &physical, &prot,
  522 + address, rw, access_type);
  523 + if (ret == 0) {
  524 + ret = tlb_set_page(env, address, physical, prot, is_user, is_softmmu);
  525 + } else if (ret < 0) {
  526 + do_fault:
  527 +#if defined (DEBUG_MMU)
  528 + printf("%s 5\n", __func__);
  529 + printf("nip=0x%08x LR=0x%08x CTR=0x%08x MSR=0x%08x TBL=0x%08x\n",
  530 + env->nip, env->lr, env->ctr, /*msr*/0, env->tb[0]);
  531 + {
  532 + int i;
  533 + for (i = 0; i < 32; i++) {
  534 + if ((i & 7) == 0)
  535 + printf("GPR%02d:", i);
  536 + printf(" %08x", env->gpr[i]);
  537 + if ((i & 7) == 7)
  538 + printf("\n");
  539 + }
  540 + printf("CR: 0x");
  541 + for (i = 0; i < 8; i++)
  542 + printf("%01x", env->crf[i]);
  543 + printf(" [");
  544 + for (i = 0; i < 8; i++) {
  545 + char a = '-';
  546 + if (env->crf[i] & 0x08)
  547 + a = 'L';
  548 + else if (env->crf[i] & 0x04)
  549 + a = 'G';
  550 + else if (env->crf[i] & 0x02)
  551 + a = 'E';
  552 + printf(" %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
  553 + }
  554 + printf(" ] ");
  555 + }
  556 + printf("TB: 0x%08x %08x\n", env->tb[1], env->tb[0]);
  557 + printf("SRR0 0x%08x SRR1 0x%08x\n", env->spr[SRR0], env->spr[SRR1]);
  558 +#endif
  559 + if (access_type == ACCESS_CODE) {
  560 + exception = EXCP_ISI;
  561 + switch (ret) {
  562 + case -1:
  563 + /* No matches in page tables */
  564 + error_code = EXCP_ISI_TRANSLATE;
  565 + break;
  566 + case -2:
  567 + /* Access rights violation */
  568 + error_code = EXCP_ISI_PROT;
  569 + break;
  570 + case -3:
  571 + error_code = EXCP_ISI_NOEXEC;
  572 + break;
  573 + case -4:
  574 + /* Direct store exception */
  575 + /* No code fetch is allowed in direct-store areas */
  576 + exception = EXCP_ISI;
  577 + error_code = EXCP_ISI_NOEXEC;
  578 + break;
  579 + }
  580 + } else {
  581 + exception = EXCP_DSI;
  582 + switch (ret) {
  583 + case -1:
  584 + /* No matches in page tables */
  585 + error_code = EXCP_DSI_TRANSLATE;
  586 + break;
  587 + case -2:
  588 + /* Access rights violation */
  589 + error_code = EXCP_DSI_PROT;
  590 + break;
  591 + case -4:
  592 + /* Direct store exception */
  593 + switch (access_type) {
  594 + case ACCESS_FLOAT:
  595 + /* Floating point load/store */
  596 + exception = EXCP_ALIGN;
  597 + error_code = EXCP_ALIGN_FP;
  598 + break;
  599 + case ACCESS_RES:
  600 + /* lwarx, ldarx or srwcx. */
  601 + exception = EXCP_DSI;
  602 + error_code = EXCP_DSI_NOTSUP | EXCP_DSI_DIRECT;
  603 + if (rw)
  604 + error_code |= EXCP_DSI_STORE;
  605 + break;
  606 + case ACCESS_EXT:
  607 + /* eciwx or ecowx */
  608 + exception = EXCP_DSI;
  609 + error_code = EXCP_DSI_NOTSUP | EXCP_DSI_DIRECT | EXCP_ECXW;
  610 + break;
  611 + default:
  612 + exception = EXCP_PROGRAM;
  613 + error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
  614 + break;
  615 + }
  616 + }
  617 + if (rw)
  618 + error_code |= EXCP_DSI_STORE;
  619 + /* Should find a better solution:
  620 + * this will be invalid for some exception if more than one
  621 + * exception occurs for one instruction
  622 + */
  623 + env->spr[DSISR] = 0;
  624 + if (error_code & EXCP_DSI_DIRECT) {
  625 + env->spr[DSISR] |= 0x80000000;
  626 + if (access_type == ACCESS_EXT ||
  627 + access_type == ACCESS_RES)
  628 + env->spr[DSISR] |= 0x04000000;
  629 + }
  630 + if ((error_code & 0xF) == EXCP_DSI_TRANSLATE)
  631 + env->spr[DSISR] |= 0x40000000;
  632 + if (error_code & EXCP_DSI_PROT)
  633 + env->spr[DSISR] |= 0x08000000;
  634 + if (error_code & EXCP_DSI_STORE)
  635 + env->spr[DSISR] |= 0x02000000;
  636 + if ((error_code & 0xF) == EXCP_DSI_DABR)
  637 + env->spr[DSISR] |= 0x00400000;
  638 + if (access_type == ACCESS_EXT)
  639 + env->spr[DSISR] |= 0x00100000;
  640 + }
  641 +#if 0
  642 + printf("%s: set exception to %d %02x\n",
  643 + __func__, exception, error_code);
  644 +#endif
  645 + env->exception_index = exception;
  646 + env->error_code = error_code;
  647 + /* Store fault address */
  648 + env->spr[DAR] = address;
  649 + ret = 1;
  650 + }
  651 +
  652 + return ret;
  653 +}
  654 +
  655 +uint32_t _load_xer (void)
70 { 656 {
71 return (xer_so << XER_SO) | 657 return (xer_so << XER_SO) |
72 (xer_ov << XER_OV) | 658 (xer_ov << XER_OV) |
@@ -74,7 +660,7 @@ uint32_t do_load_xer (void) @@ -74,7 +660,7 @@ uint32_t do_load_xer (void)
74 (xer_bc << XER_BC); 660 (xer_bc << XER_BC);
75 } 661 }
76 662
77 -void do_store_xer (uint32_t value) 663 +void _store_xer (uint32_t value)
78 { 664 {
79 xer_so = (value >> XER_SO) & 0x01; 665 xer_so = (value >> XER_SO) & 0x01;
80 xer_ov = (value >> XER_OV) & 0x01; 666 xer_ov = (value >> XER_OV) & 0x01;
@@ -82,7 +668,7 @@ void do_store_xer (uint32_t value) @@ -82,7 +668,7 @@ void do_store_xer (uint32_t value)
82 xer_bc = (value >> XER_BC) & 0x1f; 668 xer_bc = (value >> XER_BC) & 0x1f;
83 } 669 }
84 670
85 -uint32_t do_load_msr (void) 671 +uint32_t _load_msr (void)
86 { 672 {
87 return (msr_pow << MSR_POW) | 673 return (msr_pow << MSR_POW) |
88 (msr_ile << MSR_ILE) | 674 (msr_ile << MSR_ILE) |
@@ -101,167 +687,255 @@ uint32_t do_load_msr (void) @@ -101,167 +687,255 @@ uint32_t do_load_msr (void)
101 (msr_le << MSR_LE); 687 (msr_le << MSR_LE);
102 } 688 }
103 689
104 -void do_store_msr (uint32_t msr_value) 690 +void _store_msr (uint32_t value)
105 { 691 {
106 - msr_pow = (msr_value >> MSR_POW) & 0x03;  
107 - msr_ile = (msr_value >> MSR_ILE) & 0x01;  
108 - msr_ee = (msr_value >> MSR_EE) & 0x01;  
109 - msr_pr = (msr_value >> MSR_PR) & 0x01;  
110 - msr_fp = (msr_value >> MSR_FP) & 0x01;  
111 - msr_me = (msr_value >> MSR_ME) & 0x01;  
112 - msr_fe0 = (msr_value >> MSR_FE0) & 0x01;  
113 - msr_se = (msr_value >> MSR_SE) & 0x01;  
114 - msr_be = (msr_value >> MSR_BE) & 0x01;  
115 - msr_fe1 = (msr_value >> MSR_FE1) & 0x01;  
116 - msr_ip = (msr_value >> MSR_IP) & 0x01;  
117 - msr_ir = (msr_value >> MSR_IR) & 0x01;  
118 - msr_dr = (msr_value >> MSR_DR) & 0x01;  
119 - msr_ri = (msr_value >> MSR_RI) & 0x01;  
120 - msr_le = (msr_value >> MSR_LE) & 0x01; 692 + msr_pow = (value >> MSR_POW) & 0x03;
  693 + msr_ile = (value >> MSR_ILE) & 0x01;
  694 + msr_ee = (value >> MSR_EE) & 0x01;
  695 + msr_pr = (value >> MSR_PR) & 0x01;
  696 + msr_fp = (value >> MSR_FP) & 0x01;
  697 + msr_me = (value >> MSR_ME) & 0x01;
  698 + msr_fe0 = (value >> MSR_FE0) & 0x01;
  699 + msr_se = (value >> MSR_SE) & 0x01;
  700 + msr_be = (value >> MSR_BE) & 0x01;
  701 + msr_fe1 = (value >> MSR_FE1) & 0x01;
  702 + msr_ip = (value >> MSR_IP) & 0x01;
  703 + msr_ir = (value >> MSR_IR) & 0x01;
  704 + msr_dr = (value >> MSR_DR) & 0x01;
  705 + msr_ri = (value >> MSR_RI) & 0x01;
  706 + msr_le = (value >> MSR_LE) & 0x01;
121 } 707 }
122 708
123 -/* The 32 MSB of the target fpr are undefined. They'll be zero... */  
124 -/* Floating point operations helpers */  
125 -void do_load_fpscr (void) 709 +void do_interrupt (CPUState *env)
126 { 710 {
127 - /* The 32 MSB of the target fpr are undefined.  
128 - * They'll be zero...  
129 - */  
130 - union {  
131 - double d;  
132 - struct {  
133 - uint32_t u[2];  
134 - } s;  
135 - } u;  
136 - int i;  
137 -  
138 - u.s.u[0] = 0;  
139 - u.s.u[1] = 0;  
140 - for (i = 0; i < 8; i++)  
141 - u.s.u[1] |= env->fpscr[i] << (4 * i);  
142 - FT0 = u.d;  
143 -} 711 +#if defined (CONFIG_USER_ONLY)
  712 + env->exception_index |= 0x100;
  713 +#else
  714 + uint32_t msr;
  715 + int excp = env->exception_index;
144 716
145 -void do_store_fpscr (uint32_t mask)  
146 -{  
147 - /*  
148 - * We use only the 32 LSB of the incoming fpr  
149 - */  
150 - union {  
151 - double d;  
152 - struct {  
153 - uint32_t u[2];  
154 - } s;  
155 - } u; 717 + /* Dequeue PPC exceptions */
  718 + if (excp < EXCP_PPC_MAX)
  719 + env->exceptions &= ~(1 << excp);
  720 + msr = _load_msr();
  721 +#if defined (DEBUG_EXCEPTIONS)
  722 + if (excp != EXCP_DECR && excp == EXCP_PROGRAM && excp < EXCP_PPC_MAX)
  723 + {
  724 + if (loglevel > 0) {
  725 + fprintf(logfile, "Raise exception at 0x%08x => 0x%08x (%02x)\n",
  726 + env->nip, excp << 8, env->error_code);
  727 + } else {
  728 + printf("Raise exception at 0x%08x => 0x%08x (%02x)\n",
  729 + env->nip, excp << 8, env->error_code);
  730 + }
  731 + printf("nip=0x%08x LR=0x%08x CTR=0x%08x MSR=0x%08x DECR=0x%08x\n",
  732 + env->nip, env->lr, env->ctr, msr, env->decr);
  733 + {
156 int i; 734 int i;
157 -  
158 - u.d = FT0;  
159 - if (mask & 0x80)  
160 - env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[1] >> 28) & ~0x9);  
161 - for (i = 1; i < 7; i++) {  
162 - if (mask & (1 << (7 - i)))  
163 - env->fpscr[i] = (u.s.u[1] >> (4 * (7 - i))) & 0xF; 735 + for (i = 0; i < 32; i++) {
  736 + if ((i & 7) == 0)
  737 + printf("GPR%02d:", i);
  738 + printf(" %08x", env->gpr[i]);
  739 + if ((i & 7) == 7)
  740 + printf("\n");
164 } 741 }
165 - /* TODO: update FEX & VX */  
166 - /* Set rounding mode */  
167 - switch (env->fpscr[0] & 0x3) {  
168 - case 0:  
169 - /* Best approximation (round to nearest) */  
170 - fesetround(FE_TONEAREST);  
171 - break;  
172 - case 1:  
173 - /* Smaller magnitude (round toward zero) */  
174 - fesetround(FE_TOWARDZERO);  
175 - break;  
176 - case 2:  
177 - /* Round toward +infinite */  
178 - fesetround(FE_UPWARD);  
179 - break;  
180 - case 3:  
181 - /* Round toward -infinite */  
182 - fesetround(FE_DOWNWARD);  
183 - break; 742 + printf("CR: 0x");
  743 + for (i = 0; i < 8; i++)
  744 + printf("%01x", env->crf[i]);
  745 + printf(" [");
  746 + for (i = 0; i < 8; i++) {
  747 + char a = '-';
  748 + if (env->crf[i] & 0x08)
  749 + a = 'L';
  750 + else if (env->crf[i] & 0x04)
  751 + a = 'G';
  752 + else if (env->crf[i] & 0x02)
  753 + a = 'E';
  754 + printf(" %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
184 } 755 }
185 -}  
186 -  
187 -int32_t do_sraw(int32_t value, uint32_t shift)  
188 -{  
189 - int32_t ret;  
190 -  
191 - xer_ca = 0;  
192 - if (shift & 0x20) {  
193 - ret = (-1) * ((uint32_t)value >> 31);  
194 - if (ret < 0)  
195 - xer_ca = 1;  
196 - } else {  
197 - ret = value >> (shift & 0x1f);  
198 - if (ret < 0 && (value & ((1 << shift) - 1)) != 0)  
199 - xer_ca = 1; 756 + printf(" ] ");
200 } 757 }
201 -  
202 - return ret;  
203 -}  
204 -  
205 -void do_lmw (int reg, uint32_t src)  
206 -{  
207 - for (; reg <= 31; reg++, src += 4)  
208 - ugpr(reg) = ld32(src);  
209 -}  
210 -  
211 -void do_stmw (int reg, uint32_t dest)  
212 -{  
213 - for (; reg <= 31; reg++, dest += 4)  
214 - st32(dest, ugpr(reg));  
215 -}  
216 -  
217 -void do_lsw (uint32_t reg, int count, uint32_t src)  
218 -{  
219 - uint32_t tmp;  
220 - int sh;  
221 -  
222 - for (; count > 3; count -= 4, src += 4) {  
223 - ugpr(reg++) = ld32(src);  
224 - if (T2 == 32)  
225 - T2 = 0; 758 + printf("TB: 0x%08x %08x\n", env->tb[1], env->tb[0]);
  759 + printf("XER 0x%08x SRR0 0x%08x SRR1 0x%08x\n",
  760 + _load_xer(), env->spr[SRR0], env->spr[SRR1]);
226 } 761 }
227 - if (count > 0) {  
228 - tmp = 0;  
229 - for (sh = 24; count > 0; count--, src++, sh -= 8) {  
230 - tmp |= ld8(src) << sh; 762 +#endif
  763 + /* Generate informations in save/restore registers */
  764 + switch (excp) {
  765 + case EXCP_OFCALL:
  766 +#if defined (USE_OPEN_FIRMWARE)
  767 + env->gpr[3] = OF_client_entry((void *)env->gpr[3]);
  768 +#endif
  769 + return;
  770 + case EXCP_RTASCALL:
  771 +#if defined (USE_OPEN_FIRMWARE)
  772 + printf("RTAS call !\n");
  773 + env->gpr[3] = RTAS_entry((void *)env->gpr[3]);
  774 + printf("RTAS call done\n");
  775 +#endif
  776 + return;
  777 + case EXCP_NONE:
  778 + /* Do nothing */
  779 +#if defined (DEBUG_EXCEPTIONS)
  780 + printf("%s: escape EXCP_NONE\n", __func__);
  781 +#endif
  782 + return;
  783 + case EXCP_RESET:
  784 + if (msr_ip)
  785 + excp += 0xFFC00;
  786 + goto store_next;
  787 + case EXCP_MACHINE_CHECK:
  788 + if (msr_me == 0) {
  789 + printf("Machine check exception while not allowed !\n");
  790 + if (loglevel) {
  791 + fprintf(logfile,
  792 + "Machine check exception while not allowed !\n");
231 } 793 }
232 - ugpr(reg) = tmp; 794 + abort();
233 } 795 }
234 -}  
235 -  
236 -void do_stsw (uint32_t reg, int count, uint32_t dest)  
237 -{  
238 - int sh;  
239 -  
240 - for (; count > 3; count -= 4, dest += 4) {  
241 - st32(dest, ugpr(reg++));  
242 - if (reg == 32)  
243 - reg = 0; 796 + msr_me = 0;
  797 + break;
  798 + case EXCP_DSI:
  799 + /* Store exception cause */
  800 + /* data location address has been stored
  801 + * when the fault has been detected
  802 + */
  803 + goto store_current;
  804 + case EXCP_ISI:
  805 + /* Store exception cause */
  806 + if (env->error_code == EXCP_ISI_TRANSLATE)
  807 + msr |= 0x40000000;
  808 + else if (env->error_code == EXCP_ISI_NOEXEC ||
  809 + env->error_code == EXCP_ISI_GUARD)
  810 + msr |= 0x10000000;
  811 + else
  812 + msr |= 0x08000000;
  813 + goto store_next;
  814 + case EXCP_EXTERNAL:
  815 + if (msr_ee == 0) {
  816 +#if defined (DEBUG_EXCEPTIONS)
  817 + if (loglevel > 0) {
  818 + fprintf(logfile, "Skipping hardware interrupt\n");
  819 + } else {
  820 + printf("Skipping hardware interrupt\n");
244 } 821 }
245 - if (count > 0) {  
246 - for (sh = 24; count > 0; count--, dest++, sh -= 8) {  
247 - st8(dest, (ugpr(reg) >> sh) & 0xFF); 822 +#endif
  823 + return;
248 } 824 }
  825 + goto store_next;
  826 + case EXCP_ALIGN:
  827 + /* Store exception cause */
  828 + /* Get rS/rD and rA from faulting opcode */
  829 + env->spr[DSISR] |=
  830 + (ldl_code((void *)(env->nip - 4)) & 0x03FF0000) >> 16;
  831 + /* data location address has been stored
  832 + * when the fault has been detected
  833 + */
  834 + goto store_current;
  835 + case EXCP_PROGRAM:
  836 + msr &= ~0xFFFF0000;
  837 + switch (env->error_code & ~0xF) {
  838 + case EXCP_FP:
  839 + if (msr_fe0 == 0 && msr_fe1 == 0) {
  840 +#if defined (DEBUG_EXCEPTIONS)
  841 + printf("Ignore floating point exception\n");
  842 +#endif
  843 + return;
249 } 844 }
250 -}  
251 -  
252 -void do_dcbz (void)  
253 -{  
254 - int i;  
255 -  
256 - /* Assume cache line size is 32 */  
257 - for (i = 0; i < 8; i++) {  
258 - st32(T0, 0);  
259 - T0 += 4; 845 + msr |= 0x00100000;
  846 + /* Set FX */
  847 + env->fpscr[7] |= 0x8;
  848 + /* Finally, update FEX */
  849 + if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
  850 + ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
  851 + env->fpscr[7] |= 0x4;
  852 + break;
  853 + case EXCP_INVAL:
  854 + msr |= 0x00080000;
  855 + break;
  856 + case EXCP_PRIV:
  857 + msr |= 0x00040000;
  858 + break;
  859 + case EXCP_TRAP:
  860 + msr |= 0x00020000;
  861 + break;
  862 + default:
  863 + /* Should never occur */
  864 + break;
260 } 865 }
261 -}  
262 -  
263 -/* Instruction cache invalidation helper */  
264 -void do_icbi (void)  
265 -{  
266 - // tb_invalidate_page(T0); 866 + msr |= 0x00010000;
  867 + goto store_current;
  868 + case EXCP_NO_FP:
  869 + goto store_current;
  870 + case EXCP_DECR:
  871 + if (msr_ee == 0) {
  872 + /* Requeue it */
  873 + do_queue_exception(EXCP_DECR);
  874 + return;
  875 + }
  876 + goto store_next;
  877 + case EXCP_SYSCALL:
  878 +#if defined (DEBUG_EXCEPTIONS)
  879 + printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n",
  880 + env->gpr[0], env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
  881 +#endif
  882 + goto store_next;
  883 + case EXCP_TRACE:
  884 + goto store_next;
  885 + case EXCP_FP_ASSIST:
  886 + goto store_next;
  887 + case EXCP_MTMSR:
  888 + /* Nothing to do */
  889 +#if defined (DEBUG_EXCEPTIONS)
  890 + printf("%s: escape EXCP_MTMSR\n", __func__);
  891 +#endif
  892 + return;
  893 + case EXCP_BRANCH:
  894 + /* Nothing to do */
  895 +#if defined (DEBUG_EXCEPTIONS)
  896 + printf("%s: escape EXCP_BRANCH\n", __func__);
  897 +#endif
  898 + return;
  899 + case EXCP_RFI:
  900 + /* Restore user-mode state */
  901 +#if defined (DEBUG_EXCEPTIONS)
  902 + printf("%s: escape EXCP_RFI\n", __func__);
  903 +#endif
  904 + return;
  905 + store_current:
  906 + /* SRR0 is set to current instruction */
  907 + env->spr[SRR0] = (uint32_t)env->nip - 4;
  908 + break;
  909 + store_next:
  910 + /* SRR0 is set to next instruction */
  911 + env->spr[SRR0] = (uint32_t)env->nip;
  912 + break;
  913 + }
  914 + env->spr[SRR1] = msr;
  915 + /* reload MSR with correct bits */
  916 + msr_pow = 0;
  917 + msr_ee = 0;
  918 + msr_pr = 0;
  919 + msr_fp = 0;
  920 + msr_fe0 = 0;
  921 + msr_se = 0;
  922 + msr_be = 0;
  923 + msr_fe1 = 0;
  924 + msr_ir = 0;
  925 + msr_dr = 0;
  926 + msr_ri = 0;
  927 + msr_le = msr_ile;
  928 + /* Jump to handler */
  929 + env->nip = excp << 8;
  930 + env->exception_index = EXCP_NONE;
  931 + /* Invalidate all TLB as we may have changed translation mode */
  932 + do_tlbia();
  933 + /* ensure that no TB jump will be modified as
  934 + the program flow was changed */
  935 +#ifdef __sparc__
  936 + tmp_T0 = 0;
  937 +#else
  938 + T0 = 0;
  939 +#endif
  940 +#endif
267 } 941 }
target-ppc/hw.c 0 โ†’ 100644
  1 +/*
  2 + * Hardware simulation for PPC target.
  3 + * For now, this is only a 'minimal' collection of hacks needed to boot Linux.
  4 + */
  5 +
  6 +#include <stdlib.h>
  7 +#include <stdio.h>
  8 +#include <stdarg.h>
  9 +#include <string.h>
  10 +#include <ctype.h>
  11 +#include <unistd.h>
  12 +#include <fcntl.h>
  13 +#include <inttypes.h>
  14 +#include <unistd.h>
  15 +#include <time.h>
  16 +
  17 +#include "cpu.h"
  18 +#include "vl.h"
  19 +
  20 +//#define HARD_DEBUG_PPC_IO
  21 +#define DEBUG_PPC_IO
  22 +
  23 +extern int loglevel;
  24 +extern FILE *logfile;
  25 +
  26 +#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
  27 +#define DEBUG_PPC_IO
  28 +#endif
  29 +
  30 +#if defined (HARD_DEBUG_PPC_IO)
  31 +#define PPC_IO_DPRINTF(fmt, args...) \
  32 +do { \
  33 + if (loglevel > 0) { \
  34 + fprintf(logfile, "%s: " fmt, __func__ , ##args); \
  35 + } else { \
  36 + printf("%s : " fmt, __func__ , ##args); \
  37 + } \
  38 +} while (0)
  39 +#elif defined (DEBUG_PPC_IO)
  40 +#define PPC_IO_DPRINTF(fmt, args...) \
  41 +do { \
  42 + if (loglevel > 0) { \
  43 + fprintf(logfile, "%s: " fmt, __func__ , ##args); \
  44 + } \
  45 +} while (0)
  46 +#else
  47 +#define PPC_IO_DPRINTF(fmt, args...) do { } while (0)
  48 +#endif
  49 +
  50 +#if defined (USE_OPEN_FIRMWARE)
  51 +#include "of.h"
  52 +#else
  53 +#define NVRAM_SIZE 0x2000
  54 +#endif
  55 +
  56 +/* IO ports emulation */
  57 +#define PPC_IO_BASE 0x80000000
  58 +
  59 +static void PPC_io_writeb (uint32_t addr, uint32_t value)
  60 +{
  61 + /* Don't polute serial port output */
  62 + if ((addr < 0x800003F0 || addr > 0x80000400) &&
  63 + (addr < 0x80000074 || addr > 0x80000077) &&
  64 + (addr < 0x80000020 || addr > 0x80000021) &&
  65 + (addr < 0x800000a0 || addr > 0x800000a1) &&
  66 + (addr < 0x800001f0 || addr > 0x800001f7) &&
  67 + (addr < 0x80000170 || addr > 0x80000177)) {
  68 + PPC_IO_DPRINTF("0x%08x => 0x%02x\n", addr - PPC_IO_BASE, value);
  69 + }
  70 + cpu_outb(NULL, addr - PPC_IO_BASE, value);
  71 +}
  72 +
  73 +static uint32_t PPC_io_readb (uint32_t addr)
  74 +{
  75 + uint32_t ret = cpu_inb(NULL, addr - PPC_IO_BASE);
  76 +
  77 + if ((addr < 0x800003F0 || addr > 0x80000400) &&
  78 + (addr < 0x80000074 || addr > 0x80000077) &&
  79 + (addr < 0x80000020 || addr > 0x80000021) &&
  80 + (addr < 0x800000a0 || addr > 0x800000a1) &&
  81 + (addr < 0x800001f0 || addr > 0x800001f7) &&
  82 + (addr < 0x80000170 || addr > 0x80000177) &&
  83 + (addr < 0x8000060 || addr > 0x8000064)) {
  84 +// PPC_IO_DPRINTF("0x%08x <= 0x%02x\n", addr - PPC_IO_BASE, ret);
  85 + }
  86 +
  87 + return ret;
  88 +}
  89 +
  90 +static void PPC_io_writew (uint32_t addr, uint32_t value)
  91 +{
  92 + if ((addr < 0x800001f0 || addr > 0x800001f7) &&
  93 + (addr < 0x80000170 || addr > 0x80000177)) {
  94 + PPC_IO_DPRINTF("0x%08x => 0x%04x\n", addr - PPC_IO_BASE, value);
  95 + }
  96 + cpu_outw(NULL, addr - PPC_IO_BASE, value);
  97 +}
  98 +
  99 +static uint32_t PPC_io_readw (uint32_t addr)
  100 +{
  101 + uint32_t ret = cpu_inw(NULL, addr - PPC_IO_BASE);
  102 +
  103 + if ((addr < 0x800001f0 || addr > 0x800001f7) &&
  104 + (addr < 0x80000170 || addr > 0x80000177)) {
  105 + PPC_IO_DPRINTF("0x%08x <= 0x%04x\n", addr - PPC_IO_BASE, ret);
  106 + }
  107 +
  108 + return ret;
  109 +}
  110 +
  111 +static void PPC_io_writel (uint32_t addr, uint32_t value)
  112 +{
  113 + PPC_IO_DPRINTF("0x%08x => 0x%08x\n", addr - PPC_IO_BASE, value);
  114 + cpu_outl(NULL, addr - PPC_IO_BASE, value);
  115 +}
  116 +
  117 +static uint32_t PPC_io_readl (uint32_t addr)
  118 +{
  119 + uint32_t ret = cpu_inl(NULL, addr - PPC_IO_BASE);
  120 +
  121 + PPC_IO_DPRINTF("0x%08x <= 0x%08x\n", addr - PPC_IO_BASE, ret);
  122 +
  123 + return ret;
  124 +}
  125 +
  126 +static CPUWriteMemoryFunc *PPC_io_write[] = {
  127 + &PPC_io_writeb,
  128 + &PPC_io_writew,
  129 + &PPC_io_writel,
  130 +};
  131 +
  132 +static CPUReadMemoryFunc *PPC_io_read[] = {
  133 + &PPC_io_readb,
  134 + &PPC_io_readw,
  135 + &PPC_io_readl,
  136 +};
  137 +
  138 +uint32_t pic_intack_read(CPUState *env);
  139 +
  140 +/* Read-only register (?) */
  141 +static void _PPC_ioB_write (uint32_t addr, uint32_t value)
  142 +{
  143 + PPC_IO_DPRINTF("0x%08x => 0x%08x\n", addr, value);
  144 +}
  145 +
  146 +static uint32_t _PPC_ioB_read (uint32_t addr)
  147 +{
  148 + uint32_t retval = 0;
  149 +
  150 + if (addr == 0xBFFFFFF0)
  151 + retval = pic_intack_read(NULL);
  152 + PPC_IO_DPRINTF("0x%08x <= 0x%08x\n", addr, retval);
  153 +
  154 + return retval;
  155 +}
  156 +
  157 +static CPUWriteMemoryFunc *PPC_ioB_write[] = {
  158 + &_PPC_ioB_write,
  159 + &_PPC_ioB_write,
  160 + &_PPC_ioB_write,
  161 +};
  162 +
  163 +static CPUReadMemoryFunc *PPC_ioB_read[] = {
  164 + &_PPC_ioB_read,
  165 + &_PPC_ioB_read,
  166 + &_PPC_ioB_read,
  167 +};
  168 +
  169 +#if 0
  170 +static CPUWriteMemoryFunc *PPC_io3_write[] = {
  171 + &PPC_io3_writeb,
  172 + &PPC_io3_writew,
  173 + &PPC_io3_writel,
  174 +};
  175 +
  176 +static CPUReadMemoryFunc *PPC_io3_read[] = {
  177 + &PPC_io3_readb,
  178 + &PPC_io3_readw,
  179 + &PPC_io3_readl,
  180 +};
  181 +#endif
  182 +
  183 +/* Fake super-io ports for PREP platform (Intel 82378ZB) */
  184 +static uint8_t PREP_fake_io[2];
  185 +static uint8_t NVRAM_lock;
  186 +
  187 +static void PREP_io_write (CPUState *env, uint32_t addr, uint32_t val)
  188 +{
  189 + PREP_fake_io[addr - 0x0398] = val;
  190 +}
  191 +
  192 +static uint32_t PREP_io_read (CPUState *env, uint32_t addr)
  193 +{
  194 + return PREP_fake_io[addr - 0x0398];
  195 +}
  196 +
  197 +static uint8_t syscontrol;
  198 +
  199 +static void PREP_io_800_writeb (CPUState *env, uint32_t addr, uint32_t val)
  200 +{
  201 + switch (addr) {
  202 + case 0x0092:
  203 + /* Special port 92 */
  204 + /* Check soft reset asked */
  205 + if (val & 0x80) {
  206 + printf("Soft reset asked... Stop emulation\n");
  207 + abort();
  208 + }
  209 + /* Check LE mode */
  210 + if (val & 0x40) {
  211 + printf("Little Endian mode isn't supported (yet ?)\n");
  212 + abort();
  213 + }
  214 + break;
  215 + case 0x0808:
  216 + /* Hardfile light register: don't care */
  217 + break;
  218 + case 0x0810:
  219 + /* Password protect 1 register */
  220 + NVRAM_lock ^= 0x01;
  221 + break;
  222 + case 0x0812:
  223 + /* Password protect 2 register */
  224 + NVRAM_lock ^= 0x02;
  225 + break;
  226 + case 0x0814:
  227 + /* L2 invalidate register: don't care */
  228 + break;
  229 + case 0x081C:
  230 + /* system control register */
  231 + syscontrol = val;
  232 + break;
  233 + case 0x0850:
  234 + /* I/O map type register */
  235 + if (val & 0x80) {
  236 + printf("No support for non-continuous I/O map mode\n");
  237 + abort();
  238 + }
  239 + break;
  240 + default:
  241 + break;
  242 + }
  243 +}
  244 +
  245 +static uint32_t PREP_io_800_readb (CPUState *env, uint32_t addr)
  246 +{
  247 + uint32_t retval = 0xFF;
  248 +
  249 + switch (addr) {
  250 + case 0x0092:
  251 + /* Special port 92 */
  252 + retval = 0x40;
  253 + break;
  254 + case 0x080C:
  255 + /* Equipment present register:
  256 + * no L2 cache
  257 + * no upgrade processor
  258 + * no cards in PCI slots
  259 + * SCSI fuse is bad
  260 + */
  261 + retval = 0xFC;
  262 + break;
  263 + case 0x0818:
  264 + /* Keylock */
  265 + retval = 0x00;
  266 + break;
  267 + case 0x081C:
  268 + /* system control register
  269 + * 7 - 6 / 1 - 0: L2 cache enable
  270 + */
  271 + retval = syscontrol;
  272 + break;
  273 + case 0x0823:
  274 + /* */
  275 + retval = 0x03; /* no L2 cache */
  276 + break;
  277 + case 0x0850:
  278 + /* I/O map type register */
  279 + retval = 0x00;
  280 + break;
  281 + default:
  282 + break;
  283 + }
  284 +
  285 + return retval;
  286 +}
  287 +
  288 +/* M48T59 NVRAM/RTC emulation */
  289 +static uint8_t NVRAM[NVRAM_SIZE];
  290 +
  291 +/* RTC */
  292 +static time_t time_offset;
  293 +
  294 +time_t get_time (void)
  295 +{
  296 + return time(NULL) + time_offset;
  297 +}
  298 +
  299 +void set_time_offset (time_t new_time)
  300 +{
  301 + time_t now = time(NULL);
  302 +
  303 + time_offset = new_time - now;
  304 +}
  305 +
  306 +static void NVRAM_init (void)
  307 +{
  308 + /* NVRAM header */
  309 + /* 0x00: NVRAM size in kB */
  310 + NVRAM[0x00] = (NVRAM_SIZE >> 12) & 0xFF;
  311 + NVRAM[0x01] = (NVRAM_SIZE >> 10) & 0xFF;
  312 + /* 0x02: NVRAM version */
  313 + NVRAM[0x02] = 0x01;
  314 + /* 0x03: NVRAM revision */
  315 + NVRAM[0x03] = 0x00;
  316 + /* 0x04: checksum 0 => OS area */
  317 + /* 0x06: checksum of config area */
  318 + /* 0x08: last OS */
  319 + NVRAM[0x08] = 0x00; /* Unknown */
  320 + /* 0x09: endian */
  321 + NVRAM[0x09] = 'B';
  322 + /* 0x0B: PM mode */
  323 + NVRAM[0x0B] = 0x00;
  324 + /* Restart block description record */
  325 + /* 0x0C: restart block version */
  326 + NVRAM[0x0C] = 0x00;
  327 + NVRAM[0x0D] = 0x01;
  328 + /* 0x0E: restart block revision */
  329 + NVRAM[0x0E] = 0x00;
  330 + NVRAM[0x0F] = 0x00;
  331 + /* 0x1C: checksum of restart block */
  332 + /* 0x20: restart address */
  333 + NVRAM[0x20] = 0x00;
  334 + NVRAM[0x21] = 0x00;
  335 + NVRAM[0x22] = 0x00;
  336 + NVRAM[0x23] = 0x00;
  337 + /* 0x24: save area address */
  338 + NVRAM[0x24] = 0x00;
  339 + NVRAM[0x25] = 0x00;
  340 + NVRAM[0x26] = 0x00;
  341 + NVRAM[0x27] = 0x00;
  342 + /* 0x28: save area length */
  343 + NVRAM[0x28] = 0x00;
  344 + NVRAM[0x29] = 0x00;
  345 + NVRAM[0x2A] = 0x00;
  346 + NVRAM[0x2B] = 0x00;
  347 + /* Security section */
  348 + /* Set all to zero */
  349 + /* 0xC4: pointer to global environment area */
  350 + NVRAM[0xC4] = 0x00;
  351 + NVRAM[0xC5] = 0x00;
  352 + NVRAM[0xC6] = 0x01;
  353 + NVRAM[0xC7] = 0x00;
  354 + /* 0xC8: size of global environment area */
  355 + NVRAM[0xC8] = 0x00;
  356 + NVRAM[0xC9] = 0x00;
  357 + NVRAM[0xCA] = 0x07;
  358 + NVRAM[0xCB] = 0x00;
  359 + /* 0xD4: pointer to configuration area */
  360 + NVRAM[0xD4] = 0x00;
  361 + NVRAM[0xD5] = 0x00;
  362 + NVRAM[0xD6] = 0x08;
  363 + NVRAM[0xD7] = 0x00;
  364 + /* 0xD8: size of configuration area */
  365 + NVRAM[0xD8] = 0x00;
  366 + NVRAM[0xD9] = 0x00;
  367 + NVRAM[0xDA] = 0x08;
  368 + NVRAM[0xDB] = 0x00;
  369 + /* 0xE8: pointer to OS specific area */
  370 + NVRAM[0xE8] = 0x00;
  371 + NVRAM[0xE9] = 0x00;
  372 + NVRAM[0xEA] = 0x10;
  373 + NVRAM[0xEB] = 0x00;
  374 + /* 0xD8: size of OS specific area */
  375 + NVRAM[0xEC] = 0x00;
  376 + NVRAM[0xED] = 0x00;
  377 + NVRAM[0xEE] = 0x0F;
  378 + NVRAM[0xEF] = 0xF0;
  379 + /* CRC */
  380 + /* RTC init */
  381 + NVRAM[0x1FFC] = 0x50;
  382 +}
  383 +
  384 +static uint16_t NVRAM_addr;
  385 +
  386 +/* Direct access to NVRAM */
  387 +void NVRAM_write (CPUState *env, uint32_t addr, uint32_t val)
  388 +{
  389 + switch (addr) {
  390 + case 0x1FF0:
  391 + /* flags register */
  392 + break;
  393 + case 0x1FF1:
  394 + /* unused */
  395 + break;
  396 + case 0x1FF2:
  397 + /* alarm seconds */
  398 + break;
  399 + case 0x1FF3:
  400 + /* alarm minutes */
  401 + break;
  402 + case 0x1FF4:
  403 + /* alarm hours */
  404 + break;
  405 + case 0x1FF5:
  406 + /* alarm date */
  407 + break;
  408 + case 0x1FF6:
  409 + /* interrupts */
  410 + break;
  411 + case 0x1FF7:
  412 + /* watchdog */
  413 + break;
  414 + case 0x1FF8:
  415 + /* control */
  416 + break;
  417 + case 0x1FF9:
  418 + /* seconds (BCD) */
  419 + break;
  420 + case 0x1FFA:
  421 + /* minutes (BCD) */
  422 + break;
  423 + case 0x1FFB:
  424 + /* hours (BCD) */
  425 + break;
  426 + case 0x1FFC:
  427 + /* day of the week / century */
  428 + NVRAM[0x1FFC] = val & 0x50;
  429 + break;
  430 + case 0x1FFD:
  431 + /* date */
  432 + break;
  433 + case 0x1FFE:
  434 + /* month */
  435 + break;
  436 + case 0x1FFF:
  437 + /* year */
  438 + break;
  439 + default:
  440 + if (addr < NVRAM_SIZE)
  441 + NVRAM[addr] = val & 0xFF;
  442 + break;
  443 + }
  444 +}
  445 +
  446 +uint32_t NVRAM_read (CPUState *env, uint32_t addr)
  447 +{
  448 + struct tm tm;
  449 + time_t t;
  450 + uint32_t retval = 0xFF;
  451 +
  452 + switch (addr) {
  453 + case 0x1FF0:
  454 + /* flags register */
  455 + break;
  456 + case 0x1FF1:
  457 + /* unused */
  458 + break;
  459 + case 0x1FF2:
  460 + /* alarm seconds */
  461 + break;
  462 + case 0x1FF3:
  463 + /* alarm minutes */
  464 + break;
  465 + case 0x1FF4:
  466 + /* alarm hours */
  467 + break;
  468 + case 0x1FF5:
  469 + /* alarm date */
  470 + break;
  471 + case 0x1FF6:
  472 + /* interrupts */
  473 + break;
  474 + case 0x1FF7:
  475 + /* watchdog */
  476 + break;
  477 + case 0x1FF8:
  478 + /* control */
  479 + break;
  480 + case 0x1FF9:
  481 + /* seconds (BCD) */
  482 + t = get_time();
  483 + localtime_r(&t, &tm);
  484 + retval = ((tm.tm_sec / 10) << 4) | (tm.tm_sec % 10);
  485 +// printf("return seconds=%d\n", tm.tm_sec);
  486 + break;
  487 + case 0x1FFA:
  488 + /* minutes (BCD) */
  489 + t = get_time();
  490 + localtime_r(&t, &tm);
  491 + retval = ((tm.tm_min / 10) << 4) | (tm.tm_min % 10);
  492 + break;
  493 + case 0x1FFB:
  494 + /* hours (BCD) */
  495 + t = get_time();
  496 + localtime_r(&t, &tm);
  497 + retval = ((tm.tm_hour / 10) << 4) | (tm.tm_hour % 10);
  498 + break;
  499 + case 0x1FFC:
  500 + /* day of the week / century */
  501 + t = get_time();
  502 + localtime_r(&t, &tm);
  503 + retval = (NVRAM[0x1FFC] & 0x50) | tm.tm_wday;
  504 + break;
  505 + case 0x1FFD:
  506 + /* date */
  507 + t = get_time();
  508 + localtime_r(&t, &tm);
  509 + retval = ((tm.tm_mday / 10) << 4) | (tm.tm_mday % 10);
  510 + break;
  511 + case 0x1FFE:
  512 + /* month */
  513 + t = get_time();
  514 + localtime_r(&t, &tm);
  515 + retval = ((tm.tm_mon / 10) << 4) | (tm.tm_mon % 10);
  516 + break;
  517 + case 0x1FFF:
  518 + /* year */
  519 + t = get_time();
  520 + localtime_r(&t, &tm);
  521 + retval = ((tm.tm_year / 10) << 4) | (tm.tm_year % 10);
  522 + break;
  523 + default:
  524 + if (NVRAM_addr < NVRAM_SIZE)
  525 + retval = NVRAM[NVRAM_addr];
  526 + break;
  527 + }
  528 +
  529 + return retval;
  530 +}
  531 +
  532 +/* IO access to NVRAM */
  533 +static void NVRAM_writeb (CPUState *env, uint32_t addr, uint32_t val)
  534 +{
  535 + switch (addr) {
  536 + case 0x74:
  537 + NVRAM_addr &= ~0x00FF;
  538 + NVRAM_addr |= val;
  539 + break;
  540 + case 0x75:
  541 + NVRAM_addr &= ~0xFF00;
  542 + NVRAM_addr |= val << 8;
  543 + break;
  544 + case 0x77:
  545 + NVRAM_write(env, NVRAM_addr, val);
  546 + NVRAM_addr = 0x0000;
  547 + break;
  548 + default:
  549 + break;
  550 + }
  551 +}
  552 +
  553 +static uint32_t NVRAM_readb (CPUState *env, uint32_t addr)
  554 +{
  555 + if (addr == 0x77)
  556 + return NVRAM_read(env, NVRAM_addr);
  557 +
  558 + return 0xFF;
  559 +}
  560 +
  561 +int load_initrd (const char *filename, uint8_t *addr)
  562 +{
  563 + int fd, size;
  564 +
  565 + printf("Load initrd\n");
  566 + fd = open(filename, O_RDONLY);
  567 + if (fd < 0)
  568 + return -1;
  569 + size = read(fd, addr, 16 * 1024 * 1024);
  570 + if (size < 0)
  571 + goto fail;
  572 + close(fd);
  573 + printf("Load initrd: %d\n", size);
  574 + return size;
  575 + fail:
  576 + close(fd);
  577 + printf("Load initrd failed\n");
  578 + return -1;
  579 +}
  580 +
  581 +/* Quick hack for PPC memory infos... */
  582 +static void put_long (void *addr, uint32_t l)
  583 +{
  584 + char *pos = addr;
  585 + pos[0] = (l >> 24) & 0xFF;
  586 + pos[1] = (l >> 16) & 0xFF;
  587 + pos[2] = (l >> 8) & 0xFF;
  588 + pos[3] = l & 0xFF;
  589 +}
  590 +
  591 +/* bootloader infos are in the form:
  592 + * uint32_t TAG
  593 + * uint32_t TAG_size (from TAG to next TAG).
  594 + * datas
  595 + * ....
  596 + */
  597 +#if !defined (USE_OPEN_FIRMWARE)
  598 +static void *set_bootinfo_tag (void *addr, uint32_t tag, uint32_t size,
  599 + void *data)
  600 +{
  601 + char *pos = addr;
  602 +
  603 + put_long(pos, tag);
  604 + pos += 4;
  605 + put_long(pos, size + 8);
  606 + pos += 4;
  607 + memcpy(pos, data, size);
  608 + pos += size;
  609 +
  610 + return pos;
  611 +}
  612 +#endif
  613 +
  614 +typedef struct boot_dev_t {
  615 + const unsigned char *name;
  616 + int major;
  617 + int minor;
  618 +} boot_dev_t;
  619 +
  620 +static boot_dev_t boot_devs[] =
  621 +{
  622 + { "/dev/fd0", 2, 0, },
  623 + { "/dev/fd1", 2, 1, },
  624 + { "/dev/hda1", 3, 1, },
  625 +// { "/dev/ide/host0/bus0/target0/lun0/part1", 3, 1, },
  626 + { "/dev/hdc", 22, 0, },
  627 + { "/dev/ram0 init=/linuxrc", 1, 0, },
  628 +};
  629 +
  630 +/* BATU:
  631 + * BEPI : bloc virtual address
  632 + * BL : area size bits (128 kB is 0, 256 1, 512 3, ...
  633 + * Vs/Vp
  634 + * BATL:
  635 + * BPRN : bloc real address align on 4MB boundary
  636 + * WIMG : cache access mode : not used
  637 + * PP : protection bits
  638 + */
  639 +static void setup_BAT (CPUPPCState *env, int BAT,
  640 + uint32_t virtual, uint32_t physical,
  641 + uint32_t size, int Vs, int Vp, int PP)
  642 +{
  643 + uint32_t sz_bits, tmp_sz, align, tmp;
  644 +
  645 + sz_bits = 0;
  646 + align = 131072;
  647 + for (tmp_sz = size / 131072; tmp_sz != 1; tmp_sz = tmp_sz >> 1) {
  648 + sz_bits = (sz_bits << 1) + 1;
  649 + align = align << 1;
  650 + }
  651 + tmp = virtual & ~(align - 1); /* Align virtual area start */
  652 + tmp |= sz_bits << 2; /* Fix BAT size */
  653 + tmp |= Vs << 1; /* Supervisor access */
  654 + tmp |= Vp; /* User access */
  655 + env->DBAT[0][BAT] = tmp;
  656 + env->IBAT[0][BAT] = tmp;
  657 + tmp = physical & ~(align - 1); /* Align physical area start */
  658 + tmp |= 0; /* Don't care about WIMG */
  659 + tmp |= PP; /* Protection */
  660 + env->DBAT[1][BAT] = tmp;
  661 + env->IBAT[1][BAT] = tmp;
  662 + printf("Set BATU0 to 0x%08x BATL0 to 0x%08x\n",
  663 + env->DBAT[0][BAT], env->DBAT[1][BAT]);
  664 +}
  665 +
  666 +static void VGA_printf (uint8_t *s)
  667 +{
  668 + uint16_t *arg_ptr;
  669 + unsigned int format_width, i;
  670 + int in_format;
  671 + uint16_t arg, digit, nibble;
  672 + uint8_t c;
  673 +
  674 + arg_ptr = (uint16_t *)(&s);
  675 + in_format = 0;
  676 + format_width = 0;
  677 + while ((c = *s) != '\0') {
  678 + if (c == '%') {
  679 + in_format = 1;
  680 + format_width = 0;
  681 + } else if (in_format) {
  682 + if ((c >= '0') && (c <= '9')) {
  683 + format_width = (format_width * 10) + (c - '0');
  684 + } else if (c == 'x') {
  685 + arg_ptr++; // increment to next arg
  686 + arg = *arg_ptr;
  687 + if (format_width == 0)
  688 + format_width = 4;
  689 + digit = format_width - 1;
  690 + for (i = 0; i < format_width; i++) {
  691 + nibble = (arg >> (4 * digit)) & 0x000f;
  692 + if (nibble <= 9)
  693 + PPC_io_writeb(PPC_IO_BASE + 0x500, nibble + '0');
  694 + else
  695 + PPC_io_writeb(PPC_IO_BASE + 0x500, nibble + 'A');
  696 + digit--;
  697 + }
  698 + in_format = 0;
  699 + }
  700 + //else if (c == 'd') {
  701 + // in_format = 0;
  702 + // }
  703 + } else {
  704 + PPC_io_writeb(PPC_IO_BASE + 0x500, c);
  705 + }
  706 + s++;
  707 + }
  708 +}
  709 +
  710 +static void VGA_init (void)
  711 +{
  712 + /* Basic VGA init, inspired by plex86 VGAbios */
  713 + printf("Init VGA...\n");
  714 + /* switch to color mode and enable CPU access 480 lines */
  715 + PPC_io_writeb(PPC_IO_BASE + 0x3C2, 0xC3);
  716 + /* more than 64k 3C4/04 */
  717 + PPC_io_writeb(PPC_IO_BASE + 0x3C4, 0x04);
  718 + PPC_io_writeb(PPC_IO_BASE + 0x3C5, 0x02);
  719 + VGA_printf("PPC VGA BIOS...\n");
  720 +}
  721 +
  722 +void PPC_init_hw (CPUPPCState *env, uint32_t mem_size,
  723 + uint32_t kernel_addr, uint32_t kernel_size,
  724 + uint32_t stack_addr, int boot_device)
  725 +{
  726 + char *p;
  727 +#if !defined (USE_OPEN_FIRMWARE)
  728 + char *tmp;
  729 + uint32_t tmpi[2];
  730 +#endif
  731 + int PPC_io_memory;
  732 +
  733 +#if defined (USE_OPEN_FIRMWARE)
  734 + setup_memory(env, mem_size);
  735 +#endif
  736 + /* Register 64 kB of IO space */
  737 + PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write);
  738 + cpu_register_physical_memory(0x80000000, 0x10000, PPC_io_memory);
  739 + /* Register fake IO ports for PREP */
  740 + register_ioport_read(0x398, 2, PREP_io_read, 1);
  741 + register_ioport_write(0x398, 2, PREP_io_write, 1);
  742 + /* System control ports */
  743 + register_ioport_write(0x0092, 0x1, PREP_io_800_writeb, 1);
  744 + register_ioport_read(0x0800, 0x52, PREP_io_800_readb, 1);
  745 + register_ioport_write(0x0800, 0x52, PREP_io_800_writeb, 1);
  746 + /* PCI intack location */
  747 + PPC_io_memory = cpu_register_io_memory(0, PPC_ioB_read, PPC_ioB_write);
  748 + cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
  749 + /* NVRAM ports */
  750 + NVRAM_init();
  751 + register_ioport_read(0x0074, 0x04, NVRAM_readb, 1);
  752 + register_ioport_write(0x0074, 0x04, NVRAM_writeb, 1);
  753 +
  754 + /* Fake bootloader */
  755 + env->nip = kernel_addr + (3 * sizeof(uint32_t));
  756 + /* Set up msr according to PREP specification */
  757 + msr_ee = 0;
  758 + msr_fp = 1;
  759 + msr_pr = 0; /* Start in supervisor mode */
  760 + msr_me = 1;
  761 + msr_fe0 = msr_fe1 = 0;
  762 + msr_ip = 0;
  763 + msr_ir = msr_dr = 1;
  764 +// msr_sf = 0;
  765 + msr_le = msr_ile = 0;
  766 + env->gpr[1] = stack_addr; /* Let's have a stack */
  767 + env->gpr[2] = 0;
  768 + env->gpr[8] = kernel_addr;
  769 + /* There is a bug in 2.4 kernels:
  770 + * if a decrementer exception is pending when it enables msr_ee,
  771 + * it's not ready to handle it...
  772 + */
  773 + env->decr = 0xFFFFFFFF;
  774 + p = (void *)(phys_ram_base + kernel_addr);
  775 +#if !defined (USE_OPEN_FIRMWARE)
  776 + /* Let's register the whole memory available only in supervisor mode */
  777 + setup_BAT(env, 0, 0x00000000, 0x00000000, mem_size, 1, 0, 2);
  778 + /* Avoid open firmware init call (to get a console)
  779 + * This will make the kernel think we are a PREP machine...
  780 + */
  781 + put_long(p, 0xdeadc0de);
  782 + /* Build a real stack room */
  783 + p = (void *)(phys_ram_base + stack_addr);
  784 + put_long(p, stack_addr);
  785 + p -= 32;
  786 + env->gpr[1] -= 32;
  787 + /* Pretend there are no residual data */
  788 + env->gpr[3] = 0;
  789 +#if 1
  790 + {
  791 + int size;
  792 + env->gpr[4] = 0x00800000;
  793 + size = load_initrd("initrd",
  794 + (void *)((uint32_t)phys_ram_base + env->gpr[4]));
  795 + if (size < 0) {
  796 + /* No initrd */
  797 + env->gpr[4] = env->gpr[5] = 0;
  798 + } else {
  799 + env->gpr[5] = size;
  800 + boot_device = 'e';
  801 + }
  802 + printf("Initrd loaded at 0x%08x (%d)\n", env->gpr[4], env->gpr[5]);
  803 + }
  804 +#else
  805 + env->gpr[4] = env->gpr[5] = 0;
  806 +#endif
  807 + /* We have to put bootinfos after the BSS
  808 + * The BSS starts after the kernel end.
  809 + */
  810 +#if 0
  811 + p = (void *)(((uint32_t)phys_ram_base + kernel_addr +
  812 + kernel_size + (1 << 20) - 1) & ~((1 << 20) - 1));
  813 +#else
  814 + p = (void *)((uint32_t)phys_ram_base + kernel_addr + 0x400000);
  815 +#endif
  816 + if (loglevel > 0) {
  817 + fprintf(logfile, "bootinfos: %p 0x%08x\n",
  818 + p, (uint32_t)p - (uint32_t)phys_ram_base);
  819 + } else {
  820 + printf("bootinfos: %p 0x%08x\n",
  821 + p, (uint32_t)p - (uint32_t)phys_ram_base);
  822 + }
  823 + /* Command line: let's put it after bootinfos */
  824 +#if 0
  825 + sprintf(p + 0x1000, "console=ttyS0,9600 root=%02x%02x mem=%dM",
  826 + boot_devs[boot_device - 'a'].major,
  827 + boot_devs[boot_device - 'a'].minor,
  828 + phys_ram_size >> 20);
  829 +#else
  830 + sprintf(p + 0x1000, "console=ttyS0,9600 console=tty0 root=%s mem=%dM load_ramdisk=1",
  831 + boot_devs[boot_device - 'a'].name,
  832 + phys_ram_size >> 20);
  833 +#endif
  834 + env->gpr[6] = (uint32_t)p + 0x1000 - (uint32_t)phys_ram_base;
  835 + env->gpr[7] = env->gpr[6] + strlen(p + 0x1000);
  836 + if (loglevel > 0) {
  837 + fprintf(logfile, "cmdline: %p 0x%08x [%s]\n",
  838 + p + 0x1000, env->gpr[6], p + 0x1000);
  839 + } else {
  840 + printf("cmdline: %p 0x%08x [%s]\n",
  841 + p + 0x1000, env->gpr[6], p + 0x1000);
  842 + }
  843 + /* BI_FIRST */
  844 + p = set_bootinfo_tag(p, 0x1010, 0, 0);
  845 + /* BI_CMD_LINE */
  846 + p = set_bootinfo_tag(p, 0x1012, env->gpr[7] - env->gpr[6],
  847 + (void *)(env->gpr[6] + (uint32_t)phys_ram_base));
  848 + /* BI_MEM_SIZE */
  849 + tmp = (void *)tmpi;
  850 + tmp[0] = (phys_ram_size >> 24) & 0xFF;
  851 + tmp[1] = (phys_ram_size >> 16) & 0xFF;
  852 + tmp[2] = (phys_ram_size >> 8) & 0xFF;
  853 + tmp[3] = phys_ram_size & 0xFF;
  854 + p = set_bootinfo_tag(p, 0x1017, 4, tmpi);
  855 + /* BI_INITRD */
  856 + tmp[0] = (env->gpr[4] >> 24) & 0xFF;
  857 + tmp[1] = (env->gpr[4] >> 16) & 0xFF;
  858 + tmp[2] = (env->gpr[4] >> 8) & 0xFF;
  859 + tmp[3] = env->gpr[4] & 0xFF;
  860 + tmp[4] = (env->gpr[5] >> 24) & 0xFF;
  861 + tmp[5] = (env->gpr[5] >> 16) & 0xFF;
  862 + tmp[6] = (env->gpr[5] >> 8) & 0xFF;
  863 + tmp[7] = env->gpr[5] & 0xFF;
  864 + p = set_bootinfo_tag(p, 0x1014, 8, tmpi);
  865 + /* BI_LAST */
  866 + p = set_bootinfo_tag(p, 0x1011, 0, 0);
  867 +#else
  868 + /* Set up MMU:
  869 + * kernel is loaded at kernel_addr and wants to be seen at 0x01000000
  870 + */
  871 + setup_BAT(env, 0, 0x01000000, kernel_addr, 0x00400000, 1, 0, 2);
  872 + {
  873 +#if 0
  874 + uint32_t offset =
  875 + *((uint32_t *)((uint32_t)phys_ram_base + kernel_addr));
  876 +#else
  877 + uint32_t offset = 12;
  878 +#endif
  879 + env->nip = 0x01000000 | (kernel_addr + offset);
  880 + printf("Start address: 0x%08x\n", env->nip);
  881 + }
  882 + env->gpr[1] = env->nip + (1 << 22);
  883 + p = (void *)(phys_ram_base + stack_addr);
  884 + put_long(p - 32, stack_addr);
  885 + env->gpr[1] -= 32;
  886 + printf("Kernel starts at 0x%08x stack 0x%08x\n", env->nip, env->gpr[1]);
  887 + /* We want all lower address not to be translated */
  888 + setup_BAT(env, 1, 0x00000000, 0x00000000, 0x010000000, 1, 1, 2);
  889 + /* We also need a BAT to access OF */
  890 + setup_BAT(env, 2, 0xFFFE0000, mem_size - 131072, 131072, 1, 0, 1);
  891 + /* Setup OF entry point */
  892 + {
  893 + char *p;
  894 + p = (char *)phys_ram_base + mem_size - 131072;
  895 + /* Special opcode to call OF */
  896 + *p++ = 0x18; *p++ = 0x00; *p++ = 0x00; *p++ = 0x02;
  897 + /* blr */
  898 + *p++ = 0x4E; *p++ = 0x80; *p++ = 0x00; *p++ = 0x20;
  899 + }
  900 + env->gpr[5] = 0xFFFE0000;
  901 + /* Register translations */
  902 + {
  903 + OF_transl_t translations[3] = {
  904 + { 0x01000000, 0x00400000, kernel_addr, 0x00000002, },
  905 + { 0x00000000, 0x01000000, 0x00000000, 0x00000002, },
  906 + { 0xFFFE0000, 0x00020000, mem_size - (128 * 1024),
  907 + 0x00000001, },
  908 + };
  909 + OF_register_translations(3, translations);
  910 + }
  911 + /* Quite artificial, for now */
  912 + OF_register_bus("isa", "isa");
  913 + OF_register_serial("isa", "serial", 4, 0x3f8);
  914 + OF_register_stdio("serial", "serial");
  915 + /* Set up RTAS service */
  916 + RTAS_init();
  917 + /* Command line: let's put it just over the stack */
  918 +#if 1
  919 + sprintf(p, "console=ttyS0,9600 root=%02x%02x mem=%dM",
  920 + boot_devs[boot_device - 'a'].major,
  921 + boot_devs[boot_device - 'a'].minor,
  922 + phys_ram_size >> 20);
  923 +#else
  924 + sprintf(p, "console=ttyS0,9600 root=%s mem=%dM ne2000=0x300,9",
  925 + boot_devs[boot_device - 'a'].name,
  926 + phys_ram_size >> 20);
  927 +#endif
  928 + OF_register_bootargs(p);
  929 +#endif
  930 +}
  931 +
  932 +void PPC_end_init (void)
  933 +{
  934 + VGA_init();
  935 +}
target-ppc/op.c
@@ -21,6 +21,8 @@ @@ -21,6 +21,8 @@
21 #include "config.h" 21 #include "config.h"
22 #include "exec.h" 22 #include "exec.h"
23 23
  24 +//#define DEBUG_OP
  25 +
24 #define regs (env) 26 #define regs (env)
25 #define Ts0 (int32_t)T0 27 #define Ts0 (int32_t)T0
26 #define Ts1 (int32_t)T1 28 #define Ts1 (int32_t)T1
@@ -34,7 +36,7 @@ @@ -34,7 +36,7 @@
34 #define FTS1 ((float)env->ft1) 36 #define FTS1 ((float)env->ft1)
35 #define FTS2 ((float)env->ft2) 37 #define FTS2 ((float)env->ft2)
36 38
37 -#define PPC_OP(name) void op_##name(void) 39 +#define PPC_OP(name) void glue(op_, name)(void)
38 40
39 #define REG 0 41 #define REG 0
40 #include "op_template.h" 42 #include "op_template.h"
@@ -145,7 +147,7 @@ PPC_OP(set_Rc0) @@ -145,7 +147,7 @@ PPC_OP(set_Rc0)
145 } else { 147 } else {
146 tmp = 0x02; 148 tmp = 0x02;
147 } 149 }
148 - set_CRn(0, tmp); 150 + env->crf[0] = tmp;
149 RETURN(); 151 RETURN();
150 } 152 }
151 153
@@ -161,21 +163,21 @@ PPC_OP(set_Rc0_ov) @@ -161,21 +163,21 @@ PPC_OP(set_Rc0_ov)
161 tmp = 0x02; 163 tmp = 0x02;
162 } 164 }
163 tmp |= xer_ov; 165 tmp |= xer_ov;
164 - set_CRn(0, tmp); 166 + env->crf[0] = tmp;
165 RETURN(); 167 RETURN();
166 } 168 }
167 169
168 /* reset_Rc0 */ 170 /* reset_Rc0 */
169 PPC_OP(reset_Rc0) 171 PPC_OP(reset_Rc0)
170 { 172 {
171 - set_CRn(0, 0x02 | xer_ov); 173 + env->crf[0] = 0x02 | xer_ov;
172 RETURN(); 174 RETURN();
173 } 175 }
174 176
175 /* set_Rc0_1 */ 177 /* set_Rc0_1 */
176 PPC_OP(set_Rc0_1) 178 PPC_OP(set_Rc0_1)
177 { 179 {
178 - set_CRn(0, 0x04 | xer_ov); 180 + env->crf[0] = 0x04 | xer_ov;
179 RETURN(); 181 RETURN();
180 } 182 }
181 183
@@ -186,6 +188,7 @@ PPC_OP(set_Rc1) @@ -186,6 +188,7 @@ PPC_OP(set_Rc1)
186 RETURN(); 188 RETURN();
187 } 189 }
188 190
  191 +/* Constants load */
189 PPC_OP(set_T0) 192 PPC_OP(set_T0)
190 { 193 {
191 T0 = PARAM(1); 194 T0 = PARAM(1);
@@ -204,23 +207,50 @@ PPC_OP(set_T2) @@ -204,23 +207,50 @@ PPC_OP(set_T2)
204 RETURN(); 207 RETURN();
205 } 208 }
206 209
207 -/* Update time base */  
208 -PPC_OP(update_tb) 210 +/* Generate exceptions */
  211 +PPC_OP(queue_exception_err)
209 { 212 {
210 - T0 = regs->spr[SPR_ENCODE(268)];  
211 - T1 = T0;  
212 - T0 += PARAM(1);  
213 - if (T0 < T1) {  
214 - T1 = regs->spr[SPR_ENCODE(269)] + 1;  
215 - regs->spr[SPR_ENCODE(269)] = T1; 213 + do_queue_exception_err(PARAM(1), PARAM(2));
  214 +}
  215 +
  216 +PPC_OP(queue_exception)
  217 +{
  218 + do_queue_exception(PARAM(1));
  219 +}
  220 +
  221 +PPC_OP(process_exceptions)
  222 +{
  223 + if (env->exceptions != 0) {
  224 + env->nip = PARAM(1);
  225 + do_check_exception_state();
216 } 226 }
217 - regs->spr[SPR_ENCODE(268)] = T0; 227 +}
  228 +
  229 +/* Segment registers load and store with immediate index */
  230 +PPC_OP(load_srin)
  231 +{
  232 + T0 = regs->sr[T1 >> 28];
  233 + RETURN();
  234 +}
  235 +
  236 +PPC_OP(store_srin)
  237 +{
  238 +#if defined (DEBUG_OP)
  239 + dump_store_sr(T1 >> 28);
  240 +#endif
  241 + regs->sr[T1 >> 28] = T0;
  242 + RETURN();
  243 +}
  244 +
  245 +PPC_OP(load_sdr1)
  246 +{
  247 + T0 = regs->sdr1;
218 RETURN(); 248 RETURN();
219 } 249 }
220 250
221 -PPC_OP(raise_exception) 251 +PPC_OP(store_sdr1)
222 { 252 {
223 - raise_exception(PARAM(1)); 253 + regs->sdr1 = T0;
224 RETURN(); 254 RETURN();
225 } 255 }
226 256
@@ -229,15 +259,16 @@ PPC_OP(exit_tb) @@ -229,15 +259,16 @@ PPC_OP(exit_tb)
229 EXIT_TB(); 259 EXIT_TB();
230 } 260 }
231 261
  262 +/* Load/store special registers */
232 PPC_OP(load_cr) 263 PPC_OP(load_cr)
233 { 264 {
234 - T0 = do_load_cr(); 265 + do_load_cr();
235 RETURN(); 266 RETURN();
236 } 267 }
237 268
238 PPC_OP(store_cr) 269 PPC_OP(store_cr)
239 { 270 {
240 - do_store_cr(PARAM(1), T0); 271 + do_store_cr(PARAM(1));
241 RETURN(); 272 RETURN();
242 } 273 }
243 274
@@ -257,40 +288,152 @@ PPC_OP(clear_xer_cr) @@ -257,40 +288,152 @@ PPC_OP(clear_xer_cr)
257 288
258 PPC_OP(load_xer_bc) 289 PPC_OP(load_xer_bc)
259 { 290 {
260 - T0 = xer_bc; 291 + T1 = xer_bc;
261 RETURN(); 292 RETURN();
262 } 293 }
263 294
264 PPC_OP(load_xer) 295 PPC_OP(load_xer)
265 { 296 {
266 - T0 = do_load_xer(); 297 + do_load_xer();
267 RETURN(); 298 RETURN();
268 } 299 }
269 300
270 PPC_OP(store_xer) 301 PPC_OP(store_xer)
271 { 302 {
272 - do_store_xer(T0); 303 + do_store_xer();
273 RETURN(); 304 RETURN();
274 } 305 }
275 306
276 PPC_OP(load_msr) 307 PPC_OP(load_msr)
277 { 308 {
278 - T0 = do_load_msr(); 309 + do_load_msr();
279 RETURN(); 310 RETURN();
280 } 311 }
281 312
282 PPC_OP(store_msr) 313 PPC_OP(store_msr)
283 { 314 {
284 - do_store_msr(T0); 315 + do_store_msr();
  316 + RETURN();
  317 +}
  318 +
  319 +/* SPR */
  320 +PPC_OP(load_spr)
  321 +{
  322 + T0 = regs->spr[PARAM(1)];
  323 + RETURN();
  324 +}
  325 +
  326 +PPC_OP(store_spr)
  327 +{
  328 + regs->spr[PARAM(1)] = T0;
285 RETURN(); 329 RETURN();
286 } 330 }
287 331
288 PPC_OP(load_lr) 332 PPC_OP(load_lr)
289 { 333 {
290 - regs->LR = PARAM(1); 334 + T0 = regs->lr;
  335 + RETURN();
  336 +}
  337 +
  338 +PPC_OP(store_lr)
  339 +{
  340 + regs->lr = T0;
  341 + RETURN();
  342 +}
  343 +
  344 +PPC_OP(load_ctr)
  345 +{
  346 + T0 = regs->ctr;
  347 + RETURN();
  348 +}
  349 +
  350 +PPC_OP(store_ctr)
  351 +{
  352 + regs->ctr = T0;
  353 + RETURN();
  354 +}
  355 +
  356 +/* Update time base */
  357 +PPC_OP(update_tb)
  358 +{
  359 + T0 = regs->tb[0];
  360 + T1 = T0;
  361 + T0 += PARAM(1);
  362 +#if defined (DEBUG_OP)
  363 + dump_update_tb(PARAM(1));
  364 +#endif
  365 + if (T0 < T1) {
  366 + T1 = regs->tb[1] + 1;
  367 + regs->tb[1] = T1;
  368 + }
  369 + regs->tb[0] = T0;
  370 + RETURN();
  371 +}
  372 +
  373 +PPC_OP(load_tb)
  374 +{
  375 + T0 = regs->tb[PARAM(1)];
  376 + RETURN();
  377 +}
  378 +
  379 +PPC_OP(store_tb)
  380 +{
  381 + regs->tb[PARAM(1)] = T0;
  382 +#if defined (DEBUG_OP)
  383 + dump_store_tb(PARAM(1));
  384 +#endif
291 RETURN(); 385 RETURN();
292 } 386 }
293 387
  388 +/* Update decrementer */
  389 +PPC_OP(update_decr)
  390 +{
  391 + T0 = regs->decr;
  392 + T1 = T0;
  393 + T0 -= PARAM(1);
  394 + regs->decr = T0;
  395 + if (PARAM(1) > T1) {
  396 + do_queue_exception(EXCP_DECR);
  397 + }
  398 + RETURN();
  399 +}
  400 +
  401 +PPC_OP(store_decr)
  402 +{
  403 + T1 = regs->decr;
  404 + regs->decr = T0;
  405 + if (Ts0 < 0 && Ts1 > 0) {
  406 + do_queue_exception(EXCP_DECR);
  407 + }
  408 + RETURN();
  409 +}
  410 +
  411 +PPC_OP(load_ibat)
  412 +{
  413 + T0 = regs->IBAT[PARAM(1)][PARAM(2)];
  414 +}
  415 +
  416 +PPC_OP(store_ibat)
  417 +{
  418 +#if defined (DEBUG_OP)
  419 + dump_store_ibat(PARAM(1), PARAM(2));
  420 +#endif
  421 + regs->IBAT[PARAM(1)][PARAM(2)] = T0;
  422 +}
  423 +
  424 +PPC_OP(load_dbat)
  425 +{
  426 + T0 = regs->DBAT[PARAM(1)][PARAM(2)];
  427 +}
  428 +
  429 +PPC_OP(store_dbat)
  430 +{
  431 +#if defined (DEBUG_OP)
  432 + dump_store_dbat(PARAM(1), PARAM(2));
  433 +#endif
  434 + regs->DBAT[PARAM(1)][PARAM(2)] = T0;
  435 +}
  436 +
294 /* FPSCR */ 437 /* FPSCR */
295 PPC_OP(load_fpscr) 438 PPC_OP(load_fpscr)
296 { 439 {
@@ -313,14 +456,7 @@ PPC_OP(reset_scrfx) @@ -313,14 +456,7 @@ PPC_OP(reset_scrfx)
313 /* Set reservation */ 456 /* Set reservation */
314 PPC_OP(set_reservation) 457 PPC_OP(set_reservation)
315 { 458 {
316 - regs->reserve = T1 & ~0x03;  
317 - RETURN();  
318 -}  
319 -  
320 -/* Reset reservation */  
321 -PPC_OP(reset_reservation)  
322 -{  
323 - regs->reserve = 0; 459 + regs->reserve = T0 & ~0x03;
324 RETURN(); 460 RETURN();
325 } 461 }
326 462
@@ -344,47 +480,65 @@ PPC_OP(setcrfbit) @@ -344,47 +480,65 @@ PPC_OP(setcrfbit)
344 } 480 }
345 481
346 /* Branch */ 482 /* Branch */
  483 +#if 0
  484 +#define EIP regs->nip
  485 +#define TB_DO_JUMP(name, tb, n, target) JUMP_TB(name, tb, n, target)
  486 +#else
  487 +#define TB_DO_JUMP(name, tb, n, target) regs->nip = target;
  488 +#endif
  489 +
347 #define __PPC_OP_B(name, target) \ 490 #define __PPC_OP_B(name, target) \
348 PPC_OP(name) \ 491 PPC_OP(name) \
349 { \ 492 { \
350 - regs->nip = (target); \ 493 + TB_DO_JUMP(glue(op_, name), T1, 0, (target)); \
351 RETURN(); \ 494 RETURN(); \
352 } 495 }
353 496
354 -#define __PPC_OP_BL(name, target) \ 497 +#define __PPC_OP_BL(name, target, link) \
355 PPC_OP(name) \ 498 PPC_OP(name) \
356 { \ 499 { \
357 - regs->LR = PARAM(1); \  
358 - regs->nip = (target); \ 500 + regs->lr = (link); \
  501 + TB_DO_JUMP(glue(op_, name), T1, 0, (target)); \
359 RETURN(); \ 502 RETURN(); \
360 } 503 }
361 504
362 -#define PPC_OP_B(name, target) \ 505 +#define PPC_OP_B(name, target, link) \
363 __PPC_OP_B(name, target); \ 506 __PPC_OP_B(name, target); \
364 -__PPC_OP_BL(name##l, target) 507 +__PPC_OP_BL(glue(name, l), target, link)
365 508
366 #define __PPC_OP_BC(name, cond, target) \ 509 #define __PPC_OP_BC(name, cond, target) \
367 PPC_OP(name) \ 510 PPC_OP(name) \
368 { \ 511 { \
369 if (cond) { \ 512 if (cond) { \
370 - T0 = (target); \ 513 + TB_DO_JUMP(glue(op_, name), T1, 1, (target)); \
371 } else { \ 514 } else { \
372 - T0 = PARAM(1); \ 515 + TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1)); \
373 } \ 516 } \
374 - regs->nip = T0; \  
375 RETURN(); \ 517 RETURN(); \
376 } 518 }
377 519
378 #define __PPC_OP_BCL(name, cond, target) \ 520 #define __PPC_OP_BCL(name, cond, target) \
379 PPC_OP(name) \ 521 PPC_OP(name) \
380 { \ 522 { \
  523 + regs->lr = PARAM(1); \
381 if (cond) { \ 524 if (cond) { \
382 - T0 = (target); \  
383 - regs->LR = PARAM(1); \ 525 + TB_DO_JUMP(glue(op_, name), T1, 1, (target)); \
384 } else { \ 526 } else { \
385 - T0 = PARAM(1); \ 527 + TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1)); \
  528 + } \
  529 + RETURN(); \
  530 +}
  531 +
  532 +#define __PPC_OP_BCLRL(name, cond, target) \
  533 +PPC_OP(name) \
  534 +{ \
  535 + T2 = (target); \
  536 + regs->lr = PARAM(1); \
  537 + if (cond) { \
  538 + TB_DO_JUMP(glue(op_, name), T1, 1, T2); \
  539 + } else { \
  540 + TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1)); \
386 } \ 541 } \
387 - regs->nip = T0; \  
388 RETURN(); \ 542 RETURN(); \
389 } 543 }
390 544
@@ -396,48 +550,56 @@ __PPC_OP_BCL(namel, cond, target) @@ -396,48 +550,56 @@ __PPC_OP_BCL(namel, cond, target)
396 #define PPC_OP_BC(name, cond) \ 550 #define PPC_OP_BC(name, cond) \
397 _PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2)) 551 _PPC_OP_BC(b_##name, bl_##name, cond, PARAM(2))
398 552
399 -PPC_OP_B(b, PARAM(1));  
400 -PPC_OP_BC(ctr, (regs->CTR != 0));  
401 -PPC_OP_BC(ctr_true, (regs->CTR != 0 && (T0 & PARAM(3)) != 0));  
402 -PPC_OP_BC(ctr_false, (regs->CTR != 0 && (T0 & PARAM(3)) == 0));  
403 -PPC_OP_BC(ctrz, (regs->CTR == 0));  
404 -PPC_OP_BC(ctrz_true, (regs->CTR == 0 && (T0 & PARAM(3)) != 0));  
405 -PPC_OP_BC(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(3)) == 0)); 553 +PPC_OP_B(b, PARAM(1), PARAM(2));
  554 +PPC_OP_BC(ctr, (regs->ctr != 0));
  555 +PPC_OP_BC(ctr_true, (regs->ctr != 0 && (T0 & PARAM(3)) != 0));
  556 +PPC_OP_BC(ctr_false, (regs->ctr != 0 && (T0 & PARAM(3)) == 0));
  557 +PPC_OP_BC(ctrz, (regs->ctr == 0));
  558 +PPC_OP_BC(ctrz_true, (regs->ctr == 0 && (T0 & PARAM(3)) != 0));
  559 +PPC_OP_BC(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(3)) == 0));
406 PPC_OP_BC(true, ((T0 & PARAM(3)) != 0)); 560 PPC_OP_BC(true, ((T0 & PARAM(3)) != 0));
407 PPC_OP_BC(false, ((T0 & PARAM(3)) == 0)); 561 PPC_OP_BC(false, ((T0 & PARAM(3)) == 0));
408 562
409 /* Branch to CTR */ 563 /* Branch to CTR */
410 #define PPC_OP_BCCTR(name, cond) \ 564 #define PPC_OP_BCCTR(name, cond) \
411 -_PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->CTR & ~0x03)  
412 -  
413 -PPC_OP_B(bctr, regs->CTR & ~0x03);  
414 -PPC_OP_BCCTR(ctr, (regs->CTR != 0));  
415 -PPC_OP_BCCTR(ctr_true, (regs->CTR != 0 && (T0 & PARAM(2)) != 0));  
416 -PPC_OP_BCCTR(ctr_false, (regs->CTR != 0 && (T0 & PARAM(2)) == 0));  
417 -PPC_OP_BCCTR(ctrz, (regs->CTR == 0));  
418 -PPC_OP_BCCTR(ctrz_true, (regs->CTR == 0 && (T0 & PARAM(2)) != 0));  
419 -PPC_OP_BCCTR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0)); 565 +_PPC_OP_BC(bctr_##name, bctrl_##name, cond, regs->ctr & ~0x03)
  566 +
  567 +PPC_OP_B(bctr, regs->ctr & ~0x03, PARAM(1));
  568 +PPC_OP_BCCTR(ctr, (regs->ctr != 0));
  569 +PPC_OP_BCCTR(ctr_true, (regs->ctr != 0 && (T0 & PARAM(2)) != 0));
  570 +PPC_OP_BCCTR(ctr_false, (regs->ctr != 0 && (T0 & PARAM(2)) == 0));
  571 +PPC_OP_BCCTR(ctrz, (regs->ctr == 0));
  572 +PPC_OP_BCCTR(ctrz_true, (regs->ctr == 0 && (T0 & PARAM(2)) != 0));
  573 +PPC_OP_BCCTR(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(2)) == 0));
420 PPC_OP_BCCTR(true, ((T0 & PARAM(2)) != 0)); 574 PPC_OP_BCCTR(true, ((T0 & PARAM(2)) != 0));
421 PPC_OP_BCCTR(false, ((T0 & PARAM(2)) == 0)); 575 PPC_OP_BCCTR(false, ((T0 & PARAM(2)) == 0));
422 576
423 /* Branch to LR */ 577 /* Branch to LR */
424 #define PPC_OP_BCLR(name, cond) \ 578 #define PPC_OP_BCLR(name, cond) \
425 -_PPC_OP_BC(blr_##name, blrl_##name, cond, regs->LR & ~0x03)  
426 -  
427 -PPC_OP_B(blr, regs->LR & ~0x03);  
428 -PPC_OP_BCLR(ctr, (regs->CTR != 0));  
429 -PPC_OP_BCLR(ctr_true, (regs->CTR != 0 && (T0 & PARAM(2)) != 0));  
430 -PPC_OP_BCLR(ctr_false, (regs->CTR != 0 && (T0 & PARAM(2)) == 0));  
431 -PPC_OP_BCLR(ctrz, (regs->CTR == 0));  
432 -PPC_OP_BCLR(ctrz_true, (regs->CTR == 0 && (T0 & PARAM(2)) != 0));  
433 -PPC_OP_BCLR(ctrz_false, (regs->CTR == 0 && (T0 & PARAM(2)) == 0)); 579 +__PPC_OP_BC(blr_##name, cond, regs->lr & ~0x03); \
  580 +__PPC_OP_BCLRL(blrl_##name, cond, regs->lr & ~0x03)
  581 +
  582 +__PPC_OP_B(blr, regs->lr & ~0x03);
  583 +PPC_OP(blrl)
  584 +{
  585 + T0 = regs->lr & ~0x03;
  586 + regs->lr = PARAM(1);
  587 + TB_DO_JUMP(op_blrl, T1, 0, T0);
  588 + RETURN();
  589 +}
  590 +PPC_OP_BCLR(ctr, (regs->ctr != 0));
  591 +PPC_OP_BCLR(ctr_true, (regs->ctr != 0 && (T0 & PARAM(2)) != 0));
  592 +PPC_OP_BCLR(ctr_false, (regs->ctr != 0 && (T0 & PARAM(2)) == 0));
  593 +PPC_OP_BCLR(ctrz, (regs->ctr == 0));
  594 +PPC_OP_BCLR(ctrz_true, (regs->ctr == 0 && (T0 & PARAM(2)) != 0));
  595 +PPC_OP_BCLR(ctrz_false, (regs->ctr == 0 && (T0 & PARAM(2)) == 0));
434 PPC_OP_BCLR(true, ((T0 & PARAM(2)) != 0)); 596 PPC_OP_BCLR(true, ((T0 & PARAM(2)) != 0));
435 PPC_OP_BCLR(false, ((T0 & PARAM(2)) == 0)); 597 PPC_OP_BCLR(false, ((T0 & PARAM(2)) == 0));
436 598
437 /* CTR maintenance */ 599 /* CTR maintenance */
438 PPC_OP(dec_ctr) 600 PPC_OP(dec_ctr)
439 { 601 {
440 - regs->CTR--; 602 + regs->ctr--;
441 RETURN(); 603 RETURN();
442 } 604 }
443 605
@@ -1077,7 +1239,7 @@ PPC_OP(slw) @@ -1077,7 +1239,7 @@ PPC_OP(slw)
1077 /* shift right algebraic word */ 1239 /* shift right algebraic word */
1078 PPC_OP(sraw) 1240 PPC_OP(sraw)
1079 { 1241 {
1080 - Ts0 = do_sraw(Ts0, T1); 1242 + do_sraw();
1081 RETURN(); 1243 RETURN();
1082 } 1244 }
1083 1245
@@ -1106,313 +1268,280 @@ PPC_OP(srw) @@ -1106,313 +1268,280 @@ PPC_OP(srw)
1106 } 1268 }
1107 1269
1108 /*** Floating-Point arithmetic ***/ 1270 /*** Floating-Point arithmetic ***/
1109 -  
1110 -/*** Floating-Point multiply-and-add ***/  
1111 -  
1112 -/*** Floating-Point round & convert ***/  
1113 -  
1114 -/*** Floating-Point compare ***/  
1115 -  
1116 -/*** Floating-Point status & ctrl register ***/  
1117 -  
1118 -/*** Integer load ***/  
1119 -#define ld16x(x) s_ext16(ld16(x))  
1120 -#define PPC_ILD_OPX(name, op) \  
1121 -PPC_OP(l##name##x_z) \  
1122 -{ \  
1123 - T1 = op(T0); \  
1124 - RETURN(); \  
1125 -} \  
1126 -PPC_OP(l##name##x) \  
1127 -{ \  
1128 - T0 += T1; \  
1129 - T1 = op(T0); \  
1130 - RETURN(); \  
1131 -}  
1132 -  
1133 -#define PPC_ILD_OP(name, op) \  
1134 -PPC_OP(l##name##_z) \  
1135 -{ \  
1136 - T1 = op(SPARAM(1)); \  
1137 - RETURN(); \  
1138 -} \  
1139 -PPC_OP(l##name) \  
1140 -{ \  
1141 - T0 += SPARAM(1); \  
1142 - T1 = op(T0); \  
1143 - RETURN(); \  
1144 -} \  
1145 -PPC_ILD_OPX(name, op)  
1146 -  
1147 -PPC_ILD_OP(bz, ld8);  
1148 -PPC_ILD_OP(ha, ld16x);  
1149 -PPC_ILD_OP(hz, ld16);  
1150 -PPC_ILD_OP(wz, ld32);  
1151 -  
1152 -/*** Integer store ***/  
1153 -#define PPC_IST_OPX(name, op) \  
1154 -PPC_OP(st##name##x_z) \  
1155 -{ \  
1156 - op(T0, T1); \  
1157 - RETURN(); \  
1158 -} \  
1159 -PPC_OP(st##name##x) \  
1160 -{ \  
1161 - T0 += T1; \  
1162 - op(T0, T2); \  
1163 - RETURN(); \  
1164 -}  
1165 -  
1166 -#define PPC_IST_OP(name, op) \  
1167 -PPC_OP(st##name##_z) \  
1168 -{ \  
1169 - op(SPARAM(1), T0); \  
1170 - RETURN(); \  
1171 -} \  
1172 -PPC_OP(st##name) \  
1173 -{ \  
1174 - T0 += SPARAM(1); \  
1175 - op(T0, T1); \  
1176 - RETURN(); \  
1177 -} \  
1178 -PPC_IST_OPX(name, op);  
1179 -  
1180 -PPC_IST_OP(b, st8);  
1181 -PPC_IST_OP(h, st16);  
1182 -PPC_IST_OP(w, st32);  
1183 -  
1184 -/*** Integer load and store with byte reverse ***/  
1185 -PPC_ILD_OPX(hbr, ld16r);  
1186 -PPC_ILD_OPX(wbr, ld32r);  
1187 -PPC_IST_OPX(hbr, st16r);  
1188 -PPC_IST_OPX(wbr, st32r);  
1189 -  
1190 -/*** Integer load and store multiple ***/  
1191 -PPC_OP(lmw) 1271 +/* fadd - fadd. */
  1272 +PPC_OP(fadd)
1192 { 1273 {
1193 - do_lmw(PARAM(1), SPARAM(2) + T0); 1274 + FT0 += FT1;
1194 RETURN(); 1275 RETURN();
1195 } 1276 }
1196 1277
1197 -PPC_OP(stmw) 1278 +/* fadds - fadds. */
  1279 +PPC_OP(fadds)
1198 { 1280 {
1199 - do_stmw(PARAM(1), SPARAM(2) + T0); 1281 + FTS0 += FTS1;
1200 RETURN(); 1282 RETURN();
1201 } 1283 }
1202 1284
1203 -/*** Integer load and store strings ***/  
1204 -PPC_OP(lswi) 1285 +/* fsub - fsub. */
  1286 +PPC_OP(fsub)
1205 { 1287 {
1206 - do_lsw(PARAM(1), PARAM(2), T0); 1288 + FT0 -= FT1;
1207 RETURN(); 1289 RETURN();
1208 } 1290 }
1209 1291
1210 -PPC_OP(lswx) 1292 +/* fsubs - fsubs. */
  1293 +PPC_OP(fsubs)
1211 { 1294 {
1212 - do_lsw(PARAM(1), T0, T1 + T2); 1295 + FTS0 -= FTS1;
1213 RETURN(); 1296 RETURN();
1214 } 1297 }
1215 1298
1216 -PPC_OP(stswi_z) 1299 +/* fmul - fmul. */
  1300 +PPC_OP(fmul)
1217 { 1301 {
1218 - do_stsw(PARAM(1), PARAM(2), 0); 1302 + FT0 *= FT1;
1219 RETURN(); 1303 RETURN();
1220 } 1304 }
1221 1305
1222 -PPC_OP(stswi) 1306 +/* fmuls - fmuls. */
  1307 +PPC_OP(fmuls)
1223 { 1308 {
1224 - do_stsw(PARAM(1), PARAM(2), T0); 1309 + FTS0 *= FTS1;
1225 RETURN(); 1310 RETURN();
1226 } 1311 }
1227 1312
1228 -PPC_OP(stswx_z) 1313 +/* fdiv - fdiv. */
  1314 +PPC_OP(fdiv)
1229 { 1315 {
1230 - do_stsw(PARAM(1), T0, T1); 1316 + FT0 /= FT1;
1231 RETURN(); 1317 RETURN();
1232 } 1318 }
1233 1319
1234 -PPC_OP(stswx) 1320 +/* fdivs - fdivs. */
  1321 +PPC_OP(fdivs)
1235 { 1322 {
1236 - do_stsw(PARAM(1), T0, T1 + T2); 1323 + FTS0 /= FTS1;
1237 RETURN(); 1324 RETURN();
1238 } 1325 }
1239 1326
1240 -/* SPR */  
1241 -PPC_OP(load_spr) 1327 +/* fsqrt - fsqrt. */
  1328 +PPC_OP(fsqrt)
1242 { 1329 {
1243 - T0 = regs->spr[PARAM(1)]; 1330 + do_fsqrt();
  1331 + RETURN();
1244 } 1332 }
1245 1333
1246 -PPC_OP(store_spr) 1334 +/* fsqrts - fsqrts. */
  1335 +PPC_OP(fsqrts)
1247 { 1336 {
1248 - regs->spr[PARAM(1)] = T0; 1337 + do_fsqrts();
  1338 + RETURN();
1249 } 1339 }
1250 1340
1251 -/*** Floating-point store ***/  
1252 -  
1253 -PPC_OP(stfd_z_FT0) 1341 +/* fres - fres. */
  1342 +PPC_OP(fres)
1254 { 1343 {
1255 - stfq((void *)SPARAM(1), FT0); 1344 + do_fres();
  1345 + RETURN();
1256 } 1346 }
1257 1347
1258 -PPC_OP(stfd_FT0) 1348 +/* frsqrte - frsqrte. */
  1349 +PPC_OP(frsqrte)
1259 { 1350 {
1260 - T0 += SPARAM(1);  
1261 - stfq((void *)T0, FT0); 1351 + do_fsqrte();
  1352 + RETURN();
1262 } 1353 }
1263 1354
1264 -PPC_OP(stfdx_z_FT0) 1355 +/* fsel - fsel. */
  1356 +PPC_OP(fsel)
1265 { 1357 {
1266 - stfq((void *)T0, FT0); 1358 + do_fsel();
  1359 + RETURN();
1267 } 1360 }
1268 1361
1269 -PPC_OP(stfdx_FT0) 1362 +/*** Floating-Point multiply-and-add ***/
  1363 +/* fmadd - fmadd. */
  1364 +PPC_OP(fmadd)
1270 { 1365 {
1271 - T0 += T1;  
1272 - stfq((void *)T0, FT0); 1366 + FT0 = (FT0 * FT1) + FT2;
  1367 + RETURN();
1273 } 1368 }
1274 1369
1275 -PPC_OP(stfs_z_FT0) 1370 +/* fmadds - fmadds. */
  1371 +PPC_OP(fmadds)
1276 { 1372 {
1277 - float tmp = FT0;  
1278 - stfl((void *)SPARAM(1), tmp); 1373 + FTS0 = (FTS0 * FTS1) + FTS2;
  1374 + RETURN();
1279 } 1375 }
1280 1376
1281 -PPC_OP(stfs_FT0) 1377 +/* fmsub - fmsub. */
  1378 +PPC_OP(fmsub)
1282 { 1379 {
1283 - float tmp = FT0;  
1284 - T0 += SPARAM(1);  
1285 - stfl((void *)T0, tmp); 1380 + FT0 = (FT0 * FT1) - FT2;
  1381 + RETURN();
1286 } 1382 }
1287 1383
1288 -PPC_OP(stfsx_z_FT0) 1384 +/* fmsubs - fmsubs. */
  1385 +PPC_OP(fmsubs)
1289 { 1386 {
1290 - float tmp = FT0;  
1291 - stfl((void *)T0, tmp); 1387 + FTS0 = (FTS0 * FTS1) - FTS2;
  1388 + RETURN();
1292 } 1389 }
1293 1390
1294 -PPC_OP(stfsx_FT0) 1391 +/* fnmadd - fnmadd. - fnmadds - fnmadds. */
  1392 +PPC_OP(fnmadd)
1295 { 1393 {
1296 - float tmp = FT0;  
1297 - T0 += T1;  
1298 - stfl((void *)T0, tmp); 1394 + FT0 = -((FT0 * FT1) + FT2);
  1395 + RETURN();
1299 } 1396 }
1300 1397
1301 -/*** Floating-point load ***/  
1302 -PPC_OP(lfd_z_FT0) 1398 +/* fnmadds - fnmadds. */
  1399 +PPC_OP(fnmadds)
1303 { 1400 {
1304 - FT0 = ldfq((void *)SPARAM(1)); 1401 + FTS0 = -((FTS0 * FTS1) + FTS2);
  1402 + RETURN();
1305 } 1403 }
1306 1404
1307 -PPC_OP(lfd_FT0) 1405 +/* fnmsub - fnmsub. */
  1406 +PPC_OP(fnmsub)
1308 { 1407 {
1309 - T0 += SPARAM(1);  
1310 - FT0 = ldfq((void *)T0); 1408 + FT0 = -((FT0 * FT1) - FT2);
  1409 + RETURN();
1311 } 1410 }
1312 1411
1313 -PPC_OP(lfdx_z_FT0) 1412 +/* fnmsubs - fnmsubs. */
  1413 +PPC_OP(fnmsubs)
1314 { 1414 {
1315 - FT0 = ldfq((void *)T0); 1415 + FTS0 = -((FTS0 * FTS1) - FTS2);
  1416 + RETURN();
1316 } 1417 }
1317 1418
1318 -PPC_OP(lfdx_FT0) 1419 +/*** Floating-Point round & convert ***/
  1420 +/* frsp - frsp. */
  1421 +PPC_OP(frsp)
1319 { 1422 {
1320 - T0 += T1;  
1321 - FT0 = ldfq((void *)T0); 1423 + FT0 = FTS0;
  1424 + RETURN();
1322 } 1425 }
1323 1426
1324 -PPC_OP(lfs_z_FT0) 1427 +/* fctiw - fctiw. */
  1428 +PPC_OP(fctiw)
1325 { 1429 {
1326 - float tmp = ldfl((void *)SPARAM(1));  
1327 - FT0 = tmp; 1430 + do_fctiw();
  1431 + RETURN();
1328 } 1432 }
1329 1433
1330 -PPC_OP(lfs_FT0) 1434 +/* fctiwz - fctiwz. */
  1435 +PPC_OP(fctiwz)
1331 { 1436 {
1332 - float tmp;  
1333 - T0 += SPARAM(1);  
1334 - tmp = ldfl((void *)T0);  
1335 - FT0 = tmp; 1437 + do_fctiwz();
  1438 + RETURN();
1336 } 1439 }
1337 1440
1338 -PPC_OP(lfsx_z_FT0) 1441 +
  1442 +/*** Floating-Point compare ***/
  1443 +/* fcmpu */
  1444 +PPC_OP(fcmpu)
1339 { 1445 {
1340 - float tmp;  
1341 - tmp = ldfl((void *)T0);  
1342 - FT0 = tmp; 1446 + do_fcmpu();
  1447 + RETURN();
1343 } 1448 }
1344 1449
1345 -PPC_OP(lfsx_FT0) 1450 +/* fcmpo */
  1451 +PPC_OP(fcmpo)
1346 { 1452 {
1347 - float tmp;  
1348 - T0 += T1;  
1349 - tmp = ldfl((void *)T0);  
1350 - FT0 = tmp; 1453 + do_fcmpo();
  1454 + RETURN();
1351 } 1455 }
1352 1456
1353 -PPC_OP(lwarx_z) 1457 +/*** Floating-point move ***/
  1458 +/* fabs */
  1459 +PPC_OP(fabs)
1354 { 1460 {
1355 - T1 = ld32(T0);  
1356 - regs->reserve = T0; 1461 + do_fabs();
1357 RETURN(); 1462 RETURN();
1358 } 1463 }
1359 1464
1360 -PPC_OP(lwarx) 1465 +/* fnabs */
  1466 +PPC_OP(fnabs)
1361 { 1467 {
1362 - T0 += T1;  
1363 - T1 = ld32(T0);  
1364 - regs->reserve = T0; 1468 + do_fnabs();
1365 RETURN(); 1469 RETURN();
1366 } 1470 }
1367 1471
1368 -PPC_OP(stwcx_z) 1472 +/* fneg */
  1473 +PPC_OP(fneg)
1369 { 1474 {
1370 - if (regs->reserve != T0) {  
1371 - env->crf[0] = xer_ov;  
1372 - } else {  
1373 - st32(T0, T1);  
1374 - env->crf[0] = xer_ov | 0x02;  
1375 - }  
1376 - regs->reserve = 0; 1475 + FT0 = -FT0;
1377 RETURN(); 1476 RETURN();
1378 } 1477 }
1379 1478
1380 -PPC_OP(stwcx) 1479 +/* Load and store */
  1480 +#if defined(CONFIG_USER_ONLY)
  1481 +#define MEMSUFFIX _raw
  1482 +#include "op_mem.h"
  1483 +#else
  1484 +#define MEMSUFFIX _user
  1485 +#include "op_mem.h"
  1486 +
  1487 +#define MEMSUFFIX _kernel
  1488 +#include "op_mem.h"
  1489 +#endif
  1490 +
  1491 +/* Return from interrupt */
  1492 +PPC_OP(rfi)
1381 { 1493 {
1382 - T0 += T1;  
1383 - if (regs->reserve != (T0 & ~0x03)) {  
1384 - env->crf[0] = xer_ov;  
1385 - } else {  
1386 - st32(T0, T2);  
1387 - env->crf[0] = xer_ov | 0x02; 1494 + T0 = regs->spr[SRR1] & ~0xFFFF0000;
  1495 + do_store_msr();
  1496 + do_tlbia();
  1497 + dump_rfi();
  1498 + regs->nip = regs->spr[SRR0] & ~0x00000003;
  1499 + if (env->exceptions != 0) {
  1500 + do_check_exception_state();
1388 } 1501 }
1389 - regs->reserve = 0;  
1390 RETURN(); 1502 RETURN();
1391 } 1503 }
1392 1504
1393 -PPC_OP(dcbz_z) 1505 +/* Trap word */
  1506 +PPC_OP(tw)
1394 { 1507 {
1395 - do_dcbz(); 1508 + if ((Ts0 < Ts1 && (PARAM(1) & 0x10)) ||
  1509 + (Ts0 > Ts1 && (PARAM(1) & 0x08)) ||
  1510 + (Ts0 == Ts1 && (PARAM(1) & 0x04)) ||
  1511 + (T0 < T1 && (PARAM(1) & 0x02)) ||
  1512 + (T0 > T1 && (PARAM(1) & 0x01)))
  1513 + do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1396 RETURN(); 1514 RETURN();
1397 } 1515 }
1398 1516
1399 -PPC_OP(dcbz) 1517 +PPC_OP(twi)
1400 { 1518 {
1401 - T0 += T1;  
1402 - do_dcbz(); 1519 + if ((Ts0 < SPARAM(1) && (PARAM(2) & 0x10)) ||
  1520 + (Ts0 > SPARAM(1) && (PARAM(2) & 0x08)) ||
  1521 + (Ts0 == SPARAM(1) && (PARAM(2) & 0x04)) ||
  1522 + (T0 < (uint32_t)SPARAM(1) && (PARAM(2) & 0x02)) ||
  1523 + (T0 > (uint32_t)SPARAM(1) && (PARAM(2) & 0x01)))
  1524 + do_queue_exception_err(EXCP_PROGRAM, EXCP_TRAP);
1403 RETURN(); 1525 RETURN();
1404 } 1526 }
1405 1527
1406 /* Instruction cache block invalidate */ 1528 /* Instruction cache block invalidate */
1407 -PPC_OP(icbi_z) 1529 +PPC_OP(icbi)
1408 { 1530 {
1409 do_icbi(); 1531 do_icbi();
1410 RETURN(); 1532 RETURN();
1411 } 1533 }
1412 1534
1413 -PPC_OP(icbi) 1535 +/* tlbia */
  1536 +PPC_OP(tlbia)
1414 { 1537 {
1415 - T0 += T1;  
1416 - do_icbi(); 1538 + do_tlbia();
  1539 + RETURN();
  1540 +}
  1541 +
  1542 +/* tlbie */
  1543 +PPC_OP(tlbie)
  1544 +{
  1545 + do_tlbie();
1417 RETURN(); 1546 RETURN();
1418 } 1547 }
target-ppc/op_helper.c 0 โ†’ 100644
  1 +/*
  2 + * PPC emulation helpers for qemu.
  3 + *
  4 + * Copyright (c) 2003 Jocelyn Mayer
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +#include <math.h>
  21 +#include "exec.h"
  22 +
  23 +#if defined(CONFIG_USER_ONLY)
  24 +#define MEMSUFFIX _raw
  25 +#include "op_helper_mem.h"
  26 +#else
  27 +#define MEMSUFFIX _user
  28 +#include "op_helper_mem.h"
  29 +#define MEMSUFFIX _kernel
  30 +#include "op_helper_mem.h"
  31 +#endif
  32 +
  33 +/*****************************************************************************/
  34 +/* Exceptions processing helpers */
  35 +void do_queue_exception_err (uint32_t exception, int error_code)
  36 +{
  37 + /* Queue real PPC exceptions */
  38 + if (exception < EXCP_PPC_MAX) {
  39 + env->exceptions |= 1 << exception;
  40 + env->errors[exception] = error_code;
  41 + } else {
  42 + /* Preserve compatibility with qemu core */
  43 + env->exceptions |= 1;
  44 + env->exception_index = exception;
  45 + env->error_code = error_code;
  46 + }
  47 +}
  48 +
  49 +void do_queue_exception (uint32_t exception)
  50 +{
  51 + do_queue_exception_err(exception, 0);
  52 +}
  53 +
  54 +void do_check_exception_state (void)
  55 +{
  56 + if ((env->exceptions & 1) == 1 || check_exception_state(env)) {
  57 + env->exceptions &= ~1;
  58 + cpu_loop_exit();
  59 + }
  60 +}
  61 +
  62 +/*****************************************************************************/
  63 +/* Helpers for "fat" micro operations */
  64 +/* Special registers load and store */
  65 +void do_load_cr (void)
  66 +{
  67 + T0 = (env->crf[0] << 28) |
  68 + (env->crf[1] << 24) |
  69 + (env->crf[2] << 20) |
  70 + (env->crf[3] << 16) |
  71 + (env->crf[4] << 12) |
  72 + (env->crf[5] << 8) |
  73 + (env->crf[6] << 4) |
  74 + (env->crf[7] << 0);
  75 +}
  76 +
  77 +void do_store_cr (uint32_t mask)
  78 +{
  79 + int i, sh;
  80 +
  81 + for (i = 0, sh = 7; i < 8; i++, sh --) {
  82 + if (mask & (1 << sh))
  83 + env->crf[i] = (T0 >> (sh * 4)) & 0xF;
  84 + }
  85 +}
  86 +
  87 +void do_load_xer (void)
  88 +{
  89 + T0 = (xer_so << XER_SO) |
  90 + (xer_ov << XER_OV) |
  91 + (xer_ca << XER_CA) |
  92 + (xer_bc << XER_BC);
  93 +}
  94 +
  95 +void do_store_xer (void)
  96 +{
  97 + xer_so = (T0 >> XER_SO) & 0x01;
  98 + xer_ov = (T0 >> XER_OV) & 0x01;
  99 + xer_ca = (T0 >> XER_CA) & 0x01;
  100 + xer_bc = (T0 >> XER_BC) & 0x1f;
  101 +}
  102 +
  103 +void do_load_msr (void)
  104 +{
  105 + T0 = (msr_pow << MSR_POW) |
  106 + (msr_ile << MSR_ILE) |
  107 + (msr_ee << MSR_EE) |
  108 + (msr_pr << MSR_PR) |
  109 + (msr_fp << MSR_FP) |
  110 + (msr_me << MSR_ME) |
  111 + (msr_fe0 << MSR_FE0) |
  112 + (msr_se << MSR_SE) |
  113 + (msr_be << MSR_BE) |
  114 + (msr_fe1 << MSR_FE1) |
  115 + (msr_ip << MSR_IP) |
  116 + (msr_ir << MSR_IR) |
  117 + (msr_dr << MSR_DR) |
  118 + (msr_ri << MSR_RI) |
  119 + (msr_le << MSR_LE);
  120 +}
  121 +
  122 +void do_store_msr (void)
  123 +{
  124 + if (((T0 >> MSR_IR) & 0x01) != msr_ir ||
  125 + ((T0 >> MSR_DR) & 0x01) != msr_dr ||
  126 + ((T0 >> MSR_PR) & 0x01) != msr_pr) {
  127 + /* Flush all tlb when changing translation mode or privilege level */
  128 + do_tlbia();
  129 + }
  130 +#if 0
  131 + if ((T0 >> MSR_IP) & 0x01) {
  132 + printf("Halting CPU. Stop emulation\n");
  133 + do_queue_exception(EXCP_HLT);
  134 + cpu_loop_exit();
  135 + }
  136 +#endif
  137 + msr_pow = (T0 >> MSR_POW) & 0x03;
  138 + msr_ile = (T0 >> MSR_ILE) & 0x01;
  139 + msr_ee = (T0 >> MSR_EE) & 0x01;
  140 + msr_pr = (T0 >> MSR_PR) & 0x01;
  141 + msr_fp = (T0 >> MSR_FP) & 0x01;
  142 + msr_me = (T0 >> MSR_ME) & 0x01;
  143 + msr_fe0 = (T0 >> MSR_FE0) & 0x01;
  144 + msr_se = (T0 >> MSR_SE) & 0x01;
  145 + msr_be = (T0 >> MSR_BE) & 0x01;
  146 + msr_fe1 = (T0 >> MSR_FE1) & 0x01;
  147 + msr_ip = (T0 >> MSR_IP) & 0x01;
  148 + msr_ir = (T0 >> MSR_IR) & 0x01;
  149 + msr_dr = (T0 >> MSR_DR) & 0x01;
  150 + msr_ri = (T0 >> MSR_RI) & 0x01;
  151 + msr_le = (T0 >> MSR_LE) & 0x01;
  152 +}
  153 +
  154 +/* shift right arithmetic helper */
  155 +void do_sraw (void)
  156 +{
  157 + int32_t ret;
  158 +
  159 + xer_ca = 0;
  160 + if (T1 & 0x20) {
  161 + ret = (-1) * (T0 >> 31);
  162 + if (ret < 0)
  163 + xer_ca = 1;
  164 + } else {
  165 + ret = (int32_t)T0 >> (T1 & 0x1f);
  166 + if (ret < 0 && ((int32_t)T0 & ((1 << T1) - 1)) != 0)
  167 + xer_ca = 1;
  168 + }
  169 + (int32_t)T0 = ret;
  170 +}
  171 +
  172 +/* Floating point operations helpers */
  173 +void do_load_fpscr (void)
  174 +{
  175 + /* The 32 MSB of the target fpr are undefined.
  176 + * They'll be zero...
  177 + */
  178 + union {
  179 + double d;
  180 + struct {
  181 + uint32_t u[2];
  182 + } s;
  183 + } u;
  184 + int i;
  185 +
  186 + u.s.u[0] = 0;
  187 + u.s.u[1] = 0;
  188 + for (i = 0; i < 8; i++)
  189 + u.s.u[1] |= env->fpscr[i] << (4 * i);
  190 + FT0 = u.d;
  191 +}
  192 +
  193 +void do_store_fpscr (uint32_t mask)
  194 +{
  195 + /*
  196 + * We use only the 32 LSB of the incoming fpr
  197 + */
  198 + union {
  199 + double d;
  200 + struct {
  201 + uint32_t u[2];
  202 + } s;
  203 + } u;
  204 + int i;
  205 +
  206 + u.d = FT0;
  207 + if (mask & 0x80)
  208 + env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[1] >> 28) & ~0x9);
  209 + for (i = 1; i < 7; i++) {
  210 + if (mask & (1 << (7 - i)))
  211 + env->fpscr[i] = (u.s.u[1] >> (4 * (7 - i))) & 0xF;
  212 + }
  213 + /* TODO: update FEX & VX */
  214 + /* Set rounding mode */
  215 + switch (env->fpscr[0] & 0x3) {
  216 + case 0:
  217 + /* Best approximation (round to nearest) */
  218 + fesetround(FE_TONEAREST);
  219 + break;
  220 + case 1:
  221 + /* Smaller magnitude (round toward zero) */
  222 + fesetround(FE_TOWARDZERO);
  223 + break;
  224 + case 2:
  225 + /* Round toward +infinite */
  226 + fesetround(FE_UPWARD);
  227 + break;
  228 + case 3:
  229 + /* Round toward -infinite */
  230 + fesetround(FE_DOWNWARD);
  231 + break;
  232 + }
  233 +}
  234 +
  235 +void do_fctiw (void)
  236 +{
  237 + union {
  238 + double d;
  239 + uint64_t i;
  240 + } *p = (void *)&FT1;
  241 +
  242 + if (FT0 > (double)0x7FFFFFFF)
  243 + p->i = 0x7FFFFFFFULL << 32;
  244 + else if (FT0 < -(double)0x80000000)
  245 + p->i = 0x80000000ULL << 32;
  246 + else
  247 + p->i = 0;
  248 + p->i |= (uint32_t)FT0;
  249 + FT0 = p->d;
  250 +}
  251 +
  252 +void do_fctiwz (void)
  253 +{
  254 + union {
  255 + double d;
  256 + uint64_t i;
  257 + } *p = (void *)&FT1;
  258 + int cround = fegetround();
  259 +
  260 + fesetround(FE_TOWARDZERO);
  261 + if (FT0 > (double)0x7FFFFFFF)
  262 + p->i = 0x7FFFFFFFULL << 32;
  263 + else if (FT0 < -(double)0x80000000)
  264 + p->i = 0x80000000ULL << 32;
  265 + else
  266 + p->i = 0;
  267 + p->i |= (uint32_t)FT0;
  268 + FT0 = p->d;
  269 + fesetround(cround);
  270 +}
  271 +
  272 +void do_fsqrt (void)
  273 +{
  274 + FT0 = sqrt(FT0);
  275 +}
  276 +
  277 +void do_fsqrts (void)
  278 +{
  279 + FT0 = (float)sqrt((float)FT0);
  280 +}
  281 +
  282 +void do_fres (void)
  283 +{
  284 + FT0 = 1.0 / FT0;
  285 +}
  286 +
  287 +void do_fsqrte (void)
  288 +{
  289 + FT0 = 1.0 / sqrt(FT0);
  290 +}
  291 +
  292 +void do_fsel (void)
  293 +{
  294 + if (FT0 >= 0)
  295 + FT0 = FT2;
  296 + else
  297 + FT0 = FT1;
  298 +}
  299 +
  300 +void do_fcmpu (void)
  301 +{
  302 + env->fpscr[4] &= ~0x1;
  303 + if (isnan(FT0) || isnan(FT1)) {
  304 + T0 = 0x01;
  305 + env->fpscr[4] |= 0x1;
  306 + env->fpscr[6] |= 0x1;
  307 + } else if (FT0 < FT1) {
  308 + T0 = 0x08;
  309 + } else if (FT0 > FT1) {
  310 + T0 = 0x04;
  311 + } else {
  312 + T0 = 0x02;
  313 + }
  314 + env->fpscr[3] |= T0;
  315 +}
  316 +
  317 +void do_fcmpo (void)
  318 +{
  319 + env->fpscr[4] &= ~0x1;
  320 + if (isnan(FT0) || isnan(FT1)) {
  321 + T0 = 0x01;
  322 + env->fpscr[4] |= 0x1;
  323 + /* I don't know how to test "quiet" nan... */
  324 + if (0 /* || ! quiet_nan(...) */) {
  325 + env->fpscr[6] |= 0x1;
  326 + if (!(env->fpscr[1] & 0x8))
  327 + env->fpscr[4] |= 0x8;
  328 + } else {
  329 + env->fpscr[4] |= 0x8;
  330 + }
  331 + } else if (FT0 < FT1) {
  332 + T0 = 0x08;
  333 + } else if (FT0 > FT1) {
  334 + T0 = 0x04;
  335 + } else {
  336 + T0 = 0x02;
  337 + }
  338 + env->fpscr[3] |= T0;
  339 +}
  340 +
  341 +void do_fabs (void)
  342 +{
  343 + FT0 = fabsl(FT0);
  344 +}
  345 +
  346 +void do_fnabs (void)
  347 +{
  348 + FT0 = -fabsl(FT0);
  349 +}
  350 +
  351 +/* Instruction cache invalidation helper */
  352 +void do_icbi (void)
  353 +{
  354 + // tb_invalidate_page(T0);
  355 +}
  356 +
  357 +/* TLB invalidation helpers */
  358 +void do_tlbia (void)
  359 +{
  360 + tlb_flush(env);
  361 +}
  362 +
  363 +void do_tlbie (void)
  364 +{
  365 + tlb_flush_page(env, T0);
  366 +}
  367 +
  368 +/*****************************************************************************/
  369 +/* Special helpers for debug */
  370 +void dump_rfi (void)
  371 +{
  372 +#if 0
  373 + printf("Return from interrupt\n");
  374 + printf("nip=0x%08x LR=0x%08x CTR=0x%08x MSR=0x%08x\n",
  375 + env->nip, env->lr, env->ctr,
  376 + (msr_pow << MSR_POW) | (msr_ile << MSR_ILE) | (msr_ee << MSR_EE) |
  377 + (msr_pr << MSR_PR) | (msr_fp << MSR_FP) | (msr_me << MSR_ME) |
  378 + (msr_fe0 << MSR_FE0) | (msr_se << MSR_SE) | (msr_be << MSR_BE) |
  379 + (msr_fe1 << MSR_FE1) | (msr_ip << MSR_IP) | (msr_ir << MSR_IR) |
  380 + (msr_dr << MSR_DR) | (msr_ri << MSR_RI) | (msr_le << MSR_LE));
  381 + {
  382 + int i;
  383 + for (i = 0; i < 32; i++) {
  384 + if ((i & 7) == 0)
  385 + printf("GPR%02d:", i);
  386 + printf(" %08x", env->gpr[i]);
  387 + if ((i & 7) == 7)
  388 + printf("\n");
  389 + }
  390 + printf("CR: 0x");
  391 + for (i = 0; i < 8; i++)
  392 + printf("%01x", env->crf[i]);
  393 + printf(" [");
  394 + for (i = 0; i < 8; i++) {
  395 + char a = '-';
  396 + if (env->crf[i] & 0x08)
  397 + a = 'L';
  398 + else if (env->crf[i] & 0x04)
  399 + a = 'G';
  400 + else if (env->crf[i] & 0x02)
  401 + a = 'E';
  402 + printf(" %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
  403 + }
  404 + printf(" ] ");
  405 + }
  406 + printf("TB: 0x%08x %08x\n", env->tb[1], env->tb[0]);
  407 + printf("SRR0 0x%08x SRR1 0x%08x\n", env->spr[SRR0], env->spr[SRR1]);
  408 +#endif
  409 +}
  410 +
  411 +void dump_store_sr (int srnum)
  412 +{
  413 +#if 0
  414 + printf("%s: reg=%d 0x%08x\n", __func__, srnum, T0);
  415 +#endif
  416 +}
  417 +
  418 +static void _dump_store_bat (char ID, int ul, int nr)
  419 +{
  420 + printf("Set %cBAT%d%c to 0x%08x (0x%08x)\n",
  421 + ID, nr, ul == 0 ? 'u' : 'l', T0, env->nip);
  422 +}
  423 +
  424 +void dump_store_ibat (int ul, int nr)
  425 +{
  426 + _dump_store_bat('I', ul, nr);
  427 +}
  428 +
  429 +void dump_store_dbat (int ul, int nr)
  430 +{
  431 + _dump_store_bat('D', ul, nr);
  432 +}
  433 +
  434 +void dump_store_tb (int ul)
  435 +{
  436 + printf("Set TB%c to 0x%08x\n", ul == 0 ? 'L' : 'U', T0);
  437 +}
  438 +
  439 +void dump_update_tb(uint32_t param)
  440 +{
  441 +#if 0
  442 + printf("Update TB: 0x%08x + %d => 0x%08x\n", T1, param, T0);
  443 +#endif
  444 +}
  445 +
target-ppc/op_helper_mem.h 0 โ†’ 100644
  1 +void glue(do_lsw, MEMSUFFIX) (int dst)
  2 +{
  3 + uint32_t tmp;
  4 + int sh;
  5 +
  6 + if (loglevel > 0) {
  7 + fprintf(logfile, "%s: addr=0x%08x count=%d reg=%d\n",
  8 + __func__, T0, T1, dst);
  9 + }
  10 + for (; T1 > 3; T1 -= 4, T0 += 4) {
  11 + ugpr(dst++) = glue(_ldl, MEMSUFFIX)((void *)T0, ACCESS_INT);
  12 + if (dst == 32)
  13 + dst = 0;
  14 + }
  15 + if (T1 > 0) {
  16 + tmp = 0;
  17 + for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) {
  18 + tmp |= glue(_ldub, MEMSUFFIX)((void *)T0, ACCESS_INT) << sh;
  19 + }
  20 + ugpr(dst) = tmp;
  21 + }
  22 +}
  23 +
  24 +void glue(do_stsw, MEMSUFFIX) (int src)
  25 +{
  26 + int sh;
  27 +
  28 + if (loglevel > 0) {
  29 + fprintf(logfile, "%s: addr=0x%08x count=%d reg=%d\n",
  30 + __func__, T0, T1, src);
  31 + }
  32 + for (; T1 > 3; T1 -= 4, T0 += 4) {
  33 + glue(_stl, MEMSUFFIX)((void *)T0, ugpr(src++), ACCESS_INT);
  34 + if (src == 32)
  35 + src = 0;
  36 + }
  37 + if (T1 > 0) {
  38 + for (sh = 24; T1 > 0; T1--, T0++, sh -= 8)
  39 + glue(_stb, MEMSUFFIX)((void *)T0, (ugpr(src) >> sh) & 0xFF,
  40 + ACCESS_INT);
  41 + }
  42 +}
  43 +
  44 +#undef MEMSUFFIX
target-ppc/op_mem.h 0 โ†’ 100644
  1 +/* External helpers */
  2 +void glue(do_lsw, MEMSUFFIX) (int dst);
  3 +void glue(do_stsw, MEMSUFFIX) (int src);
  4 +
  5 +/* Internal helpers for sign extension and byte-reverse */
  6 +static inline uint32_t glue(_ld16x, MEMSUFFIX) (void *EA, int type)
  7 +{
  8 + return s_ext16(glue(_lduw, MEMSUFFIX)(EA, type));
  9 +}
  10 +
  11 +static inline uint16_t glue(_ld16r, MEMSUFFIX) (void *EA, int type)
  12 +{
  13 + uint16_t tmp = glue(_lduw, MEMSUFFIX)(EA, type);
  14 + return ((tmp & 0xFF00) >> 8) | ((tmp & 0x00FF) << 8);
  15 +}
  16 +
  17 +static inline uint32_t glue(_ld32r, MEMSUFFIX) (void *EA, int type)
  18 +{
  19 + uint32_t tmp = glue(_ldl, MEMSUFFIX)(EA, type);
  20 + return ((tmp & 0xFF000000) >> 24) | ((tmp & 0x00FF0000) >> 8) |
  21 + ((tmp & 0x0000FF00) << 8) | ((tmp & 0x000000FF) << 24);
  22 +}
  23 +
  24 +static inline void glue(_st16r, MEMSUFFIX) (void *EA, uint16_t data, int type)
  25 +{
  26 + uint16_t tmp = ((data & 0xFF00) >> 8) | ((data & 0x00FF) << 8);
  27 + glue(_stw, MEMSUFFIX)(EA, tmp, type);
  28 +}
  29 +
  30 +static inline void glue(_st32r, MEMSUFFIX) (void *EA, uint32_t data, int type)
  31 +{
  32 + uint32_t tmp = ((data & 0xFF000000) >> 24) | ((data & 0x00FF0000) >> 8) |
  33 + ((data & 0x0000FF00) << 8) | ((data & 0x000000FF) << 24);
  34 + glue(_stl, MEMSUFFIX)(EA, tmp, type);
  35 +}
  36 +
  37 +/*** Integer load ***/
  38 +#define PPC_LD_OP(name, op) \
  39 +PPC_OP(glue(glue(l, name), MEMSUFFIX)) \
  40 +{ \
  41 + T1 = glue(op, MEMSUFFIX)((void *)T0, ACCESS_INT); \
  42 + RETURN(); \
  43 +}
  44 +
  45 +#define PPC_ST_OP(name, op) \
  46 +PPC_OP(glue(glue(st, name), MEMSUFFIX)) \
  47 +{ \
  48 + glue(op, MEMSUFFIX)((void *)T0, T1, ACCESS_INT); \
  49 + RETURN(); \
  50 +}
  51 +
  52 +PPC_LD_OP(bz, _ldub);
  53 +PPC_LD_OP(ha, _ld16x);
  54 +PPC_LD_OP(hz, _lduw);
  55 +PPC_LD_OP(wz, _ldl);
  56 +
  57 +/*** Integer store ***/
  58 +PPC_ST_OP(b, _stb);
  59 +PPC_ST_OP(h, _stw);
  60 +PPC_ST_OP(w, _stl);
  61 +
  62 +/*** Integer load and store with byte reverse ***/
  63 +PPC_LD_OP(hbr, _ld16r);
  64 +PPC_LD_OP(wbr, _ld32r);
  65 +PPC_ST_OP(hbr, _st16r);
  66 +PPC_ST_OP(wbr, _st32r);
  67 +
  68 +/*** Integer load and store multiple ***/
  69 +PPC_OP(glue(lmw, MEMSUFFIX))
  70 +{
  71 + int dst = PARAM(1);
  72 +
  73 + for (; dst < 32; dst++, T0 += 4) {
  74 + ugpr(dst) = glue(_ldl, MEMSUFFIX)((void *)T0, ACCESS_INT);
  75 + }
  76 + RETURN();
  77 +}
  78 +
  79 +PPC_OP(glue(stmw, MEMSUFFIX))
  80 +{
  81 + int src = PARAM(1);
  82 +
  83 + for (; src < 32; src++, T0 += 4) {
  84 + glue(_stl, MEMSUFFIX)((void *)T0, ugpr(src), ACCESS_INT);
  85 + }
  86 + RETURN();
  87 +}
  88 +
  89 +/*** Integer load and store strings ***/
  90 +PPC_OP(glue(lswi, MEMSUFFIX))
  91 +{
  92 + glue(do_lsw, MEMSUFFIX)(PARAM(1));
  93 + RETURN();
  94 +}
  95 +
  96 +/* PPC32 specification says we must generate an exception if
  97 + * rA is in the range of registers to be loaded.
  98 + * In an other hand, IBM says this is valid, but rA won't be loaded.
  99 + * For now, I'll follow the spec...
  100 + */
  101 +PPC_OP(glue(lswx, MEMSUFFIX))
  102 +{
  103 + if (T1 > 0) {
  104 + if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) ||
  105 + (PARAM(1) < PARAM(3) && (PARAM(1) + T1) > PARAM(3))) {
  106 + do_queue_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
  107 + do_process_exceptions();
  108 + } else {
  109 + glue(do_lsw, MEMSUFFIX)(PARAM(1));
  110 + }
  111 + }
  112 + RETURN();
  113 +}
  114 +
  115 +PPC_OP(glue(stsw, MEMSUFFIX))
  116 +{
  117 + glue(do_stsw, MEMSUFFIX)(PARAM(1));
  118 + RETURN();
  119 +}
  120 +
  121 +/*** Floating-point store ***/
  122 +#define PPC_STF_OP(name, op) \
  123 +PPC_OP(glue(glue(st, name), MEMSUFFIX)) \
  124 +{ \
  125 + glue(op, MEMSUFFIX)((void *)T0, FT1); \
  126 + RETURN(); \
  127 +}
  128 +
  129 +PPC_STF_OP(fd, stfq);
  130 +PPC_STF_OP(fs, stfl);
  131 +
  132 +/*** Floating-point load ***/
  133 +#define PPC_LDF_OP(name, op) \
  134 +PPC_OP(glue(glue(l, name), MEMSUFFIX)) \
  135 +{ \
  136 + FT1 = glue(op, MEMSUFFIX)((void *)T0); \
  137 + RETURN(); \
  138 +}
  139 +
  140 +PPC_LDF_OP(fd, ldfq);
  141 +PPC_LDF_OP(fs, ldfl);
  142 +
  143 +/* Store with reservation */
  144 +PPC_OP(glue(stwcx, MEMSUFFIX))
  145 +{
  146 + if (T0 & 0x03) {
  147 + do_queue_exception(EXCP_ALIGN);
  148 + do_process_exceptions();
  149 + } else {
  150 + if (regs->reserve != T0) {
  151 + env->crf[0] = xer_ov;
  152 + } else {
  153 + glue(_stl, MEMSUFFIX)((void *)T0, T1, ACCESS_RES);
  154 + env->crf[0] = xer_ov | 0x02;
  155 + }
  156 + }
  157 + regs->reserve = 0;
  158 + RETURN();
  159 +}
  160 +
  161 +PPC_OP(glue(dcbz, MEMSUFFIX))
  162 +{
  163 + glue(_stl, MEMSUFFIX)((void *)(T0 + 0x00), 0, ACCESS_INT);
  164 + glue(_stl, MEMSUFFIX)((void *)(T0 + 0x04), 0, ACCESS_INT);
  165 + glue(_stl, MEMSUFFIX)((void *)(T0 + 0x08), 0, ACCESS_INT);
  166 + glue(_stl, MEMSUFFIX)((void *)(T0 + 0x0C), 0, ACCESS_INT);
  167 + glue(_stl, MEMSUFFIX)((void *)(T0 + 0x10), 0, ACCESS_INT);
  168 + glue(_stl, MEMSUFFIX)((void *)(T0 + 0x14), 0, ACCESS_INT);
  169 + glue(_stl, MEMSUFFIX)((void *)(T0 + 0x18), 0, ACCESS_INT);
  170 + glue(_stl, MEMSUFFIX)((void *)(T0 + 0x1C), 0, ACCESS_INT);
  171 + RETURN();
  172 +}
  173 +
  174 +/* External access */
  175 +PPC_OP(glue(eciwx, MEMSUFFIX))
  176 +{
  177 + T1 = glue(_ldl, MEMSUFFIX)((void *)T0, ACCESS_EXT);
  178 + RETURN();
  179 +}
  180 +
  181 +PPC_OP(glue(ecowx, MEMSUFFIX))
  182 +{
  183 + glue(_stl, MEMSUFFIX)((void *)T0, T1, ACCESS_EXT);
  184 + RETURN();
  185 +}
  186 +
  187 +#undef MEMSUFFIX
target-ppc/op_template.h
@@ -18,56 +18,67 @@ @@ -18,56 +18,67 @@
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 19 */
20 20
  21 +/* General purpose registers moves */
21 void OPPROTO glue(op_load_gpr_T0_gpr, REG)(void) 22 void OPPROTO glue(op_load_gpr_T0_gpr, REG)(void)
22 { 23 {
23 T0 = regs->gpr[REG]; 24 T0 = regs->gpr[REG];
  25 + RETURN();
24 } 26 }
25 27
26 void OPPROTO glue(op_load_gpr_T1_gpr, REG)(void) 28 void OPPROTO glue(op_load_gpr_T1_gpr, REG)(void)
27 { 29 {
28 T1 = regs->gpr[REG]; 30 T1 = regs->gpr[REG];
  31 + RETURN();
29 } 32 }
30 33
31 void OPPROTO glue(op_load_gpr_T2_gpr, REG)(void) 34 void OPPROTO glue(op_load_gpr_T2_gpr, REG)(void)
32 { 35 {
33 T2 = regs->gpr[REG]; 36 T2 = regs->gpr[REG];
  37 + RETURN();
34 } 38 }
35 39
36 void OPPROTO glue(op_store_T0_gpr_gpr, REG)(void) 40 void OPPROTO glue(op_store_T0_gpr_gpr, REG)(void)
37 { 41 {
38 regs->gpr[REG] = T0; 42 regs->gpr[REG] = T0;
  43 + RETURN();
39 } 44 }
40 45
41 void OPPROTO glue(op_store_T1_gpr_gpr, REG)(void) 46 void OPPROTO glue(op_store_T1_gpr_gpr, REG)(void)
42 { 47 {
43 regs->gpr[REG] = T1; 48 regs->gpr[REG] = T1;
  49 + RETURN();
44 } 50 }
45 51
46 void OPPROTO glue(op_store_T2_gpr_gpr, REG)(void) 52 void OPPROTO glue(op_store_T2_gpr_gpr, REG)(void)
47 { 53 {
48 regs->gpr[REG] = T2; 54 regs->gpr[REG] = T2;
  55 + RETURN();
49 } 56 }
50 57
51 #if REG <= 7 58 #if REG <= 7
52 - 59 +/* Condition register moves */
53 void OPPROTO glue(op_load_crf_T0_crf, REG)(void) 60 void OPPROTO glue(op_load_crf_T0_crf, REG)(void)
54 { 61 {
55 T0 = regs->crf[REG]; 62 T0 = regs->crf[REG];
  63 + RETURN();
56 } 64 }
57 65
58 void OPPROTO glue(op_load_crf_T1_crf, REG)(void) 66 void OPPROTO glue(op_load_crf_T1_crf, REG)(void)
59 { 67 {
60 T1 = regs->crf[REG]; 68 T1 = regs->crf[REG];
  69 + RETURN();
61 } 70 }
62 71
63 void OPPROTO glue(op_store_T0_crf_crf, REG)(void) 72 void OPPROTO glue(op_store_T0_crf_crf, REG)(void)
64 { 73 {
65 regs->crf[REG] = T0; 74 regs->crf[REG] = T0;
  75 + RETURN();
66 } 76 }
67 77
68 void OPPROTO glue(op_store_T1_crf_crf, REG)(void) 78 void OPPROTO glue(op_store_T1_crf_crf, REG)(void)
69 { 79 {
70 regs->crf[REG] = T1; 80 regs->crf[REG] = T1;
  81 + RETURN();
71 } 82 }
72 83
73 /* Floating point condition and status register moves */ 84 /* Floating point condition and status register moves */
@@ -117,8 +128,6 @@ void OPPROTO glue(op_clear_fpscr_fpscr, REG)(void) @@ -117,8 +128,6 @@ void OPPROTO glue(op_clear_fpscr_fpscr, REG)(void)
117 128
118 #endif /* REG <= 7 */ 129 #endif /* REG <= 7 */
119 130
120 -/* float moves */  
121 -  
122 /* floating point registers moves */ 131 /* floating point registers moves */
123 void OPPROTO glue(op_load_fpr_FT0_fpr, REG)(void) 132 void OPPROTO glue(op_load_fpr_FT0_fpr, REG)(void)
124 { 133 {
@@ -156,4 +165,22 @@ void OPPROTO glue(op_store_FT2_fpr_fpr, REG)(void) @@ -156,4 +165,22 @@ void OPPROTO glue(op_store_FT2_fpr_fpr, REG)(void)
156 RETURN(); 165 RETURN();
157 } 166 }
158 167
  168 +#if REG <= 15
  169 +/* Segment register moves */
  170 +void OPPROTO glue(op_load_sr, REG)(void)
  171 +{
  172 + T0 = env->sr[REG];
  173 + RETURN();
  174 +}
  175 +
  176 +void OPPROTO glue(op_store_sr, REG)(void)
  177 +{
  178 +#if defined (DEBUG_OP)
  179 + dump_store_sr(REG);
  180 +#endif
  181 + env->sr[REG] = T0;
  182 + RETURN();
  183 +}
  184 +#endif
  185 +
159 #undef REG 186 #undef REG
target-ppc/translate.c
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
24 24
25 //#define DO_SINGLE_STEP 25 //#define DO_SINGLE_STEP
26 //#define DO_STEP_FLUSH 26 //#define DO_STEP_FLUSH
  27 +//#define DEBUG_DISAS
27 28
28 enum { 29 enum {
29 #define DEF(s, n, copy_size) INDEX_op_ ## s, 30 #define DEF(s, n, copy_size) INDEX_op_ ## s,
@@ -37,41 +38,49 @@ static uint32_t *gen_opparam_ptr; @@ -37,41 +38,49 @@ static uint32_t *gen_opparam_ptr;
37 38
38 #include "gen-op.h" 39 #include "gen-op.h"
39 40
40 -typedef void (GenOpFunc)(void);  
41 -typedef void (GenOpFunc1)(long);  
42 -typedef void (GenOpFunc2)(long, long);  
43 -typedef void (GenOpFunc3)(long, long, long);  
44 -  
45 #define GEN8(func, NAME) \ 41 #define GEN8(func, NAME) \
46 -static GenOpFunc *NAME ## _table [8] = {\  
47 -NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,\  
48 -NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,\  
49 -};\  
50 -static inline void func(int n)\  
51 -{\  
52 - NAME ## _table[n]();\ 42 +static GenOpFunc *NAME ## _table [8] = { \
  43 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  44 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  45 +}; \
  46 +static inline void func(int n) \
  47 +{ \
  48 + NAME ## _table[n](); \
  49 +}
  50 +
  51 +#define GEN16(func, NAME) \
  52 +static GenOpFunc *NAME ## _table [16] = { \
  53 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  54 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  55 +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
  56 +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
  57 +}; \
  58 +static inline void func(int n) \
  59 +{ \
  60 + NAME ## _table[n](); \
53 } 61 }
54 62
55 #define GEN32(func, NAME) \ 63 #define GEN32(func, NAME) \
56 -static GenOpFunc *NAME ## _table [32] = {\  
57 -NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,\  
58 -NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,\  
59 -NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,\  
60 -NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,\  
61 -NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,\  
62 -NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,\  
63 -NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,\  
64 -NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,\  
65 -};\  
66 -static inline void func(int n)\  
67 -{\  
68 - NAME ## _table[n]();\  
69 -}  
70 -  
71 -GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf)  
72 -GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf)  
73 -GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf)  
74 -GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf) 64 +static GenOpFunc *NAME ## _table [32] = { \
  65 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  66 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  67 +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
  68 +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
  69 +NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
  70 +NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
  71 +NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
  72 +NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
  73 +}; \
  74 +static inline void func(int n) \
  75 +{ \
  76 + NAME ## _table[n](); \
  77 +}
  78 +
  79 +/* Condition register moves */
  80 +GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
  81 +GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
  82 +GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
  83 +GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
75 84
76 /* Floating point condition and status register moves */ 85 /* Floating point condition and status register moves */
77 GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr); 86 GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr);
@@ -92,13 +101,18 @@ static inline void gen_op_store_T0_fpscri(int n, uint8_t param) @@ -92,13 +101,18 @@ static inline void gen_op_store_T0_fpscri(int n, uint8_t param)
92 (*gen_op_store_T0_fpscri_fpscr_table[n])(param); 101 (*gen_op_store_T0_fpscri_fpscr_table[n])(param);
93 } 102 }
94 103
95 -GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr)  
96 -GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr)  
97 -GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr) 104 +/* Segment register moves */
  105 +GEN16(gen_op_load_sr, gen_op_load_sr);
  106 +GEN16(gen_op_store_sr, gen_op_store_sr);
98 107
99 -GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr)  
100 -GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr)  
101 -GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr) 108 +/* General purpose registers moves */
  109 +GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
  110 +GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
  111 +GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
  112 +
  113 +GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
  114 +GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
  115 +GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
102 116
103 /* floating point registers moves */ 117 /* floating point registers moves */
104 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr); 118 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
@@ -115,53 +129,51 @@ typedef struct DisasContext { @@ -115,53 +129,51 @@ typedef struct DisasContext {
115 struct TranslationBlock *tb; 129 struct TranslationBlock *tb;
116 uint32_t *nip; 130 uint32_t *nip;
117 uint32_t opcode; 131 uint32_t opcode;
118 - int exception;  
119 - int retcode;  
120 - /* Time base */ 132 + uint32_t exception;
  133 + /* Time base offset */
121 uint32_t tb_offset; 134 uint32_t tb_offset;
  135 + /* Decrementer offset */
  136 + uint32_t decr_offset;
  137 + /* Execution mode */
  138 +#if !defined(CONFIG_USER_ONLY)
122 int supervisor; 139 int supervisor;
  140 +#endif
  141 + /* Routine used to access memory */
  142 + int mem_idx;
123 } DisasContext; 143 } DisasContext;
124 144
125 typedef struct opc_handler_t { 145 typedef struct opc_handler_t {
126 /* invalid bits */ 146 /* invalid bits */
127 uint32_t inval; 147 uint32_t inval;
  148 + /* instruction type */
  149 + uint32_t type;
128 /* handler */ 150 /* handler */
129 void (*handler)(DisasContext *ctx); 151 void (*handler)(DisasContext *ctx);
130 } opc_handler_t; 152 } opc_handler_t;
131 153
132 -#define SET_RETVAL(n) \ 154 +#define RET_EXCP(excp, error) \
133 do { \ 155 do { \
134 - if ((n) != 0) { \  
135 - ctx->exception = (n); \  
136 - } \ 156 + gen_op_queue_exception_err(excp, error); \
  157 + ctx->exception = excp; \
137 return; \ 158 return; \
138 } while (0) 159 } while (0)
139 160
140 -#define GET_RETVAL(func, __opcode) \  
141 -({ \  
142 - (func)(&ctx); \  
143 - ctx.exception; \  
144 -}) 161 +#define RET_INVAL() \
  162 +RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
  163 +
  164 +#define RET_PRIVOPC() \
  165 +RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
  166 +
  167 +#define RET_PRIVREG() \
  168 +RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
145 169
146 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \ 170 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
147 static void gen_##name (DisasContext *ctx); \ 171 static void gen_##name (DisasContext *ctx); \
148 GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \ 172 GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
149 static void gen_##name (DisasContext *ctx) 173 static void gen_##name (DisasContext *ctx)
150 174
151 -/* Instruction types */  
152 -enum {  
153 - PPC_INTEGER = 0x0001, /* CPU has integer operations instructions */  
154 - PPC_FLOAT = 0x0002, /* CPU has floating point operations instructions */  
155 - PPC_FLOW = 0x0004, /* CPU has flow control instructions */  
156 - PPC_MEM = 0x0008, /* CPU has virtual memory instructions */  
157 - PPC_MISC = 0x0010, /* CPU has spr/msr access instructions */  
158 - PPC_EXTERN = 0x0020, /* CPU has external control instructions */  
159 - PPC_SEGMENT = 0x0040, /* CPU has memory segment instructions */  
160 -};  
161 -  
162 typedef struct opcode_t { 175 typedef struct opcode_t {
163 unsigned char opc1, opc2, opc3; 176 unsigned char opc1, opc2, opc3;
164 - uint32_t type;  
165 opc_handler_t handler; 177 opc_handler_t handler;
166 } opcode_t; 178 } opcode_t;
167 179
@@ -169,9 +181,6 @@ typedef struct opcode_t { @@ -169,9 +181,6 @@ typedef struct opcode_t {
169 extern FILE *logfile; 181 extern FILE *logfile;
170 extern int loglevel; 182 extern int loglevel;
171 183
172 -/* XXX: shouldn't stay all alone here ! */  
173 -static int reserve = 0;  
174 -  
175 /*** Instruction decoding ***/ 184 /*** Instruction decoding ***/
176 #define EXTRACT_HELPER(name, shift, nb) \ 185 #define EXTRACT_HELPER(name, shift, nb) \
177 static inline uint32_t name (uint32_t opcode) \ 186 static inline uint32_t name (uint32_t opcode) \
@@ -272,9 +281,9 @@ static opcode_t opc_##name = { \ @@ -272,9 +281,9 @@ static opcode_t opc_##name = { \
272 .opc1 = op1, \ 281 .opc1 = op1, \
273 .opc2 = op2, \ 282 .opc2 = op2, \
274 .opc3 = op3, \ 283 .opc3 = op3, \
275 - .type = _typ, \  
276 .handler = { \ 284 .handler = { \
277 .inval = invl, \ 285 .inval = invl, \
  286 + .type = _typ, \
278 .handler = &gen_##name, \ 287 .handler = &gen_##name, \
279 }, \ 288 }, \
280 } 289 }
@@ -285,9 +294,9 @@ static opcode_t opc_##name = { \ @@ -285,9 +294,9 @@ static opcode_t opc_##name = { \
285 .opc1 = 0xFF, \ 294 .opc1 = 0xFF, \
286 .opc2 = 0xFF, \ 295 .opc2 = 0xFF, \
287 .opc3 = 0xFF, \ 296 .opc3 = 0xFF, \
288 - .type = 0x00, \  
289 .handler = { \ 297 .handler = { \
290 .inval = 0x00000000, \ 298 .inval = 0x00000000, \
  299 + .type = 0x00, \
291 .handler = NULL, \ 300 .handler = NULL, \
292 }, \ 301 }, \
293 } 302 }
@@ -296,15 +305,36 @@ static opcode_t opc_##name = { \ @@ -296,15 +305,36 @@ static opcode_t opc_##name = { \
296 GEN_OPCODE_MARK(start); 305 GEN_OPCODE_MARK(start);
297 306
298 /* Invalid instruction */ 307 /* Invalid instruction */
299 -GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, 0) 308 +GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
  309 +{
  310 + RET_INVAL();
  311 +}
  312 +
  313 +/* Special opcode to stop emulation */
  314 +GEN_HANDLER(stop, 0x06, 0x00, 0xFF, 0x03FFFFC1, PPC_COMMON)
300 { 315 {
301 - /* Branch to next instruction to force nip update */  
302 - gen_op_b((uint32_t)ctx->nip);  
303 - SET_RETVAL(EXCP_INVAL); 316 + gen_op_queue_exception(EXCP_HLT);
  317 + ctx->exception = EXCP_HLT;
  318 +}
  319 +
  320 +/* Special opcode to call open-firmware */
  321 +GEN_HANDLER(of_enter, 0x06, 0x01, 0xFF, 0x03FFFFC1, PPC_COMMON)
  322 +{
  323 + gen_op_queue_exception(EXCP_OFCALL);
  324 + ctx->exception = EXCP_OFCALL;
  325 +}
  326 +
  327 +/* Special opcode to call RTAS */
  328 +GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON)
  329 +{
  330 + printf("RTAS entry point !\n");
  331 + gen_op_queue_exception(EXCP_RTASCALL);
  332 + ctx->exception = EXCP_RTASCALL;
304 } 333 }
305 334
306 static opc_handler_t invalid_handler = { 335 static opc_handler_t invalid_handler = {
307 .inval = 0xFFFFFFFF, 336 .inval = 0xFFFFFFFF,
  337 + .type = PPC_NONE,
308 .handler = gen_invalid, 338 .handler = gen_invalid,
309 }; 339 };
310 340
@@ -318,7 +348,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \ @@ -318,7 +348,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
318 if (Rc(ctx->opcode) != 0) \ 348 if (Rc(ctx->opcode) != 0) \
319 gen_op_set_Rc0(); \ 349 gen_op_set_Rc0(); \
320 gen_op_store_T0_gpr(rD(ctx->opcode)); \ 350 gen_op_store_T0_gpr(rD(ctx->opcode)); \
321 - SET_RETVAL(0); \  
322 } 351 }
323 352
324 #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval) \ 353 #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval) \
@@ -330,7 +359,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \ @@ -330,7 +359,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
330 if (Rc(ctx->opcode) != 0) \ 359 if (Rc(ctx->opcode) != 0) \
331 gen_op_set_Rc0_ov(); \ 360 gen_op_set_Rc0_ov(); \
332 gen_op_store_T0_gpr(rD(ctx->opcode)); \ 361 gen_op_store_T0_gpr(rD(ctx->opcode)); \
333 - SET_RETVAL(0); \  
334 } 362 }
335 363
336 #define __GEN_INT_ARITH1(name, opc1, opc2, opc3) \ 364 #define __GEN_INT_ARITH1(name, opc1, opc2, opc3) \
@@ -341,7 +369,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \ @@ -341,7 +369,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
341 if (Rc(ctx->opcode) != 0) \ 369 if (Rc(ctx->opcode) != 0) \
342 gen_op_set_Rc0(); \ 370 gen_op_set_Rc0(); \
343 gen_op_store_T0_gpr(rD(ctx->opcode)); \ 371 gen_op_store_T0_gpr(rD(ctx->opcode)); \
344 - SET_RETVAL(0); \  
345 } 372 }
346 #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3) \ 373 #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3) \
347 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \ 374 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
@@ -351,7 +378,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \ @@ -351,7 +378,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
351 if (Rc(ctx->opcode) != 0) \ 378 if (Rc(ctx->opcode) != 0) \
352 gen_op_set_Rc0_ov(); \ 379 gen_op_set_Rc0_ov(); \
353 gen_op_store_T0_gpr(rD(ctx->opcode)); \ 380 gen_op_store_T0_gpr(rD(ctx->opcode)); \
354 - SET_RETVAL(0); \  
355 } 381 }
356 382
357 /* Two operands arithmetic functions */ 383 /* Two operands arithmetic functions */
@@ -412,7 +438,6 @@ GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -412,7 +438,6 @@ GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
412 gen_op_addi(simm); 438 gen_op_addi(simm);
413 } 439 }
414 gen_op_store_T0_gpr(rD(ctx->opcode)); 440 gen_op_store_T0_gpr(rD(ctx->opcode));
415 - SET_RETVAL(0);  
416 } 441 }
417 /* addic */ 442 /* addic */
418 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 443 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -420,7 +445,6 @@ GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -420,7 +445,6 @@ GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
420 gen_op_load_gpr_T0(rA(ctx->opcode)); 445 gen_op_load_gpr_T0(rA(ctx->opcode));
421 gen_op_addic(SIMM(ctx->opcode)); 446 gen_op_addic(SIMM(ctx->opcode));
422 gen_op_store_T0_gpr(rD(ctx->opcode)); 447 gen_op_store_T0_gpr(rD(ctx->opcode));
423 - SET_RETVAL(0);  
424 } 448 }
425 /* addic. */ 449 /* addic. */
426 GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 450 GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -429,7 +453,6 @@ GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -429,7 +453,6 @@ GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
429 gen_op_addic(SIMM(ctx->opcode)); 453 gen_op_addic(SIMM(ctx->opcode));
430 gen_op_set_Rc0(); 454 gen_op_set_Rc0();
431 gen_op_store_T0_gpr(rD(ctx->opcode)); 455 gen_op_store_T0_gpr(rD(ctx->opcode));
432 - SET_RETVAL(0);  
433 } 456 }
434 /* addis */ 457 /* addis */
435 GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 458 GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -443,7 +466,6 @@ GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -443,7 +466,6 @@ GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
443 gen_op_addi(simm << 16); 466 gen_op_addi(simm << 16);
444 } 467 }
445 gen_op_store_T0_gpr(rD(ctx->opcode)); 468 gen_op_store_T0_gpr(rD(ctx->opcode));
446 - SET_RETVAL(0);  
447 } 469 }
448 /* mulli */ 470 /* mulli */
449 GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 471 GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -451,7 +473,6 @@ GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -451,7 +473,6 @@ GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
451 gen_op_load_gpr_T0(rA(ctx->opcode)); 473 gen_op_load_gpr_T0(rA(ctx->opcode));
452 gen_op_mulli(SIMM(ctx->opcode)); 474 gen_op_mulli(SIMM(ctx->opcode));
453 gen_op_store_T0_gpr(rD(ctx->opcode)); 475 gen_op_store_T0_gpr(rD(ctx->opcode));
454 - SET_RETVAL(0);  
455 } 476 }
456 /* subfic */ 477 /* subfic */
457 GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 478 GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -459,7 +480,6 @@ GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -459,7 +480,6 @@ GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
459 gen_op_load_gpr_T0(rA(ctx->opcode)); 480 gen_op_load_gpr_T0(rA(ctx->opcode));
460 gen_op_subfic(SIMM(ctx->opcode)); 481 gen_op_subfic(SIMM(ctx->opcode));
461 gen_op_store_T0_gpr(rD(ctx->opcode)); 482 gen_op_store_T0_gpr(rD(ctx->opcode));
462 - SET_RETVAL(0);  
463 } 483 }
464 484
465 /*** Integer comparison ***/ 485 /*** Integer comparison ***/
@@ -470,7 +490,6 @@ GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER) \ @@ -470,7 +490,6 @@ GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER) \
470 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 490 gen_op_load_gpr_T1(rB(ctx->opcode)); \
471 gen_op_##name(); \ 491 gen_op_##name(); \
472 gen_op_store_T0_crf(crfD(ctx->opcode)); \ 492 gen_op_store_T0_crf(crfD(ctx->opcode)); \
473 - SET_RETVAL(0); \  
474 } 493 }
475 494
476 /* cmp */ 495 /* cmp */
@@ -481,7 +500,6 @@ GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER) @@ -481,7 +500,6 @@ GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
481 gen_op_load_gpr_T0(rA(ctx->opcode)); 500 gen_op_load_gpr_T0(rA(ctx->opcode));
482 gen_op_cmpi(SIMM(ctx->opcode)); 501 gen_op_cmpi(SIMM(ctx->opcode));
483 gen_op_store_T0_crf(crfD(ctx->opcode)); 502 gen_op_store_T0_crf(crfD(ctx->opcode));
484 - SET_RETVAL(0);  
485 } 503 }
486 /* cmpl */ 504 /* cmpl */
487 GEN_CMP(cmpl, 0x01); 505 GEN_CMP(cmpl, 0x01);
@@ -491,7 +509,6 @@ GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER) @@ -491,7 +509,6 @@ GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
491 gen_op_load_gpr_T0(rA(ctx->opcode)); 509 gen_op_load_gpr_T0(rA(ctx->opcode));
492 gen_op_cmpli(UIMM(ctx->opcode)); 510 gen_op_cmpli(UIMM(ctx->opcode));
493 gen_op_store_T0_crf(crfD(ctx->opcode)); 511 gen_op_store_T0_crf(crfD(ctx->opcode));
494 - SET_RETVAL(0);  
495 } 512 }
496 513
497 /*** Integer logical ***/ 514 /*** Integer logical ***/
@@ -504,7 +521,6 @@ GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER) \ @@ -504,7 +521,6 @@ GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER) \
504 if (Rc(ctx->opcode) != 0) \ 521 if (Rc(ctx->opcode) != 0) \
505 gen_op_set_Rc0(); \ 522 gen_op_set_Rc0(); \
506 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 523 gen_op_store_T0_gpr(rA(ctx->opcode)); \
507 - SET_RETVAL(0); \  
508 } 524 }
509 #define GEN_LOGICAL2(name, opc) \ 525 #define GEN_LOGICAL2(name, opc) \
510 __GEN_LOGICAL2(name, 0x1C, opc) 526 __GEN_LOGICAL2(name, 0x1C, opc)
@@ -517,7 +533,6 @@ GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER) \ @@ -517,7 +533,6 @@ GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER) \
517 if (Rc(ctx->opcode) != 0) \ 533 if (Rc(ctx->opcode) != 0) \
518 gen_op_set_Rc0(); \ 534 gen_op_set_Rc0(); \
519 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 535 gen_op_store_T0_gpr(rA(ctx->opcode)); \
520 - SET_RETVAL(0); \  
521 } 536 }
522 537
523 /* and & and. */ 538 /* and & and. */
@@ -531,7 +546,6 @@ GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -531,7 +546,6 @@ GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
531 gen_op_andi_(UIMM(ctx->opcode)); 546 gen_op_andi_(UIMM(ctx->opcode));
532 gen_op_set_Rc0(); 547 gen_op_set_Rc0();
533 gen_op_store_T0_gpr(rA(ctx->opcode)); 548 gen_op_store_T0_gpr(rA(ctx->opcode));
534 - SET_RETVAL(0);  
535 } 549 }
536 /* andis. */ 550 /* andis. */
537 GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 551 GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -540,7 +554,6 @@ GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -540,7 +554,6 @@ GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
540 gen_op_andi_(UIMM(ctx->opcode) << 16); 554 gen_op_andi_(UIMM(ctx->opcode) << 16);
541 gen_op_set_Rc0(); 555 gen_op_set_Rc0();
542 gen_op_store_T0_gpr(rA(ctx->opcode)); 556 gen_op_store_T0_gpr(rA(ctx->opcode));
543 - SET_RETVAL(0);  
544 } 557 }
545 558
546 /* cntlzw */ 559 /* cntlzw */
@@ -555,68 +568,94 @@ GEN_LOGICAL1(extsh, 0x1C); @@ -555,68 +568,94 @@ GEN_LOGICAL1(extsh, 0x1C);
555 GEN_LOGICAL2(nand, 0x0E); 568 GEN_LOGICAL2(nand, 0x0E);
556 /* nor & nor. */ 569 /* nor & nor. */
557 GEN_LOGICAL2(nor, 0x03); 570 GEN_LOGICAL2(nor, 0x03);
  571 +
558 /* or & or. */ 572 /* or & or. */
559 -GEN_LOGICAL2(or, 0x0D); 573 +GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
  574 +{
  575 + gen_op_load_gpr_T0(rS(ctx->opcode));
  576 + /* Optimisation for mr case */
  577 + if (rS(ctx->opcode) != rB(ctx->opcode)) {
  578 + gen_op_load_gpr_T1(rB(ctx->opcode));
  579 + gen_op_or();
  580 + }
  581 + if (Rc(ctx->opcode) != 0)
  582 + gen_op_set_Rc0();
  583 + gen_op_store_T0_gpr(rA(ctx->opcode));
  584 +}
  585 +
560 /* orc & orc. */ 586 /* orc & orc. */
561 GEN_LOGICAL2(orc, 0x0C); 587 GEN_LOGICAL2(orc, 0x0C);
562 /* xor & xor. */ 588 /* xor & xor. */
563 -GEN_LOGICAL2(xor, 0x09); 589 +GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
  590 +{
  591 + gen_op_load_gpr_T0(rS(ctx->opcode));
  592 + /* Optimisation for "set to zero" case */
  593 + if (rS(ctx->opcode) != rB(ctx->opcode)) {
  594 + gen_op_load_gpr_T1(rB(ctx->opcode));
  595 + gen_op_xor();
  596 + } else {
  597 + gen_op_set_T0(0);
  598 + }
  599 + if (Rc(ctx->opcode) != 0)
  600 + gen_op_set_Rc0();
  601 + gen_op_store_T0_gpr(rA(ctx->opcode));
  602 +}
564 /* ori */ 603 /* ori */
565 GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 604 GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
566 { 605 {
567 uint32_t uimm = UIMM(ctx->opcode); 606 uint32_t uimm = UIMM(ctx->opcode);
568 607
569 -#if 0  
570 - if (uimm == 0) {  
571 - if (rA(ctx->opcode) != rS(ctx->opcode)) {  
572 - gen_op_load_gpr_T0(rS(ctx->opcode));  
573 - gen_op_store_T0_gpr(rA(ctx->opcode)); 608 + if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
  609 + /* NOP */
  610 + return;
574 } 611 }
575 - } else  
576 -#endif  
577 - {  
578 gen_op_load_gpr_T0(rS(ctx->opcode)); 612 gen_op_load_gpr_T0(rS(ctx->opcode));
  613 + if (uimm != 0)
579 gen_op_ori(uimm); 614 gen_op_ori(uimm);
580 gen_op_store_T0_gpr(rA(ctx->opcode)); 615 gen_op_store_T0_gpr(rA(ctx->opcode));
581 - }  
582 - SET_RETVAL(0);  
583 } 616 }
584 /* oris */ 617 /* oris */
585 GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 618 GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
586 { 619 {
587 uint32_t uimm = UIMM(ctx->opcode); 620 uint32_t uimm = UIMM(ctx->opcode);
588 621
589 -#if 0  
590 - if (uimm == 0) {  
591 - if (rA(ctx->opcode) != rS(ctx->opcode)) {  
592 - gen_op_load_gpr_T0(rS(ctx->opcode));  
593 - gen_op_store_T0_gpr(rA(ctx->opcode)); 622 + if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
  623 + /* NOP */
  624 + return;
594 } 625 }
595 - } else  
596 -#endif  
597 - {  
598 gen_op_load_gpr_T0(rS(ctx->opcode)); 626 gen_op_load_gpr_T0(rS(ctx->opcode));
  627 + if (uimm != 0)
599 gen_op_ori(uimm << 16); 628 gen_op_ori(uimm << 16);
600 gen_op_store_T0_gpr(rA(ctx->opcode)); 629 gen_op_store_T0_gpr(rA(ctx->opcode));
601 - }  
602 - SET_RETVAL(0);  
603 } 630 }
604 /* xori */ 631 /* xori */
605 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 632 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
606 { 633 {
  634 + uint32_t uimm = UIMM(ctx->opcode);
  635 +
  636 + if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
  637 + /* NOP */
  638 + return;
  639 + }
607 gen_op_load_gpr_T0(rS(ctx->opcode)); 640 gen_op_load_gpr_T0(rS(ctx->opcode));
  641 + if (uimm != 0)
608 gen_op_xori(UIMM(ctx->opcode)); 642 gen_op_xori(UIMM(ctx->opcode));
609 gen_op_store_T0_gpr(rA(ctx->opcode)); 643 gen_op_store_T0_gpr(rA(ctx->opcode));
610 - SET_RETVAL(0);  
611 } 644 }
612 645
613 /* xoris */ 646 /* xoris */
614 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 647 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
615 { 648 {
  649 + uint32_t uimm = UIMM(ctx->opcode);
  650 +
  651 + if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
  652 + /* NOP */
  653 + return;
  654 + }
616 gen_op_load_gpr_T0(rS(ctx->opcode)); 655 gen_op_load_gpr_T0(rS(ctx->opcode));
  656 + if (uimm != 0)
617 gen_op_xori(UIMM(ctx->opcode) << 16); 657 gen_op_xori(UIMM(ctx->opcode) << 16);
618 gen_op_store_T0_gpr(rA(ctx->opcode)); 658 gen_op_store_T0_gpr(rA(ctx->opcode));
619 - SET_RETVAL(0);  
620 } 659 }
621 660
622 /*** Integer rotate ***/ 661 /*** Integer rotate ***/
@@ -633,7 +672,6 @@ GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -633,7 +672,6 @@ GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
633 if (Rc(ctx->opcode) != 0) 672 if (Rc(ctx->opcode) != 0)
634 gen_op_set_Rc0(); 673 gen_op_set_Rc0();
635 gen_op_store_T0_gpr(rA(ctx->opcode)); 674 gen_op_store_T0_gpr(rA(ctx->opcode));
636 - SET_RETVAL(0);  
637 } 675 }
638 /* rlwinm & rlwinm. */ 676 /* rlwinm & rlwinm. */
639 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 677 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -644,10 +682,6 @@ GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -644,10 +682,6 @@ GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
644 mb = MB(ctx->opcode); 682 mb = MB(ctx->opcode);
645 me = ME(ctx->opcode); 683 me = ME(ctx->opcode);
646 gen_op_load_gpr_T0(rS(ctx->opcode)); 684 gen_op_load_gpr_T0(rS(ctx->opcode));
647 - if (loglevel > 0) {  
648 - fprintf(logfile, "%s sh=%u mb=%u me=%u MASK=0x%08x\n",  
649 - __func__, sh, mb, me, MASK(mb, me));  
650 - }  
651 if (mb == 0) { 685 if (mb == 0) {
652 if (me == 31) { 686 if (me == 31) {
653 gen_op_rotlwi(sh); 687 gen_op_rotlwi(sh);
@@ -673,7 +707,6 @@ store: @@ -673,7 +707,6 @@ store:
673 if (Rc(ctx->opcode) != 0) 707 if (Rc(ctx->opcode) != 0)
674 gen_op_set_Rc0(); 708 gen_op_set_Rc0();
675 gen_op_store_T0_gpr(rA(ctx->opcode)); 709 gen_op_store_T0_gpr(rA(ctx->opcode));
676 - SET_RETVAL(0);  
677 } 710 }
678 /* rlwnm & rlwnm. */ 711 /* rlwnm & rlwnm. */
679 GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 712 GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
@@ -693,7 +726,6 @@ GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) @@ -693,7 +726,6 @@ GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
693 if (Rc(ctx->opcode) != 0) 726 if (Rc(ctx->opcode) != 0)
694 gen_op_set_Rc0(); 727 gen_op_set_Rc0();
695 gen_op_store_T0_gpr(rA(ctx->opcode)); 728 gen_op_store_T0_gpr(rA(ctx->opcode));
696 - SET_RETVAL(0);  
697 } 729 }
698 730
699 /*** Integer shift ***/ 731 /*** Integer shift ***/
@@ -709,172 +741,169 @@ GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER) @@ -709,172 +741,169 @@ GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
709 if (Rc(ctx->opcode) != 0) 741 if (Rc(ctx->opcode) != 0)
710 gen_op_set_Rc0(); 742 gen_op_set_Rc0();
711 gen_op_store_T0_gpr(rA(ctx->opcode)); 743 gen_op_store_T0_gpr(rA(ctx->opcode));
712 - SET_RETVAL(0);  
713 } 744 }
714 /* srw & srw. */ 745 /* srw & srw. */
715 __GEN_LOGICAL2(srw, 0x18, 0x10); 746 __GEN_LOGICAL2(srw, 0x18, 0x10);
716 747
717 /*** Floating-Point arithmetic ***/ 748 /*** Floating-Point arithmetic ***/
718 -/* fadd */  
719 -GEN_HANDLER(fadd, 0x3F, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)  
720 -{  
721 - SET_RETVAL(EXCP_INVAL); 749 +#define _GEN_FLOAT_ACB(name, op1, op2) \
  750 +GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \
  751 +{ \
  752 + gen_op_reset_scrfx(); \
  753 + gen_op_load_fpr_FT0(rA(ctx->opcode)); \
  754 + gen_op_load_fpr_FT1(rC(ctx->opcode)); \
  755 + gen_op_load_fpr_FT2(rB(ctx->opcode)); \
  756 + gen_op_f##name(); \
  757 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  758 + if (Rc(ctx->opcode)) \
  759 + gen_op_set_Rc1(); \
  760 +}
  761 +
  762 +#define GEN_FLOAT_ACB(name, op2) \
  763 +_GEN_FLOAT_ACB(name, 0x3F, op2); \
  764 +_GEN_FLOAT_ACB(name##s, 0x3B, op2);
  765 +
  766 +#define _GEN_FLOAT_AB(name, op1, op2, inval) \
  767 +GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
  768 +{ \
  769 + gen_op_reset_scrfx(); \
  770 + gen_op_load_fpr_FT0(rA(ctx->opcode)); \
  771 + gen_op_load_fpr_FT1(rB(ctx->opcode)); \
  772 + gen_op_f##name(); \
  773 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  774 + if (Rc(ctx->opcode)) \
  775 + gen_op_set_Rc1(); \
  776 +}
  777 +#define GEN_FLOAT_AB(name, op2, inval) \
  778 +_GEN_FLOAT_AB(name, 0x3F, op2, inval); \
  779 +_GEN_FLOAT_AB(name##s, 0x3B, op2, inval);
  780 +
  781 +#define _GEN_FLOAT_AC(name, op1, op2, inval) \
  782 +GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
  783 +{ \
  784 + gen_op_reset_scrfx(); \
  785 + gen_op_load_fpr_FT0(rA(ctx->opcode)); \
  786 + gen_op_load_fpr_FT1(rC(ctx->opcode)); \
  787 + gen_op_f##name(); \
  788 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  789 + if (Rc(ctx->opcode)) \
  790 + gen_op_set_Rc1(); \
  791 +}
  792 +#define GEN_FLOAT_AC(name, op2, inval) \
  793 +_GEN_FLOAT_AC(name, 0x3F, op2, inval); \
  794 +_GEN_FLOAT_AC(name##s, 0x3B, op2, inval);
  795 +
  796 +#define GEN_FLOAT_B(name, op2, op3) \
  797 +GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \
  798 +{ \
  799 + gen_op_reset_scrfx(); \
  800 + gen_op_load_fpr_FT0(rB(ctx->opcode)); \
  801 + gen_op_f##name(); \
  802 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  803 + if (Rc(ctx->opcode)) \
  804 + gen_op_set_Rc1(); \
722 } 805 }
723 806
724 -/* fadds */  
725 -GEN_HANDLER(fadds, 0x3B, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)  
726 -{  
727 - SET_RETVAL(EXCP_INVAL); 807 +#define GEN_FLOAT_BS(name, op2) \
  808 +GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \
  809 +{ \
  810 + gen_op_reset_scrfx(); \
  811 + gen_op_load_fpr_FT0(rB(ctx->opcode)); \
  812 + gen_op_f##name(); \
  813 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  814 + if (Rc(ctx->opcode)) \
  815 + gen_op_set_Rc1(); \
728 } 816 }
729 817
  818 +/* fadd - fadds */
  819 +GEN_FLOAT_AB(add, 0x15, 0x000007C0);
730 /* fdiv */ 820 /* fdiv */
731 -GEN_HANDLER(fdiv, 0x3F, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)  
732 -{  
733 - SET_RETVAL(EXCP_INVAL);  
734 -}  
735 -  
736 -/* fdivs */  
737 -GEN_HANDLER(fdivs, 0x3B, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)  
738 -{  
739 - SET_RETVAL(EXCP_INVAL);  
740 -}  
741 - 821 +GEN_FLOAT_AB(div, 0x12, 0x000007C0);
742 /* fmul */ 822 /* fmul */
743 -GEN_HANDLER(fmul, 0x3F, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)  
744 -{  
745 - SET_RETVAL(EXCP_INVAL);  
746 -}  
747 -  
748 -/* fmuls */  
749 -GEN_HANDLER(fmuls, 0x3B, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)  
750 -{  
751 - SET_RETVAL(EXCP_INVAL);  
752 -} 823 +GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
753 824
754 /* fres */ 825 /* fres */
755 -GEN_HANDLER(fres, 0x3B, 0x18, 0xFF, 0x001807C0, PPC_FLOAT)  
756 -{  
757 - SET_RETVAL(EXCP_INVAL);  
758 -} 826 +GEN_FLOAT_BS(res, 0x18);
759 827
760 /* frsqrte */ 828 /* frsqrte */
761 -GEN_HANDLER(frsqrte, 0x3F, 0x1A, 0xFF, 0x001807C0, PPC_FLOAT)  
762 -{  
763 - SET_RETVAL(EXCP_INVAL);  
764 -} 829 +GEN_FLOAT_BS(rsqrte, 0x1A);
765 830
766 /* fsel */ 831 /* fsel */
767 -GEN_HANDLER(fsel, 0x3F, 0x17, 0xFF, 0x00000000, PPC_FLOAT)  
768 -{  
769 - SET_RETVAL(EXCP_INVAL);  
770 -}  
771 - 832 +_GEN_FLOAT_ACB(sel, 0x3F, 0x17);
772 /* fsub */ 833 /* fsub */
773 -GEN_HANDLER(fsub, 0x3F, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)  
774 -{  
775 - SET_RETVAL(EXCP_INVAL);  
776 -}  
777 -  
778 -/* fsubs */  
779 -GEN_HANDLER(fsubs, 0x3B, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)  
780 -{  
781 - SET_RETVAL(EXCP_INVAL);  
782 -}  
783 - 834 +GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
784 /* Optional: */ 835 /* Optional: */
785 /* fsqrt */ 836 /* fsqrt */
786 -GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)  
787 -{  
788 - SET_RETVAL(EXCP_INVAL);  
789 -} 837 +GEN_FLOAT_BS(sqrt, 0x16);
790 838
791 -/* fsqrts */  
792 -GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001807C0, PPC_FLOAT) 839 +GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
793 { 840 {
794 - SET_RETVAL(EXCP_INVAL); 841 + gen_op_reset_scrfx();
  842 + gen_op_load_fpr_FT0(rB(ctx->opcode));
  843 + gen_op_fsqrts();
  844 + gen_op_store_FT0_fpr(rD(ctx->opcode));
  845 + if (Rc(ctx->opcode))
  846 + gen_op_set_Rc1();
795 } 847 }
796 848
797 /*** Floating-Point multiply-and-add ***/ 849 /*** Floating-Point multiply-and-add ***/
798 /* fmadd */ 850 /* fmadd */
799 -GEN_HANDLER(fmadd, 0x3F, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)  
800 -{  
801 - SET_RETVAL(EXCP_INVAL);  
802 -}  
803 -  
804 -/* fmadds */  
805 -GEN_HANDLER(fmadds, 0x3B, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)  
806 -{  
807 - SET_RETVAL(EXCP_INVAL);  
808 -}  
809 - 851 +GEN_FLOAT_ACB(madd, 0x1D);
810 /* fmsub */ 852 /* fmsub */
811 -GEN_HANDLER(fmsub, 0x3F, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)  
812 -{  
813 - SET_RETVAL(EXCP_INVAL);  
814 -}  
815 -  
816 -/* fmsubs */  
817 -GEN_HANDLER(fmsubs, 0x3B, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)  
818 -{  
819 - SET_RETVAL(EXCP_INVAL);  
820 -}  
821 - 853 +GEN_FLOAT_ACB(msub, 0x1C);
822 /* fnmadd */ 854 /* fnmadd */
823 -GEN_HANDLER(fnmadd, 0x3F, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)  
824 -{  
825 - SET_RETVAL(EXCP_INVAL);  
826 -}  
827 -  
828 -/* fnmadds */  
829 -GEN_HANDLER(fnmadds, 0x3B, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)  
830 -{  
831 - SET_RETVAL(EXCP_INVAL);  
832 -}  
833 - 855 +GEN_FLOAT_ACB(nmadd, 0x1F);
834 /* fnmsub */ 856 /* fnmsub */
835 -GEN_HANDLER(fnmsub, 0x3F, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)  
836 -{  
837 - SET_RETVAL(EXCP_INVAL);  
838 -}  
839 -  
840 -/* fnmsubs */  
841 -GEN_HANDLER(fnmsubs, 0x3B, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)  
842 -{  
843 - SET_RETVAL(EXCP_INVAL);  
844 -} 857 +GEN_FLOAT_ACB(nmsub, 0x1E);
845 858
846 /*** Floating-Point round & convert ***/ 859 /*** Floating-Point round & convert ***/
847 /* fctiw */ 860 /* fctiw */
848 -GEN_HANDLER(fctiw, 0x3F, 0x0E, 0xFF, 0x001F0000, PPC_FLOAT)  
849 -{  
850 - SET_RETVAL(EXCP_INVAL);  
851 -}  
852 - 861 +GEN_FLOAT_B(ctiw, 0x0E, 0x00);
853 /* fctiwz */ 862 /* fctiwz */
854 -GEN_HANDLER(fctiwz, 0x3F, 0x0F, 0xFF, 0x001F0000, PPC_FLOAT)  
855 -{  
856 - SET_RETVAL(EXCP_INVAL);  
857 -}  
858 - 863 +GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
859 /* frsp */ 864 /* frsp */
860 -GEN_HANDLER(frsp, 0x3F, 0x0C, 0xFF, 0x001F0000, PPC_FLOAT)  
861 -{  
862 - SET_RETVAL(EXCP_INVAL);  
863 -} 865 +GEN_FLOAT_B(rsp, 0x0C, 0x00);
864 866
865 /*** Floating-Point compare ***/ 867 /*** Floating-Point compare ***/
866 /* fcmpo */ 868 /* fcmpo */
867 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT) 869 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
868 { 870 {
869 - SET_RETVAL(EXCP_INVAL); 871 + gen_op_reset_scrfx();
  872 + gen_op_load_fpr_FT0(rA(ctx->opcode));
  873 + gen_op_load_fpr_FT1(rB(ctx->opcode));
  874 + gen_op_fcmpo();
  875 + gen_op_store_T0_crf(crfD(ctx->opcode));
870 } 876 }
871 877
872 /* fcmpu */ 878 /* fcmpu */
873 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) 879 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
874 { 880 {
875 - SET_RETVAL(EXCP_INVAL); 881 + gen_op_reset_scrfx();
  882 + gen_op_load_fpr_FT0(rA(ctx->opcode));
  883 + gen_op_load_fpr_FT1(rB(ctx->opcode));
  884 + gen_op_fcmpu();
  885 + gen_op_store_T0_crf(crfD(ctx->opcode));
876 } 886 }
877 887
  888 +/*** Floating-point move ***/
  889 +/* fabs */
  890 +GEN_FLOAT_B(abs, 0x08, 0x08);
  891 +
  892 +/* fmr - fmr. */
  893 +GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
  894 +{
  895 + gen_op_reset_scrfx();
  896 + gen_op_load_fpr_FT0(rB(ctx->opcode));
  897 + gen_op_store_FT0_fpr(rD(ctx->opcode));
  898 + if (Rc(ctx->opcode))
  899 + gen_op_set_Rc1();
  900 +}
  901 +
  902 +/* fnabs */
  903 +GEN_FLOAT_B(nabs, 0x08, 0x04);
  904 +/* fneg */
  905 +GEN_FLOAT_B(neg, 0x08, 0x01);
  906 +
878 /*** Floating-Point status & ctrl register ***/ 907 /*** Floating-Point status & ctrl register ***/
879 /* mcrfs */ 908 /* mcrfs */
880 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) 909 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
@@ -882,7 +911,6 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) @@ -882,7 +911,6 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
882 gen_op_load_fpscr_T0(crfS(ctx->opcode)); 911 gen_op_load_fpscr_T0(crfS(ctx->opcode));
883 gen_op_store_T0_crf(crfD(ctx->opcode)); 912 gen_op_store_T0_crf(crfD(ctx->opcode));
884 gen_op_clear_fpscr(crfS(ctx->opcode)); 913 gen_op_clear_fpscr(crfS(ctx->opcode));
885 - SET_RETVAL(0);  
886 } 914 }
887 915
888 /* mffs */ 916 /* mffs */
@@ -892,7 +920,6 @@ GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT) @@ -892,7 +920,6 @@ GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
892 gen_op_store_FT0_fpr(rD(ctx->opcode)); 920 gen_op_store_FT0_fpr(rD(ctx->opcode));
893 if (Rc(ctx->opcode)) 921 if (Rc(ctx->opcode))
894 gen_op_set_Rc1(); 922 gen_op_set_Rc1();
895 - SET_RETVAL(0);  
896 } 923 }
897 924
898 /* mtfsb0 */ 925 /* mtfsb0 */
@@ -906,7 +933,6 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT) @@ -906,7 +933,6 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
906 gen_op_store_T0_fpscr(crb); 933 gen_op_store_T0_fpscr(crb);
907 if (Rc(ctx->opcode)) 934 if (Rc(ctx->opcode))
908 gen_op_set_Rc1(); 935 gen_op_set_Rc1();
909 - SET_RETVAL(0);  
910 } 936 }
911 937
912 /* mtfsb1 */ 938 /* mtfsb1 */
@@ -920,7 +946,6 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT) @@ -920,7 +946,6 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
920 gen_op_store_T0_fpscr(crb); 946 gen_op_store_T0_fpscr(crb);
921 if (Rc(ctx->opcode)) 947 if (Rc(ctx->opcode))
922 gen_op_set_Rc1(); 948 gen_op_set_Rc1();
923 - SET_RETVAL(0);  
924 } 949 }
925 950
926 /* mtfsf */ 951 /* mtfsf */
@@ -930,7 +955,6 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) @@ -930,7 +955,6 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
930 gen_op_store_fpscr(FM(ctx->opcode)); 955 gen_op_store_fpscr(FM(ctx->opcode));
931 if (Rc(ctx->opcode)) 956 if (Rc(ctx->opcode))
932 gen_op_set_Rc1(); 957 gen_op_set_Rc1();
933 - SET_RETVAL(0);  
934 } 958 }
935 959
936 /* mtfsfi */ 960 /* mtfsfi */
@@ -939,505 +963,541 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) @@ -939,505 +963,541 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
939 gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode)); 963 gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
940 if (Rc(ctx->opcode)) 964 if (Rc(ctx->opcode))
941 gen_op_set_Rc1(); 965 gen_op_set_Rc1();
942 - SET_RETVAL(0);  
943 } 966 }
944 967
945 /*** Integer load ***/ 968 /*** Integer load ***/
946 -#define GEN_ILDZ(width, opc) \ 969 +#if defined(CONFIG_USER_ONLY)
  970 +#define op_ldst(name) gen_op_##name##_raw()
  971 +#define OP_LD_TABLE(width)
  972 +#define OP_ST_TABLE(width)
  973 +#else
  974 +#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
  975 +#define OP_LD_TABLE(width) \
  976 +static GenOpFunc *gen_op_l##width[] = { \
  977 + &gen_op_l##width##_user, \
  978 + &gen_op_l##width##_kernel, \
  979 +}
  980 +#define OP_ST_TABLE(width) \
  981 +static GenOpFunc *gen_op_st##width[] = { \
  982 + &gen_op_st##width##_user, \
  983 + &gen_op_st##width##_kernel, \
  984 +}
  985 +#endif
  986 +
  987 +#define GEN_LD(width, opc) \
947 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ 988 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
948 { \ 989 { \
949 uint32_t simm = SIMM(ctx->opcode); \ 990 uint32_t simm = SIMM(ctx->opcode); \
950 if (rA(ctx->opcode) == 0) { \ 991 if (rA(ctx->opcode) == 0) { \
951 - gen_op_l##width##_z(simm); \ 992 + gen_op_set_T0(simm); \
952 } else { \ 993 } else { \
953 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 994 gen_op_load_gpr_T0(rA(ctx->opcode)); \
954 - gen_op_l##width (simm); \ 995 + if (simm != 0) \
  996 + gen_op_addi(simm); \
955 } \ 997 } \
  998 + op_ldst(l##width); \
956 gen_op_store_T1_gpr(rD(ctx->opcode)); \ 999 gen_op_store_T1_gpr(rD(ctx->opcode)); \
957 - SET_RETVAL(0); \  
958 } 1000 }
959 1001
960 -#define GEN_ILDZU(width, opc) \ 1002 +#define GEN_LDU(width, opc) \
961 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ 1003 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
962 { \ 1004 { \
  1005 + uint32_t simm = SIMM(ctx->opcode); \
963 if (rA(ctx->opcode) == 0 || \ 1006 if (rA(ctx->opcode) == 0 || \
964 - rA(ctx->opcode) == rD(ctx->opcode)) \  
965 - SET_RETVAL(EXCP_INVAL); \ 1007 + rA(ctx->opcode) == rD(ctx->opcode)) { \
  1008 + RET_INVAL(); \
  1009 + } \
966 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1010 gen_op_load_gpr_T0(rA(ctx->opcode)); \
967 - gen_op_l##width(SIMM(ctx->opcode)); \ 1011 + if (simm != 0) \
  1012 + gen_op_addi(simm); \
  1013 + op_ldst(l##width); \
968 gen_op_store_T1_gpr(rD(ctx->opcode)); \ 1014 gen_op_store_T1_gpr(rD(ctx->opcode)); \
969 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 1015 gen_op_store_T0_gpr(rA(ctx->opcode)); \
970 - SET_RETVAL(0); \  
971 } 1016 }
972 1017
973 -#define GEN_ILDZUX(width, opc) \ 1018 +#define GEN_LDUX(width, opc) \
974 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ 1019 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
975 { \ 1020 { \
976 if (rA(ctx->opcode) == 0 || \ 1021 if (rA(ctx->opcode) == 0 || \
977 - rA(ctx->opcode) == rD(ctx->opcode)) \  
978 - SET_RETVAL(EXCP_INVAL); \ 1022 + rA(ctx->opcode) == rD(ctx->opcode)) { \
  1023 + RET_INVAL(); \
  1024 + } \
979 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1025 gen_op_load_gpr_T0(rA(ctx->opcode)); \
980 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1026 gen_op_load_gpr_T1(rB(ctx->opcode)); \
981 - gen_op_l##width##x(); \ 1027 + gen_op_add(); \
  1028 + op_ldst(l##width); \
982 gen_op_store_T1_gpr(rD(ctx->opcode)); \ 1029 gen_op_store_T1_gpr(rD(ctx->opcode)); \
983 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 1030 gen_op_store_T0_gpr(rA(ctx->opcode)); \
984 - SET_RETVAL(0); \  
985 } 1031 }
986 1032
987 -#define GEN_ILDZX(width, opc2, opc3) \ 1033 +#define GEN_LDX(width, opc2, opc3) \
988 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ 1034 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
989 { \ 1035 { \
990 if (rA(ctx->opcode) == 0) { \ 1036 if (rA(ctx->opcode) == 0) { \
991 gen_op_load_gpr_T0(rB(ctx->opcode)); \ 1037 gen_op_load_gpr_T0(rB(ctx->opcode)); \
992 - gen_op_l##width##x_z(); \  
993 } else { \ 1038 } else { \
994 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1039 gen_op_load_gpr_T0(rA(ctx->opcode)); \
995 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1040 gen_op_load_gpr_T1(rB(ctx->opcode)); \
996 - gen_op_l##width##x(); \ 1041 + gen_op_add(); \
997 } \ 1042 } \
  1043 + op_ldst(l##width); \
998 gen_op_store_T1_gpr(rD(ctx->opcode)); \ 1044 gen_op_store_T1_gpr(rD(ctx->opcode)); \
999 - SET_RETVAL(0); \  
1000 } 1045 }
1001 1046
1002 -#define GEN_ILD(width, op) \  
1003 -GEN_ILDZ(width, op | 0x20) \  
1004 -GEN_ILDZU(width, op | 0x21) \  
1005 -GEN_ILDZUX(width, op | 0x01) \  
1006 -GEN_ILDZX(width, 0x17, op | 0x00) 1047 +#define GEN_LDS(width, op) \
  1048 +OP_LD_TABLE(width); \
  1049 +GEN_LD(width, op | 0x20); \
  1050 +GEN_LDU(width, op | 0x21); \
  1051 +GEN_LDUX(width, op | 0x01); \
  1052 +GEN_LDX(width, 0x17, op | 0x00)
1007 1053
1008 /* lbz lbzu lbzux lbzx */ 1054 /* lbz lbzu lbzux lbzx */
1009 -GEN_ILD(bz, 0x02); 1055 +GEN_LDS(bz, 0x02);
1010 /* lha lhau lhaux lhax */ 1056 /* lha lhau lhaux lhax */
1011 -GEN_ILD(ha, 0x0A); 1057 +GEN_LDS(ha, 0x0A);
1012 /* lhz lhzu lhzux lhzx */ 1058 /* lhz lhzu lhzux lhzx */
1013 -GEN_ILD(hz, 0x08); 1059 +GEN_LDS(hz, 0x08);
1014 /* lwz lwzu lwzux lwzx */ 1060 /* lwz lwzu lwzux lwzx */
1015 -GEN_ILD(wz, 0x00); 1061 +GEN_LDS(wz, 0x00);
1016 1062
1017 /*** Integer store ***/ 1063 /*** Integer store ***/
1018 -#define GEN_IST(width, opc) \ 1064 +#define GEN_ST(width, opc) \
1019 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ 1065 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1020 { \ 1066 { \
1021 uint32_t simm = SIMM(ctx->opcode); \ 1067 uint32_t simm = SIMM(ctx->opcode); \
1022 if (rA(ctx->opcode) == 0) { \ 1068 if (rA(ctx->opcode) == 0) { \
1023 - gen_op_load_gpr_T0(rS(ctx->opcode)); \  
1024 - gen_op_st##width##_z(simm); \ 1069 + gen_op_set_T0(simm); \
1025 } else { \ 1070 } else { \
1026 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1071 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1027 - gen_op_load_gpr_T1(rS(ctx->opcode)); \  
1028 - gen_op_st##width(simm); \ 1072 + if (simm != 0) \
  1073 + gen_op_addi(simm); \
1029 } \ 1074 } \
1030 - SET_RETVAL(0); \ 1075 + gen_op_load_gpr_T1(rS(ctx->opcode)); \
  1076 + op_ldst(st##width); \
1031 } 1077 }
1032 1078
1033 -#define GEN_ISTU(width, opc) \ 1079 +#define GEN_STU(width, opc) \
1034 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \ 1080 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1035 { \ 1081 { \
1036 - if (rA(ctx->opcode) == 0) \  
1037 - SET_RETVAL(EXCP_INVAL); \ 1082 + uint32_t simm = SIMM(ctx->opcode); \
  1083 + if (rA(ctx->opcode) == 0) { \
  1084 + RET_INVAL(); \
  1085 + } \
1038 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1086 gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1087 + if (simm != 0) \
  1088 + gen_op_addi(simm); \
1039 gen_op_load_gpr_T1(rS(ctx->opcode)); \ 1089 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1040 - gen_op_st##width(SIMM(ctx->opcode)); \ 1090 + op_ldst(st##width); \
1041 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 1091 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1042 - SET_RETVAL(0); \  
1043 } 1092 }
1044 1093
1045 -#define GEN_ISTUX(width, opc) \ 1094 +#define GEN_STUX(width, opc) \
1046 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \ 1095 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1047 { \ 1096 { \
1048 - if (rA(ctx->opcode) == 0) \  
1049 - SET_RETVAL(EXCP_INVAL); \ 1097 + if (rA(ctx->opcode) == 0) { \
  1098 + RET_INVAL(); \
  1099 + } \
1050 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1100 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1051 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1101 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1052 - gen_op_load_gpr_T2(rS(ctx->opcode)); \  
1053 - gen_op_st##width##x(); \ 1102 + gen_op_add(); \
  1103 + gen_op_load_gpr_T1(rS(ctx->opcode)); \
  1104 + op_ldst(st##width); \
1054 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 1105 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1055 - SET_RETVAL(0); \  
1056 } 1106 }
1057 1107
1058 -#define GEN_ISTX(width, opc2, opc3) \ 1108 +#define GEN_STX(width, opc2, opc3) \
1059 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \ 1109 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1060 { \ 1110 { \
1061 if (rA(ctx->opcode) == 0) { \ 1111 if (rA(ctx->opcode) == 0) { \
1062 gen_op_load_gpr_T0(rB(ctx->opcode)); \ 1112 gen_op_load_gpr_T0(rB(ctx->opcode)); \
1063 - gen_op_load_gpr_T1(rS(ctx->opcode)); \  
1064 - gen_op_st##width##x_z(); \  
1065 } else { \ 1113 } else { \
1066 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1114 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1067 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1115 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1068 - gen_op_load_gpr_T2(rS(ctx->opcode)); \  
1069 - gen_op_st##width##x(); \ 1116 + gen_op_add(); \
1070 } \ 1117 } \
1071 - SET_RETVAL(0); \ 1118 + gen_op_load_gpr_T1(rS(ctx->opcode)); \
  1119 + op_ldst(st##width); \
1072 } 1120 }
1073 1121
1074 -#define GEN_ISTO(width, opc) \  
1075 -GEN_IST(width, opc | 0x20) \  
1076 -GEN_ISTU(width, opc | 0x21) \  
1077 -GEN_ISTUX(width, opc | 0x01) \  
1078 -GEN_ISTX(width, 0x17, opc | 0x00) 1122 +#define GEN_STS(width, op) \
  1123 +OP_ST_TABLE(width); \
  1124 +GEN_ST(width, op | 0x20); \
  1125 +GEN_STU(width, op | 0x21); \
  1126 +GEN_STUX(width, op | 0x01); \
  1127 +GEN_STX(width, 0x17, op | 0x00)
1079 1128
1080 /* stb stbu stbux stbx */ 1129 /* stb stbu stbux stbx */
1081 -GEN_ISTO(b, 0x06); 1130 +GEN_STS(b, 0x06);
1082 /* sth sthu sthux sthx */ 1131 /* sth sthu sthux sthx */
1083 -GEN_ISTO(h, 0x0C); 1132 +GEN_STS(h, 0x0C);
1084 /* stw stwu stwux stwx */ 1133 /* stw stwu stwux stwx */
1085 -GEN_ISTO(w, 0x04); 1134 +GEN_STS(w, 0x04);
1086 1135
1087 /*** Integer load and store with byte reverse ***/ 1136 /*** Integer load and store with byte reverse ***/
1088 /* lhbrx */ 1137 /* lhbrx */
1089 -GEN_ILDZX(hbr, 0x16, 0x18); 1138 +OP_LD_TABLE(hbr);
  1139 +GEN_LDX(hbr, 0x16, 0x18);
1090 /* lwbrx */ 1140 /* lwbrx */
1091 -GEN_ILDZX(wbr, 0x16, 0x10); 1141 +OP_LD_TABLE(wbr);
  1142 +GEN_LDX(wbr, 0x16, 0x10);
1092 /* sthbrx */ 1143 /* sthbrx */
1093 -GEN_ISTX(hbr, 0x16, 0x1C); 1144 +OP_ST_TABLE(hbr);
  1145 +GEN_STX(hbr, 0x16, 0x1C);
1094 /* stwbrx */ 1146 /* stwbrx */
1095 -GEN_ISTX(wbr, 0x16, 0x14); 1147 +OP_ST_TABLE(wbr);
  1148 +GEN_STX(wbr, 0x16, 0x14);
1096 1149
1097 /*** Integer load and store multiple ***/ 1150 /*** Integer load and store multiple ***/
  1151 +#if defined(CONFIG_USER_ONLY)
  1152 +#define op_ldstm(name, reg) gen_op_##name##_raw(reg)
  1153 +#else
  1154 +#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
  1155 +static GenOpFunc1 *gen_op_lmw[] = {
  1156 + &gen_op_lmw_user,
  1157 + &gen_op_lmw_kernel,
  1158 +};
  1159 +static GenOpFunc1 *gen_op_stmw[] = {
  1160 + &gen_op_stmw_user,
  1161 + &gen_op_stmw_kernel,
  1162 +};
  1163 +#endif
  1164 +
1098 /* lmw */ 1165 /* lmw */
1099 GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 1166 GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1100 { 1167 {
  1168 + int simm = SIMM(ctx->opcode);
  1169 +
1101 if (rA(ctx->opcode) == 0) { 1170 if (rA(ctx->opcode) == 0) {
1102 - gen_op_set_T0(0); 1171 + gen_op_set_T0(simm);
1103 } else { 1172 } else {
1104 gen_op_load_gpr_T0(rA(ctx->opcode)); 1173 gen_op_load_gpr_T0(rA(ctx->opcode));
  1174 + if (simm != 0)
  1175 + gen_op_addi(simm);
1105 } 1176 }
1106 - gen_op_lmw(rD(ctx->opcode), SIMM(ctx->opcode));  
1107 - SET_RETVAL(0); 1177 + op_ldstm(lmw, rD(ctx->opcode));
1108 } 1178 }
1109 1179
1110 /* stmw */ 1180 /* stmw */
1111 GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) 1181 GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1112 { 1182 {
  1183 + int simm = SIMM(ctx->opcode);
  1184 +
1113 if (rA(ctx->opcode) == 0) { 1185 if (rA(ctx->opcode) == 0) {
1114 - gen_op_set_T0(0); 1186 + gen_op_set_T0(simm);
1115 } else { 1187 } else {
1116 gen_op_load_gpr_T0(rA(ctx->opcode)); 1188 gen_op_load_gpr_T0(rA(ctx->opcode));
  1189 + if (simm != 0)
  1190 + gen_op_addi(simm);
1117 } 1191 }
1118 - gen_op_stmw(rS(ctx->opcode), SIMM(ctx->opcode));  
1119 - SET_RETVAL(0); 1192 + op_ldstm(stmw, rS(ctx->opcode));
1120 } 1193 }
1121 1194
1122 /*** Integer load and store strings ***/ 1195 /*** Integer load and store strings ***/
  1196 +#if defined(CONFIG_USER_ONLY)
  1197 +#define op_ldsts(name, start) gen_op_##name##_raw(start)
  1198 +#define op_ldstsx(name, rd, ra, rb) gen_op_##name##_raw(rd, ra, rb)
  1199 +#else
  1200 +#define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
  1201 +#define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
  1202 +static GenOpFunc1 *gen_op_lswi[] = {
  1203 + &gen_op_lswi_user,
  1204 + &gen_op_lswi_kernel,
  1205 +};
  1206 +static GenOpFunc3 *gen_op_lswx[] = {
  1207 + &gen_op_lswx_user,
  1208 + &gen_op_lswx_kernel,
  1209 +};
  1210 +static GenOpFunc1 *gen_op_stsw[] = {
  1211 + &gen_op_stsw_user,
  1212 + &gen_op_stsw_kernel,
  1213 +};
  1214 +#endif
  1215 +
1123 /* lswi */ 1216 /* lswi */
  1217 +/* PPC32 specification says we must generate an exception if
  1218 + * rA is in the range of registers to be loaded.
  1219 + * In an other hand, IBM says this is valid, but rA won't be loaded.
  1220 + * For now, I'll follow the spec...
  1221 + */
1124 GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER) 1222 GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1125 { 1223 {
1126 int nb = NB(ctx->opcode); 1224 int nb = NB(ctx->opcode);
1127 int start = rD(ctx->opcode); 1225 int start = rD(ctx->opcode);
  1226 + int ra = rA(ctx->opcode);
1128 int nr; 1227 int nr;
1129 1228
1130 if (nb == 0) 1229 if (nb == 0)
1131 nb = 32; 1230 nb = 32;
1132 nr = nb / 4; 1231 nr = nb / 4;
1133 - if ((start + nr) > 32) {  
1134 - /* handle wrap around r0 */  
1135 - if (rA(ctx->opcode) == 0) {  
1136 - gen_op_set_T0(0);  
1137 - } else {  
1138 - gen_op_load_gpr_T0(rA(ctx->opcode)); 1232 + if (((start + nr) > 32 && start <= ra && (start + nr - 32) >= ra) ||
  1233 + ((start + nr) <= 32 && start <= ra && (start + nr) >= ra)) {
  1234 + RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
1139 } 1235 }
1140 - gen_op_lswi(start, 4 * (32 - start));  
1141 - nb -= 4 * (32 - start);  
1142 - start = 0;  
1143 - }  
1144 - if (rA(ctx->opcode) == 0) { 1236 + if (ra == 0) {
1145 gen_op_set_T0(0); 1237 gen_op_set_T0(0);
1146 } else { 1238 } else {
1147 - gen_op_load_gpr_T0(rA(ctx->opcode)); 1239 + gen_op_load_gpr_T0(ra);
1148 } 1240 }
1149 - gen_op_lswi(start, nb);  
1150 - SET_RETVAL(0); 1241 + gen_op_set_T1(nb);
  1242 + op_ldsts(lswi, start);
1151 } 1243 }
1152 1244
1153 /* lswx */ 1245 /* lswx */
1154 GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER) 1246 GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
1155 { 1247 {
1156 - gen_op_load_xer_bc();  
1157 - gen_op_load_gpr_T1(rB(ctx->opcode));  
1158 - if (rA(ctx->opcode) == 0) {  
1159 - gen_op_set_T2(0); 1248 + int ra = rA(ctx->opcode);
  1249 + int rb = rB(ctx->opcode);
  1250 +
  1251 + if (ra == 0) {
  1252 + gen_op_load_gpr_T0(rb);
  1253 + ra = rb;
1160 } else { 1254 } else {
1161 - gen_op_load_gpr_T2(rA(ctx->opcode)); 1255 + gen_op_load_gpr_T0(ra);
  1256 + gen_op_load_gpr_T1(rb);
  1257 + gen_op_add();
1162 } 1258 }
1163 - gen_op_lswx(rD(ctx->opcode));  
1164 - SET_RETVAL(0); 1259 + gen_op_load_xer_bc();
  1260 + op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
1165 } 1261 }
1166 1262
1167 /* stswi */ 1263 /* stswi */
1168 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER) 1264 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
1169 { 1265 {
1170 - int nb = NB(ctx->opcode);  
1171 - int start = rS(ctx->opcode);  
1172 - int nr;  
1173 -  
1174 - if (nb == 0)  
1175 - nb = 32;  
1176 - nr = nb / 4;  
1177 - if ((start + nr) > 32) {  
1178 - /* handle wrap around r0 */  
1179 - if (rA(ctx->opcode) == 0) {  
1180 - gen_op_set_T0(0);  
1181 - } else {  
1182 - gen_op_load_gpr_T0(rA(ctx->opcode));  
1183 - }  
1184 - gen_op_stswi(start, 4 * (32 - start));  
1185 - nb -= 4 * (32 - start);  
1186 - start = 0;  
1187 - }  
1188 if (rA(ctx->opcode) == 0) { 1266 if (rA(ctx->opcode) == 0) {
1189 gen_op_set_T0(0); 1267 gen_op_set_T0(0);
1190 } else { 1268 } else {
1191 gen_op_load_gpr_T0(rA(ctx->opcode)); 1269 gen_op_load_gpr_T0(rA(ctx->opcode));
1192 } 1270 }
1193 - gen_op_stswi(start, nb);  
1194 - SET_RETVAL(0); 1271 + gen_op_set_T1(NB(ctx->opcode));
  1272 + op_ldsts(stsw, rS(ctx->opcode));
1195 } 1273 }
1196 1274
1197 /* stswx */ 1275 /* stswx */
1198 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER) 1276 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
1199 { 1277 {
1200 - gen_op_load_xer_bc();  
1201 - gen_op_load_gpr_T1(rB(ctx->opcode));  
1202 - if (rA(ctx->opcode) == 0) {  
1203 - gen_op_set_T2(0); 1278 + int ra = rA(ctx->opcode);
  1279 +
  1280 + if (ra == 0) {
  1281 + gen_op_load_gpr_T0(rB(ctx->opcode));
  1282 + ra = rB(ctx->opcode);
1204 } else { 1283 } else {
1205 - gen_op_load_gpr_T2(rA(ctx->opcode)); 1284 + gen_op_load_gpr_T0(ra);
  1285 + gen_op_load_gpr_T1(rB(ctx->opcode));
  1286 + gen_op_add();
1206 } 1287 }
1207 - gen_op_stswx(rS(ctx->opcode));  
1208 - SET_RETVAL(0); 1288 + gen_op_load_xer_bc();
  1289 + op_ldsts(stsw, rS(ctx->opcode));
1209 } 1290 }
1210 1291
1211 /*** Memory synchronisation ***/ 1292 /*** Memory synchronisation ***/
1212 /* eieio */ 1293 /* eieio */
1213 GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM) 1294 GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
1214 { 1295 {
1215 - /* Do a branch to next instruction */  
1216 - gen_op_b((uint32_t)ctx->nip);  
1217 - SET_RETVAL(EXCP_BRANCH);  
1218 } 1296 }
1219 1297
1220 /* isync */ 1298 /* isync */
1221 GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM) 1299 GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
1222 { 1300 {
1223 - /* Do a branch to next instruction */  
1224 - gen_op_b((uint32_t)ctx->nip);  
1225 - SET_RETVAL(EXCP_BRANCH);  
1226 } 1301 }
1227 1302
1228 /* lwarx */ 1303 /* lwarx */
1229 -GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_MEM) 1304 +#if defined(CONFIG_USER_ONLY)
  1305 +#define op_stwcx() gen_op_stwcx_raw()
  1306 +#else
  1307 +#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
  1308 +static GenOpFunc *gen_op_stwcx[] = {
  1309 + &gen_op_stwcx_user,
  1310 + &gen_op_stwcx_kernel,
  1311 +};
  1312 +#endif
  1313 +
  1314 +GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_RES)
1230 { 1315 {
1231 - reserve = 1;  
1232 if (rA(ctx->opcode) == 0) { 1316 if (rA(ctx->opcode) == 0) {
1233 gen_op_load_gpr_T0(rB(ctx->opcode)); 1317 gen_op_load_gpr_T0(rB(ctx->opcode));
1234 - gen_op_lwarx_z();  
1235 } else { 1318 } else {
1236 gen_op_load_gpr_T0(rA(ctx->opcode)); 1319 gen_op_load_gpr_T0(rA(ctx->opcode));
1237 gen_op_load_gpr_T1(rB(ctx->opcode)); 1320 gen_op_load_gpr_T1(rB(ctx->opcode));
1238 - gen_op_lwarx(); 1321 + gen_op_add();
1239 } 1322 }
  1323 + op_ldst(lwz);
1240 gen_op_store_T1_gpr(rD(ctx->opcode)); 1324 gen_op_store_T1_gpr(rD(ctx->opcode));
1241 - SET_RETVAL(0); 1325 + gen_op_set_reservation();
1242 } 1326 }
1243 1327
1244 /* stwcx. */ 1328 /* stwcx. */
1245 -GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_MEM) 1329 +GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
1246 { 1330 {
1247 - if (reserve == 0) {  
1248 - gen_op_reset_Rc0();  
1249 - } else {  
1250 if (rA(ctx->opcode) == 0) { 1331 if (rA(ctx->opcode) == 0) {
1251 gen_op_load_gpr_T0(rB(ctx->opcode)); 1332 gen_op_load_gpr_T0(rB(ctx->opcode));
1252 - gen_op_load_gpr_T1(rS(ctx->opcode));  
1253 - gen_op_stwx_z();  
1254 } else { 1333 } else {
1255 gen_op_load_gpr_T0(rA(ctx->opcode)); 1334 gen_op_load_gpr_T0(rA(ctx->opcode));
1256 gen_op_load_gpr_T1(rB(ctx->opcode)); 1335 gen_op_load_gpr_T1(rB(ctx->opcode));
1257 - gen_op_load_gpr_T2(rS(ctx->opcode));  
1258 - gen_op_stwx(); 1336 + gen_op_add();
1259 } 1337 }
1260 - }  
1261 - SET_RETVAL(0); 1338 + gen_op_load_gpr_T1(rS(ctx->opcode));
  1339 + op_stwcx();
1262 } 1340 }
1263 1341
1264 /* sync */ 1342 /* sync */
1265 GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM) 1343 GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
1266 { 1344 {
1267 - /* Do a branch to next instruction */  
1268 - gen_op_b((uint32_t)ctx->nip);  
1269 - SET_RETVAL(EXCP_BRANCH);  
1270 } 1345 }
1271 1346
1272 /*** Floating-point load ***/ 1347 /*** Floating-point load ***/
1273 -#define GEN_LF(width, opc) \  
1274 -GEN_HANDLER(lf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ 1348 +#define GEN_LDF(width, opc) \
  1349 +GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1275 { \ 1350 { \
1276 uint32_t simm = SIMM(ctx->opcode); \ 1351 uint32_t simm = SIMM(ctx->opcode); \
1277 if (rA(ctx->opcode) == 0) { \ 1352 if (rA(ctx->opcode) == 0) { \
1278 - gen_op_lf##width##_z_FT0(simm); \ 1353 + gen_op_set_T0(simm); \
1279 } else { \ 1354 } else { \
1280 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1355 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1281 - gen_op_lf##width##_FT0(simm); \ 1356 + if (simm != 0) \
  1357 + gen_op_addi(simm); \
1282 } \ 1358 } \
1283 - gen_op_store_FT0_fpr(rD(ctx->opcode));\  
1284 - SET_RETVAL(0); \ 1359 + op_ldst(l##width); \
  1360 + gen_op_store_FT1_fpr(rD(ctx->opcode)); \
1285 } 1361 }
1286 1362
1287 -#define GEN_LFU(width, opc) \  
1288 -GEN_HANDLER(lf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ 1363 +#define GEN_LDUF(width, opc) \
  1364 +GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1289 { \ 1365 { \
  1366 + uint32_t simm = SIMM(ctx->opcode); \
1290 if (rA(ctx->opcode) == 0 || \ 1367 if (rA(ctx->opcode) == 0 || \
1291 - rA(ctx->opcode) == rD(ctx->opcode)) \  
1292 - SET_RETVAL(EXCP_INVAL); \ 1368 + rA(ctx->opcode) == rD(ctx->opcode)) { \
  1369 + RET_INVAL(); \
  1370 + } \
1293 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1371 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1294 - gen_op_lf##width##_FT0(SIMM(ctx->opcode)); \  
1295 - gen_op_store_FT0_fpr(rD(ctx->opcode));\ 1372 + if (simm != 0) \
  1373 + gen_op_addi(simm); \
  1374 + op_ldst(l##width); \
  1375 + gen_op_store_FT1_fpr(rD(ctx->opcode)); \
1296 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 1376 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1297 - SET_RETVAL(0); \  
1298 } 1377 }
1299 1378
1300 -#define GEN_LFUX(width, opc) \  
1301 -GEN_HANDLER(lf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ 1379 +#define GEN_LDUXF(width, opc) \
  1380 +GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1302 { \ 1381 { \
1303 if (rA(ctx->opcode) == 0 || \ 1382 if (rA(ctx->opcode) == 0 || \
1304 - rA(ctx->opcode) == rD(ctx->opcode)) \  
1305 - SET_RETVAL(EXCP_INVAL); \ 1383 + rA(ctx->opcode) == rD(ctx->opcode)) { \
  1384 + RET_INVAL(); \
  1385 + } \
1306 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1386 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1307 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1387 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1308 - gen_op_lf##width##x_FT0(); \  
1309 - gen_op_store_FT0_fpr(rD(ctx->opcode));\ 1388 + gen_op_add(); \
  1389 + op_ldst(l##width); \
  1390 + gen_op_store_FT1_fpr(rD(ctx->opcode)); \
1310 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 1391 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1311 - SET_RETVAL(0); \  
1312 } 1392 }
1313 1393
1314 -#define GEN_LFX(width, opc) \  
1315 -GEN_HANDLER(lf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ 1394 +#define GEN_LDXF(width, opc2, opc3) \
  1395 +GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1316 { \ 1396 { \
1317 if (rA(ctx->opcode) == 0) { \ 1397 if (rA(ctx->opcode) == 0) { \
1318 gen_op_load_gpr_T0(rB(ctx->opcode)); \ 1398 gen_op_load_gpr_T0(rB(ctx->opcode)); \
1319 - gen_op_lf##width##x_z_FT0(); \  
1320 } else { \ 1399 } else { \
1321 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1400 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1322 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1401 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1323 - gen_op_lf##width##x_FT0(); \ 1402 + gen_op_add(); \
1324 } \ 1403 } \
1325 - gen_op_store_FT0_fpr(rD(ctx->opcode));\  
1326 - SET_RETVAL(0); \ 1404 + op_ldst(l##width); \
  1405 + gen_op_store_FT1_fpr(rD(ctx->opcode)); \
1327 } 1406 }
1328 1407
1329 -#define GEN_LDF(width, opc) \  
1330 -GEN_LF(width, opc | 0x20) \  
1331 -GEN_LFU(width, opc | 0x21) \  
1332 -GEN_LFUX(width, opc | 0x01) \  
1333 -GEN_LFX(width, opc | 0x00) 1408 +#define GEN_LDFS(width, op) \
  1409 +OP_LD_TABLE(width); \
  1410 +GEN_LDF(width, op | 0x20); \
  1411 +GEN_LDUF(width, op | 0x21); \
  1412 +GEN_LDUXF(width, op | 0x01); \
  1413 +GEN_LDXF(width, 0x17, op | 0x00)
1334 1414
1335 /* lfd lfdu lfdux lfdx */ 1415 /* lfd lfdu lfdux lfdx */
1336 -GEN_LDF(d, 0x12); 1416 +GEN_LDFS(fd, 0x12);
1337 /* lfs lfsu lfsux lfsx */ 1417 /* lfs lfsu lfsux lfsx */
1338 -GEN_LDF(s, 0x10); 1418 +GEN_LDFS(fs, 0x10);
1339 1419
1340 /*** Floating-point store ***/ 1420 /*** Floating-point store ***/
1341 #define GEN_STF(width, opc) \ 1421 #define GEN_STF(width, opc) \
1342 -GEN_HANDLER(stf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ 1422 +GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1343 { \ 1423 { \
1344 uint32_t simm = SIMM(ctx->opcode); \ 1424 uint32_t simm = SIMM(ctx->opcode); \
1345 - gen_op_load_fpr_FT0(rS(ctx->opcode));\  
1346 if (rA(ctx->opcode) == 0) { \ 1425 if (rA(ctx->opcode) == 0) { \
1347 - gen_op_stf##width##_z_FT0(simm); \ 1426 + gen_op_set_T0(simm); \
1348 } else { \ 1427 } else { \
1349 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1428 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1350 - gen_op_stf##width##_FT0(simm); \ 1429 + if (simm != 0) \
  1430 + gen_op_addi(simm); \
1351 } \ 1431 } \
1352 - SET_RETVAL(0); \ 1432 + gen_op_load_fpr_FT1(rS(ctx->opcode)); \
  1433 + op_ldst(st##width); \
1353 } 1434 }
1354 1435
1355 -#define GEN_STFU(width, opc) \  
1356 -GEN_HANDLER(stf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ 1436 +#define GEN_STUF(width, opc) \
  1437 +GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1357 { \ 1438 { \
1358 - if (rA(ctx->opcode) == 0) \  
1359 - SET_RETVAL(EXCP_INVAL); \ 1439 + uint32_t simm = SIMM(ctx->opcode); \
  1440 + if (rA(ctx->opcode) == 0) { \
  1441 + RET_INVAL(); \
  1442 + } \
1360 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1443 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1361 - gen_op_load_fpr_FT0(rS(ctx->opcode));\  
1362 - gen_op_stf##width##_FT0(SIMM(ctx->opcode)); \ 1444 + if (simm != 0) \
  1445 + gen_op_addi(simm); \
  1446 + gen_op_load_fpr_FT1(rS(ctx->opcode)); \
  1447 + op_ldst(st##width); \
1363 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 1448 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1364 - SET_RETVAL(0); \  
1365 } 1449 }
1366 1450
1367 -#define GEN_STFUX(width, opc) \  
1368 -GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ 1451 +#define GEN_STUXF(width, opc) \
  1452 +GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1369 { \ 1453 { \
1370 - if (rA(ctx->opcode) == 0) \  
1371 - SET_RETVAL(EXCP_INVAL); \ 1454 + if (rA(ctx->opcode) == 0) { \
  1455 + RET_INVAL(); \
  1456 + } \
1372 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1457 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1373 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1458 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1374 - gen_op_load_fpr_FT0(rS(ctx->opcode));\  
1375 - gen_op_stf##width##x_FT0(); \ 1459 + gen_op_add(); \
  1460 + gen_op_load_fpr_FT1(rS(ctx->opcode)); \
  1461 + op_ldst(st##width); \
1376 gen_op_store_T0_gpr(rA(ctx->opcode)); \ 1462 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1377 - SET_RETVAL(0); \  
1378 } 1463 }
1379 1464
1380 -#define GEN_STFX(width, opc) \  
1381 -GEN_HANDLER(stf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ 1465 +#define GEN_STXF(width, opc2, opc3) \
  1466 +GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1382 { \ 1467 { \
1383 - gen_op_load_fpr_FT0(rS(ctx->opcode));\  
1384 if (rA(ctx->opcode) == 0) { \ 1468 if (rA(ctx->opcode) == 0) { \
1385 gen_op_load_gpr_T0(rB(ctx->opcode)); \ 1469 gen_op_load_gpr_T0(rB(ctx->opcode)); \
1386 - gen_op_stf##width##x_z_FT0(); \  
1387 } else { \ 1470 } else { \
1388 gen_op_load_gpr_T0(rA(ctx->opcode)); \ 1471 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1389 gen_op_load_gpr_T1(rB(ctx->opcode)); \ 1472 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1390 - gen_op_stf##width##x_FT0(); \ 1473 + gen_op_add(); \
1391 } \ 1474 } \
1392 - SET_RETVAL(0); \ 1475 + gen_op_load_fpr_FT1(rS(ctx->opcode)); \
  1476 + op_ldst(st##width); \
1393 } 1477 }
1394 1478
1395 -#define GEN_STOF(width, opc) \  
1396 -GEN_STF(width, opc | 0x20) \  
1397 -GEN_STFU(width, opc | 0x21) \  
1398 -GEN_STFUX(width, opc | 0x01) \  
1399 -GEN_STFX(width, opc | 0x00) 1479 +#define GEN_STFS(width, op) \
  1480 +OP_ST_TABLE(width); \
  1481 +GEN_STF(width, op | 0x20); \
  1482 +GEN_STUF(width, op | 0x21); \
  1483 +GEN_STUXF(width, op | 0x01); \
  1484 +GEN_STXF(width, 0x17, op | 0x00)
1400 1485
1401 /* stfd stfdu stfdux stfdx */ 1486 /* stfd stfdu stfdux stfdx */
1402 -GEN_STOF(d, 0x16); 1487 +GEN_STFS(fd, 0x16);
1403 /* stfs stfsu stfsux stfsx */ 1488 /* stfs stfsu stfsux stfsx */
1404 -GEN_STOF(s, 0x14); 1489 +GEN_STFS(fs, 0x14);
1405 1490
1406 /* Optional: */ 1491 /* Optional: */
1407 /* stfiwx */ 1492 /* stfiwx */
1408 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT) 1493 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
1409 { 1494 {
1410 - SET_RETVAL(EXCP_INVAL);  
1411 -}  
1412 -  
1413 -/*** Floating-point move ***/  
1414 -/* fabs */  
1415 -GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT)  
1416 -{  
1417 - SET_RETVAL(EXCP_INVAL);  
1418 -}  
1419 -  
1420 -/* fmr */  
1421 -GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)  
1422 -{  
1423 - SET_RETVAL(EXCP_INVAL);  
1424 -}  
1425 -  
1426 -/* fnabs */  
1427 -GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT)  
1428 -{  
1429 - SET_RETVAL(EXCP_INVAL);  
1430 -}  
1431 -  
1432 -/* fneg */  
1433 -GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT)  
1434 -{  
1435 - SET_RETVAL(EXCP_INVAL); 1495 + RET_INVAL();
1436 } 1496 }
1437 1497
1438 /*** Branch ***/ 1498 /*** Branch ***/
1439 #define GEN_BCOND(name, opc1, opc2, opc3, prologue, \ 1499 #define GEN_BCOND(name, opc1, opc2, opc3, prologue, \
1440 - bl_ctr, b_ctr, bl_ctrz, b_ctrz, b, \ 1500 + bl_ctr, b_ctr, bl_ctrz, b_ctrz, b, bl, \
1441 bl_ctr_true, b_ctr_true, bl_ctrz_true, b_ctrz_true, bl_true, b_true, \ 1501 bl_ctr_true, b_ctr_true, bl_ctrz_true, b_ctrz_true, bl_true, b_true, \
1442 bl_ctr_false, b_ctr_false, bl_ctrz_false, b_ctrz_false, bl_false, b_false) \ 1502 bl_ctr_false, b_ctr_false, bl_ctrz_false, b_ctrz_false, bl_false, b_false) \
1443 GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \ 1503 GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
@@ -1446,7 +1506,11 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \ @@ -1446,7 +1506,11 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1446 uint32_t bo = BO(ctx->opcode); \ 1506 uint32_t bo = BO(ctx->opcode); \
1447 uint32_t bi = BI(ctx->opcode); \ 1507 uint32_t bi = BI(ctx->opcode); \
1448 uint32_t mask; \ 1508 uint32_t mask; \
  1509 + gen_op_update_tb(ctx->tb_offset); \
  1510 + gen_op_update_decr(ctx->decr_offset); \
  1511 + gen_op_process_exceptions((uint32_t)ctx->nip - 4); \
1449 prologue; \ 1512 prologue; \
  1513 +/* gen_op_set_T1((uint32_t)ctx->tb);*/ \
1450 if ((bo & 0x4) == 0) \ 1514 if ((bo & 0x4) == 0) \
1451 gen_op_dec_ctr(); \ 1515 gen_op_dec_ctr(); \
1452 if (bo & 0x10) { \ 1516 if (bo & 0x10) { \
@@ -1468,13 +1532,15 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \ @@ -1468,13 +1532,15 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1468 break; \ 1532 break; \
1469 case 4: \ 1533 case 4: \
1470 case 6: \ 1534 case 6: \
  1535 + if (LK(ctx->opcode)) { \
  1536 + bl; \
  1537 + } else { \
1471 b; \ 1538 b; \
1472 - if (LK(ctx->opcode)) \  
1473 - gen_op_load_lr((uint32_t)ctx->nip); \ 1539 + } \
1474 break; \ 1540 break; \
1475 default: \ 1541 default: \
1476 printf("ERROR: %s: unhandled ba case (%d)\n", __func__, bo); \ 1542 printf("ERROR: %s: unhandled ba case (%d)\n", __func__, bo); \
1477 - SET_RETVAL(EXCP_INVAL); \ 1543 + RET_INVAL(); \
1478 break; \ 1544 break; \
1479 } \ 1545 } \
1480 } else { \ 1546 } else { \
@@ -1506,7 +1572,7 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \ @@ -1506,7 +1572,7 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1506 break; \ 1572 break; \
1507 default: \ 1573 default: \
1508 printf("ERROR: %s: unhandled b case (%d)\n", __func__, bo); \ 1574 printf("ERROR: %s: unhandled b case (%d)\n", __func__, bo); \
1509 - SET_RETVAL(EXCP_INVAL); \ 1575 + RET_INVAL(); \
1510 break; \ 1576 break; \
1511 } \ 1577 } \
1512 } else { \ 1578 } else { \
@@ -1535,12 +1601,12 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \ @@ -1535,12 +1601,12 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1535 break; \ 1601 break; \
1536 default: \ 1602 default: \
1537 printf("ERROR: %s: unhandled bn case (%d)\n", __func__, bo); \ 1603 printf("ERROR: %s: unhandled bn case (%d)\n", __func__, bo); \
1538 - SET_RETVAL(EXCP_INVAL); \ 1604 + RET_INVAL(); \
1539 break; \ 1605 break; \
1540 } \ 1606 } \
1541 } \ 1607 } \
1542 } \ 1608 } \
1543 - SET_RETVAL(EXCP_BRANCH); \ 1609 + ctx->exception = EXCP_BRANCH; \
1544 } 1610 }
1545 1611
1546 /* b ba bl bla */ 1612 /* b ba bl bla */
@@ -1548,14 +1614,20 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) @@ -1548,14 +1614,20 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1548 { 1614 {
1549 uint32_t li = s_ext24(LI(ctx->opcode)), target; 1615 uint32_t li = s_ext24(LI(ctx->opcode)), target;
1550 1616
  1617 + gen_op_update_tb(ctx->tb_offset);
  1618 + gen_op_update_decr(ctx->decr_offset);
  1619 + gen_op_process_exceptions((uint32_t)ctx->nip - 4);
1551 if (AA(ctx->opcode) == 0) 1620 if (AA(ctx->opcode) == 0)
1552 target = (uint32_t)ctx->nip + li - 4; 1621 target = (uint32_t)ctx->nip + li - 4;
1553 else 1622 else
1554 - target = s_ext24(LI(ctx->opcode)); 1623 + target = li;
  1624 +// gen_op_set_T1((uint32_t)ctx->tb);
  1625 + if (LK(ctx->opcode)) {
  1626 + gen_op_bl(target, (uint32_t)ctx->nip);
  1627 + } else {
1555 gen_op_b(target); 1628 gen_op_b(target);
1556 - if (LK(ctx->opcode))  
1557 - gen_op_load_lr((uint32_t)ctx->nip);  
1558 - SET_RETVAL(EXCP_BRANCH); 1629 + }
  1630 + ctx->exception = EXCP_BRANCH;
1559 } 1631 }
1560 1632
1561 /* bc bca bcl bcla */ 1633 /* bc bca bcl bcla */
@@ -1573,6 +1645,7 @@ GEN_BCOND(bc, 0x10, 0xFF, 0xFF, @@ -1573,6 +1645,7 @@ GEN_BCOND(bc, 0x10, 0xFF, 0xFF,
1573 gen_op_bl_ctrz((uint32_t)ctx->nip, target), 1645 gen_op_bl_ctrz((uint32_t)ctx->nip, target),
1574 gen_op_b_ctrz((uint32_t)ctx->nip, target), 1646 gen_op_b_ctrz((uint32_t)ctx->nip, target),
1575 gen_op_b(target), 1647 gen_op_b(target),
  1648 + gen_op_bl(target, (uint32_t)ctx->nip),
1576 gen_op_bl_ctr_true((uint32_t)ctx->nip, target, mask), 1649 gen_op_bl_ctr_true((uint32_t)ctx->nip, target, mask),
1577 gen_op_b_ctr_true((uint32_t)ctx->nip, target, mask), 1650 gen_op_b_ctr_true((uint32_t)ctx->nip, target, mask),
1578 gen_op_bl_ctrz_true((uint32_t)ctx->nip, target, mask), 1651 gen_op_bl_ctrz_true((uint32_t)ctx->nip, target, mask),
@@ -1593,6 +1666,7 @@ GEN_BCOND(bcctr, 0x13, 0x10, 0x10, do { } while (0), @@ -1593,6 +1666,7 @@ GEN_BCOND(bcctr, 0x13, 0x10, 0x10, do { } while (0),
1593 gen_op_bctrl_ctrz((uint32_t)ctx->nip), 1666 gen_op_bctrl_ctrz((uint32_t)ctx->nip),
1594 gen_op_bctr_ctrz((uint32_t)ctx->nip), 1667 gen_op_bctr_ctrz((uint32_t)ctx->nip),
1595 gen_op_bctr(), 1668 gen_op_bctr(),
  1669 + gen_op_bctrl((uint32_t)ctx->nip),
1596 gen_op_bctrl_ctr_true((uint32_t)ctx->nip, mask), 1670 gen_op_bctrl_ctr_true((uint32_t)ctx->nip, mask),
1597 gen_op_bctr_ctr_true((uint32_t)ctx->nip, mask), 1671 gen_op_bctr_ctr_true((uint32_t)ctx->nip, mask),
1598 gen_op_bctrl_ctrz_true((uint32_t)ctx->nip, mask), 1672 gen_op_bctrl_ctrz_true((uint32_t)ctx->nip, mask),
@@ -1613,6 +1687,7 @@ GEN_BCOND(bclr, 0x13, 0x10, 0x00, do { } while (0), @@ -1613,6 +1687,7 @@ GEN_BCOND(bclr, 0x13, 0x10, 0x00, do { } while (0),
1613 gen_op_blrl_ctrz((uint32_t)ctx->nip), 1687 gen_op_blrl_ctrz((uint32_t)ctx->nip),
1614 gen_op_blr_ctrz((uint32_t)ctx->nip), 1688 gen_op_blr_ctrz((uint32_t)ctx->nip),
1615 gen_op_blr(), 1689 gen_op_blr(),
  1690 + gen_op_blrl((uint32_t)ctx->nip),
1616 gen_op_blrl_ctr_true((uint32_t)ctx->nip, mask), 1691 gen_op_blrl_ctr_true((uint32_t)ctx->nip, mask),
1617 gen_op_blr_ctr_true((uint32_t)ctx->nip, mask), 1692 gen_op_blr_ctr_true((uint32_t)ctx->nip, mask),
1618 gen_op_blrl_ctrz_true((uint32_t)ctx->nip, mask), 1693 gen_op_blrl_ctrz_true((uint32_t)ctx->nip, mask),
@@ -1639,7 +1714,6 @@ GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \ @@ -1639,7 +1714,6 @@ GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
1639 gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \ 1714 gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \
1640 3 - (crbD(ctx->opcode) & 0x03)); \ 1715 3 - (crbD(ctx->opcode) & 0x03)); \
1641 gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \ 1716 gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \
1642 - SET_RETVAL(0); \  
1643 } 1717 }
1644 1718
1645 /* crand */ 1719 /* crand */
@@ -1663,34 +1737,53 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER) @@ -1663,34 +1737,53 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
1663 { 1737 {
1664 gen_op_load_crf_T0(crfS(ctx->opcode)); 1738 gen_op_load_crf_T0(crfS(ctx->opcode));
1665 gen_op_store_T0_crf(crfD(ctx->opcode)); 1739 gen_op_store_T0_crf(crfD(ctx->opcode));
1666 - SET_RETVAL(0);  
1667 } 1740 }
1668 1741
1669 /*** System linkage ***/ 1742 /*** System linkage ***/
1670 /* rfi (supervisor only) */ 1743 /* rfi (supervisor only) */
1671 GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW) 1744 GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1672 { 1745 {
1673 - SET_RETVAL(EXCP_INVAL); 1746 +#if defined(CONFIG_USER_ONLY)
  1747 + RET_PRIVOPC();
  1748 +#else
  1749 + /* Restore CPU state */
  1750 + if (!ctx->supervisor) {
  1751 + RET_PRIVOPC();
  1752 + }
  1753 + gen_op_rfi();
  1754 + ctx->exception = EXCP_RFI;
  1755 +#endif
1674 } 1756 }
1675 1757
1676 /* sc */ 1758 /* sc */
1677 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW) 1759 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
1678 { 1760 {
1679 - gen_op_b((uint32_t)ctx->nip);  
1680 - SET_RETVAL(EXCP_SYSCALL); 1761 +#if defined(CONFIG_USER_ONLY)
  1762 + gen_op_queue_exception(EXCP_SYSCALL_USER);
  1763 +#else
  1764 + gen_op_queue_exception(EXCP_SYSCALL);
  1765 +#endif
  1766 + ctx->exception = EXCP_SYSCALL;
1681 } 1767 }
1682 1768
1683 /*** Trap ***/ 1769 /*** Trap ***/
1684 /* tw */ 1770 /* tw */
1685 GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW) 1771 GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW)
1686 { 1772 {
1687 - SET_RETVAL(EXCP_INVAL); 1773 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1774 + gen_op_load_gpr_T1(rB(ctx->opcode));
  1775 + gen_op_tw(TO(ctx->opcode));
1688 } 1776 }
1689 1777
1690 /* twi */ 1778 /* twi */
1691 GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW) 1779 GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1692 { 1780 {
1693 - SET_RETVAL(EXCP_INVAL); 1781 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1782 +#if 0
  1783 + printf("%s: param=0x%04x T0=0x%04x\n", __func__,
  1784 + SIMM(ctx->opcode), TO(ctx->opcode));
  1785 +#endif
  1786 + gen_op_twi(SIMM(ctx->opcode), TO(ctx->opcode));
1694 } 1787 }
1695 1788
1696 /*** Processor control ***/ 1789 /*** Processor control ***/
@@ -1698,6 +1791,21 @@ static inline int check_spr_access (int spr, int rw, int supervisor) @@ -1698,6 +1791,21 @@ static inline int check_spr_access (int spr, int rw, int supervisor)
1698 { 1791 {
1699 uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1)); 1792 uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1));
1700 1793
  1794 +#if 0
  1795 + if (spr != LR && spr != CTR) {
  1796 + if (loglevel > 0) {
  1797 + fprintf(logfile, "%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
  1798 + SPR_ENCODE(spr), supervisor, rw, rights,
  1799 + (rights >> ((2 * supervisor) + rw)) & 1);
  1800 + } else {
  1801 + printf("%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
  1802 + SPR_ENCODE(spr), supervisor, rw, rights,
  1803 + (rights >> ((2 * supervisor) + rw)) & 1);
  1804 + }
  1805 + }
  1806 +#endif
  1807 + if (rights == 0)
  1808 + return -1;
1701 rights = rights >> (2 * supervisor); 1809 rights = rights >> (2 * supervisor);
1702 rights = rights >> rw; 1810 rights = rights >> rw;
1703 1811
@@ -1710,7 +1818,6 @@ GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC) @@ -1710,7 +1818,6 @@ GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
1710 gen_op_load_xer_cr(); 1818 gen_op_load_xer_cr();
1711 gen_op_store_T0_crf(crfD(ctx->opcode)); 1819 gen_op_store_T0_crf(crfD(ctx->opcode));
1712 gen_op_clear_xer_cr(); 1820 gen_op_clear_xer_cr();
1713 - SET_RETVAL(0);  
1714 } 1821 }
1715 1822
1716 /* mfcr */ 1823 /* mfcr */
@@ -1718,17 +1825,20 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC) @@ -1718,17 +1825,20 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
1718 { 1825 {
1719 gen_op_load_cr(); 1826 gen_op_load_cr();
1720 gen_op_store_T0_gpr(rD(ctx->opcode)); 1827 gen_op_store_T0_gpr(rD(ctx->opcode));
1721 - SET_RETVAL(0);  
1722 } 1828 }
1723 1829
1724 /* mfmsr */ 1830 /* mfmsr */
1725 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC) 1831 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
1726 { 1832 {
1727 - if (!ctx->supervisor)  
1728 - SET_RETVAL(EXCP_PRIV); 1833 +#if defined(CONFIG_USER_ONLY)
  1834 + RET_PRIVREG();
  1835 +#else
  1836 + if (!ctx->supervisor) {
  1837 + RET_PRIVREG();
  1838 + }
1729 gen_op_load_msr(); 1839 gen_op_load_msr();
1730 gen_op_store_T0_gpr(rD(ctx->opcode)); 1840 gen_op_store_T0_gpr(rD(ctx->opcode));
1731 - SET_RETVAL(0); 1841 +#endif
1732 } 1842 }
1733 1843
1734 /* mfspr */ 1844 /* mfspr */
@@ -1736,31 +1846,150 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC) @@ -1736,31 +1846,150 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
1736 { 1846 {
1737 uint32_t sprn = SPR(ctx->opcode); 1847 uint32_t sprn = SPR(ctx->opcode);
1738 1848
1739 - if (check_spr_access(sprn, 0, ctx->supervisor) == 0)  
1740 - SET_RETVAL(EXCP_PRIV);  
1741 - /* XXX: make this more generic */  
1742 - switch (sprn) {  
1743 - case SPR_ENCODE(1):  
1744 - if (loglevel > 0) {  
1745 - fprintf(logfile, "LOAD XER at %p\n", ctx->nip - 1); 1849 +#if defined(CONFIG_USER_ONLY)
  1850 + switch (check_spr_access(sprn, 0, 0))
  1851 +#else
  1852 + switch (check_spr_access(sprn, 0, ctx->supervisor))
  1853 +#endif
  1854 + {
  1855 + case -1:
  1856 + RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
  1857 + break;
  1858 + case 0:
  1859 + RET_PRIVREG();
  1860 + break;
  1861 + default:
  1862 + break;
1746 } 1863 }
  1864 + switch (sprn) {
  1865 + case XER:
1747 gen_op_load_xer(); 1866 gen_op_load_xer();
1748 break; 1867 break;
1749 - case SPR_ENCODE(268):  
1750 - /* We need to update the time base before reading it */ 1868 + case LR:
  1869 + gen_op_load_lr();
  1870 + break;
  1871 + case CTR:
  1872 + gen_op_load_ctr();
  1873 + break;
  1874 + case IBAT0U:
  1875 + gen_op_load_ibat(0, 0);
  1876 + break;
  1877 + case IBAT1U:
  1878 + gen_op_load_ibat(0, 1);
  1879 + break;
  1880 + case IBAT2U:
  1881 + gen_op_load_ibat(0, 2);
  1882 + break;
  1883 + case IBAT3U:
  1884 + gen_op_load_ibat(0, 3);
  1885 + break;
  1886 + case IBAT4U:
  1887 + gen_op_load_ibat(0, 4);
  1888 + break;
  1889 + case IBAT5U:
  1890 + gen_op_load_ibat(0, 5);
  1891 + break;
  1892 + case IBAT6U:
  1893 + gen_op_load_ibat(0, 6);
  1894 + break;
  1895 + case IBAT7U:
  1896 + gen_op_load_ibat(0, 7);
  1897 + break;
  1898 + case IBAT0L:
  1899 + gen_op_load_ibat(1, 0);
  1900 + break;
  1901 + case IBAT1L:
  1902 + gen_op_load_ibat(1, 1);
  1903 + break;
  1904 + case IBAT2L:
  1905 + gen_op_load_ibat(1, 2);
  1906 + break;
  1907 + case IBAT3L:
  1908 + gen_op_load_ibat(1, 3);
  1909 + break;
  1910 + case IBAT4L:
  1911 + gen_op_load_ibat(1, 4);
  1912 + break;
  1913 + case IBAT5L:
  1914 + gen_op_load_ibat(1, 5);
  1915 + break;
  1916 + case IBAT6L:
  1917 + gen_op_load_ibat(1, 6);
  1918 + break;
  1919 + case IBAT7L:
  1920 + gen_op_load_ibat(1, 7);
  1921 + break;
  1922 + case DBAT0U:
  1923 + gen_op_load_dbat(0, 0);
  1924 + break;
  1925 + case DBAT1U:
  1926 + gen_op_load_dbat(0, 1);
  1927 + break;
  1928 + case DBAT2U:
  1929 + gen_op_load_dbat(0, 2);
  1930 + break;
  1931 + case DBAT3U:
  1932 + gen_op_load_dbat(0, 3);
  1933 + break;
  1934 + case DBAT4U:
  1935 + gen_op_load_dbat(0, 4);
  1936 + break;
  1937 + case DBAT5U:
  1938 + gen_op_load_dbat(0, 5);
  1939 + break;
  1940 + case DBAT6U:
  1941 + gen_op_load_dbat(0, 6);
  1942 + break;
  1943 + case DBAT7U:
  1944 + gen_op_load_dbat(0, 7);
  1945 + break;
  1946 + case DBAT0L:
  1947 + gen_op_load_dbat(1, 0);
  1948 + break;
  1949 + case DBAT1L:
  1950 + gen_op_load_dbat(1, 1);
  1951 + break;
  1952 + case DBAT2L:
  1953 + gen_op_load_dbat(1, 2);
  1954 + break;
  1955 + case DBAT3L:
  1956 + gen_op_load_dbat(1, 3);
  1957 + break;
  1958 + case DBAT4L:
  1959 + gen_op_load_dbat(1, 4);
  1960 + break;
  1961 + case DBAT5L:
  1962 + gen_op_load_dbat(1, 5);
  1963 + break;
  1964 + case DBAT6L:
  1965 + gen_op_load_dbat(1, 6);
  1966 + break;
  1967 + case DBAT7L:
  1968 + gen_op_load_dbat(1, 7);
  1969 + break;
  1970 + case SDR1:
  1971 + gen_op_load_sdr1();
  1972 + break;
  1973 + case V_TBL:
1751 gen_op_update_tb(ctx->tb_offset); 1974 gen_op_update_tb(ctx->tb_offset);
1752 ctx->tb_offset = 0; 1975 ctx->tb_offset = 0;
  1976 + /* TBL is still in T0 */
1753 break; 1977 break;
1754 - case SPR_ENCODE(269): 1978 + case V_TBU:
1755 gen_op_update_tb(ctx->tb_offset); 1979 gen_op_update_tb(ctx->tb_offset);
1756 ctx->tb_offset = 0; 1980 ctx->tb_offset = 0;
  1981 + gen_op_load_tb(1);
  1982 + break;
  1983 + case DECR:
  1984 + gen_op_update_decr(ctx->decr_offset);
  1985 + ctx->decr_offset = 0;
  1986 + /* decr is still in T0 */
1757 break; 1987 break;
1758 default: 1988 default:
1759 gen_op_load_spr(sprn); 1989 gen_op_load_spr(sprn);
1760 break; 1990 break;
1761 } 1991 }
1762 - gen_op_store_T0_gpr(rD(ctx->opcode)); //  
1763 - SET_RETVAL(0); 1992 + gen_op_store_T0_gpr(rD(ctx->opcode));
1764 } 1993 }
1765 1994
1766 /* mftb */ 1995 /* mftb */
@@ -1768,23 +1997,22 @@ GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC) @@ -1768,23 +1997,22 @@ GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC)
1768 { 1997 {
1769 uint32_t sprn = SPR(ctx->opcode); 1998 uint32_t sprn = SPR(ctx->opcode);
1770 1999
1771 - if (check_spr_access(sprn, 0, ctx->supervisor) == 0)  
1772 - SET_RETVAL(EXCP_PRIV);  
1773 - switch (sprn) {  
1774 - case SPR_ENCODE(268):  
1775 /* We need to update the time base before reading it */ 2000 /* We need to update the time base before reading it */
  2001 + switch (sprn) {
  2002 + case V_TBL:
1776 gen_op_update_tb(ctx->tb_offset); 2003 gen_op_update_tb(ctx->tb_offset);
1777 - ctx->tb_offset = 0; 2004 + /* TBL is still in T0 */
1778 break; 2005 break;
1779 - case SPR_ENCODE(269): 2006 + case V_TBU:
1780 gen_op_update_tb(ctx->tb_offset); 2007 gen_op_update_tb(ctx->tb_offset);
1781 - ctx->tb_offset = 0; 2008 + gen_op_load_tb(1);
1782 break; 2009 break;
1783 default: 2010 default:
1784 - SET_RETVAL(EXCP_INVAL); 2011 + RET_INVAL();
1785 break; 2012 break;
1786 } 2013 }
1787 - SET_RETVAL(0); 2014 + ctx->tb_offset = 0;
  2015 + gen_op_store_T0_gpr(rD(ctx->opcode));
1788 } 2016 }
1789 2017
1790 /* mtcrf */ 2018 /* mtcrf */
@@ -1792,18 +2020,22 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC) @@ -1792,18 +2020,22 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC)
1792 { 2020 {
1793 gen_op_load_gpr_T0(rS(ctx->opcode)); 2021 gen_op_load_gpr_T0(rS(ctx->opcode));
1794 gen_op_store_cr(CRM(ctx->opcode)); 2022 gen_op_store_cr(CRM(ctx->opcode));
1795 - SET_RETVAL(0);  
1796 } 2023 }
1797 2024
1798 /* mtmsr */ 2025 /* mtmsr */
1799 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC) 2026 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
1800 { 2027 {
1801 - if (!ctx->supervisor)  
1802 - SET_RETVAL(EXCP_PRIV); 2028 +#if defined(CONFIG_USER_ONLY)
  2029 + RET_PRIVREG();
  2030 +#else
  2031 + if (!ctx->supervisor) {
  2032 + RET_PRIVREG();
  2033 + }
1803 gen_op_load_gpr_T0(rS(ctx->opcode)); 2034 gen_op_load_gpr_T0(rS(ctx->opcode));
1804 gen_op_store_msr(); 2035 gen_op_store_msr();
1805 /* Must stop the translation as machine state (may have) changed */ 2036 /* Must stop the translation as machine state (may have) changed */
1806 - SET_RETVAL(EXCP_MTMSR); 2037 + ctx->exception = EXCP_MTMSR;
  2038 +#endif
1807 } 2039 }
1808 2040
1809 /* mtspr */ 2041 /* mtspr */
@@ -1811,84 +2043,265 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC) @@ -1811,84 +2043,265 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
1811 { 2043 {
1812 uint32_t sprn = SPR(ctx->opcode); 2044 uint32_t sprn = SPR(ctx->opcode);
1813 2045
1814 - if (check_spr_access(sprn, 1, ctx->supervisor) == 0)  
1815 - SET_RETVAL(EXCP_PRIV); 2046 +#if 0
  2047 + if (loglevel > 0) {
  2048 + fprintf(logfile, "MTSPR %d src=%d (%d)\n", SPR_ENCODE(sprn),
  2049 + rS(ctx->opcode), sprn);
  2050 + }
  2051 +#endif
  2052 +#if defined(CONFIG_USER_ONLY)
  2053 + switch (check_spr_access(sprn, 1, 0))
  2054 +#else
  2055 + switch (check_spr_access(sprn, 1, ctx->supervisor))
  2056 +#endif
  2057 + {
  2058 + case -1:
  2059 + RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
  2060 + break;
  2061 + case 0:
  2062 + RET_PRIVREG();
  2063 + break;
  2064 + default:
  2065 + break;
  2066 + }
1816 gen_op_load_gpr_T0(rS(ctx->opcode)); 2067 gen_op_load_gpr_T0(rS(ctx->opcode));
1817 - if (sprn == SPR_ENCODE(1)) { 2068 + switch (sprn) {
  2069 + case XER:
1818 gen_op_store_xer(); 2070 gen_op_store_xer();
1819 - } else { 2071 + break;
  2072 + case LR:
  2073 + gen_op_andi_(~0x03);
  2074 + gen_op_store_lr();
  2075 + break;
  2076 + case CTR:
  2077 + gen_op_store_ctr();
  2078 + break;
  2079 + case IBAT0U:
  2080 + gen_op_store_ibat(0, 0);
  2081 + gen_op_tlbia();
  2082 + break;
  2083 + case IBAT1U:
  2084 + gen_op_store_ibat(0, 1);
  2085 + gen_op_tlbia();
  2086 + break;
  2087 + case IBAT2U:
  2088 + gen_op_store_ibat(0, 2);
  2089 + gen_op_tlbia();
  2090 + break;
  2091 + case IBAT3U:
  2092 + gen_op_store_ibat(0, 3);
  2093 + gen_op_tlbia();
  2094 + break;
  2095 + case IBAT4U:
  2096 + gen_op_store_ibat(0, 4);
  2097 + gen_op_tlbia();
  2098 + break;
  2099 + case IBAT5U:
  2100 + gen_op_store_ibat(0, 5);
  2101 + gen_op_tlbia();
  2102 + break;
  2103 + case IBAT6U:
  2104 + gen_op_store_ibat(0, 6);
  2105 + gen_op_tlbia();
  2106 + break;
  2107 + case IBAT7U:
  2108 + gen_op_store_ibat(0, 7);
  2109 + gen_op_tlbia();
  2110 + break;
  2111 + case IBAT0L:
  2112 + gen_op_store_ibat(1, 0);
  2113 + gen_op_tlbia();
  2114 + break;
  2115 + case IBAT1L:
  2116 + gen_op_store_ibat(1, 1);
  2117 + gen_op_tlbia();
  2118 + break;
  2119 + case IBAT2L:
  2120 + gen_op_store_ibat(1, 2);
  2121 + gen_op_tlbia();
  2122 + break;
  2123 + case IBAT3L:
  2124 + gen_op_store_ibat(1, 3);
  2125 + gen_op_tlbia();
  2126 + break;
  2127 + case IBAT4L:
  2128 + gen_op_store_ibat(1, 4);
  2129 + gen_op_tlbia();
  2130 + break;
  2131 + case IBAT5L:
  2132 + gen_op_store_ibat(1, 5);
  2133 + gen_op_tlbia();
  2134 + break;
  2135 + case IBAT6L:
  2136 + gen_op_store_ibat(1, 6);
  2137 + gen_op_tlbia();
  2138 + break;
  2139 + case IBAT7L:
  2140 + gen_op_store_ibat(1, 7);
  2141 + gen_op_tlbia();
  2142 + break;
  2143 + case DBAT0U:
  2144 + gen_op_store_dbat(0, 0);
  2145 + gen_op_tlbia();
  2146 + break;
  2147 + case DBAT1U:
  2148 + gen_op_store_dbat(0, 1);
  2149 + gen_op_tlbia();
  2150 + break;
  2151 + case DBAT2U:
  2152 + gen_op_store_dbat(0, 2);
  2153 + gen_op_tlbia();
  2154 + break;
  2155 + case DBAT3U:
  2156 + gen_op_store_dbat(0, 3);
  2157 + gen_op_tlbia();
  2158 + break;
  2159 + case DBAT4U:
  2160 + gen_op_store_dbat(0, 4);
  2161 + gen_op_tlbia();
  2162 + break;
  2163 + case DBAT5U:
  2164 + gen_op_store_dbat(0, 5);
  2165 + gen_op_tlbia();
  2166 + break;
  2167 + case DBAT6U:
  2168 + gen_op_store_dbat(0, 6);
  2169 + gen_op_tlbia();
  2170 + break;
  2171 + case DBAT7U:
  2172 + gen_op_store_dbat(0, 7);
  2173 + gen_op_tlbia();
  2174 + break;
  2175 + case DBAT0L:
  2176 + gen_op_store_dbat(1, 0);
  2177 + gen_op_tlbia();
  2178 + break;
  2179 + case DBAT1L:
  2180 + gen_op_store_dbat(1, 1);
  2181 + gen_op_tlbia();
  2182 + break;
  2183 + case DBAT2L:
  2184 + gen_op_store_dbat(1, 2);
  2185 + gen_op_tlbia();
  2186 + break;
  2187 + case DBAT3L:
  2188 + gen_op_store_dbat(1, 3);
  2189 + gen_op_tlbia();
  2190 + break;
  2191 + case DBAT4L:
  2192 + gen_op_store_dbat(1, 4);
  2193 + gen_op_tlbia();
  2194 + break;
  2195 + case DBAT5L:
  2196 + gen_op_store_dbat(1, 5);
  2197 + gen_op_tlbia();
  2198 + break;
  2199 + case DBAT6L:
  2200 + gen_op_store_dbat(1, 6);
  2201 + gen_op_tlbia();
  2202 + break;
  2203 + case DBAT7L:
  2204 + gen_op_store_dbat(1, 7);
  2205 + gen_op_tlbia();
  2206 + break;
  2207 + case SDR1:
  2208 + gen_op_store_sdr1();
  2209 + gen_op_tlbia();
  2210 + break;
  2211 + case O_TBL:
  2212 + gen_op_store_tb(0);
  2213 + ctx->tb_offset = 0;
  2214 + break;
  2215 + case O_TBU:
  2216 + gen_op_store_tb(1);
  2217 + ctx->tb_offset = 0;
  2218 + break;
  2219 + case DECR:
  2220 + gen_op_store_decr();
  2221 + ctx->decr_offset = 0;
  2222 + break;
  2223 + default:
1820 gen_op_store_spr(sprn); 2224 gen_op_store_spr(sprn);
  2225 + break;
1821 } 2226 }
1822 - SET_RETVAL(0);  
1823 } 2227 }
1824 2228
1825 /*** Cache management ***/ 2229 /*** Cache management ***/
1826 /* For now, all those will be implemented as nop: 2230 /* For now, all those will be implemented as nop:
1827 * this is valid, regarding the PowerPC specs... 2231 * this is valid, regarding the PowerPC specs...
  2232 + * We just have to flush tb while invalidating instruction cache lines...
1828 */ 2233 */
1829 /* dcbf */ 2234 /* dcbf */
1830 -GEN_HANDLER(dcbf, 0x1F, 0x16, 0x17, 0x03E00001, PPC_MEM) 2235 +GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
1831 { 2236 {
1832 - SET_RETVAL(0);  
1833 } 2237 }
1834 2238
1835 /* dcbi (Supervisor only) */ 2239 /* dcbi (Supervisor only) */
1836 -GEN_HANDLER(dcbi, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_MEM) 2240 +GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
1837 { 2241 {
1838 - SET_RETVAL(0); 2242 +#if !defined(CONFIG_USER_ONLY)
  2243 + if (!ctx->supervisor)
  2244 +#endif
  2245 + {
  2246 + RET_PRIVOPC();
  2247 + }
1839 } 2248 }
1840 2249
1841 /* dcdst */ 2250 /* dcdst */
1842 -GEN_HANDLER(dcbst, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_MEM) 2251 +GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
1843 { 2252 {
1844 - SET_RETVAL(0);  
1845 } 2253 }
1846 2254
1847 /* dcbt */ 2255 /* dcbt */
1848 -GEN_HANDLER(dcbt, 0x1F, 0x16, 0x01, 0x03E00001, PPC_MEM) 2256 +GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE)
1849 { 2257 {
1850 - SET_RETVAL(0);  
1851 } 2258 }
1852 2259
1853 /* dcbtst */ 2260 /* dcbtst */
1854 -GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x02, 0x03E00001, PPC_MEM) 2261 +GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE)
1855 { 2262 {
1856 - SET_RETVAL(0);  
1857 } 2263 }
1858 2264
1859 /* dcbz */ 2265 /* dcbz */
1860 -GEN_HANDLER(dcbz, 0x1F, 0x16, 0x08, 0x03E00001, PPC_MEM) 2266 +#if defined(CONFIG_USER_ONLY)
  2267 +#define op_dcbz() gen_op_dcbz_raw()
  2268 +#else
  2269 +#define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])()
  2270 +static GenOpFunc *gen_op_dcbz[] = {
  2271 + &gen_op_dcbz_user,
  2272 + &gen_op_dcbz_kernel,
  2273 +};
  2274 +#endif
  2275 +
  2276 +GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE)
1861 { 2277 {
1862 if (rA(ctx->opcode) == 0) { 2278 if (rA(ctx->opcode) == 0) {
1863 gen_op_load_gpr_T0(rB(ctx->opcode)); 2279 gen_op_load_gpr_T0(rB(ctx->opcode));
1864 - gen_op_dcbz_z();  
1865 } else { 2280 } else {
1866 gen_op_load_gpr_T0(rA(ctx->opcode)); 2281 gen_op_load_gpr_T0(rA(ctx->opcode));
1867 gen_op_load_gpr_T1(rB(ctx->opcode)); 2282 gen_op_load_gpr_T1(rB(ctx->opcode));
1868 - gen_op_dcbz(); 2283 + gen_op_add();
1869 } 2284 }
1870 - SET_RETVAL(0); 2285 + op_dcbz();
1871 } 2286 }
1872 2287
1873 /* icbi */ 2288 /* icbi */
1874 -GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_MEM) 2289 +GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
1875 { 2290 {
1876 if (rA(ctx->opcode) == 0) { 2291 if (rA(ctx->opcode) == 0) {
1877 gen_op_load_gpr_T0(rB(ctx->opcode)); 2292 gen_op_load_gpr_T0(rB(ctx->opcode));
1878 - gen_op_icbi_z();  
1879 } else { 2293 } else {
1880 gen_op_load_gpr_T0(rA(ctx->opcode)); 2294 gen_op_load_gpr_T0(rA(ctx->opcode));
1881 gen_op_load_gpr_T1(rB(ctx->opcode)); 2295 gen_op_load_gpr_T1(rB(ctx->opcode));
1882 - gen_op_icbi(); 2296 + gen_op_add();
1883 } 2297 }
1884 - SET_RETVAL(0); 2298 + gen_op_icbi();
1885 } 2299 }
1886 2300
1887 /* Optional: */ 2301 /* Optional: */
1888 /* dcba */ 2302 /* dcba */
1889 -GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_MEM) 2303 +GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE_OPT)
1890 { 2304 {
1891 - SET_RETVAL(0);  
1892 } 2305 }
1893 2306
1894 /*** Segment register manipulation ***/ 2307 /*** Segment register manipulation ***/
@@ -1896,70 +2309,163 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_MEM) @@ -1896,70 +2309,163 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_MEM)
1896 /* mfsr */ 2309 /* mfsr */
1897 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT) 2310 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
1898 { 2311 {
1899 - SET_RETVAL(EXCP_INVAL); 2312 +#if defined(CONFIG_USER_ONLY)
  2313 + RET_PRIVREG();
  2314 +#else
  2315 + if (!ctx->supervisor) {
  2316 + RET_PRIVREG();
  2317 + }
  2318 + gen_op_load_sr(SR(ctx->opcode));
  2319 + gen_op_store_T0_gpr(rD(ctx->opcode));
  2320 +#endif
1900 } 2321 }
1901 2322
1902 /* mfsrin */ 2323 /* mfsrin */
1903 -GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x0010F001, PPC_SEGMENT) 2324 +GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
1904 { 2325 {
1905 - SET_RETVAL(EXCP_INVAL); 2326 +#if defined(CONFIG_USER_ONLY)
  2327 + RET_PRIVREG();
  2328 +#else
  2329 + if (!ctx->supervisor) {
  2330 + RET_PRIVREG();
  2331 + }
  2332 + gen_op_load_gpr_T1(rB(ctx->opcode));
  2333 + gen_op_load_srin();
  2334 + gen_op_store_T0_gpr(rD(ctx->opcode));
  2335 +#endif
1906 } 2336 }
1907 2337
1908 /* mtsr */ 2338 /* mtsr */
1909 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT) 2339 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT)
1910 { 2340 {
1911 - SET_RETVAL(EXCP_INVAL); 2341 +#if defined(CONFIG_USER_ONLY)
  2342 + RET_PRIVREG();
  2343 +#else
  2344 + if (!ctx->supervisor) {
  2345 + RET_PRIVREG();
  2346 + }
  2347 + gen_op_load_gpr_T0(rS(ctx->opcode));
  2348 + gen_op_store_sr(SR(ctx->opcode));
  2349 + gen_op_tlbia();
  2350 +#endif
1912 } 2351 }
1913 2352
1914 /* mtsrin */ 2353 /* mtsrin */
1915 -GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x0010F001, PPC_SEGMENT) 2354 +GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
1916 { 2355 {
1917 - SET_RETVAL(EXCP_INVAL); 2356 +#if defined(CONFIG_USER_ONLY)
  2357 + RET_PRIVREG();
  2358 +#else
  2359 + if (!ctx->supervisor) {
  2360 + RET_PRIVREG();
  2361 + }
  2362 + gen_op_load_gpr_T0(rS(ctx->opcode));
  2363 + gen_op_load_gpr_T1(rB(ctx->opcode));
  2364 + gen_op_store_srin();
  2365 + gen_op_tlbia();
  2366 +#endif
1918 } 2367 }
1919 2368
1920 /*** Lookaside buffer management ***/ 2369 /*** Lookaside buffer management ***/
1921 /* Optional & supervisor only: */ 2370 /* Optional & supervisor only: */
1922 /* tlbia */ 2371 /* tlbia */
1923 -GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM) 2372 +GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT)
1924 { 2373 {
1925 - SET_RETVAL(EXCP_INVAL); 2374 +#if defined(CONFIG_USER_ONLY)
  2375 + RET_PRIVOPC();
  2376 +#else
  2377 + if (!ctx->supervisor) {
  2378 + RET_PRIVOPC();
  2379 + }
  2380 + gen_op_tlbia();
  2381 +#endif
1926 } 2382 }
1927 2383
1928 /* tlbie */ 2384 /* tlbie */
1929 -GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF8001, PPC_MEM) 2385 +GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
1930 { 2386 {
1931 - SET_RETVAL(EXCP_INVAL); 2387 +#if defined(CONFIG_USER_ONLY)
  2388 + RET_PRIVOPC();
  2389 +#else
  2390 + if (!ctx->supervisor) {
  2391 + RET_PRIVOPC();
  2392 + }
  2393 + gen_op_load_gpr_T0(rB(ctx->opcode));
  2394 + gen_op_tlbie();
  2395 +#endif
1932 } 2396 }
1933 2397
1934 /* tlbsync */ 2398 /* tlbsync */
1935 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFFC01, PPC_MEM) 2399 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFFC01, PPC_MEM)
1936 { 2400 {
1937 - SET_RETVAL(EXCP_INVAL); 2401 +#if defined(CONFIG_USER_ONLY)
  2402 + RET_PRIVOPC();
  2403 +#else
  2404 + if (!ctx->supervisor) {
  2405 + RET_PRIVOPC();
  2406 + }
  2407 + /* This has no effect: it should ensure that all previous
  2408 + * tlbie have completed
  2409 + */
  2410 +#endif
1938 } 2411 }
1939 2412
1940 /*** External control ***/ 2413 /*** External control ***/
1941 /* Optional: */ 2414 /* Optional: */
1942 /* eciwx */ 2415 /* eciwx */
  2416 +#if defined(CONFIG_USER_ONLY)
  2417 +#define op_eciwx() gen_op_eciwx_raw()
  2418 +#define op_ecowx() gen_op_ecowx_raw()
  2419 +#else
  2420 +#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
  2421 +#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
  2422 +static GenOpFunc *gen_op_eciwx[] = {
  2423 + &gen_op_eciwx_user,
  2424 + &gen_op_eciwx_kernel,
  2425 +};
  2426 +static GenOpFunc *gen_op_ecowx[] = {
  2427 + &gen_op_ecowx_user,
  2428 + &gen_op_ecowx_kernel,
  2429 +};
  2430 +#endif
  2431 +
1943 GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN) 2432 GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
1944 { 2433 {
1945 - SET_RETVAL(EXCP_INVAL); 2434 + /* Should check EAR[E] & alignment ! */
  2435 + if (rA(ctx->opcode) == 0) {
  2436 + gen_op_load_gpr_T0(rB(ctx->opcode));
  2437 + } else {
  2438 + gen_op_load_gpr_T0(rA(ctx->opcode));
  2439 + gen_op_load_gpr_T1(rB(ctx->opcode));
  2440 + gen_op_add();
  2441 + }
  2442 + op_eciwx();
  2443 + gen_op_store_T0_gpr(rD(ctx->opcode));
1946 } 2444 }
1947 2445
1948 /* ecowx */ 2446 /* ecowx */
1949 GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN) 2447 GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
1950 { 2448 {
1951 - SET_RETVAL(EXCP_INVAL); 2449 + /* Should check EAR[E] & alignment ! */
  2450 + if (rA(ctx->opcode) == 0) {
  2451 + gen_op_load_gpr_T0(rB(ctx->opcode));
  2452 + } else {
  2453 + gen_op_load_gpr_T0(rA(ctx->opcode));
  2454 + gen_op_load_gpr_T1(rB(ctx->opcode));
  2455 + gen_op_add();
  2456 + }
  2457 + gen_op_load_gpr_T2(rS(ctx->opcode));
  2458 + op_ecowx();
1952 } 2459 }
1953 2460
1954 /* End opcode list */ 2461 /* End opcode list */
1955 GEN_OPCODE_MARK(end); 2462 GEN_OPCODE_MARK(end);
1956 2463
1957 /*****************************************************************************/ 2464 /*****************************************************************************/
1958 - 2465 +#include <stdlib.h>
1959 #include <string.h> 2466 #include <string.h>
1960 -extern FILE *stderr;  
1961 -void free (void *p);  
1962 -int fflush (FILE *f); 2467 +
  2468 +int fflush (FILE *stream);
1963 2469
1964 /* Main ppc opcodes table: 2470 /* Main ppc opcodes table:
1965 * at init, all opcodes are invalids 2471 * at init, all opcodes are invalids
@@ -1982,6 +2488,7 @@ static inline opc_handler_t **ind_table(void *handler) @@ -1982,6 +2488,7 @@ static inline opc_handler_t **ind_table(void *handler)
1982 return (opc_handler_t **)((unsigned long)handler & ~3); 2488 return (opc_handler_t **)((unsigned long)handler & ~3);
1983 } 2489 }
1984 2490
  2491 +/* Instruction table creation */
1985 /* Opcodes tables creation */ 2492 /* Opcodes tables creation */
1986 static void fill_new_table (opc_handler_t **table, int len) 2493 static void fill_new_table (opc_handler_t **table, int len)
1987 { 2494 {
@@ -2014,10 +2521,11 @@ static int insert_in_table (opc_handler_t **table, unsigned char idx, @@ -2014,10 +2521,11 @@ static int insert_in_table (opc_handler_t **table, unsigned char idx,
2014 return 0; 2521 return 0;
2015 } 2522 }
2016 2523
2017 -static int register_direct_insn (unsigned char idx, opc_handler_t *handler) 2524 +static int register_direct_insn (opc_handler_t **ppc_opcodes,
  2525 + unsigned char idx, opc_handler_t *handler)
2018 { 2526 {
2019 if (insert_in_table(ppc_opcodes, idx, handler) < 0) { 2527 if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
2020 - fprintf(stderr, "*** ERROR: opcode %02x already assigned in main " 2528 + printf("*** ERROR: opcode %02x already assigned in main "
2021 "opcode table\n", idx); 2529 "opcode table\n", idx);
2022 return -1; 2530 return -1;
2023 } 2531 }
@@ -2031,20 +2539,20 @@ static int register_ind_in_table (opc_handler_t **table, @@ -2031,20 +2539,20 @@ static int register_ind_in_table (opc_handler_t **table,
2031 { 2539 {
2032 if (table[idx1] == &invalid_handler) { 2540 if (table[idx1] == &invalid_handler) {
2033 if (create_new_table(table, idx1) < 0) { 2541 if (create_new_table(table, idx1) < 0) {
2034 - fprintf(stderr, "*** ERROR: unable to create indirect table " 2542 + printf("*** ERROR: unable to create indirect table "
2035 "idx=%02x\n", idx1); 2543 "idx=%02x\n", idx1);
2036 return -1; 2544 return -1;
2037 } 2545 }
2038 } else { 2546 } else {
2039 if (!is_indirect_opcode(table[idx1])) { 2547 if (!is_indirect_opcode(table[idx1])) {
2040 - fprintf(stderr, "*** ERROR: idx %02x already assigned to a direct " 2548 + printf("*** ERROR: idx %02x already assigned to a direct "
2041 "opcode\n", idx1); 2549 "opcode\n", idx1);
2042 return -1; 2550 return -1;
2043 } 2551 }
2044 } 2552 }
2045 if (handler != NULL && 2553 if (handler != NULL &&
2046 insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) { 2554 insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
2047 - fprintf(stderr, "*** ERROR: opcode %02x already assigned in " 2555 + printf("*** ERROR: opcode %02x already assigned in "
2048 "opcode table %02x\n", idx2, idx1); 2556 "opcode table %02x\n", idx2, idx1);
2049 return -1; 2557 return -1;
2050 } 2558 }
@@ -2052,7 +2560,8 @@ static int register_ind_in_table (opc_handler_t **table, @@ -2052,7 +2560,8 @@ static int register_ind_in_table (opc_handler_t **table,
2052 return 0; 2560 return 0;
2053 } 2561 }
2054 2562
2055 -static int register_ind_insn (unsigned char idx1, unsigned char idx2, 2563 +static int register_ind_insn (opc_handler_t **ppc_opcodes,
  2564 + unsigned char idx1, unsigned char idx2,
2056 opc_handler_t *handler) 2565 opc_handler_t *handler)
2057 { 2566 {
2058 int ret; 2567 int ret;
@@ -2062,17 +2571,18 @@ static int register_ind_insn (unsigned char idx1, unsigned char idx2, @@ -2062,17 +2571,18 @@ static int register_ind_insn (unsigned char idx1, unsigned char idx2,
2062 return ret; 2571 return ret;
2063 } 2572 }
2064 2573
2065 -static int register_dblind_insn (unsigned char idx1, unsigned char idx2, 2574 +static int register_dblind_insn (opc_handler_t **ppc_opcodes,
  2575 + unsigned char idx1, unsigned char idx2,
2066 unsigned char idx3, opc_handler_t *handler) 2576 unsigned char idx3, opc_handler_t *handler)
2067 { 2577 {
2068 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) { 2578 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
2069 - fprintf(stderr, "*** ERROR: unable to join indirect table idx " 2579 + printf("*** ERROR: unable to join indirect table idx "
2070 "[%02x-%02x]\n", idx1, idx2); 2580 "[%02x-%02x]\n", idx1, idx2);
2071 return -1; 2581 return -1;
2072 } 2582 }
2073 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3, 2583 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
2074 handler) < 0) { 2584 handler) < 0) {
2075 - fprintf(stderr, "*** ERROR: unable to insert opcode " 2585 + printf("*** ERROR: unable to insert opcode "
2076 "[%02x-%02x-%02x]\n", idx1, idx2, idx3); 2586 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
2077 return -1; 2587 return -1;
2078 } 2588 }
@@ -2080,19 +2590,20 @@ static int register_dblind_insn (unsigned char idx1, unsigned char idx2, @@ -2080,19 +2590,20 @@ static int register_dblind_insn (unsigned char idx1, unsigned char idx2,
2080 return 0; 2590 return 0;
2081 } 2591 }
2082 2592
2083 -static int register_insn (opcode_t *insn) 2593 +static int register_insn (opc_handler_t **ppc_opcodes, opcode_t *insn)
2084 { 2594 {
2085 if (insn->opc2 != 0xFF) { 2595 if (insn->opc2 != 0xFF) {
2086 if (insn->opc3 != 0xFF) { 2596 if (insn->opc3 != 0xFF) {
2087 - if (register_dblind_insn(insn->opc1, insn->opc2, insn->opc3,  
2088 - &insn->handler) < 0) 2597 + if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
  2598 + insn->opc3, &insn->handler) < 0)
2089 return -1; 2599 return -1;
2090 } else { 2600 } else {
2091 - if (register_ind_insn(insn->opc1, insn->opc2, &insn->handler) < 0) 2601 + if (register_ind_insn(ppc_opcodes, insn->opc1,
  2602 + insn->opc2, &insn->handler) < 0)
2092 return -1; 2603 return -1;
2093 } 2604 }
2094 } else { 2605 } else {
2095 - if (register_direct_insn(insn->opc1, &insn->handler) < 0) 2606 + if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0)
2096 return -1; 2607 return -1;
2097 } 2608 }
2098 2609
@@ -2125,13 +2636,13 @@ static int test_opcode_table (opc_handler_t **table, int len) @@ -2125,13 +2636,13 @@ static int test_opcode_table (opc_handler_t **table, int len)
2125 return count; 2636 return count;
2126 } 2637 }
2127 2638
2128 -static void fix_opcode_tables (void) 2639 +static void fix_opcode_tables (opc_handler_t **ppc_opcodes)
2129 { 2640 {
2130 if (test_opcode_table(ppc_opcodes, 0x40) == 0) 2641 if (test_opcode_table(ppc_opcodes, 0x40) == 0)
2131 - fprintf(stderr, "*** WARNING: no opcode defined !\n"); 2642 + printf("*** WARNING: no opcode defined !\n");
2132 } 2643 }
2133 2644
2134 -#define SPR_RIGHTS(rw, priv) ((2 * (priv)) + (rw)) 2645 +#define SPR_RIGHTS(rw, priv) (1 << ((2 * (priv)) + (rw)))
2135 #define SPR_UR SPR_RIGHTS(0, 0) 2646 #define SPR_UR SPR_RIGHTS(0, 0)
2136 #define SPR_UW SPR_RIGHTS(1, 0) 2647 #define SPR_UW SPR_RIGHTS(1, 0)
2137 #define SPR_SR SPR_RIGHTS(0, 1) 2648 #define SPR_SR SPR_RIGHTS(0, 1)
@@ -2142,87 +2653,199 @@ do { \ @@ -2142,87 +2653,199 @@ do { \
2142 spr_access[(spr) >> 1] |= ((rights) << (4 * ((spr) & 1))); \ 2653 spr_access[(spr) >> 1] |= ((rights) << (4 * ((spr) & 1))); \
2143 } while (0) 2654 } while (0)
2144 2655
2145 -static void init_spr_rights (void) 2656 +static void init_spr_rights (uint32_t pvr)
2146 { 2657 {
2147 /* XER (SPR 1) */ 2658 /* XER (SPR 1) */
2148 - spr_set_rights(SPR_ENCODE(1), SPR_UR | SPR_UW | SPR_SR | SPR_SW); 2659 + spr_set_rights(XER, SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2149 /* LR (SPR 8) */ 2660 /* LR (SPR 8) */
2150 - spr_set_rights(SPR_ENCODE(8), SPR_UR | SPR_UW | SPR_SR | SPR_SW); 2661 + spr_set_rights(LR, SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2151 /* CTR (SPR 9) */ 2662 /* CTR (SPR 9) */
2152 - spr_set_rights(SPR_ENCODE(9), SPR_UR | SPR_UW | SPR_SR | SPR_SW); 2663 + spr_set_rights(CTR, SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2153 /* TBL (SPR 268) */ 2664 /* TBL (SPR 268) */
2154 - spr_set_rights(SPR_ENCODE(268), SPR_UR | SPR_SR); 2665 + spr_set_rights(V_TBL, SPR_UR | SPR_SR);
2155 /* TBU (SPR 269) */ 2666 /* TBU (SPR 269) */
2156 - spr_set_rights(SPR_ENCODE(269), SPR_UR | SPR_SR); 2667 + spr_set_rights(V_TBU, SPR_UR | SPR_SR);
2157 /* DSISR (SPR 18) */ 2668 /* DSISR (SPR 18) */
2158 - spr_set_rights(SPR_ENCODE(18), SPR_SR | SPR_SW); 2669 + spr_set_rights(DSISR, SPR_SR | SPR_SW);
2159 /* DAR (SPR 19) */ 2670 /* DAR (SPR 19) */
2160 - spr_set_rights(SPR_ENCODE(19), SPR_SR | SPR_SW); 2671 + spr_set_rights(DAR, SPR_SR | SPR_SW);
2161 /* DEC (SPR 22) */ 2672 /* DEC (SPR 22) */
2162 - spr_set_rights(SPR_ENCODE(22), SPR_SR | SPR_SW); 2673 + spr_set_rights(DECR, SPR_SR | SPR_SW);
2163 /* SDR1 (SPR 25) */ 2674 /* SDR1 (SPR 25) */
2164 - spr_set_rights(SPR_ENCODE(25), SPR_SR | SPR_SW); 2675 + spr_set_rights(SDR1, SPR_SR | SPR_SW);
  2676 + /* SRR0 (SPR 26) */
  2677 + spr_set_rights(SRR0, SPR_SR | SPR_SW);
  2678 + /* SRR1 (SPR 27) */
  2679 + spr_set_rights(SRR1, SPR_SR | SPR_SW);
2165 /* SPRG0 (SPR 272) */ 2680 /* SPRG0 (SPR 272) */
2166 - spr_set_rights(SPR_ENCODE(272), SPR_SR | SPR_SW); 2681 + spr_set_rights(SPRG0, SPR_SR | SPR_SW);
2167 /* SPRG1 (SPR 273) */ 2682 /* SPRG1 (SPR 273) */
2168 - spr_set_rights(SPR_ENCODE(273), SPR_SR | SPR_SW); 2683 + spr_set_rights(SPRG1, SPR_SR | SPR_SW);
2169 /* SPRG2 (SPR 274) */ 2684 /* SPRG2 (SPR 274) */
2170 - spr_set_rights(SPR_ENCODE(274), SPR_SR | SPR_SW); 2685 + spr_set_rights(SPRG2, SPR_SR | SPR_SW);
2171 /* SPRG3 (SPR 275) */ 2686 /* SPRG3 (SPR 275) */
2172 - spr_set_rights(SPR_ENCODE(275), SPR_SR | SPR_SW); 2687 + spr_set_rights(SPRG3, SPR_SR | SPR_SW);
2173 /* ASR (SPR 280) */ 2688 /* ASR (SPR 280) */
2174 - spr_set_rights(SPR_ENCODE(281), SPR_SR | SPR_SW); 2689 + spr_set_rights(ASR, SPR_SR | SPR_SW);
2175 /* EAR (SPR 282) */ 2690 /* EAR (SPR 282) */
2176 - spr_set_rights(SPR_ENCODE(282), SPR_SR | SPR_SW); 2691 + spr_set_rights(EAR, SPR_SR | SPR_SW);
  2692 + /* TBL (SPR 284) */
  2693 + spr_set_rights(O_TBL, SPR_SW);
  2694 + /* TBU (SPR 285) */
  2695 + spr_set_rights(O_TBU, SPR_SW);
  2696 + /* PVR (SPR 287) */
  2697 + spr_set_rights(PVR, SPR_SR);
2177 /* IBAT0U (SPR 528) */ 2698 /* IBAT0U (SPR 528) */
2178 - spr_set_rights(SPR_ENCODE(528), SPR_SR | SPR_SW); 2699 + spr_set_rights(IBAT0U, SPR_SR | SPR_SW);
2179 /* IBAT0L (SPR 529) */ 2700 /* IBAT0L (SPR 529) */
2180 - spr_set_rights(SPR_ENCODE(529), SPR_SR | SPR_SW); 2701 + spr_set_rights(IBAT0L, SPR_SR | SPR_SW);
2181 /* IBAT1U (SPR 530) */ 2702 /* IBAT1U (SPR 530) */
2182 - spr_set_rights(SPR_ENCODE(530), SPR_SR | SPR_SW); 2703 + spr_set_rights(IBAT1U, SPR_SR | SPR_SW);
2183 /* IBAT1L (SPR 531) */ 2704 /* IBAT1L (SPR 531) */
2184 - spr_set_rights(SPR_ENCODE(531), SPR_SR | SPR_SW); 2705 + spr_set_rights(IBAT1L, SPR_SR | SPR_SW);
2185 /* IBAT2U (SPR 532) */ 2706 /* IBAT2U (SPR 532) */
2186 - spr_set_rights(SPR_ENCODE(532), SPR_SR | SPR_SW); 2707 + spr_set_rights(IBAT2U, SPR_SR | SPR_SW);
2187 /* IBAT2L (SPR 533) */ 2708 /* IBAT2L (SPR 533) */
2188 - spr_set_rights(SPR_ENCODE(533), SPR_SR | SPR_SW); 2709 + spr_set_rights(IBAT2L, SPR_SR | SPR_SW);
2189 /* IBAT3U (SPR 534) */ 2710 /* IBAT3U (SPR 534) */
2190 - spr_set_rights(SPR_ENCODE(534), SPR_SR | SPR_SW); 2711 + spr_set_rights(IBAT3U, SPR_SR | SPR_SW);
2191 /* IBAT3L (SPR 535) */ 2712 /* IBAT3L (SPR 535) */
2192 - spr_set_rights(SPR_ENCODE(535), SPR_SR | SPR_SW); 2713 + spr_set_rights(IBAT3L, SPR_SR | SPR_SW);
2193 /* DBAT0U (SPR 536) */ 2714 /* DBAT0U (SPR 536) */
2194 - spr_set_rights(SPR_ENCODE(536), SPR_SR | SPR_SW); 2715 + spr_set_rights(DBAT0U, SPR_SR | SPR_SW);
2195 /* DBAT0L (SPR 537) */ 2716 /* DBAT0L (SPR 537) */
2196 - spr_set_rights(SPR_ENCODE(537), SPR_SR | SPR_SW); 2717 + spr_set_rights(DBAT0L, SPR_SR | SPR_SW);
2197 /* DBAT1U (SPR 538) */ 2718 /* DBAT1U (SPR 538) */
2198 - spr_set_rights(SPR_ENCODE(538), SPR_SR | SPR_SW); 2719 + spr_set_rights(DBAT1U, SPR_SR | SPR_SW);
2199 /* DBAT1L (SPR 539) */ 2720 /* DBAT1L (SPR 539) */
2200 - spr_set_rights(SPR_ENCODE(539), SPR_SR | SPR_SW); 2721 + spr_set_rights(DBAT1L, SPR_SR | SPR_SW);
2201 /* DBAT2U (SPR 540) */ 2722 /* DBAT2U (SPR 540) */
2202 - spr_set_rights(SPR_ENCODE(540), SPR_SR | SPR_SW); 2723 + spr_set_rights(DBAT2U, SPR_SR | SPR_SW);
2203 /* DBAT2L (SPR 541) */ 2724 /* DBAT2L (SPR 541) */
2204 - spr_set_rights(SPR_ENCODE(541), SPR_SR | SPR_SW); 2725 + spr_set_rights(DBAT2L, SPR_SR | SPR_SW);
2205 /* DBAT3U (SPR 542) */ 2726 /* DBAT3U (SPR 542) */
2206 - spr_set_rights(SPR_ENCODE(542), SPR_SR | SPR_SW); 2727 + spr_set_rights(DBAT3U, SPR_SR | SPR_SW);
2207 /* DBAT3L (SPR 543) */ 2728 /* DBAT3L (SPR 543) */
2208 - spr_set_rights(SPR_ENCODE(543), SPR_SR | SPR_SW); 2729 + spr_set_rights(DBAT3L, SPR_SR | SPR_SW);
2209 /* DABR (SPR 1013) */ 2730 /* DABR (SPR 1013) */
2210 - spr_set_rights(SPR_ENCODE(1013), SPR_SR | SPR_SW); 2731 + spr_set_rights(DABR, SPR_SR | SPR_SW);
2211 /* FPECR (SPR 1022) */ 2732 /* FPECR (SPR 1022) */
2212 - spr_set_rights(SPR_ENCODE(1022), SPR_SR | SPR_SW); 2733 + spr_set_rights(FPECR, SPR_SR | SPR_SW);
2213 /* PIR (SPR 1023) */ 2734 /* PIR (SPR 1023) */
2214 - spr_set_rights(SPR_ENCODE(1023), SPR_SR | SPR_SW);  
2215 - /* PVR (SPR 287) */  
2216 - spr_set_rights(SPR_ENCODE(287), SPR_SR);  
2217 - /* TBL (SPR 284) */  
2218 - spr_set_rights(SPR_ENCODE(284), SPR_SW);  
2219 - /* TBU (SPR 285) */  
2220 - spr_set_rights(SPR_ENCODE(285), SPR_SW); 2735 + spr_set_rights(PIR, SPR_SR | SPR_SW);
  2736 + /* Special registers for MPC740/745/750/755 (aka G3) & IBM 750 */
  2737 + if ((pvr & 0xFFFF0000) == 0x00080000 ||
  2738 + (pvr & 0xFFFF0000) == 0x70000000) {
  2739 + /* HID0 */
  2740 + spr_set_rights(SPR_ENCODE(1008), SPR_SR | SPR_SW);
  2741 + /* HID1 */
  2742 + spr_set_rights(SPR_ENCODE(1009), SPR_SR | SPR_SW);
  2743 + /* IABR */
  2744 + spr_set_rights(SPR_ENCODE(1010), SPR_SR | SPR_SW);
  2745 + /* ICTC */
  2746 + spr_set_rights(SPR_ENCODE(1019), SPR_SR | SPR_SW);
  2747 + /* L2CR */
  2748 + spr_set_rights(SPR_ENCODE(1017), SPR_SR | SPR_SW);
  2749 + /* MMCR0 */
  2750 + spr_set_rights(SPR_ENCODE(952), SPR_SR | SPR_SW);
  2751 + /* MMCR1 */
  2752 + spr_set_rights(SPR_ENCODE(956), SPR_SR | SPR_SW);
  2753 + /* PMC1 */
  2754 + spr_set_rights(SPR_ENCODE(953), SPR_SR | SPR_SW);
  2755 + /* PMC2 */
  2756 + spr_set_rights(SPR_ENCODE(954), SPR_SR | SPR_SW);
  2757 + /* PMC3 */
  2758 + spr_set_rights(SPR_ENCODE(957), SPR_SR | SPR_SW);
  2759 + /* PMC4 */
  2760 + spr_set_rights(SPR_ENCODE(958), SPR_SR | SPR_SW);
  2761 + /* SIA */
  2762 + spr_set_rights(SPR_ENCODE(955), SPR_SR | SPR_SW);
  2763 + /* THRM1 */
  2764 + spr_set_rights(SPR_ENCODE(1020), SPR_SR | SPR_SW);
  2765 + /* THRM2 */
  2766 + spr_set_rights(SPR_ENCODE(1021), SPR_SR | SPR_SW);
  2767 + /* THRM3 */
  2768 + spr_set_rights(SPR_ENCODE(1022), SPR_SR | SPR_SW);
  2769 + /* UMMCR0 */
  2770 + spr_set_rights(SPR_ENCODE(936), SPR_UR | SPR_UW);
  2771 + /* UMMCR1 */
  2772 + spr_set_rights(SPR_ENCODE(940), SPR_UR | SPR_UW);
  2773 + /* UPMC1 */
  2774 + spr_set_rights(SPR_ENCODE(937), SPR_UR | SPR_UW);
  2775 + /* UPMC2 */
  2776 + spr_set_rights(SPR_ENCODE(938), SPR_UR | SPR_UW);
  2777 + /* UPMC3 */
  2778 + spr_set_rights(SPR_ENCODE(941), SPR_UR | SPR_UW);
  2779 + /* UPMC4 */
  2780 + spr_set_rights(SPR_ENCODE(942), SPR_UR | SPR_UW);
  2781 + /* USIA */
  2782 + spr_set_rights(SPR_ENCODE(939), SPR_UR | SPR_UW);
  2783 + }
  2784 + /* MPC755 has special registers */
  2785 + if (pvr == 0x00083100) {
  2786 + /* SPRG4 */
  2787 + spr_set_rights(SPRG4, SPR_SR | SPR_SW);
  2788 + /* SPRG5 */
  2789 + spr_set_rights(SPRG5, SPR_SR | SPR_SW);
  2790 + /* SPRG6 */
  2791 + spr_set_rights(SPRG6, SPR_SR | SPR_SW);
  2792 + /* SPRG7 */
  2793 + spr_set_rights(SPRG7, SPR_SR | SPR_SW);
  2794 + /* IBAT4U */
  2795 + spr_set_rights(IBAT4U, SPR_SR | SPR_SW);
  2796 + /* IBAT4L */
  2797 + spr_set_rights(IBAT4L, SPR_SR | SPR_SW);
  2798 + /* IBAT5U */
  2799 + spr_set_rights(IBAT5U, SPR_SR | SPR_SW);
  2800 + /* IBAT5L */
  2801 + spr_set_rights(IBAT5L, SPR_SR | SPR_SW);
  2802 + /* IBAT6U */
  2803 + spr_set_rights(IBAT6U, SPR_SR | SPR_SW);
  2804 + /* IBAT6L */
  2805 + spr_set_rights(IBAT6L, SPR_SR | SPR_SW);
  2806 + /* IBAT7U */
  2807 + spr_set_rights(IBAT7U, SPR_SR | SPR_SW);
  2808 + /* IBAT7L */
  2809 + spr_set_rights(IBAT7L, SPR_SR | SPR_SW);
  2810 + /* DBAT4U */
  2811 + spr_set_rights(DBAT4U, SPR_SR | SPR_SW);
  2812 + /* DBAT4L */
  2813 + spr_set_rights(DBAT4L, SPR_SR | SPR_SW);
  2814 + /* DBAT5U */
  2815 + spr_set_rights(DBAT5U, SPR_SR | SPR_SW);
  2816 + /* DBAT5L */
  2817 + spr_set_rights(DBAT5L, SPR_SR | SPR_SW);
  2818 + /* DBAT6U */
  2819 + spr_set_rights(DBAT6U, SPR_SR | SPR_SW);
  2820 + /* DBAT6L */
  2821 + spr_set_rights(DBAT6L, SPR_SR | SPR_SW);
  2822 + /* DBAT7U */
  2823 + spr_set_rights(DBAT7U, SPR_SR | SPR_SW);
  2824 + /* DBAT7L */
  2825 + spr_set_rights(DBAT7L, SPR_SR | SPR_SW);
  2826 + /* DMISS */
  2827 + spr_set_rights(SPR_ENCODE(976), SPR_SR | SPR_SW);
  2828 + /* DCMP */
  2829 + spr_set_rights(SPR_ENCODE(977), SPR_SR | SPR_SW);
  2830 + /* DHASH1 */
  2831 + spr_set_rights(SPR_ENCODE(978), SPR_SR | SPR_SW);
  2832 + /* DHASH2 */
  2833 + spr_set_rights(SPR_ENCODE(979), SPR_SR | SPR_SW);
  2834 + /* IMISS */
  2835 + spr_set_rights(SPR_ENCODE(980), SPR_SR | SPR_SW);
  2836 + /* ICMP */
  2837 + spr_set_rights(SPR_ENCODE(981), SPR_SR | SPR_SW);
  2838 + /* RPA */
  2839 + spr_set_rights(SPR_ENCODE(982), SPR_SR | SPR_SW);
  2840 + /* HID2 */
  2841 + spr_set_rights(SPR_ENCODE(1011), SPR_SR | SPR_SW);
  2842 + /* L2PM */
  2843 + spr_set_rights(SPR_ENCODE(1016), SPR_SR | SPR_SW);
  2844 + }
2221 } 2845 }
2222 2846
2223 -/* PPC "main stream" common instructions */  
2224 -#define PPC_COMMON (PPC_INTEGER | PPC_FLOAT | PPC_FLOW | PPC_MEM | \  
2225 - PPC_MISC | PPC_EXTERN | PPC_SEGMENT) 2847 +/*****************************************************************************/
  2848 +/* PPC "main stream" common instructions (no optional ones) */
2226 2849
2227 typedef struct ppc_proc_t { 2850 typedef struct ppc_proc_t {
2228 int flags; 2851 int flags;
@@ -2240,9 +2863,26 @@ static ppc_proc_t ppc_proc_common = { @@ -2240,9 +2863,26 @@ static ppc_proc_t ppc_proc_common = {
2240 .specific = NULL, 2863 .specific = NULL,
2241 }; 2864 };
2242 2865
  2866 +static ppc_proc_t ppc_proc_G3 = {
  2867 + .flags = PPC_750,
  2868 + .specific = NULL,
  2869 +};
  2870 +
2243 static ppc_def_t ppc_defs[] = 2871 static ppc_def_t ppc_defs[] =
2244 { 2872 {
2245 - /* Fallback */ 2873 + /* MPC740/745/750/755 (G3) */
  2874 + {
  2875 + .pvr = 0x00080000,
  2876 + .pvr_mask = 0xFFFF0000,
  2877 + .proc = &ppc_proc_G3,
  2878 + },
  2879 + /* IBM 750FX (G3 embedded) */
  2880 + {
  2881 + .pvr = 0x70000000,
  2882 + .pvr_mask = 0xFFFF0000,
  2883 + .proc = &ppc_proc_G3,
  2884 + },
  2885 + /* Fallback (generic PPC) */
2246 { 2886 {
2247 .pvr = 0x00000000, 2887 .pvr = 0x00000000,
2248 .pvr_mask = 0x00000000, 2888 .pvr_mask = 0x00000000,
@@ -2250,7 +2890,7 @@ static ppc_def_t ppc_defs[] = @@ -2250,7 +2890,7 @@ static ppc_def_t ppc_defs[] =
2250 }, 2890 },
2251 }; 2891 };
2252 2892
2253 -static int create_ppc_proc (unsigned long pvr) 2893 +static int create_ppc_proc (opc_handler_t **ppc_opcodes, unsigned long pvr)
2254 { 2894 {
2255 opcode_t *opc; 2895 opcode_t *opc;
2256 int i, flags; 2896 int i, flags;
@@ -2265,65 +2905,71 @@ static int create_ppc_proc (unsigned long pvr) @@ -2265,65 +2905,71 @@ static int create_ppc_proc (unsigned long pvr)
2265 } 2905 }
2266 2906
2267 for (opc = &opc_start + 1; opc != &opc_end; opc++) { 2907 for (opc = &opc_start + 1; opc != &opc_end; opc++) {
2268 - if ((opc->type & flags) != 0)  
2269 - if (register_insn(opc) < 0) {  
2270 - fprintf(stderr, "*** ERROR initializing PPC instruction " 2908 + if ((opc->handler.type & flags) != 0)
  2909 + if (register_insn(ppc_opcodes, opc) < 0) {
  2910 + printf("*** ERROR initializing PPC instruction "
2271 "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2, 2911 "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
2272 opc->opc3); 2912 opc->opc3);
2273 return -1; 2913 return -1;
2274 } 2914 }
2275 } 2915 }
2276 - fix_opcode_tables(); 2916 + fix_opcode_tables(ppc_opcodes);
2277 2917
2278 return 0; 2918 return 0;
2279 } 2919 }
2280 2920
  2921 +
2281 /*****************************************************************************/ 2922 /*****************************************************************************/
2282 -uint32_t do_load_xer (void); 2923 +/* Misc PPC helpers */
  2924 +FILE *stdout;
2283 2925
2284 void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) 2926 void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
2285 { 2927 {
2286 int i; 2928 int i;
2287 2929
2288 - if (loglevel > 0) {  
2289 - fprintf(logfile, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x\n",  
2290 - env->nip, env->LR, env->CTR, do_load_xer()); 2930 + fprintf(f, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x "
  2931 + "MSR=0x%08x\n", env->nip, env->lr, env->ctr,
  2932 + _load_xer(), _load_msr());
2291 for (i = 0; i < 32; i++) { 2933 for (i = 0; i < 32; i++) {
2292 if ((i & 7) == 0) 2934 if ((i & 7) == 0)
2293 - fprintf(logfile, "GPR%02d:", i);  
2294 - fprintf(logfile, " %08x", env->gpr[i]); 2935 + fprintf(f, "GPR%02d:", i);
  2936 + fprintf(f, " %08x", env->gpr[i]);
2295 if ((i & 7) == 7) 2937 if ((i & 7) == 7)
2296 - fprintf(logfile, "\n"); 2938 + fprintf(f, "\n");
2297 } 2939 }
2298 - fprintf(logfile, "CR: 0x"); 2940 + fprintf(f, "CR: 0x");
2299 for (i = 0; i < 8; i++) 2941 for (i = 0; i < 8; i++)
2300 - fprintf(logfile, "%01x", env->crf[i]);  
2301 - fprintf(logfile, " ["); 2942 + fprintf(f, "%01x", env->crf[i]);
  2943 + fprintf(f, " [");
2302 for (i = 0; i < 8; i++) { 2944 for (i = 0; i < 8; i++) {
2303 char a = '-'; 2945 char a = '-';
2304 -  
2305 if (env->crf[i] & 0x08) 2946 if (env->crf[i] & 0x08)
2306 a = 'L'; 2947 a = 'L';
2307 else if (env->crf[i] & 0x04) 2948 else if (env->crf[i] & 0x04)
2308 a = 'G'; 2949 a = 'G';
2309 else if (env->crf[i] & 0x02) 2950 else if (env->crf[i] & 0x02)
2310 a = 'E'; 2951 a = 'E';
2311 - fprintf(logfile, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' '); 2952 + fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
2312 } 2953 }
2313 - fprintf(logfile, " ] ");  
2314 - fprintf(logfile, "TB: 0x%08x %08x\n", env->spr[SPR_ENCODE(269)],  
2315 - env->spr[SPR_ENCODE(268)]); 2954 + fprintf(f, " ] ");
  2955 + fprintf(f, "TB: 0x%08x %08x\n", env->tb[1], env->tb[0]);
2316 for (i = 0; i < 16; i++) { 2956 for (i = 0; i < 16; i++) {
2317 if ((i & 3) == 0) 2957 if ((i & 3) == 0)
2318 - fprintf(logfile, "FPR%02d:", i);  
2319 - fprintf(logfile, " %016llx", *((uint64_t *)(&env->fpr[i]))); 2958 + fprintf(f, "FPR%02d:", i);
  2959 + fprintf(f, " %016llx", *((uint64_t *)&env->fpr[i]));
2320 if ((i & 3) == 3) 2960 if ((i & 3) == 3)
2321 - fprintf(logfile, "\n");  
2322 - }  
2323 - fflush(logfile); 2961 + fprintf(f, "\n");
2324 } 2962 }
  2963 + fprintf(f, "SRR0 0x%08x SRR1 0x%08x\n",
  2964 + env->spr[SRR0], env->spr[SRR1]);
  2965 + fprintf(f, "reservation 0x%08x\n", env->reserve);
  2966 + fflush(f);
2325 } 2967 }
2326 2968
  2969 +#if !defined(CONFIG_USER_ONLY) && defined (USE_OPENFIRMWARE)
  2970 +int setup_machine (CPUPPCState *env, uint32_t mid);
  2971 +#endif
  2972 +
2327 CPUPPCState *cpu_ppc_init(void) 2973 CPUPPCState *cpu_ppc_init(void)
2328 { 2974 {
2329 CPUPPCState *env; 2975 CPUPPCState *env;
@@ -2334,10 +2980,26 @@ CPUPPCState *cpu_ppc_init(void) @@ -2334,10 +2980,26 @@ CPUPPCState *cpu_ppc_init(void)
2334 if (!env) 2980 if (!env)
2335 return NULL; 2981 return NULL;
2336 memset(env, 0, sizeof(CPUPPCState)); 2982 memset(env, 0, sizeof(CPUPPCState));
2337 - env->PVR = 0;  
2338 - if (create_ppc_proc(0) < 0) 2983 +#if !defined(CONFIG_USER_ONLY) && defined (USE_OPEN_FIRMWARE)
  2984 + setup_machine(env, 0);
  2985 +#else
  2986 +// env->spr[PVR] = 0; /* Basic PPC */
  2987 + env->spr[PVR] = 0x00080100; /* G3 CPU */
  2988 +// env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */
  2989 +// env->spr[PVR] = 0x00070100; /* IBM 750FX */
  2990 +#endif
  2991 + env->decr = 0xFFFFFFFF;
  2992 + if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0)
2339 return NULL; 2993 return NULL;
2340 - init_spr_rights(); 2994 + init_spr_rights(env->spr[PVR]);
  2995 + tlb_flush(env);
  2996 +#if defined (DO_SINGLE_STEP)
  2997 + /* Single step trace mode */
  2998 + msr_se = 1;
  2999 +#endif
  3000 +#if defined(CONFIG_USER_ONLY)
  3001 + msr_pr = 1;
  3002 +#endif
2341 3003
2342 return env; 3004 return env;
2343 } 3005 }
@@ -2348,6 +3010,11 @@ void cpu_ppc_close(CPUPPCState *env) @@ -2348,6 +3010,11 @@ void cpu_ppc_close(CPUPPCState *env)
2348 free(env); 3010 free(env);
2349 } 3011 }
2350 3012
  3013 +/*****************************************************************************/
  3014 +void raise_exception_err (int exception_index, int error_code);
  3015 +int print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
  3016 + int dialect);
  3017 +
2351 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, 3018 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2352 int search_pc) 3019 int search_pc)
2353 { 3020 {
@@ -2356,7 +3023,6 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -2356,7 +3023,6 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2356 uint32_t pc_start; 3023 uint32_t pc_start;
2357 uint16_t *gen_opc_end; 3024 uint16_t *gen_opc_end;
2358 int j, lj = -1; 3025 int j, lj = -1;
2359 - int ret = 0;  
2360 3026
2361 pc_start = tb->pc; 3027 pc_start = tb->pc;
2362 gen_opc_ptr = gen_opc_buf; 3028 gen_opc_ptr = gen_opc_buf;
@@ -2364,11 +3030,21 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -2364,11 +3030,21 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2364 gen_opparam_ptr = gen_opparam_buf; 3030 gen_opparam_ptr = gen_opparam_buf;
2365 ctx.nip = (uint32_t *)pc_start; 3031 ctx.nip = (uint32_t *)pc_start;
2366 ctx.tb_offset = 0; 3032 ctx.tb_offset = 0;
2367 - ctx.supervisor = msr_ip; 3033 + ctx.decr_offset = 0;
2368 ctx.tb = tb; 3034 ctx.tb = tb;
2369 - ctx.exception = 0;  
2370 -  
2371 - while (ret == 0 && gen_opc_ptr < gen_opc_end) { 3035 + ctx.exception = EXCP_NONE;
  3036 +#if defined(CONFIG_USER_ONLY)
  3037 + ctx.mem_idx = 0;
  3038 +#else
  3039 + ctx.supervisor = 1 - msr_pr;
  3040 + ctx.mem_idx = (1 - msr_pr);
  3041 +#endif
  3042 +#if defined (DO_SINGLE_STEP)
  3043 + /* Single step trace mode */
  3044 + msr_se = 1;
  3045 +#endif
  3046 + /* Set env in case of segfault during code fetch */
  3047 + while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
2372 if (search_pc) { 3048 if (search_pc) {
2373 if (loglevel > 0) 3049 if (loglevel > 0)
2374 fprintf(logfile, "Search PC...\n"); 3050 fprintf(logfile, "Search PC...\n");
@@ -2381,15 +3057,26 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -2381,15 +3057,26 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2381 gen_opc_instr_start[lj] = 1; 3057 gen_opc_instr_start[lj] = 1;
2382 } 3058 }
2383 } 3059 }
2384 - ctx.opcode = __be32_to_cpu(*ctx.nip);  
2385 -#ifdef DEBUG_DISAS 3060 +#if defined DEBUG_DISAS
2386 if (loglevel > 0) { 3061 if (loglevel > 0) {
2387 fprintf(logfile, "----------------\n"); 3062 fprintf(logfile, "----------------\n");
2388 - fprintf(logfile, "%p: translate opcode %08x\n",  
2389 - ctx.nip, ctx.opcode); 3063 + fprintf(logfile, "nip=%p super=%d ir=%d\n",
  3064 + ctx.nip, 1 - msr_pr, msr_ir);
  3065 + }
  3066 +#endif
  3067 + ctx.opcode = ldl_code(ctx.nip);
  3068 +#if defined DEBUG_DISAS
  3069 + if (loglevel > 0) {
  3070 + fprintf(logfile, "translate opcode %08x (%02x %02x %02x)\n",
  3071 + ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
  3072 + opc3(ctx.opcode));
2390 } 3073 }
2391 #endif 3074 #endif
2392 ctx.nip++; 3075 ctx.nip++;
  3076 + ctx.tb_offset++;
  3077 + /* Check decrementer exception */
  3078 + if (++ctx.decr_offset == env->decr + 1)
  3079 + ctx.exception = EXCP_DECR;
2393 table = ppc_opcodes; 3080 table = ppc_opcodes;
2394 handler = table[opc1(ctx.opcode)]; 3081 handler = table[opc1(ctx.opcode)];
2395 if (is_indirect_opcode(handler)) { 3082 if (is_indirect_opcode(handler)) {
@@ -2405,62 +3092,93 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -2405,62 +3092,93 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2405 if (loglevel > 0) { 3092 if (loglevel > 0) {
2406 if (handler->handler == &gen_invalid) { 3093 if (handler->handler == &gen_invalid) {
2407 fprintf(logfile, "invalid/unsupported opcode: " 3094 fprintf(logfile, "invalid/unsupported opcode: "
2408 - "%02x -%02x - %02x (%08x)\n", opc1(ctx.opcode),  
2409 - opc2(ctx.opcode), opc3(ctx.opcode), ctx.opcode); 3095 + "%02x -%02x - %02x (%08x) %p\n",
  3096 + opc1(ctx.opcode), opc2(ctx.opcode),
  3097 + opc3(ctx.opcode), ctx.opcode, ctx.nip - 1);
2410 } else { 3098 } else {
2411 fprintf(logfile, "invalid bits: %08x for opcode: " 3099 fprintf(logfile, "invalid bits: %08x for opcode: "
2412 - "%02x -%02x - %02x (%p)\n", 3100 + "%02x -%02x - %02x (0x%08x) (%p)\n",
2413 ctx.opcode & handler->inval, opc1(ctx.opcode), 3101 ctx.opcode & handler->inval, opc1(ctx.opcode),
2414 opc2(ctx.opcode), opc3(ctx.opcode), 3102 opc2(ctx.opcode), opc3(ctx.opcode),
2415 - handler->handler); 3103 + ctx.opcode, ctx.nip - 1);
2416 } 3104 }
  3105 + } else {
  3106 + if (handler->handler == &gen_invalid) {
  3107 + printf("invalid/unsupported opcode: "
  3108 + "%02x -%02x - %02x (%08x) %p\n",
  3109 + opc1(ctx.opcode), opc2(ctx.opcode),
  3110 + opc3(ctx.opcode), ctx.opcode, ctx.nip - 1);
  3111 + } else {
  3112 + printf("invalid bits: %08x for opcode: "
  3113 + "%02x -%02x - %02x (0x%08x) (%p)\n",
  3114 + ctx.opcode & handler->inval, opc1(ctx.opcode),
  3115 + opc2(ctx.opcode), opc3(ctx.opcode),
  3116 + ctx.opcode, ctx.nip - 1);
  3117 + }
2417 } 3118 }
2418 - ret = GET_RETVAL(gen_invalid, ctx.opcode); 3119 + (*gen_invalid)(&ctx);
2419 } else { 3120 } else {
2420 - ret = GET_RETVAL(*(handler->handler), ctx.opcode); 3121 + (*(handler->handler))(&ctx);
2421 } 3122 }
2422 - ctx.tb_offset++;  
2423 -#if defined (DO_SINGLE_STEP)  
2424 - break; 3123 + /* Check trace mode exceptions */
  3124 + if ((msr_be && ctx.exception == EXCP_BRANCH) ||
  3125 + /* Check in single step trace mode
  3126 + * we need to stop except if:
  3127 + * - rfi, trap or syscall
  3128 + * - first instruction of an exception handler
  3129 + */
  3130 + (msr_se && ((uint32_t)ctx.nip < 0x100 ||
  3131 + (uint32_t)ctx.nip > 0xF00 ||
  3132 + ((uint32_t)ctx.nip & 0xFC) != 0x04) &&
  3133 + ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI &&
  3134 + ctx.exception != EXCP_TRAP)) {
  3135 +#if !defined(CONFIG_USER_ONLY)
  3136 + gen_op_queue_exception(EXCP_TRACE);
2425 #endif 3137 #endif
  3138 + if (ctx.exception == EXCP_NONE) {
  3139 + ctx.exception = EXCP_TRACE;
2426 } 3140 }
2427 -#if defined (DO_STEP_FLUSH)  
2428 - tb_flush(env);  
2429 -#endif  
2430 - /* We need to update the time base */  
2431 - if (!search_pc)  
2432 - gen_op_update_tb(ctx.tb_offset);  
2433 - /* If we are in step-by-step mode, do a branch to the next instruction  
2434 - * so the nip will be up-to-date  
2435 - */  
2436 -#if defined (DO_SINGLE_STEP)  
2437 - if (ret == 0) { 3141 + }
  3142 + /* if too long translation, stop generation too */
  3143 + if (gen_opc_ptr >= gen_opc_end ||
  3144 + ((uint32_t)ctx.nip - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
  3145 + if (ctx.exception == EXCP_NONE) {
2438 gen_op_b((uint32_t)ctx.nip); 3146 gen_op_b((uint32_t)ctx.nip);
2439 - ret = EXCP_BRANCH; 3147 + ctx.exception = EXCP_BRANCH;
2440 } 3148 }
2441 -#endif  
2442 - /* If the exeption isn't a PPC one,  
2443 - * generate it now.  
2444 - */  
2445 - if (ret != EXCP_BRANCH) {  
2446 - gen_op_set_T0(0);  
2447 - if ((ret & 0x2000) == 0)  
2448 - gen_op_raise_exception(ret);  
2449 } 3149 }
  3150 + }
  3151 + /* In case of branch, this has already been done *BEFORE* the branch */
  3152 + if (ctx.exception != EXCP_BRANCH && ctx.exception != EXCP_RFI) {
  3153 + gen_op_update_tb(ctx.tb_offset);
  3154 + gen_op_update_decr(ctx.decr_offset);
  3155 + gen_op_process_exceptions((uint32_t)ctx.nip);
  3156 + }
  3157 +#if 1
2450 /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump 3158 /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
2451 * do bad business and then qemu crashes ! 3159 * do bad business and then qemu crashes !
2452 */ 3160 */
2453 gen_op_set_T0(0); 3161 gen_op_set_T0(0);
  3162 +#endif
2454 /* Generate the return instruction */ 3163 /* Generate the return instruction */
2455 gen_op_exit_tb(); 3164 gen_op_exit_tb();
2456 *gen_opc_ptr = INDEX_op_end; 3165 *gen_opc_ptr = INDEX_op_end;
2457 - if (!search_pc)  
2458 - tb->size = (uint32_t)ctx.nip - pc_start;  
2459 - else 3166 + if (search_pc) {
  3167 + j = gen_opc_ptr - gen_opc_buf;
  3168 + lj++;
  3169 + while (lj <= j)
  3170 + gen_opc_instr_start[lj++] = 0;
2460 tb->size = 0; 3171 tb->size = 0;
2461 -// *gen_opc_ptr = INDEX_op_end; 3172 + if (loglevel > 0) {
  3173 + page_dump(logfile);
  3174 + }
  3175 + } else {
  3176 + tb->size = (uint32_t)ctx.nip - pc_start;
  3177 + }
2462 #ifdef DEBUG_DISAS 3178 #ifdef DEBUG_DISAS
2463 if (loglevel > 0) { 3179 if (loglevel > 0) {
  3180 + fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
  3181 + cpu_ppc_dump_state(env, logfile, 0);
2464 fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start)); 3182 fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start));
2465 disas(logfile, (void *)pc_start, (uint32_t)ctx.nip - pc_start, 0, 0); 3183 disas(logfile, (void *)pc_start, (uint32_t)ctx.nip - pc_start, 0, 0);
2466 fprintf(logfile, "\n"); 3184 fprintf(logfile, "\n");
@@ -2474,12 +3192,12 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -2474,12 +3192,12 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2474 return 0; 3192 return 0;
2475 } 3193 }
2476 3194
2477 -int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb) 3195 +int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2478 { 3196 {
2479 return gen_intermediate_code_internal(env, tb, 0); 3197 return gen_intermediate_code_internal(env, tb, 0);
2480 } 3198 }
2481 3199
2482 -int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb) 3200 +int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2483 { 3201 {
2484 return gen_intermediate_code_internal(env, tb, 1); 3202 return gen_intermediate_code_internal(env, tb, 1);
2485 } 3203 }