1 /*
2 * @file emu68/inst68.c
3 * @brief 68000 instructions emulation
4 * @author http://sourceforge.net/users/benjihan
5 *
6 * Copyright (c) 1998-2015 Benjamin Gerard
7 *
8 * This program is free software: you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, either version 3 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program.
20 *
21 * If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include "inst68.h"
30 #include "assert68.h"
31 #include "srdef68.h"
32 #include "struct68.h"
33 #include "excep68.h"
34 #include "cc68.h"
35 #include "mem68.h"
36 #include "emu68.h"
37
38 /* ,-----------.
39 | Exception |
40 `-----------' */
41
42 #include "inl68_exception.h"
43
exception68(emu68_t * const emu68,const int vector,const int level)44 void exception68(emu68_t * const emu68, const int vector, const int level)
45 {
46 if ( vector < 0x100 ) {
47 /* Standard 68k exceptions */
48
49 int savesr = REG68.sr; /* save sr as it was */
50 int savest = emu68->status; /* save emu68 runstate */
51
52 emu68->status = EMU68_XCT; /* enter exception stat */
53 REG68.sr &= ~SR_T; /* no TRACE */
54 REG68.sr |= SR_S; /* Supervisor */
55
56 if ( savest == EMU68_XCT &&
57 ( vector == BUSERR_VECTOR || vector == ADRERR_VECTOR ) ) {
58 /* That's a double fault (exception produced an exception) */
59 emu68->status = EMU68_HLT; /* Halt processor */
60 /* Let user know. */
61 if (emu68->handler)
62 emu68->handler(emu68, HWHALT_VECTOR, emu68->cookie);
63 /* If user did not override notify the error. */
64 if (emu68->status == EMU68_HLT)
65 emu68_error_add(emu68, "double-fault @$%06x vector:%$x",
66 emu68->inst_pc, vector);
67 return;
68 } else if ( vector == RESET_VECTOR ) {
69 /* Reset reload SP and PC */
70 REG68.sr |= SR_I;
71 REG68.a[7] = read_L(RESET_SP_VECTOR << 2);
72 REG68.pc = read_L(RESET_PC_VECTOR << 2);
73 } else {
74 /* Standard exception, set IPL and trigger exception. */
75 if ( (unsigned int)level < 8u ) {
76 SET_IPL(REG68.sr,level);
77 }
78 pushl(REG68.pc);
79 pushw(savesr);
80 REG68.pc = read_L(vector << 2);
81
82 /* Back to saved runstate (not totally sure about that). */
83 emu68->status = savest;
84 }
85 }
86
87 /* Finally call the user handler for all kind of exceptions. */
88 if (emu68->handler)
89 emu68->handler(emu68, vector, emu68->cookie);
90
91 }
92
buserror68(emu68_t * const emu68,const int addr,const int mode)93 void buserror68(emu68_t * const emu68, const int addr, const int mode)
94 {
95 inl_buserror68(emu68, addr, mode);
96 }
97
linea68(emu68_t * const emu68)98 void linea68(emu68_t * const emu68)
99 {
100 inl_linea68(emu68);
101 }
102
linef68(emu68_t * const emu68)103 void linef68(emu68_t * const emu68)
104 {
105 inl_linef68(emu68);
106 }
107
108
109 /* ,------------.
110 | Arithmetic |
111 `------------' */
112
113 #include "inl68_arithmetic.h"
114
add68(emu68_t * const emu68,const int68_t s,int68_t d,int68_t c)115 int68_t add68(emu68_t * const emu68, const int68_t s, int68_t d, int68_t c)
116 {
117 return inl_add68(emu68, s, d, c);
118 }
119
sub68(emu68_t * const emu68,const int68_t s,int68_t d,int68_t c)120 int68_t sub68(emu68_t * const emu68, const int68_t s, int68_t d, int68_t c)
121 {
122 return inl_sub68(emu68, s, d, c);
123 }
124
cmp68(emu68_t * const emu68,const int68_t s,int68_t d)125 void cmp68(emu68_t * const emu68, const int68_t s, int68_t d)
126 {
127 inl_cmp68(emu68, s, d);
128 }
129
muls68(emu68_t * const emu68,const int68_t s,int68_t d)130 int68_t muls68(emu68_t * const emu68, const int68_t s, int68_t d)
131 {
132 return inl_muls68(emu68, s, d);
133 }
134
mulu68(emu68_t * const emu68,const uint68_t s,uint68_t d)135 int68_t mulu68(emu68_t * const emu68, const uint68_t s, uint68_t d)
136 {
137 return inl_mulu68(emu68, s, d);
138 }
139
divs68(emu68_t * const emu68,const int68_t s,int68_t d)140 int68_t divs68(emu68_t * const emu68, const int68_t s, int68_t d)
141 {
142 return inl_divs68(emu68, s, d);
143 }
144
divu68(emu68_t * const emu68,const uint68_t s,uint68_t d)145 int68_t divu68(emu68_t * const emu68, const uint68_t s, uint68_t d)
146 {
147 return inl_divu68(emu68, s, d);
148 }
149
clr68(emu68_t * const emu68)150 int68_t clr68(emu68_t * const emu68)
151 {
152 return inl_clr68(emu68);
153 }
154
neg68(emu68_t * const emu68,int68_t d,int68_t c)155 int68_t neg68(emu68_t * const emu68, int68_t d, int68_t c)
156 {
157 return inl_neg68(emu68, d, c);
158 }
159
160
161 /* ,-------.
162 | Logic |
163 `-------' */
164
165 #include "inl68_logic.h"
166
and68(emu68_t * const emu68,const int68_t s,int68_t d)167 int68_t and68(emu68_t * const emu68, const int68_t s, int68_t d)
168 {
169 return inl_and68(emu68, s, d);
170 }
171
orr68(emu68_t * const emu68,const int68_t s,int68_t d)172 int68_t orr68(emu68_t * const emu68, const int68_t s, int68_t d)
173 {
174 return inl_orr68(emu68, s, d);
175 }
176
eor68(emu68_t * const emu68,const int68_t s,int68_t d)177 int68_t eor68(emu68_t * const emu68, const int68_t s, int68_t d)
178 {
179 return inl_eor68(emu68, s, d);
180 }
181
not68(emu68_t * const emu68,int68_t d)182 int68_t not68(emu68_t * const emu68, int68_t d)
183 {
184 return inl_not68(emu68, d);
185 }
186
187
188 /* ,----------------.
189 | System Control |
190 `----------------' */
191
192 #include "inl68_systctrl.h"
193
illegal68(emu68_t * const emu68)194 void illegal68(emu68_t * const emu68)
195 {
196 inl_illegal68(emu68);
197 }
198
trapv68(emu68_t * const emu68)199 void trapv68(emu68_t * const emu68)
200 {
201 inl_trapv68(emu68);
202 }
203
trap68(emu68_t * const emu68,const int trap_n)204 void trap68(emu68_t * const emu68, const int trap_n)
205 {
206 inl_trap68(emu68, trap_n);
207 }
208
chk68(emu68_t * const emu68,const int68_t a,const int68_t b)209 void chk68(emu68_t * const emu68, const int68_t a, const int68_t b)
210 {
211 inl_chk68(emu68, a, b);
212 }
213
andtosr68(emu68_t * const emu68,int68_t v)214 void andtosr68(emu68_t * const emu68, int68_t v)
215 {
216 inl_andtosr68(emu68, v);
217 }
218
orrtosr68(emu68_t * const emu68,int68_t v)219 void orrtosr68(emu68_t * const emu68, int68_t v)
220 {
221 inl_orrtosr68(emu68, v);
222 }
223
eortosr68(emu68_t * const emu68,int68_t v)224 void eortosr68(emu68_t * const emu68, int68_t v)
225 {
226 inl_eortosr68(emu68, v);
227 }
228
reset68(emu68_t * const emu68)229 void reset68(emu68_t * const emu68)
230 {
231 inl_reset68(emu68);
232 }
233
stop68(emu68_t * const emu68)234 void stop68(emu68_t * const emu68)
235 {
236 inl_stop68(emu68);
237 }
238
239
240 /* ,------------------.
241 | Bit manipulation |
242 `------------------' */
243
244 #include "inl68_bitmanip.h"
245
btst68(emu68_t * const emu68,const int68_t v,const int bit)246 void btst68(emu68_t * const emu68, const int68_t v, const int bit)
247 {
248 inl_btst68(emu68, v, bit);
249 }
250
bset68(emu68_t * const emu68,const int68_t v,const int bit)251 int68_t bset68(emu68_t * const emu68, const int68_t v, const int bit)
252 {
253 return inl_bset68(emu68, v, bit);
254 }
255
bclr68(emu68_t * const emu68,const int68_t v,const int bit)256 int68_t bclr68(emu68_t * const emu68, const int68_t v, const int bit)
257 {
258 return inl_bclr68(emu68, v, bit);
259 }
260
bchg68(emu68_t * const emu68,const int68_t v,const int bit)261 int68_t bchg68(emu68_t * const emu68, const int68_t v, const int bit)
262 {
263 return inl_bchg68(emu68, v, bit);
264 }
265
266
267 /* ,----------------------.
268 | Binary Coded Decimal |
269 `----------------------' */
270
271 #include "inl68_bcd.h"
272
abcd68(emu68_t * const emu68,const int68_t a,int68_t b)273 int68_t abcd68(emu68_t * const emu68, const int68_t a, int68_t b)
274 {
275 return inl_abcd68(emu68, a, b);
276 }
277
sbcd68(emu68_t * const emu68,const int68_t a,int68_t b)278 int68_t sbcd68(emu68_t * const emu68, const int68_t a, int68_t b)
279 {
280 return inl_sbcd68(emu68, a, b);
281 }
282
nbcd68(emu68_t * const emu68,int68_t a)283 int68_t nbcd68(emu68_t * const emu68, int68_t a)
284 {
285 return inl_nbcd68(emu68, a);
286 }
287
288
289 /* ,-----------------.
290 | Program Control |
291 `-----------------' */
292
293 #include "inl68_progctrl.h"
294
rts68(emu68_t * const emu68)295 void rts68(emu68_t * const emu68)
296 {
297 inl_rts68(emu68);
298 }
299
rte68(emu68_t * const emu68)300 void rte68(emu68_t * const emu68)
301 {
302 inl_rte68(emu68);
303 }
304
rtr68(emu68_t * const emu68)305 void rtr68(emu68_t * const emu68)
306 {
307 inl_rtr68(emu68);
308 }
309
bsr68(emu68_t * const emu68,const addr68_t addr)310 void bsr68(emu68_t * const emu68, const addr68_t addr)
311 {
312 inl_bsr68(emu68, addr);
313 }
314
315 #define BCC_TEMPLATE(CC) \
316 static void bcc_##CC(emu68_t * const emu68, const addr68_t addr) { \
317 if (inl_is_cc##CC(REG68.sr)) \
318 REG68.pc = addr; \
319 }
320
bcc_0(emu68_t * const emu68,const addr68_t addr)321 static void bcc_0(emu68_t * const emu68, const addr68_t addr)
322 {
323 REG68.pc = addr;
324 }
325
bcc_1(emu68_t * const emu68,const addr68_t addr)326 static void bcc_1(emu68_t * const emu68, const addr68_t addr)
327 {
328 inl_bsr68(emu68, addr);
329 }
330
331 BCC_TEMPLATE(2)
332 BCC_TEMPLATE(3)
333 BCC_TEMPLATE(4)
334 BCC_TEMPLATE(5)
335 BCC_TEMPLATE(6)
336 BCC_TEMPLATE(7)
337 BCC_TEMPLATE(8)
338 BCC_TEMPLATE(9)
339 BCC_TEMPLATE(A)
340 BCC_TEMPLATE(B)
341 BCC_TEMPLATE(C)
342 BCC_TEMPLATE(D)
343 BCC_TEMPLATE(E)
344 BCC_TEMPLATE(F)
345
346 void (* const bcc68[16])(emu68_t * const, const addr68_t) = {
347 bcc_0, bcc_1, bcc_2, bcc_3, bcc_4, bcc_5, bcc_6, bcc_7,
348 bcc_8, bcc_9, bcc_A, bcc_B, bcc_C, bcc_D, bcc_E, bcc_F
349 };
350
jmp68(emu68_t * const emu68,const addr68_t addr)351 void jmp68(emu68_t * const emu68, const addr68_t addr)
352 {
353 inl_jmp68(emu68, addr);
354 }
355
jsr68(emu68_t * const emu68,const addr68_t addr)356 void jsr68(emu68_t * const emu68, const addr68_t addr)
357 {
358 inl_jsr68(emu68, addr);
359 }
360
nop68(emu68_t * const emu68)361 void nop68(emu68_t * const emu68)
362 {
363 inl_nop68(emu68);
364 }
365
tst68(emu68_t * const emu68,const int68_t a)366 void tst68(emu68_t * const emu68, const int68_t a)
367 {
368 inl_tst68(emu68, a);
369 }
370
tas68(emu68_t * const emu68,const int68_t d)371 int68_t tas68(emu68_t * const emu68, const int68_t d)
372 {
373 return inl_tas68(emu68, d);
374 }
375
376 #define DBCC_TEMPLATE(CC) \
377 static void dbcc_##CC(emu68_t * const emu68, const int dn) { \
378 const uint68_t pc = REG68.pc; \
379 if (!inl_is_cc##CC(REG68.sr)) { \
380 int68_t a = (u16)(REG68.d[dn]-1); \
381 REG68.d[dn] = (REG68.d[dn] & 0xFFFF0000) | a; \
382 if (a != 0xFFFF) { \
383 REG68.pc = pc + get_nextw(); \
384 } else { \
385 REG68.pc = pc + 2; \
386 } \
387 } else { \
388 REG68.pc = pc + 2; \
389 } \
390 }
391
392 DBCC_TEMPLATE(0)
393 DBCC_TEMPLATE(1)
394 DBCC_TEMPLATE(2)
395 DBCC_TEMPLATE(3)
396 DBCC_TEMPLATE(4)
397 DBCC_TEMPLATE(5)
398 DBCC_TEMPLATE(6)
399 DBCC_TEMPLATE(7)
400 DBCC_TEMPLATE(8)
401 DBCC_TEMPLATE(9)
402 DBCC_TEMPLATE(A)
403 DBCC_TEMPLATE(B)
404 DBCC_TEMPLATE(C)
405 DBCC_TEMPLATE(D)
406 DBCC_TEMPLATE(E)
407 DBCC_TEMPLATE(F)
408
409 void (* const dbcc68[])(emu68_t * const, const int) = {
410 dbcc_0, dbcc_1, dbcc_2, dbcc_3, dbcc_4, dbcc_5, dbcc_6, dbcc_7,
411 dbcc_8, dbcc_9, dbcc_A, dbcc_B, dbcc_C, dbcc_D, dbcc_E, dbcc_F
412 };
413
414 #define SCC_TEMPLATE(CC) \
415 static int scc_##CC(emu68_t * const emu68) \
416 { \
417 return (u8) -inl_is_cc##CC(REG68.sr); \
418 }
419
420 SCC_TEMPLATE(0)
421 SCC_TEMPLATE(1)
422 SCC_TEMPLATE(2)
423 SCC_TEMPLATE(3)
424 SCC_TEMPLATE(4)
425 SCC_TEMPLATE(5)
426 SCC_TEMPLATE(6)
427 SCC_TEMPLATE(7)
428 SCC_TEMPLATE(8)
429 SCC_TEMPLATE(9)
430 SCC_TEMPLATE(A)
431 SCC_TEMPLATE(B)
432 SCC_TEMPLATE(C)
433 SCC_TEMPLATE(D)
434 SCC_TEMPLATE(E)
435 SCC_TEMPLATE(F)
436
437 int (* const scc68[])(emu68_t * const) = {
438 scc_0, scc_1, scc_2, scc_3, scc_4, scc_5, scc_6, scc_7,
439 scc_8, scc_9, scc_A, scc_B, scc_C, scc_D, scc_E, scc_F
440 };
441
442 /* ,----------.
443 | Shifting |
444 `----------' */
445
446 #include "inl68_shifting.h"
447
swap68(emu68_t * const emu68,const int dn)448 void swap68(emu68_t * const emu68, const int dn)
449 {
450 inl_swap68(emu68, dn);
451 }
452
lsl68(emu68_t * const emu68,uint68_t d,int s,const int l)453 int68_t lsl68(emu68_t * const emu68, uint68_t d, int s, const int l)
454 {
455 return inl_lsl68(emu68, d, s, l);
456 }
457
lsr68(emu68_t * const emu68,uint68_t d,int s,const int l)458 int68_t lsr68(emu68_t * const emu68, uint68_t d, int s, const int l)
459 {
460 return inl_lsr68(emu68, d, s, l);
461 }
462
asl68(emu68_t * const emu68,int68_t d,int s,const int l)463 int68_t asl68(emu68_t * const emu68, int68_t d, int s, const int l)
464 {
465 return inl_asl68(emu68, d, s, l);
466 }
467
asr68(emu68_t * const emu68,int68_t d,int s,const int l)468 int68_t asr68(emu68_t * const emu68, int68_t d, int s, const int l)
469 {
470 return inl_asr68(emu68, d, s, l);
471 }
472
rol68(emu68_t * const emu68,uint68_t d,int s,const int l)473 int68_t rol68(emu68_t * const emu68, uint68_t d, int s, const int l)
474 {
475 return inl_rol68(emu68, d, s, l);
476 }
477
ror68(emu68_t * const emu68,uint68_t d,int s,const int l)478 int68_t ror68(emu68_t * const emu68, uint68_t d, int s, const int l)
479 {
480 return inl_ror68(emu68, d, s, l);
481 }
482
roxl68(emu68_t * const emu68,uint68_t d,int s,const int l)483 int68_t roxl68(emu68_t * const emu68, uint68_t d, int s, const int l)
484 {
485 return inl_roxl68(emu68, d, s, l);
486 }
487
roxr68(emu68_t * const emu68,uint68_t d,int s,const int l)488 int68_t roxr68(emu68_t * const emu68, uint68_t d, int s, const int l)
489 {
490 return inl_roxr68(emu68, d, s, l);
491 }
492
493 /* ,-----------.
494 | Data Move |
495 `-----------' */
496
497 #include "inl68_datamove.h"
498
exg68(emu68_t * const emu68,const int reg0,const int reg9)499 void exg68(emu68_t * const emu68, const int reg0, const int reg9)
500 {
501 inl_exg68(emu68, reg0, reg9);
502 }
503
lea68(emu68_t * const emu68,const int mode,const int reg)504 addr68_t lea68(emu68_t * const emu68, const int mode, const int reg)
505 {
506 return inl_lea68(emu68, mode, reg);
507 }
508
pea68(emu68_t * const emu68,const int mode,const int reg)509 addr68_t pea68(emu68_t * const emu68, const int mode, const int reg)
510 {
511 return inl_pea68(emu68, mode, reg);
512 }
513
link68(emu68_t * const emu68,const int reg)514 void link68(emu68_t * const emu68, const int reg)
515 {
516 inl_link68(emu68, reg);
517 }
518
unlk68(emu68_t * const emu68,const int reg)519 void unlk68(emu68_t * const emu68, const int reg)
520 {
521 inl_unlk68(emu68, reg);
522 }
523