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

Too many changes to show.

To preserve performance only 9 of 10 files are displayed.

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