1 /***************************************************************************
2
3 TMS34010: Portable Texas Instruments TMS34010 emulator
4
5 Copyright Alex Pasadyn/Zsolt Vasvari
6 Parts based on code by Aaron Giles
7
8 ***************************************************************************/
9
10 /* Combine two 32-bit integers into a 64-bit integer */
11 #define COMBINE_64_32_32(A,B) ((((UINT64)(A))<<32) | (UINT32)(B))
12 #define COMBINE_U64_U32_U32(A,B) COMBINE_64_32_32(A,B)
13 #define DIV_64_64_32(A,B) ((A)/(B))
14 #define DIV_U64_U64_U32(A,B) ((A)/(UINT32)(B))
15 #define MOD_32_64_32(A,B) ((A)%(B))
16 #define MOD_U32_U64_U32(A,B) ((A)%(UINT32)(B))
17 #define HI32_32_64(A) (((UINT64)(A)) >> 32)
18 #define HI32_U32_U64(A) HI32_32_64(A)
19 #define LO32_32_64(A) ((A) & 0xffffffff)
20 #define LO32_U32_U64(A) LO32_32_64(A)
21 #define MUL_64_32_32(A,B) ((A)*(INT64)(B))
22 #define MUL_U64_U32_U32(A,B) ((A)*(UINT64)(UINT32)(B))
23
24
25 /***************************************************************************
26 MISC MACROS
27 ***************************************************************************/
28
29 #define ZEXTEND(val,width) if (width) (val) &= ((UINT32)0xffffffff >> (32 - (width)))
30 #define SEXTEND(val,width) if (width) (val) = (INT32)((val) << (32 - (width))) >> (32 - (width))
31
32 #define SXYTOL(val) ((((INT16)(val).y * state.convsp) + ((INT16)(val).x << state.pixelshift)) + OFFSET)
33 #define DXYTOL(val) ((((INT16)(val).y * state.convdp) + ((INT16)(val).x << state.pixelshift)) + OFFSET)
34 #define MXYTOL(val) ((((INT16)(val).y * state.convmp) + ((INT16)(val).x << state.pixelshift)) + OFFSET)
35
36 #define COUNT_CYCLES(x) do { tms34010_ICount -= x; check_timer(x); } while (0)
37 #define COUNT_UNKNOWN_CYCLES(x) COUNT_CYCLES(x)
38
39 #define CORRECT_ODD_PC(x) do { if (PC & 0x0f) logerror("%s to PC=%08X\n", x, PC); PC &= ~0x0f; } while (0)
40
41
42
43 /***************************************************************************
44 FLAG HANDLING MACROS
45 ***************************************************************************/
46
47 #define SIGN(val) ((val) & 0x80000000)
48
49 #define CLR_Z state.st &= ~STBIT_Z
50 #define CLR_V state.st &= ~STBIT_V
51 #define CLR_C state.st &= ~STBIT_C
52 #define CLR_N state.st &= ~STBIT_N
53 #define CLR_NZ state.st &= ~(STBIT_N | STBIT_Z)
54 #define CLR_CZ state.st &= ~(STBIT_C | STBIT_Z)
55 #define CLR_ZV state.st &= ~(STBIT_Z | STBIT_V)
56 #define CLR_NZV state.st &= ~(STBIT_N | STBIT_Z | STBIT_V)
57 #define CLR_NCZ state.st &= ~(STBIT_N | STBIT_C | STBIT_Z)
58 #define CLR_NCZV state.st &= ~(STBIT_N | STBIT_C | STBIT_Z | STBIT_V)
59
60 #define SET_V_BIT_LO(val,bit) state.st |= ((val) << (28 - (bit))) & STBIT_V
61 #define SET_V_BIT_HI(val,bit) state.st |= ((val) >> ((bit) - 28)) & STBIT_V
62 #define SET_V_LOG(val) state.st |= (val) << 28
63 #define SET_Z_BIT_LO(val,bit) state.st |= ((val) << (29 - (bit))) & STBIT_Z
64 #define SET_Z_BIT_HI(val,bit) state.st |= ((val) >> ((bit) - 29)) & STBIT_Z
65 #define SET_Z_LOG(val) state.st |= (val) << 29
66 #define SET_C_BIT_LO(val,bit) state.st |= ((val) << (30 - (bit))) & STBIT_C
67 #define SET_C_BIT_HI(val,bit) state.st |= ((val) >> ((bit) - 30)) & STBIT_C
68 #define SET_C_LOG(val) state.st |= (val) << 30
69 #define SET_N_BIT(val,bit) state.st |= ((val) << (31 - (bit))) & STBIT_N
70 #define SET_N_LOG(val) state.st |= (val) << 31
71
72 #define SET_Z_VAL(val) SET_Z_LOG((val) == 0)
73 #define SET_N_VAL(val) SET_N_BIT(val, 31)
74 #define SET_NZ_VAL(val) SET_Z_VAL(val); SET_N_VAL(val)
75 #define SET_V_SUB(a,b,r) SET_V_BIT_HI(((a) ^ (b)) & ((a) ^ (r)), 31)
76 #define SET_V_ADD(a,b,r) SET_V_BIT_HI(~((a) ^ (b)) & ((a) ^ (r)), 31)
77 #define SET_C_SUB(a,b) SET_C_LOG((UINT32)(b) > (UINT32)(a))
78 #define SET_C_ADD(a,b) SET_C_LOG((UINT32)~(a) < (UINT32)(b))
79 #define SET_NZV_SUB(a,b,r) SET_NZ_VAL(r); SET_V_SUB(a,b,r)
80 #define SET_NZCV_SUB(a,b,r) SET_NZV_SUB(a,b,r); SET_C_SUB(a,b)
81 #define SET_NZCV_ADD(a,b,r) SET_NZ_VAL(r); SET_V_ADD(a,b,r); SET_C_ADD(a,b)
82
83 static const UINT8 fw_inc[32] = { 32,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 };
84
85
86 /***************************************************************************
87 UNIMPLEMENTED INSTRUCTION
88 ***************************************************************************/
89
unimpl(void)90 static void unimpl(void)
91 {
92 bprintf(0, _T("CPU: %d unimpl @ %x\n"), TMS34010GetActive(), TMS34010GetPC());
93 #if 1
94 /* kludge for Super High Impact -- this doesn't seem to cause */
95 /* an illegal opcode exception */
96 if (cpu_readop16(TOBYTE(PC - 0x10)) == 0x0007)
97 return;
98
99 /* 9 Ball Shootout calls to FFDF7468, expecting it */
100 /* to execute the next instruction from FFDF7470 */
101 /* but the instruction at FFDF7460 is an 0x0001 */
102 if (cpu_readop16(TOBYTE(PC - 0x10)) == 0x0001)
103 return;
104
105 PUSH(PC);
106 PUSH(GET_ST());
107 RESET_ST();
108 PC = RLONG(0xfffffc20);
109 change_pc(TOBYTE(PC));
110 COUNT_UNKNOWN_CYCLES(16);
111
112 /* extra check to prevent bad things */
113 if (PC == 0 || opcode_table[cpu_readop16(TOBYTE(PC)) >> 4] == unimpl)
114 {
115 // cpunum_set_input_line(state.screen->machine, cpu_getactivecpu(), INPUT_LINE_HALT, ASSERT_LINE);
116 // debugger_break(state.screen->machine);
117 bprintf(0, _T("unimpl halts?\n"));
118 }
119 #endif
120 }
121
122
123
124 /***************************************************************************
125 X/Y OPERATIONS
126 ***************************************************************************/
127
128 #define ADD_XY(R) \
129 { \
130 XY a = R##REG_XY(SRCREG); \
131 XY *b = &R##REG_XY(DSTREG); \
132 CLR_NCZV; \
133 b->x += a.x; \
134 b->y += a.y; \
135 SET_N_LOG(b->x == 0); \
136 SET_C_BIT_LO(b->y, 15); \
137 SET_Z_LOG(b->y == 0); \
138 SET_V_BIT_LO(b->x, 15); \
139 COUNT_CYCLES(1); \
140 }
add_xy_a(void)141 static void add_xy_a(void) { ADD_XY(A); }
add_xy_b(void)142 static void add_xy_b(void) { ADD_XY(B); }
143
144 #define SUB_XY(R) \
145 { \
146 XY a = R##REG_XY(SRCREG); \
147 XY *b = &R##REG_XY(DSTREG); \
148 CLR_NCZV; \
149 SET_N_LOG(a.x == b->x); \
150 SET_C_LOG(a.y > b->y); \
151 SET_Z_LOG(a.y == b->y); \
152 SET_V_LOG(a.x > b->x); \
153 b->x -= a.x; \
154 b->y -= a.y; \
155 COUNT_CYCLES(1); \
156 }
sub_xy_a(void)157 static void sub_xy_a(void) { SUB_XY(A); }
sub_xy_b(void)158 static void sub_xy_b(void) { SUB_XY(B); }
159
160 #define CMP_XY(R) \
161 { \
162 INT16 res; \
163 XY a = R##REG_XY(DSTREG); \
164 XY b = R##REG_XY(SRCREG); \
165 CLR_NCZV; \
166 res = a.x-b.x; \
167 SET_N_LOG(res == 0); \
168 SET_V_BIT_LO(res, 15); \
169 res = a.y-b.y; \
170 SET_Z_LOG(res == 0); \
171 SET_C_BIT_LO(res, 15); \
172 COUNT_CYCLES(1); \
173 }
cmp_xy_a(void)174 static void cmp_xy_a(void) { CMP_XY(A); }
cmp_xy_b(void)175 static void cmp_xy_b(void) { CMP_XY(B); }
176
177 #define CPW(R) \
178 { \
179 INT32 res = 0; \
180 INT16 x = R##REG_X(SRCREG); \
181 INT16 y = R##REG_Y(SRCREG); \
182 \
183 CLR_V; \
184 res |= ((WSTART_X > x) ? 0x20 : 0); \
185 res |= ((x > WEND_X) ? 0x40 : 0); \
186 res |= ((WSTART_Y > y) ? 0x80 : 0); \
187 res |= ((y > WEND_Y) ? 0x100 : 0); \
188 R##REG(DSTREG) = res; \
189 SET_V_LOG(res != 0); \
190 COUNT_CYCLES(1); \
191 }
cpw_a(void)192 static void cpw_a(void) { CPW(A); }
cpw_b(void)193 static void cpw_b(void) { CPW(B); }
194
195 #define CVXYL(R) \
196 { \
197 R##REG(DSTREG) = DXYTOL(R##REG_XY(SRCREG)); \
198 COUNT_CYCLES(3); \
199 }
cvxyl_a(void)200 static void cvxyl_a(void) { CVXYL(A); }
cvxyl_b(void)201 static void cvxyl_b(void) { CVXYL(B); }
202
203 #define MOVX(R) \
204 { \
205 R##REG(DSTREG) = (R##REG(DSTREG) & 0xffff0000) | (UINT16)R##REG(SRCREG); \
206 COUNT_CYCLES(1); \
207 }
movx_a(void)208 static void movx_a(void) { MOVX(A); }
movx_b(void)209 static void movx_b(void) { MOVX(B); }
210
211 #define MOVY(R) \
212 { \
213 R##REG(DSTREG) = (R##REG(SRCREG) & 0xffff0000) | (UINT16)R##REG(DSTREG); \
214 COUNT_CYCLES(1); \
215 }
movy_a(void)216 static void movy_a(void) { MOVY(A); }
movy_b(void)217 static void movy_b(void) { MOVY(B); }
218
219
220
221 /***************************************************************************
222 PIXEL TRANSFER OPERATIONS
223 ***************************************************************************/
224
225 #define PIXT_RI(R) \
226 { \
227 WPIXEL(R##REG(DSTREG),R##REG(SRCREG)); \
228 COUNT_UNKNOWN_CYCLES(2); \
229 }
pixt_ri_a(void)230 static void pixt_ri_a(void) { PIXT_RI(A); }
pixt_ri_b(void)231 static void pixt_ri_b(void) { PIXT_RI(B); }
232
233 #define PIXT_RIXY(R) \
234 { \
235 if (WINDOW_CHECKING != 0) \
236 { \
237 CLR_V; \
238 if (R##REG_X(DSTREG) < WSTART_X || R##REG_X(DSTREG) > WEND_X || \
239 R##REG_Y(DSTREG) < WSTART_Y || R##REG_Y(DSTREG) > WEND_Y) \
240 { \
241 SET_V_LOG(1); \
242 goto skip; \
243 } \
244 if (WINDOW_CHECKING == 1) goto skip; \
245 } \
246 WPIXEL(DXYTOL(R##REG_XY(DSTREG)),R##REG(SRCREG)); \
247 skip: \
248 COUNT_UNKNOWN_CYCLES(4); \
249 }
pixt_rixy_a(void)250 static void pixt_rixy_a(void) { PIXT_RIXY(A); }
pixt_rixy_b(void)251 static void pixt_rixy_b(void) { PIXT_RIXY(B); }
252
253 #define PIXT_IR(R) \
254 { \
255 INT32 temp = RPIXEL(R##REG(SRCREG)); \
256 CLR_V; \
257 R##REG(DSTREG) = temp; \
258 SET_V_LOG(temp != 0); \
259 COUNT_CYCLES(4); \
260 }
pixt_ir_a(void)261 static void pixt_ir_a(void) { PIXT_IR(A); }
pixt_ir_b(void)262 static void pixt_ir_b(void) { PIXT_IR(B); }
263
264 #define PIXT_II(R) \
265 { \
266 WPIXEL(R##REG(DSTREG),RPIXEL(R##REG(SRCREG))); \
267 COUNT_UNKNOWN_CYCLES(4); \
268 }
pixt_ii_a(void)269 static void pixt_ii_a(void) { PIXT_II(A); }
pixt_ii_b(void)270 static void pixt_ii_b(void) { PIXT_II(B); }
271
272 #define PIXT_IXYR(R) \
273 { \
274 INT32 temp = RPIXEL(SXYTOL(R##REG_XY(SRCREG))); \
275 CLR_V; \
276 R##REG(DSTREG) = temp; \
277 SET_V_LOG(temp != 0); \
278 COUNT_CYCLES(6); \
279 }
pixt_ixyr_a(void)280 static void pixt_ixyr_a(void) { PIXT_IXYR(A); }
pixt_ixyr_b(void)281 static void pixt_ixyr_b(void) { PIXT_IXYR(B); }
282
283 #define PIXT_IXYIXY(R) \
284 { \
285 if (WINDOW_CHECKING != 0) \
286 { \
287 CLR_V; \
288 if (R##REG_X(DSTREG) < WSTART_X || R##REG_X(DSTREG) > WEND_X || \
289 R##REG_Y(DSTREG) < WSTART_Y || R##REG_Y(DSTREG) > WEND_Y) \
290 { \
291 SET_V_LOG(1); \
292 goto skip; \
293 } \
294 if (WINDOW_CHECKING == 1) goto skip; \
295 } \
296 WPIXEL(DXYTOL(R##REG_XY(DSTREG)),RPIXEL(SXYTOL(R##REG_XY(SRCREG)))); \
297 skip: \
298 COUNT_UNKNOWN_CYCLES(7); \
299 }
pixt_ixyixy_a(void)300 static void pixt_ixyixy_a(void) { PIXT_IXYIXY(A); }
pixt_ixyixy_b(void)301 static void pixt_ixyixy_b(void) { PIXT_IXYIXY(B); }
302
303 #define DRAV(R) \
304 { \
305 if (WINDOW_CHECKING != 0) \
306 { \
307 CLR_V; \
308 if (R##REG_X(DSTREG) < WSTART_X || R##REG_X(DSTREG) > WEND_X || \
309 R##REG_Y(DSTREG) < WSTART_Y || R##REG_Y(DSTREG) > WEND_Y) \
310 { \
311 SET_V_LOG(1); \
312 goto skip; \
313 } \
314 if (WINDOW_CHECKING == 1) goto skip; \
315 } \
316 WPIXEL(DXYTOL(R##REG_XY(DSTREG)),COLOR1); \
317 skip: \
318 R##REG_X(DSTREG) += R##REG_X(SRCREG); \
319 R##REG_Y(DSTREG) += R##REG_Y(SRCREG); \
320 COUNT_UNKNOWN_CYCLES(4); \
321 }
drav_a(void)322 static void drav_a(void) { DRAV(A); }
drav_b(void)323 static void drav_b(void) { DRAV(B); }
324
325
326
327 /***************************************************************************
328 ARITHMETIC OPERATIONS
329 ***************************************************************************/
330
331 #define ABS(R) \
332 { \
333 INT32 *rd = &R##REG(DSTREG); \
334 INT32 r = 0 - *rd; \
335 CLR_NZV; \
336 if (r > 0) *rd = r; \
337 SET_NZ_VAL(r); \
338 SET_V_LOG(r == (INT32)0x80000000); \
339 COUNT_CYCLES(1); \
340 }
abs_a(void)341 static void abs_a(void) { ABS(A); }
abs_b(void)342 static void abs_b(void) { ABS(B); }
343
344 #define ADD(R) \
345 { \
346 INT32 a = R##REG(SRCREG); \
347 INT32 *rd = &R##REG(DSTREG); \
348 INT32 b = *rd; \
349 INT32 r = a + b; \
350 CLR_NCZV; \
351 *rd = r; \
352 SET_NZCV_ADD(a,b,r); \
353 COUNT_CYCLES(1); \
354 }
add_a(void)355 static void add_a(void) { ADD(A); }
add_b(void)356 static void add_b(void) { ADD(B); }
357
358 #define ADDC(R) \
359 { \
360 /* I'm not sure to which side the carry is added to, should */ \
361 /* verify it against the examples */ \
362 INT32 a = R##REG(SRCREG); \
363 INT32 *rd = &R##REG(DSTREG); \
364 INT32 b = *rd; \
365 INT32 r = a + b + (C_FLAG ? 1 : 0); \
366 CLR_NCZV; \
367 *rd = r; \
368 SET_NZCV_ADD(a,b,r); \
369 COUNT_CYCLES(1); \
370 }
addc_a(void)371 static void addc_a(void) { ADDC(A); }
addc_b(void)372 static void addc_b(void) { ADDC(B); }
373
374 #define ADDI_W(R) \
375 { \
376 INT32 a = PARAM_WORD(); \
377 INT32 *rd = &R##REG(DSTREG); \
378 INT32 b = *rd; \
379 INT32 r = a + b; \
380 CLR_NCZV; \
381 *rd = r; \
382 SET_NZCV_ADD(a,b,r); \
383 COUNT_CYCLES(2); \
384 }
addi_w_a(void)385 static void addi_w_a(void) { ADDI_W(A); }
addi_w_b(void)386 static void addi_w_b(void) { ADDI_W(B); }
387
388 #define ADDI_L(R) \
389 { \
390 INT32 a = PARAM_LONG(); \
391 INT32 *rd = &R##REG(DSTREG); \
392 INT32 b = *rd; \
393 INT32 r = a + b; \
394 CLR_NCZV; \
395 *rd = r; \
396 SET_NZCV_ADD(a,b,r); \
397 COUNT_CYCLES(3); \
398 }
addi_l_a(void)399 static void addi_l_a(void) { ADDI_L(A); }
addi_l_b(void)400 static void addi_l_b(void) { ADDI_L(B); }
401
402 #define ADDK(R) \
403 { \
404 INT32 a = fw_inc[PARAM_K]; \
405 INT32 *rd = &R##REG(DSTREG); \
406 INT32 b = *rd; \
407 INT32 r = a + b; \
408 CLR_NCZV; \
409 *rd = r; \
410 SET_NZCV_ADD(a,b,r); \
411 COUNT_CYCLES(1); \
412 }
addk_a(void)413 static void addk_a(void) { ADDK(A); }
addk_b(void)414 static void addk_b(void) { ADDK(B); }
415
416 #define AND(R) \
417 { \
418 INT32 *rd = &R##REG(DSTREG); \
419 CLR_Z; \
420 *rd &= R##REG(SRCREG); \
421 SET_Z_VAL(*rd); \
422 COUNT_CYCLES(1); \
423 }
and_a(void)424 static void and_a(void) { AND(A); }
and_b(void)425 static void and_b(void) { AND(B); }
426
427 #define ANDI(R) \
428 { \
429 INT32 *rd = &R##REG(DSTREG); \
430 CLR_Z; \
431 *rd &= ~PARAM_LONG(); \
432 SET_Z_VAL(*rd); \
433 COUNT_CYCLES(3); \
434 }
andi_a(void)435 static void andi_a(void) { ANDI(A); }
andi_b(void)436 static void andi_b(void) { ANDI(B); }
437
438 #define ANDN(R) \
439 { \
440 INT32 *rd = &R##REG(DSTREG); \
441 CLR_Z; \
442 *rd &= ~R##REG(SRCREG); \
443 SET_Z_VAL(*rd); \
444 COUNT_CYCLES(1); \
445 }
andn_a(void)446 static void andn_a(void) { ANDN(A); }
andn_b(void)447 static void andn_b(void) { ANDN(B); }
448
449 #define BTST_K(R) \
450 { \
451 int bit = 31 - PARAM_K; \
452 CLR_Z; \
453 if (bit <= 29) \
454 SET_Z_BIT_LO(~R##REG(DSTREG), bit); \
455 else \
456 SET_Z_BIT_HI(~R##REG(DSTREG), bit); \
457 COUNT_CYCLES(1); \
458 }
btst_k_a(void)459 static void btst_k_a(void) { BTST_K(A); }
btst_k_b(void)460 static void btst_k_b(void) { BTST_K(B); }
461
462 #define BTST_R(R) \
463 { \
464 int bit = R##REG(SRCREG) & 0x1f; \
465 CLR_Z; \
466 if (bit <= 29) \
467 SET_Z_BIT_LO(~R##REG(DSTREG), bit); \
468 else \
469 SET_Z_BIT_HI(~R##REG(DSTREG), bit); \
470 COUNT_CYCLES(2); \
471 }
btst_r_a(void)472 static void btst_r_a(void) { BTST_R(A); }
btst_r_b(void)473 static void btst_r_b(void) { BTST_R(B); }
474
clrc(void)475 static void clrc(void)
476 {
477 CLR_C;
478 COUNT_CYCLES(1);
479 }
480
481 #define CMP(R) \
482 { \
483 INT32 *rs = &R##REG(SRCREG); \
484 INT32 *rd = &R##REG(DSTREG); \
485 INT32 r = *rd - *rs; \
486 CLR_NCZV; \
487 SET_NZCV_SUB(*rd,*rs,r); \
488 COUNT_CYCLES(1); \
489 }
cmp_a(void)490 static void cmp_a(void) { CMP(A); }
cmp_b(void)491 static void cmp_b(void) { CMP(B); }
492
493 #define CMPI_W(R) \
494 { \
495 INT32 *rd = &R##REG(DSTREG); \
496 INT32 t = (INT16)~PARAM_WORD(); \
497 INT32 r = *rd - t; \
498 CLR_NCZV; \
499 SET_NZCV_SUB(*rd,t,r); \
500 COUNT_CYCLES(2); \
501 }
cmpi_w_a(void)502 static void cmpi_w_a(void) { CMPI_W(A); }
cmpi_w_b(void)503 static void cmpi_w_b(void) { CMPI_W(B); }
504
505 #define CMPI_L(R) \
506 { \
507 INT32 *rd = &R##REG(DSTREG); \
508 INT32 t = ~PARAM_LONG(); \
509 INT32 r = *rd - t; \
510 CLR_NCZV; \
511 SET_NZCV_SUB(*rd,t,r); \
512 COUNT_CYCLES(3); \
513 }
cmpi_l_a(void)514 static void cmpi_l_a(void) { CMPI_L(A); }
cmpi_l_b(void)515 static void cmpi_l_b(void) { CMPI_L(B); }
516
dint(void)517 static void dint(void)
518 {
519 state.st &= ~STBIT_IE;
520 COUNT_CYCLES(3);
521 }
522
523 #define DIVS(R) \
524 { \
525 INT32 *rs = &R##REG(SRCREG); \
526 INT32 *rd1 = &R##REG(DSTREG); \
527 CLR_NZV; \
528 if (!(DSTREG & 1)) \
529 { \
530 if (!*rs) \
531 { \
532 SET_V_LOG(1); \
533 } \
534 else \
535 { \
536 INT32 *rd2 = &R##REG(DSTREG+1); \
537 INT64 dividend = COMBINE_64_32_32(*rd1, *rd2); \
538 INT64 quotient = DIV_64_64_32(dividend, *rs); \
539 INT32 remainder = MOD_32_64_32(dividend, *rs); \
540 UINT32 signbits = (INT32)quotient >> 31; \
541 if (HI32_32_64(quotient) != signbits) \
542 { \
543 SET_V_LOG(1); \
544 } \
545 else \
546 { \
547 *rd1 = quotient; \
548 *rd2 = remainder; \
549 SET_NZ_VAL(*rd1); \
550 } \
551 } \
552 COUNT_CYCLES(40); \
553 } \
554 else \
555 { \
556 if (!*rs) \
557 { \
558 SET_V_LOG(1); \
559 } \
560 else \
561 { \
562 *rd1 /= *rs; \
563 SET_NZ_VAL(*rd1); \
564 } \
565 COUNT_CYCLES(39); \
566 } \
567 }
divs_a(void)568 static void divs_a(void) { DIVS(A); }
divs_b(void)569 static void divs_b(void) { DIVS(B); }
570
571 #define DIVU(R) \
572 { \
573 INT32 *rs = &R##REG(SRCREG); \
574 INT32 *rd1 = &R##REG(DSTREG); \
575 CLR_ZV; \
576 if (!(DSTREG & 1)) \
577 { \
578 if (!*rs) \
579 { \
580 SET_V_LOG(1); \
581 } \
582 else \
583 { \
584 INT32 *rd2 = &R##REG(DSTREG+1); \
585 UINT64 dividend = COMBINE_U64_U32_U32(*rd1, *rd2); \
586 UINT64 quotient = DIV_U64_U64_U32(dividend, *rs); \
587 UINT32 remainder = MOD_U32_U64_U32(dividend, *rs); \
588 if (HI32_U32_U64(quotient) != 0) \
589 { \
590 SET_V_LOG(1); \
591 } \
592 else \
593 { \
594 *rd1 = quotient; \
595 *rd2 = remainder; \
596 SET_Z_VAL(*rd1); \
597 } \
598 } \
599 } \
600 else \
601 { \
602 if (!*rs) \
603 { \
604 SET_V_LOG(1); \
605 } \
606 else \
607 { \
608 *rd1 = (UINT32)*rd1 / (UINT32)*rs; \
609 SET_Z_VAL(*rd1); \
610 } \
611 } \
612 COUNT_CYCLES(37); \
613 }
divu_a(void)614 static void divu_a(void) { DIVU(A); }
divu_b(void)615 static void divu_b(void) { DIVU(B); }
616
eint(void)617 static void eint(void)
618 {
619 state.st |= STBIT_IE;
620 check_interrupt();
621 COUNT_CYCLES(3);
622 }
623
624 #define EXGF(F,R) \
625 { \
626 UINT8 shift = F ? 6 : 0; \
627 INT32 *rd = &R##REG(DSTREG); \
628 UINT32 temp = (state.st >> shift) & 0x3f; \
629 state.st &= ~(0x3f << shift); \
630 state.st |= (*rd & 0x3f) << shift; \
631 *rd = temp; \
632 COUNT_CYCLES(1); \
633 }
exgf0_a(void)634 static void exgf0_a(void) { EXGF(0,A); }
exgf0_b(void)635 static void exgf0_b(void) { EXGF(0,B); }
exgf1_a(void)636 static void exgf1_a(void) { EXGF(1,A); }
exgf1_b(void)637 static void exgf1_b(void) { EXGF(1,B); }
638
639 #define LMO(R) \
640 { \
641 UINT32 res = 0; \
642 UINT32 rs = R##REG(SRCREG); \
643 INT32 *rd = &R##REG(DSTREG); \
644 CLR_Z; \
645 SET_Z_VAL(rs); \
646 if (rs) \
647 { \
648 while (!(rs & 0x80000000)) \
649 { \
650 res++; \
651 rs <<= 1; \
652 } \
653 } \
654 *rd = res; \
655 COUNT_CYCLES(1); \
656 }
lmo_a(void)657 static void lmo_a(void) { LMO(A); }
lmo_b(void)658 static void lmo_b(void) { LMO(B); }
659
660 #define MMFM(R) \
661 { \
662 INT32 i; \
663 UINT16 l = (UINT16) PARAM_WORD(); \
664 COUNT_CYCLES(3); \
665 { \
666 INT32 rd = DSTREG; \
667 for (i = 15; i >= 0 ; i--) \
668 { \
669 if (l & 0x8000) \
670 { \
671 R##REG(i) = RLONG(R##REG(rd)); \
672 R##REG(rd) += 0x20; \
673 COUNT_CYCLES(4); \
674 } \
675 l <<= 1; \
676 } \
677 } \
678 }
mmfm_a(void)679 static void mmfm_a(void) { MMFM(A); }
mmfm_b(void)680 static void mmfm_b(void) { MMFM(B); }
681
682 #define MMTM(R) \
683 { \
684 UINT32 i; \
685 UINT16 l = (UINT16) PARAM_WORD(); \
686 COUNT_CYCLES(2); \
687 { \
688 INT32 rd = DSTREG; \
689 if (state.is_34020) \
690 { \
691 CLR_N; \
692 SET_N_VAL(R##REG(rd) ^ 0x80000000); \
693 } \
694 for (i = 0; i < 16; i++) \
695 { \
696 if (l & 0x8000) \
697 { \
698 R##REG(rd) -= 0x20; \
699 WLONG(R##REG(rd),R##REG(i)); \
700 COUNT_CYCLES(4); \
701 } \
702 l <<= 1; \
703 } \
704 } \
705 }
mmtm_a(void)706 static void mmtm_a(void) { MMTM(A); }
mmtm_b(void)707 static void mmtm_b(void) { MMTM(B); }
708
709 #define MODS(R) \
710 { \
711 INT32 *rs = &R##REG(SRCREG); \
712 INT32 *rd = &R##REG(DSTREG); \
713 CLR_NZV; \
714 if (*rs != 0) \
715 { \
716 *rd %= *rs; \
717 SET_NZ_VAL(*rd); \
718 } \
719 else \
720 SET_V_LOG(1); \
721 COUNT_CYCLES(40); \
722 }
mods_a(void)723 static void mods_a(void) { MODS(A); }
mods_b(void)724 static void mods_b(void) { MODS(B); }
725
726 #define MODU(R) \
727 { \
728 INT32 *rs = &R##REG(SRCREG); \
729 INT32 *rd = &R##REG(DSTREG); \
730 CLR_ZV; \
731 if (*rs != 0) \
732 { \
733 *rd = (UINT32)*rd % (UINT32)*rs; \
734 SET_Z_VAL(*rd); \
735 } \
736 else \
737 SET_V_LOG(1); \
738 COUNT_CYCLES(35); \
739 }
modu_a(void)740 static void modu_a(void) { MODU(A); }
modu_b(void)741 static void modu_b(void) { MODU(B); }
742
743 #define MPYS(R) \
744 { \
745 INT32 *rd1 = &R##REG(DSTREG); \
746 INT32 m1 = R##REG(SRCREG); \
747 INT64 product; \
748 \
749 SEXTEND(m1, FW(1)); \
750 CLR_NZ; \
751 product = MUL_64_32_32(m1, *rd1); \
752 SET_Z_LOG(product == 0); \
753 SET_N_BIT(product >> 32, 31); \
754 \
755 *rd1 = HI32_32_64(product); \
756 R##REG(DSTREG|1) = LO32_32_64(product); \
757 \
758 COUNT_CYCLES(20); \
759 }
mpys_a(void)760 static void mpys_a(void) { MPYS(A); }
mpys_b(void)761 static void mpys_b(void) { MPYS(B); }
762
763 #define MPYU(R) \
764 { \
765 INT32 *rd1 = &R##REG(DSTREG); \
766 UINT32 m1 = R##REG(SRCREG); \
767 UINT64 product; \
768 \
769 ZEXTEND(m1, FW(1)); \
770 CLR_Z; \
771 product = MUL_U64_U32_U32(m1, *rd1); \
772 SET_Z_LOG(product == 0); \
773 \
774 *rd1 = HI32_32_64(product); \
775 R##REG(DSTREG|1) = LO32_32_64(product); \
776 \
777 COUNT_CYCLES(21); \
778 }
mpyu_a(void)779 static void mpyu_a(void) { MPYU(A); }
mpyu_b(void)780 static void mpyu_b(void) { MPYU(B); }
781
782 #define NEG(R) \
783 { \
784 INT32 *rd = &R##REG(DSTREG); \
785 INT32 r = 0 - *rd; \
786 CLR_NCZV; \
787 SET_NZCV_SUB(0,*rd,r); \
788 *rd = r; \
789 COUNT_CYCLES(1); \
790 }
neg_a(void)791 static void neg_a(void) { NEG(A); }
neg_b(void)792 static void neg_b(void) { NEG(B); }
793
794 #define NEGB(R) \
795 { \
796 INT32 *rd = &R##REG(DSTREG); \
797 INT32 t = *rd + (C_FLAG ? 1 : 0); \
798 INT32 r = 0 - t; \
799 CLR_NCZV; \
800 SET_NZCV_SUB(0,t,r); \
801 *rd = r; \
802 COUNT_CYCLES(1); \
803 }
negb_a(void)804 static void negb_a(void) { NEGB(A); }
negb_b(void)805 static void negb_b(void) { NEGB(B); }
806
nop(void)807 static void nop(void)
808 {
809 COUNT_CYCLES(1);
810 }
811
812 #define NOT(R) \
813 { \
814 INT32 *rd = &R##REG(DSTREG); \
815 CLR_Z; \
816 *rd = ~(*rd); \
817 SET_Z_VAL(*rd); \
818 COUNT_CYCLES(1); \
819 }
not_a(void)820 static void not_a(void) { NOT(A); }
not_b(void)821 static void not_b(void) { NOT(B); }
822
823 #define OR(R) \
824 { \
825 INT32 *rd = &R##REG(DSTREG); \
826 CLR_Z; \
827 *rd |= R##REG(SRCREG); \
828 SET_Z_VAL(*rd); \
829 COUNT_CYCLES(1); \
830 }
or_a(void)831 static void or_a(void) { OR(A); }
or_b(void)832 static void or_b(void) { OR(B); }
833
834 #define ORI(R) \
835 { \
836 INT32 *rd = &R##REG(DSTREG); \
837 CLR_Z; \
838 *rd |= PARAM_LONG(); \
839 SET_Z_VAL(*rd); \
840 COUNT_CYCLES(3); \
841 }
ori_a(void)842 static void ori_a(void) { ORI(A); }
ori_b(void)843 static void ori_b(void) { ORI(B); }
844
setc(void)845 static void setc(void)
846 {
847 SET_C_LOG(1);
848 COUNT_CYCLES(1);
849 }
850
851 #define SETF(F) \
852 { \
853 UINT8 shift = F ? 6 : 0; \
854 state.st &= ~(0x3f << shift); \
855 state.st |= (state.op & 0x3f) << shift; \
856 COUNT_CYCLES(1+F); \
857 }
setf0(void)858 static void setf0(void) { SETF(0); }
setf1(void)859 static void setf1(void) { SETF(1); }
860
861 #define SEXT(F,R) \
862 { \
863 INT32 *rd = &R##REG(DSTREG); \
864 CLR_NZ; \
865 SEXTEND(*rd,FW(F)); \
866 SET_NZ_VAL(*rd); \
867 COUNT_CYCLES(3); \
868 }
sext0_a(void)869 static void sext0_a(void) { SEXT(0,A); }
sext0_b(void)870 static void sext0_b(void) { SEXT(0,B); }
sext1_a(void)871 static void sext1_a(void) { SEXT(1,A); }
sext1_b(void)872 static void sext1_b(void) { SEXT(1,B); }
873
874 #define RL(R,K) \
875 { \
876 INT32 *rd = &R##REG(DSTREG); \
877 INT32 res = *rd; \
878 INT32 k = (K); \
879 CLR_CZ; \
880 if (k) \
881 { \
882 res<<=(k-1); \
883 SET_C_BIT_HI(res, 31); \
884 res<<=1; \
885 res |= (((UINT32)*rd)>>((-k)&0x1f)); \
886 *rd = res; \
887 } \
888 SET_Z_VAL(res); \
889 COUNT_CYCLES(1); \
890 }
rl_k_a(void)891 static void rl_k_a(void) { RL(A,PARAM_K); }
rl_k_b(void)892 static void rl_k_b(void) { RL(B,PARAM_K); }
rl_r_a(void)893 static void rl_r_a(void) { RL(A,AREG(SRCREG)&0x1f); }
rl_r_b(void)894 static void rl_r_b(void) { RL(B,BREG(SRCREG)&0x1f); }
895
896 #define SLA(R,K) \
897 { \
898 INT32 *rd = &R##REG(DSTREG); \
899 UINT32 res = *rd; \
900 INT32 k = K; \
901 CLR_NCZV; \
902 if (k) \
903 { \
904 UINT32 mask = (0xffffffff<<(31-k))&0x7fffffff; \
905 UINT32 res2 = SIGN(res) ? res^mask : res; \
906 SET_V_LOG((res2 & mask) != 0); \
907 \
908 res<<=(k-1); \
909 SET_C_BIT_HI(res, 31); \
910 res<<=1; \
911 *rd = res; \
912 } \
913 SET_NZ_VAL(res); \
914 COUNT_CYCLES(3); \
915 }
sla_k_a(void)916 static void sla_k_a(void) { SLA(A,PARAM_K); }
sla_k_b(void)917 static void sla_k_b(void) { SLA(B,PARAM_K); }
sla_r_a(void)918 static void sla_r_a(void) { SLA(A,AREG(SRCREG)&0x1f); }
sla_r_b(void)919 static void sla_r_b(void) { SLA(B,BREG(SRCREG)&0x1f); }
920
921 #define SLL(R,K) \
922 { \
923 INT32 *rd = &R##REG(DSTREG); \
924 UINT32 res = *rd; \
925 INT32 k = K; \
926 CLR_CZ; \
927 if (k) \
928 { \
929 res<<=(k-1); \
930 SET_C_BIT_HI(res, 31); \
931 res<<=1; \
932 *rd = res; \
933 } \
934 SET_Z_VAL(res); \
935 COUNT_CYCLES(1); \
936 }
sll_k_a(void)937 static void sll_k_a(void) { SLL(A,PARAM_K); }
sll_k_b(void)938 static void sll_k_b(void) { SLL(B,PARAM_K); }
sll_r_a(void)939 static void sll_r_a(void) { SLL(A,AREG(SRCREG)&0x1f); }
sll_r_b(void)940 static void sll_r_b(void) { SLL(B,BREG(SRCREG)&0x1f); }
941
942 #define SRA(R,K) \
943 { \
944 INT32 *rd = &R##REG(DSTREG); \
945 INT32 res = *rd; \
946 INT32 k = (-(K)) & 0x1f; \
947 CLR_NCZ; \
948 if (k) \
949 { \
950 res>>=(k-1); \
951 SET_C_BIT_LO(res, 0); \
952 res>>=1; \
953 *rd = res; \
954 } \
955 SET_NZ_VAL(res); \
956 COUNT_CYCLES(1); \
957 }
sra_k_a(void)958 static void sra_k_a(void) { SRA(A,PARAM_K); }
sra_k_b(void)959 static void sra_k_b(void) { SRA(B,PARAM_K); }
sra_r_a(void)960 static void sra_r_a(void) { SRA(A,AREG(SRCREG)); }
sra_r_b(void)961 static void sra_r_b(void) { SRA(B,BREG(SRCREG)); }
962
963 #define SRL(R,K) \
964 { \
965 INT32 *rd = &R##REG(DSTREG); \
966 UINT32 res = *rd; \
967 INT32 k = (-(K)) & 0x1f; \
968 CLR_CZ; \
969 if (k) \
970 { \
971 res>>=(k-1); \
972 SET_C_BIT_LO(res, 0); \
973 res>>=1; \
974 *rd = res; \
975 } \
976 SET_Z_VAL(res); \
977 COUNT_CYCLES(1); \
978 }
srl_k_a(void)979 static void srl_k_a(void) { SRL(A,PARAM_K); }
srl_k_b(void)980 static void srl_k_b(void) { SRL(B,PARAM_K); }
srl_r_a(void)981 static void srl_r_a(void) { SRL(A,AREG(SRCREG)); }
srl_r_b(void)982 static void srl_r_b(void) { SRL(B,BREG(SRCREG)); }
983
984 #define SUB(R) \
985 { \
986 INT32 *rs = &R##REG(SRCREG); \
987 INT32 *rd = &R##REG(DSTREG); \
988 INT32 r = *rd - *rs; \
989 CLR_NCZV; \
990 SET_NZCV_SUB(*rd,*rs,r); \
991 *rd = r; \
992 COUNT_CYCLES(1); \
993 }
sub_a(void)994 static void sub_a(void) { SUB(A); }
sub_b(void)995 static void sub_b(void) { SUB(B); }
996
997 #define SUBB(R) \
998 { \
999 INT32 *rd = &R##REG(DSTREG); \
1000 INT32 t = R##REG(SRCREG); \
1001 INT32 r = *rd - t - (C_FLAG ? 1 : 0); \
1002 CLR_NCZV; \
1003 SET_NZCV_SUB(*rd,t,r); \
1004 *rd = r; \
1005 COUNT_CYCLES(1); \
1006 }
subb_a(void)1007 static void subb_a(void) { SUBB(A); }
subb_b(void)1008 static void subb_b(void) { SUBB(B); }
1009
1010 #define SUBI_W(R) \
1011 { \
1012 INT32 *rd = &R##REG(DSTREG); \
1013 INT32 r; \
1014 INT32 t = ~PARAM_WORD(); \
1015 CLR_NCZV; \
1016 r = *rd - t; \
1017 SET_NZCV_SUB(*rd,t,r); \
1018 *rd = r; \
1019 COUNT_CYCLES(2); \
1020 }
subi_w_a(void)1021 static void subi_w_a(void) { SUBI_W(A); }
subi_w_b(void)1022 static void subi_w_b(void) { SUBI_W(B); }
1023
1024 #define SUBI_L(R) \
1025 { \
1026 INT32 *rd = &R##REG(DSTREG); \
1027 INT32 t = ~PARAM_LONG(); \
1028 INT32 r = *rd - t; \
1029 CLR_NCZV; \
1030 SET_NZCV_SUB(*rd,t,r); \
1031 *rd = r; \
1032 COUNT_CYCLES(3); \
1033 }
subi_l_a(void)1034 static void subi_l_a(void) { SUBI_L(A); }
subi_l_b(void)1035 static void subi_l_b(void) { SUBI_L(B); }
1036
1037 #define SUBK(R) \
1038 { \
1039 INT32 *rd = &R##REG(DSTREG); \
1040 INT32 t = fw_inc[PARAM_K]; \
1041 INT32 r = *rd - t; \
1042 CLR_NCZV; \
1043 SET_NZCV_SUB(*rd,t,r); \
1044 *rd = r; \
1045 COUNT_CYCLES(1); \
1046 }
subk_a(void)1047 static void subk_a(void) { SUBK(A); }
subk_b(void)1048 static void subk_b(void) { SUBK(B); }
1049
1050 #define XOR(R) \
1051 { \
1052 INT32 *rd = &R##REG(DSTREG); \
1053 CLR_Z; \
1054 *rd ^= R##REG(SRCREG); \
1055 SET_Z_VAL(*rd); \
1056 COUNT_CYCLES(1); \
1057 }
xor_a(void)1058 static void xor_a(void) { XOR(A); }
xor_b(void)1059 static void xor_b(void) { XOR(B); }
1060
1061 #define XORI(R) \
1062 { \
1063 INT32 *rd = &R##REG(DSTREG); \
1064 CLR_Z; \
1065 *rd ^= PARAM_LONG(); \
1066 SET_Z_VAL(*rd); \
1067 COUNT_CYCLES(3); \
1068 }
xori_a(void)1069 static void xori_a(void) { XORI(A); }
xori_b(void)1070 static void xori_b(void) { XORI(B); }
1071
1072 #define ZEXT(F,R) \
1073 { \
1074 INT32 *rd = &R##REG(DSTREG); \
1075 CLR_Z; \
1076 ZEXTEND(*rd,FW(F)); \
1077 SET_Z_VAL(*rd); \
1078 COUNT_CYCLES(1); \
1079 }
zext0_a(void)1080 static void zext0_a(void) { ZEXT(0,A); }
zext0_b(void)1081 static void zext0_b(void) { ZEXT(0,B); }
zext1_a(void)1082 static void zext1_a(void) { ZEXT(1,A); }
zext1_b(void)1083 static void zext1_b(void) { ZEXT(1,B); }
1084
1085
1086
1087 /***************************************************************************
1088 MOVE INSTRUCTIONS
1089 ***************************************************************************/
1090
1091 #define MOVI_W(R) \
1092 { \
1093 INT32 *rd = &R##REG(DSTREG); \
1094 CLR_NZV; \
1095 *rd=PARAM_WORD(); \
1096 SET_NZ_VAL(*rd); \
1097 COUNT_CYCLES(2); \
1098 }
movi_w_a(void)1099 static void movi_w_a(void) { MOVI_W(A); }
movi_w_b(void)1100 static void movi_w_b(void) { MOVI_W(B); }
1101
1102 #define MOVI_L(R) \
1103 { \
1104 INT32 *rd = &R##REG(DSTREG); \
1105 CLR_NZV; \
1106 *rd=PARAM_LONG(); \
1107 SET_NZ_VAL(*rd); \
1108 COUNT_CYCLES(3); \
1109 }
movi_l_a(void)1110 static void movi_l_a(void) { MOVI_L(A); }
movi_l_b(void)1111 static void movi_l_b(void) { MOVI_L(B); }
1112
1113 #define MOVK(R) \
1114 { \
1115 INT32 k = PARAM_K; if (!k) k = 32; \
1116 R##REG(DSTREG) = k; \
1117 COUNT_CYCLES(1); \
1118 }
movk_a(void)1119 static void movk_a(void) { MOVK(A); }
movk_b(void)1120 static void movk_b(void) { MOVK(B); }
1121
1122 #define MOVB_RN(R) \
1123 { \
1124 WBYTE(R##REG(DSTREG),R##REG(SRCREG)); \
1125 COUNT_CYCLES(1); \
1126 }
movb_rn_a(void)1127 static void movb_rn_a(void) { MOVB_RN(A); }
movb_rn_b(void)1128 static void movb_rn_b(void) { MOVB_RN(B); }
1129
1130 #define MOVB_NR(R) \
1131 { \
1132 INT32 *rd = &R##REG(DSTREG); \
1133 CLR_NZV; \
1134 *rd = (INT8)RBYTE(R##REG(SRCREG)); \
1135 SET_NZ_VAL(*rd); \
1136 COUNT_CYCLES(3); \
1137 }
movb_nr_a(void)1138 static void movb_nr_a(void) { MOVB_NR(A); }
movb_nr_b(void)1139 static void movb_nr_b(void) { MOVB_NR(B); }
1140
1141 #define MOVB_NN(R) \
1142 { \
1143 WBYTE(R##REG(DSTREG),(UINT32)(UINT8)RBYTE(R##REG(SRCREG))); \
1144 COUNT_CYCLES(3); \
1145 }
movb_nn_a(void)1146 static void movb_nn_a(void) { MOVB_NN(A); }
movb_nn_b(void)1147 static void movb_nn_b(void) { MOVB_NN(B); }
1148
1149 #define MOVB_R_NO(R) \
1150 { \
1151 INT32 o = PARAM_WORD(); \
1152 WBYTE(R##REG(DSTREG)+o,R##REG(SRCREG)); \
1153 COUNT_CYCLES(3); \
1154 }
movb_r_no_a(void)1155 static void movb_r_no_a(void) { MOVB_R_NO(A); }
movb_r_no_b(void)1156 static void movb_r_no_b(void) { MOVB_R_NO(B); }
1157
1158 #define MOVB_NO_R(R) \
1159 { \
1160 INT32 *rd = &R##REG(DSTREG); \
1161 INT32 o = PARAM_WORD(); \
1162 CLR_NZV; \
1163 *rd = (INT8)RBYTE(R##REG(SRCREG)+o); \
1164 SET_NZ_VAL(*rd); \
1165 COUNT_CYCLES(5); \
1166 }
movb_no_r_a(void)1167 static void movb_no_r_a(void) { MOVB_NO_R(A); }
movb_no_r_b(void)1168 static void movb_no_r_b(void) { MOVB_NO_R(B); }
1169
1170 #define MOVB_NO_NO(R) \
1171 { \
1172 INT32 o1 = PARAM_WORD(); \
1173 INT32 o2 = PARAM_WORD(); \
1174 WBYTE(R##REG(DSTREG)+o2,(UINT32)(UINT8)RBYTE(R##REG(SRCREG)+o1)); \
1175 COUNT_CYCLES(5); \
1176 }
movb_no_no_a(void)1177 static void movb_no_no_a(void) { MOVB_NO_NO(A); }
movb_no_no_b(void)1178 static void movb_no_no_b(void) { MOVB_NO_NO(B); }
1179
1180 #define MOVB_RA(R) \
1181 { \
1182 WBYTE(PARAM_LONG(),R##REG(DSTREG)); \
1183 COUNT_CYCLES(1); \
1184 }
movb_ra_a(void)1185 static void movb_ra_a(void) { MOVB_RA(A); }
movb_ra_b(void)1186 static void movb_ra_b(void) { MOVB_RA(B); }
1187
1188 #define MOVB_AR(R) \
1189 { \
1190 INT32 *rd = &R##REG(DSTREG); \
1191 CLR_NZV; \
1192 *rd = (INT8)RBYTE(PARAM_LONG()); \
1193 SET_NZ_VAL(*rd); \
1194 COUNT_CYCLES(5); \
1195 }
movb_ar_a(void)1196 static void movb_ar_a(void) { MOVB_AR(A); }
movb_ar_b(void)1197 static void movb_ar_b(void) { MOVB_AR(B); }
1198
movb_aa(void)1199 static void movb_aa(void)
1200 {
1201 UINT32 bitaddrs=PARAM_LONG();
1202 WBYTE(PARAM_LONG(),(UINT32)(UINT8)RBYTE(bitaddrs));
1203 COUNT_CYCLES(6);
1204 }
1205
1206 #define MOVE_RR(RS,RD) \
1207 { \
1208 INT32 *rd = &RD##REG(DSTREG); \
1209 CLR_NZV; \
1210 *rd = RS##REG(SRCREG); \
1211 SET_NZ_VAL(*rd); \
1212 COUNT_CYCLES(1); \
1213 }
move_rr_a(void)1214 static void move_rr_a (void) { MOVE_RR(A,A); }
move_rr_b(void)1215 static void move_rr_b (void) { MOVE_RR(B,B); }
move_rr_ax(void)1216 static void move_rr_ax(void) { MOVE_RR(A,B); }
move_rr_bx(void)1217 static void move_rr_bx(void) { MOVE_RR(B,A); }
1218
1219 #define MOVE_RN(F,R) \
1220 { \
1221 WFIELD##F(R##REG(DSTREG),R##REG(SRCREG)); \
1222 COUNT_CYCLES(1); \
1223 }
move0_rn_a(void)1224 static void move0_rn_a (void) { MOVE_RN(0,A); }
move0_rn_b(void)1225 static void move0_rn_b (void) { MOVE_RN(0,B); }
move1_rn_a(void)1226 static void move1_rn_a (void) { MOVE_RN(1,A); }
move1_rn_b(void)1227 static void move1_rn_b (void) { MOVE_RN(1,B); }
1228
1229 #define MOVE_R_DN(F,R) \
1230 { \
1231 INT32 *rd = &R##REG(DSTREG); \
1232 *rd-=fw_inc[FW(F)]; \
1233 WFIELD##F(*rd,R##REG(SRCREG)); \
1234 COUNT_CYCLES(2); \
1235 }
move0_r_dn_a(void)1236 static void move0_r_dn_a (void) { MOVE_R_DN(0,A); }
move0_r_dn_b(void)1237 static void move0_r_dn_b (void) { MOVE_R_DN(0,B); }
move1_r_dn_a(void)1238 static void move1_r_dn_a (void) { MOVE_R_DN(1,A); }
move1_r_dn_b(void)1239 static void move1_r_dn_b (void) { MOVE_R_DN(1,B); }
1240
1241 #define MOVE_R_NI(F,R) \
1242 { \
1243 INT32 *rd = &R##REG(DSTREG); \
1244 WFIELD##F(*rd,R##REG(SRCREG)); \
1245 *rd+=fw_inc[FW(F)]; \
1246 COUNT_CYCLES(1); \
1247 }
move0_r_ni_a(void)1248 static void move0_r_ni_a (void) { MOVE_R_NI(0,A); }
move0_r_ni_b(void)1249 static void move0_r_ni_b (void) { MOVE_R_NI(0,B); }
move1_r_ni_a(void)1250 static void move1_r_ni_a (void) { MOVE_R_NI(1,A); }
move1_r_ni_b(void)1251 static void move1_r_ni_b (void) { MOVE_R_NI(1,B); }
1252
1253 #define MOVE_NR(F,R) \
1254 { \
1255 INT32 *rd = &R##REG(DSTREG); \
1256 CLR_NZV; \
1257 *rd = RFIELD##F(R##REG(SRCREG)); \
1258 SET_NZ_VAL(*rd); \
1259 COUNT_CYCLES(3); \
1260 }
move0_nr_a(void)1261 static void move0_nr_a (void) { MOVE_NR(0,A); }
move0_nr_b(void)1262 static void move0_nr_b (void) { MOVE_NR(0,B); }
move1_nr_a(void)1263 static void move1_nr_a (void) { MOVE_NR(1,A); }
move1_nr_b(void)1264 static void move1_nr_b (void) { MOVE_NR(1,B); }
1265
1266 #define MOVE_DN_R(F,R) \
1267 { \
1268 INT32 *rd = &R##REG(DSTREG); \
1269 INT32 *rs = &R##REG(SRCREG); \
1270 CLR_NZV; \
1271 *rs-=fw_inc[FW(F)]; \
1272 *rd = RFIELD##F(*rs); \
1273 SET_NZ_VAL(*rd); \
1274 COUNT_CYCLES(4); \
1275 }
move0_dn_r_a(void)1276 static void move0_dn_r_a (void) { MOVE_DN_R(0,A); }
move0_dn_r_b(void)1277 static void move0_dn_r_b (void) { MOVE_DN_R(0,B); }
move1_dn_r_a(void)1278 static void move1_dn_r_a (void) { MOVE_DN_R(1,A); }
move1_dn_r_b(void)1279 static void move1_dn_r_b (void) { MOVE_DN_R(1,B); }
1280
1281 #define MOVE_NI_R(F,R) \
1282 { \
1283 INT32 *rd = &R##REG(DSTREG); \
1284 INT32 *rs = &R##REG(SRCREG); \
1285 INT32 data = RFIELD##F(*rs); \
1286 CLR_NZV; \
1287 *rs+=fw_inc[FW(F)]; \
1288 *rd = data; \
1289 SET_NZ_VAL(*rd); \
1290 COUNT_CYCLES(3); \
1291 }
move0_ni_r_a(void)1292 static void move0_ni_r_a (void) { MOVE_NI_R(0,A); }
move0_ni_r_b(void)1293 static void move0_ni_r_b (void) { MOVE_NI_R(0,B); }
move1_ni_r_a(void)1294 static void move1_ni_r_a (void) { MOVE_NI_R(1,A); }
move1_ni_r_b(void)1295 static void move1_ni_r_b (void) { MOVE_NI_R(1,B); }
1296
1297 #define MOVE_NN(F,R) \
1298 { \
1299 WFIELD##F(R##REG(DSTREG),RFIELD##F(R##REG(SRCREG))); \
1300 COUNT_CYCLES(3); \
1301 }
move0_nn_a(void)1302 static void move0_nn_a (void) { MOVE_NN(0,A); }
move0_nn_b(void)1303 static void move0_nn_b (void) { MOVE_NN(0,B); }
move1_nn_a(void)1304 static void move1_nn_a (void) { MOVE_NN(1,A); }
move1_nn_b(void)1305 static void move1_nn_b (void) { MOVE_NN(1,B); }
1306
1307 #define MOVE_DN_DN(F,R) \
1308 { \
1309 INT32 *rd = &R##REG(DSTREG); \
1310 INT32 *rs = &R##REG(SRCREG); \
1311 INT32 data; \
1312 *rs-=fw_inc[FW(F)]; \
1313 data = RFIELD##F(*rs); \
1314 *rd-=fw_inc[FW(F)]; \
1315 WFIELD##F(*rd,data); \
1316 COUNT_CYCLES(4); \
1317 }
move0_dn_dn_a(void)1318 static void move0_dn_dn_a (void) { MOVE_DN_DN(0,A); }
move0_dn_dn_b(void)1319 static void move0_dn_dn_b (void) { MOVE_DN_DN(0,B); }
move1_dn_dn_a(void)1320 static void move1_dn_dn_a (void) { MOVE_DN_DN(1,A); }
move1_dn_dn_b(void)1321 static void move1_dn_dn_b (void) { MOVE_DN_DN(1,B); }
1322
1323 #define MOVE_NI_NI(F,R) \
1324 { \
1325 INT32 *rd = &R##REG(DSTREG); \
1326 INT32 *rs = &R##REG(SRCREG); \
1327 INT32 data = RFIELD##F(*rs); \
1328 *rs+=fw_inc[FW(F)]; \
1329 WFIELD##F(*rd,data); \
1330 *rd+=fw_inc[FW(F)]; \
1331 COUNT_CYCLES(4); \
1332 }
move0_ni_ni_a(void)1333 static void move0_ni_ni_a (void) { MOVE_NI_NI(0,A); }
move0_ni_ni_b(void)1334 static void move0_ni_ni_b (void) { MOVE_NI_NI(0,B); }
move1_ni_ni_a(void)1335 static void move1_ni_ni_a (void) { MOVE_NI_NI(1,A); }
move1_ni_ni_b(void)1336 static void move1_ni_ni_b (void) { MOVE_NI_NI(1,B); }
1337
1338 #define MOVE_R_NO(F,R) \
1339 { \
1340 INT32 o = PARAM_WORD(); \
1341 WFIELD##F(R##REG(DSTREG)+o,R##REG(SRCREG)); \
1342 COUNT_CYCLES(3); \
1343 }
move0_r_no_a(void)1344 static void move0_r_no_a (void) { MOVE_R_NO(0,A); }
move0_r_no_b(void)1345 static void move0_r_no_b (void) { MOVE_R_NO(0,B); }
move1_r_no_a(void)1346 static void move1_r_no_a (void) { MOVE_R_NO(1,A); }
move1_r_no_b(void)1347 static void move1_r_no_b (void) { MOVE_R_NO(1,B); }
1348
1349 #define MOVE_NO_R(F,R) \
1350 { \
1351 INT32 *rd = &R##REG(DSTREG); \
1352 INT32 o = PARAM_WORD(); \
1353 CLR_NZV; \
1354 *rd = RFIELD##F(R##REG(SRCREG)+o); \
1355 SET_NZ_VAL(*rd); \
1356 COUNT_CYCLES(5); \
1357 }
move0_no_r_a(void)1358 static void move0_no_r_a (void) { MOVE_NO_R(0,A); }
move0_no_r_b(void)1359 static void move0_no_r_b (void) { MOVE_NO_R(0,B); }
move1_no_r_a(void)1360 static void move1_no_r_a (void) { MOVE_NO_R(1,A); }
move1_no_r_b(void)1361 static void move1_no_r_b (void) { MOVE_NO_R(1,B); }
1362
1363 #define MOVE_NO_NI(F,R) \
1364 { \
1365 INT32 *rd = &R##REG(DSTREG); \
1366 INT32 o = PARAM_WORD(); \
1367 INT32 data = RFIELD##F(R##REG(SRCREG)+o); \
1368 WFIELD##F(*rd,data); \
1369 *rd+=fw_inc[FW(F)]; \
1370 COUNT_CYCLES(5); \
1371 }
move0_no_ni_a(void)1372 static void move0_no_ni_a (void) { MOVE_NO_NI(0,A); }
move0_no_ni_b(void)1373 static void move0_no_ni_b (void) { MOVE_NO_NI(0,B); }
move1_no_ni_a(void)1374 static void move1_no_ni_a (void) { MOVE_NO_NI(1,A); }
move1_no_ni_b(void)1375 static void move1_no_ni_b (void) { MOVE_NO_NI(1,B); }
1376
1377 #define MOVE_NO_NO(F,R) \
1378 { \
1379 INT32 o1 = PARAM_WORD(); \
1380 INT32 o2 = PARAM_WORD(); \
1381 INT32 data = RFIELD##F(R##REG(SRCREG)+o1); \
1382 WFIELD##F(R##REG(DSTREG)+o2,data); \
1383 COUNT_CYCLES(5); \
1384 }
move0_no_no_a(void)1385 static void move0_no_no_a (void) { MOVE_NO_NO(0,A); }
move0_no_no_b(void)1386 static void move0_no_no_b (void) { MOVE_NO_NO(0,B); }
move1_no_no_a(void)1387 static void move1_no_no_a (void) { MOVE_NO_NO(1,A); }
move1_no_no_b(void)1388 static void move1_no_no_b (void) { MOVE_NO_NO(1,B); }
1389
1390 #define MOVE_RA(F,R) \
1391 { \
1392 WFIELD##F(PARAM_LONG(),R##REG(DSTREG)); \
1393 COUNT_CYCLES(3); \
1394 }
move0_ra_a(void)1395 static void move0_ra_a (void) { MOVE_RA(0,A); }
move0_ra_b(void)1396 static void move0_ra_b (void) { MOVE_RA(0,B); }
move1_ra_a(void)1397 static void move1_ra_a (void) { MOVE_RA(1,A); }
move1_ra_b(void)1398 static void move1_ra_b (void) { MOVE_RA(1,B); }
1399
1400 #define MOVE_AR(F,R) \
1401 { \
1402 INT32 *rd = &R##REG(DSTREG); \
1403 CLR_NZV; \
1404 *rd = RFIELD##F(PARAM_LONG()); \
1405 SET_NZ_VAL(*rd); \
1406 COUNT_CYCLES(5); \
1407 }
move0_ar_a(void)1408 static void move0_ar_a (void) { MOVE_AR(0,A); }
move0_ar_b(void)1409 static void move0_ar_b (void) { MOVE_AR(0,B); }
move1_ar_a(void)1410 static void move1_ar_a (void) { MOVE_AR(1,A); }
move1_ar_b(void)1411 static void move1_ar_b (void) { MOVE_AR(1,B); }
1412
1413 #define MOVE_A_NI(F,R) \
1414 { \
1415 INT32 *rd = &R##REG(DSTREG); \
1416 WFIELD##F(*rd,RFIELD##F(PARAM_LONG())); \
1417 *rd+=fw_inc[FW(F)]; \
1418 COUNT_CYCLES(5); \
1419 }
move0_a_ni_a(void)1420 static void move0_a_ni_a (void) { MOVE_A_NI(0,A); }
move0_a_ni_b(void)1421 static void move0_a_ni_b (void) { MOVE_A_NI(0,B); }
move1_a_ni_a(void)1422 static void move1_a_ni_a (void) { MOVE_A_NI(1,A); }
move1_a_ni_b(void)1423 static void move1_a_ni_b (void) { MOVE_A_NI(1,B); }
1424
1425 #define MOVE_AA(F) \
1426 { \
1427 UINT32 bitaddrs=PARAM_LONG(); \
1428 WFIELD##F(PARAM_LONG(),RFIELD##F(bitaddrs)); \
1429 COUNT_CYCLES(7); \
1430 }
move0_aa(void)1431 static void move0_aa (void) { MOVE_AA(0); }
move1_aa(void)1432 static void move1_aa (void) { MOVE_AA(1); }
1433
1434
1435
1436 /***************************************************************************
1437 PROGRAM CONTROL INSTRUCTIONS
1438 ***************************************************************************/
1439
1440 #define CALL(R) \
1441 { \
1442 PUSH(PC); \
1443 PC = R##REG(DSTREG); \
1444 CORRECT_ODD_PC("CALL"); \
1445 change_pc(TOBYTE(PC)); \
1446 COUNT_CYCLES(3); \
1447 }
call_a(void)1448 static void call_a (void) { CALL(A); }
call_b(void)1449 static void call_b (void) { CALL(B); }
1450
callr(void)1451 static void callr(void)
1452 {
1453 PUSH(PC+0x10);
1454 PC += (PARAM_WORD_NO_INC()<<4)+0x10;
1455 COUNT_CYCLES(3);
1456 }
1457
calla(void)1458 static void calla(void)
1459 {
1460 PUSH(PC+0x20);
1461 PC = PARAM_LONG_NO_INC();
1462 CORRECT_ODD_PC("CALLA");
1463 change_pc(TOBYTE(PC));
1464 COUNT_CYCLES(4);
1465 }
1466
1467 #define DSJ(R) \
1468 { \
1469 if (--R##REG(DSTREG)) \
1470 { \
1471 PC += (PARAM_WORD_NO_INC()<<4)+0x10; \
1472 COUNT_CYCLES(3); \
1473 } \
1474 else \
1475 { \
1476 SKIP_WORD; \
1477 COUNT_CYCLES(2); \
1478 } \
1479 }
dsj_a(void)1480 static void dsj_a (void) { DSJ(A); }
dsj_b(void)1481 static void dsj_b (void) { DSJ(B); }
1482
1483 #define DSJEQ(R) \
1484 { \
1485 if (Z_FLAG) \
1486 { \
1487 if (--R##REG(DSTREG)) \
1488 { \
1489 PC += (PARAM_WORD_NO_INC()<<4)+0x10; \
1490 COUNT_CYCLES(3); \
1491 } \
1492 else \
1493 { \
1494 SKIP_WORD; \
1495 COUNT_CYCLES(2); \
1496 } \
1497 } \
1498 else \
1499 { \
1500 SKIP_WORD; \
1501 COUNT_CYCLES(2); \
1502 } \
1503 }
dsjeq_a(void)1504 static void dsjeq_a (void) { DSJEQ(A); }
dsjeq_b(void)1505 static void dsjeq_b (void) { DSJEQ(B); }
1506
1507 #define DSJNE(R) \
1508 { \
1509 if (!Z_FLAG) \
1510 { \
1511 if (--R##REG(DSTREG)) \
1512 { \
1513 PC += (PARAM_WORD_NO_INC()<<4)+0x10; \
1514 COUNT_CYCLES(3); \
1515 } \
1516 else \
1517 { \
1518 SKIP_WORD; \
1519 COUNT_CYCLES(2); \
1520 } \
1521 } \
1522 else \
1523 { \
1524 SKIP_WORD; \
1525 COUNT_CYCLES(2); \
1526 } \
1527 }
dsjne_a(void)1528 static void dsjne_a (void) { DSJNE(A); }
dsjne_b(void)1529 static void dsjne_b (void) { DSJNE(B); }
1530
1531 #define DSJS(R) \
1532 { \
1533 if (state.op & 0x0400) \
1534 { \
1535 if (--R##REG(DSTREG)) \
1536 { \
1537 PC -= ((PARAM_K)<<4); \
1538 COUNT_CYCLES(2); \
1539 } \
1540 else \
1541 COUNT_CYCLES(3); \
1542 } \
1543 else \
1544 { \
1545 if (--R##REG(DSTREG)) \
1546 { \
1547 PC += ((PARAM_K)<<4); \
1548 COUNT_CYCLES(2); \
1549 } \
1550 else \
1551 COUNT_CYCLES(3); \
1552 } \
1553 }
dsjs_a(void)1554 static void dsjs_a (void) { DSJS(A); }
dsjs_b(void)1555 static void dsjs_b (void) { DSJS(B); }
1556
emu(void)1557 static void emu(void)
1558 {
1559 /* in RUN state, this instruction is a NOP */
1560 COUNT_CYCLES(6);
1561 }
1562
1563 #define EXGPC(R) \
1564 { \
1565 INT32 *rd = &R##REG(DSTREG); \
1566 INT32 temppc = *rd; \
1567 *rd = PC; \
1568 PC = temppc; \
1569 CORRECT_ODD_PC("EXGPC"); \
1570 change_pc(TOBYTE(PC)); \
1571 COUNT_CYCLES(2); \
1572 }
exgpc_a(void)1573 static void exgpc_a (void) { EXGPC(A); }
exgpc_b(void)1574 static void exgpc_b (void) { EXGPC(B); }
1575
1576 #define GETPC(R) \
1577 { \
1578 R##REG(DSTREG) = PC; \
1579 COUNT_CYCLES(1); \
1580 }
getpc_a(void)1581 static void getpc_a (void) { GETPC(A); }
getpc_b(void)1582 static void getpc_b (void) { GETPC(B); }
1583
1584 #define GETST(R) \
1585 { \
1586 R##REG(DSTREG) = GET_ST(); \
1587 COUNT_CYCLES(1); \
1588 }
getst_a(void)1589 static void getst_a (void) { GETST(A); }
getst_b(void)1590 static void getst_b (void) { GETST(B); }
1591
1592 #define j_xx_8(TAKE) \
1593 { \
1594 if (DSTREG) \
1595 { \
1596 if (TAKE) \
1597 { \
1598 PC += (PARAM_REL8 << 4); \
1599 COUNT_CYCLES(2); \
1600 } \
1601 else \
1602 COUNT_CYCLES(1); \
1603 } \
1604 else \
1605 { \
1606 if (TAKE) \
1607 { \
1608 PC = PARAM_LONG_NO_INC(); \
1609 CORRECT_ODD_PC("J_XX_8"); \
1610 change_pc(TOBYTE(PC)); \
1611 COUNT_CYCLES(3); \
1612 } \
1613 else \
1614 { \
1615 SKIP_LONG; \
1616 COUNT_CYCLES(4); \
1617 } \
1618 } \
1619 }
1620
1621 #define j_xx_0(TAKE) \
1622 { \
1623 if (DSTREG) \
1624 { \
1625 if (TAKE) \
1626 { \
1627 PC += (PARAM_REL8 << 4); \
1628 COUNT_CYCLES(2); \
1629 } \
1630 else \
1631 COUNT_CYCLES(1); \
1632 } \
1633 else \
1634 { \
1635 if (TAKE) \
1636 { \
1637 PC += (PARAM_WORD_NO_INC()<<4)+0x10; \
1638 COUNT_CYCLES(3); \
1639 } \
1640 else \
1641 { \
1642 SKIP_WORD; \
1643 COUNT_CYCLES(2); \
1644 } \
1645 } \
1646 }
1647
1648 #define j_xx_x(TAKE) \
1649 { \
1650 if (TAKE) \
1651 { \
1652 PC += (PARAM_REL8 << 4); \
1653 COUNT_CYCLES(2); \
1654 } \
1655 else \
1656 COUNT_CYCLES(1); \
1657 }
1658
j_UC_0(void)1659 static void j_UC_0(void)
1660 {
1661 j_xx_0(1);
1662 }
j_UC_8(void)1663 static void j_UC_8(void)
1664 {
1665 j_xx_8(1);
1666 }
j_UC_x(void)1667 static void j_UC_x(void)
1668 {
1669 j_xx_x(1);
1670 }
j_P_0(void)1671 static void j_P_0(void)
1672 {
1673 j_xx_0(!N_FLAG && !Z_FLAG);
1674 }
j_P_8(void)1675 static void j_P_8(void)
1676 {
1677 j_xx_8(!N_FLAG && !Z_FLAG);
1678 }
j_P_x(void)1679 static void j_P_x(void)
1680 {
1681 j_xx_x(!N_FLAG && !Z_FLAG);
1682 }
j_LS_0(void)1683 static void j_LS_0(void)
1684 {
1685 j_xx_0(C_FLAG || Z_FLAG);
1686 }
j_LS_8(void)1687 static void j_LS_8(void)
1688 {
1689 j_xx_8(C_FLAG || Z_FLAG);
1690 }
j_LS_x(void)1691 static void j_LS_x(void)
1692 {
1693 j_xx_x(C_FLAG || Z_FLAG);
1694 }
j_HI_0(void)1695 static void j_HI_0(void)
1696 {
1697 j_xx_0(!C_FLAG && !Z_FLAG);
1698 }
j_HI_8(void)1699 static void j_HI_8(void)
1700 {
1701 j_xx_8(!C_FLAG && !Z_FLAG);
1702 }
j_HI_x(void)1703 static void j_HI_x(void)
1704 {
1705 j_xx_x(!C_FLAG && !Z_FLAG);
1706 }
j_LT_0(void)1707 static void j_LT_0(void)
1708 {
1709 j_xx_0((N_FLAG && !V_FLAG) || (!N_FLAG && V_FLAG));
1710 }
j_LT_8(void)1711 static void j_LT_8(void)
1712 {
1713 j_xx_8((N_FLAG && !V_FLAG) || (!N_FLAG && V_FLAG));
1714 }
j_LT_x(void)1715 static void j_LT_x(void)
1716 {
1717 j_xx_x((N_FLAG && !V_FLAG) || (!N_FLAG && V_FLAG));
1718 }
j_GE_0(void)1719 static void j_GE_0(void)
1720 {
1721 j_xx_0((N_FLAG && V_FLAG) || (!N_FLAG && !V_FLAG));
1722 }
j_GE_8(void)1723 static void j_GE_8(void)
1724 {
1725 j_xx_8((N_FLAG && V_FLAG) || (!N_FLAG && !V_FLAG));
1726 }
j_GE_x(void)1727 static void j_GE_x(void)
1728 {
1729 j_xx_x((N_FLAG && V_FLAG) || (!N_FLAG && !V_FLAG));
1730 }
j_LE_0(void)1731 static void j_LE_0(void)
1732 {
1733 j_xx_0((N_FLAG && !V_FLAG) || (!N_FLAG && V_FLAG) || Z_FLAG);
1734 }
j_LE_8(void)1735 static void j_LE_8(void)
1736 {
1737 j_xx_8((N_FLAG && !V_FLAG) || (!N_FLAG && V_FLAG) || Z_FLAG);
1738 }
j_LE_x(void)1739 static void j_LE_x(void)
1740 {
1741 j_xx_x((N_FLAG && !V_FLAG) || (!N_FLAG && V_FLAG) || Z_FLAG);
1742 }
j_GT_0(void)1743 static void j_GT_0(void)
1744 {
1745 j_xx_0((N_FLAG && V_FLAG && !Z_FLAG) || (!N_FLAG && !V_FLAG && !Z_FLAG));
1746 }
j_GT_8(void)1747 static void j_GT_8(void)
1748 {
1749 j_xx_8((N_FLAG && V_FLAG && !Z_FLAG) || (!N_FLAG && !V_FLAG && !Z_FLAG));
1750 }
j_GT_x(void)1751 static void j_GT_x(void)
1752 {
1753 j_xx_x((N_FLAG && V_FLAG && !Z_FLAG) || (!N_FLAG && !V_FLAG && !Z_FLAG));
1754 }
j_C_0(void)1755 static void j_C_0(void)
1756 {
1757 j_xx_0(C_FLAG);
1758 }
j_C_8(void)1759 static void j_C_8(void)
1760 {
1761 j_xx_8(C_FLAG);
1762 }
j_C_x(void)1763 static void j_C_x(void)
1764 {
1765 j_xx_x(C_FLAG);
1766 }
j_NC_0(void)1767 static void j_NC_0(void)
1768 {
1769 j_xx_0(!C_FLAG);
1770 }
j_NC_8(void)1771 static void j_NC_8(void)
1772 {
1773 j_xx_8(!C_FLAG);
1774 }
j_NC_x(void)1775 static void j_NC_x(void)
1776 {
1777 j_xx_x(!C_FLAG);
1778 }
j_EQ_0(void)1779 static void j_EQ_0(void)
1780 {
1781 j_xx_0(Z_FLAG);
1782 }
j_EQ_8(void)1783 static void j_EQ_8(void)
1784 {
1785 j_xx_8(Z_FLAG);
1786 }
j_EQ_x(void)1787 static void j_EQ_x(void)
1788 {
1789 j_xx_x(Z_FLAG);
1790 }
j_NE_0(void)1791 static void j_NE_0(void)
1792 {
1793 j_xx_0(!Z_FLAG);
1794 }
j_NE_8(void)1795 static void j_NE_8(void)
1796 {
1797 j_xx_8(!Z_FLAG);
1798 }
j_NE_x(void)1799 static void j_NE_x(void)
1800 {
1801 j_xx_x(!Z_FLAG);
1802 }
j_V_0(void)1803 static void j_V_0(void)
1804 {
1805 j_xx_0(V_FLAG);
1806 }
j_V_8(void)1807 static void j_V_8(void)
1808 {
1809 j_xx_8(V_FLAG);
1810 }
j_V_x(void)1811 static void j_V_x(void)
1812 {
1813 j_xx_x(V_FLAG);
1814 }
j_NV_0(void)1815 static void j_NV_0(void)
1816 {
1817 j_xx_0(!V_FLAG);
1818 }
j_NV_8(void)1819 static void j_NV_8(void)
1820 {
1821 j_xx_8(!V_FLAG);
1822 }
j_NV_x(void)1823 static void j_NV_x(void)
1824 {
1825 j_xx_x(!V_FLAG);
1826 }
j_N_0(void)1827 static void j_N_0(void)
1828 {
1829 j_xx_0(N_FLAG);
1830 }
j_N_8(void)1831 static void j_N_8(void)
1832 {
1833 j_xx_8(N_FLAG);
1834 }
j_N_x(void)1835 static void j_N_x(void)
1836 {
1837 j_xx_x(N_FLAG);
1838 }
j_NN_0(void)1839 static void j_NN_0(void)
1840 {
1841 j_xx_0(!N_FLAG);
1842 }
j_NN_8(void)1843 static void j_NN_8(void)
1844 {
1845 j_xx_8(!N_FLAG);
1846 }
j_NN_x(void)1847 static void j_NN_x(void)
1848 {
1849 j_xx_x(!N_FLAG);
1850 }
1851
1852 #define JUMP(R) \
1853 { \
1854 PC = R##REG(DSTREG); \
1855 CORRECT_ODD_PC("JUMP"); \
1856 change_pc(TOBYTE(PC)); \
1857 COUNT_CYCLES(2); \
1858 }
jump_a(void)1859 static void jump_a (void) { JUMP(A); }
jump_b(void)1860 static void jump_b (void) { JUMP(B); }
1861
popst(void)1862 static void popst(void)
1863 {
1864 SET_ST(POP());
1865 COUNT_CYCLES(8);
1866 }
1867
pushst(void)1868 static void pushst(void)
1869 {
1870 PUSH(GET_ST());
1871 COUNT_CYCLES(2);
1872 }
1873
1874 #define PUTST(R) \
1875 { \
1876 SET_ST(R##REG(DSTREG)); \
1877 COUNT_CYCLES(3); \
1878 }
putst_a(void)1879 static void putst_a (void) { PUTST(A); }
putst_b(void)1880 static void putst_b (void) { PUTST(B); }
1881
reti(void)1882 static void reti(void)
1883 {
1884 INT32 st = POP();
1885 PC = POP();
1886 CORRECT_ODD_PC("RETI");
1887 change_pc(TOBYTE(PC));
1888 SET_ST(st);
1889 COUNT_CYCLES(11);
1890 }
1891
rets(void)1892 static void rets(void)
1893 {
1894 UINT32 offs;
1895 PC = POP();
1896 CORRECT_ODD_PC("RETS");
1897 change_pc(TOBYTE(PC));
1898 offs = PARAM_N;
1899 if (offs)
1900 {
1901 SP+=(offs<<4);
1902 }
1903 COUNT_CYCLES(7);
1904 }
1905
1906 #define REV(R) \
1907 { \
1908 R##REG(DSTREG) = 0x0008; \
1909 COUNT_CYCLES(1); \
1910 }
rev_a(void)1911 static void rev_a (void) { REV(A); }
rev_b(void)1912 static void rev_b (void) { REV(B); }
1913
trap(void)1914 static void trap(void)
1915 {
1916 UINT32 t = PARAM_N;
1917 if (t)
1918 {
1919 PUSH(PC);
1920 PUSH(GET_ST());
1921 }
1922 RESET_ST();
1923 PC = RLONG(0xffffffe0-(t<<5));
1924 CORRECT_ODD_PC("TRAP");
1925 change_pc(TOBYTE(PC));
1926 COUNT_CYCLES(16);
1927 }
1928
1929
1930
1931 /***************************************************************************
1932 34020 INSTRUCTIONS
1933 ***************************************************************************/
1934
1935 /************************************
1936
1937 New 34020 ops:
1938
1939 0000 1100 000R dddd = ADDXYI IL,Rd
1940 iiii iiii iiii iiii
1941 iiii iiii iiii iiii
1942
1943 0000 0000 1111 00SD = BLMOVE S,D
1944
1945 0000 0110 0000 0000 = CEXEC S,c,ID,L
1946 cccc cccc S000 0000
1947 iiic cccc cccc cccc
1948
1949 1101 1000 0ccc cccS = CEXEC S,c,ID
1950 iiic cccc cccc cccc
1951
1952 0000 1000 1111 0010 = CLIP
1953
1954 0000 0110 011R dddd = CMOVCG Rd1,Rd2,S,c,ID
1955 cccc cccc S00R dddd
1956 iiic cccc cccc cccc
1957
1958 0000 0110 101R dddd = CMOVCM *Rd+,n,S,c,ID
1959 cccc cccc S00n nnnn
1960 iiic cccc cccc cccc
1961
1962 0000 0110 110R dddd = CMOVCM -*Rd,n,S,c,ID
1963 cccc cccc S00n nnnn
1964 iiic cccc cccc cccc
1965
1966 0000 0110 0110 0000 = CMOVCS c,ID
1967 cccc cccc 0000 0001
1968 iiic cccc cccc cccc
1969
1970 0000 0110 001R ssss = CMOVGC Rs,c,ID
1971 cccc cccc 0000 0000
1972 iiic cccc cccc cccc
1973
1974 0000 0110 010R ssss = CMOVGC Rs1,Rs2,S,c,ID
1975 cccc cccc S00R ssss
1976 iiic cccc cccc cccc
1977
1978 0000 0110 100n nnnn = CMOVMC *Rs+,n,S,c,ID
1979 cccc cccc S00R ssss
1980 iiic cccc cccc cccc
1981
1982 0000 1000 001n nnnn = CMOVMC -*Rs,n,S,c,ID
1983 cccc cccc S00R ssss
1984 iiic cccc cccc cccc
1985
1986 0000 0110 111R dddd = CMOVMC *Rs+,Rd,S,c,ID
1987 cccc cccc S00R ssss
1988 iiic cccc cccc cccc
1989
1990 0011 01kk kkkR dddd = CMPK k,Rd
1991
1992 0000 1010 100R dddd = CVDXYL Rd
1993
1994 0000 1010 011R dddd = CVMXYL Rd
1995
1996 1110 101s sssR dddd = CVSXYL Rs,Rd
1997
1998 0000 0010 101R dddd = EXGPS Rd
1999
2000 1101 1110 Z001 1010 = FLINE Z
2001
2002 0000 1010 1011 1011 = FPIXEQ
2003
2004 0000 1010 1101 1011 = FPIXNE
2005
2006 0000 0010 110R dddd = GETPS Rd
2007
2008 0000 0000 0100 0000 = IDLE
2009
2010 0000 1100 0101 0111 = LINIT
2011
2012 0000 0000 1000 0000 = MWAIT
2013
2014 0000 1010 0011 0111 = PFILL XY
2015
2016 0000 1110 0001 0111 = PIXBLT L,M,L
2017
2018 0000 1000 0110 0000 = RETM
2019
2020 0111 101s sssR dddd = RMO Rs,Rd
2021
2022 0000 0010 100R dddd = RPIX Rd
2023
2024 0000 0010 0111 0011 = SETCDP
2025
2026 0000 0010 1111 1011 = SETCMP
2027
2028 0000 0010 0101 0001 = SETCSP
2029
2030 0111 111s sssR dddd = SWAPF *Rs,Rd,0
2031
2032 0000 1110 1111 1010 = TFILL XY
2033
2034 0000 1000 0000 1111 = TRAPL
2035
2036 0000 1000 0101 0111 = VBLT B,L
2037
2038 0000 1010 0101 0111 = VFILL L
2039
2040 0000 1010 0000 0000 = VLCOL
2041
2042 ************************************/
2043
2044
2045 #define ADD_XYI(R) \
2046 { \
2047 UINT32 a = PARAM_LONG(); \
2048 XY *b = &R##REG_XY(DSTREG); \
2049 CLR_NCZV; \
2050 b->x += (INT16)(a & 0xffff); \
2051 b->y += ((INT32)a >> 16); \
2052 SET_N_LOG(b->x == 0); \
2053 SET_C_BIT_LO(b->y, 15); \
2054 SET_Z_LOG(b->y == 0); \
2055 SET_V_BIT_LO(b->x, 15); \
2056 COUNT_CYCLES(1); \
2057 }
addxyi_a(void)2058 static void addxyi_a(void)
2059 {
2060 if (!state.is_34020) { unimpl(); return; }
2061 ADD_XYI(A);
2062 }
addxyi_b(void)2063 static void addxyi_b(void)
2064 {
2065 if (!state.is_34020) { unimpl(); return; }
2066 ADD_XYI(B);
2067 }
2068
blmove(void)2069 static void blmove(void)
2070 {
2071 offs_t src = BREG(0);
2072 offs_t dst = BREG(2);
2073 offs_t bits = BREG(7);
2074
2075 if (!state.is_34020) { unimpl(); return; }
2076
2077 /* src and dst are aligned */
2078 if (!(src & 0x0f) && !(dst & 0x0f))
2079 {
2080 while (bits >= 16 && tms34010_ICount > 0)
2081 {
2082 TMS34010_WRMEM_WORD(TOBYTE(dst), TMS34010_RDMEM_WORD(TOBYTE(src)));
2083 src += 0x10;
2084 dst += 0x10;
2085 bits -= 0x10;
2086 //tms34010_ICount -= 2;
2087 COUNT_CYCLES(2);
2088 }
2089 if (bits != 0 && tms34010_ICount > 0)
2090 {
2091 (*tms34010_wfield_functions[bits])(dst, (*tms34010_rfield_functions[bits])(src));
2092 dst += bits;
2093 src += bits;
2094 bits = 0;
2095 //tms34010_ICount -= 2;
2096 COUNT_CYCLES(2);
2097 }
2098 }
2099
2100 /* src is aligned, dst is not */
2101 else if (!(src & 0x0f))
2102 {
2103 logerror("020:BLMOVE with aligned src and unaligned dst\n");
2104 }
2105
2106 /* dst is aligned, src is not */
2107 else if (!(dst & 0x0f))
2108 {
2109 logerror("020:BLMOVE with unaligned src and aligned dst\n");
2110 }
2111
2112 /* neither are aligned */
2113 else
2114 {
2115 logerror("020:BLMOVE with completely unaligned src and dst\n");
2116 }
2117
2118 /* update the final results */
2119 BREG(0) = src;
2120 BREG(2) = dst;
2121 BREG(7) = bits;
2122
2123 /* if we're not done yet, back up the PC */
2124 if (bits != 0)
2125 PC -= 0x10;
2126 }
2127
cexec_l(void)2128 static void cexec_l(void)
2129 {
2130 if (!state.is_34020) { unimpl(); return; }
2131 logerror("020:cexec_l\n");
2132 }
2133
cexec_s(void)2134 static void cexec_s(void)
2135 {
2136 if (!state.is_34020) { unimpl(); return; }
2137 logerror("020:cexec_s\n");
2138 }
2139
clip(void)2140 static void clip(void)
2141 {
2142 if (!state.is_34020) { unimpl(); return; }
2143 logerror("020:clip\n");
2144 }
2145
cmovcg_a(void)2146 static void cmovcg_a(void)
2147 {
2148 if (!state.is_34020) { unimpl(); return; }
2149 logerror("020:cmovcg_a\n");
2150 }
2151
cmovcg_b(void)2152 static void cmovcg_b(void)
2153 {
2154 if (!state.is_34020) { unimpl(); return; }
2155 logerror("020:cmovcg_b\n");
2156 }
2157
cmovcm_f(void)2158 static void cmovcm_f(void)
2159 {
2160 if (!state.is_34020) { unimpl(); return; }
2161 logerror("020:cmovcm_f\n");
2162 }
2163
cmovcm_b(void)2164 static void cmovcm_b(void)
2165 {
2166 if (!state.is_34020) { unimpl(); return; }
2167 logerror("020:cmovcm_b\n");
2168 }
2169
cmovgc_a(void)2170 static void cmovgc_a(void)
2171 {
2172 if (!state.is_34020) { unimpl(); return; }
2173 logerror("020:cmovgc_a\n");
2174 }
2175
cmovgc_b(void)2176 static void cmovgc_b(void)
2177 {
2178 if (!state.is_34020) { unimpl(); return; }
2179 logerror("020:cmovgc_b\n");
2180 }
2181
cmovgc_a_s(void)2182 static void cmovgc_a_s(void)
2183 {
2184 if (!state.is_34020) { unimpl(); return; }
2185 logerror("020:cmovgc_a_s\n");
2186 }
2187
cmovgc_b_s(void)2188 static void cmovgc_b_s(void)
2189 {
2190 if (!state.is_34020) { unimpl(); return; }
2191 logerror("020:cmovgc_b_s\n");
2192 }
2193
cmovmc_f(void)2194 static void cmovmc_f(void)
2195 {
2196 if (!state.is_34020) { unimpl(); return; }
2197 logerror("020:cmovmc_f\n");
2198 }
2199
cmovmc_f_va(void)2200 static void cmovmc_f_va(void)
2201 {
2202 if (!state.is_34020) { unimpl(); return; }
2203 logerror("020:cmovmc_f_va\n");
2204 }
2205
cmovmc_f_vb(void)2206 static void cmovmc_f_vb(void)
2207 {
2208 if (!state.is_34020) { unimpl(); return; }
2209 logerror("020:cmovmc_f_vb\n");
2210 }
2211
cmovmc_b(void)2212 static void cmovmc_b(void)
2213 {
2214 if (!state.is_34020) { unimpl(); return; }
2215 logerror("020:cmovmc_b\n");
2216 }
2217
2218 #define CMPK(R) \
2219 { \
2220 INT32 r; \
2221 INT32 *rd = &R##REG(DSTREG); \
2222 INT32 t = PARAM_K; if (!t) t = 32; \
2223 CLR_NCZV; \
2224 r = *rd - t; \
2225 SET_NZCV_SUB(*rd,t,r); \
2226 COUNT_CYCLES(1); \
2227 }
cmp_k_a(void)2228 static void cmp_k_a(void)
2229 {
2230 if (!state.is_34020) { unimpl(); return; }
2231 CMPK(A);
2232 }
cmp_k_b(void)2233 static void cmp_k_b(void)
2234 {
2235 if (!state.is_34020) { unimpl(); return; }
2236 CMPK(B);
2237 }
2238
cvdxyl_a(void)2239 static void cvdxyl_a(void)
2240 {
2241 if (!state.is_34020) { unimpl(); return; }
2242 logerror("020:cvdxyl_a\n");
2243 }
2244
cvdxyl_b(void)2245 static void cvdxyl_b(void)
2246 {
2247 if (!state.is_34020) { unimpl(); return; }
2248 logerror("020:cvdxyl_b\n");
2249 }
2250
cvmxyl_a(void)2251 static void cvmxyl_a(void)
2252 {
2253 if (!state.is_34020) { unimpl(); return; }
2254 logerror("020:cvmxyl_a\n");
2255 }
2256
cvmxyl_b(void)2257 static void cvmxyl_b(void)
2258 {
2259 if (!state.is_34020) { unimpl(); return; }
2260 logerror("020:cvmxyl_b\n");
2261 }
2262
cvsxyl_a(void)2263 static void cvsxyl_a(void)
2264 {
2265 if (!state.is_34020) { unimpl(); return; }
2266 logerror("020:cvsxyl_a\n");
2267 }
2268
cvsxyl_b(void)2269 static void cvsxyl_b(void)
2270 {
2271 if (!state.is_34020) { unimpl(); return; }
2272 logerror("020:cvsxyl_b\n");
2273 }
2274
exgps_a(void)2275 static void exgps_a(void)
2276 {
2277 if (!state.is_34020) { unimpl(); return; }
2278 logerror("020:exgps_a\n");
2279 }
2280
exgps_b(void)2281 static void exgps_b(void)
2282 {
2283 if (!state.is_34020) { unimpl(); return; }
2284 logerror("020:exgps_b\n");
2285 }
2286
fline(void)2287 static void fline(void)
2288 {
2289 if (!state.is_34020) { unimpl(); return; }
2290 logerror("020:fline\n");
2291 }
2292
fpixeq(void)2293 static void fpixeq(void)
2294 {
2295 if (!state.is_34020) { unimpl(); return; }
2296 logerror("020:fpixeq\n");
2297 }
2298
fpixne(void)2299 static void fpixne(void)
2300 {
2301 if (!state.is_34020) { unimpl(); return; }
2302 logerror("020:fpixne\n");
2303 }
2304
getps_a(void)2305 static void getps_a(void)
2306 {
2307 if (!state.is_34020) { unimpl(); return; }
2308 logerror("020:getps_a\n");
2309 }
2310
getps_b(void)2311 static void getps_b(void)
2312 {
2313 if (!state.is_34020) { unimpl(); return; }
2314 logerror("020:getps_b\n");
2315 }
2316
idle(void)2317 static void idle(void)
2318 {
2319 if (!state.is_34020) { unimpl(); return; }
2320 logerror("020:idle\n");
2321 }
2322
linit(void)2323 static void linit(void)
2324 {
2325 if (!state.is_34020) { unimpl(); return; }
2326 logerror("020:linit\n");
2327 }
2328
mwait(void)2329 static void mwait(void)
2330 {
2331 if (!state.is_34020) { unimpl(); return; }
2332 }
2333
pfill_xy(void)2334 static void pfill_xy(void)
2335 {
2336 if (!state.is_34020) { unimpl(); return; }
2337 logerror("020:pfill_xy\n");
2338 }
2339
pixblt_l_m_l(void)2340 static void pixblt_l_m_l(void)
2341 {
2342 if (!state.is_34020) { unimpl(); return; }
2343 logerror("020:pixblt_l_m_l\n");
2344 }
2345
retm(void)2346 static void retm(void)
2347 {
2348 if (!state.is_34020) { unimpl(); return; }
2349 logerror("020:retm\n");
2350 }
2351
2352 #define RMO(R) \
2353 { \
2354 UINT32 res = 0; \
2355 UINT32 rs = R##REG(SRCREG); \
2356 INT32 *rd = &R##REG(DSTREG); \
2357 CLR_Z; \
2358 SET_Z_VAL(rs); \
2359 if (rs) \
2360 { \
2361 while (!(rs & 0x00000001)) \
2362 { \
2363 res++; \
2364 rs >>= 1; \
2365 } \
2366 } \
2367 *rd = res; \
2368 COUNT_CYCLES(1); \
2369 }
2370
rmo_a(void)2371 static void rmo_a(void) { RMO(A); }
rmo_b(void)2372 static void rmo_b(void) { RMO(B); }
2373
2374 #define RPIX(R) \
2375 { \
2376 UINT32 v = R##REG(DSTREG); \
2377 switch (state.pixelshift) \
2378 { \
2379 case 0: \
2380 v = (v & 1) ? 0xffffffff : 0x00000000;\
2381 COUNT_CYCLES(8); \
2382 break; \
2383 case 1: \
2384 v &= 3; \
2385 v |= v << 2; \
2386 v |= v << 4; \
2387 v |= v << 8; \
2388 v |= v << 16; \
2389 COUNT_CYCLES(7); \
2390 break; \
2391 case 2: \
2392 v &= 0x0f; \
2393 v |= v << 4; \
2394 v |= v << 8; \
2395 v |= v << 16; \
2396 COUNT_CYCLES(6); \
2397 break; \
2398 case 3: \
2399 v &= 0xff; \
2400 v |= v << 8; \
2401 v |= v << 16; \
2402 COUNT_CYCLES(5); \
2403 break; \
2404 case 4: \
2405 v &= 0xffff; \
2406 v |= v << 16; \
2407 COUNT_CYCLES(4); \
2408 break; \
2409 case 5: \
2410 COUNT_CYCLES(2); \
2411 break; \
2412 } \
2413 R##REG(DSTREG) = v; \
2414 }
2415
rpix_a(void)2416 static void rpix_a(void)
2417 {
2418 if (!state.is_34020) { unimpl(); return; }
2419 RPIX(A);
2420 }
2421
rpix_b(void)2422 static void rpix_b(void)
2423 {
2424 if (!state.is_34020) { unimpl(); return; }
2425 RPIX(B);
2426 }
2427
setcdp(void)2428 static void setcdp(void)
2429 {
2430 if (!state.is_34020) { unimpl(); return; }
2431 logerror("020:setcdp\n");
2432 }
2433
setcmp(void)2434 static void setcmp(void)
2435 {
2436 if (!state.is_34020) { unimpl(); return; }
2437 logerror("020:setcmp\n");
2438 }
2439
setcsp(void)2440 static void setcsp(void)
2441 {
2442 if (!state.is_34020) { unimpl(); return; }
2443 logerror("020:setcsp\n");
2444 }
2445
swapf_a(void)2446 static void swapf_a(void)
2447 {
2448 if (!state.is_34020) { unimpl(); return; }
2449 logerror("020:swapf_a\n");
2450 }
2451
swapf_b(void)2452 static void swapf_b(void)
2453 {
2454 if (!state.is_34020) { unimpl(); return; }
2455 logerror("020:swapf_b\n");
2456 }
2457
tfill_xy(void)2458 static void tfill_xy(void)
2459 {
2460 if (!state.is_34020) { unimpl(); return; }
2461 logerror("020:tfill_xy\n");
2462 }
2463
trapl(void)2464 static void trapl(void)
2465 {
2466 if (!state.is_34020) { unimpl(); return; }
2467 logerror("020:trapl\n");
2468 }
2469
vblt_b_l(void)2470 static void vblt_b_l(void)
2471 {
2472 if (!state.is_34020) { unimpl(); return; }
2473 logerror("020:vblt_b_l\n");
2474 }
2475
vfill_l(void)2476 static void vfill_l(void)
2477 {
2478 if (!state.is_34020) { unimpl(); return; }
2479 logerror("020:vfill_l\n");
2480 }
2481
vlcol(void)2482 static void vlcol(void)
2483 {
2484 if (!state.is_34020) { unimpl(); return; }
2485 logerror("020:vlcol\n");
2486 }
2487