/
syn68k_private.h.in
293 lines (237 loc) · 10.2 KB
/
syn68k_private.h.in
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
/* This file contains information needed by both the compile time and runtime
* portions of the 68k emulator.
*/
#ifndef _syn68k_private_h_
#define _syn68k_private_h_
@NONNATIVE@
/* $Id: syn68k_private.h.in 72 2004-12-28 15:57:12Z ctm $ */
#include "syn68k_public.h"
#include <signal.h>
#define ALL_CCS 0x1F
/* Note: these are _not_ the order in which the bits appear in the ccr.
* For historical reasons, we keep track of them alphabetically.
*/
#define M68K_CC_NONE 0
#define M68K_CCC 0x10
#define M68K_CCN 0x8
#define M68K_CCV 0x4
#define M68K_CCX 0x2
#define M68K_CCZ 0x1
#define M68K_CC_ALL 0x1F
/* Shorthand for some common combinations. */
#define M68K_CC_CNVZ (M68K_CCC | M68K_CCN | M68K_CCV | M68K_CCZ)
#define M68K_CC_CNVXZ (M68K_CCC | M68K_CCN | M68K_CCV | M68K_CCX | M68K_CCZ)
/* For machines with few registers, it is worth our while to put the 68000
* registers into an array and random access them.
*
* It's been a while since this was defined -- if it's not defined, we might
* not be able to build.
*/
# define M68K_REGS_IN_ARRAY
/* If a machine rounds all divisions towards zero and the remainder always
* has the same sign as the dividend, #define this for better speed. It
* should work even if you leave it undefined though. If you have problems
* with divide, try undef'ing this to use the slower but safer version.
*/
#if defined(mc68000) || defined(i386) || defined(__alpha) || defined (powerpc) || defined (__ppc__) || defined(__x86_64)
# define M68K_DIVISION_BEHAVIOR
#endif
#if defined(__alpha)
/* #define TEMPS_AT_TOP */
#endif
/* Use faster threaded code if the needed gcc extensions are present.*/
#if defined (__GNUC__ ) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 4)) && !defined (NONDIRECT)
# define USE_DIRECT_DISPATCH
#endif
/* #define this if support exists for generating native code in some
* situations.
*/
#if defined (USE_DIRECT_DISPATCH) && defined(i386) && !defined (NONNATIVE)
# define GENERATE_NATIVE_CODE
#endif
#if defined (SYNCHRONOUS_INTERRUPTS) && !defined (GENERATE_NATIVE_CODE)
/* This is easy to fix, but I have more pressing things to work on.
* The problem is that, without native code, there is no synthetic opcode
* at the beginning of each block that checks for an interrupt.
* The proper way to rectify this is to return to the good old days
* when all synthetic opcodes that could branch backwards would check
* for an interrupt. With native code, we check at the beginning of
* each block, not on branches (it's much easier that way), so you do
* NOT want to check for interrupts on backwards synthetic branches
* if GENERATE_NATIVE_CODE is defined.
*
* NOTE: I (ctm) fixed this, although I don't guarantee that my fix is
* as fast as Mat's would have been.
*/
#endif
#ifdef USE_DIRECT_DISPATCH
extern const void *direct_dispatch_table[];
#endif
#ifdef SYNCHRONOUS_INTERRUPTS
# define BLOCK_INTERRUPTS(save) (save = 0)
# define RESTORE_INTERRUPTS(save)
#else /* !SYNCHRONOUS_INTERRUPTS */
# ifdef MSDOS
extern int dos_block_interrupts (void);
extern void dos_restore_interrupts (int);
# define BLOCK_INTERRUPTS(save) (save = dos_block_interrupts ())
# define RESTORE_INTERRUPTS(save) dos_restore_interrupts (save)
# else /* Not MSDOS */
# define SIGNALS_TO_BLOCK (sigmask(SIGALRM) | sigmask(SIGURG) \
| sigmask(SIGVTALRM) | sigmask(SIGIO))
# define BLOCK_INTERRUPTS(save) (save = sigblock (SIGNALS_TO_BLOCK));
# define RESTORE_INTERRUPTS(save) sigsetmask (save)
# endif /* Not MSDOS */
#endif /* !SYNCHRONOUS_INTERRUPTS */
/* Data types. */
#if !defined(FALSE) && !defined(TRUE)
typedef enum { FALSE, TRUE, NO = 0, YES = 1 } BOOL;
#else /* defined(FALSE) || defined(TRUE) */
typedef enum { NO = 0, YES = 1 } BOOL;
#endif /* defined(FALSE) || defined(TRUE) */
#ifndef NULL
#define NULL ((void *)0)
#endif
#define PTR_BYTES (sizeof (void *))
#define PTR_WORDS (PTR_BYTES / sizeof (uint16))
#define OPCODE_BYTES PTR_BYTES
#define OPCODE_WORDS PTR_WORDS
/* Many 68k opcodes have useful operands which will not be implicit in the
* synthetic opcode. The translator will extract these operands, translate
* them to a useful form, and place them in the interpreted instruction
* stream (in order). This struct describes both the location of these
* operands in the 68k instruction stream and how to translate them to
* a form useful to the interpreter. Only 32 bit, word aligned bitfields
* are allowed to span multiple words. Note: foo.index == MAGIC_END_INDEX
* && foo.length == MAGIC_END_LENGTH implies the end of the bitfield list.
*/
#define MAGIC_END_INDEX 126
#define MAGIC_END_LENGTH 30
#define IS_TERMINATING_BITFIELD(p) ((p)->index == MAGIC_END_INDEX \
&& (p)->length == MAGIC_END_LENGTH)
typedef struct {
uint16 rev_amode :1; /* If 1, swap high 3 bits w/low 3 bits for 6 bit # */
uint16 index :7; /* # of bits into instruction for this bitfield. */
uint16 length :5; /* Length, in bits, of this bitfield, minus 1. */
uint16 sign_extend :1; /* Boolean: sign extend the resulting number? */
uint16 make_native_endian :1; /* Swap bytes if we're little endian? */
uint16 words :1; /* # of words to expand this number into, minus 1. */
} BitfieldInfo;
#define MAX_BITFIELDS 4
/* This struct contains information needed to map from 68k opcodes to
* synthetic cpu opcodes. Typically you would have one of these structs
* for each cc bit variant of each 68k opcode, although of course the
* point of the design of this structure is that sequences of these can
* be shared by many distinct 68k opcode bit patterns.
*/
typedef struct {
uint32 sequence_parity :1; /* Identifies contiguous blocks of these. */
/* CC bit information. */
uint32 cc_may_set :5; /* CC bits not necessarily left alone. */
uint32 cc_may_not_set :5; /* CC bits not necessarily changed. */
uint32 cc_needed :5; /* CC bits which must be valid for this. */
/* 68k opcode information. */
uint32 instruction_words :4; /* # of 16 bit words taken by 68k opcode. */
uint32 ends_block :1; /* Boolean: does this end a basic block? */
uint32 next_block_dynamic :1; /* Boolean: next block known runtime only. */
/* Are there addressing modes, and did we expand them? */
uint32 amode_size :2; /* 0:none, 1:byte, 2:word, 3:long. */
uint32 reversed_amode_size :2; /* 0:none, 1:byte, 2:word, 3:long. */
uint32 amode_expanded :1; /* If has amode, was it expanded? */
uint32 reversed_amode_expanded :1; /* If has reversed_amode, " " " ? */
/* Bit pattern mapping information. This lets us compute the synthetic
* opcode from the 68k opcode.
*/
uint32 opcode_shift_count :4; /* # of bits by which to >> 68k opcode. */
uint16 opcode_and_bits; /* Mask with which to & 68k opcode. */
uint16 opcode_add_bits; /* Bits to add to 68k opcode. */
/* Actual bitfield extraction/translation information. */
BitfieldInfo bitfield[MAX_BITFIELDS]; /* Bitfields to parse & translate. */
#ifdef GENERATE_NATIVE_CODE
# ifdef SYNGEN
const char *guest_code_descriptor; /* We only know its name here. */
# else /* !SYNGEN */
const struct _guest_code_descriptor_t *guest_code_descriptor;
# endif /* !SYNGEN */
#endif /* GENERATE_NATIVE_CODE */
} OpcodeMappingInfo;
#ifndef QUADALIGN
# define READUL_UNSWAPPED(addr) (*(uint32 *) SYN68K_TO_US(addr))
# define READUL_UNSWAPPED_US(addr) (*(uint32 *) (addr))
#else
# ifdef BIGENDIAN
# define READUL_UNSWAPPED(addr) \
({ const uint16 *_p = (const uint16 *)SYN68K_TO_US(addr); (uint32)(_p[0] << 16) | _p[1]; })
# define READUL_UNSWAPPED_US(addr) \
({ const uint16 *_p = (const uint16 *)(addr); (uint32)(_p[0] << 16) | _p[1]; })
# else
#if defined(__GNUC__)
typedef struct { uint32 l __attribute__((packed)); } hidden_l;
#define READUL_UNSWAPPED(addr) (((hidden_l *)(SYN68K_TO_US(addr)))->l)
#define READUL_UNSWAPPED_US(addr) (((hidden_l *)(addr))->l)
#else
static uint32 _readul_unswapped(const uint16 *p)
{
return (uint32)(p[1] << 16) | p[0];
}
#define READUL_UNSWAPPED(addr) _readul_unswapped((const uint16 *) (SYN68K_TO_US(addr)))
#define READUL_UNSWAPPED_US(addr) _readul_unswapped((const uint16 *) (addr))
#endif
# endif
#endif
#define READSL_UNSWAPPED(addr) ((int32) READUL_UNSWAPPED (addr))
#ifndef QUADALIGN
# define WRITEUL_UNSWAPPED(p,v) (*(uint32 *)(p) = (v))
#else
# ifdef BIGENDIAN
# define WRITEUL_UNSWAPPED(p, v) \
({ \
uint32 _tmp = (v); \
uint16 *_x = (uint16 *)(p); \
_x[0] = _tmp >> 16; \
_x[1] = _tmp; \
_tmp; \
})
# else
#if defined(__GNUC__)
#define WRITEUL_UNSWAPPED(addr, v) (((hidden_l *)(addr))->l = (v))
#else
static uint32 _writeul_unswapped(uint16 *p, uint32 tmp)
{
p[0] = tmp;
p[1] = tmp >> 16;
return tmp;
}
#define WRITEUL_UNSWAPPED(p, v) _writeul_unswapped((uint16 *) (p), (v))
#endif
# endif
#endif
#define WRITESL_UNSWAPPED(p,v) ((int32) WRITEUL_UNSWAPPED (p, v))
/* FIXME - could be more efficient going one byte at a time on
* LITTLEENDIAN QUADALIGN machines.
*/
#define WRITE_LONG(p,v) (WRITEUL_UNSWAPPED ((p), SWAPUL_IFLE (v)))
#define WRITE_WORD(p,v) ((void) (*(uint16 *)(p) = SWAPUW_IFLE (v)))
#ifndef QUADALIGN
# define WRITE_PTR(p,v) (*(char **)(p) = (char *)(v))
#else
# define WRITE_PTR(p,v) \
{ void *ptr = (v); memcpy ((uint16 *)(p), &ptr, sizeof ptr); }
#endif
#define COMPUTE_SR_FROM_CPU_STATE() \
(cpu_state.sr | (cpu_state.ccc != 0) | ((cpu_state.ccv != 0) << 1) \
| ((cpu_state.ccnz == 0) << 2) | ((cpu_state.ccn != 0) << 3) \
| ((cpu_state.ccx != 0) << 4))
/* #if !defined(__alpha) */
#if SIZEOF_CHAR_P != 8
#define DEREF(typ, addr) (*(typ *)addr)
#else
typedef struct { int8 n __attribute__((packed)); } HIDDEN_int8;
typedef struct { uint8 n __attribute__((packed)); } HIDDEN_uint8;
typedef struct { int16 n __attribute__((packed)); } HIDDEN_int16;
typedef struct { uint16 n __attribute__((packed)); } HIDDEN_uint16;
typedef struct { int32 n __attribute__((packed)); } HIDDEN_int32;
typedef struct { uint32 n __attribute__((packed)); } HIDDEN_uint32;
#define DEREF(typ, addr) (((HIDDEN_ ## typ *)addr)->n)
#endif
#endif /* Not _syn68k_private_h_ */