|
|
1.1 root 1: /*
1.1.1.2 root 2: * UAE - The Un*x Amiga Emulator - CPU core
1.1 root 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
1.1.1.2 root 19: *
20: * Adaptation to Hatari and better cpu timings by Thomas Huth
21: *
1.1.1.4 root 22: * This file is distributed under the GNU Public License, version 2 or at
23: * your option any later version. Read the file gpl.txt for details.
1.1 root 24: */
1.1.1.8 root 25:
26:
27: /* 2007/03/xx [NP] Use add_cycles.pl to set 'CurrentInstrCycles' in each opcode. */
28: /* 2007/04/09 [NP] Correct CLR : on 68000, CLR reads the memory before clearing it (but we should */
29: /* not add cycles for reading). This means CLR can give 2 wait states (one for */
30: /* read and one for right) (clr.b $fa1b.w in Decade's Demo Main Menu). */
31: /* 2007/04/14 [NP] - Although dest -(an) normally takes 2 cycles, this is not the case for move : */
32: /* move dest (an), (an)+ and -(an) all take the same time (curi->dmode == Apdi) */
33: /* (Syntax Terror Demo Reset). */
34: /* - Scc takes 6 cycles instead of 4 if the result is true (Ventura Demo Loader). */
35: /* - Store the family of the current opcode into OpcodeFamily : used to check */
36: /* instruction pairing on ST into m68000.c */
37: /* 2007/04/17 [NP] Add support for cycle accurate MULU (No Cooper Greeting Screen). */
38: /* 2007/04/24 [NP] BCLR #n,Dx takes 12 cycles instead of 14 if n<16 (ULM Demo Menu). */
39: /* 2007/04/25 [NP] On ST, d8(An,Xn) and d8(PC,Xn) take 2 cycles more than the official 68000's */
40: /* table (ULM Demo Menu). */
41: /* 2007/11/12 [NP] Add refill_prefetch for i_ADD to fix Transbeauce 2 demo self modified code. */
42: /* Ugly hack, we need better prefetch emulation (switch to winuae gencpu.c) */
43: /* 2007/11/25 [NP] In i_DBcc, in case of address error, last_addr_for_exception_3 should be */
44: /* pc+4, not pc+2 (Transbeauce 2 demo) (e.g. 'dbf d0,#$fff5'). */
45: /* This means the value pushed on the frame stack should be the address of the */
46: /* instruction following the one generating the address error. */
47: /* FIXME : this should be the case for i_BSR and i_BCC too (need to check on */
48: /* a real 68000). */
49: /* 2007/11/28 [NP] Backport DIVS/DIVU cycles exact routines from WinUAE (original work by Jorge */
50: /* Cwik, [email protected]). */
51: /* 2007/12/08 [NP] In case of CHK/CHK2 exception, PC stored on the stack wasn't pointing to the */
52: /* next instruction but to the current CHK/CHK2 instruction (Transbeauce 2 demo). */
53: /* We need to call 'sync_m68k_pc' before calling 'Exception'. */
54: /* 2007/12/09 [NP] CHK.L (e.g. $4700) doesn't exist on 68000 and should be considered as an illegal*/
55: /* instruction (Transbeauce 2 demo) -> change in table68k. */
56: /* 2008/01/24 [NP] BCLR Dy,Dx takes 8 cycles instead of 10 if Dy<16 (Fullshade in Anomaly Demos). */
57: /* 2008/01/26 [NP] On ST, d8(An,Xn) takes 2 cycles more when used with ADDA/SUBA (ULM Demo Menu) */
58: /* but not when used with MOVE (e.g. 'move.l 0(a5,d1),(a4)' takes 26 cycles and so */
59: /* can pair with a lsr) (Anomaly Demo Intro). */
1.1.1.9 root 60: /* 2008/04/26 [NP] Handle sz_byte for Areg in genamode, as 'move.b a1,(a0)' ($1089) is possible */
61: /* on ST (fix Blood Money on Superior 65) */
1.1.1.12 root 62: /* 2010/04/05 [NP] On ST, d8(An,Xn) takes 2 cycles more (which can generate pairing). */
63: /* Use BusCyclePenalty to properly handle the 2/4 cycles added in that case when */
64: /* addressing mode is Ad8r or PC8r (ULM Demo Menu, Anomaly Demo Intro, DHS */
65: /* Sommarhack 2010) (see m68000.h) */
1.1.1.15! root 66: /* 2012/01/29 [NP] Add refill_prefetch for i_EOR to fix Operation Clean Streets self modified code.*/
! 67: /* Ugly hack, we need better prefetch emulation (switch to winuae gencpu.c) */
! 68: /* 2012/05/05 [NP] In i_JMP, in case of address error, last_addr_for_exception_3 should not always */
! 69: /* be pc+6, (Sherman Cracktro in No Extra V2 compilation) (e.g. 'jmp (a2)' : pc+2) */
1.1.1.8 root 70:
71:
1.1.1.11 root 72: const char GenCpu_fileid[] = "Hatari gencpu.c : " __DATE__ " " __TIME__;
1.1 root 73:
74: #include <ctype.h>
1.1.1.3 root 75: #include <string.h>
1.1 root 76:
77: #include "sysdeps.h"
78: #include "readcpu.h"
79:
80: #define BOOL_TYPE "int"
81:
82: static FILE *headerfile;
83: static FILE *stblfile;
84:
85: static int using_prefetch;
86: static int using_exception_3;
87: static int cpu_level;
88:
1.1.1.2 root 89: char exactCpuCycles[256]; /* Space to store return string for exact cpu cycles */
90:
1.1.1.8 root 91: long nCurInstrCycPos; /* Stores where we have to patch in the current cycles value */
1.1.1.2 root 92:
1.1 root 93: /* For the current opcode, the next lower level that will have different code.
94: * Initialized to -1 for each opcode. If it remains unchanged, indicates we
95: * are done with that opcode. */
96: static int next_cpu_level;
97: static int *opcode_map;
98: static int *opcode_next_clev;
99: static int *opcode_last_postfix;
100: static unsigned long *counts;
101:
1.1.1.6 root 102:
1.1 root 103: static void read_counts (void)
104: {
105: FILE *file;
106: unsigned long opcode, count, total;
107: char name[20];
108: int nr = 0;
109: memset (counts, 0, 65536 * sizeof *counts);
110:
111: file = fopen ("frequent.68k", "r");
112: if (file) {
1.1.1.11 root 113: if (fscanf (file, "Total: %lu\n", &total) == EOF) {
114: perror("read_counts");
115: }
1.1 root 116: while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
117: opcode_next_clev[nr] = 4;
118: opcode_last_postfix[nr] = -1;
119: opcode_map[nr++] = opcode;
120: counts[opcode] = count;
121: }
122: fclose (file);
123: }
124: if (nr == nr_cpuop_funcs)
125: return;
126: for (opcode = 0; opcode < 0x10000; opcode++) {
127: if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG
128: && counts[opcode] == 0)
129: {
130: opcode_next_clev[nr] = 4;
131: opcode_last_postfix[nr] = -1;
132: opcode_map[nr++] = opcode;
133: counts[opcode] = count;
134: }
135: }
136: if (nr != nr_cpuop_funcs)
137: abort ();
138: }
139:
140: static char endlabelstr[80];
141: static int endlabelno = 0;
142: static int need_endlabel;
143:
144: static int n_braces = 0;
145: static int m68k_pc_offset = 0;
146: static int insn_n_cycles;
147:
148: static void start_brace (void)
149: {
150: n_braces++;
151: printf ("{");
152: }
153:
154: static void close_brace (void)
155: {
156: assert (n_braces > 0);
157: n_braces--;
158: printf ("}");
159: }
160:
161: static void finish_braces (void)
162: {
163: while (n_braces > 0)
164: close_brace ();
165: }
166:
167: static void pop_braces (int to)
168: {
169: while (n_braces > to)
170: close_brace ();
171: }
172:
173: static int bit_size (int size)
174: {
175: switch (size) {
176: case sz_byte: return 8;
177: case sz_word: return 16;
178: case sz_long: return 32;
179: default: abort ();
180: }
181: return 0;
182: }
183:
184: static const char *bit_mask (int size)
185: {
186: switch (size) {
187: case sz_byte: return "0xff";
188: case sz_word: return "0xffff";
189: case sz_long: return "0xffffffff";
190: default: abort ();
191: }
192: return 0;
193: }
194:
195: static const char *gen_nextilong (void)
196: {
197: static char buffer[80];
198: int r = m68k_pc_offset;
199: m68k_pc_offset += 4;
200:
201: insn_n_cycles += 8;
202:
203: if (using_prefetch)
204: sprintf (buffer, "get_ilong_prefetch(%d)", r);
205: else
206: sprintf (buffer, "get_ilong(%d)", r);
207: return buffer;
208: }
209:
210: static const char *gen_nextiword (void)
211: {
212: static char buffer[80];
213: int r = m68k_pc_offset;
214: m68k_pc_offset += 2;
215:
216: insn_n_cycles += 4;
217:
218: if (using_prefetch)
219: sprintf (buffer, "get_iword_prefetch(%d)", r);
220: else
221: sprintf (buffer, "get_iword(%d)", r);
222: return buffer;
223: }
224:
225: static const char *gen_nextibyte (void)
226: {
227: static char buffer[80];
228: int r = m68k_pc_offset;
229: m68k_pc_offset += 2;
230:
231: insn_n_cycles += 4;
232:
233: if (using_prefetch)
234: sprintf (buffer, "get_ibyte_prefetch(%d)", r);
235: else
236: sprintf (buffer, "get_ibyte(%d)", r);
237: return buffer;
238: }
239:
240: static void fill_prefetch_0 (void)
241: {
242: if (using_prefetch)
243: printf ("fill_prefetch_0 ();\n");
244: }
245:
246: static void fill_prefetch_2 (void)
247: {
248: if (using_prefetch)
249: printf ("fill_prefetch_2 ();\n");
250: }
251:
252: static void sync_m68k_pc (void)
253: {
254: if (m68k_pc_offset == 0)
255: return;
256: printf ("m68k_incpc(%d);\n", m68k_pc_offset);
257: switch (m68k_pc_offset) {
258: case 0:
259: /*fprintf (stderr, "refilling prefetch at 0\n"); */
260: break;
261: case 2:
262: fill_prefetch_2 ();
263: break;
264: default:
265: fill_prefetch_0 ();
266: break;
267: }
268: m68k_pc_offset = 0;
269: }
270:
271: /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
1.1.1.4 root 272: * the calling routine handles Apdi and Aipi modes.
273: * gb-- movem == 2 means the same thing but for a MOVE16 instruction */
1.1.1.12 root 274: static void genamode (amodes mode, const char *reg, wordsizes size,
275: const char *name, int getv, int movem)
1.1 root 276: {
277: start_brace ();
278: switch (mode) {
279: case Dreg:
280: if (movem)
281: abort ();
282: if (getv == 1)
283: switch (size) {
284: case sz_byte:
285: printf ("\tuae_s8 %s = m68k_dreg(regs, %s);\n", name, reg);
286: break;
287: case sz_word:
288: printf ("\tuae_s16 %s = m68k_dreg(regs, %s);\n", name, reg);
289: break;
290: case sz_long:
291: printf ("\tuae_s32 %s = m68k_dreg(regs, %s);\n", name, reg);
292: break;
293: default:
294: abort ();
295: }
296: return;
297: case Areg:
298: if (movem)
299: abort ();
300: if (getv == 1)
301: switch (size) {
1.1.1.9 root 302: case sz_byte: // [NP] Areg with .b is possible in MOVE source */
303: printf ("\tuae_s8 %s = m68k_areg(regs, %s);\n", name, reg);
304: break;
1.1 root 305: case sz_word:
306: printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg);
307: break;
308: case sz_long:
309: printf ("\tuae_s32 %s = m68k_areg(regs, %s);\n", name, reg);
310: break;
311: default:
312: abort ();
313: }
314: return;
315: case Aind:
316: printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
317: break;
318: case Aipi:
319: printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
320: break;
321: case Apdi:
322: insn_n_cycles += 2;
323: switch (size) {
324: case sz_byte:
325: if (movem)
326: printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg);
327: else
328: printf ("\tuaecptr %sa = m68k_areg(regs, %s) - areg_byteinc[%s];\n", name, reg, reg);
329: break;
330: case sz_word:
331: printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 2);
332: break;
333: case sz_long:
334: printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 4);
335: break;
336: default:
337: abort ();
338: }
339: break;
340: case Ad16:
341: printf ("\tuaecptr %sa = m68k_areg(regs, %s) + (uae_s32)(uae_s16)%s;\n", name, reg, gen_nextiword ());
342: break;
343: case Ad8r:
344: insn_n_cycles += 2;
345: if (cpu_level > 1) {
346: if (next_cpu_level < 1)
347: next_cpu_level = 1;
348: sync_m68k_pc ();
349: start_brace ();
350: /* This would ordinarily be done in gen_nextiword, which we bypass. */
351: insn_n_cycles += 4;
352: printf ("\tuaecptr %sa = get_disp_ea_020(m68k_areg(regs, %s), next_iword());\n", name, reg);
1.1.1.8 root 353: } else {
1.1 root 354: printf ("\tuaecptr %sa = get_disp_ea_000(m68k_areg(regs, %s), %s);\n", name, reg, gen_nextiword ());
1.1.1.8 root 355: }
1.1.1.12 root 356: printf ("\tBusCyclePenalty += 2;\n");
1.1 root 357:
358: break;
359: case PC16:
360: printf ("\tuaecptr %sa = m68k_getpc () + %d;\n", name, m68k_pc_offset);
361: printf ("\t%sa += (uae_s32)(uae_s16)%s;\n", name, gen_nextiword ());
362: break;
363: case PC8r:
364: insn_n_cycles += 2;
365: if (cpu_level > 1) {
366: if (next_cpu_level < 1)
367: next_cpu_level = 1;
368: sync_m68k_pc ();
369: start_brace ();
370: /* This would ordinarily be done in gen_nextiword, which we bypass. */
371: insn_n_cycles += 4;
372: printf ("\tuaecptr tmppc = m68k_getpc();\n");
373: printf ("\tuaecptr %sa = get_disp_ea_020(tmppc, next_iword());\n", name);
374: } else {
375: printf ("\tuaecptr tmppc = m68k_getpc() + %d;\n", m68k_pc_offset);
376: printf ("\tuaecptr %sa = get_disp_ea_000(tmppc, %s);\n", name, gen_nextiword ());
377: }
1.1.1.12 root 378: printf ("\tBusCyclePenalty += 2;\n");
1.1 root 379:
380: break;
381: case absw:
382: printf ("\tuaecptr %sa = (uae_s32)(uae_s16)%s;\n", name, gen_nextiword ());
383: break;
384: case absl:
385: printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ());
386: break;
387: case imm:
388: if (getv != 1)
389: abort ();
390: switch (size) {
391: case sz_byte:
392: printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
393: break;
394: case sz_word:
395: printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
396: break;
397: case sz_long:
398: printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
399: break;
400: default:
401: abort ();
402: }
403: return;
404: case imm0:
405: if (getv != 1)
406: abort ();
407: printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ());
408: return;
409: case imm1:
410: if (getv != 1)
411: abort ();
412: printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ());
413: return;
414: case imm2:
415: if (getv != 1)
416: abort ();
417: printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ());
418: return;
419: case immi:
420: if (getv != 1)
421: abort ();
422: printf ("\tuae_u32 %s = %s;\n", name, reg);
423: return;
424: default:
425: abort ();
426: }
427:
428: /* We get here for all non-reg non-immediate addressing modes to
429: * actually fetch the value. */
430:
431: if (using_exception_3 && getv != 0 && size != sz_byte) {
432: printf ("\tif ((%sa & 1) != 0) {\n", name);
433: printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name);
434: printf ("\t\tlast_op_for_exception_3 = opcode;\n");
435: printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + %d;\n", m68k_pc_offset);
1.1.1.12 root 436: printf ("\t\tException(3, 0, M68000_EXC_SRC_CPU);\n");
1.1 root 437: printf ("\t\tgoto %s;\n", endlabelstr);
438: printf ("\t}\n");
439: need_endlabel = 1;
440: start_brace ();
441: }
442:
443: if (getv == 1) {
444: switch (size) {
445: case sz_byte: insn_n_cycles += 4; break;
446: case sz_word: insn_n_cycles += 4; break;
447: case sz_long: insn_n_cycles += 8; break;
448: default: abort ();
449: }
450: start_brace ();
451: switch (size) {
452: case sz_byte: printf ("\tuae_s8 %s = get_byte(%sa);\n", name, name); break;
453: case sz_word: printf ("\tuae_s16 %s = get_word(%sa);\n", name, name); break;
454: case sz_long: printf ("\tuae_s32 %s = get_long(%sa);\n", name, name); break;
455: default: abort ();
456: }
457: }
458:
459: /* We now might have to fix up the register for pre-dec or post-inc
460: * addressing modes. */
461: if (!movem)
462: switch (mode) {
463: case Aipi:
464: switch (size) {
465: case sz_byte:
466: printf ("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg);
467: break;
468: case sz_word:
469: printf ("\tm68k_areg(regs, %s) += 2;\n", reg);
470: break;
471: case sz_long:
472: printf ("\tm68k_areg(regs, %s) += 4;\n", reg);
473: break;
474: default:
475: abort ();
476: }
477: break;
478: case Apdi:
479: printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name);
480: break;
481: default:
482: break;
483: }
484: }
485:
1.1.1.12 root 486: static void genastore (const char *from, amodes mode, const char *reg,
487: wordsizes size, const char *to)
1.1 root 488: {
489: switch (mode) {
490: case Dreg:
491: switch (size) {
492: case sz_byte:
493: printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xff) | ((%s) & 0xff);\n", reg, reg, from);
494: break;
495: case sz_word:
496: printf ("\tm68k_dreg(regs, %s) = (m68k_dreg(regs, %s) & ~0xffff) | ((%s) & 0xffff);\n", reg, reg, from);
497: break;
498: case sz_long:
499: printf ("\tm68k_dreg(regs, %s) = (%s);\n", reg, from);
500: break;
501: default:
502: abort ();
503: }
504: break;
505: case Areg:
506: switch (size) {
507: case sz_word:
508: fprintf (stderr, "Foo\n");
509: printf ("\tm68k_areg(regs, %s) = (uae_s32)(uae_s16)(%s);\n", reg, from);
510: break;
511: case sz_long:
512: printf ("\tm68k_areg(regs, %s) = (%s);\n", reg, from);
513: break;
514: default:
515: abort ();
516: }
517: break;
518: case Aind:
519: case Aipi:
520: case Apdi:
521: case Ad16:
522: case Ad8r:
523: case absw:
524: case absl:
525: case PC16:
526: case PC8r:
527: if (using_prefetch)
528: sync_m68k_pc ();
529: switch (size) {
530: case sz_byte:
531: insn_n_cycles += 4;
532: printf ("\tput_byte(%sa,%s);\n", to, from);
533: break;
534: case sz_word:
535: insn_n_cycles += 4;
536: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
537: abort ();
538: printf ("\tput_word(%sa,%s);\n", to, from);
539: break;
540: case sz_long:
541: insn_n_cycles += 8;
542: if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
543: abort ();
544: printf ("\tput_long(%sa,%s);\n", to, from);
545: break;
546: default:
547: abort ();
548: }
549: break;
550: case imm:
551: case imm0:
552: case imm1:
553: case imm2:
554: case immi:
555: abort ();
556: break;
557: default:
558: abort ();
559: }
560: }
561:
1.1.1.2 root 562:
1.1 root 563: static void genmovemel (uae_u16 opcode)
564: {
565: char getcode[100];
1.1.1.3 root 566: int bMovemLong = (table68k[opcode].size == sz_long);
567: int size = bMovemLong ? 4 : 2;
1.1 root 568:
1.1.1.3 root 569: if (bMovemLong) {
1.1 root 570: strcpy (getcode, "get_long(srca)");
571: } else {
572: strcpy (getcode, "(uae_s32)(uae_s16)get_word(srca)");
573: }
574:
575: printf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
576: printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
1.1.1.2 root 577: printf ("\tretcycles = 0;\n");
1.1.1.3 root 578: genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
1.1 root 579: start_brace ();
1.1.1.2 root 580: printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s;"
1.1.1.3 root 581: " srca += %d; dmask = movem_next[dmask]; retcycles+=%d; }\n",
582: getcode, size, (bMovemLong ? 8 : 4));
1.1.1.2 root 583: printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s;"
1.1.1.3 root 584: " srca += %d; amask = movem_next[amask]; retcycles+=%d; }\n",
585: getcode, size, (bMovemLong ? 8 : 4));
1.1 root 586:
587: if (table68k[opcode].dmode == Aipi)
588: printf ("\tm68k_areg(regs, dstreg) = srca;\n");
1.1.1.2 root 589:
590: /* Better cycles - experimental! (Thothy) */
591: switch(table68k[opcode].dmode)
1.1.1.3 root 592: {
1.1.1.2 root 593: case Aind: insn_n_cycles=12; break;
594: case Aipi: insn_n_cycles=12; break;
595: case Ad16: insn_n_cycles=16; break;
596: case Ad8r: insn_n_cycles=18; break;
597: case absw: insn_n_cycles=16; break;
598: case absl: insn_n_cycles=20; break;
599: case PC16: insn_n_cycles=16; break;
600: case PC8r: insn_n_cycles=18; break;
1.1.1.3 root 601: }
602: sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
1.1 root 603: }
604:
605: static void genmovemle (uae_u16 opcode)
606: {
607: char putcode[100];
1.1.1.3 root 608: int bMovemLong = (table68k[opcode].size == sz_long);
609: int size = bMovemLong ? 4 : 2;
610:
611: if (bMovemLong) {
1.1 root 612: strcpy (putcode, "put_long(srca,");
613: } else {
614: strcpy (putcode, "put_word(srca,");
615: }
616:
617: printf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
1.1.1.3 root 618: printf ("\tretcycles = 0;\n");
1.1 root 619: genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
620: if (using_prefetch)
621: sync_m68k_pc ();
622:
623: start_brace ();
624: if (table68k[opcode].dmode == Apdi) {
1.1.1.2 root 625: printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n");
626: printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask]));"
1.1.1.3 root 627: " amask = movem_next[amask]; retcycles+=%d; }\n",
628: size, putcode, (bMovemLong ? 8 : 4));
1.1.1.2 root 629: printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask]));"
1.1.1.3 root 630: " dmask = movem_next[dmask]; retcycles+=%d; }\n",
631: size, putcode, (bMovemLong ? 8 : 4));
1.1.1.2 root 632: printf ("\tm68k_areg(regs, dstreg) = srca;\n");
1.1 root 633: } else {
1.1.1.2 root 634: printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n");
635: printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d;"
1.1.1.3 root 636: " dmask = movem_next[dmask]; retcycles+=%d; }\n",
637: putcode, size, (bMovemLong ? 8 : 4));
1.1.1.2 root 638: printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d;"
1.1.1.3 root 639: " amask = movem_next[amask]; retcycles+=%d; }\n",
640: putcode, size, (bMovemLong ? 8 : 4));
1.1.1.2 root 641: }
642:
643: /* Better cycles - experimental! (Thothy) */
644: switch(table68k[opcode].dmode)
1.1.1.3 root 645: {
1.1.1.2 root 646: case Aind: insn_n_cycles=8; break;
647: case Apdi: insn_n_cycles=8; break;
648: case Ad16: insn_n_cycles=12; break;
649: case Ad8r: insn_n_cycles=14; break;
650: case absw: insn_n_cycles=12; break;
651: case absl: insn_n_cycles=16; break;
1.1.1.3 root 652: }
653: sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
1.1 root 654: }
655:
1.1.1.2 root 656:
1.1 root 657: static void duplicate_carry (void)
658: {
659: printf ("\tCOPY_CARRY;\n");
660: }
661:
662: typedef enum
663: {
664: flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp, flag_addx, flag_subx, flag_zn,
665: flag_av, flag_sv
666: }
667: flagtypes;
668:
1.1.1.12 root 669: static void genflags_normal (flagtypes type, wordsizes size, const char *value,
670: const char *src, const char *dst)
1.1 root 671: {
672: char vstr[100], sstr[100], dstr[100];
673: char usstr[100], udstr[100];
674: char unsstr[100], undstr[100];
675:
676: switch (size) {
677: case sz_byte:
678: strcpy (vstr, "((uae_s8)(");
679: strcpy (usstr, "((uae_u8)(");
680: break;
681: case sz_word:
682: strcpy (vstr, "((uae_s16)(");
683: strcpy (usstr, "((uae_u16)(");
684: break;
685: case sz_long:
686: strcpy (vstr, "((uae_s32)(");
687: strcpy (usstr, "((uae_u32)(");
688: break;
689: default:
690: abort ();
691: }
692: strcpy (unsstr, usstr);
693:
694: strcpy (sstr, vstr);
695: strcpy (dstr, vstr);
696: strcat (vstr, value);
697: strcat (vstr, "))");
698: strcat (dstr, dst);
699: strcat (dstr, "))");
700: strcat (sstr, src);
701: strcat (sstr, "))");
702:
703: strcpy (udstr, usstr);
704: strcat (udstr, dst);
705: strcat (udstr, "))");
706: strcat (usstr, src);
707: strcat (usstr, "))");
708:
709: strcpy (undstr, unsstr);
710: strcat (unsstr, "-");
711: strcat (undstr, "~");
712: strcat (undstr, dst);
713: strcat (undstr, "))");
714: strcat (unsstr, src);
715: strcat (unsstr, "))");
716:
717: switch (type) {
718: case flag_logical_noclobber:
719: case flag_logical:
720: case flag_zn:
721: case flag_av:
722: case flag_sv:
723: case flag_addx:
724: case flag_subx:
725: break;
726:
727: case flag_add:
728: start_brace ();
729: printf ("uae_u32 %s = %s + %s;\n", value, dstr, sstr);
730: break;
731: case flag_sub:
732: case flag_cmp:
733: start_brace ();
734: printf ("uae_u32 %s = %s - %s;\n", value, dstr, sstr);
735: break;
736: }
737:
738: switch (type) {
739: case flag_logical_noclobber:
740: case flag_logical:
741: case flag_zn:
742: break;
743:
744: case flag_add:
745: case flag_sub:
746: case flag_addx:
747: case flag_subx:
748: case flag_cmp:
749: case flag_av:
750: case flag_sv:
751: start_brace ();
752: printf ("\t" BOOL_TYPE " flgs = %s < 0;\n", sstr);
753: printf ("\t" BOOL_TYPE " flgo = %s < 0;\n", dstr);
754: printf ("\t" BOOL_TYPE " flgn = %s < 0;\n", vstr);
755: break;
756: }
757:
758: switch (type) {
759: case flag_logical:
760: printf ("\tCLEAR_CZNV;\n");
761: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
762: printf ("\tSET_NFLG (%s < 0);\n", vstr);
763: break;
764: case flag_logical_noclobber:
765: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
766: printf ("\tSET_NFLG (%s < 0);\n", vstr);
767: break;
768: case flag_av:
769: printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
770: break;
771: case flag_sv:
772: printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
773: break;
774: case flag_zn:
775: printf ("\tSET_ZFLG (GET_ZFLG & (%s == 0));\n", vstr);
776: printf ("\tSET_NFLG (%s < 0);\n", vstr);
777: break;
778: case flag_add:
779: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
780: printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n");
781: printf ("\tSET_CFLG (%s < %s);\n", undstr, usstr);
782: duplicate_carry ();
783: printf ("\tSET_NFLG (flgn != 0);\n");
784: break;
785: case flag_sub:
786: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
787: printf ("\tSET_VFLG ((flgs ^ flgo) & (flgn ^ flgo));\n");
788: printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
789: duplicate_carry ();
790: printf ("\tSET_NFLG (flgn != 0);\n");
791: break;
792: case flag_addx:
793: printf ("\tSET_VFLG ((flgs ^ flgn) & (flgo ^ flgn));\n"); /* minterm SON: 0x42 */
794: printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgo) & (flgo ^ flgn)));\n"); /* minterm SON: 0xD4 */
795: duplicate_carry ();
796: break;
797: case flag_subx:
798: printf ("\tSET_VFLG ((flgs ^ flgo) & (flgo ^ flgn));\n"); /* minterm SON: 0x24 */
799: printf ("\tSET_CFLG (flgs ^ ((flgs ^ flgn) & (flgo ^ flgn)));\n"); /* minterm SON: 0xB2 */
800: duplicate_carry ();
801: break;
802: case flag_cmp:
803: printf ("\tSET_ZFLG (%s == 0);\n", vstr);
804: printf ("\tSET_VFLG ((flgs != flgo) && (flgn != flgo));\n");
805: printf ("\tSET_CFLG (%s > %s);\n", usstr, udstr);
806: printf ("\tSET_NFLG (flgn != 0);\n");
807: break;
808: }
809: }
810:
1.1.1.12 root 811: static void genflags (flagtypes type, wordsizes size, const char *value,
812: const char *src, const char *dst)
1.1 root 813: {
814: /* Temporarily deleted 68k/ARM flag optimizations. I'd prefer to have
815: them in the appropriate m68k.h files and use just one copy of this
816: code here. The API can be changed if necessary. */
817: #ifdef OPTIMIZED_FLAGS
818: switch (type) {
819: case flag_add:
820: case flag_sub:
821: start_brace ();
822: printf ("\tuae_u32 %s;\n", value);
823: break;
824:
825: default:
826: break;
827: }
828:
829: /* At least some of those casts are fairly important! */
830: switch (type) {
831: case flag_logical_noclobber:
832: printf ("\t{uae_u32 oldcznv = GET_CZNV & ~(FLAGVAL_Z | FLAGVAL_N);\n");
833: if (strcmp (value, "0") == 0) {
834: printf ("\tSET_CZNV (olcznv | FLAGVAL_Z);\n");
835: } else {
836: switch (size) {
837: case sz_byte: printf ("\toptflag_testb ((uae_s8)(%s));\n", value); break;
838: case sz_word: printf ("\toptflag_testw ((uae_s16)(%s));\n", value); break;
839: case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break;
840: }
841: printf ("\tIOR_CZNV (oldcznv);\n");
842: }
843: printf ("\t}\n");
844: return;
845: case flag_logical:
846: if (strcmp (value, "0") == 0) {
847: printf ("\tSET_CZNV (FLAGVAL_Z);\n");
848: } else {
849: switch (size) {
850: case sz_byte: printf ("\toptflag_testb ((uae_s8)(%s));\n", value); break;
851: case sz_word: printf ("\toptflag_testw ((uae_s16)(%s));\n", value); break;
852: case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break;
853: }
854: }
855: return;
856:
857: case flag_add:
858: switch (size) {
859: case sz_byte: printf ("\toptflag_addb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break;
860: case sz_word: printf ("\toptflag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break;
861: case sz_long: printf ("\toptflag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break;
862: }
863: return;
864:
865: case flag_sub:
866: switch (size) {
867: case sz_byte: printf ("\toptflag_subb (%s, (uae_s8)(%s), (uae_s8)(%s));\n", value, src, dst); break;
868: case sz_word: printf ("\toptflag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break;
869: case sz_long: printf ("\toptflag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break;
870: }
871: return;
872:
873: case flag_cmp:
874: switch (size) {
875: case sz_byte: printf ("\toptflag_cmpb ((uae_s8)(%s), (uae_s8)(%s));\n", src, dst); break;
876: case sz_word: printf ("\toptflag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break;
877: case sz_long: printf ("\toptflag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break;
878: }
879: return;
880:
881: default:
882: break;
883: }
884: #endif
885:
886: genflags_normal (type, size, value, src, dst);
887: }
888:
889: static void force_range_for_rox (const char *var, wordsizes size)
890: {
891: /* Could do a modulo operation here... which one is faster? */
892: switch (size) {
893: case sz_long:
894: printf ("\tif (%s >= 33) %s -= 33;\n", var, var);
895: break;
896: case sz_word:
897: printf ("\tif (%s >= 34) %s -= 34;\n", var, var);
898: printf ("\tif (%s >= 17) %s -= 17;\n", var, var);
899: break;
900: case sz_byte:
901: printf ("\tif (%s >= 36) %s -= 36;\n", var, var);
902: printf ("\tif (%s >= 18) %s -= 18;\n", var, var);
903: printf ("\tif (%s >= 9) %s -= 9;\n", var, var);
904: break;
905: }
906: }
907:
908: static const char *cmask (wordsizes size)
909: {
910: switch (size) {
911: case sz_byte: return "0x80";
912: case sz_word: return "0x8000";
913: case sz_long: return "0x80000000";
914: default: abort ();
915: }
916: }
917:
918: static int source_is_imm1_8 (struct instr *i)
919: {
920: return i->stype == 3;
921: }
922:
1.1.1.2 root 923:
924:
1.1 root 925: static void gen_opcode (unsigned long int opcode)
926: {
1.1.1.2 root 927: #if 0
928: char *amodenames[] = { "Dreg", "Areg", "Aind", "Aipi", "Apdi", "Ad16", "Ad8r",
929: "absw", "absl", "PC16", "PC8r", "imm", "imm0", "imm1", "imm2", "immi", "am_unknown", "am_illg"};
930: #endif
931:
1.1 root 932: struct instr *curi = table68k + opcode;
933: insn_n_cycles = 4;
934:
1.1.1.8 root 935: /* Store the family of the instruction (used to check for pairing on ST)
936: * and leave some space for patching in the current cycles later */
937: printf ("\tOpcodeFamily = %d; CurrentInstrCycles = \n", curi->mnemo);
938: nCurInstrCycPos = ftell(stdout) - 5;
939:
1.1 root 940: start_brace ();
941: m68k_pc_offset = 2;
1.1.1.2 root 942:
1.1 root 943: switch (curi->plev) {
944: case 0: /* not privileged */
945: break;
946: case 1: /* unprivileged only on 68000 */
947: if (cpu_level == 0)
948: break;
949: if (next_cpu_level < 0)
950: next_cpu_level = 0;
951:
952: /* fall through */
953: case 2: /* priviledged */
1.1.1.12 root 954: printf ("if (!regs.s) { Exception(8,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1.1 root 955: need_endlabel = 1;
956: start_brace ();
957: break;
958: case 3: /* privileged if size == word */
959: if (curi->size == sz_byte)
960: break;
1.1.1.12 root 961: printf ("if (!regs.s) { Exception(8,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1.1 root 962: need_endlabel = 1;
963: start_brace ();
964: break;
965: }
1.1.1.2 root 966:
967: /* Build the opcodes: */
1.1 root 968: switch (curi->mnemo) {
969: case i_OR:
970: case i_AND:
971: case i_EOR:
1.1.1.2 root 972: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
973: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
974: printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^');
1.1.1.15! root 975: printf("\trefill_prefetch (m68k_getpc(), 2);\n"); // FIXME [NP] For Operation Clean Streets - Automation 168, need better prefetch emulation
1.1.1.2 root 976: genflags (flag_logical, curi->size, "src", "", "");
977: genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
978: if(curi->size==sz_long && curi->dmode==Dreg)
979: {
980: insn_n_cycles += 2;
981: if(curi->smode==Dreg || curi->smode==Areg || (curi->smode>=imm && curi->smode<=immi))
982: insn_n_cycles += 2;
983: }
984: #if 0
985: /* Output the CPU cycles: */
986: fprintf(stderr,"MOVE, size %i: ",curi->size);
987: fprintf(stderr," %s ->",amodenames[curi->smode]);
988: fprintf(stderr," %s ",amodenames[curi->dmode]);
989: fprintf(stderr," Cycles: %i\n",insn_n_cycles);
990: #endif
991: break;
1.1 root 992: case i_ORSR:
993: case i_EORSR:
1.1.1.2 root 994: printf ("\tMakeSR();\n");
995: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
996: if (curi->size == sz_byte) {
997: printf ("\tsrc &= 0xFF;\n");
998: }
999: printf ("\tregs.sr %c= src;\n", curi->mnemo == i_EORSR ? '^' : '|');
1000: printf ("\tMakeFromSR();\n");
1001: insn_n_cycles = 20;
1002: break;
1.1 root 1003: case i_ANDSR:
1.1.1.2 root 1004: printf ("\tMakeSR();\n");
1005: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1006: if (curi->size == sz_byte) {
1007: printf ("\tsrc |= 0xFF00;\n");
1008: }
1009: printf ("\tregs.sr &= src;\n");
1010: printf ("\tMakeFromSR();\n");
1011: insn_n_cycles = 20;
1012: break;
1.1 root 1013: case i_SUB:
1014: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1015: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1016: start_brace ();
1017: genflags (flag_sub, curi->size, "newv", "src", "dst");
1018: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1019: if(curi->size==sz_long && curi->dmode==Dreg)
1020: {
1021: insn_n_cycles += 2;
1022: if(curi->smode==Dreg || curi->smode==Areg || (curi->smode>=imm && curi->smode<=immi))
1023: insn_n_cycles += 2;
1024: }
1.1 root 1025: break;
1026: case i_SUBA:
1027: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1028: genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1029: start_brace ();
1030: printf ("\tuae_u32 newv = dst - src;\n");
1031: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1.1.1.2 root 1032: if(curi->size==sz_long && curi->smode!=Dreg && curi->smode!=Areg && !(curi->smode>=imm && curi->smode<=immi))
1033: insn_n_cycles += 2;
1034: else
1035: insn_n_cycles += 4;
1.1 root 1036: break;
1037: case i_SUBX:
1038: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1039: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1040: start_brace ();
1041: printf ("\tuae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);\n");
1042: genflags (flag_subx, curi->size, "newv", "src", "dst");
1043: genflags (flag_zn, curi->size, "newv", "", "");
1044: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1045: if(curi->smode==Dreg && curi->size==sz_long)
1046: insn_n_cycles=8;
1047: if(curi->smode==Apdi)
1048: {
1049: if(curi->size==sz_long)
1050: insn_n_cycles=30;
1051: else
1052: insn_n_cycles=18;
1053: }
1.1 root 1054: break;
1055: case i_SBCD:
1056: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1057: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1058: start_brace ();
1059: printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
1060: printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n");
1.1.1.4 root 1061: printf ("\tuae_u16 newv, tmp_newv;\n");
1062: printf ("\tint bcd = 0;\n");
1063: printf ("\tnewv = tmp_newv = newv_hi + newv_lo;\n");
1064: printf ("\tif (newv_lo & 0xF0) { newv -= 6; bcd = 6; };\n");
1065: printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n");
1066: printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG ? 1 : 0)) & 0x300) > 0xFF);\n");
1.1 root 1067: duplicate_carry ();
1068: genflags (flag_zn, curi->size, "newv", "", "");
1.1.1.4 root 1069: printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n");
1.1 root 1070: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.4 root 1071: if(curi->smode==Dreg) insn_n_cycles=6;
1072: if(curi->smode==Apdi) insn_n_cycles=18;
1.1 root 1073: break;
1074: case i_ADD:
1075: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1076: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1077: start_brace ();
1.1.1.8 root 1078: printf("\trefill_prefetch (m68k_getpc(), 2);\n"); // FIXME [NP] For Transbeauce 2 demo, need better prefetch emulation
1.1 root 1079: genflags (flag_add, curi->size, "newv", "src", "dst");
1080: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1081: if(curi->size==sz_long && curi->dmode==Dreg)
1082: {
1083: insn_n_cycles += 2;
1084: if(curi->smode==Dreg || curi->smode==Areg || (curi->smode>=imm && curi->smode<=immi))
1085: insn_n_cycles += 2;
1086: }
1.1 root 1087: break;
1088: case i_ADDA:
1089: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1090: genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1091: start_brace ();
1092: printf ("\tuae_u32 newv = dst + src;\n");
1093: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1.1.1.2 root 1094: if(curi->size==sz_long && curi->smode!=Dreg && curi->smode!=Areg && !(curi->smode>=imm && curi->smode<=immi))
1095: insn_n_cycles += 2;
1096: else
1097: insn_n_cycles += 4;
1.1 root 1098: break;
1099: case i_ADDX:
1100: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1101: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1102: start_brace ();
1103: printf ("\tuae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);\n");
1104: genflags (flag_addx, curi->size, "newv", "src", "dst");
1105: genflags (flag_zn, curi->size, "newv", "", "");
1106: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1107: if(curi->smode==Dreg && curi->size==sz_long)
1108: insn_n_cycles=8;
1109: if(curi->smode==Apdi)
1110: {
1111: if(curi->size==sz_long)
1112: insn_n_cycles=30;
1113: else
1114: insn_n_cycles=18;
1115: }
1.1 root 1116: break;
1117: case i_ABCD:
1118: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1119: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1120: start_brace ();
1121: printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n");
1122: printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n");
1.1.1.4 root 1123: printf ("\tuae_u16 newv, tmp_newv;\n");
1.1 root 1124: printf ("\tint cflg;\n");
1.1.1.4 root 1125: printf ("\tnewv = tmp_newv = newv_hi + newv_lo;");
1126: printf ("\tif (newv_lo > 9) { newv += 6; }\n");
1127: printf ("\tcflg = (newv & 0x3F0) > 0x90;\n");
1128: printf ("\tif (cflg) newv += 0x60;\n");
1.1 root 1129: printf ("\tSET_CFLG (cflg);\n");
1130: duplicate_carry ();
1131: genflags (flag_zn, curi->size, "newv", "", "");
1.1.1.4 root 1132: printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n");
1.1 root 1133: genastore ("newv", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.4 root 1134: if(curi->smode==Dreg) insn_n_cycles=6;
1135: if(curi->smode==Apdi) insn_n_cycles=18;
1.1 root 1136: break;
1137: case i_NEG:
1138: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1139: start_brace ();
1140: genflags (flag_sub, curi->size, "dst", "src", "0");
1141: genastore ("dst", curi->smode, "srcreg", curi->size, "src");
1.1.1.2 root 1142: if(curi->size==sz_long && curi->smode==Dreg) insn_n_cycles += 2;
1.1 root 1143: break;
1144: case i_NEGX:
1145: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1146: start_brace ();
1147: printf ("\tuae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);\n");
1148: genflags (flag_subx, curi->size, "newv", "src", "0");
1149: genflags (flag_zn, curi->size, "newv", "", "");
1150: genastore ("newv", curi->smode, "srcreg", curi->size, "src");
1.1.1.2 root 1151: if(curi->size==sz_long && curi->smode==Dreg) insn_n_cycles += 2;
1.1 root 1152: break;
1153: case i_NBCD:
1154: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1155: start_brace ();
1156: printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);\n");
1157: printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n");
1158: printf ("\tuae_u16 newv;\n");
1159: printf ("\tint cflg;\n");
1.1.1.4 root 1160: printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n");
1161: printf ("\tnewv = newv_hi + newv_lo;");
1162: printf ("\tcflg = (newv & 0x1F0) > 0x90;\n");
1163: printf ("\tif (cflg) newv -= 0x60;\n");
1.1 root 1164: printf ("\tSET_CFLG (cflg);\n");
1165: duplicate_carry();
1166: genflags (flag_zn, curi->size, "newv", "", "");
1167: genastore ("newv", curi->smode, "srcreg", curi->size, "src");
1.1.1.4 root 1168: if(curi->smode==Dreg) insn_n_cycles += 2;
1.1 root 1169: break;
1170: case i_CLR:
1171: genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
1.1.1.8 root 1172:
1173: /* [NP] CLR does a read before the write only on 68000 */
1174: /* but there's no cycle penalty for doing the read */
1175: if ( curi->smode != Dreg ) // only if destination is memory
1176: {
1177: if (curi->size==sz_byte)
1178: printf ("\tuae_s8 src = get_byte(srca);\n");
1179: else if (curi->size==sz_word)
1180: printf ("\tuae_s16 src = get_word(srca);\n");
1181: else if (curi->size==sz_long)
1182: printf ("\tuae_s32 src = get_long(srca);\n");
1183: }
1184:
1.1 root 1185: genflags (flag_logical, curi->size, "0", "", "");
1186: genastore ("0", curi->smode, "srcreg", curi->size, "src");
1.1.1.2 root 1187: if(curi->size==sz_long)
1.1.1.3 root 1188: {
1.1.1.2 root 1189: if(curi->smode==Dreg)
1190: insn_n_cycles += 2;
1191: else
1192: insn_n_cycles += 4;
1.1.1.3 root 1193: }
1.1.1.2 root 1194: if(curi->smode!=Dreg)
1195: insn_n_cycles += 4;
1.1 root 1196: break;
1197: case i_NOT:
1198: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1199: start_brace ();
1200: printf ("\tuae_u32 dst = ~src;\n");
1201: genflags (flag_logical, curi->size, "dst", "", "");
1202: genastore ("dst", curi->smode, "srcreg", curi->size, "src");
1.1.1.2 root 1203: if(curi->size==sz_long && curi->smode==Dreg) insn_n_cycles += 2;
1.1 root 1204: break;
1205: case i_TST:
1206: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1207: genflags (flag_logical, curi->size, "src", "", "");
1208: break;
1209: case i_BTST:
1210: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1211: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1212: if (curi->size == sz_byte)
1213: printf ("\tsrc &= 7;\n");
1214: else
1215: printf ("\tsrc &= 31;\n");
1216: printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
1.1.1.2 root 1217: if(curi->dmode==Dreg) insn_n_cycles += 2;
1.1 root 1218: break;
1219: case i_BCHG:
1220: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1221: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1222: if (curi->size == sz_byte)
1223: printf ("\tsrc &= 7;\n");
1224: else
1225: printf ("\tsrc &= 31;\n");
1226: printf ("\tdst ^= (1 << src);\n");
1227: printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n");
1228: genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1229: if(curi->dmode==Dreg) insn_n_cycles += 4;
1.1 root 1230: break;
1231: case i_BCLR:
1232: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1233: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1234: if (curi->size == sz_byte)
1235: printf ("\tsrc &= 7;\n");
1236: else
1237: printf ("\tsrc &= 31;\n");
1238: printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
1239: printf ("\tdst &= ~(1 << src);\n");
1240: genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1241: if(curi->dmode==Dreg) insn_n_cycles += 6;
1.1.1.8 root 1242: /* [NP] BCLR #n,Dx takes 12 cycles instead of 14 if n<16 */
1243: if((curi->smode==imm1) && (curi->dmode==Dreg))
1244: printf ("\tif ( src < 16 ) { m68k_incpc(4); return 12; }\n");
1245: /* [NP] BCLR Dy,Dx takes 8 cycles instead of 10 if Dy<16 */
1246: if((curi->smode==Dreg) && (curi->dmode==Dreg))
1247: printf ("\tif ( src < 16 ) { m68k_incpc(2); return 8; }\n");
1.1 root 1248: break;
1249: case i_BSET:
1250: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1251: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1252: if (curi->size == sz_byte)
1253: printf ("\tsrc &= 7;\n");
1254: else
1255: printf ("\tsrc &= 31;\n");
1256: printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n");
1257: printf ("\tdst |= (1 << src);\n");
1258: genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1259: if(curi->dmode==Dreg) insn_n_cycles += 4;
1.1 root 1260: break;
1261: case i_CMPM:
1262: case i_CMP:
1263: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1264: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1265: start_brace ();
1266: genflags (flag_cmp, curi->size, "newv", "src", "dst");
1.1.1.2 root 1267: if(curi->size==sz_long && curi->dmode==Dreg)
1268: insn_n_cycles += 2;
1.1 root 1269: break;
1270: case i_CMPA:
1271: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1272: genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1273: start_brace ();
1274: genflags (flag_cmp, sz_long, "newv", "src", "dst");
1.1.1.2 root 1275: insn_n_cycles += 2;
1.1 root 1276: break;
1277: /* The next two are coded a little unconventional, but they are doing
1278: * weird things... */
1279: case i_MVPRM:
1280: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1281:
1282: printf ("\tuaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ());
1283: if (curi->size == sz_word) {
1.1.1.14 root 1284: printf ("\tMovepByteNbr=1; put_byte(memp, src >> 8); MovepByteNbr=2; put_byte(memp + 2, src);\n");
1.1 root 1285: } else {
1.1.1.14 root 1286: printf ("\tMovepByteNbr=1; put_byte(memp, src >> 24); MovepByteNbr=2; put_byte(memp + 2, src >> 16);\n");
1287: printf ("\tMovepByteNbr=3; put_byte(memp + 4, src >> 8); MovepByteNbr=4; put_byte(memp + 6, src);\n");
1.1 root 1288: }
1.1.1.2 root 1289: if(curi->size==sz_long) insn_n_cycles=24; else insn_n_cycles=16;
1.1 root 1290: break;
1291: case i_MVPMR:
1292: printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ());
1293: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1294: if (curi->size == sz_word) {
1295: printf ("\tuae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);\n");
1296: } else {
1297: printf ("\tuae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)\n");
1298: printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n");
1299: }
1300: genastore ("val", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1301: if(curi->size==sz_long) insn_n_cycles=24; else insn_n_cycles=16;
1.1 root 1302: break;
1303: case i_MOVE:
1304: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1305: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1.1.1.8 root 1306:
1307: /* [NP] genamode counts 2 cycles if dest is -(An), this is wrong. */
1308: /* For move dest (An), (An)+ and -(An) take the same time */
1309: /* (for other instr, dest -(An) really takes 2 cycles more) */
1310: if ( curi->dmode == Apdi )
1311: insn_n_cycles -= 2; /* correct the wrong cycle count for -(An) */
1312:
1.1 root 1313: genflags (flag_logical, curi->size, "src", "", "");
1314: genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
1315: break;
1316: case i_MOVEA:
1317: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1318: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1319: if (curi->size == sz_word) {
1320: printf ("\tuae_u32 val = (uae_s32)(uae_s16)src;\n");
1321: } else {
1322: printf ("\tuae_u32 val = src;\n");
1323: }
1324: genastore ("val", curi->dmode, "dstreg", sz_long, "dst");
1325: break;
1.1.1.2 root 1326: case i_MVSR2: /* Move from SR */
1.1 root 1327: genamode (curi->smode, "srcreg", sz_word, "src", 2, 0);
1328: printf ("\tMakeSR();\n");
1329: if (curi->size == sz_byte)
1330: genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src");
1331: else
1332: genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src");
1.1.1.2 root 1333: if (curi->smode==Dreg) insn_n_cycles += 2; else insn_n_cycles += 4;
1.1 root 1334: break;
1.1.1.2 root 1335: case i_MV2SR: /* Move to SR */
1.1 root 1336: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
1337: if (curi->size == sz_byte)
1338: printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n");
1339: else {
1340: printf ("\tregs.sr = src;\n");
1341: }
1342: printf ("\tMakeFromSR();\n");
1.1.1.2 root 1343: insn_n_cycles += 8;
1.1 root 1344: break;
1345: case i_SWAP:
1346: genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
1347: start_brace ();
1348: printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n");
1349: genflags (flag_logical, sz_long, "dst", "", "");
1350: genastore ("dst", curi->smode, "srcreg", sz_long, "src");
1351: break;
1352: case i_EXG:
1353: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1354: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1355: genastore ("dst", curi->smode, "srcreg", curi->size, "src");
1356: genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1357: insn_n_cycles = 6;
1.1 root 1358: break;
1359: case i_EXT:
1360: genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
1361: start_brace ();
1362: switch (curi->size) {
1363: case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break;
1364: case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break;
1365: case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break;
1366: default: abort ();
1367: }
1368: genflags (flag_logical,
1369: curi->size == sz_word ? sz_word : sz_long, "dst", "", "");
1370: genastore ("dst", curi->smode, "srcreg",
1371: curi->size == sz_word ? sz_word : sz_long, "src");
1372: break;
1373: case i_MVMEL:
1374: genmovemel (opcode);
1375: break;
1376: case i_MVMLE:
1377: genmovemle (opcode);
1378: break;
1379: case i_TRAP:
1380: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1381: sync_m68k_pc ();
1.1.1.12 root 1382: printf ("\tException(src+32,0,M68000_EXC_SRC_CPU);\n");
1.1 root 1383: m68k_pc_offset = 0;
1384: break;
1385: case i_MVR2USP:
1386: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1387: printf ("\tregs.usp = src;\n");
1388: break;
1389: case i_MVUSP2R:
1390: genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
1391: genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src");
1392: break;
1393: case i_RESET:
1394: printf ("\tcustomreset();\n");
1.1.1.2 root 1395: insn_n_cycles = 132; /* I am not so sure about this!? - Thothy */
1.1 root 1396: break;
1397: case i_NOP:
1398: break;
1399: case i_STOP:
1400: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1401: printf ("\tregs.sr = src;\n");
1402: printf ("\tMakeFromSR();\n");
1403: printf ("\tm68k_setstopped(1);\n");
1.1.1.2 root 1404: insn_n_cycles = 4;
1.1 root 1405: break;
1406: case i_RTE:
1407: if (cpu_level == 0) {
1408: genamode (Aipi, "7", sz_word, "sr", 1, 0);
1409: genamode (Aipi, "7", sz_long, "pc", 1, 0);
1410: printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n");
1411: fill_prefetch_0 ();
1412: printf ("\tMakeFromSR();\n");
1413: } else {
1414: int old_brace_level = n_braces;
1415: if (next_cpu_level < 0)
1416: next_cpu_level = 0;
1417: printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n");
1418: genamode (Aipi, "7", sz_word, "sr", 1, 0);
1419: genamode (Aipi, "7", sz_long, "pc", 1, 0);
1420: genamode (Aipi, "7", sz_word, "format", 1, 0);
1421: printf ("\tnewsr = sr; newpc = pc;\n");
1422: printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n");
1423: printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n");
1424: printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n");
1425: printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n");
1426: printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n");
1427: printf ("\telse if ((format & 0xF000) == 0xa000) { m68k_areg(regs, 7) += 24; break; }\n");
1428: printf ("\telse if ((format & 0xF000) == 0xb000) { m68k_areg(regs, 7) += 84; break; }\n");
1.1.1.12 root 1429: printf ("\telse { Exception(14,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1.1 root 1430: printf ("\tregs.sr = newsr; MakeFromSR();\n}\n");
1431: pop_braces (old_brace_level);
1432: printf ("\tregs.sr = newsr; MakeFromSR();\n");
1433: printf ("\tm68k_setpc_rte(newpc);\n");
1434: fill_prefetch_0 ();
1435: need_endlabel = 1;
1436: }
1437: /* PC is set and prefetch filled. */
1438: m68k_pc_offset = 0;
1.1.1.2 root 1439: insn_n_cycles = 20;
1.1 root 1440: break;
1441: case i_RTD:
1442: genamode (Aipi, "7", sz_long, "pc", 1, 0);
1443: genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0);
1444: printf ("\tm68k_areg(regs, 7) += offs;\n");
1445: printf ("\tm68k_setpc_rte(pc);\n");
1446: fill_prefetch_0 ();
1447: /* PC is set and prefetch filled. */
1448: m68k_pc_offset = 0;
1449: break;
1450: case i_LINK:
1451: genamode (Apdi, "7", sz_long, "old", 2, 0);
1452: genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
1453: genastore ("src", Apdi, "7", sz_long, "old");
1454: genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
1455: genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
1456: printf ("\tm68k_areg(regs, 7) += offs;\n");
1457: break;
1458: case i_UNLK:
1459: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1460: printf ("\tm68k_areg(regs, 7) = src;\n");
1461: genamode (Aipi, "7", sz_long, "old", 1, 0);
1462: genastore ("old", curi->smode, "srcreg", curi->size, "src");
1463: break;
1464: case i_RTS:
1465: printf ("\tm68k_do_rts();\n");
1466: fill_prefetch_0 ();
1467: m68k_pc_offset = 0;
1.1.1.2 root 1468: insn_n_cycles = 16;
1.1 root 1469: break;
1470: case i_TRAPV:
1471: sync_m68k_pc ();
1.1.1.12 root 1472: printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc(),M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1.1 root 1473: need_endlabel = 1;
1474: break;
1475: case i_RTR:
1476: printf ("\tMakeSR();\n");
1477: genamode (Aipi, "7", sz_word, "sr", 1, 0);
1478: genamode (Aipi, "7", sz_long, "pc", 1, 0);
1479: printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
1480: printf ("\tregs.sr |= sr; m68k_setpc(pc);\n");
1481: fill_prefetch_0 ();
1482: printf ("\tMakeFromSR();\n");
1483: m68k_pc_offset = 0;
1.1.1.2 root 1484: insn_n_cycles = 20;
1.1 root 1485: break;
1486: case i_JSR:
1487: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1.1.1.13 root 1488: printf ("\tuaecptr oldpc = m68k_getpc () + %d;\n", m68k_pc_offset);
1489: if (using_exception_3) {
1490: printf ("\tif (srca & 1) {\n");
1491: printf ("\t\tlast_addr_for_exception_3 = oldpc;\n");
1492: printf ("\t\tlast_fault_for_exception_3 = srca;\n");
1493: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1494: printf ("\t}\n");
1495: need_endlabel = 1;
1496: }
1.1 root 1497: printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset);
1498: fill_prefetch_0 ();
1499: m68k_pc_offset = 0;
1.1.1.2 root 1500: switch(curi->smode)
1501: {
1502: case Aind: insn_n_cycles=16; break;
1503: case Ad16: insn_n_cycles=18; break;
1504: case Ad8r: insn_n_cycles=22; break;
1505: case absw: insn_n_cycles=18; break;
1506: case absl: insn_n_cycles=20; break;
1507: case PC16: insn_n_cycles=18; break;
1508: case PC8r: insn_n_cycles=22; break;
1509: }
1.1 root 1510: break;
1511: case i_JMP:
1512: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1.1.1.13 root 1513: if (using_exception_3) {
1514: printf ("\tif (srca & 1) {\n");
1.1.1.15! root 1515: printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + %d;\n" , m68k_pc_offset); // [NP] last_addr is not pc+6
1.1.1.13 root 1516: printf ("\t\tlast_fault_for_exception_3 = srca;\n");
1517: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1518: printf ("\t}\n");
1519: need_endlabel = 1;
1520: }
1.1 root 1521: printf ("\tm68k_setpc(srca);\n");
1522: fill_prefetch_0 ();
1523: m68k_pc_offset = 0;
1.1.1.2 root 1524: switch(curi->smode)
1525: {
1526: case Aind: insn_n_cycles=8; break;
1527: case Ad16: insn_n_cycles=10; break;
1528: case Ad8r: insn_n_cycles=14; break;
1529: case absw: insn_n_cycles=10; break;
1530: case absl: insn_n_cycles=12; break;
1531: case PC16: insn_n_cycles=10; break;
1532: case PC8r: insn_n_cycles=14; break;
1533: }
1.1 root 1534: break;
1535: case i_BSR:
1536: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1537: printf ("\tuae_s32 s = (uae_s32)src + 2;\n");
1538: if (using_exception_3) {
1539: printf ("\tif (src & 1) {\n");
1.1.1.13 root 1540: printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); // [NP] FIXME should be +4, not +2 (same as DBcc) ?
1.1 root 1541: printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + s;\n");
1.1.1.12 root 1542: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1.1 root 1543: printf ("\t}\n");
1544: need_endlabel = 1;
1545: }
1546: printf ("\tm68k_do_bsr(m68k_getpc() + %d, s);\n", m68k_pc_offset);
1547: fill_prefetch_0 ();
1548: m68k_pc_offset = 0;
1.1.1.2 root 1549: insn_n_cycles = 18;
1.1 root 1550: break;
1551: case i_Bcc:
1552: if (curi->size == sz_long) {
1553: if (cpu_level < 2) {
1554: printf ("\tm68k_incpc(2);\n");
1555: printf ("\tif (!cctrue(%d)) goto %s;\n", curi->cc, endlabelstr);
1556: printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
1557: printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 1;\n");
1.1.1.12 root 1558: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1.1 root 1559: need_endlabel = 1;
1560: } else {
1561: if (next_cpu_level < 1)
1562: next_cpu_level = 1;
1563: }
1564: }
1565: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1566: printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc);
1567: if (using_exception_3) {
1568: printf ("\tif (src & 1) {\n");
1.1.1.8 root 1569: printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); // [NP] FIXME should be +4, not +2 (same as DBcc) ?
1.1 root 1570: printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)src;\n");
1.1.1.12 root 1571: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1.1 root 1572: printf ("\t}\n");
1573: need_endlabel = 1;
1574: }
1575: printf ("\tm68k_incpc ((uae_s32)src + 2);\n");
1576: fill_prefetch_0 ();
1.1.1.2 root 1577: printf ("\treturn 10;\n");
1.1 root 1578: printf ("didnt_jump:;\n");
1579: need_endlabel = 1;
1.1.1.2 root 1580: insn_n_cycles = (curi->size == sz_byte) ? 8 : 12;
1.1 root 1581: break;
1582: case i_LEA:
1583: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1584: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1585: genastore ("srca", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.7 root 1586: /* Set correct cycles: According to the M68K User Manual, LEA takes 12
1587: * cycles in Ad8r and PC8r mode, but it takes 14 (or 16) cycles on a real ST: */
1588: if (curi->smode == Ad8r || curi->smode == PC8r)
1589: insn_n_cycles = 14;
1.1 root 1590: break;
1591: case i_PEA:
1592: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1593: genamode (Apdi, "7", sz_long, "dst", 2, 0);
1594: genastore ("srca", Apdi, "7", sz_long, "dst");
1.1.1.7 root 1595: /* Set correct cycles: */
1.1.1.2 root 1596: switch(curi->smode)
1597: {
1598: case Aind: insn_n_cycles=12; break;
1599: case Ad16: insn_n_cycles=16; break;
1.1.1.7 root 1600: /* Note: according to the M68K User Manual, PEA takes 20 cycles for
1601: * the Ad8r mode, but on a real ST, it takes 22 (or 24) cycles! */
1602: case Ad8r: insn_n_cycles=22; break;
1.1.1.2 root 1603: case absw: insn_n_cycles=16; break;
1604: case absl: insn_n_cycles=20; break;
1605: case PC16: insn_n_cycles=16; break;
1.1.1.7 root 1606: /* Note: PEA with PC8r takes 20 cycles according to the User Manual,
1607: * but it takes 22 (or 24) cycles on a real ST: */
1608: case PC8r: insn_n_cycles=22; break;
1.1.1.2 root 1609: }
1.1 root 1610: break;
1611: case i_DBcc:
1612: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1613: genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
1614:
1.1.1.2 root 1615: printf ("\tif (!cctrue(%d)) {\n\t", curi->cc);
1.1 root 1616: genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src");
1617:
1618: printf ("\t\tif (src) {\n");
1619: if (using_exception_3) {
1620: printf ("\t\t\tif (offs & 1) {\n");
1.1.1.8 root 1621: printf ("\t\t\tlast_addr_for_exception_3 = m68k_getpc() + 2 + 2;\n"); // [NP] last_addr is pc+4, not pc+2
1.1 root 1622: printf ("\t\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)offs + 2;\n");
1.1.1.12 root 1623: printf ("\t\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1.1 root 1624: printf ("\t\t}\n");
1625: need_endlabel = 1;
1626: }
1627: printf ("\t\t\tm68k_incpc((uae_s32)offs + 2);\n");
1628: fill_prefetch_0 ();
1.1.1.2 root 1629: printf ("\t\t\treturn 10;\n");
1630: printf ("\t\t} else {\n\t\t\t");
1631: {
1632: int tmp_offset = m68k_pc_offset;
1633: sync_m68k_pc(); /* not so nice to call it here... */
1634: m68k_pc_offset = tmp_offset;
1635: }
1636: printf ("\t\t\treturn 14;\n");
1637: printf ("\t\t}\n");
1.1 root 1638: printf ("\t}\n");
1639: insn_n_cycles = 12;
1640: need_endlabel = 1;
1641: break;
1642: case i_Scc:
1643: genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
1644: start_brace ();
1645: printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc);
1646: genastore ("val", curi->smode, "srcreg", curi->size, "src");
1.1.1.8 root 1647: if (curi->smode!=Dreg) insn_n_cycles += 4;
1648: else
1649: { /* [NP] if result is TRUE, we return 6 instead of 4 */
1650: printf ("\tif (val) { m68k_incpc(2) ; return 4+2; }\n");
1651: }
1.1 root 1652: break;
1653: case i_DIVU:
1654: printf ("\tuaecptr oldpc = m68k_getpc();\n");
1655: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
1656: genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1657: sync_m68k_pc ();
1658: /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends
1659: * on this (actually, it's doing a DIVS). */
1.1.1.12 root 1660: printf ("\tif (src == 0) { SET_VFLG (0); Exception (5, oldpc,M68000_EXC_SRC_CPU); goto %s; } else {\n", endlabelstr);
1.1 root 1661: printf ("\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n");
1662: printf ("\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n");
1663: /* The N flag appears to be set each time there is an overflow.
1664: * Weird. */
1665: printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
1666: genflags (flag_logical, sz_word, "newv", "", "");
1667: printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
1668: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1669: printf ("\t}\n");
1670: printf ("\t}\n");
1.1.1.8 root 1671: // insn_n_cycles += 136;
1672: printf ("\tretcycles = getDivu68kCycles((uae_u32)dst, (uae_u16)src);\n");
1673: sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
1.1 root 1674: need_endlabel = 1;
1675: break;
1676: case i_DIVS:
1677: printf ("\tuaecptr oldpc = m68k_getpc();\n");
1678: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
1679: genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1680: sync_m68k_pc ();
1.1.1.12 root 1681: printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc,M68000_EXC_SRC_CPU); goto %s; } else {\n", endlabelstr);
1.1 root 1682: printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
1683: printf ("\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n");
1684: printf ("\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
1685: printf ("\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n");
1686: genflags (flag_logical, sz_word, "newv", "", "");
1687: printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
1688: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1689: printf ("\t}\n");
1690: printf ("\t}\n");
1.1.1.8 root 1691: // insn_n_cycles += 154;
1692: printf ("\tretcycles = getDivs68kCycles((uae_s32)dst, (uae_s16)src);\n");
1693: sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
1.1 root 1694: need_endlabel = 1;
1695: break;
1696: case i_MULU:
1697: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
1698: genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
1699: start_brace ();
1700: printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n");
1701: genflags (flag_logical, sz_long, "newv", "", "");
1702: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1.1.1.8 root 1703: /* [NP] number of cycles is 38 + 2n + ea time ; n is the number of 1 bits in src */
1704: insn_n_cycles += 38-4; /* insn_n_cycles is already initialized to 4 instead of 0 */
1705: printf ("\twhile (src) { if (src & 1) retcycles++; src = (uae_u16)src >> 1; }\n");
1706: sprintf(exactCpuCycles," return (%i+retcycles*2);", insn_n_cycles);
1.1 root 1707: break;
1708: case i_MULS:
1709: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
1710: genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
1711: start_brace ();
1712: printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n");
1.1.1.8 root 1713: printf ("\tuae_u32 src2;\n");
1.1 root 1714: genflags (flag_logical, sz_long, "newv", "", "");
1715: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1.1.1.8 root 1716: /* [NP] number of cycles is 38 + 2n + ea time ; n is the number of 01 or 10 patterns in src expanded to 17 bits */
1717: insn_n_cycles += 38-4; /* insn_n_cycles is already initialized to 4 instead of 0 */
1718: printf ("\tsrc2 = ((uae_u32)src) << 1;\n");
1719: printf ("\twhile (src2) { if ( ( (src2 & 3) == 1 ) || ( (src2 & 3) == 2 ) ) retcycles++; src2 >>= 1; }\n");
1720: sprintf(exactCpuCycles," return (%i+retcycles*2);", insn_n_cycles);
1.1 root 1721: break;
1722: case i_CHK:
1723: printf ("\tuaecptr oldpc = m68k_getpc();\n");
1724: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1725: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1.1.1.8 root 1726: sync_m68k_pc ();
1.1.1.12 root 1727: printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1728: printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1.1 root 1729: need_endlabel = 1;
1.1.1.2 root 1730: insn_n_cycles += 6;
1.1 root 1731: break;
1732:
1733: case i_CHK2:
1734: printf ("\tuaecptr oldpc = m68k_getpc();\n");
1735: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
1736: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1737: printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n");
1738: switch (curi->size) {
1739: case sz_byte:
1740: printf ("\tlower=(uae_s32)(uae_s8)get_byte(dsta); upper = (uae_s32)(uae_s8)get_byte(dsta+1);\n");
1741: printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s8)reg;\n");
1742: break;
1743: case sz_word:
1744: printf ("\tlower=(uae_s32)(uae_s16)get_word(dsta); upper = (uae_s32)(uae_s16)get_word(dsta+2);\n");
1745: printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s16)reg;\n");
1746: break;
1747: case sz_long:
1748: printf ("\tlower=get_long(dsta); upper = get_long(dsta+4);\n");
1749: break;
1750: default:
1751: abort ();
1752: }
1753: printf ("\tSET_ZFLG (upper == reg || lower == reg);\n");
1754: printf ("\tSET_CFLG (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n");
1.1.1.8 root 1755: sync_m68k_pc ();
1.1.1.12 root 1756: printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n}\n", endlabelstr);
1.1 root 1757: need_endlabel = 1;
1758: break;
1759:
1760: case i_ASR:
1761: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1762: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1763: start_brace ();
1764: switch (curi->size) {
1765: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1766: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1767: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1768: default: abort ();
1769: }
1770: printf ("\tuae_u32 sign = (%s & val) >> %d;\n", cmask (curi->size), bit_size (curi->size) - 1);
1771: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1772: printf ("\tretcycles = cnt;\n");
1.1 root 1773: printf ("\tCLEAR_CZNV;\n");
1774: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
1775: printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size));
1776: printf ("\t\tSET_CFLG (sign);\n");
1777: duplicate_carry ();
1778: if (source_is_imm1_8 (curi))
1779: printf ("\t} else {\n");
1780: else
1781: printf ("\t} else if (cnt > 0) {\n");
1782: printf ("\t\tval >>= cnt - 1;\n");
1783: printf ("\t\tSET_CFLG (val & 1);\n");
1784: duplicate_carry ();
1785: printf ("\t\tval >>= 1;\n");
1786: printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n",
1787: bit_mask (curi->size),
1788: bit_size (curi->size));
1789: printf ("\t\tval &= %s;\n", bit_mask (curi->size));
1790: printf ("\t}\n");
1791: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1792: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1793: if(curi->size==sz_long)
1794: strcpy(exactCpuCycles," return (8+retcycles*2);");
1795: else
1796: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1797: break;
1798: case i_ASL:
1799: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1800: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1801: start_brace ();
1802: switch (curi->size) {
1803: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1804: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1805: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1806: default: abort ();
1807: }
1808: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1809: printf ("\tretcycles = cnt;\n");
1.1 root 1810: printf ("\tCLEAR_CZNV;\n");
1811: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
1812: printf ("\t\tSET_VFLG (val != 0);\n");
1813: printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
1814: bit_size (curi->size));
1815: duplicate_carry ();
1816: printf ("\t\tval = 0;\n");
1817: if (source_is_imm1_8 (curi))
1818: printf ("\t} else {\n");
1819: else
1820: printf ("\t} else if (cnt > 0) {\n");
1821: printf ("\t\tuae_u32 mask = (%s << (%d - cnt)) & %s;\n",
1822: bit_mask (curi->size),
1823: bit_size (curi->size) - 1,
1824: bit_mask (curi->size));
1825: printf ("\t\tSET_VFLG ((val & mask) != mask && (val & mask) != 0);\n");
1826: printf ("\t\tval <<= cnt - 1;\n");
1827: printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
1828: duplicate_carry ();
1829: printf ("\t\tval <<= 1;\n");
1830: printf ("\t\tval &= %s;\n", bit_mask (curi->size));
1831: printf ("\t}\n");
1832: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1833: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1834: if(curi->size==sz_long)
1835: strcpy(exactCpuCycles," return (8+retcycles*2);");
1836: else
1837: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1838: break;
1839: case i_LSR:
1840: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1841: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1842: start_brace ();
1843: switch (curi->size) {
1844: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1845: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1846: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1847: default: abort ();
1848: }
1849: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1850: printf ("\tretcycles = cnt;\n");
1.1 root 1851: printf ("\tCLEAR_CZNV;\n");
1852: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
1853: printf ("\t\tSET_CFLG ((cnt == %d) & (val >> %d));\n",
1854: bit_size (curi->size), bit_size (curi->size) - 1);
1855: duplicate_carry ();
1856: printf ("\t\tval = 0;\n");
1857: if (source_is_imm1_8 (curi))
1858: printf ("\t} else {\n");
1859: else
1860: printf ("\t} else if (cnt > 0) {\n");
1861: printf ("\t\tval >>= cnt - 1;\n");
1862: printf ("\t\tSET_CFLG (val & 1);\n");
1863: duplicate_carry ();
1864: printf ("\t\tval >>= 1;\n");
1865: printf ("\t}\n");
1866: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1867: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1868: if(curi->size==sz_long)
1869: strcpy(exactCpuCycles," return (8+retcycles*2);");
1870: else
1871: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1872: break;
1873: case i_LSL:
1874: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1875: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1876: start_brace ();
1877: switch (curi->size) {
1878: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1879: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1880: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1881: default: abort ();
1882: }
1883: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1884: printf ("\tretcycles = cnt;\n");
1.1 root 1885: printf ("\tCLEAR_CZNV;\n");
1886: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
1887: printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
1888: bit_size (curi->size));
1889: duplicate_carry ();
1890: printf ("\t\tval = 0;\n");
1891: if (source_is_imm1_8 (curi))
1892: printf ("\t} else {\n");
1893: else
1894: printf ("\t} else if (cnt > 0) {\n");
1895: printf ("\t\tval <<= (cnt - 1);\n");
1896: printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
1897: duplicate_carry ();
1898: printf ("\t\tval <<= 1;\n");
1899: printf ("\tval &= %s;\n", bit_mask (curi->size));
1900: printf ("\t}\n");
1901: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1902: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1903: if(curi->size==sz_long)
1904: strcpy(exactCpuCycles," return (8+retcycles*2);");
1905: else
1906: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1907: break;
1908: case i_ROL:
1909: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1910: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1911: start_brace ();
1912: switch (curi->size) {
1913: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1914: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1915: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1916: default: abort ();
1917: }
1918: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1919: printf ("\tretcycles = cnt;\n");
1.1 root 1920: printf ("\tCLEAR_CZNV;\n");
1921: if (source_is_imm1_8 (curi))
1922: printf ("{");
1923: else
1924: printf ("\tif (cnt > 0) {\n");
1925: printf ("\tuae_u32 loval;\n");
1926: printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
1927: printf ("\tloval = val >> (%d - cnt);\n", bit_size (curi->size));
1928: printf ("\tval <<= cnt;\n");
1929: printf ("\tval |= loval;\n");
1930: printf ("\tval &= %s;\n", bit_mask (curi->size));
1931: printf ("\tSET_CFLG (val & 1);\n");
1932: printf ("}\n");
1933: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1934: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1935: if(curi->size==sz_long)
1936: strcpy(exactCpuCycles," return (8+retcycles*2);");
1937: else
1938: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1939: break;
1940: case i_ROR:
1941: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1942: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1943: start_brace ();
1944: switch (curi->size) {
1945: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1946: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1947: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1948: default: abort ();
1949: }
1950: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1951: printf ("\tretcycles = cnt;\n");
1.1 root 1952: printf ("\tCLEAR_CZNV;\n");
1953: if (source_is_imm1_8 (curi))
1954: printf ("{");
1955: else
1956: printf ("\tif (cnt > 0) {");
1957: printf ("\tuae_u32 hival;\n");
1958: printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
1959: printf ("\thival = val << (%d - cnt);\n", bit_size (curi->size));
1960: printf ("\tval >>= cnt;\n");
1961: printf ("\tval |= hival;\n");
1962: printf ("\tval &= %s;\n", bit_mask (curi->size));
1963: printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
1964: printf ("\t}\n");
1965: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1966: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1967: if(curi->size==sz_long)
1968: strcpy(exactCpuCycles," return (8+retcycles*2);");
1969: else
1970: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1971: break;
1972: case i_ROXL:
1973: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1974: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1975: start_brace ();
1976: switch (curi->size) {
1977: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1978: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1979: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1980: default: abort ();
1981: }
1982: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1983: printf ("\tretcycles = cnt;\n");
1.1 root 1984: printf ("\tCLEAR_CZNV;\n");
1985: if (source_is_imm1_8 (curi))
1986: printf ("{");
1987: else {
1988: force_range_for_rox ("cnt", curi->size);
1989: printf ("\tif (cnt > 0) {\n");
1990: }
1991: printf ("\tcnt--;\n");
1992: printf ("\t{\n\tuae_u32 carry;\n");
1993: printf ("\tuae_u32 loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1);
1994: printf ("\tcarry = loval & 1;\n");
1995: printf ("\tval = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);\n");
1996: printf ("\tSET_XFLG (carry);\n");
1997: printf ("\tval &= %s;\n", bit_mask (curi->size));
1998: printf ("\t} }\n");
1999: printf ("\tSET_CFLG (GET_XFLG);\n");
2000: genflags (flag_logical_noclobber, curi->size, "val", "", "");
2001: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 2002: if(curi->size==sz_long)
2003: strcpy(exactCpuCycles," return (8+retcycles*2);");
2004: else
2005: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 2006: break;
2007: case i_ROXR:
2008: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
2009: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
2010: start_brace ();
2011: switch (curi->size) {
2012: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
2013: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
2014: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2015: default: abort ();
2016: }
2017: printf ("\tcnt &= 63;\n");
1.1.1.2 root 2018: printf ("\tretcycles = cnt;\n");
1.1 root 2019: printf ("\tCLEAR_CZNV;\n");
2020: if (source_is_imm1_8 (curi))
2021: printf ("{");
2022: else {
2023: force_range_for_rox ("cnt", curi->size);
2024: printf ("\tif (cnt > 0) {\n");
2025: }
2026: printf ("\tcnt--;\n");
2027: printf ("\t{\n\tuae_u32 carry;\n");
2028: printf ("\tuae_u32 hival = (val << 1) | GET_XFLG;\n");
2029: printf ("\thival <<= (%d - cnt);\n", bit_size (curi->size) - 1);
2030: printf ("\tval >>= cnt;\n");
2031: printf ("\tcarry = val & 1;\n");
2032: printf ("\tval >>= 1;\n");
2033: printf ("\tval |= hival;\n");
2034: printf ("\tSET_XFLG (carry);\n");
2035: printf ("\tval &= %s;\n", bit_mask (curi->size));
2036: printf ("\t} }\n");
2037: printf ("\tSET_CFLG (GET_XFLG);\n");
2038: genflags (flag_logical_noclobber, curi->size, "val", "", "");
2039: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 2040: if(curi->size==sz_long)
2041: strcpy(exactCpuCycles," return (8+retcycles*2);");
2042: else
2043: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 2044: break;
2045: case i_ASRW:
2046: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2047: start_brace ();
2048: switch (curi->size) {
2049: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
2050: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
2051: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2052: default: abort ();
2053: }
2054: printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
2055: printf ("\tuae_u32 cflg = val & 1;\n");
2056: printf ("\tval = (val >> 1) | sign;\n");
2057: genflags (flag_logical, curi->size, "val", "", "");
2058: printf ("\tSET_CFLG (cflg);\n");
2059: duplicate_carry ();
2060: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2061: break;
2062: case i_ASLW:
2063: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2064: start_brace ();
2065: switch (curi->size) {
2066: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
2067: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
2068: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2069: default: abort ();
2070: }
2071: printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
2072: printf ("\tuae_u32 sign2;\n");
2073: printf ("\tval <<= 1;\n");
2074: genflags (flag_logical, curi->size, "val", "", "");
2075: printf ("\tsign2 = %s & val;\n", cmask (curi->size));
2076: printf ("\tSET_CFLG (sign != 0);\n");
2077: duplicate_carry ();
2078:
2079: printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n");
2080: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2081: break;
2082: case i_LSRW:
2083: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2084: start_brace ();
2085: switch (curi->size) {
2086: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
2087: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
2088: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2089: default: abort ();
2090: }
2091: printf ("\tuae_u32 carry = val & 1;\n");
2092: printf ("\tval >>= 1;\n");
2093: genflags (flag_logical, curi->size, "val", "", "");
2094: printf ("SET_CFLG (carry);\n");
2095: duplicate_carry ();
2096: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2097: break;
2098: case i_LSLW:
2099: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2100: start_brace ();
2101: switch (curi->size) {
2102: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2103: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2104: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2105: default: abort ();
2106: }
2107: printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
2108: printf ("\tval <<= 1;\n");
2109: genflags (flag_logical, curi->size, "val", "", "");
2110: printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
2111: duplicate_carry ();
2112: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2113: break;
2114: case i_ROLW:
2115: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2116: start_brace ();
2117: switch (curi->size) {
2118: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2119: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2120: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2121: default: abort ();
2122: }
2123: printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
2124: printf ("\tval <<= 1;\n");
2125: printf ("\tif (carry) val |= 1;\n");
2126: genflags (flag_logical, curi->size, "val", "", "");
2127: printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
2128: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2129: break;
2130: case i_RORW:
2131: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2132: start_brace ();
2133: switch (curi->size) {
2134: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2135: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2136: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2137: default: abort ();
2138: }
2139: printf ("\tuae_u32 carry = val & 1;\n");
2140: printf ("\tval >>= 1;\n");
2141: printf ("\tif (carry) val |= %s;\n", cmask (curi->size));
2142: genflags (flag_logical, curi->size, "val", "", "");
2143: printf ("SET_CFLG (carry);\n");
2144: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2145: break;
2146: case i_ROXLW:
2147: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2148: start_brace ();
2149: switch (curi->size) {
2150: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2151: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2152: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2153: default: abort ();
2154: }
2155: printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
2156: printf ("\tval <<= 1;\n");
2157: printf ("\tif (GET_XFLG) val |= 1;\n");
2158: genflags (flag_logical, curi->size, "val", "", "");
2159: printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
2160: duplicate_carry ();
2161: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2162: break;
2163: case i_ROXRW:
2164: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2165: start_brace ();
2166: switch (curi->size) {
2167: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2168: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2169: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2170: default: abort ();
2171: }
2172: printf ("\tuae_u32 carry = val & 1;\n");
2173: printf ("\tval >>= 1;\n");
2174: printf ("\tif (GET_XFLG) val |= %s;\n", cmask (curi->size));
2175: genflags (flag_logical, curi->size, "val", "", "");
2176: printf ("SET_CFLG (carry);\n");
2177: duplicate_carry ();
2178: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2179: break;
2180: case i_MOVEC2:
2181: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
2182: start_brace ();
2183: printf ("\tint regno = (src >> 12) & 15;\n");
2184: printf ("\tuae_u32 *regp = regs.regs + regno;\n");
2185: printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
2186: break;
2187: case i_MOVE2C:
2188: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
2189: start_brace ();
2190: printf ("\tint regno = (src >> 12) & 15;\n");
2191: printf ("\tuae_u32 *regp = regs.regs + regno;\n");
2192: printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
2193: break;
2194: case i_CAS:
2195: {
2196: int old_brace_level;
2197: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
2198: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
2199: start_brace ();
2200: printf ("\tint ru = (src >> 6) & 7;\n");
2201: printf ("\tint rc = src & 7;\n");
2202: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst");
2203: printf ("\tif (GET_ZFLG)");
2204: old_brace_level = n_braces;
2205: start_brace ();
2206: genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst");
2207: pop_braces (old_brace_level);
2208: printf ("else");
2209: start_brace ();
2210: printf ("m68k_dreg(regs, rc) = dst;\n");
2211: pop_braces (old_brace_level);
2212: }
2213: break;
2214: case i_CAS2:
2215: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2216: printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n");
2217: printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n");
2218: if (curi->size == sz_word) {
2219: int old_brace_level = n_braces;
2220: printf ("\tuae_u16 dst1 = get_word(rn1), dst2 = get_word(rn2);\n");
2221: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
2222: printf ("\tif (GET_ZFLG) {\n");
2223: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
2224: printf ("\tif (GET_ZFLG) {\n");
2225: printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
2226: printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
2227: printf ("\t}}\n");
2228: pop_braces (old_brace_level);
2229: printf ("\tif (! GET_ZFLG) {\n");
2230: printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n");
2231: printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n");
2232: printf ("\t}\n");
2233: } else {
2234: int old_brace_level = n_braces;
2235: printf ("\tuae_u32 dst1 = get_long(rn1), dst2 = get_long(rn2);\n");
2236: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
2237: printf ("\tif (GET_ZFLG) {\n");
2238: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
2239: printf ("\tif (GET_ZFLG) {\n");
2240: printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
2241: printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
2242: printf ("\t}}\n");
2243: pop_braces (old_brace_level);
2244: printf ("\tif (! GET_ZFLG) {\n");
2245: printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n");
2246: printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n");
2247: printf ("\t}\n");
2248: }
2249: break;
2250: case i_MOVES: /* ignore DFC and SFC because we have no MMU */
2251: {
2252: int old_brace_level;
2253: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2254: printf ("\tif (extra & 0x800)\n");
2255: old_brace_level = n_braces;
2256: start_brace ();
2257: printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
2258: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
2259: genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
2260: pop_braces (old_brace_level);
2261: printf ("else");
2262: start_brace ();
2263: genamode (curi->dmode, "dstreg", curi->size, "src", 1, 0);
2264: printf ("\tif (extra & 0x8000) {\n");
2265: switch (curi->size) {
2266: case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break;
2267: case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break;
2268: case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break;
2269: default: abort ();
2270: }
2271: printf ("\t} else {\n");
2272: genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "");
2273: printf ("\t}\n");
2274: pop_braces (old_brace_level);
2275: }
2276: break;
2277: case i_BKPT: /* only needed for hardware emulators */
2278: sync_m68k_pc ();
2279: printf ("\top_illg(opcode);\n");
2280: break;
2281: case i_CALLM: /* not present in 68030 */
2282: sync_m68k_pc ();
2283: printf ("\top_illg(opcode);\n");
2284: break;
2285: case i_RTM: /* not present in 68030 */
2286: sync_m68k_pc ();
2287: printf ("\top_illg(opcode);\n");
2288: break;
2289: case i_TRAPcc:
2290: if (curi->smode != am_unknown && curi->smode != am_illg)
2291: genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
1.1.1.12 root 2292: printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc(),M68000_EXC_SRC_CPU); goto %s; }\n", curi->cc, endlabelstr);
1.1 root 2293: need_endlabel = 1;
2294: break;
2295: case i_DIVL:
2296: sync_m68k_pc ();
2297: start_brace ();
2298: printf ("\tuaecptr oldpc = m68k_getpc();\n");
2299: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2300: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
2301: sync_m68k_pc ();
2302: printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n");
2303: break;
2304: case i_MULL:
2305: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2306: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
2307: sync_m68k_pc ();
2308: printf ("\tm68k_mull(opcode, dst, extra);\n");
2309: break;
2310: case i_BFTST:
2311: case i_BFEXTU:
2312: case i_BFCHG:
2313: case i_BFEXTS:
2314: case i_BFCLR:
2315: case i_BFFFO:
2316: case i_BFSET:
2317: case i_BFINS:
2318: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2319: genamode (curi->dmode, "dstreg", sz_long, "dst", 2, 0);
2320: start_brace ();
2321: printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n");
2322: printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n");
2323: if (curi->dmode == Dreg) {
2324: printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg) << (offset & 0x1f);\n");
2325: } else {
2326: printf ("\tuae_u32 tmp,bf0,bf1;\n");
2327: printf ("\tdsta += (offset >> 3) | (offset & 0x80000000 ? ~0x1fffffff : 0);\n");
2328: printf ("\tbf0 = get_long(dsta);bf1 = get_byte(dsta+4) & 0xff;\n");
2329: printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n");
2330: }
2331: printf ("\ttmp >>= (32 - width);\n");
2332: printf ("\tSET_NFLG (tmp & (1 << (width-1)) ? 1 : 0);\n");
2333: printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n");
2334: switch (curi->mnemo) {
2335: case i_BFTST:
2336: break;
2337: case i_BFEXTU:
2338: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
2339: break;
2340: case i_BFCHG:
2341: printf ("\ttmp = ~tmp;\n");
2342: break;
2343: case i_BFEXTS:
2344: printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n");
2345: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
2346: break;
2347: case i_BFCLR:
2348: printf ("\ttmp = 0;\n");
2349: break;
2350: case i_BFFFO:
2351: printf ("\t{ uae_u32 mask = 1 << (width-1);\n");
2352: printf ("\twhile (mask) { if (tmp & mask) break; mask >>= 1; offset++; }}\n");
2353: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = offset;\n");
2354: break;
2355: case i_BFSET:
2356: printf ("\ttmp = 0xffffffff;\n");
2357: break;
2358: case i_BFINS:
2359: printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n");
1.1.1.4 root 2360: printf ("\tSET_NFLG (tmp & (1 << (width - 1)) ? 1 : 0);\n");
2361: printf ("\tSET_ZFLG (tmp == 0);\n");
1.1 root 2362: break;
2363: default:
2364: break;
2365: }
2366: if (curi->mnemo == i_BFCHG
2367: || curi->mnemo == i_BFCLR
2368: || curi->mnemo == i_BFSET
2369: || curi->mnemo == i_BFINS)
2370: {
2371: printf ("\ttmp <<= (32 - width);\n");
2372: if (curi->dmode == Dreg) {
2373: printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ((offset & 0x1f) == 0 ? 0 :\n");
2374: printf ("\t\t(0xffffffff << (32 - (offset & 0x1f))))) |\n");
2375: printf ("\t\t(tmp >> (offset & 0x1f)) |\n");
2376: printf ("\t\t(((offset & 0x1f) + width) >= 32 ? 0 :\n");
2377: printf (" (m68k_dreg(regs, dstreg) & ((uae_u32)0xffffffff >> ((offset & 0x1f) + width))));\n");
2378: } else {
2379: printf ("\tbf0 = (bf0 & (0xff000000 << (8 - (offset & 7)))) |\n");
2380: printf ("\t\t(tmp >> (offset & 7)) |\n");
2381: printf ("\t\t(((offset & 7) + width) >= 32 ? 0 :\n");
2382: printf ("\t\t (bf0 & ((uae_u32)0xffffffff >> ((offset & 7) + width))));\n");
2383: printf ("\tput_long(dsta,bf0 );\n");
2384: printf ("\tif (((offset & 7) + width) > 32) {\n");
2385: printf ("\t\tbf1 = (bf1 & (0xff >> (width - 32 + (offset & 7)))) |\n");
2386: printf ("\t\t\t(tmp << (8 - (offset & 7)));\n");
2387: printf ("\t\tput_byte(dsta+4,bf1);\n");
2388: printf ("\t}\n");
2389: }
2390: }
2391: break;
2392: case i_PACK:
2393: if (curi->smode == Dreg) {
2394: printf ("\tuae_u16 val = m68k_dreg(regs, srcreg) + %s;\n", gen_nextiword ());
2395: printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n");
2396: } else {
2397: printf ("\tuae_u16 val;\n");
2398: printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
2399: printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n");
2400: printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
2401: printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg)) << 8)) + %s;\n", gen_nextiword ());
2402: printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
2403: printf ("\tput_byte(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n");
2404: }
2405: break;
2406: case i_UNPK:
2407: if (curi->smode == Dreg) {
2408: printf ("\tuae_u16 val = m68k_dreg(regs, srcreg);\n");
2409: printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
2410: printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n");
2411: } else {
2412: printf ("\tuae_u16 val;\n");
2413: printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
2414: printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n");
2415: printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
2416: printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
2417: printf ("\tput_byte(m68k_areg(regs, dstreg),val);\n");
2418: printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
2419: printf ("\tput_byte(m68k_areg(regs, dstreg),val >> 8);\n");
2420: }
2421: break;
2422: case i_TAS:
2423: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
2424: genflags (flag_logical, curi->size, "src", "", "");
2425: printf ("\tsrc |= 0x80;\n");
2426: genastore ("src", curi->smode, "srcreg", curi->size, "src");
1.1.1.2 root 2427: if( curi->smode!=Dreg ) insn_n_cycles += 2;
1.1 root 2428: break;
2429: case i_FPP:
2430: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2431: sync_m68k_pc ();
2432: printf ("\tfpp_opp(opcode,extra);\n");
2433: break;
2434: case i_FDBcc:
2435: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2436: sync_m68k_pc ();
2437: printf ("\tfdbcc_opp(opcode,extra);\n");
2438: break;
2439: case i_FScc:
2440: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2441: sync_m68k_pc ();
2442: printf ("\tfscc_opp(opcode,extra);\n");
2443: break;
2444: case i_FTRAPcc:
2445: sync_m68k_pc ();
2446: start_brace ();
2447: printf ("\tuaecptr oldpc = m68k_getpc();\n");
2448: if (curi->smode != am_unknown && curi->smode != am_illg)
2449: genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
2450: sync_m68k_pc ();
2451: printf ("\tftrapcc_opp(opcode,oldpc);\n");
2452: break;
2453: case i_FBcc:
2454: sync_m68k_pc ();
2455: start_brace ();
2456: printf ("\tuaecptr pc = m68k_getpc();\n");
2457: genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0);
2458: sync_m68k_pc ();
2459: printf ("\tfbcc_opp(opcode,pc,extra);\n");
2460: break;
2461: case i_FSAVE:
2462: sync_m68k_pc ();
2463: printf ("\tfsave_opp(opcode);\n");
2464: break;
2465: case i_FRESTORE:
2466: sync_m68k_pc ();
2467: printf ("\tfrestore_opp(opcode);\n");
2468: break;
2469:
2470: case i_CINVL:
2471: case i_CINVP:
2472: case i_CINVA:
2473: case i_CPUSHL:
2474: case i_CPUSHP:
2475: case i_CPUSHA:
2476: break;
2477: case i_MOVE16:
1.1.1.4 root 2478: if ((opcode & 0xfff8) == 0xf620) {
2479: /* MOVE16 (Ax)+,(Ay)+ */
2480: printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n");
2481: printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword());
2482: printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n");
2483: printf ("\tput_long(memd, get_long(mems));\n");
2484: printf ("\tput_long(memd+4, get_long(mems+4));\n");
2485: printf ("\tput_long(memd+8, get_long(mems+8));\n");
2486: printf ("\tput_long(memd+12, get_long(mems+12));\n");
2487: printf ("\tif (srcreg != dstreg)\n");
2488: printf ("\tm68k_areg(regs, srcreg) += 16;\n");
2489: printf ("\tm68k_areg(regs, dstreg) += 16;\n");
2490: } else {
2491: /* Other variants */
2492: genamode (curi->smode, "srcreg", curi->size, "mems", 0, 2);
2493: genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2);
2494: printf ("\tmemsa &= ~15;\n");
2495: printf ("\tmemda &= ~15;\n");
2496: printf ("\tput_long(memda, get_long(memsa));\n");
2497: printf ("\tput_long(memda+4, get_long(memsa+4));\n");
2498: printf ("\tput_long(memda+8, get_long(memsa+8));\n");
2499: printf ("\tput_long(memda+12, get_long(memsa+12));\n");
2500: if ((opcode & 0xfff8) == 0xf600)
2501: printf ("\tm68k_areg(regs, srcreg) += 16;\n");
2502: else if ((opcode & 0xfff8) == 0xf608)
2503: printf ("\tm68k_areg(regs, dstreg) += 16;\n");
2504: }
1.1 root 2505: break;
2506:
2507: case i_MMUOP:
2508: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2509: sync_m68k_pc ();
2510: printf ("\tmmu_op(opcode,extra);\n");
2511: break;
2512: default:
2513: abort ();
2514: break;
2515: }
2516: finish_braces ();
2517: sync_m68k_pc ();
2518: }
2519:
2520: static void generate_includes (FILE * f)
2521: {
2522: fprintf (f, "#include \"sysdeps.h\"\n");
2523: fprintf (f, "#include \"hatari-glue.h\"\n");
2524: fprintf (f, "#include \"maccess.h\"\n");
2525: fprintf (f, "#include \"memory.h\"\n");
2526: fprintf (f, "#include \"newcpu.h\"\n");
2527: fprintf (f, "#include \"cputbl.h\"\n");
2528: fprintf (f, "#define CPUFUNC(x) x##_ff\n"
2529: "#ifdef NOFLAGS\n"
2530: "#include \"noflags.h\"\n"
2531: "#endif\n");
2532: }
2533:
2534: static int postfix;
2535:
2536: static void generate_one_opcode (int rp)
2537: {
2538: int i;
2539: uae_u16 smsk, dmsk;
2540: long int opcode = opcode_map[rp];
2541:
1.1.1.2 root 2542: exactCpuCycles[0] = 0; /* Default: not used */
2543:
1.1 root 2544: if (table68k[opcode].mnemo == i_ILLG
2545: || table68k[opcode].clev > cpu_level)
2546: return;
2547:
2548: for (i = 0; lookuptab[i].name[0]; i++) {
2549: if (table68k[opcode].mnemo == lookuptab[i].mnemo)
2550: break;
2551: }
2552:
2553: if (table68k[opcode].handler != -1)
2554: return;
2555:
2556: if (opcode_next_clev[rp] != cpu_level) {
2557: fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp],
2558: opcode, lookuptab[i].name);
2559: return;
2560: }
2561: fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, lookuptab[i].name);
2562: fprintf (headerfile, "extern cpuop_func op_%lx_%d_nf;\n", opcode, postfix);
2563: fprintf (headerfile, "extern cpuop_func op_%lx_%d_ff;\n", opcode, postfix);
2564: printf ("unsigned long REGPARAM2 CPUFUNC(op_%lx_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name);
2565:
2566: switch (table68k[opcode].stype) {
2567: case 0: smsk = 7; break;
2568: case 1: smsk = 255; break;
2569: case 2: smsk = 15; break;
2570: case 3: smsk = 7; break;
2571: case 4: smsk = 7; break;
2572: case 5: smsk = 63; break;
1.1.1.4 root 2573: case 7: smsk = 3; break;
1.1 root 2574: default: abort ();
2575: }
2576: dmsk = 7;
2577:
2578: next_cpu_level = -1;
2579: if (table68k[opcode].suse
2580: && table68k[opcode].smode != imm && table68k[opcode].smode != imm0
2581: && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2
2582: && table68k[opcode].smode != absw && table68k[opcode].smode != absl
2583: && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16)
2584: {
2585: if (table68k[opcode].spos == -1) {
2586: if (((int) table68k[opcode].sreg) >= 128)
2587: printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].sreg);
2588: else
2589: printf ("\tuae_u32 srcreg = %d;\n", (int) table68k[opcode].sreg);
2590: } else {
2591: char source[100];
2592: int pos = table68k[opcode].spos;
2593:
2594: if (pos)
2595: sprintf (source, "((opcode >> %d) & %d)", pos, smsk);
2596: else
2597: sprintf (source, "(opcode & %d)", smsk);
2598:
2599: if (table68k[opcode].stype == 3)
2600: printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source);
2601: else if (table68k[opcode].stype == 1)
2602: printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source);
2603: else
2604: printf ("\tuae_u32 srcreg = %s;\n", source);
2605: }
2606: }
2607: if (table68k[opcode].duse
2608: /* Yes, the dmode can be imm, in case of LINK or DBcc */
2609: && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0
2610: && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2
2611: && table68k[opcode].dmode != absw && table68k[opcode].dmode != absl)
2612: {
2613: if (table68k[opcode].dpos == -1) {
2614: if (((int) table68k[opcode].dreg) >= 128)
2615: printf ("\tuae_u32 dstreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].dreg);
2616: else
2617: printf ("\tuae_u32 dstreg = %d;\n", (int) table68k[opcode].dreg);
2618: } else {
2619: int pos = table68k[opcode].dpos;
2620: #if 0
2621: /* Check that we can do the little endian optimization safely. */
2622: if (pos < 8 && (dmsk >> (8 - pos)) != 0)
2623: abort ();
2624: #endif
2625: if (pos)
2626: printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
2627: pos, dmsk);
2628: else
2629: printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
2630: }
2631: }
2632: need_endlabel = 0;
2633: endlabelno++;
2634: sprintf (endlabelstr, "endlabel%d", endlabelno);
1.1.1.2 root 2635: if(table68k[opcode].mnemo==i_ASR || table68k[opcode].mnemo==i_ASL || table68k[opcode].mnemo==i_LSR || table68k[opcode].mnemo==i_LSL
2636: || table68k[opcode].mnemo==i_ROL || table68k[opcode].mnemo==i_ROR || table68k[opcode].mnemo==i_ROXL || table68k[opcode].mnemo==i_ROXR
1.1.1.8 root 2637: || table68k[opcode].mnemo==i_MVMEL || table68k[opcode].mnemo==i_MVMLE
2638: || table68k[opcode].mnemo==i_MULU || table68k[opcode].mnemo==i_MULS
2639: || table68k[opcode].mnemo==i_DIVU || table68k[opcode].mnemo==i_DIVS )
2640: printf("\tunsigned int retcycles = 0;\n");
1.1 root 2641: gen_opcode (opcode);
2642: if (need_endlabel)
2643: printf ("%s: ;\n", endlabelstr);
1.1.1.8 root 2644:
2645: if (strlen(exactCpuCycles) > 0)
2646: printf("%s\n",exactCpuCycles);
2647: else
2648: printf ("return %d;\n", insn_n_cycles);
2649: /* Now patch in the instruction cycles at the beginning of the function: */
2650: fseek(stdout, nCurInstrCycPos, SEEK_SET);
2651: printf("%d;", insn_n_cycles);
2652: fseek(stdout, 0, SEEK_END);
2653:
1.1 root 2654: printf ("}\n");
2655: opcode_next_clev[rp] = next_cpu_level;
2656: opcode_last_postfix[rp] = postfix;
2657: }
2658:
2659: static void generate_func (void)
2660: {
2661: int i, j, rp;
2662:
2663: using_prefetch = 0;
2664: using_exception_3 = 0;
2665: for (i = 0; i < 6; i++) {
2666: cpu_level = 4 - i;
2667: if (i == 5) {
2668: cpu_level = 0;
2669: using_prefetch = 1;
2670: using_exception_3 = 1;
2671: for (rp = 0; rp < nr_cpuop_funcs; rp++)
2672: opcode_next_clev[rp] = 0;
2673: }
2674:
2675: postfix = i;
1.1.1.7 root 2676: fprintf (stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix);
1.1 root 2677:
2678: /* sam: this is for people with low memory (eg. me :)) */
2679: printf ("\n"
2680: "#if !defined(PART_1) && !defined(PART_2) && "
2681: "!defined(PART_3) && !defined(PART_4) && "
2682: "!defined(PART_5) && !defined(PART_6) && "
2683: "!defined(PART_7) && !defined(PART_8)"
2684: "\n"
2685: "#define PART_1 1\n"
2686: "#define PART_2 1\n"
2687: "#define PART_3 1\n"
2688: "#define PART_4 1\n"
2689: "#define PART_5 1\n"
2690: "#define PART_6 1\n"
2691: "#define PART_7 1\n"
2692: "#define PART_8 1\n"
2693: "#endif\n\n");
2694:
2695: rp = 0;
2696: for(j=1;j<=8;++j) {
2697: int k = (j*nr_cpuop_funcs)/8;
2698: printf ("#ifdef PART_%d\n",j);
2699: for (; rp < k; rp++)
2700: generate_one_opcode (rp);
2701: printf ("#endif\n\n");
2702: }
2703:
2704: fprintf (stblfile, "{ 0, 0, 0 }};\n");
2705: }
2706:
2707: }
2708:
2709: int main (int argc, char **argv)
2710: {
2711: read_table68k ();
2712: do_merges ();
2713:
2714: opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
2715: opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
2716: opcode_next_clev = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
2717: counts = (unsigned long *) malloc (65536 * sizeof (unsigned long));
2718: read_counts ();
2719:
2720: /* It would be a lot nicer to put all in one file (we'd also get rid of
2721: * cputbl.h that way), but cpuopti can't cope. That could be fixed, but
2722: * I don't dare to touch the 68k version. */
2723:
2724: headerfile = fopen ("cputbl.h", "wb");
2725: stblfile = fopen ("cpustbl.c", "wb");
1.1.1.11 root 2726: if (freopen ("cpuemu.c", "wb", stdout) == NULL) {
2727: perror("cpuemu.c");
2728: return -1;
2729: }
1.1 root 2730:
2731: generate_includes (stdout);
2732: generate_includes (stblfile);
2733:
2734: generate_func ();
2735:
2736: free (table68k);
2737: return 0;
2738: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.