|
|
1.1.1.4 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * MC68000 emulation generator
5: *
6: * This is a fairly stupid program that generates a lot of case labels that
7: * can be #included in a switch statement.
8: * As an alternative, it can generate functions that handle specific
9: * MC68000 instructions, plus a prototype header file and a function pointer
10: * array to look up the function for an opcode.
11: * Error checking is bad, an illegal table68k file will cause the program to
12: * call abort().
13: * The generated code is sometimes sub-optimal, an optimizing compiler should
14: * take care of this.
15: *
16: * The source for the insn timings is Markt & Technik's Amiga Magazin 8/1992.
17: *
18: * Copyright 1995, 1996, 1997, 1998, 1999, 2000 Bernd Schmidt
19: */
20:
21: #include "sysconfig.h"
22: #include "sysdeps.h"
23: #include <ctype.h>
24: #include <string.h>
25:
26: #include "readcpu.h"
1.1.1.7 root 27:
28: char *ua (const char *s) {
29: return strdup(s);
30: }
1.1.1.4 root 31:
32: #define BOOL_TYPE "int"
33: /* Define the minimal 680x0 where NV flags are not affected by xBCD instructions. */
1.1.1.9 root 34: #define xBCD_KEEPS_N_FLAG 4
35: #define xBCD_KEEPS_V_FLAG 2
1.1.1.4 root 36:
37: static FILE *headerfile;
38: static FILE *stblfile;
39:
40: static int using_prefetch, using_indirect, using_mmu;
1.1.1.7 root 41: static int using_prefetch_020, using_ce020;
1.1.1.4 root 42: static int using_exception_3;
1.1.1.7 root 43: static int using_bus_error;
1.1.1.4 root 44: static int using_ce;
1.1.1.7 root 45: static int using_tracer;
46: static int using_waitstates;
47: static int using_simple_cycles;
1.1.1.8 root 48: static int cpu_level, cpu_generic;
1.1.1.4 root 49: static int count_read, count_write, count_cycles, count_ncycles;
1.1.1.7 root 50: static int count_cycles_ce020;
1.1.1.4 root 51: static int count_read_ea, count_write_ea, count_cycles_ea;
1.1.1.10! root 52: static const char *mmu_postfix, *xfc_postfix;
1.1.1.7 root 53: static int memory_cycle_cnt;
54: static int did_prefetch;
55: static int ipl_fetched;
1.1.1.4 root 56:
57: static int optimized_flags;
58:
1.1.1.7 root 59: #ifdef WINUAE_FOR_HATARI
1.1.1.8 root 60: static long nCurInstrCycPos; /* Hatari only : Stores where we have to patch in the current cycles value */
1.1.1.7 root 61: #endif
1.1.1.4 root 62:
63: #define GF_APDI 1
64: #define GF_AD8R 2
65: #define GF_PC8R 4
66: #define GF_AA 7
67: #define GF_NOREFILL 8
68: #define GF_PREFETCH 16
69: #define GF_FC 32
70: #define GF_MOVE 64
1.1.1.7 root 71: #define GF_IR2IRC 128
72: #define GF_LRMW 256
73: #define GF_NOFAULTPC 512
74: #define GF_RMW 1024
75: #define GF_OPCE020 2048
1.1.1.9 root 76: #define GF_REVERSE 4096
77: #define GF_REVERSE2 8192
1.1.1.4 root 78:
79: /* For the current opcode, the next lower level that will have different code.
80: * Initialized to -1 for each opcode. If it remains unchanged, indicates we
81: * are done with that opcode. */
82: static int next_cpu_level;
83:
84: static int *opcode_map;
85: static int *opcode_next_clev;
86: static int *opcode_last_postfix;
87: static unsigned long *counts;
88: static int generate_stbl;
1.1.1.7 root 89: static int mmufixupcnt;
90: static int mmufixupstate;
91: static int disp020cnt;
92: static bool candormw;
93: static bool genastore_done;
94: static char rmw_varname[100];
1.1.1.4 root 95:
96: #define GENA_GETV_NO_FETCH 0
97: #define GENA_GETV_FETCH 1
98: #define GENA_GETV_FETCH_ALIGN 2
99: #define GENA_MOVEM_DO_INC 0
100: #define GENA_MOVEM_NO_INC 1
101: #define GENA_MOVEM_MOVE16 2
102:
1.1.1.7 root 103: static const char *srcl, *dstl;
104: static const char *srcw, *dstw;
105: static const char *srcb, *dstb;
106: static const char *srcblrmw, *srcwlrmw, *srcllrmw;
107: static const char *dstblrmw, *dstwlrmw, *dstllrmw;
108: static const char *srcbrmw, *srcwrmw, *srclrmw;
109: static const char *dstbrmw, *dstwrmw, *dstlrmw;
1.1.1.9 root 110: static const char *prefetch_long, *prefetch_word, *prefetch_opcode;
1.1.1.7 root 111: static const char *srcli, *srcwi, *srcbi, *nextl, *nextw;
112: static const char *srcld, *dstld;
113: static const char *srcwd, *dstwd;
114: static const char *do_cycles, *disp000, *disp020, *getpc;
115:
116: #define fetchmode_fea 1
117: #define fetchmode_cea 2
118: #define fetchmode_fiea 3
119: #define fetchmode_ciea 4
120: #define fetchmode_jea 5
121:
122: NORETURN static void term (void)
123: {
124: printf("Abort!\n");
125: abort ();
126: }
127: NORETURN static void term_err (const char *err)
128: {
129: printf ("%s\n", err);
130: term ();
131: }
1.1.1.4 root 132:
133: static void read_counts (void)
134: {
135: FILE *file;
1.1.1.7 root 136: unsigned int opcode, count, total;
1.1.1.4 root 137: char name[20];
138: int nr = 0;
139: memset (counts, 0, 65536 * sizeof *counts);
140:
141: count = 0;
142: file = fopen ("frequent.68k", "r");
143: if (file) {
1.1.1.7 root 144: if (fscanf (file, "Total: %u\n", &total) == 0) {
145: abort ();
1.1.1.6 root 146: }
1.1.1.7 root 147: while (fscanf (file, "%x: %u %s\n", &opcode, &count, name) == 3) {
1.1.1.4 root 148: opcode_next_clev[nr] = 5;
149: opcode_last_postfix[nr] = -1;
150: opcode_map[nr++] = opcode;
151: counts[opcode] = count;
152: }
153: fclose (file);
154: }
155: if (nr == nr_cpuop_funcs)
156: return;
157: for (opcode = 0; opcode < 0x10000; opcode++) {
158: if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG
159: && counts[opcode] == 0)
160: {
161: opcode_next_clev[nr] = 5;
162: opcode_last_postfix[nr] = -1;
163: opcode_map[nr++] = opcode;
164: counts[opcode] = count;
165: }
166: }
167: if (nr != nr_cpuop_funcs)
1.1.1.7 root 168: term ();
1.1.1.4 root 169: }
170:
171: static char endlabelstr[80];
172: static int endlabelno = 0;
173: static int need_endlabel;
1.1.1.8 root 174: static int genamode_cnt, genamode8r_offset[2];
1.1.1.4 root 175:
176: static int n_braces, limit_braces;
1.1.1.7 root 177: static int m68k_pc_offset, m68k_pc_offset_old;
178: static int m68k_pc_total;
179: static int branch_inst;
1.1.1.4 root 180: static int insn_n_cycles, insn_n_cycles020;
1.1.1.7 root 181: static int ir2irc;
182:
183: static int tail_ce020, total_ce020, head_in_ea_ce020;
184: static bool head_ce020_cycs_done, tail_ce020_done;
185: static int subhead_ce020;
186: static struct instr *curi_ce020;
187: static bool no_prefetch_ce020;
188: static bool got_ea_ce020;
1.1.1.4 root 189:
190: static void fpulimit (void)
191: {
192: if (limit_braces)
193: return;
194: printf ("\n#ifdef FPUEMU\n");
195: limit_braces = n_braces;
196: n_braces = 0;
197: }
198:
1.1.1.7 root 199: static int s_count_read, s_count_write, s_count_cycles, s_count_ncycles;
200:
201: static void push_ins_cnt(void)
1.1.1.4 root 202: {
1.1.1.7 root 203: s_count_read = count_read;
204: s_count_write = count_write;
205: s_count_cycles = count_cycles;
206: s_count_ncycles = count_ncycles;
207: }
208: static void pop_ins_cnt(void)
209: {
210: count_read = s_count_read;
211: count_write = s_count_write;
212: count_cycles = s_count_cycles;
213: count_ncycles = s_count_ncycles;
214: }
215:
216: static bool isce020(void)
217: {
218: if (!using_ce020)
219: return false;
220: if (using_ce020 >= 3)
221: return false;
222: return true;
223: }
224: static bool isprefetch020(void)
225: {
226: if (!using_prefetch_020)
227: return false;
228: if (using_prefetch_020 >= 3)
229: return false;
230: return true;
231: }
232:
233: static void addcycles_ce020_2 (int cycles, const char *s)
234: {
235: if (!isce020())
1.1.1.4 root 236: return;
1.1.1.7 root 237: if (cycles > 0) {
238: if (s == NULL)
239: printf ("\t%s (%d);\n", do_cycles, cycles);
240: else
241: printf ("\t%s (%d); /* %s */\n", do_cycles, cycles, s);
242: }
243: count_cycles += cycles;
244: count_cycles_ce020 += cycles;
245: }
246: static void addcycles_ce020 (int cycles)
247: {
248: addcycles_ce020_2 (cycles, NULL);
249: }
1.1.1.4 root 250:
1.1.1.7 root 251: static void get_prefetch_020 (void)
252: {
253: if (!isprefetch020() || no_prefetch_ce020)
254: return;
1.1.1.10! root 255: printf ("\tregs.irc = %s (%d);\n", prefetch_opcode, m68k_pc_offset);
1.1.1.7 root 256: }
257: static void get_prefetch_020_continue(void)
258: {
259: if (!isprefetch020())
260: return;
1.1.1.9 root 261: if (using_ce020) {
262: if (using_ce020 > 1)
263: printf("\tcontinue_ce030_prefetch();\n");
264: else
265: printf("\tcontinue_ce020_prefetch();\n");
266: } else {
267: if (using_prefetch_020 > 1)
268: printf ("\tcontinue_030_prefetch();\n");
269: else
270: printf ("\tcontinue_020_prefetch();\n");
271: }
1.1.1.7 root 272: }
273:
274: static void returntail (bool iswrite)
275: {
276: if (!isce020()) {
277: if (isprefetch020()) {
278: if (!tail_ce020_done) {
279: if (!did_prefetch)
280: get_prefetch_020 ();
281: did_prefetch = 1;
282: tail_ce020_done = true;
283: }
1.1.1.4 root 284: }
1.1.1.7 root 285: return;
286: }
287: if (!tail_ce020_done) {
288: total_ce020 -= 2;
289: #if 0
290: if (iswrite) {
291: printf("\t/* C - %d = %d */\n", memory_cycle_cnt, total_ce020 - memory_cycle_cnt);
292: total_ce020 -= memory_cycle_cnt;
293: } else {
294: printf("\t/* C = %d */\n", total_ce020);
295: }
296: #endif
297: if (0 && total_ce020 <= 0) {
298: printf ("\t/* C was zero */\n");
299: total_ce020 = 1;
300: }
301: if (!did_prefetch)
302: get_prefetch_020 ();
303: if (total_ce020 > 0)
304: addcycles_ce020 (total_ce020);
305:
1.1.1.9 root 306: //printf ("\tregs.irc = %s;\n", prefetch_opcode);
1.1.1.7 root 307: if (0 && total_ce020 >= 2) {
308: printf ("\top_cycles = get_cycles () - op_cycles;\n");
309: printf ("\top_cycles /= cpucycleunit;\n");
310: printf ("\tif (op_cycles < %d) {\n", total_ce020);
311: printf ("\t\tdo_cycles_ce020 ((%d) - op_cycles);\n", total_ce020);
312: printf ("\t}\n");
313: }
314: #if 0
315: if (tail_ce020 > 0) {
316: printf ("\tregs.ce020_tail = %d * cpucycleunit;\n", tail_ce020);
317: printf ("\tregs.ce020_tail_cycles = get_cycles () + regs.ce020_tail;\n");
318: } else {
319: printf ("\tregs.ce020_tail = 0;\n");
1.1.1.4 root 320: }
1.1.1.7 root 321: #endif
322: tail_ce020_done = true;
323: }
324: }
325:
1.1.1.4 root 326:
1.1.1.7 root 327: static void returncycles (const char *s, int cycles)
328: {
329: if (using_ce || using_ce020) {
330: #if 0
331: if (tail_ce020 == 0)
332: printf ("\tregs.ce020memcycles -= 2 * cpucycleunit; /* T=0 */ \n");
333: else if (tail_ce020 == 1)
334: printf ("\tregs.ce020memcycles -= 1 * cpucycleunit; /* T=1 */ \n");
335: else if (tail_ce020 == 2)
336: printf ("\tregs.ce020memcycles -= 0 * cpucycleunit; /* T=2 */\n");
337: #endif
338: printf ("%sreturn;\n", s);
339: return;
1.1.1.4 root 340: }
1.1.1.7 root 341: if (using_simple_cycles)
342: printf ("%sreturn %d * CYCLE_UNIT / 2 + count_cycles;\n", s, cycles);
1.1.1.4 root 343: else
344: printf ("%sreturn %d * CYCLE_UNIT / 2;\n", s, cycles);
345: }
346:
1.1.1.7 root 347: static void addcycles_ce020_4 (const char *name, int head, int tail, int cycles)
1.1.1.4 root 348: {
1.1.1.7 root 349: if (!isce020())
350: return;
351: if (!head && !tail && !cycles)
352: return;
353: printf ("\t/* %s H:%d,T:%d,C:%d */\n", name, head, tail, cycles);
354: }
355: static void addcycles_ce020_5 (const char *name, int head, int tail, int cycles, int ophead)
356: {
357: if (!isce020())
358: return;
359: if (!head && !tail && !cycles && !ophead) {
360: printf ("\t/* OP zero */\n");
1.1.1.4 root 361: return;
362: }
1.1.1.7 root 363: count_cycles += cycles;
364: if (!ophead) {
365: addcycles_ce020_4 (name, head, tail, cycles);
366: } else if (ophead > 0) {
367: printf ("\t/* %s H:%d-,T:%d,C:%d */\n", name, head, tail, cycles);
368: } else {
369: printf ("\t/* %s H:%d+,T:%d,C:%d */\n", name, head, tail, cycles);
370: }
371: }
372:
373: static void addcycles000_nonces(const char *s, const char *sc)
374: {
375: if (using_simple_cycles) {
376: printf("%scount_cycles += (%s) * CYCLE_UNIT / 2;\n", s, sc);
377: count_ncycles++;
378: }
379: }
380: static void addcycles000_nonce(const char *s, int c)
381: {
382: if (using_simple_cycles) {
383: printf("%scount_cycles += %d * CYCLE_UNIT / 2;\n", s, c);
384: count_ncycles++;
385: }
386: }
387:
388: static void addcycles000_onlyce (int cycles)
389: {
390: if (using_ce) {
391: printf ("\t%s (%d);\n", do_cycles, cycles);
392: }
1.1.1.4 root 393: }
394:
395: static void addcycles000 (int cycles)
396: {
1.1.1.7 root 397: if (using_ce) {
398: printf ("\t%s (%d);\n", do_cycles, cycles);
399: }
1.1.1.4 root 400: count_cycles += cycles;
401: }
1.1.1.7 root 402:
403: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 404: static void addcycles000_2 (const char *s, int cycles)
405: {
1.1.1.7 root 406: if (using_ce) {
407: printf ("%s%s (%d);\n", s, do_cycles, cycles);
408: }
1.1.1.4 root 409: count_cycles += cycles;
410: }
1.1.1.7 root 411: #endif
412:
1.1.1.4 root 413:
414: static void addcycles000_3 (const char *s)
415: {
1.1.1.7 root 416: if (using_ce) {
417: printf ("%sif (cycles > 0) %s (cycles);\n", s, do_cycles);
418: }
1.1.1.4 root 419: count_ncycles++;
420: }
421:
422: static int isreg (amodes mode)
423: {
424: if (mode == Dreg || mode == Areg)
425: return 1;
426: return 0;
427: }
428:
429: static void start_brace (void)
430: {
431: n_braces++;
432: printf ("{");
433: }
434:
435: static void close_brace (void)
436: {
437: assert (n_braces > 0);
438: n_braces--;
439: printf ("}");
440: }
441:
442: static void finish_braces (void)
443: {
444: while (n_braces > 0)
445: close_brace ();
446: }
447:
448: static void pop_braces (int to)
449: {
450: while (n_braces > to)
451: close_brace ();
452: }
453:
454: static int bit_size (int size)
455: {
456: switch (size) {
457: case sz_byte: return 8;
458: case sz_word: return 16;
459: case sz_long: return 32;
1.1.1.7 root 460: default: term ();
1.1.1.4 root 461: }
462: return 0;
463: }
464:
465: static const char *bit_mask (int size)
466: {
467: switch (size) {
468: case sz_byte: return "0xff";
469: case sz_word: return "0xffff";
470: case sz_long: return "0xffffffff";
1.1.1.7 root 471: default: term ();
1.1.1.4 root 472: }
473: return 0;
474: }
475:
1.1.1.7 root 476: static void add_mmu040_movem (int movem)
477: {
478: if (movem != 3)
479: return;
480: printf ("\tif (mmu040_movem) {\n");
481: printf ("\t\tsrca = mmu040_movem_ea;\n");
482: printf ("\t} else\n");
483: start_brace ();
484: }
1.1.1.4 root 485:
1.1.1.7 root 486: static void gen_nextilong2 (const char *type, const char *name, int flags, int movem)
1.1.1.4 root 487: {
488: int r = m68k_pc_offset;
489: m68k_pc_offset += 4;
490:
1.1.1.7 root 491: printf ("\t%s %s;\n", type, name);
492: add_mmu040_movem (movem);
1.1.1.4 root 493: if (using_ce020) {
1.1.1.7 root 494: if (flags & GF_NOREFILL)
495: printf("\t%s = %s (%d);\n", name, prefetch_long, r);
496: else
497: printf("\t%s = %s (%d);\n", name, prefetch_long, r);
1.1.1.4 root 498: count_read += 2;
499: } else if (using_ce) {
500: /* we must do this because execution order of (something | something2) is not defined */
501: if (flags & GF_NOREFILL) {
1.1.1.7 root 502: printf ("\t%s = %s (%d) << 16;\n", name, prefetch_word, r + 2);
1.1.1.4 root 503: count_read++;
504: printf ("\t%s |= regs.irc;\n", name);
505: } else {
1.1.1.7 root 506: printf ("\t%s = %s (%d) << 16;\n", name, prefetch_word, r + 2);
1.1.1.4 root 507: count_read++;
1.1.1.7 root 508: printf ("\t%s |= %s (%d);\n", name, prefetch_word, r + 4);
1.1.1.4 root 509: count_read++;
510: }
511: } else {
512: if (using_prefetch) {
513: if (flags & GF_NOREFILL) {
1.1.1.7 root 514: printf ("\t%s = %s (%d) << 16;\n", name, prefetch_word, r + 2);
1.1.1.4 root 515: count_read++;
516: printf ("\t%s |= regs.irc;\n", name);
517: insn_n_cycles += 4;
518: } else {
1.1.1.7 root 519: printf ("\t%s = %s (%d) << 16;\n", name, prefetch_word, r + 2);
520: count_read += 2;
521: printf ("\t%s |= %s (%d);\n", name, prefetch_word, r + 4);
1.1.1.4 root 522: insn_n_cycles += 8;
523: }
524: } else {
525: insn_n_cycles += 8;
1.1.1.7 root 526: printf ("\t%s = %s (%d);\n", name, prefetch_long, r);
1.1.1.4 root 527: }
528: }
529: }
1.1.1.7 root 530: static void gen_nextilong (const char *type, const char *name, int flags)
531: {
532: gen_nextilong2 (type, name, flags, 0);
533: }
1.1.1.4 root 534:
535: static const char *gen_nextiword (int flags)
536: {
537: static char buffer[80];
538: int r = m68k_pc_offset;
539: m68k_pc_offset += 2;
540:
541: if (using_ce020) {
1.1.1.7 root 542: if (flags & GF_NOREFILL)
543: sprintf(buffer, "%s (%d)", prefetch_word, r);
544: else
545: sprintf(buffer, "%s (%d)", prefetch_word, r);
1.1.1.4 root 546: count_read++;
547: } else if (using_ce) {
548: if (flags & GF_NOREFILL) {
549: strcpy (buffer, "regs.irc");
550: } else {
1.1.1.7 root 551: sprintf (buffer, "%s (%d)", prefetch_word, r + 2);
1.1.1.4 root 552: count_read++;
553: }
554: } else {
555: if (using_prefetch) {
556: if (flags & GF_NOREFILL) {
1.1.1.7 root 557: strcpy (buffer, "regs.irc");
1.1.1.4 root 558: } else {
1.1.1.7 root 559: sprintf (buffer, "%s (%d)", prefetch_word, r + 2);
1.1.1.4 root 560: count_read++;
561: insn_n_cycles += 4;
562: }
563: } else {
1.1.1.7 root 564: sprintf (buffer, "%s (%d)", prefetch_word, r);
1.1.1.4 root 565: insn_n_cycles += 4;
566: }
567: }
568: return buffer;
569: }
570:
571: static const char *gen_nextibyte (int flags)
572: {
573: static char buffer[80];
574: int r = m68k_pc_offset;
575: m68k_pc_offset += 2;
576:
1.1.1.7 root 577: if (using_ce020 || using_prefetch_020) {
578: if (flags & GF_NOREFILL)
579: sprintf(buffer, "(uae_u8)%s (%d)", prefetch_word, r);
580: else
581: sprintf(buffer, "(uae_u8)%s (%d)", prefetch_word, r);
1.1.1.4 root 582: count_read++;
583: } else if (using_ce) {
584: if (flags & GF_NOREFILL) {
585: strcpy (buffer, "(uae_u8)regs.irc");
586: } else {
1.1.1.7 root 587: sprintf (buffer, "(uae_u8)%s (%d)", prefetch_word, r + 2);
1.1.1.4 root 588: count_read++;
589: }
590: } else {
591: insn_n_cycles += 4;
592: if (using_prefetch) {
593: if (flags & GF_NOREFILL) {
1.1.1.7 root 594: strcpy (buffer, "(uae_u8)regs.irc");
1.1.1.4 root 595: } else {
1.1.1.7 root 596: sprintf (buffer, "(uae_u8)%s (%d)", prefetch_word, r + 2);
1.1.1.4 root 597: insn_n_cycles += 4;
598: count_read++;
599: }
600: } else {
1.1.1.7 root 601: sprintf (buffer, "%s (%d)", srcbi, r);
1.1.1.4 root 602: insn_n_cycles += 4;
603: }
604: }
605: return buffer;
606: }
607:
1.1.1.9 root 608: static void makefromsr(void)
1.1.1.4 root 609: {
1.1.1.7 root 610: printf ("\tMakeFromSR();\n");
611: if (using_ce || isce020())
612: printf ("\tregs.ipl_pin = intlev ();\n");
613: }
614:
1.1.1.9 root 615: static void makefromsr_t0(void)
616: {
617: printf ("\tMakeFromSR_T0();\n");
618: if (using_ce || isce020())
619: printf ("\tregs.ipl_pin = intlev ();\n");
620: }
621:
1.1.1.7 root 622: static void check_ipl (void)
623: {
624: if (ipl_fetched)
625: return;
626: if (using_ce || isce020())
627: printf ("\tipl_fetch ();\n");
628: ipl_fetched = 1;
629: }
630:
631: static void single_check_ipl(void)
632: {
633: check_ipl();
634: ipl_fetched = 2;
635:
636: }
637: /* this is not true, it seems to be microcode controller */
638:
639: /* Apparently interrupt state is sampled
640: * during any memory access. Because we don't
641: * know if there are future memory accesses,
642: * we'll check each memory access after prefetch
643: * and recheck interrupt state again.
644: */
645: static void check_ipl_again (void)
646: {
647: if (ipl_fetched != 1)
1.1.1.4 root 648: return;
649: if (using_ce)
650: printf ("\tipl_fetch ();\n");
651: }
652:
1.1.1.7 root 653: static void irc2ir_2 (bool dozero)
654: {
655: if (!using_prefetch)
656: return;
657: if (ir2irc)
658: return;
659: ir2irc = 1;
660: printf ("\tregs.ir = regs.irc;\n");
661: if (dozero)
662: printf ("\tregs.irc = 0;\n");
663: check_ipl ();
664: }
665: static void irc2ir (void)
666: {
667: irc2ir_2 (false);
668: }
1.1.1.4 root 669:
670: static void fill_prefetch_2 (void)
671: {
672: if (!using_prefetch)
673: return;
1.1.1.7 root 674: printf ("\t%s (%d);\n", prefetch_word, m68k_pc_offset + 2);
1.1.1.4 root 675: did_prefetch = 1;
1.1.1.7 root 676: ir2irc = 0;
1.1.1.4 root 677: count_read++;
678: insn_n_cycles += 4;
679: }
680:
681: static void fill_prefetch_1 (int o)
682: {
1.1.1.7 root 683: if (using_prefetch) {
684: printf ("\t%s (%d);\n", prefetch_word, o);
685: did_prefetch = 1;
686: ir2irc = 0;
687: count_read++;
688: insn_n_cycles += 4;
1.1.1.4 root 689: }
690: }
691:
1.1.1.9 root 692: #ifndef WINUAE_FOR_HATARI
693: static void fill_prefetch_full_2 (void)
694: {
695: if (using_prefetch) {
696: fill_prefetch_1 (0);
697: irc2ir ();
698: fill_prefetch_1 (2);
699: } else if (isprefetch020()) {
700: did_prefetch = 2;
701: total_ce020 -= 4;
702: returntail (false);
703: if (cpu_level >= 3)
704: printf ("\tfill_prefetch_030();\n");
705: else if (cpu_level == 2)
706: printf ("\tfill_prefetch_020();\n");
707: }
708: }
709: #endif
710:
711: // don't check trace bits
712: static void fill_prefetch_full_ntx (void)
713: {
714: if (using_prefetch) {
715: fill_prefetch_1 (0);
716: irc2ir ();
717: fill_prefetch_1 (2);
718: } else if (isprefetch020()) {
719: did_prefetch = 2;
720: total_ce020 -= 4;
721: returntail (false);
722: if (cpu_level >= 3)
723: printf ("\tfill_prefetch_030_ntx();\n");
724: else if (cpu_level == 2)
725: printf ("\tfill_prefetch_020_ntx();\n");
726: }
727: }
728: // check trace bits
1.1.1.4 root 729: static void fill_prefetch_full (void)
730: {
1.1.1.7 root 731: if (using_prefetch) {
732: fill_prefetch_1 (0);
733: irc2ir ();
734: fill_prefetch_1 (2);
735: } else if (isprefetch020()) {
736: did_prefetch = 2;
737: total_ce020 -= 4;
738: returntail (false);
739: if (cpu_level >= 3)
1.1.1.9 root 740: printf ("\tfill_prefetch_030();\n");
1.1.1.7 root 741: else if (cpu_level == 2)
1.1.1.9 root 742: printf ("\tfill_prefetch_020();\n");
743: } else if (!using_prefetch_020 && cpu_level >= 2) {
744: printf("\tif(regs.t0) check_t0_trace();\n");
1.1.1.7 root 745: }
746: }
747:
748: // 68000 and 68010 only
749: static void fill_prefetch_full_000 (void)
750: {
751: if (!using_prefetch)
752: return;
753: fill_prefetch_full ();
754: }
755:
756: // 68020+
757: static void fill_prefetch_full_020 (void)
758: {
1.1.1.9 root 759: if (!using_prefetch_020) {
760: printf("\tif(regs.t0) check_t0_trace();\n");
1.1.1.7 root 761: return;
1.1.1.9 root 762: }
1.1.1.7 root 763: fill_prefetch_full ();
1.1.1.4 root 764: }
765:
766: static void fill_prefetch_0 (void)
767: {
768: if (!using_prefetch)
769: return;
1.1.1.7 root 770: printf ("\t%s (0);\n", prefetch_word);
1.1.1.4 root 771: did_prefetch = 1;
1.1.1.7 root 772: ir2irc = 0;
1.1.1.4 root 773: count_read++;
774: insn_n_cycles += 4;
775: }
776:
1.1.1.7 root 777: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 778: static void dummy_prefetch (void)
779: {
780: int o = m68k_pc_offset + 2;
781: if (!using_prefetch)
782: return;
1.1.1.7 root 783: printf ("\t%s (%d);\n", srcwi, o);
1.1.1.4 root 784: count_read++;
785: insn_n_cycles += 4;
786: }
1.1.1.7 root 787: #endif
1.1.1.4 root 788:
789: static void fill_prefetch_next_1 (void)
790: {
791: irc2ir ();
792: fill_prefetch_1 (m68k_pc_offset + 2);
793: }
794:
795: static void fill_prefetch_next (void)
796: {
1.1.1.7 root 797: if (using_prefetch) {
798: fill_prefetch_next_1 ();
1.1.1.4 root 799: }
1.1.1.7 root 800: // if (using_prefetch_020) {
801: // printf ("\t%s (%d);\n", prefetch_word, m68k_pc_offset);
802: // did_prefetch = 1;
803: // }
1.1.1.4 root 804: }
805:
806: static void fill_prefetch_finish (void)
807: {
1.1.1.7 root 808: if (did_prefetch)
1.1.1.4 root 809: return;
1.1.1.7 root 810: if (using_prefetch) {
811: fill_prefetch_1 (m68k_pc_offset);
812: }
813: if (using_prefetch_020) {
814: did_prefetch = 1;
815: }
1.1.1.4 root 816: }
817:
818: static void setpc (const char *format, ...)
819: {
820: va_list parms;
821: char buffer[1000];
822:
823: va_start (parms, format);
824: _vsnprintf (buffer, 1000 - 1, format, parms);
825: va_end (parms);
826:
1.1.1.10! root 827: if (using_mmu)
! 828: printf("\tm68k_setpci(%s);\n", buffer);
! 829: else if (using_prefetch || using_prefetch_020)
! 830: printf ("\tm68k_setpci_j(%s);\n", buffer);
1.1.1.4 root 831: else
1.1.1.10! root 832: printf ("\tm68k_setpc_j(%s);\n", buffer);
1.1.1.4 root 833: }
834:
835: static void incpc (const char *format, ...)
836: {
837: va_list parms;
838: char buffer[1000];
839:
840: va_start (parms, format);
841: _vsnprintf (buffer, 1000 - 1, format, parms);
842: va_end (parms);
843:
1.1.1.7 root 844: if (using_mmu || using_prefetch || using_prefetch_020)
1.1.1.4 root 845: printf ("\tm68k_incpci (%s);\n", buffer);
846: else
847: printf ("\tm68k_incpc (%s);\n", buffer);
848: }
849:
850: static void sync_m68k_pc (void)
851: {
1.1.1.7 root 852: m68k_pc_offset_old = m68k_pc_offset;
1.1.1.4 root 853: if (m68k_pc_offset == 0)
854: return;
855: incpc ("%d", m68k_pc_offset);
1.1.1.7 root 856: m68k_pc_total += m68k_pc_offset;
1.1.1.4 root 857: m68k_pc_offset = 0;
858: }
859:
1.1.1.7 root 860: static void clear_m68k_offset(void)
861: {
862: m68k_pc_total += m68k_pc_offset;
863: m68k_pc_offset = 0;
864: }
865:
866: static void sync_m68k_pc_noreset (void)
867: {
868: sync_m68k_pc ();
869: m68k_pc_offset = m68k_pc_offset_old;
870: }
871:
872: static void addmmufixup (const char *reg)
1.1.1.4 root 873: {
874: if (!using_mmu)
875: return;
1.1.1.7 root 876: if (using_mmu == 68040 && (mmufixupstate || mmufixupcnt > 0))
877: return;
878: printf ("\tmmufixup[%d].reg = %s;\n", mmufixupcnt, reg);
879: printf ("\tmmufixup[%d].value = m68k_areg (regs, %s);\n", mmufixupcnt, reg);
880: mmufixupstate |= 1 << mmufixupcnt;
881: mmufixupcnt++;
882: }
883:
884: static void clearmmufixup (int cnt)
885: {
886: if (mmufixupstate & (1 << cnt)) {
887: printf ("\tmmufixup[%d].reg = -1;\n", cnt);
888: mmufixupstate &= ~(1 << cnt);
889: }
890: }
891:
1.1.1.10! root 892: #ifndef WINUAE_FOR_HATARI
! 893: static bool is_gen_set_fault_pc(void)
1.1.1.7 root 894: {
1.1.1.10! root 895: return using_mmu == 68040 || using_mmu == 68030;
! 896: }
! 897: #endif
! 898:
! 899: static void gen_set_fault_pc (bool multi)
! 900: {
! 901: int m68k_pc_total_old = m68k_pc_total;
! 902: if (using_mmu == 68040) {
! 903: sync_m68k_pc();
! 904: printf("\tregs.instruction_pc = %s;\n", getpc);
! 905: printf("\tmmu_restart = false;\n");
! 906: m68k_pc_offset = 0;
! 907: clearmmufixup(0);
! 908: } else if (using_mmu == 68030) {
! 909: sync_m68k_pc();
! 910: printf("\tregs.instruction_pc = %s;\n", getpc);
! 911: printf("\tmmu030_state[1] |= MMU030_STATEFLAG1_LASTWRITE;\n");
! 912: m68k_pc_offset = 0;
! 913: }
! 914: if (multi)
! 915: m68k_pc_total = m68k_pc_total_old;
1.1.1.4 root 916: }
917:
918: static void syncmovepc (int getv, int flags)
919: {
920: #if 0
921: if (!(flags & GF_MOVE))
922: return;
923: if (getv == 1) {
924: sync_m68k_pc ();
925: //fill_prefetch_next ();
926: }
927: #endif
928: }
929:
1.1.1.7 root 930: static void head_cycs (int h)
931: {
932: if (head_ce020_cycs_done)
933: return;
934: if (h < 0)
935: return;
936: //printf ("\tdo_sync_tail (%d);\n", h);
937: //printf ("\tdo_head_cycles_ce020 (%d);\n", h);
938: head_ce020_cycs_done = true;
939: tail_ce020 = -1;
940: }
1.1.1.4 root 941:
1.1.1.7 root 942: static void add_head_cycs (int h)
943: {
944: if (!isce020())
945: return;
946: head_ce020_cycs_done = false;
947: head_cycs (h);
948: }
1.1.1.4 root 949:
1.1.1.7 root 950: static void addopcycles_ce20 (int h, int t, int c, int subhead)
1.1.1.4 root 951: {
1.1.1.7 root 952: head_cycs (h);
1.1.1.4 root 953:
1.1.1.7 root 954: //c = 0;
955: #if 0
956: if (tail_ce020 == 1)
957: printf ("\tregs.ce020memcycles -= 1 * cpucycleunit; /* T=1 */ \n");
958: else if (tail_ce020 == 2)
959: printf ("\tregs.ce020memcycles -= 2 * cpucycleunit; /* T=2 */\n");
960: #endif
961: if (1 && !subhead && (h > 0 || t > 0 || c > 0) && got_ea_ce020) {
962: if (!did_prefetch) {
963: get_prefetch_020 ();
964: did_prefetch = 1;
965: }
966: if (1) {
967: if (h > 0) {
1.1.1.9 root 968: printf ("\tlimit_cycles_ce020(%d);\n", h);
1.1.1.7 root 969: } else {
1.1.1.9 root 970: printf ("\tlimit_all_cycles_ce020();\n");
1.1.1.7 root 971: }
972: }
973: }
1.1.1.4 root 974:
1.1.1.7 root 975: #if 0
976: if (tail_ce020 >= 0 && h >= 0 && head_in_ea_ce020 == 0) {
977: int largest = tail_ce020 > h ? tail_ce020: h;
978: if (tail_ce020 != h) {
979: //printf ("\tdo_cycles_ce020 (%d - %d);\n", tail_ce020 > h ? tail_ce020 : h, tail_ce020 > h ? h : tail_ce020);
980: //printf ("\tdo_cycles_ce020 (%d - %d);\n", tail_ce020 > h ? tail_ce020 : h, tail_ce020 > h ? h : tail_ce020);
981: if (h) {
982: printf ("\tregs.ce020memcycles -= %d * cpucycleunit;\n", h);
983: printf ("\tif (regs.ce020memcycles < 0) {\n");
984: //printf ("\t\tx_do_cycles (-regs.ce020memcycles);\n");
985: printf ("\t\tregs.ce020memcycles = 0;\n");
986: printf ("\t}\n");
987: } else {
988: printf ("\tregs.ce020memcycles = 0;\n");
989: }
990: //printf ("\tregs.ce020memcycles = 0;\n");
991:
992: #if 0
993: if (tail_ce020)
994: printf ("\tregs.ce020_tail = get_cycles () - regs.ce020_tail;\n");
995: else
996: printf ("\tregs.ce020_tail = 0;\n");
997: printf ("\tif (regs.ce020_tail < %d * cpucycleunit)\n", largest);
998: printf ("\t\tx_do_cycles (%d * cpucycleunit - regs.ce020_tail);\n", largest);
999: #endif
1000: } else if (h) {
1001: printf ("\t/* ea tail == op head (%d) */\n", h);
1002:
1003: printf ("\tregs.ce020memcycles -= %d * cpucycleunit;\n", h);
1004: printf ("\tif (regs.ce020memcycles < 0) {\n");
1005: //printf ("\t\tx_do_cycles (-regs.ce020memcycles);\n");
1006: printf ("\t\tregs.ce020memcycles = 0;\n");
1007: printf ("\t}\n");
1008: }
1009: }
1010: #endif
1011:
1012: if (h < 0)
1013: h = 0;
1.1.1.9 root 1014:
1015: if (c < 8) // HACK
1016: c = 0;
1.1.1.7 root 1017:
1018: // c = internal cycles needed after head cycles and before tail cycles. Not total cycles.
1019: addcycles_ce020_5 ("op", h, t, c - h - t, -subhead);
1020: //printf ("\tregs.irc = get_word_ce020_prefetch (%d);\n", m68k_pc_offset);
1021: #if 0
1022: if (c - h - t > 0) {
1023: printf ("\t%s (%d);\n", do_cycles, c - h - t);
1024: count_cycles_ce020 += c;
1025: count_cycles += c;
1026: }
1027: #endif
1028: //printf ("\tregs.ce020_tail = 0;\n");
1029: total_ce020 = c;
1030: tail_ce020 = t;
1031: // if (total_ce020 >= 2)
1032: // printf ("\tint op_cycles = get_cycles ();\n");
1033: }
1034:
1035: static void addop_ce020 (struct instr *curi, int subhead)
1036: {
1.1.1.9 root 1037: if (isce020()) {
1038: int h = curi->head;
1039: int t = curi->tail;
1040: int c = curi->clocks;
1041: #if 0
1042: if ((((curi->sduse & 2) && !isreg (curi->smode)) || (((curi->sduse >> 4) & 2) && !isreg (curi->dmode))) && using_waitstates) {
1043: t += using_waitstates;
1044: c += using_waitstates;
1045: }
1046: #endif
1047: addopcycles_ce20 (h, t, c, -subhead);
1.1.1.7 root 1048: }
1049: }
1050:
1051: static void addcycles_ea_ce020_5 (const char *ea, int h, int t, int c, int oph)
1052: {
1.1.1.9 root 1053: if (!isce020())
1054: return;
1055:
1.1.1.7 root 1056: head_cycs (h + oph);
1057:
1058: // if (!h && !h && !c && !oph)
1059: // return;
1060:
1061: c = c - h - t;
1062:
1.1.1.9 root 1063: c = 0; // HACK
1.1.1.7 root 1064:
1065: if (!oph) {
1066: printf ("\t/* ea H:%d,T:%d,C:%d %s */\n", h, t, c, ea);
1067: } else {
1068: if (oph && t)
1069: term_err ("Both op head and tail can't be non-zero");
1070: if (oph > 0) {
1071: printf ("\t/* ea H:%d+%d=%d,T:%d,C:%d %s */\n", h, oph, h + oph, t, c, ea);
1072: h += oph;
1073: } else {
1074: printf ("\t/* ea H:%d-%d=%d,T:%d,C:%d %s */\n", h, -oph, h + oph, t, c, ea);
1075: h += oph;
1076: }
1077: }
1078:
1079: if (h) {
1.1.1.9 root 1080: printf ("\tlimit_cycles_ce020(%d);\n", h);
1.1.1.7 root 1081: } else {
1.1.1.9 root 1082: printf ("\tlimit_all_cycles_ce020();\n");
1.1.1.7 root 1083: }
1084:
1085: if (1 && c > 0) {
1086: printf ("\t%s (%d);\n", do_cycles, c);
1087: count_cycles += c;
1088: }
1089: tail_ce020 = t;
1090: head_in_ea_ce020 = oph;
1091: got_ea_ce020 = true;
1092: // if (t > 0)
1093: // printf ("\tregs.ce020_tail = get_cycles () + %d * cpucycleunit;\n", t);
1094: }
1095: static void addcycles_ea_ce020_4 (const char *ea, int h, int t, int c)
1096: {
1097: addcycles_ea_ce020_5 (ea, h, t, c, 0);
1098: }
1099:
1100: #define SETCE020(h2,t2,c2) { h = h2; t = t2; c = c2; }
1101: #define SETCE020H(h2,t2,c2) { h = h2; oph = curi ? curi->head : 0; t = t2; c = c2; }
1102:
1103: static int gence020cycles_fiea (struct instr *curi, wordsizes ssize, amodes dmode)
1104: {
1105: bool l = ssize == sz_long;
1106: int h = 0, t = 0, c = 0, oph = 0;
1107: switch ((int)dmode)
1108: {
1109: case Dreg:
1110: case Areg:
1111: if (!l)
1112: SETCE020H(2, 0, 2)
1113: else
1114: SETCE020H(4, 0, 4)
1115: break;
1116: case Aind: // (An)
1117: if (!l)
1118: SETCE020(1, 1, 3)
1119: else
1120: SETCE020(1, 0, 4)
1121: break;
1122: case Aipi: // (An)+
1123: if (!l)
1124: SETCE020(2, 1, 5)
1125: else
1126: SETCE020(4, 1, 7)
1127: break;
1128: case Apdi: // -(An)
1129: if (!l)
1130: SETCE020(2, 2, 4)
1131: else
1132: SETCE020(2, 0, 4)
1133: break;
1134: case Ad8r: // (d8,An,Xn)
1135: case PC8r: // (d8,PC,Xn)
1136: if (!l)
1137: SETCE020(6, 2, 8)
1138: else
1139: SETCE020(8, 2, 10)
1140: break;
1141: case Ad16: // (d16,An)
1142: case PC16: // (d16,PC)
1143: if (!l)
1144: SETCE020(2, 0, 4)
1145: else
1146: SETCE020(4, 0, 6)
1147: break;
1148: case absw:
1149: if (!l)
1150: SETCE020(4, 2, 6)
1151: else
1152: SETCE020(6, 2, 8)
1153: break;
1154: case absl:
1155: if (!l)
1156: SETCE020(3, 0, 6)
1157: else
1158: SETCE020(5, 0, 8)
1159: break;
1160: }
1161: addcycles_ea_ce020_5 ("fiea", h, t, c, oph);
1162: return oph;
1163: }
1164:
1165:
1166: static int gence020cycles_ciea (struct instr *curi, wordsizes ssize, amodes dmode)
1167: {
1168: int h = 0, t = 0, c = 0, oph = 0;
1169: bool l = ssize == sz_long;
1170: switch ((int)dmode)
1171: {
1172: case Dreg:
1173: case Areg:
1174: if (!l)
1175: SETCE020H(2, 0, 2)
1176: else
1177: SETCE020H(4, 0, 4)
1178: break;
1179: case Aind: // (An)
1180: if (!l)
1181: SETCE020H(2, 0, 2)
1182: else
1183: SETCE020H(4, 0, 4)
1184: break;
1185: case Aipi: // (An)+
1186: if (!l)
1187: SETCE020(2, 0, 4)
1188: else
1189: SETCE020(4, 0, 6)
1190: break;
1191: case Apdi: // -(An)
1192: if (!l)
1193: SETCE020H(2, 0, 2)
1194: else
1195: SETCE020H(4, 0, 4)
1196: break;
1197: case Ad8r: // (d8,An,Xn)
1198: case PC8r: // (d8,PC,Xn)
1199: if (!l)
1200: SETCE020H(6, 0, 6)
1201: else
1202: SETCE020H(8, 0, 8)
1203: break;
1204: case Ad16: // (d16,An)
1205: case PC16: // (d16,PC)
1206: if (!l)
1207: SETCE020H(4, 0, 4)
1208: else
1209: SETCE020H(6, 0, 6)
1210: break;
1211: case absw:
1212: if (!l)
1213: SETCE020H(4, 0, 4)
1214: else
1215: SETCE020H(6, 0, 6)
1216: break;
1217: case absl:
1218: if (!l)
1219: SETCE020H(6, 0, 6)
1220: else
1221: SETCE020H(8, 0, 8)
1222: break;
1223: }
1224: addcycles_ea_ce020_5 ("ciea", h, t, c, oph);
1225: return oph;
1226: }
1227:
1228:
1229: static int gence020cycles_fea (amodes mode)
1230: {
1231: int h = 0, t = 0, c = 0, ws = 0;
1232: switch ((int)mode)
1233: {
1234: case Dreg:
1235: case Areg:
1236: SETCE020(0, 0, 0)
1237: break;
1238: case Aind: // (An)
1239: ws++;
1240: SETCE020(1, 1, 3)
1241: break;
1242: case Aipi: // (An)+
1243: ws++;
1244: SETCE020(0, 1, 3)
1245: break;
1246: case Apdi: // -(An)
1247: ws++;
1248: SETCE020(2, 2, 4)
1249: break;
1250: case Ad8r: // (d8,An,Xn)
1251: case PC8r: // (d8,PC,Xn)
1252: ws++;
1253: SETCE020(4, 2, 6)
1254: break;
1255: case Ad16: // (d16,An)
1256: case PC16: // (d16,PC)
1257: ws++;
1258: SETCE020(2, 2, 4)
1259: break;
1260: case absw:
1261: ws++;
1262: SETCE020(2, 2, 4)
1263: break;
1264: case absl:
1265: ws++;
1266: SETCE020(1, 0, 4)
1267: break;
1268: }
1269: #if 0
1270: if (using_waitstates) {
1271: t += ws * using_waitstates;
1272: c += ws * using_waitstates;
1273: }
1274: #endif
1275: addcycles_ea_ce020_4 ("fea", h, t, c);
1276: return 0;
1277: }
1278:
1279: static int gence020cycles_cea (struct instr *curi, amodes mode)
1280: {
1281: int h = 0, t = 0, c = 0, oph = 0;
1282: switch ((int)mode)
1283: {
1284: case Dreg:
1285: case Areg:
1286: SETCE020(0, 0, 0);
1287: break;
1288: case Aind: // (An)
1289: SETCE020H(2 + h, 0, 2);
1290: break;
1291: case Aipi: // (An)+
1292: SETCE020(0, 0, 2);
1293: break;
1294: case Apdi: // -(An)
1295: SETCE020H(2, 0, 2)
1296: break;
1297: case Ad8r: // (d8,An,Xn)
1298: case PC8r: // (d8,PC,Xn)
1299: SETCE020H(4, 0, 4)
1300: break;
1301: case Ad16: // (d16,An)
1302: case PC16: // (d16,PC)
1303: SETCE020H(2, 0, 2)
1304: break;
1305: case absw:
1306: SETCE020H(2, 0, 2)
1307: break;
1308: case absl:
1309: SETCE020H(4, 0, 4)
1310: break;
1311: }
1312: addcycles_ea_ce020_5 ("cea", h, t, c, oph);
1313: return oph;
1314: }
1315:
1316: static int gence020cycles_jea (struct instr *curi, amodes mode)
1317: {
1318: int h = 0, t = 0, c = 0, oph = 0;
1319: switch ((int)mode)
1320: {
1321: case Aind: // (An)
1322: SETCE020H(2, 0, 2)
1323: break;
1324: case Ad16: // (d16,An)
1325: case PC16: // (d16,PC)
1326: SETCE020H(4, 0, 4)
1327: break;
1328: case absw:
1329: SETCE020H(2, 0, 2)
1330: break;
1331: case absl:
1332: SETCE020H(2, 0, 2)
1333: break;
1334: }
1335: addcycles_ea_ce020_5 ("jea", h, t, c, oph);
1336: return oph;
1337: }
1338:
1339: static void next_level_000 (void)
1340: {
1341: if (next_cpu_level < 0)
1342: next_cpu_level = 0;
1343: }
1344:
1345: static void maybeaddop_ce020 (int flags)
1346: {
1347: if (flags & GF_OPCE020)
1348: addop_ce020 (curi_ce020, subhead_ce020);
1349: }
1350:
1351:
1352: /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
1353: * the calling routine handles Apdi and Aipi modes.
1354: * gb-- movem == 2 means the same thing but for a MOVE16 instruction */
1355:
1.1.1.9 root 1356: /* fixup indicates if we want to fix up address registers in pre decrement
1.1.1.7 root 1357: * or post increment mode now (0) or later (1). A value of 2 will then be
1358: * used to do the actual fix up. This allows to do all memory readings
1359: * before any register is modified, and so to rerun operation without
1360: * side effect in case a bus fault is generated by any memory access.
1361: * XJ - 2006/11/13 */
1362:
1363: static void genamode2x (amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem, int flags, int fetchmode)
1364: {
1365: char namea[100];
1366: bool rmw = false;
1367: int pc_68000_offset = m68k_pc_offset;
1368: int pc_68000_offset_fetch = 0;
1369: int pc_68000_offset_store = 0;
1370:
1371: sprintf (namea, "%sa", name);
1372: if ((flags & GF_RMW) && using_mmu == 68060) {
1373: strcpy (rmw_varname, name);
1374: candormw = true;
1375: rmw = true;
1376: }
1377:
1378: if (mode == Ad8r || mode == PC8r) {
1379: genamode8r_offset[genamode_cnt] = m68k_pc_total + m68k_pc_offset;
1380: genamode_cnt++;
1381: }
1382:
1383: start_brace ();
1384:
1385: switch (mode) {
1386: case Dreg:
1387: if (movem)
1388: term ();
1.1.1.4 root 1389: if (getv == 1)
1390: switch (size) {
1391: case sz_byte:
1392: #ifdef USE_DUBIOUS_BIGENDIAN_OPTIMIZATION
1393: /* This causes the target compiler to generate better code on few systems */
1394: printf ("\tuae_s8 %s = ((uae_u8*)&m68k_dreg (regs, %s))[3];\n", name, reg);
1395: #else
1396: printf ("\tuae_s8 %s = m68k_dreg (regs, %s);\n", name, reg);
1397: #endif
1398: break;
1399: case sz_word:
1400: #ifdef USE_DUBIOUS_BIGENDIAN_OPTIMIZATION
1401: printf ("\tuae_s16 %s = ((uae_s16*)&m68k_dreg (regs, %s))[1];\n", name, reg);
1402: #else
1403: printf ("\tuae_s16 %s = m68k_dreg (regs, %s);\n", name, reg);
1404: #endif
1405: break;
1406: case sz_long:
1407: printf ("\tuae_s32 %s = m68k_dreg (regs, %s);\n", name, reg);
1408: break;
1409: default:
1.1.1.7 root 1410: term ();
1.1.1.4 root 1411: }
1.1.1.7 root 1412: maybeaddop_ce020 (flags);
1.1.1.4 root 1413: syncmovepc (getv, flags);
1414: return;
1415: case Areg:
1416: if (movem)
1.1.1.7 root 1417: term ();
1.1.1.4 root 1418: if (getv == 1)
1419: switch (size) {
1420: case sz_word:
1421: printf ("\tuae_s16 %s = m68k_areg (regs, %s);\n", name, reg);
1422: break;
1423: case sz_long:
1424: printf ("\tuae_s32 %s = m68k_areg (regs, %s);\n", name, reg);
1425: break;
1426: default:
1.1.1.7 root 1427: term ();
1.1.1.4 root 1428: }
1.1.1.7 root 1429: maybeaddop_ce020 (flags);
1.1.1.4 root 1430: syncmovepc (getv, flags);
1431: return;
1432: case Aind: // (An)
1.1.1.7 root 1433: switch (fetchmode)
1434: {
1435: case fetchmode_fea:
1436: addcycles_ce020 (1);
1437: break;
1438: case fetchmode_cea:
1439: addcycles_ce020 (2);
1440: break;
1441: case fetchmode_jea:
1442: addcycles_ce020 (2);
1443: break;
1444: }
1445: printf ("\tuaecptr %sa;\n", name);
1446: add_mmu040_movem (movem);
1447: printf ("\t%sa = m68k_areg (regs, %s);\n", name, reg);
1.1.1.4 root 1448: break;
1449: case Aipi: // (An)+
1.1.1.7 root 1450: switch (fetchmode)
1451: {
1452: case fetchmode_fea:
1453: addcycles_ce020 (1);
1454: break;
1455: case fetchmode_cea:
1456: break;
1457: }
1458: printf ("\tuaecptr %sa;\n", name);
1459: add_mmu040_movem (movem);
1460: printf ("\t%sa = m68k_areg (regs, %s);\n", name, reg);
1.1.1.4 root 1461: break;
1462: case Apdi: // -(An)
1.1.1.7 root 1463: switch (fetchmode)
1464: {
1465: case fetchmode_fea:
1466: case fetchmode_cea:
1467: addcycles_ce020 (2);
1468: break;
1469: }
1.1.1.4 root 1470: printf ("\tuaecptr %sa;\n", name);
1.1.1.7 root 1471: add_mmu040_movem (movem);
1.1.1.4 root 1472: switch (size) {
1473: case sz_byte:
1474: if (movem)
1475: printf ("\t%sa = m68k_areg (regs, %s);\n", name, reg);
1476: else
1477: printf ("\t%sa = m68k_areg (regs, %s) - areg_byteinc[%s];\n", name, reg, reg);
1478: break;
1479: case sz_word:
1480: printf ("\t%sa = m68k_areg (regs, %s) - %d;\n", name, reg, movem ? 0 : 2);
1481: break;
1482: case sz_long:
1483: printf ("\t%sa = m68k_areg (regs, %s) - %d;\n", name, reg, movem ? 0 : 4);
1484: break;
1485: default:
1.1.1.7 root 1486: term ();
1.1.1.4 root 1487: }
1488: if (!(flags & GF_APDI)) {
1489: addcycles000 (2);
1490: insn_n_cycles += 2;
1491: count_cycles_ea += 2;
1.1.1.7 root 1492: pc_68000_offset_fetch += 2;
1.1.1.4 root 1493: }
1494: break;
1495: case Ad16: // (d16,An)
1.1.1.7 root 1496: printf ("\tuaecptr %sa;\n", name);
1497: add_mmu040_movem (movem);
1498: printf ("\t%sa = m68k_areg (regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword (flags));
1499: count_read_ea++;
1500: break;
1501: case PC16: // (d16,PC)
1502: printf ("\tuaecptr %sa;\n", name);
1503: add_mmu040_movem (movem);
1504: printf ("\t%sa = %s + %d;\n", name, getpc, m68k_pc_offset);
1505: printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags));
1.1.1.4 root 1506: break;
1507: case Ad8r: // (d8,An,Xn)
1.1.1.7 root 1508: switch (fetchmode)
1509: {
1510: case fetchmode_fea:
1511: addcycles_ce020 (4);
1512: break;
1513: case fetchmode_cea:
1514: case fetchmode_jea:
1515: break;
1516: }
1.1.1.4 root 1517: printf ("\tuaecptr %sa;\n", name);
1518: if (cpu_level > 1) {
1519: if (next_cpu_level < 1)
1520: next_cpu_level = 1;
1521: sync_m68k_pc ();
1.1.1.7 root 1522: add_mmu040_movem (movem);
1.1.1.4 root 1523: start_brace ();
1524: /* This would ordinarily be done in gen_nextiword, which we bypass. */
1525: insn_n_cycles += 4;
1.1.1.7 root 1526: printf ("\t%sa = %s (m68k_areg (regs, %s), %d);\n", name, disp020, reg, disp020cnt++);
1.1.1.4 root 1527: } else {
1528: if (!(flags & GF_AD8R)) {
1529: addcycles000 (2);
1530: insn_n_cycles += 2;
1531: count_cycles_ea += 2;
1.1.1.7 root 1532: #ifdef WINUAE_FOR_HATARI
1533: /* Hatari : on 68000 ST, Ad8r causes an unaligned memory prefetch and take 2 cycles more */
1534: /* JSR, JMP, LEA and PEA are handled separately */
1535: /* We add 2 cycles only in 68000 prefetch mode, 68000 CE mode is handled at the memory access level */
1536: if ( using_prefetch && !using_ce )
1537: printf ("\tBusCyclePenalty += 2;\n");
1538: #endif
1.1.1.4 root 1539: }
1.1.1.7 root 1540: if ((flags & GF_NOREFILL) && using_prefetch) {
1541: printf ("\t%sa = %s (m68k_areg (regs, %s), regs.irc);\n", name, disp000, reg);
1542: } else {
1543: printf ("\t%sa = %s (m68k_areg (regs, %s), %s);\n", name, disp000, reg, gen_nextiword (flags));
1544: }
1545: count_read_ea++;
1.1.1.4 root 1546: }
1547: break;
1548: case PC8r: // (d8,PC,Xn)
1.1.1.7 root 1549: switch (fetchmode)
1550: {
1551: case fetchmode_fea:
1552: addcycles_ce020 (4);
1553: break;
1554: case fetchmode_cea:
1555: case fetchmode_jea:
1556: break;
1557: }
1.1.1.4 root 1558: printf ("\tuaecptr tmppc;\n");
1559: printf ("\tuaecptr %sa;\n", name);
1560: if (cpu_level > 1) {
1561: if (next_cpu_level < 1)
1562: next_cpu_level = 1;
1563: sync_m68k_pc ();
1.1.1.7 root 1564: add_mmu040_movem (movem);
1.1.1.4 root 1565: start_brace ();
1566: /* This would ordinarily be done in gen_nextiword, which we bypass. */
1567: insn_n_cycles += 4;
1.1.1.7 root 1568: printf ("\ttmppc = %s;\n", getpc);
1569: printf ("\t%sa = %s (tmppc, %d);\n", name, disp020, disp020cnt++);
1.1.1.4 root 1570: } else {
1.1.1.7 root 1571: printf ("\ttmppc = %s + %d;\n", getpc, m68k_pc_offset);
1.1.1.4 root 1572: if (!(flags & GF_PC8R)) {
1573: addcycles000 (2);
1574: insn_n_cycles += 2;
1575: count_cycles_ea += 2;
1.1.1.7 root 1576: #ifdef WINUAE_FOR_HATARI
1577: /* Hatari : on 68000 ST, Ad8r causes an unaligned memory prefetch and take 2 cycles more */
1578: /* JSR, JMP, LEA and PEA are handled separately */
1579: /* We add 2 cycles only in 68000 prefetch mode, 68000 CE mode is handled at the memory access level */
1580: if ( using_prefetch && !using_ce )
1581: printf ("\tBusCyclePenalty += 2;\n");
1582: #endif
1583: }
1584: if ((flags & GF_NOREFILL) && using_prefetch) {
1585: printf ("\t%sa = %s (tmppc, regs.irc);\n", name, disp000);
1586: } else {
1587: printf ("\t%sa = %s (tmppc, %s);\n", name, disp000, gen_nextiword (flags));
1.1.1.4 root 1588: }
1589: }
1590:
1591: break;
1592: case absw:
1.1.1.7 root 1593: printf ("\tuaecptr %sa;\n", name);
1594: add_mmu040_movem (movem);
1595: printf ("\t%sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword (flags));
1596: pc_68000_offset_fetch += 2;
1.1.1.4 root 1597: break;
1598: case absl:
1.1.1.7 root 1599: gen_nextilong2 ("uaecptr", namea, flags, movem);
1.1.1.4 root 1600: count_read_ea += 2;
1.1.1.7 root 1601: pc_68000_offset_fetch += 4;
1602: pc_68000_offset_store += 2;
1.1.1.4 root 1603: break;
1604: case imm:
1.1.1.7 root 1605: // fetch immediate address
1.1.1.4 root 1606: if (getv != 1)
1.1.1.7 root 1607: term ();
1.1.1.4 root 1608: insn_n_cycles020++;
1609: switch (size) {
1610: case sz_byte:
1611: printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags));
1612: count_read_ea++;
1613: break;
1614: case sz_word:
1615: printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags));
1616: count_read_ea++;
1617: break;
1618: case sz_long:
1619: gen_nextilong ("uae_s32", name, flags);
1620: count_read_ea += 2;
1621: break;
1622: default:
1.1.1.7 root 1623: term ();
1.1.1.4 root 1624: }
1.1.1.7 root 1625: maybeaddop_ce020 (flags);
1.1.1.4 root 1626: syncmovepc (getv, flags);
1627: return;
1628: case imm0:
1629: if (getv != 1)
1.1.1.7 root 1630: term ();
1.1.1.4 root 1631: printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte (flags));
1632: count_read_ea++;
1.1.1.7 root 1633: maybeaddop_ce020 (flags);
1.1.1.4 root 1634: syncmovepc (getv, flags);
1635: return;
1636: case imm1:
1637: if (getv != 1)
1.1.1.7 root 1638: term ();
1.1.1.4 root 1639: printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword (flags));
1640: count_read_ea++;
1.1.1.7 root 1641: maybeaddop_ce020 (flags);
1.1.1.4 root 1642: syncmovepc (getv, flags);
1643: return;
1644: case imm2:
1645: if (getv != 1)
1.1.1.7 root 1646: term ();
1.1.1.4 root 1647: gen_nextilong ("uae_s32", name, flags);
1648: count_read_ea += 2;
1.1.1.7 root 1649: maybeaddop_ce020 (flags);
1.1.1.4 root 1650: syncmovepc (getv, flags);
1651: return;
1652: case immi:
1653: if (getv != 1)
1.1.1.7 root 1654: term ();
1.1.1.4 root 1655: printf ("\tuae_u32 %s = %s;\n", name, reg);
1.1.1.7 root 1656: maybeaddop_ce020 (flags);
1.1.1.4 root 1657: syncmovepc (getv, flags);
1658: return;
1659: default:
1.1.1.7 root 1660: term ();
1.1.1.4 root 1661: }
1662:
1663: syncmovepc (getv, flags);
1.1.1.7 root 1664: maybeaddop_ce020 (flags);
1.1.1.4 root 1665:
1666: /* We get here for all non-reg non-immediate addressing modes to
1667: * actually fetch the value. */
1668:
1.1.1.7 root 1669: int exception_pc_offset = 0;
1670: if (getv == 2) {
1671: // store
1672: if (pc_68000_offset) {
1673: exception_pc_offset = pc_68000_offset + pc_68000_offset_store + 2;
1.1.1.4 root 1674: }
1.1.1.7 root 1675: } else {
1676: // fetch
1.1.1.9 root 1677: exception_pc_offset = pc_68000_offset + pc_68000_offset_fetch;
1.1.1.7 root 1678: }
1679:
1680: if ((using_prefetch || using_ce) && using_exception_3 && getv != 0 && size != sz_byte) {
1.1.1.4 root 1681: printf ("\tif (%sa & 1) {\n", name);
1.1.1.7 root 1682: if (exception_pc_offset)
1683: incpc("%d", exception_pc_offset);
1.1.1.9 root 1684: // MOVE.L EA,-(An) causing address error: stacked value is original An - 2, not An - 4.
1685: if ((flags & (GF_REVERSE | GF_REVERSE2)) && size == sz_long && mode == Apdi)
1686: printf("\t\t%sa += %d;\n", name, flags & GF_REVERSE2 ? -2 : 2);
1.1.1.7 root 1687: printf ("\t\texception3_%s(opcode, %sa);\n", getv == 2 ? "write" : "read", name);
1.1.1.4 root 1688: printf ("\t\tgoto %s;\n", endlabelstr);
1689: printf ("\t}\n");
1690: need_endlabel = 1;
1691: start_brace ();
1692: }
1693:
1.1.1.7 root 1694: if ((using_prefetch || using_ce) && using_bus_error && getv != 0) {
1695: if (exception_pc_offset)
1696: printf("\tbus_error_offset = %d;\n", exception_pc_offset);
1697: }
1698:
1.1.1.4 root 1699: if (flags & GF_PREFETCH)
1700: fill_prefetch_next ();
1.1.1.7 root 1701: else if (flags & GF_IR2IRC)
1702: irc2ir_2 (true);
1.1.1.4 root 1703:
1704: if (getv == 1) {
1.1.1.10! root 1705: const char *srcbx = !(flags & GF_FC) ? srcb : "sfc_nommu_get_byte";
! 1706: const char *srcwx = !(flags & GF_FC) ? srcw : "sfc_nommu_get_word";
! 1707: const char *srclx = !(flags & GF_FC) ? srcl : "sfc_nommu_get_long";
1.1.1.4 root 1708: start_brace ();
1.1.1.9 root 1709: if (using_mmu) {
1.1.1.4 root 1710: if (flags & GF_FC) {
1711: switch (size) {
1.1.1.10! root 1712: case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = sfc%s_get_byte%s (%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
! 1713: case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = sfc%s_get_word%s (%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
! 1714: case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = sfc%s_get_long%s (%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
1.1.1.7 root 1715: default: term ();
1.1.1.4 root 1716: }
1717: } else {
1718: switch (size) {
1.1.1.7 root 1719: case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, (flags & GF_LRMW) ? srcblrmw : (rmw ? srcbrmw : srcb), name); break;
1720: case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, (flags & GF_LRMW) ? srcwlrmw : (rmw ? srcwrmw : srcw), name); break;
1721: case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, (flags & GF_LRMW) ? srcllrmw : (rmw ? srclrmw : srcl), name); break;
1722: default: term ();
1.1.1.4 root 1723: }
1724: }
1.1.1.9 root 1725: } else if (using_ce020 || using_prefetch_020) {
1726: switch (size) {
1.1.1.10! root 1727: case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcbx, name); count_read++; break;
! 1728: case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcwx, name); count_read++; break;
! 1729: case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, srclx, name); count_read += 2; break;
1.1.1.9 root 1730: default: term ();
1731: }
1732: } else if (using_ce || using_prefetch) {
1733: switch (size) {
1.1.1.10! root 1734: case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcbx, name); count_read++; break;
! 1735: case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcwx, name); count_read++; break;
1.1.1.9 root 1736: case sz_long: {
1737: insn_n_cycles += 8;
1738: if ((flags & GF_REVERSE) && mode == Apdi)
1.1.1.10! root 1739: printf("\tuae_s32 %s = %s (%sa + 2); %s |= %s (%sa) << 16;\n", name, srcwx, name, name, srcw, name);
1.1.1.9 root 1740: else
1.1.1.10! root 1741: printf("\tuae_s32 %s = %s (%sa) << 16; %s |= %s (%sa + 2);\n", name, srcwx, name, name, srcw, name);
1.1.1.9 root 1742: count_read += 2;
1743: break;
1744: }
1745: default: term ();
1746: }
1.1.1.4 root 1747: } else {
1748: switch (size) {
1.1.1.10! root 1749: case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcbx, name); count_read++; break;
! 1750: case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcwx, name); count_read++; break;
! 1751: case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, srclx, name); count_read += 2; break;
1.1.1.7 root 1752: default: term ();
1.1.1.4 root 1753: }
1754: }
1755: }
1756:
1757: /* We now might have to fix up the register for pre-dec or post-inc
1758: * addressing modes. */
1759: if (!movem)
1760: switch (mode) {
1761: case Aipi:
1.1.1.7 root 1762: addmmufixup (reg);
1.1.1.4 root 1763: switch (size) {
1764: case sz_byte:
1765: printf ("\tm68k_areg (regs, %s) += areg_byteinc[%s];\n", reg, reg);
1766: break;
1767: case sz_word:
1768: printf ("\tm68k_areg (regs, %s) += 2;\n", reg);
1769: break;
1770: case sz_long:
1771: printf ("\tm68k_areg (regs, %s) += 4;\n", reg);
1772: break;
1773: default:
1.1.1.7 root 1774: term ();
1.1.1.4 root 1775: }
1776: break;
1777: case Apdi:
1.1.1.7 root 1778: addmmufixup (reg);
1.1.1.4 root 1779: printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name);
1780: break;
1781: default:
1782: break;
1783: }
1.1.1.7 root 1784:
1785: if (movem == 3) {
1786: close_brace ();
1787: }
1.1.1.4 root 1788: }
1789:
1.1.1.7 root 1790: static void genamode2 (amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem, int flags)
1.1.1.4 root 1791: {
1.1.1.7 root 1792: genamode2x (mode, reg, size, name, getv, movem, flags, -1);
1.1.1.4 root 1793: }
1794:
1.1.1.7 root 1795: static void genamode (struct instr *curi, amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem, int flags)
1.1.1.4 root 1796: {
1.1.1.7 root 1797: int oldfixup = mmufixupstate;
1798: int subhead = 0;
1799: if (isce020() && curi) {
1800: switch (curi->fetchmode)
1801: {
1802: case fetchmode_fea:
1803: subhead = gence020cycles_fea (mode);
1804: break;
1805: case fetchmode_cea:
1806: subhead = gence020cycles_cea (curi, mode);
1807: break;
1808: case fetchmode_jea:
1809: subhead = gence020cycles_jea (curi, mode);
1810: break;
1811: }
1812: genamode2x (mode, reg, size, name, getv, movem, flags, curi->fetchmode);
1813: } else {
1814: genamode2 (mode, reg, size, name, getv, movem, flags);
1815: }
1816: if (using_mmu == 68040 && (oldfixup & 1)) {
1817: // we have fixup already active = this genamode call is destination mode and we can now clear previous source fixup.
1818: clearmmufixup (0);
1819: }
1.1.1.9 root 1820: if (curi)
1.1.1.7 root 1821: addop_ce020 (curi, subhead);
1.1.1.4 root 1822: }
1.1.1.7 root 1823:
1824: static void genamode3 (struct instr *curi, amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem, int flags)
1.1.1.4 root 1825: {
1.1.1.7 root 1826: int oldfixup = mmufixupstate;
1827: genamode2x (mode, reg, size, name, getv, movem, flags, curi ? curi->fetchmode : -1);
1828: if (using_mmu == 68040 && (oldfixup & 1)) {
1829: // we have fixup already active = this genamode call is destination mode and we can now clear previous source fixup.
1830: clearmmufixup (0);
1831: }
1.1.1.4 root 1832: }
1.1.1.7 root 1833:
1834: static void genamodedual (struct instr *curi, amodes smode, const char *sreg, wordsizes ssize, const char *sname, int sgetv, int sflags,
1835: amodes dmode, const char *dreg, wordsizes dsize, const char *dname, int dgetv, int dflags)
1.1.1.4 root 1836: {
1.1.1.7 root 1837: int subhead = 0;
1838: bool eadmode = false;
1839:
1840: if (isce020()) {
1841: switch (curi->fetchmode)
1842: {
1843: case fetchmode_fea:
1844: if (smode >= imm || isreg (smode)) {
1845: subhead = gence020cycles_fea (dmode);
1846: eadmode = true;
1847: } else {
1848: subhead = gence020cycles_fea (smode);
1849: }
1850: break;
1851: case fetchmode_cea:
1852: subhead = gence020cycles_cea (curi, smode);
1853: break;
1854: case fetchmode_fiea:
1855: subhead = gence020cycles_fiea (curi, ssize, dmode);
1856: break;
1857: case fetchmode_ciea:
1858: subhead = gence020cycles_ciea (curi, ssize, dmode);
1859: break;
1860: case fetchmode_jea:
1861: subhead = gence020cycles_jea (curi, smode);
1862: break;
1863: default:
1864: printf ("\t/* No EA */\n");
1865: break;
1866: }
1867: }
1868: subhead_ce020 = subhead;
1869: curi_ce020 = curi;
1870: genamode3 (curi, smode, sreg, ssize, sname, sgetv, 0, sflags);
1871: genamode3 (NULL, dmode, dreg, dsize, dname, dgetv, 0, dflags | (eadmode == true ? GF_OPCE020 : 0));
1872: if (eadmode == false)
1873: maybeaddop_ce020 (GF_OPCE020);
1.1.1.4 root 1874: }
1875:
1876: static void genastore_2 (const char *from, amodes mode, const char *reg, wordsizes size, const char *to, int store_dir, int flags)
1877: {
1.1.1.7 root 1878: if (candormw) {
1879: if (strcmp (rmw_varname, to) != 0)
1880: candormw = false;
1881: }
1882: genastore_done = true;
1883: returntail (mode != Dreg && mode != Areg);
1884:
1.1.1.4 root 1885: switch (mode) {
1886: case Dreg:
1887: switch (size) {
1888: case sz_byte:
1889: printf ("\tm68k_dreg (regs, %s) = (m68k_dreg (regs, %s) & ~0xff) | ((%s) & 0xff);\n", reg, reg, from);
1890: break;
1891: case sz_word:
1892: printf ("\tm68k_dreg (regs, %s) = (m68k_dreg (regs, %s) & ~0xffff) | ((%s) & 0xffff);\n", reg, reg, from);
1893: break;
1894: case sz_long:
1895: printf ("\tm68k_dreg (regs, %s) = (%s);\n", reg, from);
1896: break;
1897: default:
1.1.1.7 root 1898: term ();
1.1.1.4 root 1899: }
1900: break;
1901: case Areg:
1902: switch (size) {
1903: case sz_word:
1904: printf ("\tm68k_areg (regs, %s) = (uae_s32)(uae_s16)(%s);\n", reg, from);
1905: break;
1906: case sz_long:
1907: printf ("\tm68k_areg (regs, %s) = (%s);\n", reg, from);
1908: break;
1909: default:
1.1.1.7 root 1910: term ();
1.1.1.4 root 1911: }
1912: break;
1913: case Aind:
1914: case Aipi:
1915: case Apdi:
1916: case Ad16:
1917: case Ad8r:
1918: case absw:
1919: case absl:
1920: case PC16:
1921: case PC8r:
1.1.1.10! root 1922: {
! 1923: const char *dstbx = !(flags & GF_FC) ? dstb : "dfc_nommu_put_byte";
! 1924: const char *dstwx = !(flags & GF_FC) ? dstw : "dfc_nommu_put_word";
! 1925: const char *dstlx = !(flags & GF_FC) ? dstl : "dfc_nommu_put_long";
1.1.1.7 root 1926: if (!(flags & GF_NOFAULTPC))
1.1.1.10! root 1927: gen_set_fault_pc (false);
1.1.1.9 root 1928: if (using_mmu) {
1929: switch (size) {
1930: case sz_byte:
1931: insn_n_cycles += 4;
1932: if (flags & GF_FC)
1.1.1.10! root 1933: printf ("\tdfc%s_put_byte%s (%sa, %s);\n", mmu_postfix, xfc_postfix, to, from);
1.1.1.9 root 1934: else
1935: printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstblrmw : (candormw ? dstbrmw : dstb), to, from);
1936: break;
1937: case sz_word:
1938: insn_n_cycles += 4;
1939: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
1940: term ();
1941: if (flags & GF_FC)
1.1.1.10! root 1942: printf ("\tdfc%s_put_word%s (%sa, %s);\n", mmu_postfix, xfc_postfix, to, from);
1.1.1.9 root 1943: else
1944: printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstwlrmw : (candormw ? dstwrmw : dstw), to, from);
1945: break;
1946: case sz_long:
1947: insn_n_cycles += 8;
1948: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
1949: term ();
1950: if (flags & GF_FC)
1.1.1.10! root 1951: printf ("\tdfc%s_put_long%s (%sa, %s);\n", mmu_postfix, xfc_postfix, to, from);
1.1.1.9 root 1952: else
1953: printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstllrmw : (candormw ? dstlrmw : dstl), to, from);
1954: break;
1955: default:
1956: term ();
1957: }
1958: } else if (using_ce020 || using_prefetch_020) {
1.1.1.4 root 1959: switch (size) {
1960: case sz_byte:
1.1.1.10! root 1961: printf ("\t%s (%sa, %s);\n", dstbx, to, from);
1.1.1.4 root 1962: count_write++;
1963: break;
1964: case sz_word:
1965: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
1.1.1.7 root 1966: term ();
1.1.1.10! root 1967: printf ("\t%s (%sa, %s);\n", dstwx, to, from);
1.1.1.4 root 1968: count_write++;
1969: break;
1970: case sz_long:
1971: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
1.1.1.7 root 1972: term ();
1.1.1.10! root 1973: printf ("\t%s (%sa, %s);\n", dstlx, to, from);
1.1.1.4 root 1974: count_write += 2;
1975: break;
1976: default:
1.1.1.7 root 1977: term ();
1.1.1.4 root 1978: }
1979: } else if (using_ce) {
1980: switch (size) {
1981: case sz_byte:
1.1.1.7 root 1982: check_ipl_again();
1983: printf ("\tx_put_byte (%sa, %s);\n", to, from);
1.1.1.4 root 1984: count_write++;
1985: break;
1986: case sz_word:
1987: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
1.1.1.7 root 1988: term ();
1989: check_ipl_again();
1990: printf ("\tx_put_word (%sa, %s);\n", to, from);
1.1.1.4 root 1991: count_write++;
1992: break;
1993: case sz_long:
1994: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
1.1.1.7 root 1995: term ();
1996: if (store_dir) {
1997: printf ("\t%s (%sa + 2, %s);\n", dstw, to, from);
1998: check_ipl_again();
1999: printf ("%s (%sa, %s >> 16);\n", dstw, to, from);
2000: } else {
2001: printf ("\t%s (%sa, %s >> 16);\n", dstw, to, from);
2002: check_ipl_again();
2003: printf ("\t%s (%sa + 2, %s);\n", dstw, to, from);
2004: }
1.1.1.4 root 2005: count_write += 2;
2006: break;
2007: default:
1.1.1.7 root 2008: term ();
1.1.1.4 root 2009: }
1.1.1.7 root 2010: } else if (using_prefetch) {
2011: switch (size) {
2012: case sz_byte:
2013: insn_n_cycles += 4;
1.1.1.10! root 2014: printf ("\t%s (%sa, %s);\n", dstbx, to, from);
1.1.1.7 root 2015: count_write++;
2016: break;
2017: case sz_word:
2018: insn_n_cycles += 4;
2019: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
2020: term ();
1.1.1.10! root 2021: printf ("\t%s (%sa, %s);\n", dstwx, to, from);
1.1.1.7 root 2022: count_write++;
2023: break;
2024: case sz_long:
2025: insn_n_cycles += 8;
2026: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
2027: term ();
2028: if (store_dir)
1.1.1.10! root 2029: printf ("\t%s (%sa + 2, %s); %s (%sa, %s >> 16);\n", dstwx, to, from, dstwx, to, from);
1.1.1.7 root 2030: else
1.1.1.10! root 2031: printf ("\t%s (%sa, %s >> 16); %s (%sa + 2, %s);\n", dstwx, to, from, dstwx, to, from);
1.1.1.7 root 2032: count_write += 2;
1.1.1.4 root 2033: break;
2034: default:
1.1.1.7 root 2035: term ();
1.1.1.4 root 2036: }
2037: } else {
2038: switch (size) {
2039: case sz_byte:
2040: insn_n_cycles += 4;
1.1.1.7 root 2041: printf ("\t%s (%sa, %s);\n", dstb, to, from);
1.1.1.4 root 2042: count_write++;
2043: break;
2044: case sz_word:
2045: insn_n_cycles += 4;
2046: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
1.1.1.7 root 2047: term ();
2048: printf ("\t%s (%sa, %s);\n", dstw, to, from);
1.1.1.4 root 2049: count_write++;
2050: break;
2051: case sz_long:
2052: insn_n_cycles += 8;
2053: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
1.1.1.7 root 2054: term ();
2055: printf ("\t%s (%sa, %s);\n", dstl, to, from);
1.1.1.4 root 2056: count_write += 2;
2057: break;
2058: default:
1.1.1.7 root 2059: term ();
1.1.1.4 root 2060: }
2061: }
2062: break;
1.1.1.10! root 2063: }
1.1.1.4 root 2064: case imm:
2065: case imm0:
2066: case imm1:
2067: case imm2:
2068: case immi:
1.1.1.7 root 2069: term ();
1.1.1.4 root 2070: break;
2071: default:
1.1.1.7 root 2072: term ();
1.1.1.4 root 2073: }
2074: }
2075:
2076: static void genastore (const char *from, amodes mode, const char *reg, wordsizes size, const char *to)
2077: {
2078: genastore_2 (from, mode, reg, size, to, 0, 0);
2079: }
1.1.1.7 root 2080: static void genastore_tas (const char *from, amodes mode, const char *reg, wordsizes size, const char *to)
2081: {
2082: genastore_2 (from, mode, reg, size, to, 0, GF_LRMW);
2083: }
2084: static void genastore_cas (const char *from, amodes mode, const char *reg, wordsizes size, const char *to)
2085: {
2086: genastore_2 (from, mode, reg, size, to, 0, GF_LRMW | GF_NOFAULTPC);
2087: }
1.1.1.4 root 2088: static void genastore_rev (const char *from, amodes mode, const char *reg, wordsizes size, const char *to)
2089: {
2090: genastore_2 (from, mode, reg, size, to, 1, 0);
2091: }
2092: static void genastore_fc (const char *from, amodes mode, const char *reg, wordsizes size, const char *to)
2093: {
2094: genastore_2 (from, mode, reg, size, to, 1, GF_FC);
2095: }
2096:
1.1.1.7 root 2097: static void movem_mmu060 (const char *code, int size, bool put, bool aipi, bool apdi)
2098: {
2099: const char *index;
2100: int dphase;
1.1.1.10! root 2101:
1.1.1.7 root 2102: if (apdi) {
2103: dphase = 1;
2104: index = "movem_index2";
2105: } else {
2106: dphase = 0;
2107: index = "movem_index1";
2108: }
2109:
2110: if (!put) {
2111: printf("\tuae_u32 tmp[16];\n");
2112: printf("\tint tmpreg[16];\n");
2113: printf("\tint idx = 0;\n");
1.1.1.10! root 2114: for (int i = 0; i < 2; i++) {
1.1.1.7 root 2115: char reg;
2116: if (i == dphase)
2117: reg = 'd';
2118: else
2119: reg = 'a';
2120: printf ("\twhile (%cmask) {\n", reg);
2121: if (apdi)
2122: printf ("\t\tsrca -= %d;\n", size);
2123: printf ("\t\ttmpreg[idx] = %s[%cmask] + %d;\n", index, reg, i == dphase ? 0 : 8);
2124: printf ("\t\ttmp[idx++] = %s;\n", code);
2125: if (!apdi)
2126: printf ("\t\tsrca += %d;\n", size);
2127: printf ("\t\t%cmask = movem_next[%cmask];\n", reg, reg);
2128: printf ("\t}\n");
2129: }
2130: if (aipi || apdi)
2131: printf ("\tm68k_areg (regs, dstreg) = srca;\n");
2132: printf ("\twhile (--idx >= 0) {\n");
2133: printf ("\t\tregs.regs[tmpreg[idx]] = tmp[idx];\n");
2134: printf ("\t}\n");
2135: } else {
1.1.1.10! root 2136: for (int i = 0; i < 2; i++) {
1.1.1.7 root 2137: char reg;
2138: if (i == dphase)
2139: reg = 'd';
2140: else
2141: reg = 'a';
2142: printf ("\twhile (%cmask) {\n", reg);
2143: if (apdi)
2144: printf ("\t\tsrca -= %d;\n", size);
2145: if (put) {
2146: printf ("\t\t%s, m68k_%creg (regs, %s[%cmask]));\n", code, reg, index, reg);
2147: } else {
2148: printf ("\t\tm68k_%creg (regs, %s[%cmask]) = %s;\n", reg, index, reg, code);
2149: }
2150: if (!apdi)
2151: printf ("\t\tsrca += %d;\n", size);
2152: printf ("\t\t%cmask = movem_next[%cmask];\n", reg, reg);
2153: printf ("\t}\n");
2154: }
2155: if (aipi || apdi)
2156: printf ("\tm68k_areg (regs, dstreg) = srca;\n");
2157: }
2158: }
2159:
2160: static bool mmu040_special_movem (uae_u16 opcode)
2161: {
2162: if (using_mmu != 68040)
2163: return false;
2164: return true;
2165: // return (((((opcode >> 3) & 7) == 7) && ((opcode & 7) == 2 || (opcode & 7) == 3)) || ((opcode >> 3) & 7) == 6);
2166: }
2167:
2168: static void movem_mmu040 (const char *code, int size, bool put, bool aipi, bool apdi, uae_u16 opcode)
2169: {
2170: const char *index;
2171: int dphase;
2172:
2173: if (apdi) {
2174: dphase = 1;
2175: index = "movem_index2";
2176: } else {
2177: dphase = 0;
2178: index = "movem_index1";
2179: }
2180:
2181: printf ("\tmmu040_movem = 1;\n");
2182: printf ("\tmmu040_movem_ea = srca;\n");
2183:
1.1.1.10! root 2184: for (int i = 0; i < 2; i++) {
1.1.1.7 root 2185: char reg;
2186: if (i == dphase)
2187: reg = 'd';
2188: else
2189: reg = 'a';
2190: printf ("\twhile (%cmask) {\n", reg);
2191: if (apdi)
2192: printf ("\t\tsrca -= %d;\n", size);
2193: if (put) {
2194: printf ("\t\t%s, m68k_%creg (regs, %s[%cmask]));\n", code, reg, index, reg);
2195: } else {
2196: printf ("\t\tm68k_%creg (regs, %s[%cmask]) = %s;\n", reg, index, reg, code);
2197: }
2198: if (!apdi)
2199: printf ("\t\tsrca += %d;\n", size);
2200: printf ("\t\t%cmask = movem_next[%cmask];\n", reg, reg);
2201: printf ("\t}\n");
2202: }
2203: if (aipi || apdi)
2204: printf ("\tm68k_areg (regs, dstreg) = srca;\n");
2205: printf ("\tmmu040_movem = 0;\n");
2206: }
2207:
2208: /* 68030 MMU does not restore register state if it bus faults.
2209: * (also there wouldn't be enough space in stack frame to store all registers)
2210: */
2211: static void movem_mmu030 (const char *code, int size, bool put, bool aipi, bool apdi)
2212: {
2213: const char *index;
2214: int dphase;
1.1.1.10! root 2215: int old_m68k_pc_offset = m68k_pc_offset;
! 2216:
1.1.1.7 root 2217: if (apdi) {
2218: dphase = 1;
2219: index = "movem_index2";
2220: } else {
2221: dphase = 0;
2222: index = "movem_index1";
2223: }
1.1.1.10! root 2224: if (put) {
! 2225: printf("\tint prefetch = 0;\n");
! 2226: }
1.1.1.7 root 2227: printf ("\tmmu030_state[1] |= MMU030_STATEFLAG1_MOVEM1;\n");
2228: printf ("\tint movem_cnt = 0;\n");
2229: if (!put) {
2230: printf ("\tuae_u32 val;\n");
1.1.1.10! root 2231: // Store original EA because MOVEM from memory may modify same register
! 2232: printf ("\tsrca = state_store_mmu030(srca);\n");
1.1.1.7 root 2233: }
1.1.1.10! root 2234: for (int i = 0; i < 2; i++) {
1.1.1.7 root 2235: char reg;
2236: if (i == dphase)
2237: reg = 'd';
2238: else
2239: reg = 'a';
2240: printf ("\twhile (%cmask) {\n", reg);
1.1.1.10! root 2241: printf("\t\tuae_u16 nextmask = movem_next[%cmask];\n", reg);
1.1.1.7 root 2242: if (apdi)
2243: printf ("\t\tsrca -= %d;\n", size);
2244: printf ("\t\tif (mmu030_state[0] == movem_cnt) {\n");
2245: printf ("\t\t\tif (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM2) {\n");
2246: printf ("\t\t\t\tmmu030_state[1] &= ~MMU030_STATEFLAG1_MOVEM2;\n");
2247: if (!put)
1.1.1.10! root 2248: printf ("\t\t\t\tval = %smmu030_data_buffer_out;\n", size == 2 ? "(uae_s32)(uae_s16)" : "");
1.1.1.7 root 2249: printf ("\t\t\t} else {\n");
1.1.1.10! root 2250: if (put) {
! 2251: printf("\t\t\t\tmmu030_data_buffer_out = m68k_%creg(regs, %s[%cmask]);\n", reg, index, reg);
! 2252: // last write?
! 2253: if (dphase == i)
! 2254: printf("\t\t\t\tif(!amask && !nextmask) {\n");
! 2255: else
! 2256: printf("\t\t\t\tif(!dmask && !nextmask) {\n");
! 2257: get_prefetch_020();
! 2258: gen_set_fault_pc(true);
! 2259: printf("\t\t\t\t\tmmu030_state[1] &= ~MMU030_STATEFLAG1_MOVEM1;\n");
! 2260: m68k_pc_offset = old_m68k_pc_offset;
! 2261: printf("\t\t\t\t\tprefetch = 1;\n");
! 2262: if (aipi || apdi)
! 2263: printf("\tm68k_areg (regs, dstreg) = srca;\n");
! 2264: printf("\t\t\t\t}\n");
! 2265: printf("\t\t\t\t%s, mmu030_data_buffer_out);\n", code);
! 2266: } else {
! 2267: printf("\t\t\t\tval = %s;\n", code);
! 2268: }
1.1.1.7 root 2269: printf ("\t\t\t}\n");
2270: if (!put) {
2271: printf ("\t\t\tm68k_%creg (regs, %s[%cmask]) = val;\n", reg, index, reg);
2272: }
2273: printf ("\t\t\tmmu030_state[0]++;\n");
2274: printf ("\t\t}\n");
2275: if (!apdi)
2276: printf ("\t\tsrca += %d;\n", size);
2277: printf ("\t\tmovem_cnt++;\n");
1.1.1.10! root 2278: printf ("\t\t%cmask = nextmask;\n", reg);
1.1.1.7 root 2279: printf ("\t}\n");
2280: }
2281: if (aipi || apdi)
2282: printf ("\tm68k_areg (regs, dstreg) = srca;\n");
1.1.1.10! root 2283: if (put) {
! 2284: // if both masks are zero
! 2285: printf("\tif(prefetch == 0) {\n");
! 2286: if (using_prefetch_020) {
! 2287: get_prefetch_020();
! 2288: }
! 2289: sync_m68k_pc();
! 2290: printf("\t}\n");
! 2291: m68k_pc_offset = 0;
! 2292: }
1.1.1.7 root 2293: }
2294:
1.1.1.4 root 2295: static void genmovemel (uae_u16 opcode)
2296: {
2297: char getcode[100];
2298: int size = table68k[opcode].size == sz_long ? 4 : 2;
2299:
2300: if (table68k[opcode].size == sz_long) {
1.1.1.7 root 2301: sprintf (getcode, "%s (srca)", srcld);
1.1.1.4 root 2302: } else {
1.1.1.7 root 2303: sprintf (getcode, "(uae_s32)(uae_s16)%s (srca)", srcwd);
1.1.1.4 root 2304: }
2305: count_read += table68k[opcode].size == sz_long ? 2 : 1;
2306: printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0));
1.1.1.7 root 2307: printf ("\tuae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
2308: genamode (NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, GF_MOVE);
2309: addcycles_ce020 (8 - 2);
1.1.1.4 root 2310: start_brace ();
1.1.1.7 root 2311: if (using_mmu == 68030) {
2312: movem_mmu030 (getcode, size, false, table68k[opcode].dmode == Aipi, false);
2313: } else if (using_mmu == 68060) {
2314: movem_mmu060 (getcode, size, false, table68k[opcode].dmode == Aipi, false);
2315: } else if (using_mmu == 68040) {
2316: movem_mmu040 (getcode, size, false, table68k[opcode].dmode == Aipi, false, opcode);
2317: } else {
2318: printf ("\twhile (dmask) {\n");
2319: printf ("\t\tm68k_dreg (regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask];\n", getcode, size);
2320: //addcycles_ce020 (1);
2321: printf ("\t}\n");
2322: printf ("\twhile (amask) {\n");
2323: printf ("\t\tm68k_areg (regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask];\n", getcode, size);
2324: //addcycles_ce020 (1);
2325: printf ("\t}\n");
2326: if (table68k[opcode].dmode == Aipi) {
2327: printf ("\tm68k_areg (regs, dstreg) = srca;\n");
2328: count_read++;
2329: }
1.1.1.4 root 2330: }
2331: count_ncycles++;
2332: fill_prefetch_next ();
1.1.1.7 root 2333: get_prefetch_020 ();
1.1.1.4 root 2334: }
2335:
2336: static void genmovemel_ce (uae_u16 opcode)
2337: {
2338: int size = table68k[opcode].size == sz_long ? 4 : 2;
2339: printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0));
1.1.1.7 root 2340: printf ("\tuae_u32 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
1.1.1.4 root 2341: printf ("\tuae_u32 v;\n");
2342: if (table68k[opcode].dmode == Ad8r || table68k[opcode].dmode == PC8r)
2343: addcycles000 (2);
1.1.1.7 root 2344: genamode (NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, GF_AA | GF_MOVE);
1.1.1.4 root 2345: start_brace ();
2346: if (table68k[opcode].size == sz_long) {
1.1.1.7 root 2347: printf ("\twhile (dmask) {\n");
2348: printf ("\t\tv = %s (srca) << 16;\n", srcw);
2349: printf ("\t\tv |= %s (srca + 2);\n", srcw);
2350: printf ("\t\tm68k_dreg (regs, movem_index1[dmask]) = v;\n");
2351: printf ("\t\tsrca += %d;\n", size);
2352: printf ("\t\tdmask = movem_next[dmask];\n");
2353: addcycles000_nonce("\t\t", 8);
2354: printf ("\t}\n");
2355: printf ("\twhile (amask) {\n");
2356: printf ("\t\tv = %s (srca) << 16;\n", srcw);
2357: printf ("\t\tv |= %s (srca + 2);\n", srcw);
2358: printf ("\t\tm68k_areg (regs, movem_index1[amask]) = v;\n");
2359: printf ("\t\tsrca += %d;\n", size);
2360: printf ("\t\tamask = movem_next[amask];\n");
2361: addcycles000_nonce("\t\t", 8);
2362: printf ("\t}\n");
1.1.1.4 root 2363: } else {
1.1.1.7 root 2364: printf ("\twhile (dmask) {\n");
2365: printf ("\t\tm68k_dreg (regs, movem_index1[dmask]) = (uae_s32)(uae_s16)%s (srca);\n", srcw);
2366: printf ("\t\tsrca += %d;\n", size);
2367: printf ("\t\tdmask = movem_next[dmask];\n");
2368: addcycles000_nonce("\t\t", 4);
2369: printf ("\t}\n");
2370: printf ("\twhile (amask) {\n");
2371: printf ("\t\tm68k_areg (regs, movem_index1[amask]) = (uae_s32)(uae_s16)%s (srca);\n", srcw);
2372: printf ("\t\tsrca += %d;\n", size);
2373: printf ("\t\tamask = movem_next[amask];\n");
2374: addcycles000_nonce("\t\t", 4);
2375: printf ("\t}\n");
1.1.1.4 root 2376: }
1.1.1.7 root 2377: printf ("\t%s (srca);\n", srcw); // and final extra word fetch that goes nowhere..
1.1.1.4 root 2378: count_read++;
2379: if (table68k[opcode].dmode == Aipi)
2380: printf ("\tm68k_areg (regs, dstreg) = srca;\n");
2381: count_ncycles++;
2382: fill_prefetch_next ();
2383: }
2384:
2385: static void genmovemle (uae_u16 opcode)
2386: {
2387: char putcode[100];
2388: int size = table68k[opcode].size == sz_long ? 4 : 2;
2389:
2390: if (table68k[opcode].size == sz_long) {
1.1.1.7 root 2391: sprintf (putcode, "%s (srca", dstld);
1.1.1.4 root 2392: } else {
1.1.1.7 root 2393: sprintf (putcode, "%s (srca", dstwd);
1.1.1.4 root 2394: }
2395: count_write += table68k[opcode].size == sz_long ? 2 : 1;
2396:
2397: printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0));
1.1.1.7 root 2398: genamode (NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, mmu040_special_movem (opcode) ? 3 : 1, GF_MOVE);
2399: addcycles_ce020 (4 - 2);
1.1.1.4 root 2400: start_brace ();
1.1.1.7 root 2401: if (using_mmu >= 68030) {
2402: if (table68k[opcode].dmode == Apdi)
2403: printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
2404: else
2405: printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
1.1.1.10! root 2406: if (using_mmu == 68030) {
! 2407: movem_mmu030(putcode, size, true, false, table68k[opcode].dmode == Apdi);
! 2408: count_ncycles++;
! 2409: return;
! 2410: } else if (using_mmu == 68060) {
! 2411: movem_mmu060(putcode, size, true, false, table68k[opcode].dmode == Apdi);
! 2412: } else if (using_mmu == 68040) {
! 2413: movem_mmu040(putcode, size, true, false, table68k[opcode].dmode == Apdi, opcode);
! 2414: }
1.1.1.4 root 2415: } else {
1.1.1.7 root 2416: if (table68k[opcode].dmode == Apdi) {
2417: printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
2418: if (!using_mmu)
2419: printf ("\tint type = get_cpu_model () >= 68020;\n");
2420: printf ("\twhile (amask) {\n");
2421: printf ("\t\tsrca -= %d;\n", size);
2422:
2423: printf ("\t\tif (!type || movem_index2[amask] != dstreg)\n");
2424: printf ("\t\t\t%s, m68k_areg (regs, movem_index2[amask]));\n", putcode);
2425: printf ("\t\telse\n");
2426: printf ("\t\t\t%s, m68k_areg (regs, movem_index2[amask]) - %d);\n", putcode, size);
1.1.1.4 root 2427:
1.1.1.7 root 2428: printf ("\t\tamask = movem_next[amask];\n");
2429: printf ("\t}\n");
2430: printf ("\twhile (dmask) { srca -= %d; %s, m68k_dreg (regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n",
2431: size, putcode);
2432: printf ("\tm68k_areg (regs, dstreg) = srca;\n");
2433: } else {
2434: printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
2435: printf ("\twhile (dmask) { %s, m68k_dreg (regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n",
2436: putcode, size);
2437: printf ("\twhile (amask) { %s, m68k_areg (regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n",
2438: putcode, size);
2439: }
1.1.1.4 root 2440: }
1.1.1.7 root 2441: count_ncycles++;
1.1.1.4 root 2442: fill_prefetch_next ();
1.1.1.7 root 2443: get_prefetch_020 ();
1.1.1.4 root 2444: }
2445:
2446: static void genmovemle_ce (uae_u16 opcode)
2447: {
2448: int size = table68k[opcode].size == sz_long ? 4 : 2;
2449:
1.1.1.7 root 2450: printf ("\tuae_u16 mask = %s;\n", gen_nextiword (0));
2451: if (table68k[opcode].dmode == Ad8r || table68k[opcode].dmode == PC8r)
1.1.1.4 root 2452: addcycles000 (2);
1.1.1.9 root 2453: genamode (NULL, table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1, GF_AA | GF_MOVE | GF_REVERSE | GF_REVERSE2);
1.1.1.4 root 2454: start_brace ();
2455: if (table68k[opcode].size == sz_long) {
2456: if (table68k[opcode].dmode == Apdi) {
2457: printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
1.1.1.7 root 2458: printf ("\twhile (amask) {\n");
1.1.1.9 root 2459: printf ("\t\t%s (srca - 2, m68k_areg (regs, movem_index2[amask]));\n", dstw);
2460: printf ("\t\t%s (srca - 4, m68k_areg (regs, movem_index2[amask]) >> 16);\n", dstw);
2461: printf("\t\tsrca -= %d;\n", size);
1.1.1.7 root 2462: printf ("\t\tamask = movem_next[amask];\n");
2463: addcycles000_nonce("\t\t", 8);
2464: printf ("\t}\n");
2465: printf ("\twhile (dmask) {\n");
1.1.1.9 root 2466: printf ("\t\t%s (srca - 2, m68k_dreg (regs, movem_index2[dmask]));\n", dstw);
2467: printf ("\t\t%s (srca - 4, m68k_dreg (regs, movem_index2[dmask]) >> 16);\n", dstw);
2468: printf("\t\tsrca -= %d;\n", size);
1.1.1.7 root 2469: printf ("\t\tdmask = movem_next[dmask];\n");
2470: addcycles000_nonce("\t\t", 8);
2471: printf ("\t}\n");
1.1.1.4 root 2472: printf ("\tm68k_areg (regs, dstreg) = srca;\n");
2473: } else {
2474: printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
1.1.1.7 root 2475: printf ("\twhile (dmask) {\n");
2476: printf ("\t\t%s (srca, m68k_dreg (regs, movem_index1[dmask]) >> 16);\n", dstw);
1.1.1.10! root 2477: printf ("\t\t%s (srca + 2, m68k_dreg (regs, movem_index1[dmask]));\n", dstw);
! 2478: printf ("\t\tsrca += %d;\n", size);
1.1.1.7 root 2479: printf ("\t\tdmask = movem_next[dmask];\n");
2480: addcycles000_nonce("\t\t", 8);
2481: printf ("\t}\n");
2482: printf ("\twhile (amask) {\n");
2483: printf ("\t\t%s (srca, m68k_areg (regs, movem_index1[amask]) >> 16);\n", dstw);
1.1.1.10! root 2484: printf ("\t\t%s (srca + 2, m68k_areg (regs, movem_index1[amask]));\n", dstw);
! 2485: printf ("\t\tsrca += %d;\n", size);
1.1.1.7 root 2486: printf ("\t\tamask = movem_next[amask];\n");
2487: addcycles000_nonce("\t\t", 8);
2488: printf ("\t}\n");
1.1.1.4 root 2489: }
2490: } else {
2491: if (table68k[opcode].dmode == Apdi) {
2492: printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
1.1.1.7 root 2493: printf ("\twhile (amask) {\n");
2494: printf ("\t\tsrca -= %d;\n", size);
2495: printf ("\t\t%s (srca, m68k_areg (regs, movem_index2[amask]));\n", dstw);
2496: printf ("\tamask = movem_next[amask];\n");
2497: addcycles000_nonce("\t\t", 4);
2498: printf ("\t}\n");
2499: printf ("\twhile (dmask) {\n");
2500: printf ("\t\tsrca -= %d;\n", size);
2501: printf ("\t\t%s (srca, m68k_dreg (regs, movem_index2[dmask]));\n", dstw);
2502: printf ("\t\tdmask = movem_next[dmask];\n");
2503: addcycles000_nonce("\t\t", 4);
2504: printf ("\t}\n");
1.1.1.4 root 2505: printf ("\tm68k_areg (regs, dstreg) = srca;\n");
2506: } else {
2507: printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
1.1.1.7 root 2508: printf ("\twhile (dmask) {\n");
2509: printf ("\t\t%s (srca, m68k_dreg (regs, movem_index1[dmask]));\n", dstw);
2510: printf ("\t\tsrca += %d;\n", size);
2511: printf ("\t\tdmask = movem_next[dmask];\n");
2512: addcycles000_nonce("\t\t", 4);
2513: printf ("\t}\n");
2514: printf ("\twhile (amask) {\n");
2515: printf ("\t\t%s (srca, m68k_areg (regs, movem_index1[amask]));\n", dstw);
2516: printf ("\t\tsrca += %d;\n", size);
2517: printf ("\t\tamask = movem_next[amask];\n");
2518: addcycles000_nonce("\t\t", 4);
2519: printf ("\t}\n");
1.1.1.4 root 2520: }
2521: }
2522: count_ncycles++;
2523: fill_prefetch_next ();
2524: }
2525:
2526: static void duplicate_carry (int n)
2527: {
2528: int i;
2529: for (i = 0; i <= n; i++)
2530: printf ("\t");
2531: printf ("COPY_CARRY ();\n");
2532: }
2533:
2534: typedef enum
2535: {
2536: flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_z, flag_zn,
2537: flag_av, flag_sv
2538: }
2539: flagtypes;
2540:
2541: static void genflags_normal (flagtypes type, wordsizes size, const char *value, const char *src, const char *dst)
2542: {
2543: char vstr[100], sstr[100], dstr[100];
2544: char usstr[100], udstr[100];
2545: char unsstr[100], undstr[100];
2546:
2547: switch (size) {
2548: case sz_byte:
2549: strcpy (vstr, "((uae_s8)(");
2550: strcpy (usstr, "((uae_u8)(");
2551: break;
2552: case sz_word:
2553: strcpy (vstr, "((uae_s16)(");
2554: strcpy (usstr, "((uae_u16)(");
2555: break;
2556: case sz_long:
2557: strcpy (vstr, "((uae_s32)(");
2558: strcpy (usstr, "((uae_u32)(");
2559: break;
2560: default:
1.1.1.7 root 2561: term ();
1.1.1.4 root 2562: }
2563: strcpy (unsstr, usstr);
2564:
2565: strcpy (sstr, vstr);
2566: strcpy (dstr, vstr);
2567: strcat (vstr, value);
2568: strcat (vstr, "))");
2569: strcat (dstr, dst);
2570: strcat (dstr, "))");
2571: strcat (sstr, src);
2572: strcat (sstr, "))");
2573:
2574: strcpy (udstr, usstr);
2575: strcat (udstr, dst);
2576: strcat (udstr, "))");
2577: strcat (usstr, src);
2578: strcat (usstr, "))");
2579:
2580: strcpy (undstr, unsstr);
2581: strcat (unsstr, "-");
2582: strcat (undstr, "~");
2583: strcat (undstr, dst);
2584: strcat (undstr, "))");
2585: strcat (unsstr, src);
2586: strcat (unsstr, "))");
2587:
2588: switch (type) {
2589: case flag_logical_noclobber:
2590: case flag_logical:
2591: case flag_z:
2592: case flag_zn:
2593: case flag_av:
2594: case flag_sv:
2595: case flag_addx:
2596: case flag_subx:
2597: break;
2598:
2599: case flag_add:
2600: start_brace ();
1.1.1.7 root 2601: printf ("uae_u32 %s = %s + %s;\n", value, udstr, usstr);
1.1.1.4 root 2602: break;
2603: case flag_sub:
2604: case flag_cmp:
2605: start_brace ();
1.1.1.7 root 2606: printf ("uae_u32 %s = %s - %s;\n", value, udstr, usstr);
1.1.1.4 root 2607: break;
2608: }
2609:
2610: switch ((int)type) {
2611: case flag_logical_noclobber:
2612: case flag_logical:
2613: case flag_zn:
2614: break;
2615:
2616: case flag_add:
2617: case flag_sub:
2618: case flag_addx:
2619: case flag_subx:
2620: case flag_cmp:
2621: case flag_av:
2622: case flag_sv:
2623: start_brace ();
2624: printf ("\t" BOOL_TYPE " flgs = %s < 0;\n", sstr);
2625: printf ("\t" BOOL_TYPE " flgo = %s < 0;\n", dstr);
2626: printf ("\t" BOOL_TYPE " flgn = %s < 0;\n", vstr);
2627: break;
2628: }
2629:
2630: switch (type) {
2631: case flag_logical:
2632: printf ("\tCLEAR_CZNV ();\n");
1.1.1.7 root 2633: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
2634: printf ("\tSET_NFLG (%s < 0);\n", vstr);
1.1.1.4 root 2635: break;
2636: case flag_logical_noclobber:
2637: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
2638: printf ("\tSET_NFLG (%s < 0);\n", vstr);
2639: break;
2640: case flag_av:
2641: printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
2642: break;
2643: case flag_sv:
2644: printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
2645: break;
2646: case flag_z:
2647: printf ("\tSET_ZFLG (GET_ZFLG () & (%s == 0));\n", vstr);
2648: break;
2649: case flag_zn:
2650: printf ("\tSET_ZFLG (GET_ZFLG () & (%s == 0));\n", vstr);
2651: printf ("\tSET_NFLG (%s < 0);\n", vstr);
2652: break;
2653: case flag_add:
2654: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
2655: printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
2656: printf ("\tSET_CFLG (%s < %s);\n", undstr, usstr);
2657: duplicate_carry (0);
2658: printf ("\tSET_NFLG (flgn != 0);\n");
2659: break;
2660: case flag_sub:
2661: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
2662: printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
2663: printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
2664: duplicate_carry (0);
2665: printf ("\tSET_NFLG (flgn != 0);\n");
2666: break;
2667: case flag_addx:
2668: printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n"); /* minterm SON: 0x42 */
2669: printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));\n"); /* minterm SON: 0xD4 */
2670: duplicate_carry (0);
2671: break;
2672: case flag_subx:
2673: printf ("\tSET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));\n"); /* minterm SON: 0x24 */
2674: printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));\n"); /* minterm SON: 0xB2 */
2675: duplicate_carry (0);
2676: break;
2677: case flag_cmp:
2678: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
2679: printf ("\tSET_VFLG ((flgs != flgo) && (flgn != flgo));\n");
2680: printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
2681: printf ("\tSET_NFLG (flgn != 0);\n");
2682: break;
2683: }
2684: }
2685:
2686: static void genflags (flagtypes type, wordsizes size, const char *value, const char *src, const char *dst)
2687: {
2688: /* Temporarily deleted 68k/ARM flag optimizations. I'd prefer to have
2689: them in the appropriate m68k.h files and use just one copy of this
2690: code here. The API can be changed if necessary. */
2691: if (optimized_flags) {
2692: switch (type) {
2693: case flag_add:
2694: case flag_sub:
2695: start_brace ();
2696: printf ("\tuae_u32 %s;\n", value);
2697: break;
2698:
2699: default:
2700: break;
2701: }
2702:
2703: /* At least some of those casts are fairly important! */
2704: switch (type) {
2705: case flag_logical_noclobber:
2706: printf ("\t{uae_u32 oldcznv = GET_CZNV & ~(FLAGVAL_Z | FLAGVAL_N);\n");
2707: if (strcmp (value, "0") == 0) {
2708: printf ("\tSET_CZNV (olcznv | FLAGVAL_Z);\n");
2709: } else {
1.1.1.7 root 2710: switch ((int)size) {
1.1.1.4 root 2711: case sz_byte: printf ("\toptflag_testb (regs, (uae_s8)(%s));\n", value); break;
2712: case sz_word: printf ("\toptflag_testw (regs, (uae_s16)(%s));\n", value); break;
2713: case sz_long: printf ("\toptflag_testl (regs, (uae_s32)(%s));\n", value); break;
2714: }
2715: printf ("\tIOR_CZNV (oldcznv);\n");
2716: }
2717: printf ("\t}\n");
2718: return;
2719: case flag_logical:
2720: if (strcmp (value, "0") == 0) {
2721: printf ("\tSET_CZNV (FLAGVAL_Z);\n");
2722: } else {
1.1.1.7 root 2723: switch ((int)size) {
1.1.1.4 root 2724: case sz_byte: printf ("\toptflag_testb (regs, (uae_s8)(%s));\n", value); break;
2725: case sz_word: printf ("\toptflag_testw (regs, (uae_s16)(%s));\n", value); break;
2726: case sz_long: printf ("\toptflag_testl (regs, (uae_s32)(%s));\n", value); break;
2727: }
2728: }
2729: return;
2730:
2731: case flag_add:
1.1.1.7 root 2732: switch ((int)size) {
1.1.1.4 root 2733: case sz_byte: printf ("\toptflag_addb (regs, %s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break;
2734: case sz_word: printf ("\toptflag_addw (regs, %s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break;
2735: case sz_long: printf ("\toptflag_addl (regs, %s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break;
2736: }
2737: return;
2738:
2739: case flag_sub:
1.1.1.7 root 2740: switch ((int)size) {
1.1.1.4 root 2741: case sz_byte: printf ("\toptflag_subb (regs, %s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break;
2742: case sz_word: printf ("\toptflag_subw (regs, %s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break;
2743: case sz_long: printf ("\toptflag_subl (regs, %s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break;
2744: }
2745: return;
2746:
2747: case flag_cmp:
1.1.1.7 root 2748: switch ((int)size) {
1.1.1.4 root 2749: case sz_byte: printf ("\toptflag_cmpb (regs, (uae_s8)(%s), (uae_s8)(%s));\n", src, dst); break;
2750: case sz_word: printf ("\toptflag_cmpw (regs, (uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break;
2751: case sz_long: printf ("\toptflag_cmpl (regs, (uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break;
2752: }
2753: return;
2754:
2755: default:
2756: break;
2757: }
2758: }
2759:
2760: genflags_normal (type, size, value, src, dst);
2761: }
2762:
2763: static void force_range_for_rox (const char *var, wordsizes size)
2764: {
2765: /* Could do a modulo operation here... which one is faster? */
1.1.1.7 root 2766: switch ((int)size) {
1.1.1.4 root 2767: case sz_long:
2768: printf ("\tif (%s >= 33) %s -= 33;\n", var, var);
2769: break;
2770: case sz_word:
2771: printf ("\tif (%s >= 34) %s -= 34;\n", var, var);
2772: printf ("\tif (%s >= 17) %s -= 17;\n", var, var);
2773: break;
2774: case sz_byte:
2775: printf ("\tif (%s >= 36) %s -= 36;\n", var, var);
2776: printf ("\tif (%s >= 18) %s -= 18;\n", var, var);
2777: printf ("\tif (%s >= 9) %s -= 9;\n", var, var);
2778: break;
2779: }
2780: }
2781:
2782: static const char *cmask (wordsizes size)
2783: {
2784: switch (size) {
2785: case sz_byte: return "0x80";
2786: case sz_word: return "0x8000";
2787: case sz_long: return "0x80000000";
1.1.1.7 root 2788: default: term ();
1.1.1.4 root 2789: }
2790: }
2791:
2792: static int source_is_imm1_8 (struct instr *i)
2793: {
2794: return i->stype == 3;
2795: }
2796:
2797: static void shift_ce (amodes dmode, int size)
2798: {
1.1.1.7 root 2799: if (isreg (dmode)) {
1.1.1.4 root 2800: int c = size == sz_long ? 4 : 2;
1.1.1.7 root 2801: if (using_ce) {
2802: printf ("\t{\n");
2803: printf ("\t\tint cycles = %d;\n", c);
2804: printf ("\t\tcycles += 2 * ccnt;\n");
2805: addcycles000_3 ("\t\t");
2806: printf ("\t}\n");
2807: }
2808: addcycles000_nonces("\t", "2 * ccnt");
1.1.1.4 root 2809: count_cycles += c;
1.1.1.7 root 2810: count_ncycles++;
1.1.1.4 root 2811: }
2812: }
2813:
1.1.1.7 root 2814: // BCHG/BSET/BCLR Dx,Dx or #xx,Dx adds 2 cycles if bit number > 15
1.1.1.4 root 2815: static void bsetcycles (struct instr *curi)
2816: {
2817: if (curi->size == sz_byte) {
2818: printf ("\tsrc &= 7;\n");
2819: } else {
2820: printf ("\tsrc &= 31;\n");
2821: if (isreg (curi->dmode)) {
2822: addcycles000 (2);
1.1.1.7 root 2823: if (curi->mnemo != i_BTST) {
2824: if (using_ce)
2825: printf ("\tif (src > 15) %s (2);\n", do_cycles);
2826: addcycles000_nonce("\tif (src > 15) ", 2);
1.1.1.4 root 2827: count_ncycles++;
2828: }
2829: }
2830: }
2831: }
2832:
2833: static int islongimm (struct instr *curi)
2834: {
1.1.1.7 root 2835: return (curi->size == sz_long && (curi->smode == Dreg || curi->smode == imm || curi->smode == Areg));
1.1.1.4 root 2836: }
2837:
2838:
1.1.1.7 root 2839: static void resetvars (void)
2840: {
1.1.1.4 root 2841: insn_n_cycles = using_prefetch ? 0 : 4;
1.1.1.7 root 2842: insn_n_cycles020 = 0;
2843: genamode_cnt = 0;
2844: genamode8r_offset[0] = genamode8r_offset[1] = 0;
2845: m68k_pc_total = 0;
2846: branch_inst = 0;
2847:
2848: ir2irc = 0;
2849: mmufixupcnt = 0;
2850: mmufixupstate = 0;
2851: disp020cnt = 0;
2852: candormw = false;
2853: genastore_done = false;
2854: rmw_varname[0] = 0;
2855: tail_ce020 = 0;
2856: total_ce020 = 0;
2857: tail_ce020_done = false;
2858: head_in_ea_ce020 = 0;
2859: head_ce020_cycs_done = false;
2860: no_prefetch_ce020 = false;
2861: got_ea_ce020 = false;
2862:
2863: prefetch_long = NULL;
1.1.1.9 root 2864: prefetch_opcode = NULL;
1.1.1.7 root 2865: srcli = NULL;
2866: srcbi = NULL;
2867: disp000 = "get_disp_ea_000";
2868: disp020 = "get_disp_ea_020";
2869: nextw = NULL;
2870: nextl = NULL;
2871: do_cycles = "do_cycles";
2872: srcwd = srcld = NULL;
2873: dstwd = dstld = NULL;
2874: srcblrmw = NULL;
2875: srcwlrmw = NULL;
2876: srcllrmw = NULL;
2877: dstblrmw = NULL;
2878: dstwlrmw = NULL;
2879: dstllrmw = NULL;
2880: getpc = "m68k_getpc ()";
2881:
1.1.1.8 root 2882: if (using_indirect > 0) {
1.1.1.7 root 2883: // tracer
2884: getpc = "m68k_getpci ()";
1.1.1.9 root 2885: if (using_mmu == 68030) {
2886: // 68030 cache MMU / CE cache MMU
2887: disp020 = "get_disp_ea_020_mmu030c";
2888: prefetch_long = "get_ilong_mmu030c_state";
2889: prefetch_word = "get_iword_mmu030c_state";
2890: prefetch_opcode = "get_iword_mmu030c_opcode_state";
2891: nextw = "next_iword_mmu030c_state";
2892: nextl = "next_ilong_mmu030c_state";
2893: srcli = "get_ilong_mmu030c_state";
2894: srcwi = "get_iword_mmu030c_state";
2895: srcbi = "get_ibyte_mmu030c_state";
2896: srcl = "get_long_mmu030c_state";
2897: dstl = "put_long_mmu030c_state";
2898: srcw = "get_word_mmu030c_state";
2899: dstw = "put_word_mmu030c_state";
2900: srcb = "get_byte_mmu030c_state";
2901: dstb = "put_byte_mmu030c_state";
2902: srcblrmw = "get_lrmw_byte_mmu030c_state";
2903: srcwlrmw = "get_lrmw_word_mmu030c_state";
2904: srcllrmw = "get_lrmw_long_mmu030c_state";
2905: dstblrmw = "put_lrmw_byte_mmu030c_state";
2906: dstwlrmw = "put_lrmw_word_mmu030c_state";
2907: dstllrmw = "put_lrmw_long_mmu030c_state";
2908: srcld = "get_long_mmu030c";
2909: srcwd = "get_word_mmu030c";
2910: dstld = "put_long_mmu030c";
2911: dstwd = "put_word_mmu030c";
2912: getpc = "m68k_getpci ()";
2913: } else if (!using_ce020 && !using_prefetch_020 && !using_ce) {
1.1.1.7 root 2914: // generic + indirect
2915: disp020 = "x_get_disp_ea_020";
2916: prefetch_long = "get_iilong_jit";
2917: prefetch_word = "get_iiword_jit";
2918: nextw = "next_iiword_jit";
2919: nextl = "next_iilong_jit";
2920: srcli = "get_iilong_jit";
2921: srcwi = "get_iiword_jit";
2922: srcbi = "get_iibyte_jit";
2923: srcl = "x_get_long";
2924: dstl = "x_put_long";
2925: srcw = "x_get_word";
2926: dstw = "x_put_word";
2927: srcb = "x_get_byte";
2928: dstb = "x_put_byte";
2929: getpc = "m68k_getpc()"; // special jit support
2930: } else if (!using_ce020 && !using_prefetch_020) {
2931: prefetch_word = "get_word_ce000_prefetch";
2932: srcli = "x_get_ilong";
2933: srcwi = "x_get_iword";
2934: srcbi = "x_get_ibyte";
2935: srcl = "x_get_long";
2936: dstl = "x_put_long";
2937: srcw = "x_get_word";
2938: dstw = "x_put_word";
2939: srcb = "x_get_byte";
2940: dstb = "x_put_byte";
2941: do_cycles = "do_cycles_ce000_internal";
2942: } else if (using_ce020 == 1) {
2943: /* x_ not used if it redirects to
2944: * get_word_ce020_prefetch()
2945: */
2946: disp020 = "x_get_disp_ea_ce020";
2947: prefetch_word = "get_word_ce020_prefetch";
2948: prefetch_long = "get_long_ce020_prefetch";
1.1.1.9 root 2949: prefetch_opcode = "get_word_ce020_prefetch_opcode";
1.1.1.7 root 2950: srcli = "x_get_ilong";
2951: srcwi = "x_get_iword";
2952: srcbi = "x_get_ibyte";
2953: srcl = "x_get_long";
2954: dstl = "x_put_long";
2955: srcw = "x_get_word";
2956: dstw = "x_put_word";
2957: srcb = "x_get_byte";
2958: dstb = "x_put_byte";
2959: do_cycles = "do_cycles_ce020_internal";
2960: nextw = "next_iword_020ce";
2961: nextl = "next_ilong_020ce";
2962: } else if (using_ce020 == 2) {
2963: // 68030 CE
2964: disp020 = "x_get_disp_ea_ce030";
2965: prefetch_long = "get_long_ce030_prefetch";
2966: prefetch_word = "get_word_ce030_prefetch";
1.1.1.9 root 2967: prefetch_opcode = "get_word_ce030_prefetch_opcode";
1.1.1.7 root 2968: srcli = "x_get_ilong";
2969: srcwi = "x_get_iword";
2970: srcbi = "x_get_ibyte";
2971: srcl = "x_get_long";
2972: dstl = "x_put_long";
2973: srcw = "x_get_word";
2974: dstw = "x_put_word";
2975: srcb = "x_get_byte";
2976: dstb = "x_put_byte";
2977: do_cycles = "do_cycles_ce020_internal";
2978: nextw = "next_iword_030ce";
2979: nextl = "next_ilong_030ce";
2980: } else if (using_ce020 == 3) {
2981: // 68040/060 CE
2982: disp020 = "x_get_disp_ea_040";
2983: prefetch_long = "get_ilong_cache_040";
2984: prefetch_word = "get_iword_cache_040";
2985: srcli = "x_get_ilong";
2986: srcwi = "x_get_iword";
2987: srcbi = "x_get_ibyte";
2988: srcl = "x_get_long";
2989: dstl = "x_put_long";
2990: srcw = "x_get_word";
2991: dstw = "x_put_word";
2992: srcb = "x_get_byte";
2993: dstb = "x_put_byte";
2994: do_cycles = "do_cycles_ce020_internal";
2995: nextw = "next_iword_cache040";
2996: nextl = "next_ilong_cache040";
2997: } else if (using_prefetch_020 == 1) {
2998: disp020 = "x_get_disp_ea_020";
2999: prefetch_word = "get_word_020_prefetch";
3000: prefetch_long = "get_long_020_prefetch";
3001: srcli = "x_get_ilong";
3002: srcwi = "x_get_iword";
3003: srcbi = "x_get_ibyte";
3004: srcl = "x_get_long";
3005: dstl = "x_put_long";
3006: srcw = "x_get_word";
3007: dstw = "x_put_word";
3008: srcb = "x_get_byte";
3009: dstb = "x_put_byte";
3010: nextw = "next_iword_020_prefetch";
3011: nextl = "next_ilong_020_prefetch";
3012: } else if (using_prefetch_020 == 2) {
3013: disp020 = "x_get_disp_ea_020";
3014: prefetch_word = "get_word_030_prefetch";
3015: prefetch_long = "get_long_030_prefetch";
3016: srcli = "x_get_ilong";
3017: srcwi = "x_get_iword";
3018: srcbi = "x_get_ibyte";
3019: srcl = "x_get_long";
3020: dstl = "x_put_long";
3021: srcw = "x_get_word";
3022: dstw = "x_put_word";
3023: srcb = "x_get_byte";
3024: dstb = "x_put_byte";
3025: nextw = "next_iword_030_prefetch";
3026: nextl = "next_ilong_030_prefetch";
3027: }
3028: #if 0
3029: } else if (using_ce020) {
3030: disp020 = "x_get_disp_ea_020";
3031: do_cycles = "do_cycles_ce020";
1.1.1.4 root 3032: if (using_ce020 == 2) {
1.1.1.7 root 3033: // 68030/40/60 CE
3034: prefetch_long = "get_long_ce030_prefetch";
3035: prefetch_word = "get_word_ce030_prefetch";
3036: nextw = "next_iword_030ce";
3037: nextl = "next_ilong_030ce";
3038: srcli = "get_word_ce030_prefetch";
3039: srcwi = "get_long_ce030_prefetch";
1.1.1.4 root 3040: srcl = "get_long_ce030";
3041: dstl = "put_long_ce030";
3042: srcw = "get_word_ce030";
3043: dstw = "put_word_ce030";
3044: srcb = "get_byte_ce030";
3045: dstb = "put_byte_ce030";
3046: } else {
1.1.1.7 root 3047: // 68020 CE
3048: prefetch_long = "get_long_ce020_prefetch";
3049: prefetch_word = "get_word_ce020_prefetch";
3050: nextw = "next_iword_020ce";
3051: nextl = "next_ilong_020ce";
3052: srcli = "get_word_ce020_prefetch";
3053: srcwi = "get_long_ce020_prefetch";
1.1.1.4 root 3054: srcl = "get_long_ce020";
3055: dstl = "put_long_ce020";
3056: srcw = "get_word_ce020";
3057: dstw = "put_word_ce020";
3058: srcb = "get_byte_ce020";
3059: dstb = "put_byte_ce020";
3060: }
1.1.1.7 root 3061: #endif
3062: } else if (using_mmu == 68030) {
3063: // 68030 MMU
3064: disp020 = "get_disp_ea_020_mmu030";
3065: prefetch_long = "get_ilong_mmu030_state";
3066: prefetch_word = "get_iword_mmu030_state";
3067: nextw = "next_iword_mmu030_state";
3068: nextl = "next_ilong_mmu030_state";
3069: srcli = "get_ilong_mmu030_state";
3070: srcwi = "get_iword_mmu030_state";
3071: srcbi = "get_ibyte_mmu030_state";
3072: srcl = "get_long_mmu030_state";
3073: dstl = "put_long_mmu030_state";
3074: srcw = "get_word_mmu030_state";
3075: dstw = "put_word_mmu030_state";
3076: srcb = "get_byte_mmu030_state";
3077: dstb = "put_byte_mmu030_state";
3078: srcblrmw = "get_lrmw_byte_mmu030_state";
3079: srcwlrmw = "get_lrmw_word_mmu030_state";
3080: srcllrmw = "get_lrmw_long_mmu030_state";
3081: dstblrmw = "put_lrmw_byte_mmu030_state";
3082: dstwlrmw = "put_lrmw_word_mmu030_state";
3083: dstllrmw = "put_lrmw_long_mmu030_state";
3084: srcld = "get_long_mmu030";
3085: srcwd = "get_word_mmu030";
3086: dstld = "put_long_mmu030";
3087: dstwd = "put_word_mmu030";
3088: getpc = "m68k_getpci ()";
3089: } else if (using_mmu == 68040) {
3090: // 68040 MMU
3091: disp020 = "x_get_disp_ea_020";
3092: prefetch_long = "get_ilong_mmu040";
3093: prefetch_word = "get_iword_mmu040";
3094: nextw = "next_iword_mmu040";
3095: nextl = "next_ilong_mmu040";
3096: srcli = "get_ilong_mmu040";
3097: srcwi = "get_iword_mmu040";
3098: srcbi = "get_ibyte_mmu040";
3099: srcl = "get_long_mmu040";
3100: dstl = "put_long_mmu040";
3101: srcw = "get_word_mmu040";
3102: dstw = "put_word_mmu040";
3103: srcb = "get_byte_mmu040";
3104: dstb = "put_byte_mmu040";
3105: srcblrmw = "get_lrmw_byte_mmu040";
3106: srcwlrmw = "get_lrmw_word_mmu040";
3107: srcllrmw = "get_lrmw_long_mmu040";
3108: dstblrmw = "put_lrmw_byte_mmu040";
3109: dstwlrmw = "put_lrmw_word_mmu040";
3110: dstllrmw = "put_lrmw_long_mmu040";
3111: getpc = "m68k_getpci ()";
1.1.1.4 root 3112: } else if (using_mmu) {
1.1.1.7 root 3113: // 68060 MMU
3114: disp020 = "x_get_disp_ea_020";
3115: prefetch_long = "get_ilong_mmu060";
3116: prefetch_word = "get_iword_mmu060";
3117: nextw = "next_iword_mmu060";
3118: nextl = "next_ilong_mmu060";
3119: srcli = "get_ilong_mmu060";
3120: srcwi = "get_iword_mmu060";
3121: srcbi = "get_ibyte_mmu060";
3122: srcl = "get_long_mmu060";
3123: dstl = "put_long_mmu060";
3124: srcw = "get_word_mmu060";
3125: dstw = "put_word_mmu060";
3126: srcb = "get_byte_mmu060";
3127: dstb = "put_byte_mmu060";
3128: srcblrmw = "get_lrmw_byte_mmu060";
3129: srcwlrmw = "get_lrmw_word_mmu060";
3130: srcllrmw = "get_lrmw_long_mmu060";
3131: dstblrmw = "put_lrmw_byte_mmu060";
3132: dstwlrmw = "put_lrmw_word_mmu060";
3133: dstllrmw = "put_lrmw_long_mmu060";
3134: // 68060 only: also non-locked read-modify-write accesses are reported
3135: srcbrmw = "get_rmw_byte_mmu060";
3136: srcwrmw = "get_rmw_word_mmu060";
3137: srclrmw = "get_rmw_long_mmu060";
3138: dstbrmw = "put_rmw_byte_mmu060";
3139: dstwrmw = "put_rmw_word_mmu060";
3140: dstlrmw = "put_rmw_long_mmu060";
3141: getpc = "m68k_getpci ()";
1.1.1.4 root 3142: } else if (using_ce) {
1.1.1.7 root 3143: // 68000 ce
3144: prefetch_word = "get_word_ce000_prefetch";
3145: srcwi = "get_wordi_ce000";
3146: srcl = "get_long_ce000";
3147: dstl = "put_long_ce000";
3148: srcw = "get_word_ce000";
3149: dstw = "put_word_ce000";
3150: srcb = "get_byte_ce000";
3151: dstb = "put_byte_ce000";
3152: do_cycles = "do_cycles_ce000";
3153: getpc = "m68k_getpci ()";
3154: } else if (using_prefetch) {
3155: // 68000 prefetch
1.1.1.8 root 3156: prefetch_word = "get_word_000_prefetch";
3157: prefetch_long = "get_long_000_prefetch";
3158: srcwi = "get_wordi_000";
3159: srcl = "get_long_000";
3160: dstl = "put_long_000";
3161: srcw = "get_word_000";
3162: dstw = "put_word_000";
3163: srcb = "get_byte_000";
3164: dstb = "put_byte_000";
1.1.1.7 root 3165: getpc = "m68k_getpci ()";
1.1.1.4 root 3166: } else {
1.1.1.7 root 3167: // generic + direct
3168: prefetch_long = "get_dilong";
3169: prefetch_word = "get_diword";
3170: nextw = "next_diword";
3171: nextl = "next_dilong";
3172: srcli = "get_dilong";
3173: srcwi = "get_diword";
3174: srcbi = "get_dibyte";
1.1.1.8 root 3175: if (using_indirect < 0) {
3176: srcl = "get_long_jit";
3177: dstl = "put_long_jit";
3178: srcw = "get_word_jit";
3179: dstw = "put_word_jit";
3180: srcb = "get_byte_jit";
3181: dstb = "put_byte_jit";
3182: } else {
3183: srcl = "get_long";
3184: dstl = "put_long";
3185: srcw = "get_word";
3186: dstw = "put_word";
3187: srcb = "get_byte";
3188: dstb = "put_byte";
3189: }
1.1.1.4 root 3190: }
1.1.1.7 root 3191: if (!dstld)
3192: dstld = dstl;
3193: if (!dstwd)
3194: dstwd = dstw;
3195: if (!srcld)
3196: srcld = srcl;
3197: if (!srcwd)
3198: srcwd = srcw;
3199: if (!srcblrmw) {
3200: srcblrmw = srcb;
3201: srcwlrmw = srcw;
3202: srcllrmw = srcl;
3203: dstblrmw = dstb;
3204: dstwlrmw = dstw;
3205: dstllrmw = dstl;
3206: }
1.1.1.9 root 3207: if (!prefetch_opcode)
3208: prefetch_opcode = prefetch_word;
1.1.1.4 root 3209:
1.1.1.7 root 3210: }
3211:
3212: static void gen_opcode (unsigned int opcode)
3213: {
3214: struct instr *curi = table68k + opcode;
3215:
3216: resetvars ();
3217:
3218: #ifdef WINUAE_FOR_HATARI
3219: /* Hatari : Store the family of the instruction (used to check for pairing on ST,
3220: * for non-CPU cycles calculation and profiling)
3221: */
3222: printf ("\tOpcodeFamily = %d;\n", curi->mnemo);
3223: /* leave some space for patching in the current cycles later */
3224: if (!using_ce020) {
3225: printf("\tCurrentInstrCycles = \n");
3226: nCurInstrCycPos = ftell(stdout) - 5;
3227: }
3228: #endif
1.1.1.4 root 3229:
3230: start_brace ();
1.1.1.7 root 3231:
1.1.1.4 root 3232: m68k_pc_offset = 2;
1.1.1.7 root 3233:
1.1.1.8 root 3234: // do not unnecessarily create useless mmuop030
3235: // functions when CPU is not 68030
3236: if (curi->mnemo == i_MMUOP030 && cpu_level != 3 && !cpu_generic) {
3237: printf("\top_illg (opcode);\n");
3238: did_prefetch = -1;
3239: goto end;
3240: }
3241:
1.1.1.4 root 3242: switch (curi->plev) {
3243: case 0: /* not privileged */
3244: break;
3245: case 1: /* unprivileged only on 68000 */
3246: if (cpu_level == 0)
3247: break;
3248: if (next_cpu_level < 0)
3249: next_cpu_level = 0;
3250:
3251: /* fall through */
3252: case 2: /* priviledged */
1.1.1.7 root 3253: printf ("if (!regs.s) { Exception (8); goto %s; }\n", endlabelstr);
1.1.1.4 root 3254: need_endlabel = 1;
3255: start_brace ();
3256: break;
3257: case 3: /* privileged if size == word */
3258: if (curi->size == sz_byte)
3259: break;
1.1.1.7 root 3260: printf ("if (!regs.s) { Exception (8); goto %s; }\n", endlabelstr);
1.1.1.4 root 3261: need_endlabel = 1;
3262: start_brace ();
3263: break;
3264: }
3265: switch (curi->mnemo) {
3266: case i_OR:
3267: case i_AND:
3268: case i_EOR:
3269: {
1.1.1.7 root 3270: // documentaion error: and.l #imm,dn = 2 idle, not 1 idle (same as OR and EOR)
1.1.1.4 root 3271: int c = 0;
1.1.1.7 root 3272: genamodedual (curi,
3273: curi->smode, "srcreg", curi->size, "src", 1, 0,
3274: curi->dmode, "dstreg", curi->size, "dst", 1, GF_RMW);
3275: // genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3276: // genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_RMW);
1.1.1.4 root 3277: printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^');
3278: genflags (flag_logical, curi->size, "src", "", "");
3279: if (curi->dmode == Dreg && curi->size == sz_long) {
3280: c += 2;
3281: if (curi->smode == imm || curi->smode == Dreg)
3282: c += 2;
3283: }
3284: fill_prefetch_next ();
3285: if (c > 0)
3286: addcycles000 (c);
3287: genastore_rev ("src", curi->dmode, "dstreg", curi->size, "dst");
3288: break;
3289: }
1.1.1.7 root 3290: // all SR/CCR modifications does full prefetch
1.1.1.4 root 3291: case i_ORSR:
3292: case i_EORSR:
3293: printf ("\tMakeSR ();\n");
1.1.1.7 root 3294: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.4 root 3295: if (curi->size == sz_byte) {
3296: printf ("\tsrc &= 0xFF;\n");
3297: }
3298: addcycles000 (8);
3299: printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|');
1.1.1.9 root 3300: makefromsr_t0();
3301: sync_m68k_pc ();
3302: fill_prefetch_full_ntx();
1.1.1.4 root 3303: break;
3304: case i_ANDSR:
3305: printf ("\tMakeSR ();\n");
1.1.1.7 root 3306: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.4 root 3307: if (curi->size == sz_byte) {
3308: printf ("\tsrc |= 0xFF00;\n");
3309: }
3310: addcycles000 (8);
3311: printf ("\tregs.sr &= src;\n");
1.1.1.9 root 3312: makefromsr_t0();
3313: sync_m68k_pc ();
3314: fill_prefetch_full_ntx();
1.1.1.4 root 3315: break;
3316: case i_SUB:
3317: {
3318: int c = 0;
1.1.1.7 root 3319: genamodedual (curi,
3320: curi->smode, "srcreg", curi->size, "src", 1, 0,
3321: curi->dmode, "dstreg", curi->size, "dst", 1, GF_RMW);
3322: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3323: //genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_RMW);
1.1.1.4 root 3324: if (curi->dmode == Dreg) {
3325: if (curi->size == sz_long) {
3326: c += 2;
1.1.1.7 root 3327: if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg || curi->smode == Areg)
1.1.1.4 root 3328: c += 2;
3329: }
3330: }
3331: fill_prefetch_next ();
3332: if (c > 0)
3333: addcycles000 (c);
3334: start_brace ();
3335: genflags (flag_sub, curi->size, "newv", "src", "dst");
3336: genastore_rev ("newv", curi->dmode, "dstreg", curi->size, "dst");
3337: break;
3338: }
3339: case i_SUBA:
3340: {
3341: int c = 0;
1.1.1.7 root 3342: genamodedual (curi,
3343: curi->smode, "srcreg", curi->size, "src", 1, 0,
3344: curi->dmode, "dstreg", sz_long, "dst", 1, GF_RMW);
3345: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3346: //genamode (curi, curi->dmode, "dstreg", sz_long, "dst", 1, 0, GF_RMW);
1.1.1.4 root 3347: if (curi->smode == immi) {
3348: // SUBAQ.x is always 8 cycles
3349: c += 4;
3350: } else {
3351: c = curi->size == sz_long ? 2 : 4;
3352: if (islongimm (curi))
3353: c += 2;
3354: }
3355: fill_prefetch_next ();
3356: if (c > 0)
3357: addcycles000 (c);
3358: start_brace ();
3359: printf ("\tuae_u32 newv = dst - src;\n");
3360: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
3361: break;
3362: }
3363: case i_SUBX:
3364: if (!isreg (curi->smode))
3365: addcycles000 (2);
1.1.1.9 root 3366: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA | GF_REVERSE);
3367: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA | GF_REVERSE | GF_RMW);
1.1.1.4 root 3368: fill_prefetch_next ();
3369: if (curi->size == sz_long && isreg (curi->smode))
3370: addcycles000 (4);
3371: start_brace ();
3372: printf ("\tuae_u32 newv = dst - src - (GET_XFLG () ? 1 : 0);\n");
3373: genflags (flag_subx, curi->size, "newv", "src", "dst");
3374: genflags (flag_zn, curi->size, "newv", "", "");
3375: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
3376: break;
3377: case i_SBCD:
3378: if (!isreg (curi->smode))
3379: addcycles000 (2);
1.1.1.7 root 3380: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
3381: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA | GF_RMW);
1.1.1.4 root 3382: fill_prefetch_next ();
3383: start_brace ();
3384: printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG () ? 1 : 0);\n");
3385: printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n");
3386: printf ("\tuae_u16 newv, tmp_newv;\n");
3387: printf ("\tint bcd = 0;\n");
3388: printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n");
3389: printf ("\tif (newv_lo & 0xF0) { newv -= 6; bcd = 6; };\n");
3390: printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG () ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n");
3391: printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG () ? 1 : 0)) & 0x300) > 0xFF);\n");
3392: duplicate_carry (0);
1.1.1.9 root 3393: /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */
3394: if (cpu_level >= xBCD_KEEPS_N_FLAG) {
3395: if (next_cpu_level < xBCD_KEEPS_N_FLAG)
3396: next_cpu_level = xBCD_KEEPS_N_FLAG - 1;
1.1.1.4 root 3397: genflags (flag_z, curi->size, "newv", "", "");
3398: } else {
3399: genflags (flag_zn, curi->size, "newv", "", "");
1.1.1.9 root 3400: }
3401: if (cpu_level >= xBCD_KEEPS_V_FLAG) {
3402: if (next_cpu_level < xBCD_KEEPS_V_FLAG)
3403: next_cpu_level = xBCD_KEEPS_V_FLAG - 1;
3404: } else {
1.1.1.4 root 3405: printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
3406: }
1.1.1.7 root 3407: if (isreg (curi->smode)) {
1.1.1.4 root 3408: addcycles000 (2);
1.1.1.7 root 3409: }
1.1.1.4 root 3410: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
3411: break;
3412: case i_ADD:
3413: {
3414: int c = 0;
1.1.1.7 root 3415: genamodedual (curi,
3416: curi->smode, "srcreg", curi->size, "src", 1, 0,
3417: curi->dmode, "dstreg", curi->size, "dst", 1, GF_RMW);
3418: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3419: //genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_RMW);
1.1.1.4 root 3420: if (curi->dmode == Dreg) {
3421: if (curi->size == sz_long) {
3422: c += 2;
1.1.1.7 root 3423: if (curi->smode == imm || curi->smode == immi || curi->smode == Dreg || curi->smode == Areg)
1.1.1.4 root 3424: c += 2;
3425: }
3426: }
3427: fill_prefetch_next ();
3428: if (c > 0)
3429: addcycles000 (c);
3430: start_brace ();
3431: genflags (flag_add, curi->size, "newv", "src", "dst");
3432: genastore_rev ("newv", curi->dmode, "dstreg", curi->size, "dst");
3433: break;
3434: }
3435: case i_ADDA:
3436: {
3437: int c = 0;
1.1.1.7 root 3438: genamodedual (curi,
3439: curi->smode, "srcreg", curi->size, "src", 1, 0,
3440: curi->dmode, "dstreg", sz_long, "dst", 1, GF_RMW);
3441: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3442: //genamode (curi, curi->dmode, "dstreg", sz_long, "dst", 1, 0, GF_RMW);
1.1.1.4 root 3443: if (curi->smode == immi) {
3444: // ADDAQ.x is always 8 cycles
3445: c += 4;
3446: } else {
3447: c = curi->size == sz_long ? 2 : 4;
3448: if (islongimm (curi))
3449: c += 2;
3450: }
3451: fill_prefetch_next ();
3452: if (c > 0)
3453: addcycles000 (c);
3454: start_brace ();
3455: printf ("\tuae_u32 newv = dst + src;\n");
3456: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
3457: break;
3458: }
3459: case i_ADDX:
3460: if (!isreg (curi->smode))
3461: addcycles000 (2);
1.1.1.9 root 3462: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA | GF_REVERSE);
3463: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA | GF_REVERSE | GF_RMW);
1.1.1.4 root 3464: fill_prefetch_next ();
3465: if (curi->size == sz_long && isreg (curi->smode))
3466: addcycles000 (4);
3467: start_brace ();
3468: printf ("\tuae_u32 newv = dst + src + (GET_XFLG () ? 1 : 0);\n");
3469: genflags (flag_addx, curi->size, "newv", "src", "dst");
3470: genflags (flag_zn, curi->size, "newv", "", "");
3471: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
3472: break;
3473: case i_ABCD:
3474: if (!isreg (curi->smode))
3475: addcycles000 (2);
1.1.1.7 root 3476: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
3477: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA | GF_RMW);
1.1.1.4 root 3478: fill_prefetch_next ();
3479: start_brace ();
3480: printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG () ? 1 : 0);\n");
3481: printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n");
3482: printf ("\tuae_u16 newv, tmp_newv;\n");
3483: printf ("\tint cflg;\n");
3484: printf ("\tnewv = tmp_newv = newv_hi + newv_lo;");
3485: printf ("\tif (newv_lo > 9) { newv += 6; }\n");
3486: printf ("\tcflg = (newv & 0x3F0) > 0x90;\n");
3487: printf ("\tif (cflg) newv += 0x60;\n");
3488: printf ("\tSET_CFLG (cflg);\n");
3489: duplicate_carry (0);
1.1.1.9 root 3490: /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */
3491: if (cpu_level >= xBCD_KEEPS_N_FLAG) {
3492: if (next_cpu_level < xBCD_KEEPS_N_FLAG)
3493: next_cpu_level = xBCD_KEEPS_N_FLAG - 1;
1.1.1.4 root 3494: genflags (flag_z, curi->size, "newv", "", "");
1.1.1.9 root 3495: } else {
1.1.1.4 root 3496: genflags (flag_zn, curi->size, "newv", "", "");
1.1.1.9 root 3497: }
3498: if (cpu_level >= xBCD_KEEPS_V_FLAG) {
3499: if (next_cpu_level < xBCD_KEEPS_V_FLAG)
3500: next_cpu_level = xBCD_KEEPS_V_FLAG - 1;
3501: } else {
1.1.1.4 root 3502: printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n");
3503: }
1.1.1.7 root 3504: if (isreg (curi->smode)) {
1.1.1.4 root 3505: addcycles000 (2);
1.1.1.7 root 3506: }
1.1.1.4 root 3507: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
3508: break;
3509: case i_NEG:
1.1.1.7 root 3510: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_RMW);
1.1.1.4 root 3511: fill_prefetch_next ();
3512: if (isreg (curi->smode) && curi->size == sz_long)
3513: addcycles000 (2);
3514: start_brace ();
3515: genflags (flag_sub, curi->size, "dst", "src", "0");
3516: genastore_rev ("dst", curi->smode, "srcreg", curi->size, "src");
3517: break;
3518: case i_NEGX:
1.1.1.7 root 3519: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_RMW);
1.1.1.4 root 3520: fill_prefetch_next ();
3521: if (isreg (curi->smode) && curi->size == sz_long)
3522: addcycles000 (2);
3523: start_brace ();
3524: printf ("\tuae_u32 newv = 0 - src - (GET_XFLG () ? 1 : 0);\n");
3525: genflags (flag_subx, curi->size, "newv", "src", "0");
3526: genflags (flag_zn, curi->size, "newv", "", "");
3527: genastore_rev ("newv", curi->smode, "srcreg", curi->size, "src");
3528: break;
3529: case i_NBCD:
1.1.1.7 root 3530: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_RMW);
1.1.1.4 root 3531: if (isreg (curi->smode))
3532: addcycles000 (2);
3533: fill_prefetch_next ();
3534: start_brace ();
3535: printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG () ? 1 : 0);\n");
3536: printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n");
3537: printf ("\tuae_u16 newv;\n");
1.1.1.7 root 3538: printf ("\tint cflg, tmp_newv;\n");
1.1.1.9 root 3539: printf ("\ttmp_newv = newv_hi + newv_lo;\n");
1.1.1.4 root 3540: printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n");
1.1.1.9 root 3541: printf ("\tnewv = newv_hi + newv_lo;\n");
1.1.1.4 root 3542: printf ("\tcflg = (newv & 0x1F0) > 0x90;\n");
3543: printf ("\tif (cflg) newv -= 0x60;\n");
3544: printf ("\tSET_CFLG (cflg);\n");
3545: duplicate_carry(0);
1.1.1.9 root 3546: /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */
3547: if (cpu_level >= xBCD_KEEPS_N_FLAG) {
3548: if (next_cpu_level < xBCD_KEEPS_N_FLAG)
3549: next_cpu_level = xBCD_KEEPS_N_FLAG - 1;
1.1.1.4 root 3550: genflags (flag_z, curi->size, "newv", "", "");
1.1.1.9 root 3551: } else {
1.1.1.4 root 3552: genflags (flag_zn, curi->size, "newv", "", "");
1.1.1.9 root 3553: }
3554: if (cpu_level >= xBCD_KEEPS_V_FLAG) {
3555: if (next_cpu_level < xBCD_KEEPS_V_FLAG)
3556: next_cpu_level = xBCD_KEEPS_V_FLAG - 1;
3557: } else {
1.1.1.7 root 3558: printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
1.1.1.4 root 3559: }
3560: genastore ("newv", curi->smode, "srcreg", curi->size, "src");
3561: break;
3562: case i_CLR:
1.1.1.7 root 3563: next_level_000 ();
3564: genamode (curi, curi->smode, "srcreg", curi->size, "src", cpu_level == 0 ? 1 : 2, 0, 0);
1.1.1.4 root 3565: fill_prefetch_next ();
3566: if (isreg (curi->smode) && curi->size == sz_long)
3567: addcycles000 (2);
3568: genflags (flag_logical, curi->size, "0", "", "");
3569: genastore_rev ("0", curi->smode, "srcreg", curi->size, "src");
3570: break;
3571: case i_NOT:
1.1.1.7 root 3572: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_RMW);
1.1.1.4 root 3573: fill_prefetch_next ();
3574: if (isreg (curi->smode) && curi->size == sz_long)
3575: addcycles000 (2);
3576: start_brace ();
3577: printf ("\tuae_u32 dst = ~src;\n");
3578: genflags (flag_logical, curi->size, "dst", "", "");
3579: genastore_rev ("dst", curi->smode, "srcreg", curi->size, "src");
3580: break;
3581: case i_TST:
1.1.1.7 root 3582: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.4 root 3583: fill_prefetch_next ();
3584: genflags (flag_logical, curi->size, "src", "", "");
3585: break;
3586: case i_BTST:
1.1.1.7 root 3587: genamodedual (curi,
3588: curi->smode, "srcreg", curi->size, "src", 1, 0,
3589: curi->dmode, "dstreg", curi->size, "dst", 1, 0);
3590: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3591: //genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_IR2IRC);
1.1.1.4 root 3592: fill_prefetch_next ();
3593: bsetcycles (curi);
3594: printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
3595: break;
3596: case i_BCHG:
3597: case i_BCLR:
3598: case i_BSET:
1.1.1.7 root 3599: // on 68000 these have weird side-effect, if EA points to write-only custom register
3600: //during instruction's read access CPU data lines appear as zero to outside world,
3601: // (normally previously fetched data appears in data lines if reading write-only register)
3602: // this allows stupid things like bset #2,$dff096 to work "correctly"
3603: // NOTE: above can't be right.
3604: genamodedual (curi,
3605: curi->smode, "srcreg", curi->size, "src", 1, 0,
3606: curi->dmode, "dstreg", curi->size, "dst", 1, GF_RMW);
3607: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3608: //genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_IR2IRC | GF_RMW);
1.1.1.4 root 3609: fill_prefetch_next ();
3610: bsetcycles (curi);
3611: // bclr needs 1 extra cycle
3612: if (curi->mnemo == i_BCLR && curi->dmode == Dreg)
3613: addcycles000 (2);
3614: if (curi->mnemo == i_BCHG) {
3615: printf ("\tdst ^= (1 << src);\n");
3616: printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n");
3617: } else if (curi->mnemo == i_BCLR) {
3618: printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
3619: printf ("\tdst &= ~(1 << src);\n");
3620: } else if (curi->mnemo == i_BSET) {
3621: printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
3622: printf ("\tdst |= (1 << src);\n");
3623: }
3624: genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
3625: break;
3626: case i_CMPM:
3627: // confirmed
1.1.1.7 root 3628: genamodedual (curi,
3629: curi->smode, "srcreg", curi->size, "src", 1, GF_AA,
3630: curi->dmode, "dstreg", curi->size, "dst", 1, GF_AA);
3631: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA);
3632: //genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_AA);
1.1.1.4 root 3633: fill_prefetch_next ();
3634: start_brace ();
3635: genflags (flag_cmp, curi->size, "newv", "src", "dst");
3636: break;
3637: case i_CMP:
1.1.1.7 root 3638: genamodedual (curi,
3639: curi->smode, "srcreg", curi->size, "src", 1, 0,
3640: curi->dmode, "dstreg", curi->size, "dst", 1, 0);
3641: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3642: //genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
1.1.1.4 root 3643: fill_prefetch_next ();
3644: if (curi->dmode == Dreg && curi->size == sz_long)
3645: addcycles000 (2);
3646: start_brace ();
3647: genflags (flag_cmp, curi->size, "newv", "src", "dst");
3648: break;
3649: case i_CMPA:
1.1.1.7 root 3650: genamodedual (curi,
3651: curi->smode, "srcreg", curi->size, "src", 1, 0,
3652: curi->dmode, "dstreg", sz_long, "dst", 1, 0);
3653: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3654: //genamode (curi, curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0);
1.1.1.4 root 3655: fill_prefetch_next ();
3656: addcycles000 (2);
3657: start_brace ();
3658: genflags (flag_cmp, sz_long, "newv", "src", "dst");
3659: break;
3660: /* The next two are coded a little unconventional, but they are doing
3661: * weird things... */
3662: case i_MVPRM: // MOVEP R->M
1.1.1.7 root 3663: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.4 root 3664: printf ("\tuaecptr memp = m68k_areg (regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0));
3665: if (curi->size == sz_word) {
1.1.1.7 root 3666: printf ("\t%s (memp, src >> 8);\n\t%s (memp + 2, src);\n", dstb, dstb);
1.1.1.4 root 3667: count_write += 2;
3668: } else {
1.1.1.7 root 3669: printf ("\t%s (memp, src >> 24);\n\t%s (memp + 2, src >> 16);\n", dstb, dstb);
3670: printf ("\t%s (memp + 4, src >> 8);\n\t%s (memp + 6, src);\n", dstb, dstb);
3671: count_write += 4;
3672: }
1.1.1.4 root 3673: fill_prefetch_next ();
3674: break;
3675: case i_MVPMR: // MOVEP M->R
3676: printf ("\tuaecptr memp = m68k_areg (regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword (0));
1.1.1.7 root 3677: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0);
3678: if (curi->size == sz_word) {
1.1.1.9 root 3679: printf ("\tuae_u16 val = (%s (memp) & 0xff) << 8;\n", srcb);
3680: printf ("\t val |= (%s (memp + 2) & 0xff);\n", srcb);
1.1.1.7 root 3681: count_read += 2;
3682: } else {
1.1.1.9 root 3683: printf ("\tuae_u32 val = (%s (memp) & 0xff) << 24;\n", srcb);
3684: printf ("\t val |= (%s (memp + 2) & 0xff) << 16;\n", srcb);
3685: printf ("\t val |= (%s (memp + 4) & 0xff) << 8;\n", srcb);
3686: printf ("\t val |= (%s (memp + 6) & 0xff);\n", srcb);
1.1.1.7 root 3687: count_read += 4;
3688: }
1.1.1.4 root 3689: fill_prefetch_next ();
3690: genastore ("val", curi->dmode, "dstreg", curi->size, "dst");
3691: break;
3692: case i_MOVE:
3693: case i_MOVEA:
3694: {
3695: /* 2 MOVE instruction variants have special prefetch sequence:
3696: * - MOVE <ea>,-(An) = prefetch is before writes (Apdi)
3697: * - MOVE memory,(xxx).L = 2 prefetches after write
1.1.1.7 root 3698: * - move.x #imm = prefetch is done before write
1.1.1.4 root 3699: * - all others = prefetch is done after writes
3700: *
3701: * - move.x xxx,[at least 1 extension word here] = fetch 1 extension word before (xxx)
3702: *
3703: */
1.1.1.7 root 3704: if (isce020()) {
3705: // MOVE is too complex to handle in table68k
3706: int h = 0, t = 0, c = 0, subhead = 0;
3707: bool fea = false;
3708: if (curi->smode == immi && isreg (curi->dmode)) {
3709: // MOVEQ
3710: h = 2; t = 0; c = 0;
3711: } else if (isreg (curi->smode) && isreg (curi->dmode)) {
3712: // MOVE Rn,Rn
3713: h = 2; t = 0; c = 2;
3714: } else if (isreg (curi->dmode)) {
3715: // MOVE EA,Rn
3716: h = 0; t = 0; c = 2;
3717: fea = true;
3718: } else if (curi->dmode == Aind) {
3719: if (isreg (curi->smode)) {
3720: // MOVE Rn,(An)
3721: h = 0; t = 1; c = 3;
3722: } else {
3723: // MOVE SOURCE,(An)
3724: h = 2; t = 0; c = 4;
3725: fea = true;
3726: }
3727: } else if (curi->dmode == Aipi) {
3728: if (isreg (curi->smode)) {
3729: // MOVE Rn,(An)+
3730: h = 0; t = 1; c = 3;
3731: } else {
3732: // MOVE SOURCE,(An)+
3733: h = 2; t = 0; c = 4;
3734: fea = true;
3735: }
3736: } else if (curi->dmode == Apdi) {
3737: if (isreg (curi->smode)) {
3738: // MOVE Rn,-(An)
3739: h = 0; t = 2; c = 4;
3740: } else {
3741: // MOVE SOURCE,-(An)
3742: h = 2; t = 0; c = 4;
3743: fea = true;
3744: }
3745: } else if (curi->dmode == Ad16) {
3746: // MOVE EA,(d16,An)
3747: h = 2; t = 0; c = 4;
3748: fea = true;
3749: } else if (curi->dmode == Ad8r) {
3750: h = 4; t = 0; c = 6;
3751: fea = true;
3752: } else if (curi->dmode == absw) {
3753: // MOVE EA,xxx.W
3754: h = 2; t = 0; c = 4;
3755: fea = true;
3756: } else if (curi->dmode == absl) {
3757: // MOVE EA,xxx.L
3758: h = 0; t = 0; c = 6;
3759: fea = true;
3760: } else {
3761: h = 4; t = 0; c = 6;
3762: fea = true;
3763: }
3764: if (fea) {
3765: if (curi->smode == imm)
3766: subhead = gence020cycles_fiea (curi, curi->size, Dreg);
3767: else
3768: subhead = gence020cycles_fea (curi->smode);
3769: }
3770: genamode2x (curi->smode, "srcreg", curi->size, "src", 1, 0, 0, fea ? fetchmode_fea : -1);
3771: genamode2 (curi->dmode, "dstreg", curi->size, "dst", 2, 0, GF_MOVE);
3772: addopcycles_ce20 (h, t, c, -subhead);
3773: if (curi->mnemo == i_MOVEA && curi->size == sz_word)
3774: printf ("\tsrc = (uae_s32)(uae_s16)src;\n");
3775: if (curi->mnemo == i_MOVE)
3776: genflags (flag_logical, curi->size, "src", "", "");
3777: genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
3778: sync_m68k_pc ();
3779:
3780: } else {
1.1.1.9 root 3781:
1.1.1.7 root 3782: int prefetch_done = 0, flags;
3783: int dualprefetch = curi->dmode == absl && (curi->smode != Dreg && curi->smode != Areg && curi->smode != imm);
1.1.1.9 root 3784:
1.1.1.7 root 3785: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3786: flags = GF_MOVE | GF_APDI;
3787: //if (curi->size == sz_long && (curi->smode == Dreg || curi->smode == Areg))
3788: // flags &= ~GF_APDI;
3789: flags |= dualprefetch ? GF_NOREFILL : 0;
1.1.1.9 root 3790: if (curi->dmode == Apdi && curi->size == sz_long)
3791: flags |= GF_REVERSE;
1.1.1.7 root 3792: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, flags);
3793: if (curi->mnemo == i_MOVEA && curi->size == sz_word)
3794: printf ("\tsrc = (uae_s32)(uae_s16)src;\n");
3795: if (curi->dmode == Apdi) {
3796: fill_prefetch_next ();
3797: prefetch_done = 1;
3798: }
3799: if (curi->mnemo == i_MOVE)
3800: genflags (flag_logical, curi->size, "src", "", "");
3801:
3802: if (curi->size == sz_long) {
3803: if ((curi->dmode == Ad16 || curi->dmode == PC16) && curi->smode == imm) {
3804: // lots more needed..
3805: // move.l x,absl
3806: // move.l (an),x(an)
3807: single_check_ipl();
3808: }
3809: }
1.1.1.9 root 3810: // MOVE EA,-(An) long writes are always reversed. Reads are normal.
3811: if (curi->dmode == Apdi && curi->size == sz_long) {
3812: genastore_rev("src", curi->dmode, "dstreg", curi->size, "dst");
3813: } else {
3814: genastore("src", curi->dmode, "dstreg", curi->size, "dst");
3815: }
1.1.1.7 root 3816: sync_m68k_pc ();
3817: if (dualprefetch) {
3818: fill_prefetch_full_000 ();
3819: prefetch_done = 1;
3820: }
3821: if (!prefetch_done)
3822: fill_prefetch_next ();
1.1.1.4 root 3823: }
3824: }
3825: break;
3826: case i_MVSR2: // MOVE FROM SR
1.1.1.7 root 3827: genamode (curi, curi->smode, "srcreg", sz_word, "src", 2, 0, 0);
3828: if (isreg (curi->smode)) {
3829: fill_prefetch_next ();
1.1.1.4 root 3830: addcycles000 (2);
1.1.1.7 root 3831: } else {
3832: // write to memory, dummy write to same address, X-flag seems to be always set
3833: if (cpu_level <= 1 && curi->size == sz_word) {
3834: printf ("\t%s (srca, regs.sr | 0x0010);\n", dstw);
3835: count_write++;
3836: }
3837: fill_prefetch_next ();
3838: }
1.1.1.4 root 3839: printf ("\tMakeSR ();\n");
1.1.1.7 root 3840: // real write
1.1.1.4 root 3841: if (curi->size == sz_byte)
3842: genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src");
3843: else
3844: genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src");
3845: break;
3846: case i_MV2SR: // MOVE TO SR
1.1.1.7 root 3847: genamode (curi, curi->smode, "srcreg", sz_word, "src", 1, 0, 0);
1.1.1.4 root 3848: if (curi->size == sz_byte) {
3849: // MOVE TO CCR
3850: addcycles000 (4);
3851: printf ("\tMakeSR ();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n");
3852: } else {
3853: // MOVE TO SR
3854: addcycles000 (4);
3855: printf ("\tregs.sr = src;\n");
3856: }
1.1.1.9 root 3857: makefromsr_t0();
3858: // does full prefetch because S-bit change may change memory mapping under the CPU
3859: sync_m68k_pc ();
3860: fill_prefetch_full_ntx();
1.1.1.4 root 3861: break;
3862: case i_SWAP:
1.1.1.7 root 3863: genamode (curi, curi->smode, "srcreg", sz_long, "src", 1, 0, 0);
1.1.1.4 root 3864: fill_prefetch_next ();
3865: start_brace ();
3866: printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n");
3867: genflags (flag_logical, sz_long, "dst", "", "");
3868: genastore ("dst", curi->smode, "srcreg", sz_long, "src");
3869: break;
3870: case i_EXG:
3871: // confirmed
1.1.1.7 root 3872: genamodedual (curi,
3873: curi->smode, "srcreg", curi->size, "src", 1, 0,
3874: curi->dmode, "dstreg", curi->size, "dst", 1, 0);
3875: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
3876: //genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
1.1.1.4 root 3877: fill_prefetch_next ();
3878: addcycles000 (2);
3879: genastore ("dst", curi->smode, "srcreg", curi->size, "src");
3880: genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
3881: break;
3882: case i_EXT:
3883: // confirmed
1.1.1.7 root 3884: genamode (curi, curi->smode, "srcreg", sz_long, "src", 1, 0, 0);
1.1.1.4 root 3885: fill_prefetch_next ();
3886: start_brace ();
3887: switch (curi->size) {
3888: case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break;
3889: case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break;
3890: case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break;
1.1.1.7 root 3891: default: term ();
1.1.1.4 root 3892: }
3893: genflags (flag_logical,
3894: curi->size == sz_word ? sz_word : sz_long, "dst", "", "");
3895: genastore ("dst", curi->smode, "srcreg",
3896: curi->size == sz_word ? sz_word : sz_long, "src");
3897: break;
3898: case i_MVMEL:
3899: // confirmed
1.1.1.7 root 3900: if (using_ce || using_prefetch)
1.1.1.4 root 3901: genmovemel_ce (opcode);
3902: else
3903: genmovemel (opcode);
1.1.1.7 root 3904: tail_ce020_done = true;
1.1.1.4 root 3905: break;
3906: case i_MVMLE:
3907: // confirmed
1.1.1.7 root 3908: if (using_ce || using_prefetch)
1.1.1.4 root 3909: genmovemle_ce (opcode);
3910: else
3911: genmovemle (opcode);
1.1.1.7 root 3912: tail_ce020_done = true;
1.1.1.4 root 3913: break;
3914: case i_TRAP:
1.1.1.7 root 3915: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.10! root 3916: gen_set_fault_pc (false);
1.1.1.4 root 3917: sync_m68k_pc ();
1.1.1.9 root 3918: printf ("\tException_cpu(src + 32);\n");
1.1.1.4 root 3919: did_prefetch = 1;
1.1.1.7 root 3920: clear_m68k_offset();
1.1.1.4 root 3921: break;
3922: case i_MVR2USP:
1.1.1.7 root 3923: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.4 root 3924: fill_prefetch_next ();
3925: printf ("\tregs.usp = src;\n");
3926: break;
3927: case i_MVUSP2R:
1.1.1.7 root 3928: genamode (curi, curi->smode, "srcreg", curi->size, "src", 2, 0, 0);
1.1.1.4 root 3929: fill_prefetch_next ();
3930: genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src");
3931: break;
3932: case i_RESET:
3933: fill_prefetch_next ();
3934: printf ("\tcpureset ();\n");
1.1.1.7 root 3935: sync_m68k_pc ();
1.1.1.4 root 3936: addcycles000 (128);
1.1.1.7 root 3937: if (using_prefetch) {
3938: printf ("\t%s (2);\n", prefetch_word);
3939: clear_m68k_offset();
3940: }
1.1.1.4 root 3941: break;
3942: case i_NOP:
3943: fill_prefetch_next ();
3944: break;
3945: case i_STOP:
1.1.1.9 root 3946: next_level_000();
1.1.1.4 root 3947: if (using_prefetch) {
1.1.1.9 root 3948: printf("\tuae_u16 sr = regs.irc;\n");
1.1.1.4 root 3949: m68k_pc_offset += 2;
3950: } else {
1.1.1.7 root 3951: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.9 root 3952: printf("\tuae_u16 sr = src;\n");
3953: }
3954: // STOP undocumented features:
3955: // if SR is not set:
3956: // 68000 (68010?): Update SR, increase PC and then cause privilege violation exception (handled in newcpu)
3957: // 68000 (68010?): Traced STOP also runs 4 cycles faster.
3958: // 68020 68030: STOP works normally
3959: // 68040 68060: Immediate privilege violation exception
3960: if ((cpu_level == 0 || cpu_level == 1) && using_ce) {
3961: printf("\t%s(regs.t1 ? 4 : 8);\n", do_cycles);
3962: }
3963: if (cpu_level >= 4) {
3964: printf("\tif (!(sr & 0x2000)) {\n");
3965: incpc("%d", m68k_pc_offset);
3966: printf("\t\tException(8); goto %s;\n", endlabelstr);
3967: printf("\t}\n");
1.1.1.4 root 3968: }
1.1.1.9 root 3969: printf("\tregs.sr = sr;\n");
3970: makefromsr();
1.1.1.4 root 3971: printf ("\tm68k_setstopped ();\n");
3972: sync_m68k_pc ();
3973: // STOP does not prefetch anything
3974: did_prefetch = -1;
1.1.1.9 root 3975: next_cpu_level = cpu_level - 1;
1.1.1.4 root 3976: break;
3977: case i_LPSTOP: /* 68060 */
1.1.1.7 root 3978: printf ("\tuae_u16 sw = %s (2);\n", srcwi);
3979: printf ("\tif (sw != (0x100|0x80|0x40)) { Exception (4); goto %s; }\n", endlabelstr);
1.1.1.9 root 3980: printf("\tif (!(regs.sr & 0x2000)) {\n");
3981: printf("\t\tException(8); goto %s;\n", endlabelstr);
3982: printf("\t}\n");
3983: printf("\tregs.sr = %s (4);\n", srcwi);
3984: makefromsr();
1.1.1.4 root 3985: printf ("\tm68k_setstopped();\n");
3986: m68k_pc_offset += 4;
3987: sync_m68k_pc ();
1.1.1.9 root 3988: fill_prefetch_full_ntx();
1.1.1.4 root 3989: break;
3990: case i_RTE:
1.1.1.7 root 3991: addop_ce020 (curi, 0);
3992: next_level_000 ();
1.1.1.4 root 3993: if (cpu_level == 0) {
1.1.1.7 root 3994: genamode (NULL, Aipi, "7", sz_word, "sr", 1, 0, GF_NOREFILL);
3995: genamode (NULL, Aipi, "7", sz_long, "pc", 1, 0, GF_NOREFILL);
1.1.1.10! root 3996: printf("\tuaecptr oldpc = %s;\n", getpc);
1.1.1.4 root 3997: printf ("\tregs.sr = sr;\n");
1.1.1.7 root 3998: printf ("\tif (pc & 1) {\n");
3999: printf ("\t\texception3i (0x%04X, pc);\n", opcode);
4000: printf ("\t\tgoto %s;\n", endlabelstr);
4001: printf ("\t}\n");
1.1.1.4 root 4002: setpc ("pc");
1.1.1.10! root 4003: printf("\tbranch_stack_pop_rte(oldpc);\n");
1.1.1.9 root 4004: makefromsr();
1.1.1.7 root 4005: } else if (cpu_level == 1 && using_prefetch) {
4006: int old_brace_level = n_braces;
1.1.1.10! root 4007: printf("\tuaecptr oldpc = %s;\n", getpc);
1.1.1.7 root 4008: printf ("\tuae_u16 newsr; uae_u32 newpc;\n");
4009: printf ("\tfor (;;) {\n");
4010: printf ("\t\tuaecptr a = m68k_areg (regs, 7);\n");
4011: printf ("\t\tuae_u16 sr = %s (a);\n", srcw);
4012: count_read++;
4013: printf ("\t\tuae_u32 pc = %s (a + 2) << 16; pc |= %s (a + 4);\n", srcw, srcw);
4014: count_read += 2;
4015: printf ("\t\tuae_u16 format = %s (a + 2 + 4);\n", srcw);
4016: count_read++;
4017: printf ("\t\tint frame = format >> 12;\n");
4018: printf ("\t\tint offset = 8;\n");
4019: printf ("\t\tnewsr = sr; newpc = pc;\n");
4020: printf ("\t\tif (frame == 0x0) { m68k_areg (regs, 7) += offset; break; }\n");
4021: printf ("\t\telse if (frame == 0x8) { m68k_areg (regs, 7) += offset + 50; break; }\n");
1.1.1.9 root 4022: printf ("\t\telse { m68k_areg (regs, 7) += offset; Exception_cpu(14); goto %s; }\n", endlabelstr);
1.1.1.7 root 4023: printf ("\t\tregs.sr = newsr; MakeFromSR ();\n}\n");
4024: pop_braces (old_brace_level);
4025: printf ("\tregs.sr = newsr;\n");
1.1.1.9 root 4026: makefromsr();
1.1.1.7 root 4027: printf ("\tif (newpc & 1) {\n");
4028: printf ("\t\texception3i (0x%04X, newpc);\n", opcode);
4029: printf ("\t\tgoto %s;\n", endlabelstr);
4030: printf ("\t}\n");
4031: setpc ("newpc");
1.1.1.10! root 4032: printf("\tbranch_stack_pop_rte(oldpc);\n");
1.1.1.7 root 4033: check_ipl ();
4034: need_endlabel = 1;
1.1.1.4 root 4035: } else {
1.1 root 4036: int old_brace_level = n_braces;
1.1.1.10! root 4037: printf("\tuaecptr oldpc = %s;\n", getpc);
! 4038: printf ("\tuae_u16 newsr; uae_u32 newpc;\n");
1.1 root 4039: printf ("\tfor (;;) {\n");
4040: printf ("\t\tuaecptr a = m68k_areg (regs, 7);\n");
1.1.1.5 root 4041: printf ("\t\tuae_u16 sr = %s (a);\n", srcw);
1.1.1.7 root 4042: count_read++;
1.1.1.5 root 4043: printf ("\t\tuae_u32 pc = %s (a + 2);\n", srcl);
1.1.1.7 root 4044: count_read += 2;
1.1.1.5 root 4045: printf ("\t\tuae_u16 format = %s (a + 2 + 4);\n", srcw);
1.1.1.7 root 4046: count_read++;
1.1 root 4047: printf ("\t\tint frame = format >> 12;\n");
4048: printf ("\t\tint offset = 8;\n");
4049: printf ("\t\tnewsr = sr; newpc = pc;\n");
1.1.1.7 root 4050: addcycles_ce020 (6);
1.1 root 4051: printf ("\t\tif (frame == 0x0) { m68k_areg (regs, 7) += offset; break; }\n");
4052: printf ("\t\telse if (frame == 0x1) { m68k_areg (regs, 7) += offset; }\n");
4053: printf ("\t\telse if (frame == 0x2) { m68k_areg (regs, 7) += offset + 4; break; }\n");
1.1.1.9 root 4054: if (cpu_level >= 4) {
4055: printf ("\t\telse if (frame == 0x3) { m68k_areg (regs, 7) += offset + 4; break; }\n");
4056: }
4057: if (using_mmu == 68060) {
1.1.1.7 root 4058: printf ("\t\telse if (frame == 0x4) { m68k_do_rte_mmu060 (a); m68k_areg (regs, 7) += offset + 8; break; }\n");
1.1.1.8 root 4059: } else if (cpu_level >= 4) {
1.1.1.7 root 4060: printf ("\t\telse if (frame == 0x4) { m68k_areg (regs, 7) += offset + 8; break; }\n");
4061: }
1.1.1.8 root 4062: if (cpu_level == 1) // 68010 only
4063: printf ("\t\telse if (frame == 0x8) { m68k_areg (regs, 7) += offset + 50; break; }\n");
1.1.1.7 root 4064: if (using_mmu == 68040) {
4065: printf ("\t\telse if (frame == 0x7) { m68k_do_rte_mmu040 (a); m68k_areg (regs, 7) += offset + 52; break; }\n");
1.1.1.8 root 4066: } else if (cpu_level >= 4) {
1.1.1.7 root 4067: printf ("\t\telse if (frame == 0x7) { m68k_areg (regs, 7) += offset + 52; break; }\n");
4068: }
1.1.1.9 root 4069: if (cpu_level == 2 || cpu_level == 3) { // 68020/68030 only
4070: printf ("\t\telse if (frame == 0x9) { m68k_areg (regs, 7) += offset + 12; break; }\n");
4071: if (using_mmu == 68030) {
4072: if (using_prefetch_020) {
4073: printf ("\t\telse if (frame == 0xa) { m68k_do_rte_mmu030c (a); break; }\n");
4074: printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030c (a); goto %s; }\n", endlabelstr);
4075: } else {
4076: printf ("\t\telse if (frame == 0xa) { m68k_do_rte_mmu030 (a); break; }\n");
1.1.1.10! root 4077: printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030 (a); goto %s; }\n", endlabelstr);
1.1.1.9 root 4078: }
4079: } else {
4080: printf ("\t\telse if (frame == 0xa) { m68k_areg (regs, 7) += offset + 24; break; }\n");
4081: printf ("\t\telse if (frame == 0xb) { m68k_areg (regs, 7) += offset + 84; break; }\n");
4082: }
1.1.1.7 root 4083: }
1.1.1.9 root 4084: printf ("\t\telse { m68k_areg (regs, 7) += offset; Exception_cpu(14); goto %s; }\n", endlabelstr);
1.1.1.7 root 4085: printf ("\t\tregs.sr = newsr;\n");
1.1.1.9 root 4086: makefromsr_t0();
1.1.1.7 root 4087: printf ("}\n");
1.1 root 4088: pop_braces (old_brace_level);
1.1.1.7 root 4089: printf ("\tregs.sr = newsr;\n");
4090: addcycles_ce020 (4);
1.1.1.9 root 4091: makefromsr_t0();
1.1 root 4092: printf ("\tif (newpc & 1) {\n");
1.1.1.7 root 4093: printf ("\t\texception3i (0x%04X, newpc);\n", opcode);
1.1 root 4094: printf ("\t\tgoto %s;\n", endlabelstr);
4095: printf ("\t}\n");
1.1.1.7 root 4096: setpc ("newpc");
1.1.1.10! root 4097: printf("\tbranch_stack_pop_rte(oldpc);\n");
1.1.1.7 root 4098: check_ipl ();
1.1 root 4099: need_endlabel = 1;
1.1.1.4 root 4100: }
4101: /* PC is set and prefetch filled. */
1.1.1.7 root 4102: clear_m68k_offset();
4103: tail_ce020_done = true;
1.1.1.9 root 4104: fill_prefetch_full_ntx();
1.1.1.7 root 4105: branch_inst = 1;
1.1.1.9 root 4106: next_cpu_level = cpu_level - 1;
1.1.1.4 root 4107: break;
4108: case i_RTD:
1.1.1.7 root 4109: addop_ce020 (curi, 0);
1.1.1.4 root 4110: if (using_mmu) {
1.1.1.7 root 4111: genamode (curi, curi->smode, "srcreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
4112: genamode (NULL, Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
1.1.1.4 root 4113: printf ("\tm68k_areg(regs, 7) += offs;\n");
4114: } else {
1.1.1.7 root 4115: genamode (NULL, Aipi, "7", sz_long, "pc", 1, 0, 0);
4116: genamode (curi, curi->smode, "srcreg", curi->size, "offs", 1, 0, 0);
1.1.1.4 root 4117: printf ("\tm68k_areg (regs, 7) += offs;\n");
4118: }
1.1 root 4119: printf ("\tif (pc & 1) {\n");
1.1.1.7 root 4120: printf ("\t\texception3i (0x%04X, pc);\n", opcode);
1.1 root 4121: printf ("\t\tgoto %s;\n", endlabelstr);
4122: printf ("\t}\n");
1.1.1.4 root 4123: setpc ("pc");
4124: /* PC is set and prefetch filled. */
1.1.1.7 root 4125: clear_m68k_offset();
4126: tail_ce020_done = true;
1.1.1.4 root 4127: fill_prefetch_full ();
1.1 root 4128: need_endlabel = 1;
1.1.1.7 root 4129: branch_inst = 1;
1.1.1.4 root 4130: break;
4131: case i_LINK:
4132: // ce confirmed
4133: if (using_mmu) {
1.1.1.7 root 4134: addmmufixup ("srcreg");
4135: genamode (NULL, curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
4136: genamode (NULL, Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, 0);
4137: genamode (NULL, curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, 0);
1.1.1.4 root 4138: genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
4139: printf ("\tm68k_areg(regs, 7) += offs;\n");
4140: genastore ("src", Apdi, "7", sz_long, "old");
4141: } else {
1.1.1.7 root 4142: addop_ce020 (curi, 0);
4143: genamode (NULL, Apdi, "7", sz_long, "old", 2, 0, GF_AA);
4144: genamode (NULL, curi->smode, "srcreg", sz_long, "src", 1, 0, GF_AA);
4145: genamode (NULL, curi->dmode, "dstreg", curi->size, "offs", 1, 0, 0);
1.1.1.4 root 4146: genastore ("src", Apdi, "7", sz_long, "old");
4147: genastore ("m68k_areg (regs, 7)", curi->smode, "srcreg", sz_long, "src");
4148: printf ("\tm68k_areg (regs, 7) += offs;\n");
4149: fill_prefetch_next ();
4150: }
4151: break;
4152: case i_UNLK:
4153: // ce confirmed
4154: if (using_mmu) {
1.1.1.7 root 4155: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
4156: printf ("\tuae_s32 old = %s (src);\n", srcl);
1.1 root 4157: printf ("\tm68k_areg (regs, 7) = src + 4;\n");
4158: printf ("\tm68k_areg (regs, srcreg) = old;\n");
1.1.1.4 root 4159: } else {
1.1.1.7 root 4160: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.4 root 4161: printf ("\tm68k_areg (regs, 7) = src;\n");
1.1.1.7 root 4162: genamode (NULL, Aipi, "7", sz_long, "old", 1, 0, 0);
1.1.1.4 root 4163: fill_prefetch_next ();
4164: genastore ("old", curi->smode, "srcreg", curi->size, "src");
4165: }
4166: break;
4167: case i_RTS:
1.1.1.7 root 4168: addop_ce020 (curi, 0);
4169: printf ("\tuaecptr pc = %s;\n", getpc);
1.1.1.8 root 4170: if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce) {
1.1.1.7 root 4171: printf("\tm68k_do_rtsi_jit ();\n");
1.1.1.9 root 4172: } else if (using_mmu) {
4173: printf ("\tm68k_do_rts_mmu%s ();\n", mmu_postfix);
1.1.1.7 root 4174: } else if (using_ce020 == 1) {
4175: add_head_cycs (1);
1.1.1.4 root 4176: printf ("\tm68k_do_rts_ce020 ();\n");
1.1.1.7 root 4177: } else if (using_ce020 == 2) {
4178: add_head_cycs (1);
1.1.1.4 root 4179: printf ("\tm68k_do_rts_ce030 ();\n");
1.1.1.7 root 4180: } else if (using_ce) {
1.1.1.4 root 4181: printf ("\tm68k_do_rts_ce ();\n");
1.1.1.7 root 4182: } else if (using_prefetch || using_prefetch_020) {
4183: printf ("\tm68k_do_rtsi ();\n");
4184: } else {
1.1.1.4 root 4185: printf ("\tm68k_do_rts ();\n");
1.1.1.7 root 4186: }
1.1.1.10! root 4187: printf("\tif (debugmem_trace)\n");
! 4188: printf("\t\tbranch_stack_pop_rts(pc);\n");
1.1.1.7 root 4189: printf ("\tif (%s & 1) {\n", getpc);
4190: printf ("\t\tuaecptr faultpc = %s;\n", getpc);
4191: setpc ("pc");
4192: printf ("\t\texception3i (0x%04X, faultpc);\n", opcode);
1.1 root 4193: printf ("\t\tgoto %s;\n", endlabelstr);
4194: printf ("\t}\n");
1.1.1.4 root 4195: count_read += 2;
1.1.1.7 root 4196: clear_m68k_offset();
1.1.1.4 root 4197: fill_prefetch_full ();
1.1 root 4198: need_endlabel = 1;
1.1.1.7 root 4199: branch_inst = 1;
1.1.1.4 root 4200: break;
4201: case i_TRAPV:
4202: sync_m68k_pc ();
4203: fill_prefetch_next ();
4204: printf ("\tif (GET_VFLG ()) {\n");
1.1.1.9 root 4205: printf ("\t\tException_cpu(7);\n");
1.1.1.4 root 4206: printf ("\t\tgoto %s;\n", endlabelstr);
4207: printf ("\t}\n");
4208: need_endlabel = 1;
4209: break;
4210: case i_RTR:
1.1.1.7 root 4211: printf ("\tuaecptr oldpc = %s;\n", getpc);
1.1.1.4 root 4212: printf ("\tMakeSR ();\n");
1.1.1.7 root 4213: genamode (NULL, Aipi, "7", sz_word, "sr", 1, 0, 0);
4214: genamode (NULL, Aipi, "7", sz_long, "pc", 1, 0, 0);
1.1.1.4 root 4215: printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
4216: printf ("\tregs.sr |= sr;\n");
4217: setpc ("pc");
1.1.1.9 root 4218: makefromsr();
1.1.1.7 root 4219: printf ("\tif (%s & 1) {\n", getpc);
4220: printf ("\t\tuaecptr faultpc = %s;\n", getpc);
4221: setpc ("oldpc");
4222: printf ("\t\texception3i (0x%04X, faultpc);\n", opcode);
4223: printf ("\t\tgoto %s;\n", endlabelstr);
4224: printf ("\t}\n");
4225: clear_m68k_offset();
1.1.1.4 root 4226: fill_prefetch_full ();
1.1.1.7 root 4227: need_endlabel = 1;
4228: branch_inst = 1;
4229: tail_ce020_done = true;
1.1.1.4 root 4230: break;
1.1.1.7 root 4231: case i_JSR:
4232: // possible idle cycle, prefetch from new address, stack high return addr, stack low, prefetch
4233: no_prefetch_ce020 = true;
4234: genamode (curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA|GF_NOREFILL);
1.1.1.4 root 4235: start_brace ();
1.1.1.10! root 4236: printf("\tuaecptr oldpc = %s;\n", getpc);
! 4237: printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset);
1.1.1.4 root 4238: if (using_exception_3) {
4239: printf ("\tif (srca & 1) {\n");
1.1.1.7 root 4240: printf ("\t\texception3i (opcode, srca);\n");
1.1.1.4 root 4241: printf ("\t\tgoto %s;\n", endlabelstr);
4242: printf ("\t}\n");
4243: need_endlabel = 1;
4244: }
4245: if (using_mmu) {
1.1.1.10! root 4246: printf ("\t%s (m68k_areg (regs, 7) - 4, nextpc);\n", dstl);
1.1.1.4 root 4247: printf ("\tm68k_areg (regs, 7) -= 4;\n");
4248: setpc ("srca");
1.1.1.7 root 4249: clear_m68k_offset();
1.1.1.4 root 4250: } else {
4251: if (curi->smode == Ad16 || curi->smode == absw || curi->smode == PC16)
4252: addcycles000 (2);
1.1.1.7 root 4253: if (curi->smode == Ad8r || curi->smode == PC8r) {
4254: addcycles000 (6);
4255: #ifdef WINUAE_FOR_HATARI
4256: /* Hatari : JSR in Ad8r and PC8r mode takes 22 cycles, but on ST it takes 24 cycles */
4257: /* because of an unaligned memory prefetch in this EA mode */
4258: /* We add 2 cycles only in 68000 prefetch mode, 68000 CE mode is handled at the memory access level */
4259: if ( using_prefetch && !using_ce )
4260: addcycles000 (2);
4261: #endif
4262: if (cpu_level <= 1 && using_prefetch)
1.1.1.10! root 4263: printf ("\tnextpc += 2;\n");
1.1.1.7 root 4264: }
1.1.1.4 root 4265: setpc ("srca");
1.1.1.7 root 4266: clear_m68k_offset();
1.1.1.4 root 4267: fill_prefetch_1 (0);
4268: printf ("\tm68k_areg (regs, 7) -= 4;\n");
1.1.1.7 root 4269: if (using_ce || using_prefetch) {
1.1.1.10! root 4270: printf ("\t%s (m68k_areg (regs, 7), nextpc >> 16);\n", dstw);
! 4271: printf ("\t%s (m68k_areg (regs, 7) + 2, nextpc);\n", dstw);
1.1.1.4 root 4272: } else {
1.1.1.10! root 4273: printf ("\t%s (m68k_areg (regs, 7), nextpc);\n", dstl);
1.1.1.4 root 4274: }
1.1.1.10! root 4275: printf("\tif (debugmem_trace)\n");
! 4276: printf("\t\tbranch_stack_push(oldpc, nextpc);\n");
1.1.1.4 root 4277: }
4278: count_write += 2;
1.1.1.7 root 4279: fill_prefetch_full_020 ();
1.1.1.4 root 4280: fill_prefetch_next ();
1.1.1.7 root 4281: branch_inst = 1;
1.1.1.4 root 4282: break;
4283: case i_JMP:
1.1.1.7 root 4284: no_prefetch_ce020 = true;
4285: genamode (curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA|GF_NOREFILL);
1.1.1.4 root 4286: if (using_exception_3) {
4287: printf ("\tif (srca & 1) {\n");
1.1.1.7 root 4288: printf ("\t\texception3i (opcode, srca);\n");
1.1.1.4 root 4289: printf ("\t\tgoto %s;\n", endlabelstr);
4290: printf ("\t}\n");
4291: need_endlabel = 1;
4292: }
1.1.1.7 root 4293: if (curi->smode == Ad16 || curi->smode == absw || curi->smode == PC16)
1.1.1.4 root 4294: addcycles000 (2);
1.1.1.7 root 4295: if (curi->smode == Ad8r || curi->smode == PC8r) {
4296: addcycles000 (6);
4297: #ifdef WINUAE_FOR_HATARI
4298: /* Hatari : JMP in Ad8r and PC8r mode takes 22 cycles, but on ST it takes 24 cycles */
4299: /* because of an unaligned memory prefetch in this EA mode */
4300: /* We add 2 cycles only in 68000 prefetch mode, 68000 CE mode is handled at the memory access level */
4301: if ( using_prefetch && !using_ce )
4302: addcycles000 (2);
4303: #endif
4304: }
1.1.1.4 root 4305: setpc ("srca");
1.1.1.7 root 4306: clear_m68k_offset();
1.1.1.4 root 4307: fill_prefetch_full ();
1.1.1.7 root 4308: branch_inst = 1;
1.1.1.4 root 4309: break;
4310: case i_BSR:
1.1.1.7 root 4311: // .b/.w = idle cycle, store high, store low, 2xprefetch
4312: if (isce020())
4313: no_prefetch_ce020 = true;
1.1.1.4 root 4314: printf ("\tuae_s32 s;\n");
1.1.1.7 root 4315: if (curi->size == sz_long) {
4316: if (next_cpu_level < 1)
4317: next_cpu_level = 1;
4318: }
4319: if (curi->size == sz_long && cpu_level < 2) {
4320: printf ("\tuae_u32 src = 0xffffffff;\n");
4321: } else {
4322: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA|GF_NOREFILL);
4323: }
1.1.1.4 root 4324: printf ("\ts = (uae_s32)src + 2;\n");
4325: if (using_exception_3) {
4326: printf ("\tif (src & 1) {\n");
1.1.1.7 root 4327: printf ("\t\texception3b (opcode, %s + s, 0, 1, %s + s);\n", getpc, getpc);
1.1.1.4 root 4328: printf ("\t\tgoto %s;\n", endlabelstr);
4329: printf ("\t}\n");
4330: need_endlabel = 1;
4331: }
4332: addcycles000 (2);
1.1.1.10! root 4333: printf("\tuaecptr oldpc = %s;\n", getpc);
! 4334: printf("\tuaecptr nextpc = oldpc + %d;\n", m68k_pc_offset);
1.1.1.8 root 4335: if (using_indirect > 0 && !using_ce020 && !using_prefetch_020 && !using_ce) {
1.1.1.10! root 4336: printf("\tm68k_do_bsri_jit (nextpc, s);\n");
1.1.1.9 root 4337: } else if (using_mmu) {
1.1.1.10! root 4338: printf ("\tm68k_do_bsr_mmu%s (nextpc, s);\n", mmu_postfix);
1.1.1.7 root 4339: } else if (using_ce020 == 1) {
1.1.1.10! root 4340: printf ("\tm68k_do_bsr_ce020 (nextpc, s);\n");
1.1.1.4 root 4341: } else if (using_ce020 == 2) {
1.1.1.10! root 4342: printf ("\tm68k_do_bsr_ce030 (nextpc, s);\n");
1.1.1.4 root 4343: } else if (using_ce) {
1.1.1.10! root 4344: printf ("\tm68k_do_bsr_ce (nextpc, s);\n");
1.1.1.7 root 4345: } else if (using_prefetch || using_prefetch_020) {
1.1.1.10! root 4346: printf ("\tm68k_do_bsri (nextpc, s);\n");
1.1.1.4 root 4347: } else {
1.1.1.10! root 4348: printf ("\tm68k_do_bsr (nextpc, s);\n");
1.1.1.4 root 4349: }
1.1.1.10! root 4350: printf("\tif (debugmem_trace)\n");
! 4351: printf("\t\tbranch_stack_push(oldpc, nextpc);\n");
1.1.1.4 root 4352: count_write += 2;
1.1.1.7 root 4353: clear_m68k_offset();
1.1.1.4 root 4354: fill_prefetch_full ();
1.1.1.7 root 4355: branch_inst = 1;
1.1.1.4 root 4356: break;
4357: case i_Bcc:
1.1.1.7 root 4358: tail_ce020_done = true;
1.1.1.4 root 4359: if (curi->size == sz_long) {
4360: if (cpu_level < 2) {
4361: addcycles000 (2);
4362: printf ("\tif (cctrue (%d)) {\n", curi->cc);
1.1.1.7 root 4363: printf ("\t\texception3i (opcode, %s + 1);\n", getpc);
1.1.1.4 root 4364: printf ("\t\tgoto %s;\n", endlabelstr);
4365: printf ("\t}\n");
4366: sync_m68k_pc ();
1.1.1.7 root 4367: addcycles000 (2);
1.1.1.4 root 4368: irc2ir ();
4369: fill_prefetch_2 ();
4370: need_endlabel = 1;
1.1.1.7 root 4371: goto bccl_not68020;
1.1.1.4 root 4372: } else {
4373: if (next_cpu_level < 1)
4374: next_cpu_level = 1;
4375: }
4376: }
1.1.1.7 root 4377: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0));
1.1.1.4 root 4378: addcycles000 (2);
4379: printf ("\tif (!cctrue (%d)) goto didnt_jump;\n", curi->cc);
4380: if (using_exception_3) {
4381: printf ("\tif (src & 1) {\n");
1.1.1.7 root 4382: printf ("\t\texception3i (opcode, %s + 2 + (uae_s32)src);\n", getpc);
1.1.1.4 root 4383: printf ("\t\tgoto %s;\n", endlabelstr);
4384: printf ("\t}\n");
4385: need_endlabel = 1;
4386: }
1.1.1.7 root 4387: push_ins_cnt();
1.1.1.4 root 4388: if (using_prefetch) {
4389: incpc ("(uae_s32)src + 2");
1.1.1.7 root 4390: fill_prefetch_full_000 ();
1.1.1.4 root 4391: if (using_ce)
4392: printf ("\treturn;\n");
4393: else
4394: printf ("\treturn 10 * CYCLE_UNIT / 2;\n");
4395: } else {
4396: incpc ("(uae_s32)src + 2");
1.1.1.7 root 4397: add_head_cycs (6);
4398: fill_prefetch_full_020 ();
4399: returncycles ("\t", 10);
1.1.1.4 root 4400: }
1.1.1.7 root 4401: pop_ins_cnt();
1.1.1.4 root 4402: printf ("didnt_jump:;\n");
4403: need_endlabel = 1;
4404: sync_m68k_pc ();
1.1.1.7 root 4405: addcycles000 (2);
4406: get_prefetch_020_continue ();
1.1.1.4 root 4407: if (curi->size == sz_byte) {
4408: irc2ir ();
1.1.1.7 root 4409: add_head_cycs (4);
1.1.1.4 root 4410: fill_prefetch_2 ();
4411: } else if (curi->size == sz_word) {
1.1.1.7 root 4412: add_head_cycs (6);
4413: fill_prefetch_full_000 ();
1.1.1.4 root 4414: } else {
1.1.1.7 root 4415: add_head_cycs (6);
4416: fill_prefetch_full_000 ();
1.1.1.4 root 4417: }
4418: insn_n_cycles = curi->size == sz_byte ? 8 : 12;
1.1.1.7 root 4419: branch_inst = 1;
4420: bccl_not68020:
1.1.1.4 root 4421: break;
4422: case i_LEA:
4423: if (curi->smode == Ad8r || curi->smode == PC8r)
4424: addcycles000 (2);
1.1.1.7 root 4425: genamodedual (curi,
4426: curi->smode, "srcreg", curi->size, "src", 0, GF_AA,
4427: curi->dmode, "dstreg", curi->size, "dst", 2, GF_AA);
4428: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA);
4429: //genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, GF_AA);
4430: if (curi->smode == Ad8r || curi->smode == PC8r) {
1.1.1.4 root 4431: addcycles000 (2);
1.1.1.7 root 4432: #ifdef WINUAE_FOR_HATARI
4433: /* Hatari : LEA in Ad8r and PC8r mode takes 12 cycles, but on ST it takes 14 cycles */
4434: /* because of an unaligned memory prefetch in this EA mode */
4435: /* We add 2 cycles only in 68000 prefetch mode, 68000 CE mode is handled at the memory access level */
4436: if ( using_prefetch && !using_ce )
4437: addcycles000 (2);
4438: #endif
4439: }
4440: fill_prefetch_next ();
1.1.1.4 root 4441: genastore ("srca", curi->dmode, "dstreg", curi->size, "dst");
4442: break;
4443: case i_PEA:
4444: if (curi->smode == Ad8r || curi->smode == PC8r)
4445: addcycles000 (2);
1.1.1.7 root 4446: genamode (curi, curi->smode, "srcreg", curi->size, "src", 0, 0, GF_AA);
4447: genamode (NULL, Apdi, "7", sz_long, "dst", 2, 0, GF_AA);
1.1.1.4 root 4448: if (!(curi->smode == absw || curi->smode == absl))
4449: fill_prefetch_next ();
1.1.1.7 root 4450: if (curi->smode == Ad8r || curi->smode == PC8r) {
1.1.1.4 root 4451: addcycles000 (2);
1.1.1.7 root 4452: #ifdef WINUAE_FOR_HATARI
4453: /* Hatari : PEA in Ad8r and PC8r mode takes 20 cycles, but on ST it takes 22 cycles */
4454: /* because of an unaligned memory prefetch in this EA mode */
4455: /* We add 2 cycles only in 68000 prefetch mode, 68000 CE mode is handled at the memory access level */
4456: if ( using_prefetch && !using_ce )
4457: addcycles000 (2);
4458: #endif
4459: }
1.1.1.4 root 4460: genastore ("srca", Apdi, "7", sz_long, "dst");
4461: if ((curi->smode == absw || curi->smode == absl))
4462: fill_prefetch_next ();
4463: break;
4464: case i_DBcc:
1.1.1.7 root 4465: // cc true: idle cycle, prefetch
4466: // cc false, counter expired: idle cycle, prefetch (from branch address), 2xprefetch (from next address)
4467: // cc false, counter not expired: idle cycle, prefetch
4468: tail_ce020_done = true;
4469: genamodedual (curi,
4470: curi->smode, "srcreg", curi->size, "src", 1, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0),
4471: curi->dmode, "dstreg", curi->size, "offs", 1, GF_AA | (cpu_level < 2 ? GF_NOREFILL : 0));
4472: //genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_AA | GF_NOREFILL);
4473: //genamode (curi, curi->dmode, "dstreg", curi->size, "offs", 1, 0, GF_AA | GF_NOREFILL);
4474: printf ("\tuaecptr oldpc = %s;\n", getpc);
1.1.1.4 root 4475: addcycles000 (2);
1.1.1.7 root 4476: push_ins_cnt();
1.1.1.4 root 4477: printf ("\tif (!cctrue (%d)) {\n", curi->cc);
1.1.1.7 root 4478: incpc ("(uae_s32)offs + 2");
4479: printf ("\t");
1.1.1.4 root 4480: fill_prefetch_1 (0);
1.1.1.7 root 4481: printf ("\t");
4482: genastore ("(src - 1)", curi->smode, "srcreg", curi->size, "src");
1.1.1.4 root 4483:
4484: printf ("\t\tif (src) {\n");
4485: if (using_exception_3) {
4486: printf ("\t\t\tif (offs & 1) {\n");
1.1.1.7 root 4487: printf ("\t\t\t\texception3i (opcode, %s + 2 + (uae_s32)offs + 2);\n", getpc);
1.1.1.4 root 4488: printf ("\t\t\t\tgoto %s;\n", endlabelstr);
4489: printf ("\t\t\t}\n");
4490: need_endlabel = 1;
4491: }
4492: irc2ir ();
1.1.1.7 root 4493: add_head_cycs (6);
1.1.1.4 root 4494: fill_prefetch_1 (2);
1.1.1.7 root 4495: fill_prefetch_full_020 ();
1.1.1.8 root 4496: returncycles ("\t\t\t", 10);
1.1.1.4 root 4497: printf ("\t\t}\n");
1.1.1.7 root 4498: add_head_cycs (10);
1.1.1.8 root 4499: addcycles000_nonce("\t\t", 2 + 2);
1.1.1.4 root 4500: printf ("\t} else {\n");
1.1.1.7 root 4501: addcycles000_onlyce(2);
4502: addcycles000_nonce("\t\t", 2);
1.1.1.4 root 4503: printf ("\t}\n");
1.1.1.7 root 4504: pop_ins_cnt();
1.1.1.4 root 4505: setpc ("oldpc + %d", m68k_pc_offset);
1.1.1.7 root 4506: clear_m68k_offset();
4507: get_prefetch_020_continue ();
4508: fill_prefetch_full_000 ();
1.1.1.4 root 4509: insn_n_cycles = 12;
4510: need_endlabel = 1;
1.1.1.7 root 4511: branch_inst = 1;
1.1.1.4 root 4512: break;
4513: case i_Scc:
4514: // confirmed
1.1.1.7 root 4515: next_level_000 ();
4516: genamode (curi, curi->smode, "srcreg", curi->size, "src", cpu_level == 0 ? 1 : 2, 0, 0);
1.1.1.4 root 4517: start_brace ();
4518: fill_prefetch_next();
4519: start_brace ();
4520: printf ("\tint val = cctrue (%d) ? 0xff : 0;\n", curi->cc);
1.1.1.7 root 4521: if (isreg (curi->smode)) {
4522: if (using_ce)
4523: printf ("\tint cycles = val ? 2 : 0;\n");
1.1.1.4 root 4524: addcycles000_3 ("\t");
1.1.1.7 root 4525: addcycles000_nonces("\t", "(val ? 2 : 0)");
1.1.1.4 root 4526: }
4527: genastore ("val", curi->smode, "srcreg", curi->size, "src");
4528: break;
4529: case i_DIVU:
1.1.1.7 root 4530: tail_ce020_done = true;
4531: genamodedual (curi,
4532: curi->smode, "srcreg", sz_word, "src", 1, 0,
4533: curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1.1.1.4 root 4534: printf ("\tCLEAR_CZNV ();\n");
4535: printf ("\tif (src == 0) {\n");
1.1.1.7 root 4536: if (cpu_level > 1)
4537: printf ("\t\tdivbyzero_special (0, dst);\n");
1.1.1.4 root 4538: incpc ("%d", m68k_pc_offset);
1.1.1.9 root 4539: printf ("\t\tException_cpu(5);\n");
1.1.1.4 root 4540: printf ("\t\tgoto %s;\n", endlabelstr);
4541: printf ("\t} else {\n");
4542: printf ("\t\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n");
4543: printf ("\t\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n");
4544: if (using_ce) {
4545: start_brace ();
1.1.1.7 root 4546: printf ("\t\tint cycles = (getDivu68kCycles((uae_u32)dst, (uae_u16)src)) - 4;\n");
1.1.1.4 root 4547: addcycles000_3 ("\t\t");
4548: }
1.1.1.7 root 4549: addcycles000_nonces("\t\t", "(getDivu68kCycles((uae_u32)dst, (uae_u16)src)) - 4");
4550: fill_prefetch_next ();
1.1.1.4 root 4551: /* The N flag appears to be set each time there is an overflow.
1.1.1.7 root 4552: * Weird. but 68020 only sets N when dst is negative.. */
1.1.1.4 root 4553: printf ("\t\tif (newv > 0xffff) {\n");
1.1.1.9 root 4554: printf ("\t\t\tsetdivuoverflowflags((uae_u32)dst, (uae_u16)src);\n");
1.1.1.4 root 4555: printf ("\t\t} else {\n");
4556: printf ("\t\t"); genflags (flag_logical, sz_word, "newv", "", "");
4557: printf ("\t\t\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
4558: printf ("\t\t"); genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
4559: printf ("\t\t}\n");
4560: sync_m68k_pc ();
4561: printf ("\t}\n");
4562: count_ncycles++;
4563: insn_n_cycles += 136 - (136 - 76) / 2; /* average */
4564: need_endlabel = 1;
1.1.1.7 root 4565: tail_ce020_done = false;
4566: returntail (false);
1.1.1.4 root 4567: break;
4568: case i_DIVS:
1.1.1.7 root 4569: tail_ce020_done = true;
4570: genamodedual (curi,
4571: curi->smode, "srcreg", sz_word, "src", 1, 0,
4572: curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1.1.1.4 root 4573: printf ("\tif (src == 0) {\n");
1.1.1.7 root 4574: if (cpu_level > 1)
4575: printf ("\t\tdivbyzero_special (1, dst);\n");
1.1.1.4 root 4576: incpc ("%d", m68k_pc_offset);
1.1.1.9 root 4577: printf ("\t\tException_cpu(5);\n");
1.1.1.4 root 4578: printf ("\t\tgoto %s;\n", endlabelstr);
1.1.1.7 root 4579: printf ("\t}\n");
4580: printf ("\tCLEAR_CZNV ();\n");
1.1.1.4 root 4581: if (using_ce) {
4582: start_brace ();
1.1.1.7 root 4583: printf ("\t\tint cycles = (getDivs68kCycles((uae_s32)dst, (uae_s16)src)) - 4;\n");
1.1.1.4 root 4584: addcycles000_3 ("\t\t");
4585: }
1.1.1.7 root 4586: addcycles000_nonces("\t\t", "(getDivs68kCycles((uae_s32)dst, (uae_s16)src)) - 4");
4587: fill_prefetch_next ();
4588: printf ("\tif (dst == 0x80000000 && src == -1) {\n");
1.1.1.9 root 4589: printf ("\t\tsetdivsoverflowflags((uae_s32)dst, (uae_s16)src);\n");
1.1.1.7 root 4590: printf ("\t} else {\n");
4591: printf ("\t\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
4592: printf ("\t\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n");
1.1.1.4 root 4593: printf ("\t\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) {\n");
1.1.1.9 root 4594: printf ("\t\t\tsetdivsoverflowflags((uae_s32)dst, (uae_s16)src);\n");
1.1.1.4 root 4595: printf ("\t\t} else {\n");
4596: printf ("\t\t\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n");
4597: genflags (flag_logical, sz_word, "newv", "", "");
4598: printf ("\t\t\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
4599: printf ("\t\t"); genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
4600: printf ("\t\t}\n");
4601: printf ("\t}\n");
1.1.1.7 root 4602: sync_m68k_pc ();
1.1.1.4 root 4603: count_ncycles++;
4604: insn_n_cycles += 156 - (156 - 120) / 2; /* average */
4605: need_endlabel = 1;
1.1.1.7 root 4606: tail_ce020_done = false;
4607: returntail (false);
1.1.1.4 root 4608: break;
4609: case i_MULU:
1.1.1.7 root 4610: genamodedual (curi,
4611: curi->smode, "srcreg", sz_word, "src", 1, 0,
4612: curi->dmode, "dstreg", sz_word, "dst", 1, 0);
1.1.1.4 root 4613: fill_prefetch_next();
4614: start_brace ();
4615: printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n");
4616: if (using_ce)
4617: printf ("\tint cycles = 38 - 4, bits;\n");
1.1.1.7 root 4618: else if (using_prefetch)
4619: printf ("\tint bits;\n");
1.1.1.4 root 4620: genflags (flag_logical, sz_long, "newv", "", "");
4621: if (using_ce) {
4622: printf ("\tfor(bits = 0; bits < 16 && src; bits++, src >>= 1)\n");
4623: printf ("\t\tif (src & 1) cycles += 2;\n");
4624: addcycles000_3 ("\t");
4625: }
1.1.1.7 root 4626: addcycles000_nonce("\tfor(bits = 0; bits < 16 && src; bits++, src >>= 1)\n\t\tif (src & 1) ", 2);
1.1.1.4 root 4627: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
4628: sync_m68k_pc ();
4629: count_cycles += 38 - 4;
4630: count_ncycles++;
4631: insn_n_cycles += (70 - 38) / 2 + 38; /* average */
4632: break;
4633: case i_MULS:
1.1.1.7 root 4634: genamodedual (curi,
4635: curi->smode, "srcreg", sz_word, "src", 1, 0,
4636: curi->dmode, "dstreg", sz_word, "dst", 1, 0);
1.1.1.4 root 4637: fill_prefetch_next();
4638: start_brace ();
4639: printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n");
4640: if (using_ce) {
4641: printf ("\tint cycles = 38 - 4, bits;\n");
4642: printf ("\tuae_u32 usrc;\n");
1.1.1.7 root 4643: } else if (using_prefetch) {
4644: printf ("\tint bits;\n");
4645: printf ("\tuae_u32 usrc;\n");
1.1.1.4 root 4646: }
4647: genflags (flag_logical, sz_long, "newv", "", "");
4648: if (using_ce) {
4649: printf ("\tusrc = ((uae_u32)src) << 1;\n");
4650: printf ("\tfor(bits = 0; bits < 16 && usrc; bits++, usrc >>= 1)\n");
4651: printf ("\t\tif ((usrc & 3) == 1 || (usrc & 3) == 2) cycles += 2;\n");
4652: addcycles000_3 ("\t");
4653: }
1.1.1.7 root 4654: addcycles000_nonce("\tusrc = ((uae_u32)src) << 1;\n\tfor(bits = 0; bits < 16 && usrc; bits++, usrc >>= 1)\n\t\tif ((usrc & 3) == 1 || (usrc & 3) == 2) ", 2);
1.1.1.4 root 4655: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
4656: count_cycles += 38 - 4;
4657: count_ncycles++;
4658: insn_n_cycles += (70 - 38) / 2 + 38; /* average */
4659: break;
4660: case i_CHK:
1.1.1.7 root 4661: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
4662: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
1.1.1.4 root 4663: sync_m68k_pc ();
4664: addcycles000 (4);
4665: printf ("\tif (dst > src) {\n");
4666: printf ("\t\tSET_NFLG (0);\n");
1.1.1.9 root 4667: printf ("\t\tException_cpu(6);\n");
1.1.1.4 root 4668: printf ("\t\tgoto %s;\n", endlabelstr);
4669: printf ("\t}\n");
4670: addcycles000 (2);
4671: printf ("\tif ((uae_s32)dst < 0) {\n");
4672: printf ("\t\tSET_NFLG (1);\n");
1.1.1.9 root 4673: printf ("\t\tException_cpu(6);\n");
1.1.1.4 root 4674: printf ("\t\tgoto %s;\n", endlabelstr);
4675: printf ("\t}\n");
4676: fill_prefetch_next ();
4677: need_endlabel = 1;
4678: break;
4679: case i_CHK2:
1.1.1.7 root 4680: genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
4681: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0);
1.1.1.4 root 4682: fill_prefetch_0 ();
4683: printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n");
4684: switch (curi->size) {
4685: case sz_byte:
4686: printf ("\tlower = (uae_s32)(uae_s8)%s (dsta); upper = (uae_s32)(uae_s8)%s (dsta + 1);\n", srcb, srcb);
4687: printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s8)reg;\n");
4688: break;
4689: case sz_word:
4690: printf ("\tlower = (uae_s32)(uae_s16)%s (dsta); upper = (uae_s32)(uae_s16)%s (dsta + 2);\n", srcw, srcw);
4691: printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s16)reg;\n");
4692: break;
4693: case sz_long:
4694: printf ("\tlower = %s (dsta); upper = %s (dsta + 4);\n", srcl, srcl);
4695: break;
4696: default:
1.1.1.7 root 4697: term ();
1.1.1.4 root 4698: }
4699: printf ("\tSET_ZFLG (upper == reg || lower == reg);\n");
4700: printf ("\tSET_CFLG_ALWAYS (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n");
1.1.1.9 root 4701: printf ("\tif ((extra & 0x800) && GET_CFLG ()) { Exception_cpu(6); goto %s; }\n}\n", endlabelstr);
1.1.1.7 root 4702: need_endlabel = 1;
1.1.1.4 root 4703: break;
4704:
4705: case i_ASR:
1.1.1.7 root 4706: genamodedual (curi,
4707: curi->smode, "srcreg", curi->size, "cnt", 1, 0,
4708: curi->dmode, "dstreg", curi->size, "data", 1, GF_RMW);
4709: //genamode (curi, curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
4710: //genamode (curi, curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 4711: fill_prefetch_next();
4712: start_brace ();
4713: switch (curi->size) {
4714: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
4715: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
4716: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 4717: default: term ();
1.1.1.4 root 4718: }
4719: printf ("\tuae_u32 sign = (%s & val) >> %d;\n", cmask (curi->size), bit_size (curi->size) - 1);
4720: printf ("\tint ccnt = cnt & 63;\n");
4721: printf ("\tcnt &= 63;\n");
4722: printf ("\tCLEAR_CZNV ();\n");
4723: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
4724: printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size));
4725: printf ("\t\tSET_CFLG (sign);\n");
4726: duplicate_carry (1);
4727: if (source_is_imm1_8 (curi))
4728: printf ("\t} else {\n");
1.1.1.7 root 4729: else
1.1.1.4 root 4730: printf ("\t} else if (cnt > 0) {\n");
4731: printf ("\t\tval >>= cnt - 1;\n");
4732: printf ("\t\tSET_CFLG (val & 1);\n");
4733: duplicate_carry (1);
4734: printf ("\t\tval >>= 1;\n");
4735: printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n",
4736: bit_mask (curi->size),
4737: bit_size (curi->size));
4738: printf ("\t\tval &= %s;\n", bit_mask (curi->size));
4739: printf ("\t}\n");
4740: genflags (flag_logical_noclobber, curi->size, "val", "", "");
4741: shift_ce (curi->dmode, curi->size);
4742: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
4743: break;
4744: case i_ASL:
1.1.1.7 root 4745: genamodedual (curi,
4746: curi->smode, "srcreg", curi->size, "cnt", 1, 0,
4747: curi->dmode, "dstreg", curi->size, "data", 1, GF_RMW);
4748: //genamode (curi, curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
4749: //genamode (curi, curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 4750: fill_prefetch_next();
4751: start_brace ();
4752: switch (curi->size) {
4753: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
4754: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
4755: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 4756: default: term ();
1.1.1.4 root 4757: }
4758: printf ("\tint ccnt = cnt & 63;\n");
4759: printf ("\tcnt &= 63;\n");
4760: printf ("\tCLEAR_CZNV ();\n");
4761: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
4762: printf ("\t\tSET_VFLG (val != 0);\n");
4763: printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
4764: bit_size (curi->size));
4765: duplicate_carry (1);
4766: printf ("\t\tval = 0;\n");
4767: if (source_is_imm1_8 (curi))
4768: printf ("\t} else {\n");
4769: else
4770: printf ("\t} else if (cnt > 0) {\n");
4771: printf ("\t\tuae_u32 mask = (%s << (%d - cnt)) & %s;\n",
4772: bit_mask (curi->size),
4773: bit_size (curi->size) - 1,
4774: bit_mask (curi->size));
4775: printf ("\t\tSET_VFLG ((val & mask) != mask && (val & mask) != 0);\n");
4776: printf ("\t\tval <<= cnt - 1;\n");
4777: printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
4778: duplicate_carry (1);
4779: printf ("\t\tval <<= 1;\n");
4780: printf ("\t\tval &= %s;\n", bit_mask (curi->size));
4781: printf ("\t}\n");
4782: genflags (flag_logical_noclobber, curi->size, "val", "", "");
4783: shift_ce (curi->dmode, curi->size);
4784: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
4785: break;
4786: case i_LSR:
1.1.1.7 root 4787: genamodedual (curi,
4788: curi->smode, "srcreg", curi->size, "cnt", 1, 0,
4789: curi->dmode, "dstreg", curi->size, "data", 1, GF_RMW);
4790: //genamode (curi, curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
4791: //genamode (curi, curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 4792: fill_prefetch_next();
4793: start_brace ();
4794: switch (curi->size) {
4795: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
4796: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
4797: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 4798: default: term ();
1.1.1.4 root 4799: }
4800: printf ("\tint ccnt = cnt & 63;\n");
4801: printf ("\tcnt &= 63;\n");
4802: printf ("\tCLEAR_CZNV ();\n");
4803: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
4804: printf ("\t\tSET_CFLG ((cnt == %d) & (val >> %d));\n",
4805: bit_size (curi->size), bit_size (curi->size) - 1);
4806: duplicate_carry (1);
4807: printf ("\t\tval = 0;\n");
4808: if (source_is_imm1_8 (curi))
4809: printf ("\t} else {\n");
1.1.1.7 root 4810: else
1.1.1.4 root 4811: printf ("\t} else if (cnt > 0) {\n");
4812: printf ("\t\tval >>= cnt - 1;\n");
4813: printf ("\t\tSET_CFLG (val & 1);\n");
4814: duplicate_carry (1);
4815: printf ("\t\tval >>= 1;\n");
4816: printf ("\t}\n");
4817: genflags (flag_logical_noclobber, curi->size, "val", "", "");
4818: shift_ce (curi->dmode, curi->size);
4819: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
4820: break;
4821: case i_LSL:
1.1.1.7 root 4822: genamodedual (curi,
4823: curi->smode, "srcreg", curi->size, "cnt", 1, 0,
4824: curi->dmode, "dstreg", curi->size, "data", 1, GF_RMW);
4825: //genamode (curi, curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
4826: //genamode (curi, curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 4827: fill_prefetch_next();
4828: start_brace ();
4829: switch (curi->size) {
4830: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
4831: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
4832: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 4833: default: term ();
1.1.1.4 root 4834: }
4835: printf ("\tint ccnt = cnt & 63;\n");
4836: printf ("\tcnt &= 63;\n");
4837: printf ("\tCLEAR_CZNV ();\n");
4838: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
4839: printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n", bit_size (curi->size));
4840: duplicate_carry (1);
4841: printf ("\t\tval = 0;\n");
4842: if (source_is_imm1_8 (curi))
4843: printf ("\t} else {\n");
1.1.1.7 root 4844: else
1.1.1.4 root 4845: printf ("\t} else if (cnt > 0) {\n");
4846: printf ("\t\tval <<= (cnt - 1);\n");
4847: printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
4848: duplicate_carry (1);
4849: printf ("\t\tval <<= 1;\n");
4850: printf ("\tval &= %s;\n", bit_mask (curi->size));
4851: printf ("\t}\n");
4852: genflags (flag_logical_noclobber, curi->size, "val", "", "");
4853: shift_ce (curi->dmode, curi->size);
4854: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
4855: break;
4856: case i_ROL:
1.1.1.7 root 4857: genamodedual (curi,
4858: curi->smode, "srcreg", curi->size, "cnt", 1, 0,
4859: curi->dmode, "dstreg", curi->size, "data", 1, GF_RMW);
4860: //genamode (curi, curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
4861: //genamode (curi, curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 4862: fill_prefetch_next ();
4863: start_brace ();
4864: switch (curi->size) {
4865: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
4866: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
4867: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 4868: default: term ();
1.1.1.4 root 4869: }
4870: printf ("\tint ccnt = cnt & 63;\n");
4871: printf ("\tcnt &= 63;\n");
4872: printf ("\tCLEAR_CZNV ();\n");
4873: if (source_is_imm1_8 (curi))
4874: printf ("{");
4875: else
4876: printf ("\tif (cnt > 0) {\n");
4877: printf ("\tuae_u32 loval;\n");
4878: printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
4879: printf ("\tloval = val >> (%d - cnt);\n", bit_size (curi->size));
4880: printf ("\tval <<= cnt;\n");
4881: printf ("\tval |= loval;\n");
4882: printf ("\tval &= %s;\n", bit_mask (curi->size));
4883: printf ("\tSET_CFLG (val & 1);\n");
4884: printf ("}\n");
4885: genflags (flag_logical_noclobber, curi->size, "val", "", "");
4886: shift_ce (curi->dmode, curi->size);
4887: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
4888: break;
4889: case i_ROR:
1.1.1.7 root 4890: genamodedual (curi,
4891: curi->smode, "srcreg", curi->size, "cnt", 1, 0,
4892: curi->dmode, "dstreg", curi->size, "data", 1, GF_RMW);
4893: //genamode (curi, curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
4894: //genamode (curi, curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 4895: fill_prefetch_next ();
4896: start_brace ();
4897: switch (curi->size) {
4898: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
4899: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
4900: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 4901: default: term ();
1.1.1.4 root 4902: }
4903: printf ("\tint ccnt = cnt & 63;\n");
4904: printf ("\tcnt &= 63;\n");
4905: printf ("\tCLEAR_CZNV ();\n");
4906: if (source_is_imm1_8 (curi))
4907: printf ("{");
4908: else
4909: printf ("\tif (cnt > 0) {");
4910: printf ("\tuae_u32 hival;\n");
4911: printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
4912: printf ("\thival = val << (%d - cnt);\n", bit_size (curi->size));
4913: printf ("\tval >>= cnt;\n");
4914: printf ("\tval |= hival;\n");
4915: printf ("\tval &= %s;\n", bit_mask (curi->size));
4916: printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
4917: printf ("\t}\n");
4918: genflags (flag_logical_noclobber, curi->size, "val", "", "");
4919: shift_ce (curi->dmode, curi->size);
4920: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
4921: break;
4922: case i_ROXL:
1.1.1.7 root 4923: genamodedual (curi,
4924: curi->smode, "srcreg", curi->size, "cnt", 1, 0,
4925: curi->dmode, "dstreg", curi->size, "data", 1, GF_RMW);
4926: //genamode (curi, curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
4927: //genamode (curi, curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 4928: fill_prefetch_next ();
4929: start_brace ();
4930: switch (curi->size) {
4931: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
4932: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
4933: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 4934: default: term ();
1.1.1.4 root 4935: }
4936: printf ("\tint ccnt = cnt & 63;\n");
4937: printf ("\tcnt &= 63;\n");
4938: printf ("\tCLEAR_CZNV ();\n");
4939: if (source_is_imm1_8 (curi))
4940: printf ("{");
4941: else {
4942: force_range_for_rox ("cnt", curi->size);
4943: printf ("\tif (cnt > 0) {\n");
4944: }
4945: printf ("\tcnt--;\n");
4946: printf ("\t{\n\tuae_u32 carry;\n");
4947: printf ("\tuae_u32 loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1);
4948: printf ("\tcarry = loval & 1;\n");
4949: printf ("\tval = (((val << 1) | GET_XFLG ()) << cnt) | (loval >> 1);\n");
4950: printf ("\tSET_XFLG (carry);\n");
4951: printf ("\tval &= %s;\n", bit_mask (curi->size));
4952: printf ("\t} }\n");
4953: printf ("\tSET_CFLG (GET_XFLG ());\n");
4954: genflags (flag_logical_noclobber, curi->size, "val", "", "");
4955: shift_ce (curi->dmode, curi->size);
4956: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
4957: break;
4958: case i_ROXR:
1.1.1.7 root 4959: genamodedual (curi,
4960: curi->smode, "srcreg", curi->size, "cnt", 1, 0,
4961: curi->dmode, "dstreg", curi->size, "data", 1, GF_RMW);
4962: //genamode (curi, curi->smode, "srcreg", curi->size, "cnt", 1, 0, 0);
4963: //genamode (curi, curi->dmode, "dstreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 4964: fill_prefetch_next ();
4965: start_brace ();
4966: switch (curi->size) {
4967: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
4968: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
4969: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 4970: default: term ();
1.1.1.4 root 4971: }
4972: printf ("\tint ccnt = cnt & 63;\n");
4973: printf ("\tcnt &= 63;\n");
4974: printf ("\tCLEAR_CZNV ();\n");
4975: if (source_is_imm1_8 (curi))
4976: printf ("{");
4977: else {
4978: force_range_for_rox ("cnt", curi->size);
4979: printf ("\tif (cnt > 0) {\n");
4980: }
4981: printf ("\tcnt--;\n");
4982: printf ("\t{\n\tuae_u32 carry;\n");
4983: printf ("\tuae_u32 hival = (val << 1) | GET_XFLG ();\n");
4984: printf ("\thival <<= (%d - cnt);\n", bit_size (curi->size) - 1);
4985: printf ("\tval >>= cnt;\n");
4986: printf ("\tcarry = val & 1;\n");
4987: printf ("\tval >>= 1;\n");
4988: printf ("\tval |= hival;\n");
4989: printf ("\tSET_XFLG (carry);\n");
4990: printf ("\tval &= %s;\n", bit_mask (curi->size));
4991: printf ("\t} }\n");
4992: printf ("\tSET_CFLG (GET_XFLG ());\n");
4993: genflags (flag_logical_noclobber, curi->size, "val", "", "");
4994: shift_ce (curi->dmode, curi->size);
4995: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
4996: break;
4997: case i_ASRW:
1.1.1.7 root 4998: genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 4999: fill_prefetch_next ();
5000: start_brace ();
5001: switch (curi->size) {
5002: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
5003: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
5004: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 5005: default: term ();
1.1.1.4 root 5006: }
5007: printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
5008: printf ("\tuae_u32 cflg = val & 1;\n");
5009: printf ("\tval = (val >> 1) | sign;\n");
5010: genflags (flag_logical, curi->size, "val", "", "");
5011: printf ("\tSET_CFLG (cflg);\n");
5012: duplicate_carry (0);
5013: genastore ("val", curi->smode, "srcreg", curi->size, "data");
5014: break;
5015: case i_ASLW:
1.1.1.7 root 5016: genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 5017: fill_prefetch_next ();
5018: start_brace ();
5019: switch (curi->size) {
5020: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
5021: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
5022: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 5023: default: term ();
1.1.1.4 root 5024: }
5025: printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
5026: printf ("\tuae_u32 sign2;\n");
5027: printf ("\tval <<= 1;\n");
5028: genflags (flag_logical, curi->size, "val", "", "");
5029: printf ("\tsign2 = %s & val;\n", cmask (curi->size));
5030: printf ("\tSET_CFLG (sign != 0);\n");
5031: duplicate_carry (0);
5032: printf ("\tSET_VFLG (GET_VFLG () | (sign2 != sign));\n");
5033: genastore ("val", curi->smode, "srcreg", curi->size, "data");
5034: break;
5035: case i_LSRW:
1.1.1.7 root 5036: genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 5037: fill_prefetch_next ();
5038: start_brace ();
5039: switch (curi->size) {
5040: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
5041: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
5042: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 5043: default: term ();
1.1.1.4 root 5044: }
5045: printf ("\tuae_u32 carry = val & 1;\n");
5046: printf ("\tval >>= 1;\n");
5047: genflags (flag_logical, curi->size, "val", "", "");
5048: printf ("\tSET_CFLG (carry);\n");
5049: duplicate_carry (0);
5050: genastore ("val", curi->smode, "srcreg", curi->size, "data");
5051: break;
5052: case i_LSLW:
1.1.1.7 root 5053: genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 5054: fill_prefetch_next ();
5055: start_brace ();
5056: switch (curi->size) {
5057: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
5058: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
5059: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 5060: default: term ();
1.1.1.4 root 5061: }
5062: printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
5063: printf ("\tval <<= 1;\n");
5064: genflags (flag_logical, curi->size, "val", "", "");
5065: printf ("\tSET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
5066: duplicate_carry (0);
5067: genastore ("val", curi->smode, "srcreg", curi->size, "data");
5068: break;
5069: case i_ROLW:
1.1.1.7 root 5070: genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 5071: fill_prefetch_next ();
5072: start_brace ();
5073: switch (curi->size) {
5074: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
5075: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
5076: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 5077: default: term ();
1.1.1.4 root 5078: }
5079: printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
5080: printf ("\tval <<= 1;\n");
5081: printf ("\tif (carry) val |= 1;\n");
5082: genflags (flag_logical, curi->size, "val", "", "");
5083: printf ("\tSET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
5084: genastore ("val", curi->smode, "srcreg", curi->size, "data");
5085: break;
5086: case i_RORW:
1.1.1.7 root 5087: genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 5088: fill_prefetch_next ();
5089: start_brace ();
5090: switch (curi->size) {
5091: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
5092: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
5093: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 5094: default: term ();
1.1.1.4 root 5095: }
5096: printf ("\tuae_u32 carry = val & 1;\n");
5097: printf ("\tval >>= 1;\n");
5098: printf ("\tif (carry) val |= %s;\n", cmask (curi->size));
5099: genflags (flag_logical, curi->size, "val", "", "");
5100: printf ("\tSET_CFLG (carry);\n");
5101: genastore ("val", curi->smode, "srcreg", curi->size, "data");
5102: break;
5103: case i_ROXLW:
1.1.1.7 root 5104: genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 5105: fill_prefetch_next ();
5106: start_brace ();
5107: switch (curi->size) {
5108: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
5109: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
5110: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 5111: default: term ();
1.1.1.4 root 5112: }
5113: printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
5114: printf ("\tval <<= 1;\n");
5115: printf ("\tif (GET_XFLG ()) val |= 1;\n");
5116: genflags (flag_logical, curi->size, "val", "", "");
5117: printf ("\tSET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
5118: duplicate_carry (0);
5119: genastore ("val", curi->smode, "srcreg", curi->size, "data");
5120: break;
5121: case i_ROXRW:
1.1.1.7 root 5122: genamode (curi, curi->smode, "srcreg", curi->size, "data", 1, 0, GF_RMW);
1.1.1.4 root 5123: fill_prefetch_next ();
5124: start_brace ();
5125: switch (curi->size) {
5126: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
5127: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
5128: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1.1.1.7 root 5129: default: term ();
1.1.1.4 root 5130: }
5131: printf ("\tuae_u32 carry = val & 1;\n");
5132: printf ("\tval >>= 1;\n");
5133: printf ("\tif (GET_XFLG ()) val |= %s;\n", cmask (curi->size));
5134: genflags (flag_logical, curi->size, "val", "", "");
5135: printf ("\tSET_CFLG (carry);\n");
5136: duplicate_carry (0);
5137: genastore ("val", curi->smode, "srcreg", curi->size, "data");
5138: break;
5139: case i_MOVEC2:
1.1.1.7 root 5140: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.4 root 5141: fill_prefetch_next ();
5142: start_brace ();
5143: printf ("\tint regno = (src >> 12) & 15;\n");
5144: printf ("\tuae_u32 *regp = regs.regs + regno;\n");
5145: printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
5146: break;
5147: case i_MOVE2C:
1.1.1.7 root 5148: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
1.1.1.4 root 5149: fill_prefetch_next ();
5150: start_brace ();
5151: printf ("\tint regno = (src >> 12) & 15;\n");
5152: printf ("\tuae_u32 *regp = regs.regs + regno;\n");
5153: printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
5154: break;
5155: case i_CAS:
5156: {
5157: int old_brace_level;
1.1.1.7 root 5158: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_LRMW);
5159: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_LRMW);
5160: if (cpu_level == 5 && curi->size > 0) {
5161: printf ("\tif ((dsta & %d) && currprefs.int_no_unimplemented && get_cpu_model () == 68060) {\n", curi->size == 1 ? 1 : 3);
5162: if (curi->dmode == Aipi || curi->dmode == Apdi)
5163: printf ("\t\tm68k_areg (regs, dstreg) %c= %d;\n", curi->dmode == Aipi ? '-' : '+', 1 << curi->size);
5164: sync_m68k_pc_noreset ();
5165: printf ("\t\top_unimpl (opcode);\n");
5166: printf ("\t\tgoto %s;\n", endlabelstr);
5167: printf ("\t}\n");
5168: need_endlabel = 1;
5169: }
1.1.1.4 root 5170: fill_prefetch_0 ();
5171: start_brace ();
5172: printf ("\tint ru = (src >> 6) & 7;\n");
5173: printf ("\tint rc = src & 7;\n");
5174: genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, rc)", "dst");
1.1.1.10! root 5175: gen_set_fault_pc (false);
1.1.1.7 root 5176: printf ("\tif (GET_ZFLG ()) ");
1.1.1.4 root 5177: old_brace_level = n_braces;
5178: start_brace ();
1.1.1.7 root 5179: printf ("\n\t");
5180: genastore_cas ("(m68k_dreg (regs, ru))", curi->dmode, "dstreg", curi->size, "dst");
5181: printf ("\t");
1.1.1.4 root 5182: pop_braces (old_brace_level);
5183: printf ("else");
5184: start_brace ();
1.1.1.7 root 5185: printf ("\n");
5186: get_prefetch_020 ();
5187: if (cpu_level >= 4) {
5188: // apparently 68040/060 needs to always write at the end of RMW cycle
5189: printf ("\t");
5190: genastore_cas ("dst", curi->dmode, "dstreg", curi->size, "dst");
5191: }
5192: switch (curi->size) {
5193: case sz_byte:
5194: printf ("\t\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xff) | (dst & 0xff);\n");
5195: break;
5196: case sz_word:
5197: printf ("\t\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xffff) | (dst & 0xffff);\n");
5198: break;
5199: default:
5200: printf ("\t\tm68k_dreg(regs, rc) = dst;\n");
5201: break;
5202: }
1.1.1.4 root 5203: pop_braces (old_brace_level);
5204: }
5205: break;
5206: case i_CAS2:
1.1.1.7 root 5207: genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, GF_LRMW);
1.1.1.4 root 5208: printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n");
5209: printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n");
5210: if (curi->size == sz_word) {
5211: int old_brace_level = n_braces;
1.1.1.7 root 5212: printf ("\tuae_u16 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcwlrmw, srcwlrmw);
1.1.1.4 root 5213: genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1");
5214: printf ("\tif (GET_ZFLG ()) {\n");
5215: genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2");
5216: printf ("\tif (GET_ZFLG ()) {\n");
1.1.1.7 root 5217: printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstwlrmw);
5218: printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstwlrmw);
1.1.1.4 root 5219: printf ("\t}}\n");
5220: pop_braces (old_brace_level);
5221: printf ("\tif (! GET_ZFLG ()) {\n");
1.1.1.8 root 5222: printf ("\tm68k_dreg (regs, (extra >> 0) & 7) = (m68k_dreg (regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n");
5223: printf ("\tm68k_dreg (regs, (extra >> 16) & 7) = (m68k_dreg (regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n");
1.1.1.4 root 5224: printf ("\t}\n");
5225: } else {
5226: int old_brace_level = n_braces;
1.1.1.7 root 5227: printf ("\tuae_u32 dst1 = %s (rn1), dst2 = %s (rn2);\n", srcllrmw, srcllrmw);
1.1.1.4 root 5228: genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, (extra >> 16) & 7)", "dst1");
5229: printf ("\tif (GET_ZFLG ()) {\n");
5230: genflags (flag_cmp, curi->size, "newv", "m68k_dreg (regs, extra & 7)", "dst2");
5231: printf ("\tif (GET_ZFLG ()) {\n");
1.1.1.7 root 5232: printf ("\t%s (rn1, m68k_dreg (regs, (extra >> 22) & 7));\n", dstllrmw);
5233: printf ("\t%s (rn2, m68k_dreg (regs, (extra >> 6) & 7));\n", dstllrmw);
1.1.1.4 root 5234: printf ("\t}}\n");
5235: pop_braces (old_brace_level);
5236: printf ("\tif (! GET_ZFLG ()) {\n");
1.1.1.8 root 5237: printf ("\tm68k_dreg (regs, (extra >> 0) & 7) = dst2;\n");
5238: printf ("\tm68k_dreg (regs, (extra >> 16) & 7) = dst1;\n");
1.1.1.4 root 5239: printf ("\t}\n");
5240: }
5241: break;
5242: case i_MOVES: /* ignore DFC and SFC when using_mmu == false */
5243: {
5244: int old_brace_level;
1.1.1.7 root 5245: tail_ce020_done = true;
5246: genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
1.1.1.4 root 5247: printf ("\tif (extra & 0x800)\n");
5248: {
5249: int old_m68k_pc_offset = m68k_pc_offset;
5250: old_brace_level = n_braces;
5251: start_brace ();
5252: printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
1.1.1.7 root 5253: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 2, 0, 0);
1.1.1.10! root 5254: tail_ce020_done = false;
! 5255: returntail(false);
! 5256: did_prefetch = 0;
1.1.1.4 root 5257: genastore_fc ("src", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.10! root 5258: sync_m68k_pc();
! 5259: pop_braces(old_brace_level);
1.1.1.4 root 5260: m68k_pc_offset = old_m68k_pc_offset;
5261: }
5262: printf ("else");
5263: {
5264: start_brace ();
1.1.1.7 root 5265: genamode (curi, curi->dmode, "dstreg", curi->size, "src", 1, 0, GF_FC);
1.1.1.4 root 5266: printf ("\tif (extra & 0x8000) {\n");
5267: switch (curi->size) {
5268: case sz_byte: printf ("\tm68k_areg (regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break;
5269: case sz_word: printf ("\tm68k_areg (regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break;
5270: case sz_long: printf ("\tm68k_areg (regs, (extra >> 12) & 7) = src;\n"); break;
1.1.1.7 root 5271: default: term ();
1.1.1.4 root 5272: }
5273: printf ("\t} else {\n");
5274: genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "");
5275: printf ("\t}\n");
1.1.1.10! root 5276: sync_m68k_pc();
! 5277: tail_ce020_done = false;
! 5278: returntail(false);
1.1.1.4 root 5279: pop_braces (old_brace_level);
5280: }
5281: }
5282: break;
5283: case i_BKPT: /* only needed for hardware emulators */
5284: sync_m68k_pc ();
5285: printf ("\top_illg (opcode);\n");
1.1.1.8 root 5286: did_prefetch = -1;
1.1.1.4 root 5287: break;
5288: case i_CALLM: /* not present in 68030 */
5289: sync_m68k_pc ();
5290: printf ("\top_illg (opcode);\n");
1.1.1.8 root 5291: did_prefetch = -1;
1.1.1.4 root 5292: break;
5293: case i_RTM: /* not present in 68030 */
5294: sync_m68k_pc ();
5295: printf ("\top_illg (opcode);\n");
1.1.1.8 root 5296: did_prefetch = -1;
1.1.1.4 root 5297: break;
5298: case i_TRAPcc:
5299: if (curi->smode != am_unknown && curi->smode != am_illg)
1.1.1.7 root 5300: genamode (curi, curi->smode, "srcreg", curi->size, "dummy", 1, 0, 0);
1.1.1.4 root 5301: fill_prefetch_0 ();
1.1.1.9 root 5302: printf ("\tif (cctrue (%d)) { Exception_cpu(7); goto %s; }\n", curi->cc, endlabelstr);
1.1.1.4 root 5303: need_endlabel = 1;
5304: break;
5305: case i_DIVL:
1.1.1.7 root 5306: genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
5307: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
1.1.1.4 root 5308: sync_m68k_pc ();
1.1.1.7 root 5309: printf ("\tif (!m68k_divl(opcode, dst, extra)) goto %s;\n", endlabelstr);
5310: need_endlabel = 1;
1.1.1.4 root 5311: break;
5312: case i_MULL:
1.1.1.7 root 5313: genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
5314: genamode (curi, curi->dmode, "dstreg", curi->size, "dst", 1, 0, 0);
1.1.1.4 root 5315: sync_m68k_pc ();
1.1.1.7 root 5316: printf ("\tif (!m68k_mull(opcode, dst, extra)) goto %s;\n", endlabelstr);
5317: need_endlabel = 1;
1.1.1.4 root 5318: break;
5319: case i_BFTST:
5320: case i_BFEXTU:
5321: case i_BFCHG:
5322: case i_BFEXTS:
5323: case i_BFCLR:
5324: case i_BFFFO:
5325: case i_BFSET:
5326: case i_BFINS:
5327: {
5328: const char *getb, *putb;
5329:
1.1.1.7 root 5330: if (using_mmu == 68060 && (curi->mnemo == i_BFCHG || curi->mnemo == i_BFCLR || curi->mnemo == i_BFSET || curi->mnemo == i_BFINS)) {
5331: getb = "mmu060_get_rmw_bitfield";
5332: putb = "mmu060_put_rmw_bitfield";
1.1.1.8 root 5333: } else if (using_mmu || using_ce020 || using_indirect > 0) {
1.1.1.4 root 5334: getb = "x_get_bitfield";
5335: putb = "x_put_bitfield";
5336: } else {
5337: getb = "get_bitfield";
5338: putb = "put_bitfield";
5339: }
5340:
1.1.1.7 root 5341: genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
5342: genamode (curi, curi->dmode, "dstreg", sz_long, "dst", 2, 0, 0);
1.1.1.4 root 5343: start_brace ();
5344: printf ("\tuae_u32 bdata[2];\n");
5345: printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n");
5346: printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n");
1.1.1.8 root 5347: if (curi->mnemo == i_BFFFO)
5348: printf("\tuae_u32 offset2 = offset;\n");
1.1.1.4 root 5349: if (curi->dmode == Dreg) {
5350: printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg);\n");
5351: printf ("\toffset &= 0x1f;\n");
5352: printf ("\ttmp = (tmp << offset) | (tmp >> (32 - offset));\n");
5353: printf ("\tbdata[0] = tmp & ((1 << (32 - width)) - 1);\n");
5354: } else {
5355: printf ("\tuae_u32 tmp;\n");
5356: printf ("\tdsta += offset >> 3;\n");
5357: printf ("\ttmp = %s (dsta, bdata, offset, width);\n", getb);
5358: }
5359: printf ("\tSET_NFLG_ALWAYS (((uae_s32)tmp) < 0 ? 1 : 0);\n");
5360: if (curi->mnemo == i_BFEXTS)
5361: printf ("\ttmp = (uae_s32)tmp >> (32 - width);\n");
5362: else
5363: printf ("\ttmp >>= (32 - width);\n");
5364: printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n");
5365: switch (curi->mnemo) {
5366: case i_BFTST:
5367: break;
5368: case i_BFEXTU:
5369: case i_BFEXTS:
5370: printf ("\tm68k_dreg (regs, (extra >> 12) & 7) = tmp;\n");
5371: break;
5372: case i_BFCHG:
5373: printf ("\ttmp = tmp ^ (0xffffffffu >> (32 - width));\n");
5374: break;
5375: case i_BFCLR:
5376: printf ("\ttmp = 0;\n");
5377: break;
5378: case i_BFFFO:
5379: printf ("\t{ uae_u32 mask = 1 << (width - 1);\n");
1.1.1.8 root 5380: printf ("\twhile (mask) { if (tmp & mask) break; mask >>= 1; offset2++; }}\n");
5381: printf ("\tm68k_dreg (regs, (extra >> 12) & 7) = offset2;\n");
1.1.1.4 root 5382: break;
5383: case i_BFSET:
5384: printf ("\ttmp = 0xffffffffu >> (32 - width);\n");
5385: break;
5386: case i_BFINS:
5387: printf ("\ttmp = m68k_dreg (regs, (extra >> 12) & 7);\n");
5388: printf ("\ttmp = tmp & (0xffffffffu >> (32 - width));\n");
5389: printf ("\tSET_NFLG (tmp & (1 << (width - 1)) ? 1 : 0);\n");
5390: printf ("\tSET_ZFLG (tmp == 0);\n");
5391: break;
5392: default:
5393: break;
5394: }
5395: if (curi->mnemo == i_BFCHG
5396: || curi->mnemo == i_BFCLR
5397: || curi->mnemo == i_BFSET
5398: || curi->mnemo == i_BFINS) {
5399: if (curi->dmode == Dreg) {
5400: printf ("\ttmp = bdata[0] | (tmp << (32 - width));\n");
5401: printf ("\tm68k_dreg(regs, dstreg) = (tmp >> offset) | (tmp << (32 - offset));\n");
5402: } else {
5403: printf ("\t%s(dsta, bdata, tmp, offset, width);\n", putb);
5404: }
5405: }
5406: }
5407: break;
5408: case i_PACK:
5409: if (curi->smode == Dreg) {
5410: printf ("\tuae_u16 val = m68k_dreg (regs, srcreg) + %s;\n", gen_nextiword (0));
5411: printf ("\tm68k_dreg (regs, dstreg) = (m68k_dreg (regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n");
5412: } else {
5413: printf ("\tuae_u16 val;\n");
1.1.1.7 root 5414: addmmufixup ("srcreg");
1.1.1.4 root 5415: printf ("\tm68k_areg (regs, srcreg) -= areg_byteinc[srcreg];\n");
1.1.1.7 root 5416: printf ("\tval = (uae_u16)(%s (m68k_areg (regs, srcreg)) & 0xff);\n", srcb);
1.1.1.4 root 5417: printf ("\tm68k_areg (regs, srcreg) -= areg_byteinc[srcreg];\n");
1.1.1.10! root 5418: printf ("\tval = val | ((uae_u16)(%s (m68k_areg (regs, srcreg)) & 0xff) << 8);\n", srcb);
! 5419: printf ("\tval += %s;\n", gen_nextiword(0));
1.1.1.7 root 5420: addmmufixup ("dstreg");
1.1.1.4 root 5421: printf ("\tm68k_areg (regs, dstreg) -= areg_byteinc[dstreg];\n");
1.1.1.10! root 5422: gen_set_fault_pc (false);
1.1.1.4 root 5423: printf ("\t%s (m68k_areg (regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n", dstb);
5424: }
5425: break;
5426: case i_UNPK:
5427: if (curi->smode == Dreg) {
5428: printf ("\tuae_u16 val = m68k_dreg (regs, srcreg);\n");
1.1.1.10! root 5429: printf ("\tval = val | ((uae_u16)(%s (m68k_areg (regs, srcreg)) & 0xff) << 8);\n", srcb);
! 5430: printf ("\tval += %s;\n", gen_nextiword(0));
1.1.1.4 root 5431: printf ("\tm68k_dreg (regs, dstreg) = (m68k_dreg (regs, dstreg) & 0xffff0000) | (val & 0xffff);\n");
5432: } else {
5433: printf ("\tuae_u16 val;\n");
1.1.1.7 root 5434: addmmufixup ("srcreg");
1.1.1.4 root 5435: printf ("\tm68k_areg (regs, srcreg) -= areg_byteinc[srcreg];\n");
1.1.1.7 root 5436: printf ("\tval = (uae_u16)(%s (m68k_areg (regs, srcreg)) & 0xff);\n", srcb);
1.1.1.4 root 5437: printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword (0));
1.1.1.7 root 5438: addmmufixup ("dstreg");
1.1.1.4 root 5439: if (cpu_level >= 2) {
5440: printf ("\tm68k_areg (regs, dstreg) -= 2 * areg_byteinc[dstreg];\n");
5441: printf ("\t%s (m68k_areg (regs, dstreg) + areg_byteinc[dstreg], val);\n", dstb);
5442: printf ("\t%s (m68k_areg (regs, dstreg), val >> 8);\n", dstb);
5443: } else {
5444: printf ("\tm68k_areg (regs, dstreg) -= areg_byteinc[dstreg];\n");
5445: printf ("\t%s (m68k_areg (regs, dstreg),val);\n", dstb);
5446: printf ("\tm68k_areg (regs, dstreg) -= areg_byteinc[dstreg];\n");
1.1.1.10! root 5447: gen_set_fault_pc (false);
1.1.1.4 root 5448: printf ("\t%s (m68k_areg (regs, dstreg),val >> 8);\n", dstb);
5449: }
5450: }
5451: break;
5452: case i_TAS:
1.1.1.7 root 5453: genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, GF_LRMW);
1.1.1.4 root 5454: genflags (flag_logical, curi->size, "src", "", "");
5455: if (!isreg (curi->smode))
5456: addcycles000 (2);
5457: fill_prefetch_next ();
5458: printf ("\tsrc |= 0x80;\n");
5459: if (cpu_level >= 2 || curi->smode == Dreg || !using_ce) {
5460: if (next_cpu_level < 2)
5461: next_cpu_level = 2 - 1;
1.1.1.7 root 5462: genastore_tas ("src", curi->smode, "srcreg", curi->size, "src");
1.1.1.4 root 5463: } else {
5464: printf ("\tif (!is_cycle_ce ()) {\n");
5465: genastore ("src", curi->smode, "srcreg", curi->size, "src");
5466: printf ("\t} else {\n");
1.1.1.7 root 5467: printf ("\t\t%s (4);\n", do_cycles);
5468: addcycles000_nonce("\t\t", 4);
1.1.1.4 root 5469: printf ("\t}\n");
5470: }
5471: break;
5472: case i_FPP:
5473: fpulimit();
1.1.1.7 root 5474: genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
1.1.1.4 root 5475: sync_m68k_pc ();
5476: printf ("\tfpuop_arithmetic(opcode, extra);\n");
1.1.1.7 root 5477: if (using_prefetch || using_prefetch_020) {
5478: printf ("\tif (regs.fp_exception) goto %s;\n", endlabelstr);
5479: need_endlabel = 1;
5480: }
1.1.1.4 root 5481: break;
5482: case i_FDBcc:
5483: fpulimit();
1.1.1.7 root 5484: genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
1.1.1.4 root 5485: sync_m68k_pc ();
5486: printf ("\tfpuop_dbcc (opcode, extra);\n");
1.1.1.7 root 5487: if (using_prefetch || using_prefetch_020) {
5488: printf ("\tif (regs.fp_exception) goto %s;\n", endlabelstr);
5489: printf ("\tif (regs.fp_branch) {\n");
5490: printf ("\t\tregs.fp_branch = false;\n");
5491: printf ("\t\tfill_prefetch();\n");
5492: printf ("\t\tgoto %s;\n", endlabelstr);
5493: printf ("\t}\n");
5494: need_endlabel = 1;
1.1.1.9 root 5495: } else {
5496: printf ("\tif (regs.fp_branch) {\n");
5497: printf ("\t\tregs.fp_branch = false;\n");
5498: printf ("\t\tif(regs.t0) check_t0_trace();\n");
5499: printf ("\t}\n");
1.1.1.7 root 5500: }
1.1.1.4 root 5501: break;
5502: case i_FScc:
5503: fpulimit();
1.1.1.7 root 5504: genamode (curi, curi->smode, "srcreg", curi->size, "extra", 1, 0, 0);
1.1.1.4 root 5505: sync_m68k_pc ();
5506: printf ("\tfpuop_scc (opcode, extra);\n");
1.1.1.7 root 5507: if (using_prefetch || using_prefetch_020) {
5508: printf ("\tif (regs.fp_exception) goto %s;\n", endlabelstr);
5509: need_endlabel = 1;
5510: }
1.1.1.4 root 5511: break;
5512: case i_FTRAPcc:
5513: fpulimit();
1.1.1.7 root 5514: printf ("\tuaecptr oldpc = %s;\n", getpc);
1.1.1.4 root 5515: printf ("\tuae_u16 extra = %s;\n", gen_nextiword (0));
5516: if (curi->smode != am_unknown && curi->smode != am_illg)
1.1.1.7 root 5517: genamode (curi, curi->smode, "srcreg", curi->size, "dummy", 1, 0, 0);
1.1.1.4 root 5518: sync_m68k_pc ();
5519: printf ("\tfpuop_trapcc (opcode, oldpc, extra);\n");
1.1.1.7 root 5520: if (using_prefetch || using_prefetch_020) {
5521: printf ("\tif (regs.fp_exception) goto %s;\n", endlabelstr);
5522: need_endlabel = 1;
5523: }
1.1.1.4 root 5524: break;
5525: case i_FBcc:
5526: fpulimit();
5527: sync_m68k_pc ();
5528: start_brace ();
1.1.1.7 root 5529: printf ("\tuaecptr pc = %s;\n", getpc);
5530: genamode (curi, curi->dmode, "srcreg", curi->size, "extra", 1, 0, 0);
1.1.1.4 root 5531: sync_m68k_pc ();
5532: printf ("\tfpuop_bcc (opcode, pc,extra);\n");
1.1.1.7 root 5533: if (using_prefetch || using_prefetch_020) {
5534: printf ("\tif (regs.fp_exception) goto %s;\n", endlabelstr);
5535: printf ("\tif (regs.fp_branch) {\n");
5536: printf ("\t\tregs.fp_branch = false;\n");
5537: printf ("\t\tfill_prefetch();\n");
5538: printf ("\t\tgoto %s;\n", endlabelstr);
5539: printf ("\t}\n");
5540: need_endlabel = 1;
1.1.1.9 root 5541: } else {
5542: printf ("\tif (regs.fp_branch) {\n");
5543: printf ("\t\tregs.fp_branch = false;\n");
5544: printf ("\t\tif(regs.t0) check_t0_trace();\n");
5545: printf ("\t}\n");
1.1.1.7 root 5546: }
1.1.1.4 root 5547: break;
5548: case i_FSAVE:
5549: fpulimit();
5550: sync_m68k_pc ();
5551: printf ("\tfpuop_save (opcode);\n");
1.1.1.7 root 5552: if (using_prefetch || using_prefetch_020) {
5553: printf ("\tif (regs.fp_exception) goto %s;\n", endlabelstr);
5554: need_endlabel = 1;
5555: }
1.1.1.4 root 5556: break;
5557: case i_FRESTORE:
5558: fpulimit();
5559: sync_m68k_pc ();
5560: printf ("\tfpuop_restore (opcode);\n");
1.1.1.7 root 5561: if (using_prefetch || using_prefetch_020) {
5562: printf ("\tif (regs.fp_exception) goto %s;\n", endlabelstr);
5563: need_endlabel = 1;
5564: }
1.1.1.4 root 5565: break;
5566:
5567: case i_CINVL:
5568: case i_CINVP:
5569: case i_CINVA:
5570: case i_CPUSHL:
5571: case i_CPUSHP:
5572: case i_CPUSHA:
1.1.1.7 root 5573: printf ("\tflush_cpu_caches_040(opcode);\n");
1.1.1.4 root 5574: if (using_mmu)
1.1.1.5 root 5575: printf ("\tflush_mmu%s(m68k_areg (regs, opcode & 3), (opcode >> 6) & 3);\n", mmu_postfix);
1.1.1.4 root 5576: printf ("\tif (opcode & 0x80)\n");
1.1.1.9 root 5577: printf ("\t\tflush_icache((opcode >> 6) & 3);\n");
1.1.1.4 root 5578: break;
5579:
5580: case i_MOVE16:
5581: {
5582: if ((opcode & 0xfff8) == 0xf620) {
5583: /* MOVE16 (Ax)+,(Ay)+ */
1.1.1.7 root 5584: printf ("\tuae_u32 v[4];\n");
1.1.1.4 root 5585: printf ("\tuaecptr mems = m68k_areg (regs, srcreg) & ~15, memd;\n");
5586: printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword (0));
5587: printf ("\tmemd = m68k_areg (regs, dstreg) & ~15;\n");
1.1.1.7 root 5588: if (using_mmu >= 68040) {
5589: printf ("\tget_move16_mmu (mems, v);\n");
5590: printf ("\tput_move16_mmu (memd, v);\n");
5591: } else {
5592: printf ("\tv[0] = %s (mems);\n", srcl);
5593: printf ("\tv[1] = %s (mems + 4);\n", srcl);
5594: printf ("\tv[2] = %s (mems + 8);\n", srcl);
5595: printf ("\tv[3] = %s (mems + 12);\n", srcl);
5596: printf ("\t%s (memd , v[0]);\n", dstl);
5597: printf ("\t%s (memd + 4, v[1]);\n", dstl);
5598: printf ("\t%s (memd + 8, v[2]);\n", dstl);
5599: printf ("\t%s (memd + 12, v[3]);\n", dstl);
5600: }
1.1.1.4 root 5601: printf ("\tif (srcreg != dstreg)\n");
5602: printf ("\t\tm68k_areg (regs, srcreg) += 16;\n");
5603: printf ("\tm68k_areg (regs, dstreg) += 16;\n");
5604: } else {
5605: /* Other variants */
1.1.1.7 root 5606: printf ("\tuae_u32 v[4];\n");
5607: genamode (curi, curi->smode, "srcreg", curi->size, "mems", 0, 2, 0);
5608: genamode (curi, curi->dmode, "dstreg", curi->size, "memd", 0, 2, 0);
5609: if (using_mmu == 68040) {
5610: printf ("\tget_move16_mmu (memsa, mmu040_move16);\n");
5611: printf ("\tput_move16_mmu (memda, mmu040_move16);\n");
5612: } else if (using_mmu == 68060) {
5613: printf ("\tget_move16_mmu (memsa, v);\n");
5614: printf ("\tput_move16_mmu (memda, v);\n");
5615: } else {
5616: printf ("\tmemsa &= ~15;\n");
5617: printf ("\tmemda &= ~15;\n");
5618: printf ("\tv[0] = %s (memsa);\n", srcl);
5619: printf ("\tv[1] = %s (memsa + 4);\n", srcl);
5620: printf ("\tv[2] = %s (memsa + 8);\n", srcl);
5621: printf ("\tv[3] = %s (memsa + 12);\n", srcl);
5622: printf ("\t%s (memda , v[0]);\n", dstl);
5623: printf ("\t%s (memda + 4, v[1]);\n", dstl);
5624: printf ("\t%s (memda + 8, v[2]);\n", dstl);
5625: printf ("\t%s (memda + 12, v[3]);\n", dstl);
5626: }
1.1.1.4 root 5627: if ((opcode & 0xfff8) == 0xf600)
5628: printf ("\tm68k_areg (regs, srcreg) += 16;\n");
5629: else if ((opcode & 0xfff8) == 0xf608)
5630: printf ("\tm68k_areg (regs, dstreg) += 16;\n");
5631: }
5632: }
5633: break;
5634:
5635: case i_PFLUSHN:
5636: case i_PFLUSH:
5637: case i_PFLUSHAN:
5638: case i_PFLUSHA:
5639: case i_PLPAR:
5640: case i_PLPAW:
5641: case i_PTESTR:
5642: case i_PTESTW:
5643: sync_m68k_pc ();
5644: printf ("\tmmu_op (opcode, 0);\n");
5645: break;
5646: case i_MMUOP030:
1.1.1.8 root 5647: printf("\tuaecptr pc = %s;\n", getpc);
5648: printf("\tuae_u16 extra = %s (2);\n", prefetch_word);
1.1.1.4 root 5649: m68k_pc_offset += 2;
1.1.1.8 root 5650: sync_m68k_pc();
1.1.1.4 root 5651: if (curi->smode == Areg || curi->smode == Dreg)
5652: printf("\tuae_u16 extraa = 0;\n");
5653: else
1.1.1.8 root 5654: genamode(curi, curi->smode, "srcreg", curi->size, "extra", 0, 0, 0);
5655: sync_m68k_pc();
1.1.1.7 root 5656: if (using_ce020 || using_prefetch_020) {
1.1.1.8 root 5657: printf("\tif (mmu_op30 (pc, opcode, extra, extraa)) goto %s;\n", endlabelstr);
1.1.1.7 root 5658: need_endlabel = 1;
5659: } else {
1.1.1.8 root 5660: printf("\tmmu_op30 (pc, opcode, extra, extraa);\n");
1.1.1.7 root 5661: }
1.1.1.4 root 5662: break;
5663: default:
1.1.1.7 root 5664: term ();
1.1.1.4 root 5665: break;
5666: }
1.1.1.8 root 5667: end:
1.1.1.7 root 5668: if (!genastore_done)
5669: returntail (0);
1.1.1.4 root 5670: finish_braces ();
5671: if (limit_braces) {
5672: printf ("\n#endif\n");
5673: n_braces = limit_braces;
5674: limit_braces = 0;
5675: finish_braces ();
5676: }
5677: if (did_prefetch >= 0)
5678: fill_prefetch_finish ();
5679: sync_m68k_pc ();
5680: did_prefetch = 0;
1.1.1.7 root 5681: ipl_fetched = 0;
1.1.1.9 root 5682: if (cpu_level >= 2 && !using_ce && !using_ce020) {
5683: int v = curi->clocks;
5684: if (v < 4)
5685: v = 4;
5686: count_cycles = insn_n_cycles = v;
5687: }
1.1.1.4 root 5688: }
5689:
1.1.1.7 root 5690: static void generate_includes (FILE * f, int id)
1.1.1.4 root 5691: {
1.1.1.8 root 5692: fprintf (f, "#include \"main.h\"\n");
1.1.1.7 root 5693: // fprintf (f, "#include \"sysconfig.h\"\n");
1.1.1.4 root 5694: fprintf (f, "#include \"sysdeps.h\"\n");
1.1.1.7 root 5695: // fprintf (f, "#include \"options.h\"\n");
1.1.1.8 root 5696: fprintf (f, "#include \"hatari-glue.h\"\n");
5697: fprintf (f, "#include \"maccess.h\"\n");
1.1.1.4 root 5698: fprintf (f, "#include \"memory.h\"\n");
5699: fprintf (f, "#include \"custom.h\"\n");
1.1.1.7 root 5700: // fprintf (f, "#include \"events.h\"\n");
1.1.1.4 root 5701: fprintf (f, "#include \"newcpu.h\"\n");
5702: fprintf (f, "#include \"cpu_prefetch.h\"\n");
5703: fprintf (f, "#include \"cputbl.h\"\n");
1.1.1.10! root 5704: fprintf (f, "#include \"debugmem.h\"\n");
1.1.1.7 root 5705: if (id == 31 || id == 33)
5706: fprintf (f, "#include \"cpummu.h\"\n");
1.1.1.9 root 5707: else if (id == 32 || id == 34 || id == 35)
1.1.1.7 root 5708: fprintf (f, "#include \"cpummu030.h\"\n");
1.1.1.4 root 5709:
5710: fprintf (f, "#define CPUFUNC(x) x##_ff\n"
5711: "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"
5712: "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"
5713: "#ifdef NOFLAGS\n"
5714: "#include \"noflags.h\"\n"
5715: "#endif\n");
5716: }
5717:
5718: static int postfix;
5719:
5720:
5721: static char *decodeEA (amodes mode, wordsizes size)
5722: {
5723: static char buffer[80];
5724:
5725: buffer[0] = 0;
5726: switch (mode){
5727: case Dreg:
5728: strcpy (buffer,"Dn");
5729: break;
5730: case Areg:
5731: strcpy (buffer,"An");
5732: break;
5733: case Aind:
5734: strcpy (buffer,"(An)");
5735: break;
5736: case Aipi:
5737: strcpy (buffer,"(An)+");
5738: break;
5739: case Apdi:
5740: strcpy (buffer,"-(An)");
5741: break;
5742: case Ad16:
5743: strcpy (buffer,"(d16,An)");
5744: break;
5745: case Ad8r:
5746: strcpy (buffer,"(d8,An,Xn)");
5747: break;
5748: case PC16:
5749: strcpy (buffer,"(d16,PC)");
5750: break;
5751: case PC8r:
5752: strcpy (buffer,"(d8,PC,Xn)");
5753: break;
5754: case absw:
5755: strcpy (buffer,"(xxx).W");
5756: break;
5757: case absl:
5758: strcpy (buffer,"(xxx).L");
5759: break;
5760: case imm:
5761: switch (size){
5762: case sz_byte:
5763: strcpy (buffer,"#<data>.B");
5764: break;
5765: case sz_word:
5766: strcpy (buffer,"#<data>.W");
5767: break;
5768: case sz_long:
5769: strcpy (buffer,"#<data>.L");
5770: break;
5771: default:
5772: break;
5773: }
5774: break;
5775: case imm0:
5776: strcpy (buffer,"#<data>.B");
5777: break;
5778: case imm1:
5779: strcpy (buffer,"#<data>.W");
5780: break;
5781: case imm2:
5782: strcpy (buffer,"#<data>.L");
5783: break;
5784: case immi:
5785: strcpy (buffer,"#<data>");
5786: break;
5787:
5788: default:
5789: break;
5790: }
5791: return buffer;
5792: }
5793:
1.1.1.7 root 5794: static const char *m68k_cc[] = {
5795: "T",
5796: "F",
5797: "HI",
5798: "LS",
5799: "CC",
5800: "CS",
5801: "NE",
5802: "EQ",
5803: "VC",
5804: "VS",
5805: "PL",
5806: "MI",
5807: "GE",
5808: "LT",
5809: "GT",
5810: "LE"
5811: };
5812:
1.1.1.4 root 5813: static char *outopcode (int opcode)
5814: {
5815: static char out[100];
5816: struct instr *ins;
5817: int i;
5818:
5819: ins = &table68k[opcode];
5820: for (i = 0; lookuptab[i].name[0]; i++) {
5821: if (ins->mnemo == lookuptab[i].mnemo)
5822: break;
5823: }
5824: {
1.1.1.7 root 5825: char *s = ua (lookuptab[i].name);
1.1.1.4 root 5826: strcpy (out, s);
1.1.1.7 root 5827: xfree (s);
1.1.1.4 root 5828: }
5829: if (ins->smode == immi)
5830: strcat (out, "Q");
5831: if (ins->size == sz_byte)
5832: strcat (out,".B");
5833: if (ins->size == sz_word)
5834: strcat (out,".W");
5835: if (ins->size == sz_long)
5836: strcat (out,".L");
5837: strcat (out," ");
5838: if (ins->suse)
5839: strcat (out, decodeEA (ins->smode, ins->size));
5840: if (ins->duse) {
5841: if (ins->suse) strcat (out,",");
5842: strcat (out, decodeEA (ins->dmode, ins->size));
5843: }
1.1.1.7 root 5844: if (ins->mnemo == i_DBcc || ins->mnemo == i_Scc || ins->mnemo == i_Bcc || ins->mnemo == i_TRAPcc) {
5845: strcat (out, " (");
5846: strcat (out, m68k_cc[table68k[opcode].cc]);
5847: strcat (out, ")");
5848: }
5849:
1.1.1.4 root 5850: return out;
5851: }
5852:
1.1.1.7 root 5853: struct cputbl_tmp
5854: {
5855: uae_s16 length;
5856: uae_s8 disp020[2];
5857: uae_u8 branch;
5858: };
5859: static struct cputbl_tmp cputbltmp[65536];
5860:
5861: static void generate_one_opcode (int rp, const char *extra)
1.1.1.4 root 5862: {
5863: int idx;
5864: uae_u16 smsk, dmsk;
1.1.1.7 root 5865: unsigned int opcode = opcode_map[rp];
1.1.1.4 root 5866: int i68000 = table68k[opcode].clev > 0;
5867:
5868: if (table68k[opcode].mnemo == i_ILLG
5869: || table68k[opcode].clev > cpu_level)
5870: return;
5871:
5872: for (idx = 0; lookuptab[idx].name[0]; idx++) {
5873: if (table68k[opcode].mnemo == lookuptab[idx].mnemo)
5874: break;
5875: }
5876:
5877: if (table68k[opcode].handler != -1)
5878: return;
5879:
5880: if (opcode_next_clev[rp] != cpu_level) {
1.1.1.7 root 5881: char *name = ua (lookuptab[idx].name);
1.1.1.4 root 5882: if (generate_stbl)
1.1.1.7 root 5883: fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d%s), 0x%04x, %d, { %d, %d }, %d }, /* %s */\n",
5884: (using_ce || using_ce020) ? "(cpuop_func*)" : "",
5885: opcode, opcode_last_postfix[rp],
5886: extra, opcode,
5887: cputbltmp[opcode].length, cputbltmp[opcode].disp020[0], cputbltmp[opcode].disp020[1], cputbltmp[opcode].branch, name);
5888: xfree (name);
1.1.1.4 root 5889: return;
5890: }
1.1.1.7 root 5891: fprintf (headerfile, "extern %s op_%04x_%d%s_nf;\n",
5892: (using_ce || using_ce020) ? "cpuop_func_ce" : "cpuop_func", opcode, postfix, extra);
5893: fprintf (headerfile, "extern %s op_%04x_%d%s_ff;\n",
5894: (using_ce || using_ce020) ? "cpuop_func_ce" : "cpuop_func", opcode, postfix, extra);
1.1.1.4 root 5895: printf ("/* %s */\n", outopcode (opcode));
5896: if (i68000)
5897: printf("#ifndef CPUEMU_68000_ONLY\n");
1.1.1.7 root 5898: printf ("%s REGPARAM2 CPUFUNC(op_%04x_%d%s)(uae_u32 opcode)\n{\n", (using_ce || using_ce020) ? "void" : "uae_u32", opcode, postfix, extra);
5899: if (using_simple_cycles)
5900: printf("\tint count_cycles = 0;\n");
1.1.1.4 root 5901:
5902: switch (table68k[opcode].stype) {
5903: case 0: smsk = 7; break;
5904: case 1: smsk = 255; break;
5905: case 2: smsk = 15; break;
5906: case 3: smsk = 7; break;
5907: case 4: smsk = 7; break;
5908: case 5: smsk = 63; break;
5909: case 7: smsk = 3; break;
1.1.1.7 root 5910: default: term ();
1.1.1.4 root 5911: }
5912: dmsk = 7;
5913:
5914: next_cpu_level = -1;
5915: if (table68k[opcode].suse
5916: && table68k[opcode].smode != imm && table68k[opcode].smode != imm0
5917: && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2
5918: && table68k[opcode].smode != absw && table68k[opcode].smode != absl
5919: && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16)
5920: {
5921: if (table68k[opcode].spos == -1) {
5922: if (((int) table68k[opcode].sreg) >= 128)
5923: printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].sreg);
5924: else
5925: printf ("\tuae_u32 srcreg = %d;\n", (int) table68k[opcode].sreg);
5926: } else {
5927: char source[100];
5928: int pos = table68k[opcode].spos;
5929:
5930: if (pos)
5931: sprintf (source, "((opcode >> %d) & %d)", pos, smsk);
5932: else
5933: sprintf (source, "(opcode & %d)", smsk);
5934:
5935: if (table68k[opcode].stype == 3)
5936: printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source);
5937: else if (table68k[opcode].stype == 1)
5938: printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source);
5939: else
5940: printf ("\tuae_u32 srcreg = %s;\n", source);
5941: }
5942: }
5943: if (table68k[opcode].duse
5944: /* Yes, the dmode can be imm, in case of LINK or DBcc */
5945: && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0
5946: && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2
5947: && table68k[opcode].dmode != absw && table68k[opcode].dmode != absl)
5948: {
5949: if (table68k[opcode].dpos == -1) {
5950: if (((int) table68k[opcode].dreg) >= 128)
5951: printf ("\tuae_u32 dstreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].dreg);
5952: else
5953: printf ("\tuae_u32 dstreg = %d;\n", (int) table68k[opcode].dreg);
5954: } else {
5955: int pos = table68k[opcode].dpos;
5956: if (pos)
5957: printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
5958: pos, dmsk);
5959: else
5960: printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
5961: }
5962: }
5963: need_endlabel = 0;
5964: endlabelno++;
1.1.1.7 root 5965: sprintf (endlabelstr, "l_%d", endlabelno);
1.1.1.4 root 5966: count_read = count_write = count_ncycles = count_cycles = 0;
1.1.1.7 root 5967: count_cycles_ce020 = 0;
1.1.1.4 root 5968: count_read_ea = count_write_ea = count_cycles_ea = 0;
5969: gen_opcode (opcode);
5970: if (need_endlabel)
5971: printf ("%s: ;\n", endlabelstr);
1.1.1.7 root 5972: clearmmufixup (0);
5973: clearmmufixup (1);
1.1.1.4 root 5974: if (using_ce || using_prefetch) {
5975: if (count_read + count_write + count_cycles == 0)
5976: count_cycles = 4;
1.1.1.7 root 5977: returncycles ("", (count_read + count_write) * 4 + count_cycles);
5978: printf ("}");
1.1.1.4 root 5979: printf (" /* %d%s (%d/%d)",
5980: (count_read + count_write) * 4 + count_cycles, count_ncycles ? "+" : "", count_read, count_write);
5981: printf (" */\n");
1.1.1.7 root 5982: #ifdef WINUAE_FOR_HATARI
5983: insn_n_cycles = (count_read + count_write) * 4 + count_cycles;
5984: #endif
5985: //printf ( "pom_%d %s %x %d\n" , postfix , lookuptab[idx].name , opcode , (count_read + count_write) * 4 + count_cycles );
5986: } else if (count_read + count_write) {
5987: returncycles ("", (count_read + count_write) * 4 + count_cycles);
5988: printf ("}");
5989: printf("\n");
5990: #ifdef WINUAE_FOR_HATARI
5991: insn_n_cycles = (count_read + count_write) * 4 + count_cycles;
5992: #endif
5993: //printf ( "pom_%d %s %x %d\n" , postfix , lookuptab[idx].name , opcode , (count_read + count_write) * 4 + count_cycles );
1.1.1.4 root 5994: } else {
1.1.1.7 root 5995: returncycles ("", insn_n_cycles);
5996: printf ("}");
1.1.1.4 root 5997: printf("\n");
1.1.1.7 root 5998: //printf ( "pom_%d %s %x %d\n" , postfix , lookuptab[idx].name , opcode , insn_n_cycles );
1.1.1.4 root 5999: }
1.1.1.7 root 6000: if ((opcode & 0xf000) == 0xf000)
6001: m68k_pc_total = -1;
6002:
1.1.1.10! root 6003: cputbltmp[opcode].length = m68k_pc_total;
1.1.1.7 root 6004: cputbltmp[opcode].disp020[0] = 0;
6005: if (genamode8r_offset[0] > 0)
6006: cputbltmp[opcode].disp020[0] = m68k_pc_total - genamode8r_offset[0] + 2;
6007: cputbltmp[opcode].disp020[1] = 0;
6008: if (genamode8r_offset[1] > 0)
6009: cputbltmp[opcode].disp020[1] = m68k_pc_total - genamode8r_offset[1] + 2;
6010: cputbltmp[opcode].branch = branch_inst;
6011:
1.1.1.10! root 6012: if (m68k_pc_total > 0)
! 6013: printf("/* %d %d,%d %c */\n",
! 6014: m68k_pc_total, cputbltmp[opcode].disp020[0], cputbltmp[opcode].disp020[1], cputbltmp[opcode].branch ? 'B' : ' ');
! 6015:
! 6016: printf("\n");
! 6017: if (i68000)
! 6018: printf("#endif\n");
! 6019: opcode_next_clev[rp] = next_cpu_level;
! 6020: opcode_last_postfix[rp] = postfix;
! 6021:
1.1.1.7 root 6022: #ifdef WINUAE_FOR_HATARI
6023: /* Hatari only : Now patch in the instruction cycles at the beginning of the function: */
1.1.1.4 root 6024: if (!using_ce020) {
6025: fseek(stdout, nCurInstrCycPos, SEEK_SET);
6026: printf("%d;", insn_n_cycles);
6027: fseek(stdout, 0, SEEK_END);
6028: }
1.1.1.7 root 6029: #endif
1.1.1.4 root 6030:
6031: if (generate_stbl) {
1.1.1.7 root 6032: char *name = ua (lookuptab[idx].name);
1.1.1.4 root 6033: if (i68000)
6034: fprintf (stblfile, "#ifndef CPUEMU_68000_ONLY\n");
1.1.1.7 root 6035: fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d%s), 0x%04x, %d, { %d, %d }, %d }, /* %s */\n",
1.1.1.4 root 6036: (using_ce || using_ce020) ? "(cpuop_func*)" : "",
1.1.1.7 root 6037: opcode, postfix, extra, opcode,
6038: cputbltmp[opcode].length, cputbltmp[opcode].disp020[0], cputbltmp[opcode].disp020[1], cputbltmp[opcode].branch, name);
1.1.1.4 root 6039: if (i68000)
6040: fprintf (stblfile, "#endif\n");
1.1.1.7 root 6041: xfree (name);
1.1.1.4 root 6042: }
6043: }
6044:
1.1.1.7 root 6045: static void generate_func (const char *extra)
1.1.1.4 root 6046: {
6047: int j, rp;
6048:
6049: /* sam: this is for people with low memory (eg. me :)) */
6050: printf ("\n"
6051: "#if !defined(PART_1) && !defined(PART_2) && "
6052: "!defined(PART_3) && !defined(PART_4) && "
6053: "!defined(PART_5) && !defined(PART_6) && "
6054: "!defined(PART_7) && !defined(PART_8)"
6055: "\n"
6056: "#define PART_1 1\n"
6057: "#define PART_2 1\n"
6058: "#define PART_3 1\n"
6059: "#define PART_4 1\n"
6060: "#define PART_5 1\n"
6061: "#define PART_6 1\n"
6062: "#define PART_7 1\n"
6063: "#define PART_8 1\n"
6064: "#endif\n\n");
6065:
6066: rp = 0;
6067: for(j = 1; j <= 8; ++j) {
6068: int k = (j * nr_cpuop_funcs) / 8;
6069: printf ("#ifdef PART_%d\n",j);
6070: for (; rp < k; rp++)
1.1.1.7 root 6071: generate_one_opcode (rp, extra);
1.1.1.4 root 6072: printf ("#endif\n\n");
6073: }
6074:
6075: if (generate_stbl)
6076: fprintf (stblfile, "{ 0, 0 }};\n");
6077: }
6078:
1.1.1.7 root 6079: static void generate_cpu (int id, int mode)
1.1.1.4 root 6080: {
6081: char fname[100];
1.1.1.7 root 6082: const char *extra, *extraup;
6083: static int postfix2 = -1;
6084: int rp;
6085:
6086: using_tracer = mode;
6087: extra = "";
6088: extraup = "";
6089: if (using_tracer) {
6090: extra = "_t";
6091: extraup = "_T";
6092: }
6093:
6094: postfix = id;
1.1.1.9 root 6095: if (id == 0 || id == 11 || id == 13 ||
6096: id == 20 || id == 21 || id == 22 || id == 23 || id == 24 ||
6097: id == 31 || id == 32 || id == 33 || id == 34 || id == 35 ||
6098: id == 40 || id == 50) {
1.1.1.7 root 6099: if (generate_stbl)
6100: fprintf (stblfile, "#ifdef CPUEMU_%d%s\n", postfix, extraup);
6101: postfix2 = postfix;
6102: sprintf (fname, "cpuemu_%d%s.c", postfix, extra);
6103: if (freopen (fname, "wb", stdout) == NULL) {
6104: abort ();
6105: }
6106: generate_includes (stdout, id);
6107: }
6108:
6109: using_exception_3 = 1;
6110: using_prefetch = 0;
6111: using_prefetch_020 = 0;
6112: using_ce = 0;
6113: using_ce020 = 0;
6114: using_mmu = 0;
6115: using_waitstates = 0;
6116: memory_cycle_cnt = 4;
6117: mmu_postfix = "";
1.1.1.10! root 6118: xfc_postfix = "";
1.1.1.7 root 6119: using_simple_cycles = 0;
1.1.1.8 root 6120: using_indirect = 0;
6121: cpu_generic = false;
1.1.1.7 root 6122:
6123: #ifdef WINUAE_FOR_HATARI
6124: using_bus_error = 1; /* Enable code to handle bus error */
6125: #endif
6126:
6127: if (id == 11 || id == 12) { // 11 = 68010 prefetch, 12 = 68000 prefetch
6128: cpu_level = id == 11 ? 1 : 0;
6129: using_prefetch = 1;
6130: using_exception_3 = 1;
6131: using_simple_cycles = 1;
6132: if (id == 11) {
6133: read_counts ();
6134: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6135: opcode_next_clev[rp] = cpu_level;
6136: }
6137: } else if (id == 13 || id == 14) { // 13 = 68010 cycle-exact, 14 = 68000 cycle-exact
6138: cpu_level = id == 13 ? 1 : 0;
6139: using_prefetch = 1;
6140: using_exception_3 = 1;
6141: using_ce = 1;
6142: if (id == 13) {
6143: read_counts ();
6144: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6145: opcode_next_clev[rp] = cpu_level;
6146: }
6147: } else if (id == 20) { // 68020 prefetch
6148: cpu_level = 2;
6149: using_prefetch_020 = 1;
6150: read_counts ();
6151: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6152: opcode_next_clev[rp] = cpu_level;
6153: } else if (id == 21) { // 68020 cycle-exact
6154: cpu_level = 2;
6155: using_ce020 = 1;
6156: using_prefetch_020 = 1;
6157: // timing tables are from 030 which has 2
6158: // clock memory accesses, 68020 has 3 clock
6159: // memory accesses
6160: using_waitstates = 1;
6161: memory_cycle_cnt = 3;
6162: read_counts ();
6163: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6164: opcode_next_clev[rp] = cpu_level;
6165: } else if (id == 22) { // 68030 prefetch
6166: cpu_level = 3;
6167: using_prefetch_020 = 2;
6168: read_counts ();
6169: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6170: opcode_next_clev[rp] = cpu_level;
6171: } else if (id == 23) { // 68030 "cycle-exact"
6172: cpu_level = 3;
6173: using_ce020 = 2;
6174: using_prefetch_020 = 2;
6175: memory_cycle_cnt = 2;
6176: read_counts ();
6177: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6178: opcode_next_clev[rp] = cpu_level;
6179: } else if (id == 24 || id == 25) { // 68040/060 "cycle-exact"
6180: cpu_level = id == 24 ? 5 : 4;
6181: using_ce020 = 3;
6182: using_prefetch_020 = 3;
6183: memory_cycle_cnt = 0;
6184: if (id == 24) {
6185: read_counts();
6186: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6187: opcode_next_clev[rp] = cpu_level;
6188: }
6189: } else if (id == 31) { // 31 = 68040 MMU
6190: mmu_postfix = "040";
6191: cpu_level = 4;
6192: using_mmu = 68040;
6193: read_counts ();
6194: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6195: opcode_next_clev[rp] = cpu_level;
6196: } else if (id == 32) { // 32 = 68030 MMU
6197: mmu_postfix = "030";
1.1.1.10! root 6198: xfc_postfix = "_state";
1.1.1.7 root 6199: cpu_level = 3;
6200: using_mmu = 68030;
6201: read_counts ();
6202: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6203: opcode_next_clev[rp] = cpu_level;
6204: } else if (id == 33) { // 33 = 68060 MMU
6205: mmu_postfix = "060";
6206: cpu_level = 5;
6207: using_mmu = 68060;
6208: read_counts ();
6209: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6210: opcode_next_clev[rp] = cpu_level;
1.1.1.9 root 6211: } else if (id == 34) { // 34 = 68030 MMU + caches
6212: mmu_postfix = "030c";
1.1.1.10! root 6213: xfc_postfix = "_state";
1.1.1.9 root 6214: cpu_level = 3;
6215: using_prefetch_020 = 2;
6216: using_mmu = 68030;
6217: read_counts ();
6218: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6219: opcode_next_clev[rp] = cpu_level;
6220: } else if (id == 35) { // 35 = 68030 MMU + caches + CE
6221: mmu_postfix = "030c";
6222: cpu_level = 3;
6223: using_ce020 = 2;
6224: using_prefetch_020 = 2;
6225: using_mmu = 68030;
6226: read_counts ();
6227: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6228: opcode_next_clev[rp] = cpu_level;
1.1.1.7 root 6229: } else if (id < 6) {
1.1.1.8 root 6230: cpu_level = 5 - (id - 0); // "generic"
6231: cpu_generic = true;
1.1.1.7 root 6232: } else if (id >= 40 && id < 46) {
1.1.1.8 root 6233: cpu_level = 5 - (id - 40); // "generic" + direct
6234: cpu_generic = true;
1.1.1.7 root 6235: if (id == 40) {
6236: read_counts();
6237: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6238: opcode_next_clev[rp] = cpu_level;
6239: }
1.1.1.8 root 6240: using_indirect = -1;
6241: } else if (id >= 50 && id < 56) {
6242: cpu_level = 5 - (id - 50); // "generic" + indirect
6243: cpu_generic = true;
6244: if (id == 50) {
6245: read_counts();
6246: for (rp = 0; rp < nr_cpuop_funcs; rp++)
6247: opcode_next_clev[rp] = cpu_level;
6248: }
6249: }
6250:
6251: if (!using_indirect)
6252: using_indirect = using_ce || using_ce020 || using_prefetch_020 || id >= 50;
1.1.1.7 root 6253:
6254: if (generate_stbl) {
1.1.1.8 root 6255: if ((id > 0 && id < 6) || (id >= 20 && id < 40) || (id > 40 && id < 46) || (id > 50 && id < 56))
1.1.1.7 root 6256: fprintf (stblfile, "#ifndef CPUEMU_68000_ONLY\n");
6257: fprintf (stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d%s)[] = {\n", postfix, extra);
6258: }
6259: endlabelno = id * 10000;
6260: generate_func (extra);
6261: if (generate_stbl) {
1.1.1.8 root 6262: if ((id > 0 && id < 6) || (id >= 20 && id < 40) || (id > 40 && id < 46) || (id > 50 && id < 56))
1.1.1.7 root 6263: fprintf (stblfile, "#endif /* CPUEMU_68000_ONLY */\n");
6264: if (postfix2 >= 0)
6265: fprintf (stblfile, "#endif /* CPUEMU_%d%s */\n", postfix2, extraup);
6266: }
6267: postfix2 = -1;
6268: }
6269:
6270: int main(int argc, char *argv[])
6271: {
6272: int i;
1.1.1.4 root 6273:
6274: read_table68k ();
6275: do_merges ();
6276:
6277: opcode_map = xmalloc (int, nr_cpuop_funcs);
6278: opcode_last_postfix = xmalloc (int, nr_cpuop_funcs);
6279: opcode_next_clev = xmalloc (int, nr_cpuop_funcs);
6280: counts = xmalloc (unsigned long, 65536);
6281: read_counts ();
6282:
6283: /* It would be a lot nicer to put all in one file (we'd also get rid of
6284: * cputbl.h that way), but cpuopti can't cope. That could be fixed, but
6285: * I don't dare to touch the 68k version. */
6286:
6287: headerfile = fopen ("cputbl.h", "wb");
6288:
6289: stblfile = fopen ("cpustbl.c", "wb");
1.1.1.7 root 6290: generate_includes (stblfile, 0);
1.1.1.4 root 6291:
1.1.1.8 root 6292: for (i = 0; i <= 55; i++) {
1.1.1.9 root 6293: if ((i >= 6 && i < 11) || (i > 14 && i < 20) || (i > 25 && i < 31) || (i > 35 && i < 40))
1.1.1.4 root 6294: continue;
6295: generate_stbl = 1;
1.1.1.7 root 6296: generate_cpu (i, 0);
1.1.1.4 root 6297: }
6298:
6299: free (table68k);
6300: return 0;
6301: }
6302:
1.1.1.10! root 6303: #ifndef WINUAE_FOR_HATARI
1.1.1.4 root 6304: void write_log (const TCHAR *format,...)
6305: {
6306: }
1.1.1.10! root 6307: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.