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 25  
26 26 #include "cpu-defs.h"
27 27  
  28 +//#define USE_OPEN_FIRMWARE
  29 +
28 30 /*** Sign extend constants ***/
29 31 /* 8 to 32 bits */
30 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 #include "config.h"
55 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 82 /* Supervisor mode registers */
109 83 /* Machine state register */
... ... @@ -139,26 +113,16 @@ static inline int32_t s_ext24 (uint32_t value)
139 113 #define msr_le env->msr[MSR_LE]
140 114  
141 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 116 typedef struct CPUPPCState {
152 117 /* general purpose registers */
153 118 uint32_t gpr[32];
154 119 /* floating point registers */
155 120 double fpr[32];
156 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 124 /* XER */
161   - uint8_t xer[32];
  125 + uint8_t xer[4];
162 126 /* Reservation address */
163 127 uint32_t reserve;
164 128 /* machine state register */
... ... @@ -166,11 +130,20 @@ typedef struct CPUPPCState {
166 130 /* condition register */
167 131 uint8_t crf[8];
168 132 /* floating point status and control register */
169   - uint8_t fpscr[32];
  133 + uint8_t fpscr[8];
170 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 147 /* qemu dedicated */
175 148 /* temporary float registers */
176 149 double ft0;
... ... @@ -180,9 +153,14 @@ typedef struct CPUPPCState {
180 153 jmp_buf jmp_env;
181 154 int exception_index;
182 155 int error_code;
  156 + uint32_t exceptions; /* exception queue */
  157 + uint32_t errors[16];
183 158 int user_mode_only; /* user mode only simulation */
184 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 164 /* user data */
187 165 void *opaque;
188 166 } CPUPPCState;
... ... @@ -198,107 +176,99 @@ int cpu_ppc_signal_handler(int host_signum, struct siginfo *info,
198 176 void *puc);
199 177  
200 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 187 #define TARGET_PAGE_BITS 12
203 188 #include "cpu-all.h"
204 189  
205 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 196 #define SPR_ENCODE(sprn) \
209 197 (((sprn) >> 5) | (((sprn) & 0x1F) << 5))
210 198  
211 199 /* User mode SPR */
212 200 #define spr(n) env->spr[n]
213   -//#define XER spr[1]
214   -#define XER env->xer
215 201 #define XER_SO 31
216 202 #define XER_OV 30
217 203 #define XER_CA 29
218 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 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 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 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 273 #define TARGET_PAGE_BITS 12
304 274 #include "cpu-all.h"
... ... @@ -307,10 +277,30 @@ CPUPPCState *cpu_ppc_init(void);
307 277 int cpu_ppc_exec(CPUPPCState *s);
308 278 void cpu_ppc_close(CPUPPCState *s);
309 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 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 304 /* PPC hardware exceptions : exception vector / 0x100 */
315 305 EXCP_RESET = 0x01, /* System reset */
316 306 EXCP_MACHINE_CHECK = 0x02, /* Machine check exception */
... ... @@ -326,55 +316,80 @@ enum {
326 316 EXCP_SYSCALL = 0x0C, /* System call */
327 317 EXCP_TRACE = 0x0D, /* Trace exception (optional) */
328 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 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 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 385 /* Privileged instruction */
371   - EXCP_PRIV = 0x71, /* Privileged instruction */
  386 + EXCP_PRIV = 0x30,
  387 + EXCP_PRIV_OPC = 0x01,
  388 + EXCP_PRIV_REG = 0x02,
372 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 395 #endif /* !defined (__CPU_PPC_H__) */
... ...
target-ppc/exec.h
... ... @@ -41,126 +41,119 @@ register uint32_t T2 asm(AREG3);
41 41 #include "cpu.h"
42 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 131 void do_load_fpscr (void);
155 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 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 159 #endif /* !defined (__PPC_H__) */
... ...
target-ppc/helper.c
... ... @@ -17,56 +17,642 @@
17 17 * License along with this library; if not, write to the Free Software
18 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 19 */
  20 +#include <sys/mman.h>
  21 +
20 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 39 void cpu_loop_exit(void)
25 40 {
26 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 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 657 return (xer_so << XER_SO) |
72 658 (xer_ov << XER_OV) |
... ... @@ -74,7 +660,7 @@ uint32_t do_load_xer (void)
74 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 665 xer_so = (value >> XER_SO) & 0x01;
80 666 xer_ov = (value >> XER_OV) & 0x01;
... ... @@ -82,7 +668,7 @@ void do_store_xer (uint32_t value)
82 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 673 return (msr_pow << MSR_POW) |
88 674 (msr_ile << MSR_ILE) |
... ... @@ -101,167 +687,255 @@ uint32_t do_load_msr (void)
101 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 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 21 #include "config.h"
22 22 #include "exec.h"
23 23  
  24 +//#define DEBUG_OP
  25 +
24 26 #define regs (env)
25 27 #define Ts0 (int32_t)T0
26 28 #define Ts1 (int32_t)T1
... ... @@ -34,7 +36,7 @@
34 36 #define FTS1 ((float)env->ft1)
35 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 41 #define REG 0
40 42 #include "op_template.h"
... ... @@ -145,7 +147,7 @@ PPC_OP(set_Rc0)
145 147 } else {
146 148 tmp = 0x02;
147 149 }
148   - set_CRn(0, tmp);
  150 + env->crf[0] = tmp;
149 151 RETURN();
150 152 }
151 153  
... ... @@ -161,21 +163,21 @@ PPC_OP(set_Rc0_ov)
161 163 tmp = 0x02;
162 164 }
163 165 tmp |= xer_ov;
164   - set_CRn(0, tmp);
  166 + env->crf[0] = tmp;
165 167 RETURN();
166 168 }
167 169  
168 170 /* reset_Rc0 */
169 171 PPC_OP(reset_Rc0)
170 172 {
171   - set_CRn(0, 0x02 | xer_ov);
  173 + env->crf[0] = 0x02 | xer_ov;
172 174 RETURN();
173 175 }
174 176  
175 177 /* set_Rc0_1 */
176 178 PPC_OP(set_Rc0_1)
177 179 {
178   - set_CRn(0, 0x04 | xer_ov);
  180 + env->crf[0] = 0x04 | xer_ov;
179 181 RETURN();
180 182 }
181 183  
... ... @@ -186,6 +188,7 @@ PPC_OP(set_Rc1)
186 188 RETURN();
187 189 }
188 190  
  191 +/* Constants load */
189 192 PPC_OP(set_T0)
190 193 {
191 194 T0 = PARAM(1);
... ... @@ -204,23 +207,50 @@ PPC_OP(set_T2)
204 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 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 254 RETURN();
225 255 }
226 256  
... ... @@ -229,15 +259,16 @@ PPC_OP(exit_tb)
229 259 EXIT_TB();
230 260 }
231 261  
  262 +/* Load/store special registers */
232 263 PPC_OP(load_cr)
233 264 {
234   - T0 = do_load_cr();
  265 + do_load_cr();
235 266 RETURN();
236 267 }
237 268  
238 269 PPC_OP(store_cr)
239 270 {
240   - do_store_cr(PARAM(1), T0);
  271 + do_store_cr(PARAM(1));
241 272 RETURN();
242 273 }
243 274  
... ... @@ -257,40 +288,152 @@ PPC_OP(clear_xer_cr)
257 288  
258 289 PPC_OP(load_xer_bc)
259 290 {
260   - T0 = xer_bc;
  291 + T1 = xer_bc;
261 292 RETURN();
262 293 }
263 294  
264 295 PPC_OP(load_xer)
265 296 {
266   - T0 = do_load_xer();
  297 + do_load_xer();
267 298 RETURN();
268 299 }
269 300  
270 301 PPC_OP(store_xer)
271 302 {
272   - do_store_xer(T0);
  303 + do_store_xer();
273 304 RETURN();
274 305 }
275 306  
276 307 PPC_OP(load_msr)
277 308 {
278   - T0 = do_load_msr();
  309 + do_load_msr();
279 310 RETURN();
280 311 }
281 312  
282 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 329 RETURN();
286 330 }
287 331  
288 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 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 437 /* FPSCR */
295 438 PPC_OP(load_fpscr)
296 439 {
... ... @@ -313,14 +456,7 @@ PPC_OP(reset_scrfx)
313 456 /* Set reservation */
314 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 460 RETURN();
325 461 }
326 462  
... ... @@ -344,47 +480,65 @@ PPC_OP(setcrfbit)
344 480 }
345 481  
346 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 490 #define __PPC_OP_B(name, target) \
348 491 PPC_OP(name) \
349 492 { \
350   - regs->nip = (target); \
  493 + TB_DO_JUMP(glue(op_, name), T1, 0, (target)); \
351 494 RETURN(); \
352 495 }
353 496  
354   -#define __PPC_OP_BL(name, target) \
  497 +#define __PPC_OP_BL(name, target, link) \
355 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 502 RETURN(); \
360 503 }
361 504  
362   -#define PPC_OP_B(name, target) \
  505 +#define PPC_OP_B(name, target, link) \
363 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 509 #define __PPC_OP_BC(name, cond, target) \
367 510 PPC_OP(name) \
368 511 { \
369 512 if (cond) { \
370   - T0 = (target); \
  513 + TB_DO_JUMP(glue(op_, name), T1, 1, (target)); \
371 514 } else { \
372   - T0 = PARAM(1); \
  515 + TB_DO_JUMP(glue(op_, name), T1, 0, PARAM(1)); \
373 516 } \
374   - regs->nip = T0; \
375 517 RETURN(); \
376 518 }
377 519  
378 520 #define __PPC_OP_BCL(name, cond, target) \
379 521 PPC_OP(name) \
380 522 { \
  523 + regs->lr = PARAM(1); \
381 524 if (cond) { \
382   - T0 = (target); \
383   - regs->LR = PARAM(1); \
  525 + TB_DO_JUMP(glue(op_, name), T1, 1, (target)); \
384 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 542 RETURN(); \
389 543 }
390 544  
... ... @@ -396,48 +550,56 @@ __PPC_OP_BCL(namel, cond, target)
396 550 #define PPC_OP_BC(name, cond) \
397 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 560 PPC_OP_BC(true, ((T0 & PARAM(3)) != 0));
407 561 PPC_OP_BC(false, ((T0 & PARAM(3)) == 0));
408 562  
409 563 /* Branch to CTR */
410 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 574 PPC_OP_BCCTR(true, ((T0 & PARAM(2)) != 0));
421 575 PPC_OP_BCCTR(false, ((T0 & PARAM(2)) == 0));
422 576  
423 577 /* Branch to LR */
424 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 596 PPC_OP_BCLR(true, ((T0 & PARAM(2)) != 0));
435 597 PPC_OP_BCLR(false, ((T0 & PARAM(2)) == 0));
436 598  
437 599 /* CTR maintenance */
438 600 PPC_OP(dec_ctr)
439 601 {
440   - regs->CTR--;
  602 + regs->ctr--;
441 603 RETURN();
442 604 }
443 605  
... ... @@ -1077,7 +1239,7 @@ PPC_OP(slw)
1077 1239 /* shift right algebraic word */
1078 1240 PPC_OP(sraw)
1079 1241 {
1080   - Ts0 = do_sraw(Ts0, T1);
  1242 + do_sraw();
1081 1243 RETURN();
1082 1244 }
1083 1245  
... ... @@ -1106,313 +1268,280 @@ PPC_OP(srw)
1106 1268 }
1107 1269  
1108 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1525 RETURN();
1404 1526 }
1405 1527  
1406 1528 /* Instruction cache block invalidate */
1407   -PPC_OP(icbi_z)
  1529 +PPC_OP(icbi)
1408 1530 {
1409 1531 do_icbi();
1410 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 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 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 19 */
20 20  
  21 +/* General purpose registers moves */
21 22 void OPPROTO glue(op_load_gpr_T0_gpr, REG)(void)
22 23 {
23 24 T0 = regs->gpr[REG];
  25 + RETURN();
24 26 }
25 27  
26 28 void OPPROTO glue(op_load_gpr_T1_gpr, REG)(void)
27 29 {
28 30 T1 = regs->gpr[REG];
  31 + RETURN();
29 32 }
30 33  
31 34 void OPPROTO glue(op_load_gpr_T2_gpr, REG)(void)
32 35 {
33 36 T2 = regs->gpr[REG];
  37 + RETURN();
34 38 }
35 39  
36 40 void OPPROTO glue(op_store_T0_gpr_gpr, REG)(void)
37 41 {
38 42 regs->gpr[REG] = T0;
  43 + RETURN();
39 44 }
40 45  
41 46 void OPPROTO glue(op_store_T1_gpr_gpr, REG)(void)
42 47 {
43 48 regs->gpr[REG] = T1;
  49 + RETURN();
44 50 }
45 51  
46 52 void OPPROTO glue(op_store_T2_gpr_gpr, REG)(void)
47 53 {
48 54 regs->gpr[REG] = T2;
  55 + RETURN();
49 56 }
50 57  
51 58 #if REG <= 7
52   -
  59 +/* Condition register moves */
53 60 void OPPROTO glue(op_load_crf_T0_crf, REG)(void)
54 61 {
55 62 T0 = regs->crf[REG];
  63 + RETURN();
56 64 }
57 65  
58 66 void OPPROTO glue(op_load_crf_T1_crf, REG)(void)
59 67 {
60 68 T1 = regs->crf[REG];
  69 + RETURN();
61 70 }
62 71  
63 72 void OPPROTO glue(op_store_T0_crf_crf, REG)(void)
64 73 {
65 74 regs->crf[REG] = T0;
  75 + RETURN();
66 76 }
67 77  
68 78 void OPPROTO glue(op_store_T1_crf_crf, REG)(void)
69 79 {
70 80 regs->crf[REG] = T1;
  81 + RETURN();
71 82 }
72 83  
73 84 /* Floating point condition and status register moves */
... ... @@ -117,8 +128,6 @@ void OPPROTO glue(op_clear_fpscr_fpscr, REG)(void)
117 128  
118 129 #endif /* REG <= 7 */
119 130  
120   -/* float moves */
121   -
122 131 /* floating point registers moves */
123 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 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 186 #undef REG
... ...