Commit 9a64fbe4d89751524be0954f87dd514083295e99

Authored by bellard
1 parent efe160c5

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


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@528 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/cpu.h
... ... @@ -25,6 +25,8 @@
25 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
... ...
target-ppc/translate.c
... ... @@ -24,6 +24,7 @@
24 24  
25 25 //#define DO_SINGLE_STEP
26 26 //#define DO_STEP_FLUSH
  27 +//#define DEBUG_DISAS
27 28  
28 29 enum {
29 30 #define DEF(s, n, copy_size) INDEX_op_ ## s,
... ... @@ -37,41 +38,49 @@ static uint32_t *gen_opparam_ptr;
37 38  
38 39 #include "gen-op.h"
39 40  
40   -typedef void (GenOpFunc)(void);
41   -typedef void (GenOpFunc1)(long);
42   -typedef void (GenOpFunc2)(long, long);
43   -typedef void (GenOpFunc3)(long, long, long);
44   -
45 41 #define GEN8(func, NAME) \
46   -static GenOpFunc *NAME ## _table [8] = {\
47   -NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,\
48   -NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,\
49   -};\
50   -static inline void func(int n)\
51   -{\
52   - NAME ## _table[n]();\
  42 +static GenOpFunc *NAME ## _table [8] = { \
  43 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  44 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  45 +}; \
  46 +static inline void func(int n) \
  47 +{ \
  48 + NAME ## _table[n](); \
  49 +}
  50 +
  51 +#define GEN16(func, NAME) \
  52 +static GenOpFunc *NAME ## _table [16] = { \
  53 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  54 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  55 +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
  56 +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
  57 +}; \
  58 +static inline void func(int n) \
  59 +{ \
  60 + NAME ## _table[n](); \
53 61 }
54 62  
55 63 #define GEN32(func, NAME) \
56   -static GenOpFunc *NAME ## _table [32] = {\
57   -NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,\
58   -NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,\
59   -NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,\
60   -NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,\
61   -NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,\
62   -NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,\
63   -NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,\
64   -NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,\
65   -};\
66   -static inline void func(int n)\
67   -{\
68   - NAME ## _table[n]();\
69   -}
70   -
71   -GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf)
72   -GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf)
73   -GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf)
74   -GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf)
  64 +static GenOpFunc *NAME ## _table [32] = { \
  65 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  66 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  67 +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
  68 +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
  69 +NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
  70 +NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
  71 +NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
  72 +NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
  73 +}; \
  74 +static inline void func(int n) \
  75 +{ \
  76 + NAME ## _table[n](); \
  77 +}
  78 +
  79 +/* Condition register moves */
  80 +GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
  81 +GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
  82 +GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
  83 +GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
75 84  
76 85 /* Floating point condition and status register moves */
77 86 GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr);
... ... @@ -92,13 +101,18 @@ static inline void gen_op_store_T0_fpscri(int n, uint8_t param)
92 101 (*gen_op_store_T0_fpscri_fpscr_table[n])(param);
93 102 }
94 103  
95   -GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr)
96   -GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr)
97   -GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr)
  104 +/* Segment register moves */
  105 +GEN16(gen_op_load_sr, gen_op_load_sr);
  106 +GEN16(gen_op_store_sr, gen_op_store_sr);
98 107  
99   -GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr)
100   -GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr)
101   -GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr)
  108 +/* General purpose registers moves */
  109 +GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr);
  110 +GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr);
  111 +GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr);
  112 +
  113 +GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr);
  114 +GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr);
  115 +GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr);
102 116  
103 117 /* floating point registers moves */
104 118 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
... ... @@ -115,53 +129,51 @@ typedef struct DisasContext {
115 129 struct TranslationBlock *tb;
116 130 uint32_t *nip;
117 131 uint32_t opcode;
118   - int exception;
119   - int retcode;
120   - /* Time base */
  132 + uint32_t exception;
  133 + /* Time base offset */
121 134 uint32_t tb_offset;
  135 + /* Decrementer offset */
  136 + uint32_t decr_offset;
  137 + /* Execution mode */
  138 +#if !defined(CONFIG_USER_ONLY)
122 139 int supervisor;
  140 +#endif
  141 + /* Routine used to access memory */
  142 + int mem_idx;
123 143 } DisasContext;
124 144  
125 145 typedef struct opc_handler_t {
126 146 /* invalid bits */
127 147 uint32_t inval;
  148 + /* instruction type */
  149 + uint32_t type;
128 150 /* handler */
129 151 void (*handler)(DisasContext *ctx);
130 152 } opc_handler_t;
131 153  
132   -#define SET_RETVAL(n) \
  154 +#define RET_EXCP(excp, error) \
133 155 do { \
134   - if ((n) != 0) { \
135   - ctx->exception = (n); \
136   - } \
  156 + gen_op_queue_exception_err(excp, error); \
  157 + ctx->exception = excp; \
137 158 return; \
138 159 } while (0)
139 160  
140   -#define GET_RETVAL(func, __opcode) \
141   -({ \
142   - (func)(&ctx); \
143   - ctx.exception; \
144   -})
  161 +#define RET_INVAL() \
  162 +RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
  163 +
  164 +#define RET_PRIVOPC() \
  165 +RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
  166 +
  167 +#define RET_PRIVREG() \
  168 +RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
145 169  
146 170 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
147 171 static void gen_##name (DisasContext *ctx); \
148 172 GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
149 173 static void gen_##name (DisasContext *ctx)
150 174  
151   -/* Instruction types */
152   -enum {
153   - PPC_INTEGER = 0x0001, /* CPU has integer operations instructions */
154   - PPC_FLOAT = 0x0002, /* CPU has floating point operations instructions */
155   - PPC_FLOW = 0x0004, /* CPU has flow control instructions */
156   - PPC_MEM = 0x0008, /* CPU has virtual memory instructions */
157   - PPC_MISC = 0x0010, /* CPU has spr/msr access instructions */
158   - PPC_EXTERN = 0x0020, /* CPU has external control instructions */
159   - PPC_SEGMENT = 0x0040, /* CPU has memory segment instructions */
160   -};
161   -
162 175 typedef struct opcode_t {
163 176 unsigned char opc1, opc2, opc3;
164   - uint32_t type;
165 177 opc_handler_t handler;
166 178 } opcode_t;
167 179  
... ... @@ -169,9 +181,6 @@ typedef struct opcode_t {
169 181 extern FILE *logfile;
170 182 extern int loglevel;
171 183  
172   -/* XXX: shouldn't stay all alone here ! */
173   -static int reserve = 0;
174   -
175 184 /*** Instruction decoding ***/
176 185 #define EXTRACT_HELPER(name, shift, nb) \
177 186 static inline uint32_t name (uint32_t opcode) \
... ... @@ -272,9 +281,9 @@ static opcode_t opc_##name = { \
272 281 .opc1 = op1, \
273 282 .opc2 = op2, \
274 283 .opc3 = op3, \
275   - .type = _typ, \
276 284 .handler = { \
277 285 .inval = invl, \
  286 + .type = _typ, \
278 287 .handler = &gen_##name, \
279 288 }, \
280 289 }
... ... @@ -285,9 +294,9 @@ static opcode_t opc_##name = { \
285 294 .opc1 = 0xFF, \
286 295 .opc2 = 0xFF, \
287 296 .opc3 = 0xFF, \
288   - .type = 0x00, \
289 297 .handler = { \
290 298 .inval = 0x00000000, \
  299 + .type = 0x00, \
291 300 .handler = NULL, \
292 301 }, \
293 302 }
... ... @@ -296,15 +305,36 @@ static opcode_t opc_##name = { \
296 305 GEN_OPCODE_MARK(start);
297 306  
298 307 /* Invalid instruction */
299   -GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, 0)
  308 +GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
  309 +{
  310 + RET_INVAL();
  311 +}
  312 +
  313 +/* Special opcode to stop emulation */
  314 +GEN_HANDLER(stop, 0x06, 0x00, 0xFF, 0x03FFFFC1, PPC_COMMON)
300 315 {
301   - /* Branch to next instruction to force nip update */
302   - gen_op_b((uint32_t)ctx->nip);
303   - SET_RETVAL(EXCP_INVAL);
  316 + gen_op_queue_exception(EXCP_HLT);
  317 + ctx->exception = EXCP_HLT;
  318 +}
  319 +
  320 +/* Special opcode to call open-firmware */
  321 +GEN_HANDLER(of_enter, 0x06, 0x01, 0xFF, 0x03FFFFC1, PPC_COMMON)
  322 +{
  323 + gen_op_queue_exception(EXCP_OFCALL);
  324 + ctx->exception = EXCP_OFCALL;
  325 +}
  326 +
  327 +/* Special opcode to call RTAS */
  328 +GEN_HANDLER(rtas_enter, 0x06, 0x02, 0xFF, 0x03FFFFC1, PPC_COMMON)
  329 +{
  330 + printf("RTAS entry point !\n");
  331 + gen_op_queue_exception(EXCP_RTASCALL);
  332 + ctx->exception = EXCP_RTASCALL;
304 333 }
305 334  
306 335 static opc_handler_t invalid_handler = {
307 336 .inval = 0xFFFFFFFF,
  337 + .type = PPC_NONE,
308 338 .handler = gen_invalid,
309 339 };
310 340  
... ... @@ -318,7 +348,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
318 348 if (Rc(ctx->opcode) != 0) \
319 349 gen_op_set_Rc0(); \
320 350 gen_op_store_T0_gpr(rD(ctx->opcode)); \
321   - SET_RETVAL(0); \
322 351 }
323 352  
324 353 #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval) \
... ... @@ -330,7 +359,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, inval, PPC_INTEGER) \
330 359 if (Rc(ctx->opcode) != 0) \
331 360 gen_op_set_Rc0_ov(); \
332 361 gen_op_store_T0_gpr(rD(ctx->opcode)); \
333   - SET_RETVAL(0); \
334 362 }
335 363  
336 364 #define __GEN_INT_ARITH1(name, opc1, opc2, opc3) \
... ... @@ -341,7 +369,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
341 369 if (Rc(ctx->opcode) != 0) \
342 370 gen_op_set_Rc0(); \
343 371 gen_op_store_T0_gpr(rD(ctx->opcode)); \
344   - SET_RETVAL(0); \
345 372 }
346 373 #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3) \
347 374 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
... ... @@ -351,7 +378,6 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, PPC_INTEGER) \
351 378 if (Rc(ctx->opcode) != 0) \
352 379 gen_op_set_Rc0_ov(); \
353 380 gen_op_store_T0_gpr(rD(ctx->opcode)); \
354   - SET_RETVAL(0); \
355 381 }
356 382  
357 383 /* Two operands arithmetic functions */
... ... @@ -412,7 +438,6 @@ GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
412 438 gen_op_addi(simm);
413 439 }
414 440 gen_op_store_T0_gpr(rD(ctx->opcode));
415   - SET_RETVAL(0);
416 441 }
417 442 /* addic */
418 443 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
... ... @@ -420,7 +445,6 @@ GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
420 445 gen_op_load_gpr_T0(rA(ctx->opcode));
421 446 gen_op_addic(SIMM(ctx->opcode));
422 447 gen_op_store_T0_gpr(rD(ctx->opcode));
423   - SET_RETVAL(0);
424 448 }
425 449 /* addic. */
426 450 GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
... ... @@ -429,7 +453,6 @@ GEN_HANDLER(addic_, 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
429 453 gen_op_addic(SIMM(ctx->opcode));
430 454 gen_op_set_Rc0();
431 455 gen_op_store_T0_gpr(rD(ctx->opcode));
432   - SET_RETVAL(0);
433 456 }
434 457 /* addis */
435 458 GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
... ... @@ -443,7 +466,6 @@ GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
443 466 gen_op_addi(simm << 16);
444 467 }
445 468 gen_op_store_T0_gpr(rD(ctx->opcode));
446   - SET_RETVAL(0);
447 469 }
448 470 /* mulli */
449 471 GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
... ... @@ -451,7 +473,6 @@ GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
451 473 gen_op_load_gpr_T0(rA(ctx->opcode));
452 474 gen_op_mulli(SIMM(ctx->opcode));
453 475 gen_op_store_T0_gpr(rD(ctx->opcode));
454   - SET_RETVAL(0);
455 476 }
456 477 /* subfic */
457 478 GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
... ... @@ -459,7 +480,6 @@ GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
459 480 gen_op_load_gpr_T0(rA(ctx->opcode));
460 481 gen_op_subfic(SIMM(ctx->opcode));
461 482 gen_op_store_T0_gpr(rD(ctx->opcode));
462   - SET_RETVAL(0);
463 483 }
464 484  
465 485 /*** Integer comparison ***/
... ... @@ -470,7 +490,6 @@ GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, PPC_INTEGER) \
470 490 gen_op_load_gpr_T1(rB(ctx->opcode)); \
471 491 gen_op_##name(); \
472 492 gen_op_store_T0_crf(crfD(ctx->opcode)); \
473   - SET_RETVAL(0); \
474 493 }
475 494  
476 495 /* cmp */
... ... @@ -481,7 +500,6 @@ GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
481 500 gen_op_load_gpr_T0(rA(ctx->opcode));
482 501 gen_op_cmpi(SIMM(ctx->opcode));
483 502 gen_op_store_T0_crf(crfD(ctx->opcode));
484   - SET_RETVAL(0);
485 503 }
486 504 /* cmpl */
487 505 GEN_CMP(cmpl, 0x01);
... ... @@ -491,7 +509,6 @@ GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
491 509 gen_op_load_gpr_T0(rA(ctx->opcode));
492 510 gen_op_cmpli(UIMM(ctx->opcode));
493 511 gen_op_store_T0_crf(crfD(ctx->opcode));
494   - SET_RETVAL(0);
495 512 }
496 513  
497 514 /*** Integer logical ***/
... ... @@ -504,7 +521,6 @@ GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, PPC_INTEGER) \
504 521 if (Rc(ctx->opcode) != 0) \
505 522 gen_op_set_Rc0(); \
506 523 gen_op_store_T0_gpr(rA(ctx->opcode)); \
507   - SET_RETVAL(0); \
508 524 }
509 525 #define GEN_LOGICAL2(name, opc) \
510 526 __GEN_LOGICAL2(name, 0x1C, opc)
... ... @@ -517,7 +533,6 @@ GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, PPC_INTEGER) \
517 533 if (Rc(ctx->opcode) != 0) \
518 534 gen_op_set_Rc0(); \
519 535 gen_op_store_T0_gpr(rA(ctx->opcode)); \
520   - SET_RETVAL(0); \
521 536 }
522 537  
523 538 /* and & and. */
... ... @@ -531,7 +546,6 @@ GEN_HANDLER(andi_, 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
531 546 gen_op_andi_(UIMM(ctx->opcode));
532 547 gen_op_set_Rc0();
533 548 gen_op_store_T0_gpr(rA(ctx->opcode));
534   - SET_RETVAL(0);
535 549 }
536 550 /* andis. */
537 551 GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
... ... @@ -540,7 +554,6 @@ GEN_HANDLER(andis_, 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
540 554 gen_op_andi_(UIMM(ctx->opcode) << 16);
541 555 gen_op_set_Rc0();
542 556 gen_op_store_T0_gpr(rA(ctx->opcode));
543   - SET_RETVAL(0);
544 557 }
545 558  
546 559 /* cntlzw */
... ... @@ -555,68 +568,94 @@ GEN_LOGICAL1(extsh, 0x1C);
555 568 GEN_LOGICAL2(nand, 0x0E);
556 569 /* nor & nor. */
557 570 GEN_LOGICAL2(nor, 0x03);
  571 +
558 572 /* or & or. */
559   -GEN_LOGICAL2(or, 0x0D);
  573 +GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
  574 +{
  575 + gen_op_load_gpr_T0(rS(ctx->opcode));
  576 + /* Optimisation for mr case */
  577 + if (rS(ctx->opcode) != rB(ctx->opcode)) {
  578 + gen_op_load_gpr_T1(rB(ctx->opcode));
  579 + gen_op_or();
  580 + }
  581 + if (Rc(ctx->opcode) != 0)
  582 + gen_op_set_Rc0();
  583 + gen_op_store_T0_gpr(rA(ctx->opcode));
  584 +}
  585 +
560 586 /* orc & orc. */
561 587 GEN_LOGICAL2(orc, 0x0C);
562 588 /* xor & xor. */
563   -GEN_LOGICAL2(xor, 0x09);
  589 +GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
  590 +{
  591 + gen_op_load_gpr_T0(rS(ctx->opcode));
  592 + /* Optimisation for "set to zero" case */
  593 + if (rS(ctx->opcode) != rB(ctx->opcode)) {
  594 + gen_op_load_gpr_T1(rB(ctx->opcode));
  595 + gen_op_xor();
  596 + } else {
  597 + gen_op_set_T0(0);
  598 + }
  599 + if (Rc(ctx->opcode) != 0)
  600 + gen_op_set_Rc0();
  601 + gen_op_store_T0_gpr(rA(ctx->opcode));
  602 +}
564 603 /* ori */
565 604 GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
566 605 {
567 606 uint32_t uimm = UIMM(ctx->opcode);
568 607  
569   -#if 0
570   - if (uimm == 0) {
571   - if (rA(ctx->opcode) != rS(ctx->opcode)) {
572   - gen_op_load_gpr_T0(rS(ctx->opcode));
573   - gen_op_store_T0_gpr(rA(ctx->opcode));
  608 + if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
  609 + /* NOP */
  610 + return;
574 611 }
575   - } else
576   -#endif
577   - {
578 612 gen_op_load_gpr_T0(rS(ctx->opcode));
  613 + if (uimm != 0)
579 614 gen_op_ori(uimm);
580 615 gen_op_store_T0_gpr(rA(ctx->opcode));
581   - }
582   - SET_RETVAL(0);
583 616 }
584 617 /* oris */
585 618 GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
586 619 {
587 620 uint32_t uimm = UIMM(ctx->opcode);
588 621  
589   -#if 0
590   - if (uimm == 0) {
591   - if (rA(ctx->opcode) != rS(ctx->opcode)) {
592   - gen_op_load_gpr_T0(rS(ctx->opcode));
593   - gen_op_store_T0_gpr(rA(ctx->opcode));
  622 + if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
  623 + /* NOP */
  624 + return;
594 625 }
595   - } else
596   -#endif
597   - {
598 626 gen_op_load_gpr_T0(rS(ctx->opcode));
  627 + if (uimm != 0)
599 628 gen_op_ori(uimm << 16);
600 629 gen_op_store_T0_gpr(rA(ctx->opcode));
601   - }
602   - SET_RETVAL(0);
603 630 }
604 631 /* xori */
605 632 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
606 633 {
  634 + uint32_t uimm = UIMM(ctx->opcode);
  635 +
  636 + if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
  637 + /* NOP */
  638 + return;
  639 + }
607 640 gen_op_load_gpr_T0(rS(ctx->opcode));
  641 + if (uimm != 0)
608 642 gen_op_xori(UIMM(ctx->opcode));
609 643 gen_op_store_T0_gpr(rA(ctx->opcode));
610   - SET_RETVAL(0);
611 644 }
612 645  
613 646 /* xoris */
614 647 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
615 648 {
  649 + uint32_t uimm = UIMM(ctx->opcode);
  650 +
  651 + if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
  652 + /* NOP */
  653 + return;
  654 + }
616 655 gen_op_load_gpr_T0(rS(ctx->opcode));
  656 + if (uimm != 0)
617 657 gen_op_xori(UIMM(ctx->opcode) << 16);
618 658 gen_op_store_T0_gpr(rA(ctx->opcode));
619   - SET_RETVAL(0);
620 659 }
621 660  
622 661 /*** Integer rotate ***/
... ... @@ -633,7 +672,6 @@ GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
633 672 if (Rc(ctx->opcode) != 0)
634 673 gen_op_set_Rc0();
635 674 gen_op_store_T0_gpr(rA(ctx->opcode));
636   - SET_RETVAL(0);
637 675 }
638 676 /* rlwinm & rlwinm. */
639 677 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
... ... @@ -644,10 +682,6 @@ GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
644 682 mb = MB(ctx->opcode);
645 683 me = ME(ctx->opcode);
646 684 gen_op_load_gpr_T0(rS(ctx->opcode));
647   - if (loglevel > 0) {
648   - fprintf(logfile, "%s sh=%u mb=%u me=%u MASK=0x%08x\n",
649   - __func__, sh, mb, me, MASK(mb, me));
650   - }
651 685 if (mb == 0) {
652 686 if (me == 31) {
653 687 gen_op_rotlwi(sh);
... ... @@ -673,7 +707,6 @@ store:
673 707 if (Rc(ctx->opcode) != 0)
674 708 gen_op_set_Rc0();
675 709 gen_op_store_T0_gpr(rA(ctx->opcode));
676   - SET_RETVAL(0);
677 710 }
678 711 /* rlwnm & rlwnm. */
679 712 GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
... ... @@ -693,7 +726,6 @@ GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
693 726 if (Rc(ctx->opcode) != 0)
694 727 gen_op_set_Rc0();
695 728 gen_op_store_T0_gpr(rA(ctx->opcode));
696   - SET_RETVAL(0);
697 729 }
698 730  
699 731 /*** Integer shift ***/
... ... @@ -709,172 +741,169 @@ GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
709 741 if (Rc(ctx->opcode) != 0)
710 742 gen_op_set_Rc0();
711 743 gen_op_store_T0_gpr(rA(ctx->opcode));
712   - SET_RETVAL(0);
713 744 }
714 745 /* srw & srw. */
715 746 __GEN_LOGICAL2(srw, 0x18, 0x10);
716 747  
717 748 /*** Floating-Point arithmetic ***/
718   -/* fadd */
719   -GEN_HANDLER(fadd, 0x3F, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
720   -{
721   - SET_RETVAL(EXCP_INVAL);
  749 +#define _GEN_FLOAT_ACB(name, op1, op2) \
  750 +GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, PPC_FLOAT) \
  751 +{ \
  752 + gen_op_reset_scrfx(); \
  753 + gen_op_load_fpr_FT0(rA(ctx->opcode)); \
  754 + gen_op_load_fpr_FT1(rC(ctx->opcode)); \
  755 + gen_op_load_fpr_FT2(rB(ctx->opcode)); \
  756 + gen_op_f##name(); \
  757 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  758 + if (Rc(ctx->opcode)) \
  759 + gen_op_set_Rc1(); \
  760 +}
  761 +
  762 +#define GEN_FLOAT_ACB(name, op2) \
  763 +_GEN_FLOAT_ACB(name, 0x3F, op2); \
  764 +_GEN_FLOAT_ACB(name##s, 0x3B, op2);
  765 +
  766 +#define _GEN_FLOAT_AB(name, op1, op2, inval) \
  767 +GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
  768 +{ \
  769 + gen_op_reset_scrfx(); \
  770 + gen_op_load_fpr_FT0(rA(ctx->opcode)); \
  771 + gen_op_load_fpr_FT1(rB(ctx->opcode)); \
  772 + gen_op_f##name(); \
  773 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  774 + if (Rc(ctx->opcode)) \
  775 + gen_op_set_Rc1(); \
  776 +}
  777 +#define GEN_FLOAT_AB(name, op2, inval) \
  778 +_GEN_FLOAT_AB(name, 0x3F, op2, inval); \
  779 +_GEN_FLOAT_AB(name##s, 0x3B, op2, inval);
  780 +
  781 +#define _GEN_FLOAT_AC(name, op1, op2, inval) \
  782 +GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT) \
  783 +{ \
  784 + gen_op_reset_scrfx(); \
  785 + gen_op_load_fpr_FT0(rA(ctx->opcode)); \
  786 + gen_op_load_fpr_FT1(rC(ctx->opcode)); \
  787 + gen_op_f##name(); \
  788 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  789 + if (Rc(ctx->opcode)) \
  790 + gen_op_set_Rc1(); \
  791 +}
  792 +#define GEN_FLOAT_AC(name, op2, inval) \
  793 +_GEN_FLOAT_AC(name, 0x3F, op2, inval); \
  794 +_GEN_FLOAT_AC(name##s, 0x3B, op2, inval);
  795 +
  796 +#define GEN_FLOAT_B(name, op2, op3) \
  797 +GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, PPC_FLOAT) \
  798 +{ \
  799 + gen_op_reset_scrfx(); \
  800 + gen_op_load_fpr_FT0(rB(ctx->opcode)); \
  801 + gen_op_f##name(); \
  802 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  803 + if (Rc(ctx->opcode)) \
  804 + gen_op_set_Rc1(); \
722 805 }
723 806  
724   -/* fadds */
725   -GEN_HANDLER(fadds, 0x3B, 0x15, 0xFF, 0x000007C0, PPC_FLOAT)
726   -{
727   - SET_RETVAL(EXCP_INVAL);
  807 +#define GEN_FLOAT_BS(name, op2) \
  808 +GEN_HANDLER(f##name, 0x3F, op2, 0xFF, 0x001F07C0, PPC_FLOAT) \
  809 +{ \
  810 + gen_op_reset_scrfx(); \
  811 + gen_op_load_fpr_FT0(rB(ctx->opcode)); \
  812 + gen_op_f##name(); \
  813 + gen_op_store_FT0_fpr(rD(ctx->opcode)); \
  814 + if (Rc(ctx->opcode)) \
  815 + gen_op_set_Rc1(); \
728 816 }
729 817  
  818 +/* fadd - fadds */
  819 +GEN_FLOAT_AB(add, 0x15, 0x000007C0);
730 820 /* fdiv */
731   -GEN_HANDLER(fdiv, 0x3F, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
732   -{
733   - SET_RETVAL(EXCP_INVAL);
734   -}
735   -
736   -/* fdivs */
737   -GEN_HANDLER(fdivs, 0x3B, 0x12, 0xFF, 0x000007C0, PPC_FLOAT)
738   -{
739   - SET_RETVAL(EXCP_INVAL);
740   -}
741   -
  821 +GEN_FLOAT_AB(div, 0x12, 0x000007C0);
742 822 /* fmul */
743   -GEN_HANDLER(fmul, 0x3F, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
744   -{
745   - SET_RETVAL(EXCP_INVAL);
746   -}
747   -
748   -/* fmuls */
749   -GEN_HANDLER(fmuls, 0x3B, 0x19, 0xFF, 0x0000F800, PPC_FLOAT)
750   -{
751   - SET_RETVAL(EXCP_INVAL);
752   -}
  823 +GEN_FLOAT_AC(mul, 0x19, 0x0000F800);
753 824  
754 825 /* fres */
755   -GEN_HANDLER(fres, 0x3B, 0x18, 0xFF, 0x001807C0, PPC_FLOAT)
756   -{
757   - SET_RETVAL(EXCP_INVAL);
758   -}
  826 +GEN_FLOAT_BS(res, 0x18);
759 827  
760 828 /* frsqrte */
761   -GEN_HANDLER(frsqrte, 0x3F, 0x1A, 0xFF, 0x001807C0, PPC_FLOAT)
762   -{
763   - SET_RETVAL(EXCP_INVAL);
764   -}
  829 +GEN_FLOAT_BS(rsqrte, 0x1A);
765 830  
766 831 /* fsel */
767   -GEN_HANDLER(fsel, 0x3F, 0x17, 0xFF, 0x00000000, PPC_FLOAT)
768   -{
769   - SET_RETVAL(EXCP_INVAL);
770   -}
771   -
  832 +_GEN_FLOAT_ACB(sel, 0x3F, 0x17);
772 833 /* fsub */
773   -GEN_HANDLER(fsub, 0x3F, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
774   -{
775   - SET_RETVAL(EXCP_INVAL);
776   -}
777   -
778   -/* fsubs */
779   -GEN_HANDLER(fsubs, 0x3B, 0x14, 0xFF, 0x000007C0, PPC_FLOAT)
780   -{
781   - SET_RETVAL(EXCP_INVAL);
782   -}
783   -
  834 +GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
784 835 /* Optional: */
785 836 /* fsqrt */
786   -GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
787   -{
788   - SET_RETVAL(EXCP_INVAL);
789   -}
  837 +GEN_FLOAT_BS(sqrt, 0x16);
790 838  
791   -/* fsqrts */
792   -GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001807C0, PPC_FLOAT)
  839 +GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_OPT)
793 840 {
794   - SET_RETVAL(EXCP_INVAL);
  841 + gen_op_reset_scrfx();
  842 + gen_op_load_fpr_FT0(rB(ctx->opcode));
  843 + gen_op_fsqrts();
  844 + gen_op_store_FT0_fpr(rD(ctx->opcode));
  845 + if (Rc(ctx->opcode))
  846 + gen_op_set_Rc1();
795 847 }
796 848  
797 849 /*** Floating-Point multiply-and-add ***/
798 850 /* fmadd */
799   -GEN_HANDLER(fmadd, 0x3F, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
800   -{
801   - SET_RETVAL(EXCP_INVAL);
802   -}
803   -
804   -/* fmadds */
805   -GEN_HANDLER(fmadds, 0x3B, 0x1D, 0xFF, 0x00000000, PPC_FLOAT)
806   -{
807   - SET_RETVAL(EXCP_INVAL);
808   -}
809   -
  851 +GEN_FLOAT_ACB(madd, 0x1D);
810 852 /* fmsub */
811   -GEN_HANDLER(fmsub, 0x3F, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
812   -{
813   - SET_RETVAL(EXCP_INVAL);
814   -}
815   -
816   -/* fmsubs */
817   -GEN_HANDLER(fmsubs, 0x3B, 0x1C, 0xFF, 0x00000000, PPC_FLOAT)
818   -{
819   - SET_RETVAL(EXCP_INVAL);
820   -}
821   -
  853 +GEN_FLOAT_ACB(msub, 0x1C);
822 854 /* fnmadd */
823   -GEN_HANDLER(fnmadd, 0x3F, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
824   -{
825   - SET_RETVAL(EXCP_INVAL);
826   -}
827   -
828   -/* fnmadds */
829   -GEN_HANDLER(fnmadds, 0x3B, 0x1F, 0xFF, 0x00000000, PPC_FLOAT)
830   -{
831   - SET_RETVAL(EXCP_INVAL);
832   -}
833   -
  855 +GEN_FLOAT_ACB(nmadd, 0x1F);
834 856 /* fnmsub */
835   -GEN_HANDLER(fnmsub, 0x3F, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
836   -{
837   - SET_RETVAL(EXCP_INVAL);
838   -}
839   -
840   -/* fnmsubs */
841   -GEN_HANDLER(fnmsubs, 0x3B, 0x1E, 0xFF, 0x00000000, PPC_FLOAT)
842   -{
843   - SET_RETVAL(EXCP_INVAL);
844   -}
  857 +GEN_FLOAT_ACB(nmsub, 0x1E);
845 858  
846 859 /*** Floating-Point round & convert ***/
847 860 /* fctiw */
848   -GEN_HANDLER(fctiw, 0x3F, 0x0E, 0xFF, 0x001F0000, PPC_FLOAT)
849   -{
850   - SET_RETVAL(EXCP_INVAL);
851   -}
852   -
  861 +GEN_FLOAT_B(ctiw, 0x0E, 0x00);
853 862 /* fctiwz */
854   -GEN_HANDLER(fctiwz, 0x3F, 0x0F, 0xFF, 0x001F0000, PPC_FLOAT)
855   -{
856   - SET_RETVAL(EXCP_INVAL);
857   -}
858   -
  863 +GEN_FLOAT_B(ctiwz, 0x0F, 0x00);
859 864 /* frsp */
860   -GEN_HANDLER(frsp, 0x3F, 0x0C, 0xFF, 0x001F0000, PPC_FLOAT)
861   -{
862   - SET_RETVAL(EXCP_INVAL);
863   -}
  865 +GEN_FLOAT_B(rsp, 0x0C, 0x00);
864 866  
865 867 /*** Floating-Point compare ***/
866 868 /* fcmpo */
867 869 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
868 870 {
869   - SET_RETVAL(EXCP_INVAL);
  871 + gen_op_reset_scrfx();
  872 + gen_op_load_fpr_FT0(rA(ctx->opcode));
  873 + gen_op_load_fpr_FT1(rB(ctx->opcode));
  874 + gen_op_fcmpo();
  875 + gen_op_store_T0_crf(crfD(ctx->opcode));
870 876 }
871 877  
872 878 /* fcmpu */
873 879 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
874 880 {
875   - SET_RETVAL(EXCP_INVAL);
  881 + gen_op_reset_scrfx();
  882 + gen_op_load_fpr_FT0(rA(ctx->opcode));
  883 + gen_op_load_fpr_FT1(rB(ctx->opcode));
  884 + gen_op_fcmpu();
  885 + gen_op_store_T0_crf(crfD(ctx->opcode));
876 886 }
877 887  
  888 +/*** Floating-point move ***/
  889 +/* fabs */
  890 +GEN_FLOAT_B(abs, 0x08, 0x08);
  891 +
  892 +/* fmr - fmr. */
  893 +GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
  894 +{
  895 + gen_op_reset_scrfx();
  896 + gen_op_load_fpr_FT0(rB(ctx->opcode));
  897 + gen_op_store_FT0_fpr(rD(ctx->opcode));
  898 + if (Rc(ctx->opcode))
  899 + gen_op_set_Rc1();
  900 +}
  901 +
  902 +/* fnabs */
  903 +GEN_FLOAT_B(nabs, 0x08, 0x04);
  904 +/* fneg */
  905 +GEN_FLOAT_B(neg, 0x08, 0x01);
  906 +
878 907 /*** Floating-Point status & ctrl register ***/
879 908 /* mcrfs */
880 909 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
... ... @@ -882,7 +911,6 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
882 911 gen_op_load_fpscr_T0(crfS(ctx->opcode));
883 912 gen_op_store_T0_crf(crfD(ctx->opcode));
884 913 gen_op_clear_fpscr(crfS(ctx->opcode));
885   - SET_RETVAL(0);
886 914 }
887 915  
888 916 /* mffs */
... ... @@ -892,7 +920,6 @@ GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
892 920 gen_op_store_FT0_fpr(rD(ctx->opcode));
893 921 if (Rc(ctx->opcode))
894 922 gen_op_set_Rc1();
895   - SET_RETVAL(0);
896 923 }
897 924  
898 925 /* mtfsb0 */
... ... @@ -906,7 +933,6 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
906 933 gen_op_store_T0_fpscr(crb);
907 934 if (Rc(ctx->opcode))
908 935 gen_op_set_Rc1();
909   - SET_RETVAL(0);
910 936 }
911 937  
912 938 /* mtfsb1 */
... ... @@ -920,7 +946,6 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
920 946 gen_op_store_T0_fpscr(crb);
921 947 if (Rc(ctx->opcode))
922 948 gen_op_set_Rc1();
923   - SET_RETVAL(0);
924 949 }
925 950  
926 951 /* mtfsf */
... ... @@ -930,7 +955,6 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
930 955 gen_op_store_fpscr(FM(ctx->opcode));
931 956 if (Rc(ctx->opcode))
932 957 gen_op_set_Rc1();
933   - SET_RETVAL(0);
934 958 }
935 959  
936 960 /* mtfsfi */
... ... @@ -939,505 +963,541 @@ GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
939 963 gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
940 964 if (Rc(ctx->opcode))
941 965 gen_op_set_Rc1();
942   - SET_RETVAL(0);
943 966 }
944 967  
945 968 /*** Integer load ***/
946   -#define GEN_ILDZ(width, opc) \
  969 +#if defined(CONFIG_USER_ONLY)
  970 +#define op_ldst(name) gen_op_##name##_raw()
  971 +#define OP_LD_TABLE(width)
  972 +#define OP_ST_TABLE(width)
  973 +#else
  974 +#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
  975 +#define OP_LD_TABLE(width) \
  976 +static GenOpFunc *gen_op_l##width[] = { \
  977 + &gen_op_l##width##_user, \
  978 + &gen_op_l##width##_kernel, \
  979 +}
  980 +#define OP_ST_TABLE(width) \
  981 +static GenOpFunc *gen_op_st##width[] = { \
  982 + &gen_op_st##width##_user, \
  983 + &gen_op_st##width##_kernel, \
  984 +}
  985 +#endif
  986 +
  987 +#define GEN_LD(width, opc) \
947 988 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
948 989 { \
949 990 uint32_t simm = SIMM(ctx->opcode); \
950 991 if (rA(ctx->opcode) == 0) { \
951   - gen_op_l##width##_z(simm); \
  992 + gen_op_set_T0(simm); \
952 993 } else { \
953 994 gen_op_load_gpr_T0(rA(ctx->opcode)); \
954   - gen_op_l##width (simm); \
  995 + if (simm != 0) \
  996 + gen_op_addi(simm); \
955 997 } \
  998 + op_ldst(l##width); \
956 999 gen_op_store_T1_gpr(rD(ctx->opcode)); \
957   - SET_RETVAL(0); \
958 1000 }
959 1001  
960   -#define GEN_ILDZU(width, opc) \
  1002 +#define GEN_LDU(width, opc) \
961 1003 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
962 1004 { \
  1005 + uint32_t simm = SIMM(ctx->opcode); \
963 1006 if (rA(ctx->opcode) == 0 || \
964   - rA(ctx->opcode) == rD(ctx->opcode)) \
965   - SET_RETVAL(EXCP_INVAL); \
  1007 + rA(ctx->opcode) == rD(ctx->opcode)) { \
  1008 + RET_INVAL(); \
  1009 + } \
966 1010 gen_op_load_gpr_T0(rA(ctx->opcode)); \
967   - gen_op_l##width(SIMM(ctx->opcode)); \
  1011 + if (simm != 0) \
  1012 + gen_op_addi(simm); \
  1013 + op_ldst(l##width); \
968 1014 gen_op_store_T1_gpr(rD(ctx->opcode)); \
969 1015 gen_op_store_T0_gpr(rA(ctx->opcode)); \
970   - SET_RETVAL(0); \
971 1016 }
972 1017  
973   -#define GEN_ILDZUX(width, opc) \
  1018 +#define GEN_LDUX(width, opc) \
974 1019 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
975 1020 { \
976 1021 if (rA(ctx->opcode) == 0 || \
977   - rA(ctx->opcode) == rD(ctx->opcode)) \
978   - SET_RETVAL(EXCP_INVAL); \
  1022 + rA(ctx->opcode) == rD(ctx->opcode)) { \
  1023 + RET_INVAL(); \
  1024 + } \
979 1025 gen_op_load_gpr_T0(rA(ctx->opcode)); \
980 1026 gen_op_load_gpr_T1(rB(ctx->opcode)); \
981   - gen_op_l##width##x(); \
  1027 + gen_op_add(); \
  1028 + op_ldst(l##width); \
982 1029 gen_op_store_T1_gpr(rD(ctx->opcode)); \
983 1030 gen_op_store_T0_gpr(rA(ctx->opcode)); \
984   - SET_RETVAL(0); \
985 1031 }
986 1032  
987   -#define GEN_ILDZX(width, opc2, opc3) \
  1033 +#define GEN_LDX(width, opc2, opc3) \
988 1034 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
989 1035 { \
990 1036 if (rA(ctx->opcode) == 0) { \
991 1037 gen_op_load_gpr_T0(rB(ctx->opcode)); \
992   - gen_op_l##width##x_z(); \
993 1038 } else { \
994 1039 gen_op_load_gpr_T0(rA(ctx->opcode)); \
995 1040 gen_op_load_gpr_T1(rB(ctx->opcode)); \
996   - gen_op_l##width##x(); \
  1041 + gen_op_add(); \
997 1042 } \
  1043 + op_ldst(l##width); \
998 1044 gen_op_store_T1_gpr(rD(ctx->opcode)); \
999   - SET_RETVAL(0); \
1000 1045 }
1001 1046  
1002   -#define GEN_ILD(width, op) \
1003   -GEN_ILDZ(width, op | 0x20) \
1004   -GEN_ILDZU(width, op | 0x21) \
1005   -GEN_ILDZUX(width, op | 0x01) \
1006   -GEN_ILDZX(width, 0x17, op | 0x00)
  1047 +#define GEN_LDS(width, op) \
  1048 +OP_LD_TABLE(width); \
  1049 +GEN_LD(width, op | 0x20); \
  1050 +GEN_LDU(width, op | 0x21); \
  1051 +GEN_LDUX(width, op | 0x01); \
  1052 +GEN_LDX(width, 0x17, op | 0x00)
1007 1053  
1008 1054 /* lbz lbzu lbzux lbzx */
1009   -GEN_ILD(bz, 0x02);
  1055 +GEN_LDS(bz, 0x02);
1010 1056 /* lha lhau lhaux lhax */
1011   -GEN_ILD(ha, 0x0A);
  1057 +GEN_LDS(ha, 0x0A);
1012 1058 /* lhz lhzu lhzux lhzx */
1013   -GEN_ILD(hz, 0x08);
  1059 +GEN_LDS(hz, 0x08);
1014 1060 /* lwz lwzu lwzux lwzx */
1015   -GEN_ILD(wz, 0x00);
  1061 +GEN_LDS(wz, 0x00);
1016 1062  
1017 1063 /*** Integer store ***/
1018   -#define GEN_IST(width, opc) \
  1064 +#define GEN_ST(width, opc) \
1019 1065 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1020 1066 { \
1021 1067 uint32_t simm = SIMM(ctx->opcode); \
1022 1068 if (rA(ctx->opcode) == 0) { \
1023   - gen_op_load_gpr_T0(rS(ctx->opcode)); \
1024   - gen_op_st##width##_z(simm); \
  1069 + gen_op_set_T0(simm); \
1025 1070 } else { \
1026 1071 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1027   - gen_op_load_gpr_T1(rS(ctx->opcode)); \
1028   - gen_op_st##width(simm); \
  1072 + if (simm != 0) \
  1073 + gen_op_addi(simm); \
1029 1074 } \
1030   - SET_RETVAL(0); \
  1075 + gen_op_load_gpr_T1(rS(ctx->opcode)); \
  1076 + op_ldst(st##width); \
1031 1077 }
1032 1078  
1033   -#define GEN_ISTU(width, opc) \
  1079 +#define GEN_STU(width, opc) \
1034 1080 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1035 1081 { \
1036   - if (rA(ctx->opcode) == 0) \
1037   - SET_RETVAL(EXCP_INVAL); \
  1082 + uint32_t simm = SIMM(ctx->opcode); \
  1083 + if (rA(ctx->opcode) == 0) { \
  1084 + RET_INVAL(); \
  1085 + } \
1038 1086 gen_op_load_gpr_T0(rA(ctx->opcode)); \
  1087 + if (simm != 0) \
  1088 + gen_op_addi(simm); \
1039 1089 gen_op_load_gpr_T1(rS(ctx->opcode)); \
1040   - gen_op_st##width(SIMM(ctx->opcode)); \
  1090 + op_ldst(st##width); \
1041 1091 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1042   - SET_RETVAL(0); \
1043 1092 }
1044 1093  
1045   -#define GEN_ISTUX(width, opc) \
  1094 +#define GEN_STUX(width, opc) \
1046 1095 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1047 1096 { \
1048   - if (rA(ctx->opcode) == 0) \
1049   - SET_RETVAL(EXCP_INVAL); \
  1097 + if (rA(ctx->opcode) == 0) { \
  1098 + RET_INVAL(); \
  1099 + } \
1050 1100 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1051 1101 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1052   - gen_op_load_gpr_T2(rS(ctx->opcode)); \
1053   - gen_op_st##width##x(); \
  1102 + gen_op_add(); \
  1103 + gen_op_load_gpr_T1(rS(ctx->opcode)); \
  1104 + op_ldst(st##width); \
1054 1105 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1055   - SET_RETVAL(0); \
1056 1106 }
1057 1107  
1058   -#define GEN_ISTX(width, opc2, opc3) \
  1108 +#define GEN_STX(width, opc2, opc3) \
1059 1109 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1060 1110 { \
1061 1111 if (rA(ctx->opcode) == 0) { \
1062 1112 gen_op_load_gpr_T0(rB(ctx->opcode)); \
1063   - gen_op_load_gpr_T1(rS(ctx->opcode)); \
1064   - gen_op_st##width##x_z(); \
1065 1113 } else { \
1066 1114 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1067 1115 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1068   - gen_op_load_gpr_T2(rS(ctx->opcode)); \
1069   - gen_op_st##width##x(); \
  1116 + gen_op_add(); \
1070 1117 } \
1071   - SET_RETVAL(0); \
  1118 + gen_op_load_gpr_T1(rS(ctx->opcode)); \
  1119 + op_ldst(st##width); \
1072 1120 }
1073 1121  
1074   -#define GEN_ISTO(width, opc) \
1075   -GEN_IST(width, opc | 0x20) \
1076   -GEN_ISTU(width, opc | 0x21) \
1077   -GEN_ISTUX(width, opc | 0x01) \
1078   -GEN_ISTX(width, 0x17, opc | 0x00)
  1122 +#define GEN_STS(width, op) \
  1123 +OP_ST_TABLE(width); \
  1124 +GEN_ST(width, op | 0x20); \
  1125 +GEN_STU(width, op | 0x21); \
  1126 +GEN_STUX(width, op | 0x01); \
  1127 +GEN_STX(width, 0x17, op | 0x00)
1079 1128  
1080 1129 /* stb stbu stbux stbx */
1081   -GEN_ISTO(b, 0x06);
  1130 +GEN_STS(b, 0x06);
1082 1131 /* sth sthu sthux sthx */
1083   -GEN_ISTO(h, 0x0C);
  1132 +GEN_STS(h, 0x0C);
1084 1133 /* stw stwu stwux stwx */
1085   -GEN_ISTO(w, 0x04);
  1134 +GEN_STS(w, 0x04);
1086 1135  
1087 1136 /*** Integer load and store with byte reverse ***/
1088 1137 /* lhbrx */
1089   -GEN_ILDZX(hbr, 0x16, 0x18);
  1138 +OP_LD_TABLE(hbr);
  1139 +GEN_LDX(hbr, 0x16, 0x18);
1090 1140 /* lwbrx */
1091   -GEN_ILDZX(wbr, 0x16, 0x10);
  1141 +OP_LD_TABLE(wbr);
  1142 +GEN_LDX(wbr, 0x16, 0x10);
1092 1143 /* sthbrx */
1093   -GEN_ISTX(hbr, 0x16, 0x1C);
  1144 +OP_ST_TABLE(hbr);
  1145 +GEN_STX(hbr, 0x16, 0x1C);
1094 1146 /* stwbrx */
1095   -GEN_ISTX(wbr, 0x16, 0x14);
  1147 +OP_ST_TABLE(wbr);
  1148 +GEN_STX(wbr, 0x16, 0x14);
1096 1149  
1097 1150 /*** Integer load and store multiple ***/
  1151 +#if defined(CONFIG_USER_ONLY)
  1152 +#define op_ldstm(name, reg) gen_op_##name##_raw(reg)
  1153 +#else
  1154 +#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
  1155 +static GenOpFunc1 *gen_op_lmw[] = {
  1156 + &gen_op_lmw_user,
  1157 + &gen_op_lmw_kernel,
  1158 +};
  1159 +static GenOpFunc1 *gen_op_stmw[] = {
  1160 + &gen_op_stmw_user,
  1161 + &gen_op_stmw_kernel,
  1162 +};
  1163 +#endif
  1164 +
1098 1165 /* lmw */
1099 1166 GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1100 1167 {
  1168 + int simm = SIMM(ctx->opcode);
  1169 +
1101 1170 if (rA(ctx->opcode) == 0) {
1102   - gen_op_set_T0(0);
  1171 + gen_op_set_T0(simm);
1103 1172 } else {
1104 1173 gen_op_load_gpr_T0(rA(ctx->opcode));
  1174 + if (simm != 0)
  1175 + gen_op_addi(simm);
1105 1176 }
1106   - gen_op_lmw(rD(ctx->opcode), SIMM(ctx->opcode));
1107   - SET_RETVAL(0);
  1177 + op_ldstm(lmw, rD(ctx->opcode));
1108 1178 }
1109 1179  
1110 1180 /* stmw */
1111 1181 GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1112 1182 {
  1183 + int simm = SIMM(ctx->opcode);
  1184 +
1113 1185 if (rA(ctx->opcode) == 0) {
1114   - gen_op_set_T0(0);
  1186 + gen_op_set_T0(simm);
1115 1187 } else {
1116 1188 gen_op_load_gpr_T0(rA(ctx->opcode));
  1189 + if (simm != 0)
  1190 + gen_op_addi(simm);
1117 1191 }
1118   - gen_op_stmw(rS(ctx->opcode), SIMM(ctx->opcode));
1119   - SET_RETVAL(0);
  1192 + op_ldstm(stmw, rS(ctx->opcode));
1120 1193 }
1121 1194  
1122 1195 /*** Integer load and store strings ***/
  1196 +#if defined(CONFIG_USER_ONLY)
  1197 +#define op_ldsts(name, start) gen_op_##name##_raw(start)
  1198 +#define op_ldstsx(name, rd, ra, rb) gen_op_##name##_raw(rd, ra, rb)
  1199 +#else
  1200 +#define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
  1201 +#define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
  1202 +static GenOpFunc1 *gen_op_lswi[] = {
  1203 + &gen_op_lswi_user,
  1204 + &gen_op_lswi_kernel,
  1205 +};
  1206 +static GenOpFunc3 *gen_op_lswx[] = {
  1207 + &gen_op_lswx_user,
  1208 + &gen_op_lswx_kernel,
  1209 +};
  1210 +static GenOpFunc1 *gen_op_stsw[] = {
  1211 + &gen_op_stsw_user,
  1212 + &gen_op_stsw_kernel,
  1213 +};
  1214 +#endif
  1215 +
1123 1216 /* lswi */
  1217 +/* PPC32 specification says we must generate an exception if
  1218 + * rA is in the range of registers to be loaded.
  1219 + * In an other hand, IBM says this is valid, but rA won't be loaded.
  1220 + * For now, I'll follow the spec...
  1221 + */
1124 1222 GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
1125 1223 {
1126 1224 int nb = NB(ctx->opcode);
1127 1225 int start = rD(ctx->opcode);
  1226 + int ra = rA(ctx->opcode);
1128 1227 int nr;
1129 1228  
1130 1229 if (nb == 0)
1131 1230 nb = 32;
1132 1231 nr = nb / 4;
1133   - if ((start + nr) > 32) {
1134   - /* handle wrap around r0 */
1135   - if (rA(ctx->opcode) == 0) {
1136   - gen_op_set_T0(0);
1137   - } else {
1138   - gen_op_load_gpr_T0(rA(ctx->opcode));
  1232 + if (((start + nr) > 32 && start <= ra && (start + nr - 32) >= ra) ||
  1233 + ((start + nr) <= 32 && start <= ra && (start + nr) >= ra)) {
  1234 + RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
1139 1235 }
1140   - gen_op_lswi(start, 4 * (32 - start));
1141   - nb -= 4 * (32 - start);
1142   - start = 0;
1143   - }
1144   - if (rA(ctx->opcode) == 0) {
  1236 + if (ra == 0) {
1145 1237 gen_op_set_T0(0);
1146 1238 } else {
1147   - gen_op_load_gpr_T0(rA(ctx->opcode));
  1239 + gen_op_load_gpr_T0(ra);
1148 1240 }
1149   - gen_op_lswi(start, nb);
1150   - SET_RETVAL(0);
  1241 + gen_op_set_T1(nb);
  1242 + op_ldsts(lswi, start);
1151 1243 }
1152 1244  
1153 1245 /* lswx */
1154 1246 GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_INTEGER)
1155 1247 {
1156   - gen_op_load_xer_bc();
1157   - gen_op_load_gpr_T1(rB(ctx->opcode));
1158   - if (rA(ctx->opcode) == 0) {
1159   - gen_op_set_T2(0);
  1248 + int ra = rA(ctx->opcode);
  1249 + int rb = rB(ctx->opcode);
  1250 +
  1251 + if (ra == 0) {
  1252 + gen_op_load_gpr_T0(rb);
  1253 + ra = rb;
1160 1254 } else {
1161   - gen_op_load_gpr_T2(rA(ctx->opcode));
  1255 + gen_op_load_gpr_T0(ra);
  1256 + gen_op_load_gpr_T1(rb);
  1257 + gen_op_add();
1162 1258 }
1163   - gen_op_lswx(rD(ctx->opcode));
1164   - SET_RETVAL(0);
  1259 + gen_op_load_xer_bc();
  1260 + op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
1165 1261 }
1166 1262  
1167 1263 /* stswi */
1168 1264 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_INTEGER)
1169 1265 {
1170   - int nb = NB(ctx->opcode);
1171   - int start = rS(ctx->opcode);
1172   - int nr;
1173   -
1174   - if (nb == 0)
1175   - nb = 32;
1176   - nr = nb / 4;
1177   - if ((start + nr) > 32) {
1178   - /* handle wrap around r0 */
1179   - if (rA(ctx->opcode) == 0) {
1180   - gen_op_set_T0(0);
1181   - } else {
1182   - gen_op_load_gpr_T0(rA(ctx->opcode));
1183   - }
1184   - gen_op_stswi(start, 4 * (32 - start));
1185   - nb -= 4 * (32 - start);
1186   - start = 0;
1187   - }
1188 1266 if (rA(ctx->opcode) == 0) {
1189 1267 gen_op_set_T0(0);
1190 1268 } else {
1191 1269 gen_op_load_gpr_T0(rA(ctx->opcode));
1192 1270 }
1193   - gen_op_stswi(start, nb);
1194   - SET_RETVAL(0);
  1271 + gen_op_set_T1(NB(ctx->opcode));
  1272 + op_ldsts(stsw, rS(ctx->opcode));
1195 1273 }
1196 1274  
1197 1275 /* stswx */
1198 1276 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_INTEGER)
1199 1277 {
1200   - gen_op_load_xer_bc();
1201   - gen_op_load_gpr_T1(rB(ctx->opcode));
1202   - if (rA(ctx->opcode) == 0) {
1203   - gen_op_set_T2(0);
  1278 + int ra = rA(ctx->opcode);
  1279 +
  1280 + if (ra == 0) {
  1281 + gen_op_load_gpr_T0(rB(ctx->opcode));
  1282 + ra = rB(ctx->opcode);
1204 1283 } else {
1205   - gen_op_load_gpr_T2(rA(ctx->opcode));
  1284 + gen_op_load_gpr_T0(ra);
  1285 + gen_op_load_gpr_T1(rB(ctx->opcode));
  1286 + gen_op_add();
1206 1287 }
1207   - gen_op_stswx(rS(ctx->opcode));
1208   - SET_RETVAL(0);
  1288 + gen_op_load_xer_bc();
  1289 + op_ldsts(stsw, rS(ctx->opcode));
1209 1290 }
1210 1291  
1211 1292 /*** Memory synchronisation ***/
1212 1293 /* eieio */
1213 1294 GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM)
1214 1295 {
1215   - /* Do a branch to next instruction */
1216   - gen_op_b((uint32_t)ctx->nip);
1217   - SET_RETVAL(EXCP_BRANCH);
1218 1296 }
1219 1297  
1220 1298 /* isync */
1221 1299 GEN_HANDLER(isync, 0x13, 0x16, 0xFF, 0x03FF0801, PPC_MEM)
1222 1300 {
1223   - /* Do a branch to next instruction */
1224   - gen_op_b((uint32_t)ctx->nip);
1225   - SET_RETVAL(EXCP_BRANCH);
1226 1301 }
1227 1302  
1228 1303 /* lwarx */
1229   -GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_MEM)
  1304 +#if defined(CONFIG_USER_ONLY)
  1305 +#define op_stwcx() gen_op_stwcx_raw()
  1306 +#else
  1307 +#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
  1308 +static GenOpFunc *gen_op_stwcx[] = {
  1309 + &gen_op_stwcx_user,
  1310 + &gen_op_stwcx_kernel,
  1311 +};
  1312 +#endif
  1313 +
  1314 +GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_RES)
1230 1315 {
1231   - reserve = 1;
1232 1316 if (rA(ctx->opcode) == 0) {
1233 1317 gen_op_load_gpr_T0(rB(ctx->opcode));
1234   - gen_op_lwarx_z();
1235 1318 } else {
1236 1319 gen_op_load_gpr_T0(rA(ctx->opcode));
1237 1320 gen_op_load_gpr_T1(rB(ctx->opcode));
1238   - gen_op_lwarx();
  1321 + gen_op_add();
1239 1322 }
  1323 + op_ldst(lwz);
1240 1324 gen_op_store_T1_gpr(rD(ctx->opcode));
1241   - SET_RETVAL(0);
  1325 + gen_op_set_reservation();
1242 1326 }
1243 1327  
1244 1328 /* stwcx. */
1245   -GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_MEM)
  1329 +GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
1246 1330 {
1247   - if (reserve == 0) {
1248   - gen_op_reset_Rc0();
1249   - } else {
1250 1331 if (rA(ctx->opcode) == 0) {
1251 1332 gen_op_load_gpr_T0(rB(ctx->opcode));
1252   - gen_op_load_gpr_T1(rS(ctx->opcode));
1253   - gen_op_stwx_z();
1254 1333 } else {
1255 1334 gen_op_load_gpr_T0(rA(ctx->opcode));
1256 1335 gen_op_load_gpr_T1(rB(ctx->opcode));
1257   - gen_op_load_gpr_T2(rS(ctx->opcode));
1258   - gen_op_stwx();
  1336 + gen_op_add();
1259 1337 }
1260   - }
1261   - SET_RETVAL(0);
  1338 + gen_op_load_gpr_T1(rS(ctx->opcode));
  1339 + op_stwcx();
1262 1340 }
1263 1341  
1264 1342 /* sync */
1265 1343 GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03FF0801, PPC_MEM)
1266 1344 {
1267   - /* Do a branch to next instruction */
1268   - gen_op_b((uint32_t)ctx->nip);
1269   - SET_RETVAL(EXCP_BRANCH);
1270 1345 }
1271 1346  
1272 1347 /*** Floating-point load ***/
1273   -#define GEN_LF(width, opc) \
1274   -GEN_HANDLER(lf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
  1348 +#define GEN_LDF(width, opc) \
  1349 +GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1275 1350 { \
1276 1351 uint32_t simm = SIMM(ctx->opcode); \
1277 1352 if (rA(ctx->opcode) == 0) { \
1278   - gen_op_lf##width##_z_FT0(simm); \
  1353 + gen_op_set_T0(simm); \
1279 1354 } else { \
1280 1355 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1281   - gen_op_lf##width##_FT0(simm); \
  1356 + if (simm != 0) \
  1357 + gen_op_addi(simm); \
1282 1358 } \
1283   - gen_op_store_FT0_fpr(rD(ctx->opcode));\
1284   - SET_RETVAL(0); \
  1359 + op_ldst(l##width); \
  1360 + gen_op_store_FT1_fpr(rD(ctx->opcode)); \
1285 1361 }
1286 1362  
1287   -#define GEN_LFU(width, opc) \
1288   -GEN_HANDLER(lf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
  1363 +#define GEN_LDUF(width, opc) \
  1364 +GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1289 1365 { \
  1366 + uint32_t simm = SIMM(ctx->opcode); \
1290 1367 if (rA(ctx->opcode) == 0 || \
1291   - rA(ctx->opcode) == rD(ctx->opcode)) \
1292   - SET_RETVAL(EXCP_INVAL); \
  1368 + rA(ctx->opcode) == rD(ctx->opcode)) { \
  1369 + RET_INVAL(); \
  1370 + } \
1293 1371 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1294   - gen_op_lf##width##_FT0(SIMM(ctx->opcode)); \
1295   - gen_op_store_FT0_fpr(rD(ctx->opcode));\
  1372 + if (simm != 0) \
  1373 + gen_op_addi(simm); \
  1374 + op_ldst(l##width); \
  1375 + gen_op_store_FT1_fpr(rD(ctx->opcode)); \
1296 1376 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1297   - SET_RETVAL(0); \
1298 1377 }
1299 1378  
1300   -#define GEN_LFUX(width, opc) \
1301   -GEN_HANDLER(lf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
  1379 +#define GEN_LDUXF(width, opc) \
  1380 +GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1302 1381 { \
1303 1382 if (rA(ctx->opcode) == 0 || \
1304   - rA(ctx->opcode) == rD(ctx->opcode)) \
1305   - SET_RETVAL(EXCP_INVAL); \
  1383 + rA(ctx->opcode) == rD(ctx->opcode)) { \
  1384 + RET_INVAL(); \
  1385 + } \
1306 1386 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1307 1387 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1308   - gen_op_lf##width##x_FT0(); \
1309   - gen_op_store_FT0_fpr(rD(ctx->opcode));\
  1388 + gen_op_add(); \
  1389 + op_ldst(l##width); \
  1390 + gen_op_store_FT1_fpr(rD(ctx->opcode)); \
1310 1391 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1311   - SET_RETVAL(0); \
1312 1392 }
1313 1393  
1314   -#define GEN_LFX(width, opc) \
1315   -GEN_HANDLER(lf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
  1394 +#define GEN_LDXF(width, opc2, opc3) \
  1395 +GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1316 1396 { \
1317 1397 if (rA(ctx->opcode) == 0) { \
1318 1398 gen_op_load_gpr_T0(rB(ctx->opcode)); \
1319   - gen_op_lf##width##x_z_FT0(); \
1320 1399 } else { \
1321 1400 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1322 1401 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1323   - gen_op_lf##width##x_FT0(); \
  1402 + gen_op_add(); \
1324 1403 } \
1325   - gen_op_store_FT0_fpr(rD(ctx->opcode));\
1326   - SET_RETVAL(0); \
  1404 + op_ldst(l##width); \
  1405 + gen_op_store_FT1_fpr(rD(ctx->opcode)); \
1327 1406 }
1328 1407  
1329   -#define GEN_LDF(width, opc) \
1330   -GEN_LF(width, opc | 0x20) \
1331   -GEN_LFU(width, opc | 0x21) \
1332   -GEN_LFUX(width, opc | 0x01) \
1333   -GEN_LFX(width, opc | 0x00)
  1408 +#define GEN_LDFS(width, op) \
  1409 +OP_LD_TABLE(width); \
  1410 +GEN_LDF(width, op | 0x20); \
  1411 +GEN_LDUF(width, op | 0x21); \
  1412 +GEN_LDUXF(width, op | 0x01); \
  1413 +GEN_LDXF(width, 0x17, op | 0x00)
1334 1414  
1335 1415 /* lfd lfdu lfdux lfdx */
1336   -GEN_LDF(d, 0x12);
  1416 +GEN_LDFS(fd, 0x12);
1337 1417 /* lfs lfsu lfsux lfsx */
1338   -GEN_LDF(s, 0x10);
  1418 +GEN_LDFS(fs, 0x10);
1339 1419  
1340 1420 /*** Floating-point store ***/
1341 1421 #define GEN_STF(width, opc) \
1342   -GEN_HANDLER(stf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
  1422 +GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1343 1423 { \
1344 1424 uint32_t simm = SIMM(ctx->opcode); \
1345   - gen_op_load_fpr_FT0(rS(ctx->opcode));\
1346 1425 if (rA(ctx->opcode) == 0) { \
1347   - gen_op_stf##width##_z_FT0(simm); \
  1426 + gen_op_set_T0(simm); \
1348 1427 } else { \
1349 1428 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1350   - gen_op_stf##width##_FT0(simm); \
  1429 + if (simm != 0) \
  1430 + gen_op_addi(simm); \
1351 1431 } \
1352   - SET_RETVAL(0); \
  1432 + gen_op_load_fpr_FT1(rS(ctx->opcode)); \
  1433 + op_ldst(st##width); \
1353 1434 }
1354 1435  
1355   -#define GEN_STFU(width, opc) \
1356   -GEN_HANDLER(stf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \
  1436 +#define GEN_STUF(width, opc) \
  1437 +GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) \
1357 1438 { \
1358   - if (rA(ctx->opcode) == 0) \
1359   - SET_RETVAL(EXCP_INVAL); \
  1439 + uint32_t simm = SIMM(ctx->opcode); \
  1440 + if (rA(ctx->opcode) == 0) { \
  1441 + RET_INVAL(); \
  1442 + } \
1360 1443 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1361   - gen_op_load_fpr_FT0(rS(ctx->opcode));\
1362   - gen_op_stf##width##_FT0(SIMM(ctx->opcode)); \
  1444 + if (simm != 0) \
  1445 + gen_op_addi(simm); \
  1446 + gen_op_load_fpr_FT1(rS(ctx->opcode)); \
  1447 + op_ldst(st##width); \
1363 1448 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1364   - SET_RETVAL(0); \
1365 1449 }
1366 1450  
1367   -#define GEN_STFUX(width, opc) \
1368   -GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
  1451 +#define GEN_STUXF(width, opc) \
  1452 +GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_INTEGER) \
1369 1453 { \
1370   - if (rA(ctx->opcode) == 0) \
1371   - SET_RETVAL(EXCP_INVAL); \
  1454 + if (rA(ctx->opcode) == 0) { \
  1455 + RET_INVAL(); \
  1456 + } \
1372 1457 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1373 1458 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1374   - gen_op_load_fpr_FT0(rS(ctx->opcode));\
1375   - gen_op_stf##width##x_FT0(); \
  1459 + gen_op_add(); \
  1460 + gen_op_load_fpr_FT1(rS(ctx->opcode)); \
  1461 + op_ldst(st##width); \
1376 1462 gen_op_store_T0_gpr(rA(ctx->opcode)); \
1377   - SET_RETVAL(0); \
1378 1463 }
1379 1464  
1380   -#define GEN_STFX(width, opc) \
1381   -GEN_HANDLER(stf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \
  1465 +#define GEN_STXF(width, opc2, opc3) \
  1466 +GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_INTEGER) \
1382 1467 { \
1383   - gen_op_load_fpr_FT0(rS(ctx->opcode));\
1384 1468 if (rA(ctx->opcode) == 0) { \
1385 1469 gen_op_load_gpr_T0(rB(ctx->opcode)); \
1386   - gen_op_stf##width##x_z_FT0(); \
1387 1470 } else { \
1388 1471 gen_op_load_gpr_T0(rA(ctx->opcode)); \
1389 1472 gen_op_load_gpr_T1(rB(ctx->opcode)); \
1390   - gen_op_stf##width##x_FT0(); \
  1473 + gen_op_add(); \
1391 1474 } \
1392   - SET_RETVAL(0); \
  1475 + gen_op_load_fpr_FT1(rS(ctx->opcode)); \
  1476 + op_ldst(st##width); \
1393 1477 }
1394 1478  
1395   -#define GEN_STOF(width, opc) \
1396   -GEN_STF(width, opc | 0x20) \
1397   -GEN_STFU(width, opc | 0x21) \
1398   -GEN_STFUX(width, opc | 0x01) \
1399   -GEN_STFX(width, opc | 0x00)
  1479 +#define GEN_STFS(width, op) \
  1480 +OP_ST_TABLE(width); \
  1481 +GEN_STF(width, op | 0x20); \
  1482 +GEN_STUF(width, op | 0x21); \
  1483 +GEN_STUXF(width, op | 0x01); \
  1484 +GEN_STXF(width, 0x17, op | 0x00)
1400 1485  
1401 1486 /* stfd stfdu stfdux stfdx */
1402   -GEN_STOF(d, 0x16);
  1487 +GEN_STFS(fd, 0x16);
1403 1488 /* stfs stfsu stfsux stfsx */
1404   -GEN_STOF(s, 0x14);
  1489 +GEN_STFS(fs, 0x14);
1405 1490  
1406 1491 /* Optional: */
1407 1492 /* stfiwx */
1408 1493 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT)
1409 1494 {
1410   - SET_RETVAL(EXCP_INVAL);
1411   -}
1412   -
1413   -/*** Floating-point move ***/
1414   -/* fabs */
1415   -GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT)
1416   -{
1417   - SET_RETVAL(EXCP_INVAL);
1418   -}
1419   -
1420   -/* fmr */
1421   -GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
1422   -{
1423   - SET_RETVAL(EXCP_INVAL);
1424   -}
1425   -
1426   -/* fnabs */
1427   -GEN_HANDLER(fnabs, 0x3F, 0x08, 0x04, 0x001F0000, PPC_FLOAT)
1428   -{
1429   - SET_RETVAL(EXCP_INVAL);
1430   -}
1431   -
1432   -/* fneg */
1433   -GEN_HANDLER(fneg, 0x3F, 0x08, 0x01, 0x001F0000, PPC_FLOAT)
1434   -{
1435   - SET_RETVAL(EXCP_INVAL);
  1495 + RET_INVAL();
1436 1496 }
1437 1497  
1438 1498 /*** Branch ***/
1439 1499 #define GEN_BCOND(name, opc1, opc2, opc3, prologue, \
1440   - bl_ctr, b_ctr, bl_ctrz, b_ctrz, b, \
  1500 + bl_ctr, b_ctr, bl_ctrz, b_ctrz, b, bl, \
1441 1501 bl_ctr_true, b_ctr_true, bl_ctrz_true, b_ctrz_true, bl_true, b_true, \
1442 1502 bl_ctr_false, b_ctr_false, bl_ctrz_false, b_ctrz_false, bl_false, b_false) \
1443 1503 GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
... ... @@ -1446,7 +1506,11 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1446 1506 uint32_t bo = BO(ctx->opcode); \
1447 1507 uint32_t bi = BI(ctx->opcode); \
1448 1508 uint32_t mask; \
  1509 + gen_op_update_tb(ctx->tb_offset); \
  1510 + gen_op_update_decr(ctx->decr_offset); \
  1511 + gen_op_process_exceptions((uint32_t)ctx->nip - 4); \
1449 1512 prologue; \
  1513 +/* gen_op_set_T1((uint32_t)ctx->tb);*/ \
1450 1514 if ((bo & 0x4) == 0) \
1451 1515 gen_op_dec_ctr(); \
1452 1516 if (bo & 0x10) { \
... ... @@ -1468,13 +1532,15 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1468 1532 break; \
1469 1533 case 4: \
1470 1534 case 6: \
  1535 + if (LK(ctx->opcode)) { \
  1536 + bl; \
  1537 + } else { \
1471 1538 b; \
1472   - if (LK(ctx->opcode)) \
1473   - gen_op_load_lr((uint32_t)ctx->nip); \
  1539 + } \
1474 1540 break; \
1475 1541 default: \
1476 1542 printf("ERROR: %s: unhandled ba case (%d)\n", __func__, bo); \
1477   - SET_RETVAL(EXCP_INVAL); \
  1543 + RET_INVAL(); \
1478 1544 break; \
1479 1545 } \
1480 1546 } else { \
... ... @@ -1506,7 +1572,7 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1506 1572 break; \
1507 1573 default: \
1508 1574 printf("ERROR: %s: unhandled b case (%d)\n", __func__, bo); \
1509   - SET_RETVAL(EXCP_INVAL); \
  1575 + RET_INVAL(); \
1510 1576 break; \
1511 1577 } \
1512 1578 } else { \
... ... @@ -1535,12 +1601,12 @@ GEN_HANDLER(name, opc1, opc2, opc3, 0x00000000, PPC_FLOW) \
1535 1601 break; \
1536 1602 default: \
1537 1603 printf("ERROR: %s: unhandled bn case (%d)\n", __func__, bo); \
1538   - SET_RETVAL(EXCP_INVAL); \
  1604 + RET_INVAL(); \
1539 1605 break; \
1540 1606 } \
1541 1607 } \
1542 1608 } \
1543   - SET_RETVAL(EXCP_BRANCH); \
  1609 + ctx->exception = EXCP_BRANCH; \
1544 1610 }
1545 1611  
1546 1612 /* b ba bl bla */
... ... @@ -1548,14 +1614,20 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1548 1614 {
1549 1615 uint32_t li = s_ext24(LI(ctx->opcode)), target;
1550 1616  
  1617 + gen_op_update_tb(ctx->tb_offset);
  1618 + gen_op_update_decr(ctx->decr_offset);
  1619 + gen_op_process_exceptions((uint32_t)ctx->nip - 4);
1551 1620 if (AA(ctx->opcode) == 0)
1552 1621 target = (uint32_t)ctx->nip + li - 4;
1553 1622 else
1554   - target = s_ext24(LI(ctx->opcode));
  1623 + target = li;
  1624 +// gen_op_set_T1((uint32_t)ctx->tb);
  1625 + if (LK(ctx->opcode)) {
  1626 + gen_op_bl(target, (uint32_t)ctx->nip);
  1627 + } else {
1555 1628 gen_op_b(target);
1556   - if (LK(ctx->opcode))
1557   - gen_op_load_lr((uint32_t)ctx->nip);
1558   - SET_RETVAL(EXCP_BRANCH);
  1629 + }
  1630 + ctx->exception = EXCP_BRANCH;
1559 1631 }
1560 1632  
1561 1633 /* bc bca bcl bcla */
... ... @@ -1573,6 +1645,7 @@ GEN_BCOND(bc, 0x10, 0xFF, 0xFF,
1573 1645 gen_op_bl_ctrz((uint32_t)ctx->nip, target),
1574 1646 gen_op_b_ctrz((uint32_t)ctx->nip, target),
1575 1647 gen_op_b(target),
  1648 + gen_op_bl(target, (uint32_t)ctx->nip),
1576 1649 gen_op_bl_ctr_true((uint32_t)ctx->nip, target, mask),
1577 1650 gen_op_b_ctr_true((uint32_t)ctx->nip, target, mask),
1578 1651 gen_op_bl_ctrz_true((uint32_t)ctx->nip, target, mask),
... ... @@ -1593,6 +1666,7 @@ GEN_BCOND(bcctr, 0x13, 0x10, 0x10, do { } while (0),
1593 1666 gen_op_bctrl_ctrz((uint32_t)ctx->nip),
1594 1667 gen_op_bctr_ctrz((uint32_t)ctx->nip),
1595 1668 gen_op_bctr(),
  1669 + gen_op_bctrl((uint32_t)ctx->nip),
1596 1670 gen_op_bctrl_ctr_true((uint32_t)ctx->nip, mask),
1597 1671 gen_op_bctr_ctr_true((uint32_t)ctx->nip, mask),
1598 1672 gen_op_bctrl_ctrz_true((uint32_t)ctx->nip, mask),
... ... @@ -1613,6 +1687,7 @@ GEN_BCOND(bclr, 0x13, 0x10, 0x00, do { } while (0),
1613 1687 gen_op_blrl_ctrz((uint32_t)ctx->nip),
1614 1688 gen_op_blr_ctrz((uint32_t)ctx->nip),
1615 1689 gen_op_blr(),
  1690 + gen_op_blrl((uint32_t)ctx->nip),
1616 1691 gen_op_blrl_ctr_true((uint32_t)ctx->nip, mask),
1617 1692 gen_op_blr_ctr_true((uint32_t)ctx->nip, mask),
1618 1693 gen_op_blrl_ctrz_true((uint32_t)ctx->nip, mask),
... ... @@ -1639,7 +1714,6 @@ GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
1639 1714 gen_op_setcrfbit(~(1 << (3 - (crbD(ctx->opcode) & 0x03))), \
1640 1715 3 - (crbD(ctx->opcode) & 0x03)); \
1641 1716 gen_op_store_T1_crf(crbD(ctx->opcode) >> 2); \
1642   - SET_RETVAL(0); \
1643 1717 }
1644 1718  
1645 1719 /* crand */
... ... @@ -1663,34 +1737,53 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
1663 1737 {
1664 1738 gen_op_load_crf_T0(crfS(ctx->opcode));
1665 1739 gen_op_store_T0_crf(crfD(ctx->opcode));
1666   - SET_RETVAL(0);
1667 1740 }
1668 1741  
1669 1742 /*** System linkage ***/
1670 1743 /* rfi (supervisor only) */
1671 1744 GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1672 1745 {
1673   - SET_RETVAL(EXCP_INVAL);
  1746 +#if defined(CONFIG_USER_ONLY)
  1747 + RET_PRIVOPC();
  1748 +#else
  1749 + /* Restore CPU state */
  1750 + if (!ctx->supervisor) {
  1751 + RET_PRIVOPC();
  1752 + }
  1753 + gen_op_rfi();
  1754 + ctx->exception = EXCP_RFI;
  1755 +#endif
1674 1756 }
1675 1757  
1676 1758 /* sc */
1677 1759 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
1678 1760 {
1679   - gen_op_b((uint32_t)ctx->nip);
1680   - SET_RETVAL(EXCP_SYSCALL);
  1761 +#if defined(CONFIG_USER_ONLY)
  1762 + gen_op_queue_exception(EXCP_SYSCALL_USER);
  1763 +#else
  1764 + gen_op_queue_exception(EXCP_SYSCALL);
  1765 +#endif
  1766 + ctx->exception = EXCP_SYSCALL;
1681 1767 }
1682 1768  
1683 1769 /*** Trap ***/
1684 1770 /* tw */
1685 1771 GEN_HANDLER(tw, 0x1F, 0x04, 0xFF, 0x00000001, PPC_FLOW)
1686 1772 {
1687   - SET_RETVAL(EXCP_INVAL);
  1773 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1774 + gen_op_load_gpr_T1(rB(ctx->opcode));
  1775 + gen_op_tw(TO(ctx->opcode));
1688 1776 }
1689 1777  
1690 1778 /* twi */
1691 1779 GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
1692 1780 {
1693   - SET_RETVAL(EXCP_INVAL);
  1781 + gen_op_load_gpr_T0(rA(ctx->opcode));
  1782 +#if 0
  1783 + printf("%s: param=0x%04x T0=0x%04x\n", __func__,
  1784 + SIMM(ctx->opcode), TO(ctx->opcode));
  1785 +#endif
  1786 + gen_op_twi(SIMM(ctx->opcode), TO(ctx->opcode));
1694 1787 }
1695 1788  
1696 1789 /*** Processor control ***/
... ... @@ -1698,6 +1791,21 @@ static inline int check_spr_access (int spr, int rw, int supervisor)
1698 1791 {
1699 1792 uint32_t rights = spr_access[spr >> 1] >> (4 * (spr & 1));
1700 1793  
  1794 +#if 0
  1795 + if (spr != LR && spr != CTR) {
  1796 + if (loglevel > 0) {
  1797 + fprintf(logfile, "%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
  1798 + SPR_ENCODE(spr), supervisor, rw, rights,
  1799 + (rights >> ((2 * supervisor) + rw)) & 1);
  1800 + } else {
  1801 + printf("%s reg=%d s=%d rw=%d r=0x%02x 0x%02x\n", __func__,
  1802 + SPR_ENCODE(spr), supervisor, rw, rights,
  1803 + (rights >> ((2 * supervisor) + rw)) & 1);
  1804 + }
  1805 + }
  1806 +#endif
  1807 + if (rights == 0)
  1808 + return -1;
1701 1809 rights = rights >> (2 * supervisor);
1702 1810 rights = rights >> rw;
1703 1811  
... ... @@ -1710,7 +1818,6 @@ GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
1710 1818 gen_op_load_xer_cr();
1711 1819 gen_op_store_T0_crf(crfD(ctx->opcode));
1712 1820 gen_op_clear_xer_cr();
1713   - SET_RETVAL(0);
1714 1821 }
1715 1822  
1716 1823 /* mfcr */
... ... @@ -1718,17 +1825,20 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x001FF801, PPC_MISC)
1718 1825 {
1719 1826 gen_op_load_cr();
1720 1827 gen_op_store_T0_gpr(rD(ctx->opcode));
1721   - SET_RETVAL(0);
1722 1828 }
1723 1829  
1724 1830 /* mfmsr */
1725 1831 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
1726 1832 {
1727   - if (!ctx->supervisor)
1728   - SET_RETVAL(EXCP_PRIV);
  1833 +#if defined(CONFIG_USER_ONLY)
  1834 + RET_PRIVREG();
  1835 +#else
  1836 + if (!ctx->supervisor) {
  1837 + RET_PRIVREG();
  1838 + }
1729 1839 gen_op_load_msr();
1730 1840 gen_op_store_T0_gpr(rD(ctx->opcode));
1731   - SET_RETVAL(0);
  1841 +#endif
1732 1842 }
1733 1843  
1734 1844 /* mfspr */
... ... @@ -1736,31 +1846,150 @@ GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
1736 1846 {
1737 1847 uint32_t sprn = SPR(ctx->opcode);
1738 1848  
1739   - if (check_spr_access(sprn, 0, ctx->supervisor) == 0)
1740   - SET_RETVAL(EXCP_PRIV);
1741   - /* XXX: make this more generic */
1742   - switch (sprn) {
1743   - case SPR_ENCODE(1):
1744   - if (loglevel > 0) {
1745   - fprintf(logfile, "LOAD XER at %p\n", ctx->nip - 1);
  1849 +#if defined(CONFIG_USER_ONLY)
  1850 + switch (check_spr_access(sprn, 0, 0))
  1851 +#else
  1852 + switch (check_spr_access(sprn, 0, ctx->supervisor))
  1853 +#endif
  1854 + {
  1855 + case -1:
  1856 + RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
  1857 + break;
  1858 + case 0:
  1859 + RET_PRIVREG();
  1860 + break;
  1861 + default:
  1862 + break;
1746 1863 }
  1864 + switch (sprn) {
  1865 + case XER:
1747 1866 gen_op_load_xer();
1748 1867 break;
1749   - case SPR_ENCODE(268):
1750   - /* We need to update the time base before reading it */
  1868 + case LR:
  1869 + gen_op_load_lr();
  1870 + break;
  1871 + case CTR:
  1872 + gen_op_load_ctr();
  1873 + break;
  1874 + case IBAT0U:
  1875 + gen_op_load_ibat(0, 0);
  1876 + break;
  1877 + case IBAT1U:
  1878 + gen_op_load_ibat(0, 1);
  1879 + break;
  1880 + case IBAT2U:
  1881 + gen_op_load_ibat(0, 2);
  1882 + break;
  1883 + case IBAT3U:
  1884 + gen_op_load_ibat(0, 3);
  1885 + break;
  1886 + case IBAT4U:
  1887 + gen_op_load_ibat(0, 4);
  1888 + break;
  1889 + case IBAT5U:
  1890 + gen_op_load_ibat(0, 5);
  1891 + break;
  1892 + case IBAT6U:
  1893 + gen_op_load_ibat(0, 6);
  1894 + break;
  1895 + case IBAT7U:
  1896 + gen_op_load_ibat(0, 7);
  1897 + break;
  1898 + case IBAT0L:
  1899 + gen_op_load_ibat(1, 0);
  1900 + break;
  1901 + case IBAT1L:
  1902 + gen_op_load_ibat(1, 1);
  1903 + break;
  1904 + case IBAT2L:
  1905 + gen_op_load_ibat(1, 2);
  1906 + break;
  1907 + case IBAT3L:
  1908 + gen_op_load_ibat(1, 3);
  1909 + break;
  1910 + case IBAT4L:
  1911 + gen_op_load_ibat(1, 4);
  1912 + break;
  1913 + case IBAT5L:
  1914 + gen_op_load_ibat(1, 5);
  1915 + break;
  1916 + case IBAT6L:
  1917 + gen_op_load_ibat(1, 6);
  1918 + break;
  1919 + case IBAT7L:
  1920 + gen_op_load_ibat(1, 7);
  1921 + break;
  1922 + case DBAT0U:
  1923 + gen_op_load_dbat(0, 0);
  1924 + break;
  1925 + case DBAT1U:
  1926 + gen_op_load_dbat(0, 1);
  1927 + break;
  1928 + case DBAT2U:
  1929 + gen_op_load_dbat(0, 2);
  1930 + break;
  1931 + case DBAT3U:
  1932 + gen_op_load_dbat(0, 3);
  1933 + break;
  1934 + case DBAT4U:
  1935 + gen_op_load_dbat(0, 4);
  1936 + break;
  1937 + case DBAT5U:
  1938 + gen_op_load_dbat(0, 5);
  1939 + break;
  1940 + case DBAT6U:
  1941 + gen_op_load_dbat(0, 6);
  1942 + break;
  1943 + case DBAT7U:
  1944 + gen_op_load_dbat(0, 7);
  1945 + break;
  1946 + case DBAT0L:
  1947 + gen_op_load_dbat(1, 0);
  1948 + break;
  1949 + case DBAT1L:
  1950 + gen_op_load_dbat(1, 1);
  1951 + break;
  1952 + case DBAT2L:
  1953 + gen_op_load_dbat(1, 2);
  1954 + break;
  1955 + case DBAT3L:
  1956 + gen_op_load_dbat(1, 3);
  1957 + break;
  1958 + case DBAT4L:
  1959 + gen_op_load_dbat(1, 4);
  1960 + break;
  1961 + case DBAT5L:
  1962 + gen_op_load_dbat(1, 5);
  1963 + break;
  1964 + case DBAT6L:
  1965 + gen_op_load_dbat(1, 6);
  1966 + break;
  1967 + case DBAT7L:
  1968 + gen_op_load_dbat(1, 7);
  1969 + break;
  1970 + case SDR1:
  1971 + gen_op_load_sdr1();
  1972 + break;
  1973 + case V_TBL:
1751 1974 gen_op_update_tb(ctx->tb_offset);
1752 1975 ctx->tb_offset = 0;
  1976 + /* TBL is still in T0 */
1753 1977 break;
1754   - case SPR_ENCODE(269):
  1978 + case V_TBU:
1755 1979 gen_op_update_tb(ctx->tb_offset);
1756 1980 ctx->tb_offset = 0;
  1981 + gen_op_load_tb(1);
  1982 + break;
  1983 + case DECR:
  1984 + gen_op_update_decr(ctx->decr_offset);
  1985 + ctx->decr_offset = 0;
  1986 + /* decr is still in T0 */
1757 1987 break;
1758 1988 default:
1759 1989 gen_op_load_spr(sprn);
1760 1990 break;
1761 1991 }
1762   - gen_op_store_T0_gpr(rD(ctx->opcode)); //
1763   - SET_RETVAL(0);
  1992 + gen_op_store_T0_gpr(rD(ctx->opcode));
1764 1993 }
1765 1994  
1766 1995 /* mftb */
... ... @@ -1768,23 +1997,22 @@ GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MISC)
1768 1997 {
1769 1998 uint32_t sprn = SPR(ctx->opcode);
1770 1999  
1771   - if (check_spr_access(sprn, 0, ctx->supervisor) == 0)
1772   - SET_RETVAL(EXCP_PRIV);
1773   - switch (sprn) {
1774   - case SPR_ENCODE(268):
1775 2000 /* We need to update the time base before reading it */
  2001 + switch (sprn) {
  2002 + case V_TBL:
1776 2003 gen_op_update_tb(ctx->tb_offset);
1777   - ctx->tb_offset = 0;
  2004 + /* TBL is still in T0 */
1778 2005 break;
1779   - case SPR_ENCODE(269):
  2006 + case V_TBU:
1780 2007 gen_op_update_tb(ctx->tb_offset);
1781   - ctx->tb_offset = 0;
  2008 + gen_op_load_tb(1);
1782 2009 break;
1783 2010 default:
1784   - SET_RETVAL(EXCP_INVAL);
  2011 + RET_INVAL();
1785 2012 break;
1786 2013 }
1787   - SET_RETVAL(0);
  2014 + ctx->tb_offset = 0;
  2015 + gen_op_store_T0_gpr(rD(ctx->opcode));
1788 2016 }
1789 2017  
1790 2018 /* mtcrf */
... ... @@ -1792,18 +2020,22 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00100801, PPC_MISC)
1792 2020 {
1793 2021 gen_op_load_gpr_T0(rS(ctx->opcode));
1794 2022 gen_op_store_cr(CRM(ctx->opcode));
1795   - SET_RETVAL(0);
1796 2023 }
1797 2024  
1798 2025 /* mtmsr */
1799 2026 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
1800 2027 {
1801   - if (!ctx->supervisor)
1802   - SET_RETVAL(EXCP_PRIV);
  2028 +#if defined(CONFIG_USER_ONLY)
  2029 + RET_PRIVREG();
  2030 +#else
  2031 + if (!ctx->supervisor) {
  2032 + RET_PRIVREG();
  2033 + }
1803 2034 gen_op_load_gpr_T0(rS(ctx->opcode));
1804 2035 gen_op_store_msr();
1805 2036 /* Must stop the translation as machine state (may have) changed */
1806   - SET_RETVAL(EXCP_MTMSR);
  2037 + ctx->exception = EXCP_MTMSR;
  2038 +#endif
1807 2039 }
1808 2040  
1809 2041 /* mtspr */
... ... @@ -1811,84 +2043,265 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
1811 2043 {
1812 2044 uint32_t sprn = SPR(ctx->opcode);
1813 2045  
1814   - if (check_spr_access(sprn, 1, ctx->supervisor) == 0)
1815   - SET_RETVAL(EXCP_PRIV);
  2046 +#if 0
  2047 + if (loglevel > 0) {
  2048 + fprintf(logfile, "MTSPR %d src=%d (%d)\n", SPR_ENCODE(sprn),
  2049 + rS(ctx->opcode), sprn);
  2050 + }
  2051 +#endif
  2052 +#if defined(CONFIG_USER_ONLY)
  2053 + switch (check_spr_access(sprn, 1, 0))
  2054 +#else
  2055 + switch (check_spr_access(sprn, 1, ctx->supervisor))
  2056 +#endif
  2057 + {
  2058 + case -1:
  2059 + RET_EXCP(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
  2060 + break;
  2061 + case 0:
  2062 + RET_PRIVREG();
  2063 + break;
  2064 + default:
  2065 + break;
  2066 + }
1816 2067 gen_op_load_gpr_T0(rS(ctx->opcode));
1817   - if (sprn == SPR_ENCODE(1)) {
  2068 + switch (sprn) {
  2069 + case XER:
1818 2070 gen_op_store_xer();
1819   - } else {
  2071 + break;
  2072 + case LR:
  2073 + gen_op_andi_(~0x03);
  2074 + gen_op_store_lr();
  2075 + break;
  2076 + case CTR:
  2077 + gen_op_store_ctr();
  2078 + break;
  2079 + case IBAT0U:
  2080 + gen_op_store_ibat(0, 0);
  2081 + gen_op_tlbia();
  2082 + break;
  2083 + case IBAT1U:
  2084 + gen_op_store_ibat(0, 1);
  2085 + gen_op_tlbia();
  2086 + break;
  2087 + case IBAT2U:
  2088 + gen_op_store_ibat(0, 2);
  2089 + gen_op_tlbia();
  2090 + break;
  2091 + case IBAT3U:
  2092 + gen_op_store_ibat(0, 3);
  2093 + gen_op_tlbia();
  2094 + break;
  2095 + case IBAT4U:
  2096 + gen_op_store_ibat(0, 4);
  2097 + gen_op_tlbia();
  2098 + break;
  2099 + case IBAT5U:
  2100 + gen_op_store_ibat(0, 5);
  2101 + gen_op_tlbia();
  2102 + break;
  2103 + case IBAT6U:
  2104 + gen_op_store_ibat(0, 6);
  2105 + gen_op_tlbia();
  2106 + break;
  2107 + case IBAT7U:
  2108 + gen_op_store_ibat(0, 7);
  2109 + gen_op_tlbia();
  2110 + break;
  2111 + case IBAT0L:
  2112 + gen_op_store_ibat(1, 0);
  2113 + gen_op_tlbia();
  2114 + break;
  2115 + case IBAT1L:
  2116 + gen_op_store_ibat(1, 1);
  2117 + gen_op_tlbia();
  2118 + break;
  2119 + case IBAT2L:
  2120 + gen_op_store_ibat(1, 2);
  2121 + gen_op_tlbia();
  2122 + break;
  2123 + case IBAT3L:
  2124 + gen_op_store_ibat(1, 3);
  2125 + gen_op_tlbia();
  2126 + break;
  2127 + case IBAT4L:
  2128 + gen_op_store_ibat(1, 4);
  2129 + gen_op_tlbia();
  2130 + break;
  2131 + case IBAT5L:
  2132 + gen_op_store_ibat(1, 5);
  2133 + gen_op_tlbia();
  2134 + break;
  2135 + case IBAT6L:
  2136 + gen_op_store_ibat(1, 6);
  2137 + gen_op_tlbia();
  2138 + break;
  2139 + case IBAT7L:
  2140 + gen_op_store_ibat(1, 7);
  2141 + gen_op_tlbia();
  2142 + break;
  2143 + case DBAT0U:
  2144 + gen_op_store_dbat(0, 0);
  2145 + gen_op_tlbia();
  2146 + break;
  2147 + case DBAT1U:
  2148 + gen_op_store_dbat(0, 1);
  2149 + gen_op_tlbia();
  2150 + break;
  2151 + case DBAT2U:
  2152 + gen_op_store_dbat(0, 2);
  2153 + gen_op_tlbia();
  2154 + break;
  2155 + case DBAT3U:
  2156 + gen_op_store_dbat(0, 3);
  2157 + gen_op_tlbia();
  2158 + break;
  2159 + case DBAT4U:
  2160 + gen_op_store_dbat(0, 4);
  2161 + gen_op_tlbia();
  2162 + break;
  2163 + case DBAT5U:
  2164 + gen_op_store_dbat(0, 5);
  2165 + gen_op_tlbia();
  2166 + break;
  2167 + case DBAT6U:
  2168 + gen_op_store_dbat(0, 6);
  2169 + gen_op_tlbia();
  2170 + break;
  2171 + case DBAT7U:
  2172 + gen_op_store_dbat(0, 7);
  2173 + gen_op_tlbia();
  2174 + break;
  2175 + case DBAT0L:
  2176 + gen_op_store_dbat(1, 0);
  2177 + gen_op_tlbia();
  2178 + break;
  2179 + case DBAT1L:
  2180 + gen_op_store_dbat(1, 1);
  2181 + gen_op_tlbia();
  2182 + break;
  2183 + case DBAT2L:
  2184 + gen_op_store_dbat(1, 2);
  2185 + gen_op_tlbia();
  2186 + break;
  2187 + case DBAT3L:
  2188 + gen_op_store_dbat(1, 3);
  2189 + gen_op_tlbia();
  2190 + break;
  2191 + case DBAT4L:
  2192 + gen_op_store_dbat(1, 4);
  2193 + gen_op_tlbia();
  2194 + break;
  2195 + case DBAT5L:
  2196 + gen_op_store_dbat(1, 5);
  2197 + gen_op_tlbia();
  2198 + break;
  2199 + case DBAT6L:
  2200 + gen_op_store_dbat(1, 6);
  2201 + gen_op_tlbia();
  2202 + break;
  2203 + case DBAT7L:
  2204 + gen_op_store_dbat(1, 7);
  2205 + gen_op_tlbia();
  2206 + break;
  2207 + case SDR1:
  2208 + gen_op_store_sdr1();
  2209 + gen_op_tlbia();
  2210 + break;
  2211 + case O_TBL:
  2212 + gen_op_store_tb(0);
  2213 + ctx->tb_offset = 0;
  2214 + break;
  2215 + case O_TBU:
  2216 + gen_op_store_tb(1);
  2217 + ctx->tb_offset = 0;
  2218 + break;
  2219 + case DECR:
  2220 + gen_op_store_decr();
  2221 + ctx->decr_offset = 0;
  2222 + break;
  2223 + default:
1820 2224 gen_op_store_spr(sprn);
  2225 + break;
1821 2226 }
1822   - SET_RETVAL(0);
1823 2227 }
1824 2228  
1825 2229 /*** Cache management ***/
1826 2230 /* For now, all those will be implemented as nop:
1827 2231 * this is valid, regarding the PowerPC specs...
  2232 + * We just have to flush tb while invalidating instruction cache lines...
1828 2233 */
1829 2234 /* dcbf */
1830   -GEN_HANDLER(dcbf, 0x1F, 0x16, 0x17, 0x03E00001, PPC_MEM)
  2235 +GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
1831 2236 {
1832   - SET_RETVAL(0);
1833 2237 }
1834 2238  
1835 2239 /* dcbi (Supervisor only) */
1836   -GEN_HANDLER(dcbi, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_MEM)
  2240 +GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
1837 2241 {
1838   - SET_RETVAL(0);
  2242 +#if !defined(CONFIG_USER_ONLY)
  2243 + if (!ctx->supervisor)
  2244 +#endif
  2245 + {
  2246 + RET_PRIVOPC();
  2247 + }
1839 2248 }
1840 2249  
1841 2250 /* dcdst */
1842   -GEN_HANDLER(dcbst, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_MEM)
  2251 +GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
1843 2252 {
1844   - SET_RETVAL(0);
1845 2253 }
1846 2254  
1847 2255 /* dcbt */
1848   -GEN_HANDLER(dcbt, 0x1F, 0x16, 0x01, 0x03E00001, PPC_MEM)
  2256 +GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x03E00001, PPC_CACHE)
1849 2257 {
1850   - SET_RETVAL(0);
1851 2258 }
1852 2259  
1853 2260 /* dcbtst */
1854   -GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x02, 0x03E00001, PPC_MEM)
  2261 +GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE)
1855 2262 {
1856   - SET_RETVAL(0);
1857 2263 }
1858 2264  
1859 2265 /* dcbz */
1860   -GEN_HANDLER(dcbz, 0x1F, 0x16, 0x08, 0x03E00001, PPC_MEM)
  2266 +#if defined(CONFIG_USER_ONLY)
  2267 +#define op_dcbz() gen_op_dcbz_raw()
  2268 +#else
  2269 +#define op_dcbz() (*gen_op_dcbz[ctx->mem_idx])()
  2270 +static GenOpFunc *gen_op_dcbz[] = {
  2271 + &gen_op_dcbz_user,
  2272 + &gen_op_dcbz_kernel,
  2273 +};
  2274 +#endif
  2275 +
  2276 +GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE)
1861 2277 {
1862 2278 if (rA(ctx->opcode) == 0) {
1863 2279 gen_op_load_gpr_T0(rB(ctx->opcode));
1864   - gen_op_dcbz_z();
1865 2280 } else {
1866 2281 gen_op_load_gpr_T0(rA(ctx->opcode));
1867 2282 gen_op_load_gpr_T1(rB(ctx->opcode));
1868   - gen_op_dcbz();
  2283 + gen_op_add();
1869 2284 }
1870   - SET_RETVAL(0);
  2285 + op_dcbz();
1871 2286 }
1872 2287  
1873 2288 /* icbi */
1874   -GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_MEM)
  2289 +GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
1875 2290 {
1876 2291 if (rA(ctx->opcode) == 0) {
1877 2292 gen_op_load_gpr_T0(rB(ctx->opcode));
1878   - gen_op_icbi_z();
1879 2293 } else {
1880 2294 gen_op_load_gpr_T0(rA(ctx->opcode));
1881 2295 gen_op_load_gpr_T1(rB(ctx->opcode));
1882   - gen_op_icbi();
  2296 + gen_op_add();
1883 2297 }
1884   - SET_RETVAL(0);
  2298 + gen_op_icbi();
1885 2299 }
1886 2300  
1887 2301 /* Optional: */
1888 2302 /* dcba */
1889   -GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_MEM)
  2303 +GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_CACHE_OPT)
1890 2304 {
1891   - SET_RETVAL(0);
1892 2305 }
1893 2306  
1894 2307 /*** Segment register manipulation ***/
... ... @@ -1896,70 +2309,163 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x07, 0x03E00001, PPC_MEM)
1896 2309 /* mfsr */
1897 2310 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
1898 2311 {
1899   - SET_RETVAL(EXCP_INVAL);
  2312 +#if defined(CONFIG_USER_ONLY)
  2313 + RET_PRIVREG();
  2314 +#else
  2315 + if (!ctx->supervisor) {
  2316 + RET_PRIVREG();
  2317 + }
  2318 + gen_op_load_sr(SR(ctx->opcode));
  2319 + gen_op_store_T0_gpr(rD(ctx->opcode));
  2320 +#endif
1900 2321 }
1901 2322  
1902 2323 /* mfsrin */
1903   -GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x0010F001, PPC_SEGMENT)
  2324 +GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
1904 2325 {
1905   - SET_RETVAL(EXCP_INVAL);
  2326 +#if defined(CONFIG_USER_ONLY)
  2327 + RET_PRIVREG();
  2328 +#else
  2329 + if (!ctx->supervisor) {
  2330 + RET_PRIVREG();
  2331 + }
  2332 + gen_op_load_gpr_T1(rB(ctx->opcode));
  2333 + gen_op_load_srin();
  2334 + gen_op_store_T0_gpr(rD(ctx->opcode));
  2335 +#endif
1906 2336 }
1907 2337  
1908 2338 /* mtsr */
1909 2339 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x02, 0x0010F801, PPC_SEGMENT)
1910 2340 {
1911   - SET_RETVAL(EXCP_INVAL);
  2341 +#if defined(CONFIG_USER_ONLY)
  2342 + RET_PRIVREG();
  2343 +#else
  2344 + if (!ctx->supervisor) {
  2345 + RET_PRIVREG();
  2346 + }
  2347 + gen_op_load_gpr_T0(rS(ctx->opcode));
  2348 + gen_op_store_sr(SR(ctx->opcode));
  2349 + gen_op_tlbia();
  2350 +#endif
1912 2351 }
1913 2352  
1914 2353 /* mtsrin */
1915   -GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x0010F001, PPC_SEGMENT)
  2354 +GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
1916 2355 {
1917   - SET_RETVAL(EXCP_INVAL);
  2356 +#if defined(CONFIG_USER_ONLY)
  2357 + RET_PRIVREG();
  2358 +#else
  2359 + if (!ctx->supervisor) {
  2360 + RET_PRIVREG();
  2361 + }
  2362 + gen_op_load_gpr_T0(rS(ctx->opcode));
  2363 + gen_op_load_gpr_T1(rB(ctx->opcode));
  2364 + gen_op_store_srin();
  2365 + gen_op_tlbia();
  2366 +#endif
1918 2367 }
1919 2368  
1920 2369 /*** Lookaside buffer management ***/
1921 2370 /* Optional & supervisor only: */
1922 2371 /* tlbia */
1923   -GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM)
  2372 +GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_OPT)
1924 2373 {
1925   - SET_RETVAL(EXCP_INVAL);
  2374 +#if defined(CONFIG_USER_ONLY)
  2375 + RET_PRIVOPC();
  2376 +#else
  2377 + if (!ctx->supervisor) {
  2378 + RET_PRIVOPC();
  2379 + }
  2380 + gen_op_tlbia();
  2381 +#endif
1926 2382 }
1927 2383  
1928 2384 /* tlbie */
1929   -GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF8001, PPC_MEM)
  2385 +GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM)
1930 2386 {
1931   - SET_RETVAL(EXCP_INVAL);
  2387 +#if defined(CONFIG_USER_ONLY)
  2388 + RET_PRIVOPC();
  2389 +#else
  2390 + if (!ctx->supervisor) {
  2391 + RET_PRIVOPC();
  2392 + }
  2393 + gen_op_load_gpr_T0(rB(ctx->opcode));
  2394 + gen_op_tlbie();
  2395 +#endif
1932 2396 }
1933 2397  
1934 2398 /* tlbsync */
1935 2399 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFFC01, PPC_MEM)
1936 2400 {
1937   - SET_RETVAL(EXCP_INVAL);
  2401 +#if defined(CONFIG_USER_ONLY)
  2402 + RET_PRIVOPC();
  2403 +#else
  2404 + if (!ctx->supervisor) {
  2405 + RET_PRIVOPC();
  2406 + }
  2407 + /* This has no effect: it should ensure that all previous
  2408 + * tlbie have completed
  2409 + */
  2410 +#endif
1938 2411 }
1939 2412  
1940 2413 /*** External control ***/
1941 2414 /* Optional: */
1942 2415 /* eciwx */
  2416 +#if defined(CONFIG_USER_ONLY)
  2417 +#define op_eciwx() gen_op_eciwx_raw()
  2418 +#define op_ecowx() gen_op_ecowx_raw()
  2419 +#else
  2420 +#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
  2421 +#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
  2422 +static GenOpFunc *gen_op_eciwx[] = {
  2423 + &gen_op_eciwx_user,
  2424 + &gen_op_eciwx_kernel,
  2425 +};
  2426 +static GenOpFunc *gen_op_ecowx[] = {
  2427 + &gen_op_ecowx_user,
  2428 + &gen_op_ecowx_kernel,
  2429 +};
  2430 +#endif
  2431 +
1943 2432 GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
1944 2433 {
1945   - SET_RETVAL(EXCP_INVAL);
  2434 + /* Should check EAR[E] & alignment ! */
  2435 + if (rA(ctx->opcode) == 0) {
  2436 + gen_op_load_gpr_T0(rB(ctx->opcode));
  2437 + } else {
  2438 + gen_op_load_gpr_T0(rA(ctx->opcode));
  2439 + gen_op_load_gpr_T1(rB(ctx->opcode));
  2440 + gen_op_add();
  2441 + }
  2442 + op_eciwx();
  2443 + gen_op_store_T0_gpr(rD(ctx->opcode));
1946 2444 }
1947 2445  
1948 2446 /* ecowx */
1949 2447 GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
1950 2448 {
1951   - SET_RETVAL(EXCP_INVAL);
  2449 + /* Should check EAR[E] & alignment ! */
  2450 + if (rA(ctx->opcode) == 0) {
  2451 + gen_op_load_gpr_T0(rB(ctx->opcode));
  2452 + } else {
  2453 + gen_op_load_gpr_T0(rA(ctx->opcode));
  2454 + gen_op_load_gpr_T1(rB(ctx->opcode));
  2455 + gen_op_add();
  2456 + }
  2457 + gen_op_load_gpr_T2(rS(ctx->opcode));
  2458 + op_ecowx();
1952 2459 }
1953 2460  
1954 2461 /* End opcode list */
1955 2462 GEN_OPCODE_MARK(end);
1956 2463  
1957 2464 /*****************************************************************************/
1958   -
  2465 +#include <stdlib.h>
1959 2466 #include <string.h>
1960   -extern FILE *stderr;
1961   -void free (void *p);
1962   -int fflush (FILE *f);
  2467 +
  2468 +int fflush (FILE *stream);
1963 2469  
1964 2470 /* Main ppc opcodes table:
1965 2471 * at init, all opcodes are invalids
... ... @@ -1982,6 +2488,7 @@ static inline opc_handler_t **ind_table(void *handler)
1982 2488 return (opc_handler_t **)((unsigned long)handler & ~3);
1983 2489 }
1984 2490  
  2491 +/* Instruction table creation */
1985 2492 /* Opcodes tables creation */
1986 2493 static void fill_new_table (opc_handler_t **table, int len)
1987 2494 {
... ... @@ -2014,10 +2521,11 @@ static int insert_in_table (opc_handler_t **table, unsigned char idx,
2014 2521 return 0;
2015 2522 }
2016 2523  
2017   -static int register_direct_insn (unsigned char idx, opc_handler_t *handler)
  2524 +static int register_direct_insn (opc_handler_t **ppc_opcodes,
  2525 + unsigned char idx, opc_handler_t *handler)
2018 2526 {
2019 2527 if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
2020   - fprintf(stderr, "*** ERROR: opcode %02x already assigned in main "
  2528 + printf("*** ERROR: opcode %02x already assigned in main "
2021 2529 "opcode table\n", idx);
2022 2530 return -1;
2023 2531 }
... ... @@ -2031,20 +2539,20 @@ static int register_ind_in_table (opc_handler_t **table,
2031 2539 {
2032 2540 if (table[idx1] == &invalid_handler) {
2033 2541 if (create_new_table(table, idx1) < 0) {
2034   - fprintf(stderr, "*** ERROR: unable to create indirect table "
  2542 + printf("*** ERROR: unable to create indirect table "
2035 2543 "idx=%02x\n", idx1);
2036 2544 return -1;
2037 2545 }
2038 2546 } else {
2039 2547 if (!is_indirect_opcode(table[idx1])) {
2040   - fprintf(stderr, "*** ERROR: idx %02x already assigned to a direct "
  2548 + printf("*** ERROR: idx %02x already assigned to a direct "
2041 2549 "opcode\n", idx1);
2042 2550 return -1;
2043 2551 }
2044 2552 }
2045 2553 if (handler != NULL &&
2046 2554 insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
2047   - fprintf(stderr, "*** ERROR: opcode %02x already assigned in "
  2555 + printf("*** ERROR: opcode %02x already assigned in "
2048 2556 "opcode table %02x\n", idx2, idx1);
2049 2557 return -1;
2050 2558 }
... ... @@ -2052,7 +2560,8 @@ static int register_ind_in_table (opc_handler_t **table,
2052 2560 return 0;
2053 2561 }
2054 2562  
2055   -static int register_ind_insn (unsigned char idx1, unsigned char idx2,
  2563 +static int register_ind_insn (opc_handler_t **ppc_opcodes,
  2564 + unsigned char idx1, unsigned char idx2,
2056 2565 opc_handler_t *handler)
2057 2566 {
2058 2567 int ret;
... ... @@ -2062,17 +2571,18 @@ static int register_ind_insn (unsigned char idx1, unsigned char idx2,
2062 2571 return ret;
2063 2572 }
2064 2573  
2065   -static int register_dblind_insn (unsigned char idx1, unsigned char idx2,
  2574 +static int register_dblind_insn (opc_handler_t **ppc_opcodes,
  2575 + unsigned char idx1, unsigned char idx2,
2066 2576 unsigned char idx3, opc_handler_t *handler)
2067 2577 {
2068 2578 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
2069   - fprintf(stderr, "*** ERROR: unable to join indirect table idx "
  2579 + printf("*** ERROR: unable to join indirect table idx "
2070 2580 "[%02x-%02x]\n", idx1, idx2);
2071 2581 return -1;
2072 2582 }
2073 2583 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
2074 2584 handler) < 0) {
2075   - fprintf(stderr, "*** ERROR: unable to insert opcode "
  2585 + printf("*** ERROR: unable to insert opcode "
2076 2586 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
2077 2587 return -1;
2078 2588 }
... ... @@ -2080,19 +2590,20 @@ static int register_dblind_insn (unsigned char idx1, unsigned char idx2,
2080 2590 return 0;
2081 2591 }
2082 2592  
2083   -static int register_insn (opcode_t *insn)
  2593 +static int register_insn (opc_handler_t **ppc_opcodes, opcode_t *insn)
2084 2594 {
2085 2595 if (insn->opc2 != 0xFF) {
2086 2596 if (insn->opc3 != 0xFF) {
2087   - if (register_dblind_insn(insn->opc1, insn->opc2, insn->opc3,
2088   - &insn->handler) < 0)
  2597 + if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
  2598 + insn->opc3, &insn->handler) < 0)
2089 2599 return -1;
2090 2600 } else {
2091   - if (register_ind_insn(insn->opc1, insn->opc2, &insn->handler) < 0)
  2601 + if (register_ind_insn(ppc_opcodes, insn->opc1,
  2602 + insn->opc2, &insn->handler) < 0)
2092 2603 return -1;
2093 2604 }
2094 2605 } else {
2095   - if (register_direct_insn(insn->opc1, &insn->handler) < 0)
  2606 + if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0)
2096 2607 return -1;
2097 2608 }
2098 2609  
... ... @@ -2125,13 +2636,13 @@ static int test_opcode_table (opc_handler_t **table, int len)
2125 2636 return count;
2126 2637 }
2127 2638  
2128   -static void fix_opcode_tables (void)
  2639 +static void fix_opcode_tables (opc_handler_t **ppc_opcodes)
2129 2640 {
2130 2641 if (test_opcode_table(ppc_opcodes, 0x40) == 0)
2131   - fprintf(stderr, "*** WARNING: no opcode defined !\n");
  2642 + printf("*** WARNING: no opcode defined !\n");
2132 2643 }
2133 2644  
2134   -#define SPR_RIGHTS(rw, priv) ((2 * (priv)) + (rw))
  2645 +#define SPR_RIGHTS(rw, priv) (1 << ((2 * (priv)) + (rw)))
2135 2646 #define SPR_UR SPR_RIGHTS(0, 0)
2136 2647 #define SPR_UW SPR_RIGHTS(1, 0)
2137 2648 #define SPR_SR SPR_RIGHTS(0, 1)
... ... @@ -2142,87 +2653,199 @@ do { \
2142 2653 spr_access[(spr) >> 1] |= ((rights) << (4 * ((spr) & 1))); \
2143 2654 } while (0)
2144 2655  
2145   -static void init_spr_rights (void)
  2656 +static void init_spr_rights (uint32_t pvr)
2146 2657 {
2147 2658 /* XER (SPR 1) */
2148   - spr_set_rights(SPR_ENCODE(1), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
  2659 + spr_set_rights(XER, SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2149 2660 /* LR (SPR 8) */
2150   - spr_set_rights(SPR_ENCODE(8), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
  2661 + spr_set_rights(LR, SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2151 2662 /* CTR (SPR 9) */
2152   - spr_set_rights(SPR_ENCODE(9), SPR_UR | SPR_UW | SPR_SR | SPR_SW);
  2663 + spr_set_rights(CTR, SPR_UR | SPR_UW | SPR_SR | SPR_SW);
2153 2664 /* TBL (SPR 268) */
2154   - spr_set_rights(SPR_ENCODE(268), SPR_UR | SPR_SR);
  2665 + spr_set_rights(V_TBL, SPR_UR | SPR_SR);
2155 2666 /* TBU (SPR 269) */
2156   - spr_set_rights(SPR_ENCODE(269), SPR_UR | SPR_SR);
  2667 + spr_set_rights(V_TBU, SPR_UR | SPR_SR);
2157 2668 /* DSISR (SPR 18) */
2158   - spr_set_rights(SPR_ENCODE(18), SPR_SR | SPR_SW);
  2669 + spr_set_rights(DSISR, SPR_SR | SPR_SW);
2159 2670 /* DAR (SPR 19) */
2160   - spr_set_rights(SPR_ENCODE(19), SPR_SR | SPR_SW);
  2671 + spr_set_rights(DAR, SPR_SR | SPR_SW);
2161 2672 /* DEC (SPR 22) */
2162   - spr_set_rights(SPR_ENCODE(22), SPR_SR | SPR_SW);
  2673 + spr_set_rights(DECR, SPR_SR | SPR_SW);
2163 2674 /* SDR1 (SPR 25) */
2164   - spr_set_rights(SPR_ENCODE(25), SPR_SR | SPR_SW);
  2675 + spr_set_rights(SDR1, SPR_SR | SPR_SW);
  2676 + /* SRR0 (SPR 26) */
  2677 + spr_set_rights(SRR0, SPR_SR | SPR_SW);
  2678 + /* SRR1 (SPR 27) */
  2679 + spr_set_rights(SRR1, SPR_SR | SPR_SW);
2165 2680 /* SPRG0 (SPR 272) */
2166   - spr_set_rights(SPR_ENCODE(272), SPR_SR | SPR_SW);
  2681 + spr_set_rights(SPRG0, SPR_SR | SPR_SW);
2167 2682 /* SPRG1 (SPR 273) */
2168   - spr_set_rights(SPR_ENCODE(273), SPR_SR | SPR_SW);
  2683 + spr_set_rights(SPRG1, SPR_SR | SPR_SW);
2169 2684 /* SPRG2 (SPR 274) */
2170   - spr_set_rights(SPR_ENCODE(274), SPR_SR | SPR_SW);
  2685 + spr_set_rights(SPRG2, SPR_SR | SPR_SW);
2171 2686 /* SPRG3 (SPR 275) */
2172   - spr_set_rights(SPR_ENCODE(275), SPR_SR | SPR_SW);
  2687 + spr_set_rights(SPRG3, SPR_SR | SPR_SW);
2173 2688 /* ASR (SPR 280) */
2174   - spr_set_rights(SPR_ENCODE(281), SPR_SR | SPR_SW);
  2689 + spr_set_rights(ASR, SPR_SR | SPR_SW);
2175 2690 /* EAR (SPR 282) */
2176   - spr_set_rights(SPR_ENCODE(282), SPR_SR | SPR_SW);
  2691 + spr_set_rights(EAR, SPR_SR | SPR_SW);
  2692 + /* TBL (SPR 284) */
  2693 + spr_set_rights(O_TBL, SPR_SW);
  2694 + /* TBU (SPR 285) */
  2695 + spr_set_rights(O_TBU, SPR_SW);
  2696 + /* PVR (SPR 287) */
  2697 + spr_set_rights(PVR, SPR_SR);
2177 2698 /* IBAT0U (SPR 528) */
2178   - spr_set_rights(SPR_ENCODE(528), SPR_SR | SPR_SW);
  2699 + spr_set_rights(IBAT0U, SPR_SR | SPR_SW);
2179 2700 /* IBAT0L (SPR 529) */
2180   - spr_set_rights(SPR_ENCODE(529), SPR_SR | SPR_SW);
  2701 + spr_set_rights(IBAT0L, SPR_SR | SPR_SW);
2181 2702 /* IBAT1U (SPR 530) */
2182   - spr_set_rights(SPR_ENCODE(530), SPR_SR | SPR_SW);
  2703 + spr_set_rights(IBAT1U, SPR_SR | SPR_SW);
2183 2704 /* IBAT1L (SPR 531) */
2184   - spr_set_rights(SPR_ENCODE(531), SPR_SR | SPR_SW);
  2705 + spr_set_rights(IBAT1L, SPR_SR | SPR_SW);
2185 2706 /* IBAT2U (SPR 532) */
2186   - spr_set_rights(SPR_ENCODE(532), SPR_SR | SPR_SW);
  2707 + spr_set_rights(IBAT2U, SPR_SR | SPR_SW);
2187 2708 /* IBAT2L (SPR 533) */
2188   - spr_set_rights(SPR_ENCODE(533), SPR_SR | SPR_SW);
  2709 + spr_set_rights(IBAT2L, SPR_SR | SPR_SW);
2189 2710 /* IBAT3U (SPR 534) */
2190   - spr_set_rights(SPR_ENCODE(534), SPR_SR | SPR_SW);
  2711 + spr_set_rights(IBAT3U, SPR_SR | SPR_SW);
2191 2712 /* IBAT3L (SPR 535) */
2192   - spr_set_rights(SPR_ENCODE(535), SPR_SR | SPR_SW);
  2713 + spr_set_rights(IBAT3L, SPR_SR | SPR_SW);
2193 2714 /* DBAT0U (SPR 536) */
2194   - spr_set_rights(SPR_ENCODE(536), SPR_SR | SPR_SW);
  2715 + spr_set_rights(DBAT0U, SPR_SR | SPR_SW);
2195 2716 /* DBAT0L (SPR 537) */
2196   - spr_set_rights(SPR_ENCODE(537), SPR_SR | SPR_SW);
  2717 + spr_set_rights(DBAT0L, SPR_SR | SPR_SW);
2197 2718 /* DBAT1U (SPR 538) */
2198   - spr_set_rights(SPR_ENCODE(538), SPR_SR | SPR_SW);
  2719 + spr_set_rights(DBAT1U, SPR_SR | SPR_SW);
2199 2720 /* DBAT1L (SPR 539) */
2200   - spr_set_rights(SPR_ENCODE(539), SPR_SR | SPR_SW);
  2721 + spr_set_rights(DBAT1L, SPR_SR | SPR_SW);
2201 2722 /* DBAT2U (SPR 540) */
2202   - spr_set_rights(SPR_ENCODE(540), SPR_SR | SPR_SW);
  2723 + spr_set_rights(DBAT2U, SPR_SR | SPR_SW);
2203 2724 /* DBAT2L (SPR 541) */
2204   - spr_set_rights(SPR_ENCODE(541), SPR_SR | SPR_SW);
  2725 + spr_set_rights(DBAT2L, SPR_SR | SPR_SW);
2205 2726 /* DBAT3U (SPR 542) */
2206   - spr_set_rights(SPR_ENCODE(542), SPR_SR | SPR_SW);
  2727 + spr_set_rights(DBAT3U, SPR_SR | SPR_SW);
2207 2728 /* DBAT3L (SPR 543) */
2208   - spr_set_rights(SPR_ENCODE(543), SPR_SR | SPR_SW);
  2729 + spr_set_rights(DBAT3L, SPR_SR | SPR_SW);
2209 2730 /* DABR (SPR 1013) */
2210   - spr_set_rights(SPR_ENCODE(1013), SPR_SR | SPR_SW);
  2731 + spr_set_rights(DABR, SPR_SR | SPR_SW);
2211 2732 /* FPECR (SPR 1022) */
2212   - spr_set_rights(SPR_ENCODE(1022), SPR_SR | SPR_SW);
  2733 + spr_set_rights(FPECR, SPR_SR | SPR_SW);
2213 2734 /* PIR (SPR 1023) */
2214   - spr_set_rights(SPR_ENCODE(1023), SPR_SR | SPR_SW);
2215   - /* PVR (SPR 287) */
2216   - spr_set_rights(SPR_ENCODE(287), SPR_SR);
2217   - /* TBL (SPR 284) */
2218   - spr_set_rights(SPR_ENCODE(284), SPR_SW);
2219   - /* TBU (SPR 285) */
2220   - spr_set_rights(SPR_ENCODE(285), SPR_SW);
  2735 + spr_set_rights(PIR, SPR_SR | SPR_SW);
  2736 + /* Special registers for MPC740/745/750/755 (aka G3) & IBM 750 */
  2737 + if ((pvr & 0xFFFF0000) == 0x00080000 ||
  2738 + (pvr & 0xFFFF0000) == 0x70000000) {
  2739 + /* HID0 */
  2740 + spr_set_rights(SPR_ENCODE(1008), SPR_SR | SPR_SW);
  2741 + /* HID1 */
  2742 + spr_set_rights(SPR_ENCODE(1009), SPR_SR | SPR_SW);
  2743 + /* IABR */
  2744 + spr_set_rights(SPR_ENCODE(1010), SPR_SR | SPR_SW);
  2745 + /* ICTC */
  2746 + spr_set_rights(SPR_ENCODE(1019), SPR_SR | SPR_SW);
  2747 + /* L2CR */
  2748 + spr_set_rights(SPR_ENCODE(1017), SPR_SR | SPR_SW);
  2749 + /* MMCR0 */
  2750 + spr_set_rights(SPR_ENCODE(952), SPR_SR | SPR_SW);
  2751 + /* MMCR1 */
  2752 + spr_set_rights(SPR_ENCODE(956), SPR_SR | SPR_SW);
  2753 + /* PMC1 */
  2754 + spr_set_rights(SPR_ENCODE(953), SPR_SR | SPR_SW);
  2755 + /* PMC2 */
  2756 + spr_set_rights(SPR_ENCODE(954), SPR_SR | SPR_SW);
  2757 + /* PMC3 */
  2758 + spr_set_rights(SPR_ENCODE(957), SPR_SR | SPR_SW);
  2759 + /* PMC4 */
  2760 + spr_set_rights(SPR_ENCODE(958), SPR_SR | SPR_SW);
  2761 + /* SIA */
  2762 + spr_set_rights(SPR_ENCODE(955), SPR_SR | SPR_SW);
  2763 + /* THRM1 */
  2764 + spr_set_rights(SPR_ENCODE(1020), SPR_SR | SPR_SW);
  2765 + /* THRM2 */
  2766 + spr_set_rights(SPR_ENCODE(1021), SPR_SR | SPR_SW);
  2767 + /* THRM3 */
  2768 + spr_set_rights(SPR_ENCODE(1022), SPR_SR | SPR_SW);
  2769 + /* UMMCR0 */
  2770 + spr_set_rights(SPR_ENCODE(936), SPR_UR | SPR_UW);
  2771 + /* UMMCR1 */
  2772 + spr_set_rights(SPR_ENCODE(940), SPR_UR | SPR_UW);
  2773 + /* UPMC1 */
  2774 + spr_set_rights(SPR_ENCODE(937), SPR_UR | SPR_UW);
  2775 + /* UPMC2 */
  2776 + spr_set_rights(SPR_ENCODE(938), SPR_UR | SPR_UW);
  2777 + /* UPMC3 */
  2778 + spr_set_rights(SPR_ENCODE(941), SPR_UR | SPR_UW);
  2779 + /* UPMC4 */
  2780 + spr_set_rights(SPR_ENCODE(942), SPR_UR | SPR_UW);
  2781 + /* USIA */
  2782 + spr_set_rights(SPR_ENCODE(939), SPR_UR | SPR_UW);
  2783 + }
  2784 + /* MPC755 has special registers */
  2785 + if (pvr == 0x00083100) {
  2786 + /* SPRG4 */
  2787 + spr_set_rights(SPRG4, SPR_SR | SPR_SW);
  2788 + /* SPRG5 */
  2789 + spr_set_rights(SPRG5, SPR_SR | SPR_SW);
  2790 + /* SPRG6 */
  2791 + spr_set_rights(SPRG6, SPR_SR | SPR_SW);
  2792 + /* SPRG7 */
  2793 + spr_set_rights(SPRG7, SPR_SR | SPR_SW);
  2794 + /* IBAT4U */
  2795 + spr_set_rights(IBAT4U, SPR_SR | SPR_SW);
  2796 + /* IBAT4L */
  2797 + spr_set_rights(IBAT4L, SPR_SR | SPR_SW);
  2798 + /* IBAT5U */
  2799 + spr_set_rights(IBAT5U, SPR_SR | SPR_SW);
  2800 + /* IBAT5L */
  2801 + spr_set_rights(IBAT5L, SPR_SR | SPR_SW);
  2802 + /* IBAT6U */
  2803 + spr_set_rights(IBAT6U, SPR_SR | SPR_SW);
  2804 + /* IBAT6L */
  2805 + spr_set_rights(IBAT6L, SPR_SR | SPR_SW);
  2806 + /* IBAT7U */
  2807 + spr_set_rights(IBAT7U, SPR_SR | SPR_SW);
  2808 + /* IBAT7L */
  2809 + spr_set_rights(IBAT7L, SPR_SR | SPR_SW);
  2810 + /* DBAT4U */
  2811 + spr_set_rights(DBAT4U, SPR_SR | SPR_SW);
  2812 + /* DBAT4L */
  2813 + spr_set_rights(DBAT4L, SPR_SR | SPR_SW);
  2814 + /* DBAT5U */
  2815 + spr_set_rights(DBAT5U, SPR_SR | SPR_SW);
  2816 + /* DBAT5L */
  2817 + spr_set_rights(DBAT5L, SPR_SR | SPR_SW);
  2818 + /* DBAT6U */
  2819 + spr_set_rights(DBAT6U, SPR_SR | SPR_SW);
  2820 + /* DBAT6L */
  2821 + spr_set_rights(DBAT6L, SPR_SR | SPR_SW);
  2822 + /* DBAT7U */
  2823 + spr_set_rights(DBAT7U, SPR_SR | SPR_SW);
  2824 + /* DBAT7L */
  2825 + spr_set_rights(DBAT7L, SPR_SR | SPR_SW);
  2826 + /* DMISS */
  2827 + spr_set_rights(SPR_ENCODE(976), SPR_SR | SPR_SW);
  2828 + /* DCMP */
  2829 + spr_set_rights(SPR_ENCODE(977), SPR_SR | SPR_SW);
  2830 + /* DHASH1 */
  2831 + spr_set_rights(SPR_ENCODE(978), SPR_SR | SPR_SW);
  2832 + /* DHASH2 */
  2833 + spr_set_rights(SPR_ENCODE(979), SPR_SR | SPR_SW);
  2834 + /* IMISS */
  2835 + spr_set_rights(SPR_ENCODE(980), SPR_SR | SPR_SW);
  2836 + /* ICMP */
  2837 + spr_set_rights(SPR_ENCODE(981), SPR_SR | SPR_SW);
  2838 + /* RPA */
  2839 + spr_set_rights(SPR_ENCODE(982), SPR_SR | SPR_SW);
  2840 + /* HID2 */
  2841 + spr_set_rights(SPR_ENCODE(1011), SPR_SR | SPR_SW);
  2842 + /* L2PM */
  2843 + spr_set_rights(SPR_ENCODE(1016), SPR_SR | SPR_SW);
  2844 + }
2221 2845 }
2222 2846  
2223   -/* PPC "main stream" common instructions */
2224   -#define PPC_COMMON (PPC_INTEGER | PPC_FLOAT | PPC_FLOW | PPC_MEM | \
2225   - PPC_MISC | PPC_EXTERN | PPC_SEGMENT)
  2847 +/*****************************************************************************/
  2848 +/* PPC "main stream" common instructions (no optional ones) */
2226 2849  
2227 2850 typedef struct ppc_proc_t {
2228 2851 int flags;
... ... @@ -2240,9 +2863,26 @@ static ppc_proc_t ppc_proc_common = {
2240 2863 .specific = NULL,
2241 2864 };
2242 2865  
  2866 +static ppc_proc_t ppc_proc_G3 = {
  2867 + .flags = PPC_750,
  2868 + .specific = NULL,
  2869 +};
  2870 +
2243 2871 static ppc_def_t ppc_defs[] =
2244 2872 {
2245   - /* Fallback */
  2873 + /* MPC740/745/750/755 (G3) */
  2874 + {
  2875 + .pvr = 0x00080000,
  2876 + .pvr_mask = 0xFFFF0000,
  2877 + .proc = &ppc_proc_G3,
  2878 + },
  2879 + /* IBM 750FX (G3 embedded) */
  2880 + {
  2881 + .pvr = 0x70000000,
  2882 + .pvr_mask = 0xFFFF0000,
  2883 + .proc = &ppc_proc_G3,
  2884 + },
  2885 + /* Fallback (generic PPC) */
2246 2886 {
2247 2887 .pvr = 0x00000000,
2248 2888 .pvr_mask = 0x00000000,
... ... @@ -2250,7 +2890,7 @@ static ppc_def_t ppc_defs[] =
2250 2890 },
2251 2891 };
2252 2892  
2253   -static int create_ppc_proc (unsigned long pvr)
  2893 +static int create_ppc_proc (opc_handler_t **ppc_opcodes, unsigned long pvr)
2254 2894 {
2255 2895 opcode_t *opc;
2256 2896 int i, flags;
... ... @@ -2265,65 +2905,71 @@ static int create_ppc_proc (unsigned long pvr)
2265 2905 }
2266 2906  
2267 2907 for (opc = &opc_start + 1; opc != &opc_end; opc++) {
2268   - if ((opc->type & flags) != 0)
2269   - if (register_insn(opc) < 0) {
2270   - fprintf(stderr, "*** ERROR initializing PPC instruction "
  2908 + if ((opc->handler.type & flags) != 0)
  2909 + if (register_insn(ppc_opcodes, opc) < 0) {
  2910 + printf("*** ERROR initializing PPC instruction "
2271 2911 "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
2272 2912 opc->opc3);
2273 2913 return -1;
2274 2914 }
2275 2915 }
2276   - fix_opcode_tables();
  2916 + fix_opcode_tables(ppc_opcodes);
2277 2917  
2278 2918 return 0;
2279 2919 }
2280 2920  
  2921 +
2281 2922 /*****************************************************************************/
2282   -uint32_t do_load_xer (void);
  2923 +/* Misc PPC helpers */
  2924 +FILE *stdout;
2283 2925  
2284 2926 void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags)
2285 2927 {
2286 2928 int i;
2287 2929  
2288   - if (loglevel > 0) {
2289   - fprintf(logfile, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x\n",
2290   - env->nip, env->LR, env->CTR, do_load_xer());
  2930 + fprintf(f, "nip=0x%08x LR=0x%08x CTR=0x%08x XER=0x%08x "
  2931 + "MSR=0x%08x\n", env->nip, env->lr, env->ctr,
  2932 + _load_xer(), _load_msr());
2291 2933 for (i = 0; i < 32; i++) {
2292 2934 if ((i & 7) == 0)
2293   - fprintf(logfile, "GPR%02d:", i);
2294   - fprintf(logfile, " %08x", env->gpr[i]);
  2935 + fprintf(f, "GPR%02d:", i);
  2936 + fprintf(f, " %08x", env->gpr[i]);
2295 2937 if ((i & 7) == 7)
2296   - fprintf(logfile, "\n");
  2938 + fprintf(f, "\n");
2297 2939 }
2298   - fprintf(logfile, "CR: 0x");
  2940 + fprintf(f, "CR: 0x");
2299 2941 for (i = 0; i < 8; i++)
2300   - fprintf(logfile, "%01x", env->crf[i]);
2301   - fprintf(logfile, " [");
  2942 + fprintf(f, "%01x", env->crf[i]);
  2943 + fprintf(f, " [");
2302 2944 for (i = 0; i < 8; i++) {
2303 2945 char a = '-';
2304   -
2305 2946 if (env->crf[i] & 0x08)
2306 2947 a = 'L';
2307 2948 else if (env->crf[i] & 0x04)
2308 2949 a = 'G';
2309 2950 else if (env->crf[i] & 0x02)
2310 2951 a = 'E';
2311   - fprintf(logfile, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
  2952 + fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
2312 2953 }
2313   - fprintf(logfile, " ] ");
2314   - fprintf(logfile, "TB: 0x%08x %08x\n", env->spr[SPR_ENCODE(269)],
2315   - env->spr[SPR_ENCODE(268)]);
  2954 + fprintf(f, " ] ");
  2955 + fprintf(f, "TB: 0x%08x %08x\n", env->tb[1], env->tb[0]);
2316 2956 for (i = 0; i < 16; i++) {
2317 2957 if ((i & 3) == 0)
2318   - fprintf(logfile, "FPR%02d:", i);
2319   - fprintf(logfile, " %016llx", *((uint64_t *)(&env->fpr[i])));
  2958 + fprintf(f, "FPR%02d:", i);
  2959 + fprintf(f, " %016llx", *((uint64_t *)&env->fpr[i]));
2320 2960 if ((i & 3) == 3)
2321   - fprintf(logfile, "\n");
2322   - }
2323   - fflush(logfile);
  2961 + fprintf(f, "\n");
2324 2962 }
  2963 + fprintf(f, "SRR0 0x%08x SRR1 0x%08x\n",
  2964 + env->spr[SRR0], env->spr[SRR1]);
  2965 + fprintf(f, "reservation 0x%08x\n", env->reserve);
  2966 + fflush(f);
2325 2967 }
2326 2968  
  2969 +#if !defined(CONFIG_USER_ONLY) && defined (USE_OPENFIRMWARE)
  2970 +int setup_machine (CPUPPCState *env, uint32_t mid);
  2971 +#endif
  2972 +
2327 2973 CPUPPCState *cpu_ppc_init(void)
2328 2974 {
2329 2975 CPUPPCState *env;
... ... @@ -2334,10 +2980,26 @@ CPUPPCState *cpu_ppc_init(void)
2334 2980 if (!env)
2335 2981 return NULL;
2336 2982 memset(env, 0, sizeof(CPUPPCState));
2337   - env->PVR = 0;
2338   - if (create_ppc_proc(0) < 0)
  2983 +#if !defined(CONFIG_USER_ONLY) && defined (USE_OPEN_FIRMWARE)
  2984 + setup_machine(env, 0);
  2985 +#else
  2986 +// env->spr[PVR] = 0; /* Basic PPC */
  2987 + env->spr[PVR] = 0x00080100; /* G3 CPU */
  2988 +// env->spr[PVR] = 0x00083100; /* MPC755 (G3 embedded) */
  2989 +// env->spr[PVR] = 0x00070100; /* IBM 750FX */
  2990 +#endif
  2991 + env->decr = 0xFFFFFFFF;
  2992 + if (create_ppc_proc(ppc_opcodes, env->spr[PVR]) < 0)
2339 2993 return NULL;
2340   - init_spr_rights();
  2994 + init_spr_rights(env->spr[PVR]);
  2995 + tlb_flush(env);
  2996 +#if defined (DO_SINGLE_STEP)
  2997 + /* Single step trace mode */
  2998 + msr_se = 1;
  2999 +#endif
  3000 +#if defined(CONFIG_USER_ONLY)
  3001 + msr_pr = 1;
  3002 +#endif
2341 3003  
2342 3004 return env;
2343 3005 }
... ... @@ -2348,6 +3010,11 @@ void cpu_ppc_close(CPUPPCState *env)
2348 3010 free(env);
2349 3011 }
2350 3012  
  3013 +/*****************************************************************************/
  3014 +void raise_exception_err (int exception_index, int error_code);
  3015 +int print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
  3016 + int dialect);
  3017 +
2351 3018 int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2352 3019 int search_pc)
2353 3020 {
... ... @@ -2356,7 +3023,6 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2356 3023 uint32_t pc_start;
2357 3024 uint16_t *gen_opc_end;
2358 3025 int j, lj = -1;
2359   - int ret = 0;
2360 3026  
2361 3027 pc_start = tb->pc;
2362 3028 gen_opc_ptr = gen_opc_buf;
... ... @@ -2364,11 +3030,21 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2364 3030 gen_opparam_ptr = gen_opparam_buf;
2365 3031 ctx.nip = (uint32_t *)pc_start;
2366 3032 ctx.tb_offset = 0;
2367   - ctx.supervisor = msr_ip;
  3033 + ctx.decr_offset = 0;
2368 3034 ctx.tb = tb;
2369   - ctx.exception = 0;
2370   -
2371   - while (ret == 0 && gen_opc_ptr < gen_opc_end) {
  3035 + ctx.exception = EXCP_NONE;
  3036 +#if defined(CONFIG_USER_ONLY)
  3037 + ctx.mem_idx = 0;
  3038 +#else
  3039 + ctx.supervisor = 1 - msr_pr;
  3040 + ctx.mem_idx = (1 - msr_pr);
  3041 +#endif
  3042 +#if defined (DO_SINGLE_STEP)
  3043 + /* Single step trace mode */
  3044 + msr_se = 1;
  3045 +#endif
  3046 + /* Set env in case of segfault during code fetch */
  3047 + while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
2372 3048 if (search_pc) {
2373 3049 if (loglevel > 0)
2374 3050 fprintf(logfile, "Search PC...\n");
... ... @@ -2381,15 +3057,26 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2381 3057 gen_opc_instr_start[lj] = 1;
2382 3058 }
2383 3059 }
2384   - ctx.opcode = __be32_to_cpu(*ctx.nip);
2385   -#ifdef DEBUG_DISAS
  3060 +#if defined DEBUG_DISAS
2386 3061 if (loglevel > 0) {
2387 3062 fprintf(logfile, "----------------\n");
2388   - fprintf(logfile, "%p: translate opcode %08x\n",
2389   - ctx.nip, ctx.opcode);
  3063 + fprintf(logfile, "nip=%p super=%d ir=%d\n",
  3064 + ctx.nip, 1 - msr_pr, msr_ir);
  3065 + }
  3066 +#endif
  3067 + ctx.opcode = ldl_code(ctx.nip);
  3068 +#if defined DEBUG_DISAS
  3069 + if (loglevel > 0) {
  3070 + fprintf(logfile, "translate opcode %08x (%02x %02x %02x)\n",
  3071 + ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
  3072 + opc3(ctx.opcode));
2390 3073 }
2391 3074 #endif
2392 3075 ctx.nip++;
  3076 + ctx.tb_offset++;
  3077 + /* Check decrementer exception */
  3078 + if (++ctx.decr_offset == env->decr + 1)
  3079 + ctx.exception = EXCP_DECR;
2393 3080 table = ppc_opcodes;
2394 3081 handler = table[opc1(ctx.opcode)];
2395 3082 if (is_indirect_opcode(handler)) {
... ... @@ -2405,62 +3092,93 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2405 3092 if (loglevel > 0) {
2406 3093 if (handler->handler == &gen_invalid) {
2407 3094 fprintf(logfile, "invalid/unsupported opcode: "
2408   - "%02x -%02x - %02x (%08x)\n", opc1(ctx.opcode),
2409   - opc2(ctx.opcode), opc3(ctx.opcode), ctx.opcode);
  3095 + "%02x -%02x - %02x (%08x) %p\n",
  3096 + opc1(ctx.opcode), opc2(ctx.opcode),
  3097 + opc3(ctx.opcode), ctx.opcode, ctx.nip - 1);
2410 3098 } else {
2411 3099 fprintf(logfile, "invalid bits: %08x for opcode: "
2412   - "%02x -%02x - %02x (%p)\n",
  3100 + "%02x -%02x - %02x (0x%08x) (%p)\n",
2413 3101 ctx.opcode & handler->inval, opc1(ctx.opcode),
2414 3102 opc2(ctx.opcode), opc3(ctx.opcode),
2415   - handler->handler);
  3103 + ctx.opcode, ctx.nip - 1);
2416 3104 }
  3105 + } else {
  3106 + if (handler->handler == &gen_invalid) {
  3107 + printf("invalid/unsupported opcode: "
  3108 + "%02x -%02x - %02x (%08x) %p\n",
  3109 + opc1(ctx.opcode), opc2(ctx.opcode),
  3110 + opc3(ctx.opcode), ctx.opcode, ctx.nip - 1);
  3111 + } else {
  3112 + printf("invalid bits: %08x for opcode: "
  3113 + "%02x -%02x - %02x (0x%08x) (%p)\n",
  3114 + ctx.opcode & handler->inval, opc1(ctx.opcode),
  3115 + opc2(ctx.opcode), opc3(ctx.opcode),
  3116 + ctx.opcode, ctx.nip - 1);
  3117 + }
2417 3118 }
2418   - ret = GET_RETVAL(gen_invalid, ctx.opcode);
  3119 + (*gen_invalid)(&ctx);
2419 3120 } else {
2420   - ret = GET_RETVAL(*(handler->handler), ctx.opcode);
  3121 + (*(handler->handler))(&ctx);
2421 3122 }
2422   - ctx.tb_offset++;
2423   -#if defined (DO_SINGLE_STEP)
2424   - break;
  3123 + /* Check trace mode exceptions */
  3124 + if ((msr_be && ctx.exception == EXCP_BRANCH) ||
  3125 + /* Check in single step trace mode
  3126 + * we need to stop except if:
  3127 + * - rfi, trap or syscall
  3128 + * - first instruction of an exception handler
  3129 + */
  3130 + (msr_se && ((uint32_t)ctx.nip < 0x100 ||
  3131 + (uint32_t)ctx.nip > 0xF00 ||
  3132 + ((uint32_t)ctx.nip & 0xFC) != 0x04) &&
  3133 + ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI &&
  3134 + ctx.exception != EXCP_TRAP)) {
  3135 +#if !defined(CONFIG_USER_ONLY)
  3136 + gen_op_queue_exception(EXCP_TRACE);
2425 3137 #endif
  3138 + if (ctx.exception == EXCP_NONE) {
  3139 + ctx.exception = EXCP_TRACE;
2426 3140 }
2427   -#if defined (DO_STEP_FLUSH)
2428   - tb_flush(env);
2429   -#endif
2430   - /* We need to update the time base */
2431   - if (!search_pc)
2432   - gen_op_update_tb(ctx.tb_offset);
2433   - /* If we are in step-by-step mode, do a branch to the next instruction
2434   - * so the nip will be up-to-date
2435   - */
2436   -#if defined (DO_SINGLE_STEP)
2437   - if (ret == 0) {
  3141 + }
  3142 + /* if too long translation, stop generation too */
  3143 + if (gen_opc_ptr >= gen_opc_end ||
  3144 + ((uint32_t)ctx.nip - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
  3145 + if (ctx.exception == EXCP_NONE) {
2438 3146 gen_op_b((uint32_t)ctx.nip);
2439   - ret = EXCP_BRANCH;
  3147 + ctx.exception = EXCP_BRANCH;
2440 3148 }
2441   -#endif
2442   - /* If the exeption isn't a PPC one,
2443   - * generate it now.
2444   - */
2445   - if (ret != EXCP_BRANCH) {
2446   - gen_op_set_T0(0);
2447   - if ((ret & 0x2000) == 0)
2448   - gen_op_raise_exception(ret);
2449 3149 }
  3150 + }
  3151 + /* In case of branch, this has already been done *BEFORE* the branch */
  3152 + if (ctx.exception != EXCP_BRANCH && ctx.exception != EXCP_RFI) {
  3153 + gen_op_update_tb(ctx.tb_offset);
  3154 + gen_op_update_decr(ctx.decr_offset);
  3155 + gen_op_process_exceptions((uint32_t)ctx.nip);
  3156 + }
  3157 +#if 1
2450 3158 /* TO BE FIXED: T0 hasn't got a proper value, which makes tb_add_jump
2451 3159 * do bad business and then qemu crashes !
2452 3160 */
2453 3161 gen_op_set_T0(0);
  3162 +#endif
2454 3163 /* Generate the return instruction */
2455 3164 gen_op_exit_tb();
2456 3165 *gen_opc_ptr = INDEX_op_end;
2457   - if (!search_pc)
2458   - tb->size = (uint32_t)ctx.nip - pc_start;
2459   - else
  3166 + if (search_pc) {
  3167 + j = gen_opc_ptr - gen_opc_buf;
  3168 + lj++;
  3169 + while (lj <= j)
  3170 + gen_opc_instr_start[lj++] = 0;
2460 3171 tb->size = 0;
2461   -// *gen_opc_ptr = INDEX_op_end;
  3172 + if (loglevel > 0) {
  3173 + page_dump(logfile);
  3174 + }
  3175 + } else {
  3176 + tb->size = (uint32_t)ctx.nip - pc_start;
  3177 + }
2462 3178 #ifdef DEBUG_DISAS
2463 3179 if (loglevel > 0) {
  3180 + fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
  3181 + cpu_ppc_dump_state(env, logfile, 0);
2464 3182 fprintf(logfile, "IN: %s\n", lookup_symbol((void *)pc_start));
2465 3183 disas(logfile, (void *)pc_start, (uint32_t)ctx.nip - pc_start, 0, 0);
2466 3184 fprintf(logfile, "\n");
... ... @@ -2474,12 +3192,12 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2474 3192 return 0;
2475 3193 }
2476 3194  
2477   -int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb)
  3195 +int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
2478 3196 {
2479 3197 return gen_intermediate_code_internal(env, tb, 0);
2480 3198 }
2481 3199  
2482   -int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb)
  3200 +int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
2483 3201 {
2484 3202 return gen_intermediate_code_internal(env, tb, 1);
2485 3203 }
... ...