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