-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy patharmdefs.h
362 lines (289 loc) · 14.1 KB
/
armdefs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator.
Copyright (C) 1994 Advanced RISC Machines Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* DAG - added header recursion tests */
#ifndef ARMDEFS_HEADER
#define ARMDEFS_HEADER
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "c99.h"
/* Control caching of instruction handler functions */
#define ARMUL_INSTR_FUNC_CACHE
typedef uint32_t ARMword; /* must be 32 bits wide */
typedef struct ARMul_State ARMul_State;
extern ARMul_State statestr;
#define LOW false
#define HIGH true
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define UNUSED_VAR(x) (void)(x)
#define UPDATEBLOCKSIZE 256
/***************************************************************************\
* Macros to extract instruction fields *
\***************************************************************************/
#define BIT(n) ( (ARMword)(instr>>(n))&1) /* bit n of instruction */
#define BITS(m,n) ( (ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) ) /* bits m to n of instr */
#define TOPBITS(n) (instr >> (n)) /* bits 31 to n of instr */
/***************************************************************************\
* The hardware vector addresses *
\***************************************************************************/
#define ARMResetV 0L
#define ARMUndefinedInstrV 4L
#define ARMSWIV 8L
#define ARMPrefetchAbortV 12L
#define ARMDataAbortV 16L
#define ARMAddrExceptnV 20L
#define ARMIRQV 24L
#define ARMFIQV 28L
#define ARMErrorV 32L /* This is an offset, not an address ! */
#define ARMul_ResetV ARMResetV
#define ARMul_UndefinedInstrV ARMUndefinedInstrV
#define ARMul_SWIV ARMSWIV
#define ARMul_PrefetchAbortV ARMPrefetchAbortV
#define ARMul_DataAbortV ARMDataAbortV
#define ARMul_AddrExceptnV ARMAddrExceptnV
#define ARMul_IRQV ARMIRQV
#define ARMul_FIQV ARMFIQV
/***************************************************************************\
* Mode and Bank Constants *
\***************************************************************************/
#define USER26MODE 0L
#define FIQ26MODE 1L
#define IRQ26MODE 2L
#define SVC26MODE 3L
#define USERBANK USER26MODE
#define FIQBANK FIQ26MODE
#define IRQBANK IRQ26MODE
#define SVCBANK SVC26MODE
/***************************************************************************\
* Fastmap definitions *
\***************************************************************************/
/* The fast map encodes the page access flags, memory pointer, and read/write
function pointers into just two words of data (8 bytes on 32bit platforms,
16 bytes on 64bit)
The first word contains the access flags and memory pointer
The second word contains the read/write func pointer (combined function
under the assumption that MMIO read/write will be infrequent)
*/
#ifndef FASTMAP_64
#if defined(__LP64__) || defined(_WIN64)
#define FASTMAP_64
#endif
#endif
typedef intptr_t FastMapInt;
typedef uintptr_t FastMapUInt;
#ifdef FASTMAP_64
#define FASTMAP_FLAG(X) (((FastMapUInt)(X))<<56) /* Shift a byte to the top byte of the word */
#else
#define FASTMAP_FLAG(X) (((FastMapUInt)(X))<<24) /* Shift a byte to the top byte of the word */
#endif
#define FASTMAP_SIZE (0x4000000/4096)
#define FASTMAP_R_FUNC FASTMAP_FLAG(0x80) /* Use function for reading */
#define FASTMAP_W_FUNC FASTMAP_FLAG(0x40) /* Use function for writing */
#define FASTMAP_R_SVC FASTMAP_FLAG(0x20) /* Page has SVC read access */
#define FASTMAP_W_SVC FASTMAP_FLAG(0x10) /* Page has SVC write access */
#define FASTMAP_R_OS FASTMAP_FLAG(0x08) /* Page has OS read access */
#define FASTMAP_W_OS FASTMAP_FLAG(0x04) /* Page has OS write access */
#define FASTMAP_R_USR FASTMAP_FLAG(0x02) /* Page has USR read access */
#define FASTMAP_W_USR FASTMAP_FLAG(0x01) /* Page has USR write access */
#define FASTMAP_MODE_USR FASTMAP_FLAG(0x02) /* We are in user mode */
#define FASTMAP_MODE_OS FASTMAP_FLAG(0x08) /* The OS flag is set in the control register */
#define FASTMAP_MODE_SVC FASTMAP_FLAG(0x20) /* We are in SVC mode */
#define FASTMAP_MODE_MBO FASTMAP_FLAG(0x80) /* Must be one! */
#define FASTMAP_ACCESSFUNC_WRITE 0x01UL
#define FASTMAP_ACCESSFUNC_BYTE 0x02UL /* Only relevant for writes */
#define FASTMAP_ACCESSFUNC_STATECHANGE 0x04UL /* Only relevant for writes */
#ifdef ARMUL_INSTR_FUNC_CACHE
#define FASTMAP_CLOBBEREDFUNC 0 /* Value written when a func gets clobbered */
#endif
typedef FastMapInt FastMapRes; /* Result of a DecodeRead/DecodeWrite function */
typedef ARMword (*FastMapAccessFunc)(ARMul_State *state,ARMword addr,ARMword data,ARMword flags);
typedef struct {
FastMapUInt FlagsAndData;
FastMapAccessFunc AccessFunc;
} FastMapEntry;
/***************************************************************************\
* Event queue *
\***************************************************************************/
/* The event queue is a simple priority queue used for all time-based events
external to the CPU. Updating IOC timers, frontend screen output, etc.
The CPU cycle counter is the timer used to trigger the events.
When an event is triggered, it must either remove itself (via EventQ_Remove)
or reschedule itself for a different time (EventQ_RescheduleHead). Failure
to do either of those will result in an infinite loop where the same event
is repeatedly triggered without the CPU emulation advancing.
It's also acceptable for an event to remove itself and schedule several
other events, in its place. Just be careful about the order events are
inserted, otherwise when you call Remove(0) or RescheduleHead() the head
may not be the same as before. Also be wary of timer overflows; any event
scheduled for more than MAX_CYCLES_INTO_FUTURE cycles into the future will
be considered as having already been triggered and will fire immediately.
*/
typedef uint32_t CycleCount;
typedef int32_t CycleDiff;
#define MAX_CYCLES_INTO_FUTURE INT32_MAX
typedef void (*EventQ_Func)(ARMul_State *state,CycleCount nowtime);
typedef struct {
CycleCount Time; /* When to trigger the event */
EventQ_Func Func; /* Function to call */
} EventQ_Entry;
#define EVENTQ_SIZE 8
/* NOTE - For speed reasons there aren't any overflow checks in the eventq
code, so be aware of how many systems are using the queue. At the
moment, these are:
arch/newsound.c - One entry for sound DMA fetches
arch/XXXdisplaydev.c - One entry for screen updates
arch/keyboard.c - One entry for keyboard/mouse polling
arch/archio.c - One entry for IOC timers
arch/archio.c - One entry for FDC & HDC updates
= 5 total
*/
/***************************************************************************\
* Main emulator state *
\***************************************************************************/
typedef bool ARMul_CPInits(ARMul_State *state);
typedef bool ARMul_CPExits(ARMul_State *state);
typedef unsigned ARMul_LDCs(ARMul_State *state, unsigned type, ARMword instr, ARMword value);
typedef unsigned ARMul_STCs(ARMul_State *state, unsigned type, ARMword instr, ARMword *value);
typedef unsigned ARMul_MRCs(ARMul_State *state, unsigned type, ARMword instr, ARMword *value);
typedef unsigned ARMul_MCRs(ARMul_State *state, unsigned type, ARMword instr, ARMword value);
typedef unsigned ARMul_CDPs(ARMul_State *state, unsigned type, ARMword instr);
typedef bool ARMul_CPReads(ARMul_State *state, unsigned reg, ARMword *value);
typedef bool ARMul_CPWrites(ARMul_State *state, unsigned reg, ARMword value);
typedef enum ARMStartIns {
NORMAL = 0,
PCINCED = 1,
PRIMEPIPE = 2,
RESUME = 4
} ARMStartIns;
typedef struct arch_keyboard arch_keyboard;
typedef struct Vidc_Regs Vidc_Regs;
typedef struct ArcemConfig_s ArcemConfig;
#define Exception_IRQ R15IBIT
#define Exception_FIQ R15FBIT
struct ARMul_State {
/* Most common stuff, current register file first to ease indexing */
ARMword Reg[16]; /* the current register file */
CycleCount NumCycles; /* Number of cycles */
enum ARMStartIns NextInstr;/* Pipeline state */
bool abortSig; /* Abort state */
ARMword Aborted; /* sticky flag for aborts */
ARMword AbortAddr; /* to keep track of Prefetch aborts */
ARMword Exception; /* IRQ & FIQ pins */
Vidc_Regs *Display; /* VIDC regs/host display struct */
arch_keyboard *Kbd; /* Keyboard struct */
ARMword Bank; /* the current register bank */
bool NtransSig; /* MEMC USR/SVC flag, somewhat redundant with FastMapMode */
ARMword Base; /* extra hand for base writeback */
ArcemConfig *Config;
/* Event queue */
EventQ_Entry EventQ[EVENTQ_SIZE];
uint_fast8_t NumEvents;
/* Fastmap stuff */
FastMapUInt FastMapMode; /* Current access mode flags */
#ifdef ARMUL_INSTR_FUNC_CACHE
FastMapUInt FastMapInstrFuncOfs; /* Offset between the RAM/ROM data and the ARMEmuFunc data */
#endif
FastMapEntry *FastMap;
/* Less common stuff */
ARMword RegBank[4][16]; /* all the registers */
ARMword instr, pc, temp; /* saved register state */
ARMword loaded, decoded; /* saved pipeline state */
/* Rare stuff */
ARMul_CPInits *CPInit[16]; /* coprocessor initialisers */
ARMul_CPExits *CPExit[16]; /* coprocessor finalisers */
ARMul_LDCs *LDC[16]; /* LDC instruction */
ARMul_STCs *STC[16]; /* STC instruction */
ARMul_MRCs *MRC[16]; /* MRC instruction */
ARMul_MCRs *MCR[16]; /* MCR instruction */
ARMul_CDPs *CDP[16]; /* CDP instruction */
ARMul_CPReads *CPRead[16]; /* Read CP register */
ARMul_CPWrites *CPWrite[16]; /* Write CP register */
unsigned char *CPData[16]; /* Coprocessor data */
};
#ifdef AMIGA
extern void *state_alloc(int s);
extern void state_free(void *p);
#else
/* If you need special allocation for the state rather than
* using the usual static global, you can override these functions
* and provide your own.
*/
static inline void *state_alloc(int s)
{
return &statestr;
}
static inline void state_free(void *p)
{
}
#endif
/***************************************************************************\
* Definitons of things in the emulator *
\***************************************************************************/
void ARMul_EmulateInit(void);
ARMul_State *ARMul_NewState(ArcemConfig *pConfig);
void ARMul_Reset(ARMul_State *state);
ARMword ARMul_DoProg(ARMul_State *state);
/***************************************************************************\
* Definitons of things for event handling *
\***************************************************************************/
#define ARMul_Time (state->NumCycles)
/***************************************************************************\
* Useful support routines *
\***************************************************************************/
void ARMul_SetReg(ARMul_State *state, unsigned mode, unsigned reg, ARMword value);
ARMword ARMul_GetPC(ARMul_State *state);
ARMword ARMul_GetNextPC(ARMul_State *state);
void ARMul_SetPC(ARMul_State *state, ARMword value);
ARMword ARMul_GetR15(ARMul_State *state);
void ARMul_SetR15(ARMul_State *state, ARMword value);
/***************************************************************************\
* Definitons of things to handle aborts *
\***************************************************************************/
extern void ARMul_Abort(ARMul_State *state, ARMword address);
#define ARMul_ABORTWORD 0xefffffff /* SWI -1 */
#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
state->AbortAddr = ((address) & ~3L)
#define ARMul_DATAABORT(address) state->abortSig = HIGH; \
state->Aborted = ARMul_DataAbortV;
#define ARMul_CLEARABORT state->abortSig = LOW
/***************************************************************************\
* Definitons of things in the memory interface *
\***************************************************************************/
extern bool ARMul_MemoryInit(ARMul_State *state);
extern void ARMul_MemoryExit(ARMul_State *state);
/***************************************************************************\
* Definitons of things in the co-processor interface *
\***************************************************************************/
#define ARMul_FIRST 0
#define ARMul_TRANSFER 1
#define ARMul_BUSY 2
#define ARMul_DATA 3
#define ARMul_INTERRUPT 4
#define ARMul_DONE 0
#define ARMul_CANT 1
#define ARMul_INC 3
extern bool ARMul_CoProInit(ARMul_State *state);
extern void ARMul_CoProExit(ARMul_State *state);
extern void ARMul_CoProAttach(ARMul_State *state, unsigned number,
ARMul_CPInits *init, ARMul_CPExits *exits,
ARMul_LDCs *ldc, ARMul_STCs *stc,
ARMul_MRCs *mrc, ARMul_MCRs *mcr,
ARMul_CDPs *cdp,
ARMul_CPReads *reads, ARMul_CPWrites *writes);
extern void ARMul_CoProDetach(ARMul_State *state, unsigned number);
#include "arch/archio.h"
#include "arch/armarc.h"
#include "eventq.h"
#endif