Revision 9a64fbe4

b/target-ppc/cpu.h
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
#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 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 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 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 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 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 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__) */
b/target-ppc/exec.h
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__) */
b/target-ppc/helper.c
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 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 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 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)
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff