|
|
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.16! root 22: * This file is distributed under the GNU General Public License, version 2
! 23: * or at 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 ());
1.1.1.16! root 1283: /* [NP] Use MovepByteNbr to keep track of each access inside a movep */
1.1 root 1284: if (curi->size == sz_word) {
1.1.1.14 root 1285: printf ("\tMovepByteNbr=1; put_byte(memp, src >> 8); MovepByteNbr=2; put_byte(memp + 2, src);\n");
1.1 root 1286: } else {
1.1.1.14 root 1287: printf ("\tMovepByteNbr=1; put_byte(memp, src >> 24); MovepByteNbr=2; put_byte(memp + 2, src >> 16);\n");
1288: printf ("\tMovepByteNbr=3; put_byte(memp + 4, src >> 8); MovepByteNbr=4; put_byte(memp + 6, src);\n");
1.1 root 1289: }
1.1.1.16! root 1290: printf ("\tMovepByteNbr=0;\n");
1.1.1.2 root 1291: if(curi->size==sz_long) insn_n_cycles=24; else insn_n_cycles=16;
1.1 root 1292: break;
1293: case i_MVPMR:
1294: printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ());
1295: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1.1.1.16! root 1296: /* [NP] Use MovepByteNbr to keep track of each access inside a movep */
1.1 root 1297: if (curi->size == sz_word) {
1.1.1.16! root 1298: //printf ("\tuae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);\n");
! 1299: printf ("\tuae_u16 val;\n");
! 1300: printf ("\tMovepByteNbr=1; val = (get_byte(memp) << 8);\n");
! 1301: printf ("\tMovepByteNbr=2; val += get_byte(memp + 2);\n");
1.1 root 1302: } else {
1.1.1.16! root 1303: //printf ("\tuae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)\n");
! 1304: //printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n");
! 1305: printf ("\tuae_u32 val;\n");
! 1306: printf ("\tMovepByteNbr=1; val = (get_byte(memp) << 24);\n");
! 1307: printf ("\tMovepByteNbr=2; val += (get_byte(memp + 2) << 16);\n");
! 1308: printf ("\tMovepByteNbr=3; val += (get_byte(memp + 4) << 8);\n");
! 1309: printf ("\tMovepByteNbr=4; val += get_byte(memp + 6);\n");
1.1 root 1310: }
1.1.1.16! root 1311: printf ("\tMovepByteNbr=0;\n");
1.1 root 1312: genastore ("val", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1313: if(curi->size==sz_long) insn_n_cycles=24; else insn_n_cycles=16;
1.1 root 1314: break;
1315: case i_MOVE:
1316: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1317: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1.1.1.8 root 1318:
1319: /* [NP] genamode counts 2 cycles if dest is -(An), this is wrong. */
1320: /* For move dest (An), (An)+ and -(An) take the same time */
1321: /* (for other instr, dest -(An) really takes 2 cycles more) */
1322: if ( curi->dmode == Apdi )
1323: insn_n_cycles -= 2; /* correct the wrong cycle count for -(An) */
1324:
1.1 root 1325: genflags (flag_logical, curi->size, "src", "", "");
1326: genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
1327: break;
1328: case i_MOVEA:
1329: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1330: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1331: if (curi->size == sz_word) {
1332: printf ("\tuae_u32 val = (uae_s32)(uae_s16)src;\n");
1333: } else {
1334: printf ("\tuae_u32 val = src;\n");
1335: }
1336: genastore ("val", curi->dmode, "dstreg", sz_long, "dst");
1337: break;
1.1.1.2 root 1338: case i_MVSR2: /* Move from SR */
1.1 root 1339: genamode (curi->smode, "srcreg", sz_word, "src", 2, 0);
1340: printf ("\tMakeSR();\n");
1341: if (curi->size == sz_byte)
1342: genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src");
1343: else
1344: genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src");
1.1.1.2 root 1345: if (curi->smode==Dreg) insn_n_cycles += 2; else insn_n_cycles += 4;
1.1 root 1346: break;
1.1.1.2 root 1347: case i_MV2SR: /* Move to SR */
1.1 root 1348: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
1349: if (curi->size == sz_byte)
1350: printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n");
1351: else {
1352: printf ("\tregs.sr = src;\n");
1353: }
1354: printf ("\tMakeFromSR();\n");
1.1.1.2 root 1355: insn_n_cycles += 8;
1.1 root 1356: break;
1357: case i_SWAP:
1358: genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
1359: start_brace ();
1360: printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n");
1361: genflags (flag_logical, sz_long, "dst", "", "");
1362: genastore ("dst", curi->smode, "srcreg", sz_long, "src");
1363: break;
1364: case i_EXG:
1365: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1366: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1367: genastore ("dst", curi->smode, "srcreg", curi->size, "src");
1368: genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.2 root 1369: insn_n_cycles = 6;
1.1 root 1370: break;
1371: case i_EXT:
1372: genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
1373: start_brace ();
1374: switch (curi->size) {
1375: case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break;
1376: case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break;
1377: case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break;
1378: default: abort ();
1379: }
1380: genflags (flag_logical,
1381: curi->size == sz_word ? sz_word : sz_long, "dst", "", "");
1382: genastore ("dst", curi->smode, "srcreg",
1383: curi->size == sz_word ? sz_word : sz_long, "src");
1384: break;
1385: case i_MVMEL:
1386: genmovemel (opcode);
1387: break;
1388: case i_MVMLE:
1389: genmovemle (opcode);
1390: break;
1391: case i_TRAP:
1392: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1393: sync_m68k_pc ();
1.1.1.12 root 1394: printf ("\tException(src+32,0,M68000_EXC_SRC_CPU);\n");
1.1 root 1395: m68k_pc_offset = 0;
1396: break;
1397: case i_MVR2USP:
1398: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1399: printf ("\tregs.usp = src;\n");
1400: break;
1401: case i_MVUSP2R:
1402: genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
1403: genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src");
1404: break;
1405: case i_RESET:
1406: printf ("\tcustomreset();\n");
1.1.1.2 root 1407: insn_n_cycles = 132; /* I am not so sure about this!? - Thothy */
1.1 root 1408: break;
1409: case i_NOP:
1410: break;
1411: case i_STOP:
1412: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1413: printf ("\tregs.sr = src;\n");
1414: printf ("\tMakeFromSR();\n");
1415: printf ("\tm68k_setstopped(1);\n");
1.1.1.2 root 1416: insn_n_cycles = 4;
1.1 root 1417: break;
1418: case i_RTE:
1419: if (cpu_level == 0) {
1420: genamode (Aipi, "7", sz_word, "sr", 1, 0);
1421: genamode (Aipi, "7", sz_long, "pc", 1, 0);
1422: printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n");
1423: fill_prefetch_0 ();
1424: printf ("\tMakeFromSR();\n");
1425: } else {
1426: int old_brace_level = n_braces;
1427: if (next_cpu_level < 0)
1428: next_cpu_level = 0;
1429: printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n");
1430: genamode (Aipi, "7", sz_word, "sr", 1, 0);
1431: genamode (Aipi, "7", sz_long, "pc", 1, 0);
1432: genamode (Aipi, "7", sz_word, "format", 1, 0);
1433: printf ("\tnewsr = sr; newpc = pc;\n");
1434: printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n");
1435: printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n");
1436: printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n");
1437: printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n");
1438: printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n");
1439: printf ("\telse if ((format & 0xF000) == 0xa000) { m68k_areg(regs, 7) += 24; break; }\n");
1440: printf ("\telse if ((format & 0xF000) == 0xb000) { m68k_areg(regs, 7) += 84; break; }\n");
1.1.1.12 root 1441: printf ("\telse { Exception(14,0,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1.1 root 1442: printf ("\tregs.sr = newsr; MakeFromSR();\n}\n");
1443: pop_braces (old_brace_level);
1444: printf ("\tregs.sr = newsr; MakeFromSR();\n");
1445: printf ("\tm68k_setpc_rte(newpc);\n");
1446: fill_prefetch_0 ();
1447: need_endlabel = 1;
1448: }
1449: /* PC is set and prefetch filled. */
1450: m68k_pc_offset = 0;
1.1.1.2 root 1451: insn_n_cycles = 20;
1.1 root 1452: break;
1453: case i_RTD:
1454: genamode (Aipi, "7", sz_long, "pc", 1, 0);
1455: genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0);
1456: printf ("\tm68k_areg(regs, 7) += offs;\n");
1457: printf ("\tm68k_setpc_rte(pc);\n");
1458: fill_prefetch_0 ();
1459: /* PC is set and prefetch filled. */
1460: m68k_pc_offset = 0;
1461: break;
1462: case i_LINK:
1463: genamode (Apdi, "7", sz_long, "old", 2, 0);
1464: genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
1465: genastore ("src", Apdi, "7", sz_long, "old");
1466: genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src");
1467: genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
1468: printf ("\tm68k_areg(regs, 7) += offs;\n");
1469: break;
1470: case i_UNLK:
1471: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1472: printf ("\tm68k_areg(regs, 7) = src;\n");
1473: genamode (Aipi, "7", sz_long, "old", 1, 0);
1474: genastore ("old", curi->smode, "srcreg", curi->size, "src");
1475: break;
1476: case i_RTS:
1477: printf ("\tm68k_do_rts();\n");
1478: fill_prefetch_0 ();
1479: m68k_pc_offset = 0;
1.1.1.2 root 1480: insn_n_cycles = 16;
1.1 root 1481: break;
1482: case i_TRAPV:
1483: sync_m68k_pc ();
1.1.1.12 root 1484: printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc(),M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1.1 root 1485: need_endlabel = 1;
1486: break;
1487: case i_RTR:
1488: printf ("\tMakeSR();\n");
1489: genamode (Aipi, "7", sz_word, "sr", 1, 0);
1490: genamode (Aipi, "7", sz_long, "pc", 1, 0);
1491: printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n");
1492: printf ("\tregs.sr |= sr; m68k_setpc(pc);\n");
1493: fill_prefetch_0 ();
1494: printf ("\tMakeFromSR();\n");
1495: m68k_pc_offset = 0;
1.1.1.2 root 1496: insn_n_cycles = 20;
1.1 root 1497: break;
1498: case i_JSR:
1499: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1.1.1.13 root 1500: printf ("\tuaecptr oldpc = m68k_getpc () + %d;\n", m68k_pc_offset);
1501: if (using_exception_3) {
1502: printf ("\tif (srca & 1) {\n");
1503: printf ("\t\tlast_addr_for_exception_3 = oldpc;\n");
1504: printf ("\t\tlast_fault_for_exception_3 = srca;\n");
1505: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1506: printf ("\t}\n");
1507: need_endlabel = 1;
1508: }
1.1 root 1509: printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset);
1510: fill_prefetch_0 ();
1511: m68k_pc_offset = 0;
1.1.1.2 root 1512: switch(curi->smode)
1513: {
1514: case Aind: insn_n_cycles=16; break;
1515: case Ad16: insn_n_cycles=18; break;
1516: case Ad8r: insn_n_cycles=22; break;
1517: case absw: insn_n_cycles=18; break;
1518: case absl: insn_n_cycles=20; break;
1519: case PC16: insn_n_cycles=18; break;
1520: case PC8r: insn_n_cycles=22; break;
1521: }
1.1 root 1522: break;
1523: case i_JMP:
1524: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1.1.1.13 root 1525: if (using_exception_3) {
1526: printf ("\tif (srca & 1) {\n");
1.1.1.15 root 1527: 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 1528: printf ("\t\tlast_fault_for_exception_3 = srca;\n");
1529: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1530: printf ("\t}\n");
1531: need_endlabel = 1;
1532: }
1.1 root 1533: printf ("\tm68k_setpc(srca);\n");
1534: fill_prefetch_0 ();
1535: m68k_pc_offset = 0;
1.1.1.2 root 1536: switch(curi->smode)
1537: {
1538: case Aind: insn_n_cycles=8; break;
1539: case Ad16: insn_n_cycles=10; break;
1540: case Ad8r: insn_n_cycles=14; break;
1541: case absw: insn_n_cycles=10; break;
1542: case absl: insn_n_cycles=12; break;
1543: case PC16: insn_n_cycles=10; break;
1544: case PC8r: insn_n_cycles=14; break;
1545: }
1.1 root 1546: break;
1547: case i_BSR:
1548: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1549: printf ("\tuae_s32 s = (uae_s32)src + 2;\n");
1550: if (using_exception_3) {
1551: printf ("\tif (src & 1) {\n");
1.1.1.13 root 1552: printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); // [NP] FIXME should be +4, not +2 (same as DBcc) ?
1.1 root 1553: printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + s;\n");
1.1.1.12 root 1554: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1.1 root 1555: printf ("\t}\n");
1556: need_endlabel = 1;
1557: }
1558: printf ("\tm68k_do_bsr(m68k_getpc() + %d, s);\n", m68k_pc_offset);
1559: fill_prefetch_0 ();
1560: m68k_pc_offset = 0;
1.1.1.2 root 1561: insn_n_cycles = 18;
1.1 root 1562: break;
1563: case i_Bcc:
1564: if (curi->size == sz_long) {
1565: if (cpu_level < 2) {
1566: printf ("\tm68k_incpc(2);\n");
1567: printf ("\tif (!cctrue(%d)) goto %s;\n", curi->cc, endlabelstr);
1568: printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n");
1569: printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 1;\n");
1.1.1.12 root 1570: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1.1 root 1571: need_endlabel = 1;
1572: } else {
1573: if (next_cpu_level < 1)
1574: next_cpu_level = 1;
1575: }
1576: }
1577: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1578: printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc);
1579: if (using_exception_3) {
1580: printf ("\tif (src & 1) {\n");
1.1.1.8 root 1581: printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); // [NP] FIXME should be +4, not +2 (same as DBcc) ?
1.1 root 1582: printf ("\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)src;\n");
1.1.1.12 root 1583: printf ("\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1.1 root 1584: printf ("\t}\n");
1585: need_endlabel = 1;
1586: }
1587: printf ("\tm68k_incpc ((uae_s32)src + 2);\n");
1588: fill_prefetch_0 ();
1.1.1.2 root 1589: printf ("\treturn 10;\n");
1.1 root 1590: printf ("didnt_jump:;\n");
1591: need_endlabel = 1;
1.1.1.2 root 1592: insn_n_cycles = (curi->size == sz_byte) ? 8 : 12;
1.1 root 1593: break;
1594: case i_LEA:
1595: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1596: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1597: genastore ("srca", curi->dmode, "dstreg", curi->size, "dst");
1.1.1.7 root 1598: /* Set correct cycles: According to the M68K User Manual, LEA takes 12
1599: * cycles in Ad8r and PC8r mode, but it takes 14 (or 16) cycles on a real ST: */
1600: if (curi->smode == Ad8r || curi->smode == PC8r)
1601: insn_n_cycles = 14;
1.1 root 1602: break;
1603: case i_PEA:
1604: genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1605: genamode (Apdi, "7", sz_long, "dst", 2, 0);
1606: genastore ("srca", Apdi, "7", sz_long, "dst");
1.1.1.7 root 1607: /* Set correct cycles: */
1.1.1.2 root 1608: switch(curi->smode)
1609: {
1610: case Aind: insn_n_cycles=12; break;
1611: case Ad16: insn_n_cycles=16; break;
1.1.1.7 root 1612: /* Note: according to the M68K User Manual, PEA takes 20 cycles for
1613: * the Ad8r mode, but on a real ST, it takes 22 (or 24) cycles! */
1614: case Ad8r: insn_n_cycles=22; break;
1.1.1.2 root 1615: case absw: insn_n_cycles=16; break;
1616: case absl: insn_n_cycles=20; break;
1617: case PC16: insn_n_cycles=16; break;
1.1.1.7 root 1618: /* Note: PEA with PC8r takes 20 cycles according to the User Manual,
1619: * but it takes 22 (or 24) cycles on a real ST: */
1620: case PC8r: insn_n_cycles=22; break;
1.1.1.2 root 1621: }
1.1 root 1622: break;
1623: case i_DBcc:
1624: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1625: genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
1626:
1.1.1.2 root 1627: printf ("\tif (!cctrue(%d)) {\n\t", curi->cc);
1.1 root 1628: genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src");
1629:
1630: printf ("\t\tif (src) {\n");
1631: if (using_exception_3) {
1632: printf ("\t\t\tif (offs & 1) {\n");
1.1.1.8 root 1633: 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 1634: printf ("\t\t\tlast_fault_for_exception_3 = m68k_getpc() + 2 + (uae_s32)offs + 2;\n");
1.1.1.12 root 1635: printf ("\t\t\tlast_op_for_exception_3 = opcode; Exception(3,0,M68000_EXC_SRC_CPU); goto %s;\n", endlabelstr);
1.1 root 1636: printf ("\t\t}\n");
1637: need_endlabel = 1;
1638: }
1639: printf ("\t\t\tm68k_incpc((uae_s32)offs + 2);\n");
1640: fill_prefetch_0 ();
1.1.1.2 root 1641: printf ("\t\t\treturn 10;\n");
1642: printf ("\t\t} else {\n\t\t\t");
1643: {
1644: int tmp_offset = m68k_pc_offset;
1645: sync_m68k_pc(); /* not so nice to call it here... */
1646: m68k_pc_offset = tmp_offset;
1647: }
1648: printf ("\t\t\treturn 14;\n");
1649: printf ("\t\t}\n");
1.1 root 1650: printf ("\t}\n");
1651: insn_n_cycles = 12;
1652: need_endlabel = 1;
1653: break;
1654: case i_Scc:
1655: genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
1656: start_brace ();
1657: printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc);
1658: genastore ("val", curi->smode, "srcreg", curi->size, "src");
1.1.1.8 root 1659: if (curi->smode!=Dreg) insn_n_cycles += 4;
1660: else
1661: { /* [NP] if result is TRUE, we return 6 instead of 4 */
1662: printf ("\tif (val) { m68k_incpc(2) ; return 4+2; }\n");
1663: }
1.1 root 1664: break;
1665: case i_DIVU:
1666: printf ("\tuaecptr oldpc = m68k_getpc();\n");
1667: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
1668: genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1669: sync_m68k_pc ();
1670: /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends
1671: * on this (actually, it's doing a DIVS). */
1.1.1.12 root 1672: printf ("\tif (src == 0) { SET_VFLG (0); Exception (5, oldpc,M68000_EXC_SRC_CPU); goto %s; } else {\n", endlabelstr);
1.1 root 1673: printf ("\tuae_u32 newv = (uae_u32)dst / (uae_u32)(uae_u16)src;\n");
1674: printf ("\tuae_u32 rem = (uae_u32)dst %% (uae_u32)(uae_u16)src;\n");
1675: /* The N flag appears to be set each time there is an overflow.
1676: * Weird. */
1677: printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
1678: genflags (flag_logical, sz_word, "newv", "", "");
1679: printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
1680: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1681: printf ("\t}\n");
1682: printf ("\t}\n");
1.1.1.8 root 1683: // insn_n_cycles += 136;
1684: printf ("\tretcycles = getDivu68kCycles((uae_u32)dst, (uae_u16)src);\n");
1685: sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
1.1 root 1686: need_endlabel = 1;
1687: break;
1688: case i_DIVS:
1689: printf ("\tuaecptr oldpc = m68k_getpc();\n");
1690: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
1691: genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1692: sync_m68k_pc ();
1.1.1.12 root 1693: printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc,M68000_EXC_SRC_CPU); goto %s; } else {\n", endlabelstr);
1.1 root 1694: printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n");
1695: printf ("\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n");
1696: printf ("\tif ((newv & 0xffff8000) != 0 && (newv & 0xffff8000) != 0xffff8000) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n");
1697: printf ("\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n");
1698: genflags (flag_logical, sz_word, "newv", "", "");
1699: printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n");
1700: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1701: printf ("\t}\n");
1702: printf ("\t}\n");
1.1.1.8 root 1703: // insn_n_cycles += 154;
1704: printf ("\tretcycles = getDivs68kCycles((uae_s32)dst, (uae_s16)src);\n");
1705: sprintf(exactCpuCycles," return (%i+retcycles);", insn_n_cycles);
1.1 root 1706: need_endlabel = 1;
1707: break;
1708: case i_MULU:
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_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n");
1713: genflags (flag_logical, sz_long, "newv", "", "");
1714: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1.1.1.8 root 1715: /* [NP] number of cycles is 38 + 2n + ea time ; n is the number of 1 bits in src */
1716: insn_n_cycles += 38-4; /* insn_n_cycles is already initialized to 4 instead of 0 */
1717: printf ("\twhile (src) { if (src & 1) retcycles++; src = (uae_u16)src >> 1; }\n");
1718: sprintf(exactCpuCycles," return (%i+retcycles*2);", insn_n_cycles);
1.1 root 1719: break;
1720: case i_MULS:
1721: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
1722: genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
1723: start_brace ();
1724: printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n");
1.1.1.8 root 1725: printf ("\tuae_u32 src2;\n");
1.1 root 1726: genflags (flag_logical, sz_long, "newv", "", "");
1727: genastore ("newv", curi->dmode, "dstreg", sz_long, "dst");
1.1.1.8 root 1728: /* [NP] number of cycles is 38 + 2n + ea time ; n is the number of 01 or 10 patterns in src expanded to 17 bits */
1729: insn_n_cycles += 38-4; /* insn_n_cycles is already initialized to 4 instead of 0 */
1730: printf ("\tsrc2 = ((uae_u32)src) << 1;\n");
1731: printf ("\twhile (src2) { if ( ( (src2 & 3) == 1 ) || ( (src2 & 3) == 2 ) ) retcycles++; src2 >>= 1; }\n");
1732: sprintf(exactCpuCycles," return (%i+retcycles*2);", insn_n_cycles);
1.1 root 1733: break;
1734: case i_CHK:
1735: printf ("\tuaecptr oldpc = m68k_getpc();\n");
1736: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1737: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1.1.1.8 root 1738: sync_m68k_pc ();
1.1.1.12 root 1739: printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1740: printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n", endlabelstr);
1.1 root 1741: need_endlabel = 1;
1.1.1.2 root 1742: insn_n_cycles += 6;
1.1 root 1743: break;
1744:
1745: case i_CHK2:
1746: printf ("\tuaecptr oldpc = m68k_getpc();\n");
1747: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
1748: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1749: printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n");
1750: switch (curi->size) {
1751: case sz_byte:
1752: printf ("\tlower=(uae_s32)(uae_s8)get_byte(dsta); upper = (uae_s32)(uae_s8)get_byte(dsta+1);\n");
1753: printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s8)reg;\n");
1754: break;
1755: case sz_word:
1756: printf ("\tlower=(uae_s32)(uae_s16)get_word(dsta); upper = (uae_s32)(uae_s16)get_word(dsta+2);\n");
1757: printf ("\tif ((extra & 0x8000) == 0) reg = (uae_s32)(uae_s16)reg;\n");
1758: break;
1759: case sz_long:
1760: printf ("\tlower=get_long(dsta); upper = get_long(dsta+4);\n");
1761: break;
1762: default:
1763: abort ();
1764: }
1765: printf ("\tSET_ZFLG (upper == reg || lower == reg);\n");
1766: printf ("\tSET_CFLG (lower <= upper ? reg < lower || reg > upper : reg > upper || reg < lower);\n");
1.1.1.8 root 1767: sync_m68k_pc ();
1.1.1.12 root 1768: printf ("\tif ((extra & 0x800) && GET_CFLG) { Exception(6,oldpc,M68000_EXC_SRC_CPU); goto %s; }\n}\n", endlabelstr);
1.1 root 1769: need_endlabel = 1;
1770: break;
1771:
1772: case i_ASR:
1773: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1774: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1775: start_brace ();
1776: switch (curi->size) {
1777: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1778: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1779: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1780: default: abort ();
1781: }
1782: printf ("\tuae_u32 sign = (%s & val) >> %d;\n", cmask (curi->size), bit_size (curi->size) - 1);
1783: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1784: printf ("\tretcycles = cnt;\n");
1.1 root 1785: printf ("\tCLEAR_CZNV;\n");
1786: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
1787: printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size));
1788: printf ("\t\tSET_CFLG (sign);\n");
1789: duplicate_carry ();
1790: if (source_is_imm1_8 (curi))
1791: printf ("\t} else {\n");
1792: else
1793: printf ("\t} else if (cnt > 0) {\n");
1794: printf ("\t\tval >>= cnt - 1;\n");
1795: printf ("\t\tSET_CFLG (val & 1);\n");
1796: duplicate_carry ();
1797: printf ("\t\tval >>= 1;\n");
1798: printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n",
1799: bit_mask (curi->size),
1800: bit_size (curi->size));
1801: printf ("\t\tval &= %s;\n", bit_mask (curi->size));
1802: printf ("\t}\n");
1803: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1804: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1805: if(curi->size==sz_long)
1806: strcpy(exactCpuCycles," return (8+retcycles*2);");
1807: else
1808: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1809: break;
1810: case i_ASL:
1811: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1812: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1813: start_brace ();
1814: switch (curi->size) {
1815: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1816: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1817: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1818: default: abort ();
1819: }
1820: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1821: printf ("\tretcycles = cnt;\n");
1.1 root 1822: printf ("\tCLEAR_CZNV;\n");
1823: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
1824: printf ("\t\tSET_VFLG (val != 0);\n");
1825: printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
1826: bit_size (curi->size));
1827: duplicate_carry ();
1828: printf ("\t\tval = 0;\n");
1829: if (source_is_imm1_8 (curi))
1830: printf ("\t} else {\n");
1831: else
1832: printf ("\t} else if (cnt > 0) {\n");
1833: printf ("\t\tuae_u32 mask = (%s << (%d - cnt)) & %s;\n",
1834: bit_mask (curi->size),
1835: bit_size (curi->size) - 1,
1836: bit_mask (curi->size));
1837: printf ("\t\tSET_VFLG ((val & mask) != mask && (val & mask) != 0);\n");
1838: printf ("\t\tval <<= cnt - 1;\n");
1839: printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
1840: duplicate_carry ();
1841: printf ("\t\tval <<= 1;\n");
1842: printf ("\t\tval &= %s;\n", bit_mask (curi->size));
1843: printf ("\t}\n");
1844: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1845: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1846: if(curi->size==sz_long)
1847: strcpy(exactCpuCycles," return (8+retcycles*2);");
1848: else
1849: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1850: break;
1851: case i_LSR:
1852: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1853: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1854: start_brace ();
1855: switch (curi->size) {
1856: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1857: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1858: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1859: default: abort ();
1860: }
1861: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1862: printf ("\tretcycles = cnt;\n");
1.1 root 1863: printf ("\tCLEAR_CZNV;\n");
1864: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
1865: printf ("\t\tSET_CFLG ((cnt == %d) & (val >> %d));\n",
1866: bit_size (curi->size), bit_size (curi->size) - 1);
1867: duplicate_carry ();
1868: printf ("\t\tval = 0;\n");
1869: if (source_is_imm1_8 (curi))
1870: printf ("\t} else {\n");
1871: else
1872: printf ("\t} else if (cnt > 0) {\n");
1873: printf ("\t\tval >>= cnt - 1;\n");
1874: printf ("\t\tSET_CFLG (val & 1);\n");
1875: duplicate_carry ();
1876: printf ("\t\tval >>= 1;\n");
1877: printf ("\t}\n");
1878: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1879: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1880: if(curi->size==sz_long)
1881: strcpy(exactCpuCycles," return (8+retcycles*2);");
1882: else
1883: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1884: break;
1885: case i_LSL:
1886: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1887: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1888: start_brace ();
1889: switch (curi->size) {
1890: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1891: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1892: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1893: default: abort ();
1894: }
1895: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1896: printf ("\tretcycles = cnt;\n");
1.1 root 1897: printf ("\tCLEAR_CZNV;\n");
1898: printf ("\tif (cnt >= %d) {\n", bit_size (curi->size));
1899: printf ("\t\tSET_CFLG (cnt == %d ? val & 1 : 0);\n",
1900: bit_size (curi->size));
1901: duplicate_carry ();
1902: printf ("\t\tval = 0;\n");
1903: if (source_is_imm1_8 (curi))
1904: printf ("\t} else {\n");
1905: else
1906: printf ("\t} else if (cnt > 0) {\n");
1907: printf ("\t\tval <<= (cnt - 1);\n");
1908: printf ("\t\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
1909: duplicate_carry ();
1910: printf ("\t\tval <<= 1;\n");
1911: printf ("\tval &= %s;\n", bit_mask (curi->size));
1912: printf ("\t}\n");
1913: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1914: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1915: if(curi->size==sz_long)
1916: strcpy(exactCpuCycles," return (8+retcycles*2);");
1917: else
1918: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1919: break;
1920: case i_ROL:
1921: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1922: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1923: start_brace ();
1924: switch (curi->size) {
1925: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1926: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1927: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1928: default: abort ();
1929: }
1930: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1931: printf ("\tretcycles = cnt;\n");
1.1 root 1932: printf ("\tCLEAR_CZNV;\n");
1933: if (source_is_imm1_8 (curi))
1934: printf ("{");
1935: else
1936: printf ("\tif (cnt > 0) {\n");
1937: printf ("\tuae_u32 loval;\n");
1938: printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
1939: printf ("\tloval = val >> (%d - cnt);\n", bit_size (curi->size));
1940: printf ("\tval <<= cnt;\n");
1941: printf ("\tval |= loval;\n");
1942: printf ("\tval &= %s;\n", bit_mask (curi->size));
1943: printf ("\tSET_CFLG (val & 1);\n");
1944: printf ("}\n");
1945: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1946: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1947: if(curi->size==sz_long)
1948: strcpy(exactCpuCycles," return (8+retcycles*2);");
1949: else
1950: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1951: break;
1952: case i_ROR:
1953: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1954: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1955: start_brace ();
1956: switch (curi->size) {
1957: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1958: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1959: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1960: default: abort ();
1961: }
1962: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1963: printf ("\tretcycles = cnt;\n");
1.1 root 1964: printf ("\tCLEAR_CZNV;\n");
1965: if (source_is_imm1_8 (curi))
1966: printf ("{");
1967: else
1968: printf ("\tif (cnt > 0) {");
1969: printf ("\tuae_u32 hival;\n");
1970: printf ("\tcnt &= %d;\n", bit_size (curi->size) - 1);
1971: printf ("\thival = val << (%d - cnt);\n", bit_size (curi->size));
1972: printf ("\tval >>= cnt;\n");
1973: printf ("\tval |= hival;\n");
1974: printf ("\tval &= %s;\n", bit_mask (curi->size));
1975: printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1);
1976: printf ("\t}\n");
1977: genflags (flag_logical_noclobber, curi->size, "val", "", "");
1978: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 1979: if(curi->size==sz_long)
1980: strcpy(exactCpuCycles," return (8+retcycles*2);");
1981: else
1982: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 1983: break;
1984: case i_ROXL:
1985: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
1986: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
1987: start_brace ();
1988: switch (curi->size) {
1989: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
1990: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
1991: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
1992: default: abort ();
1993: }
1994: printf ("\tcnt &= 63;\n");
1.1.1.2 root 1995: printf ("\tretcycles = cnt;\n");
1.1 root 1996: printf ("\tCLEAR_CZNV;\n");
1997: if (source_is_imm1_8 (curi))
1998: printf ("{");
1999: else {
2000: force_range_for_rox ("cnt", curi->size);
2001: printf ("\tif (cnt > 0) {\n");
2002: }
2003: printf ("\tcnt--;\n");
2004: printf ("\t{\n\tuae_u32 carry;\n");
2005: printf ("\tuae_u32 loval = val >> (%d - cnt);\n", bit_size (curi->size) - 1);
2006: printf ("\tcarry = loval & 1;\n");
2007: printf ("\tval = (((val << 1) | GET_XFLG) << cnt) | (loval >> 1);\n");
2008: printf ("\tSET_XFLG (carry);\n");
2009: printf ("\tval &= %s;\n", bit_mask (curi->size));
2010: printf ("\t} }\n");
2011: printf ("\tSET_CFLG (GET_XFLG);\n");
2012: genflags (flag_logical_noclobber, curi->size, "val", "", "");
2013: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 2014: if(curi->size==sz_long)
2015: strcpy(exactCpuCycles," return (8+retcycles*2);");
2016: else
2017: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 2018: break;
2019: case i_ROXR:
2020: genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
2021: genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
2022: start_brace ();
2023: switch (curi->size) {
2024: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
2025: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
2026: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2027: default: abort ();
2028: }
2029: printf ("\tcnt &= 63;\n");
1.1.1.2 root 2030: printf ("\tretcycles = cnt;\n");
1.1 root 2031: printf ("\tCLEAR_CZNV;\n");
2032: if (source_is_imm1_8 (curi))
2033: printf ("{");
2034: else {
2035: force_range_for_rox ("cnt", curi->size);
2036: printf ("\tif (cnt > 0) {\n");
2037: }
2038: printf ("\tcnt--;\n");
2039: printf ("\t{\n\tuae_u32 carry;\n");
2040: printf ("\tuae_u32 hival = (val << 1) | GET_XFLG;\n");
2041: printf ("\thival <<= (%d - cnt);\n", bit_size (curi->size) - 1);
2042: printf ("\tval >>= cnt;\n");
2043: printf ("\tcarry = val & 1;\n");
2044: printf ("\tval >>= 1;\n");
2045: printf ("\tval |= hival;\n");
2046: printf ("\tSET_XFLG (carry);\n");
2047: printf ("\tval &= %s;\n", bit_mask (curi->size));
2048: printf ("\t} }\n");
2049: printf ("\tSET_CFLG (GET_XFLG);\n");
2050: genflags (flag_logical_noclobber, curi->size, "val", "", "");
2051: genastore ("val", curi->dmode, "dstreg", curi->size, "data");
1.1.1.2 root 2052: if(curi->size==sz_long)
2053: strcpy(exactCpuCycles," return (8+retcycles*2);");
2054: else
2055: strcpy(exactCpuCycles," return (6+retcycles*2);");
1.1 root 2056: break;
2057: case i_ASRW:
2058: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2059: start_brace ();
2060: switch (curi->size) {
2061: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
2062: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
2063: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2064: default: abort ();
2065: }
2066: printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
2067: printf ("\tuae_u32 cflg = val & 1;\n");
2068: printf ("\tval = (val >> 1) | sign;\n");
2069: genflags (flag_logical, curi->size, "val", "", "");
2070: printf ("\tSET_CFLG (cflg);\n");
2071: duplicate_carry ();
2072: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2073: break;
2074: case i_ASLW:
2075: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2076: start_brace ();
2077: switch (curi->size) {
2078: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
2079: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
2080: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2081: default: abort ();
2082: }
2083: printf ("\tuae_u32 sign = %s & val;\n", cmask (curi->size));
2084: printf ("\tuae_u32 sign2;\n");
2085: printf ("\tval <<= 1;\n");
2086: genflags (flag_logical, curi->size, "val", "", "");
2087: printf ("\tsign2 = %s & val;\n", cmask (curi->size));
2088: printf ("\tSET_CFLG (sign != 0);\n");
2089: duplicate_carry ();
2090:
2091: printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n");
2092: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2093: break;
2094: case i_LSRW:
2095: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2096: start_brace ();
2097: switch (curi->size) {
2098: case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break;
2099: case sz_word: printf ("\tuae_u32 val = (uae_u16)data;\n"); break;
2100: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2101: default: abort ();
2102: }
2103: printf ("\tuae_u32 carry = val & 1;\n");
2104: printf ("\tval >>= 1;\n");
2105: genflags (flag_logical, curi->size, "val", "", "");
2106: printf ("SET_CFLG (carry);\n");
2107: duplicate_carry ();
2108: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2109: break;
2110: case i_LSLW:
2111: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2112: start_brace ();
2113: switch (curi->size) {
2114: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2115: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2116: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2117: default: abort ();
2118: }
2119: printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
2120: printf ("\tval <<= 1;\n");
2121: genflags (flag_logical, curi->size, "val", "", "");
2122: printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
2123: duplicate_carry ();
2124: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2125: break;
2126: case i_ROLW:
2127: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2128: start_brace ();
2129: switch (curi->size) {
2130: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2131: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2132: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2133: default: abort ();
2134: }
2135: printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
2136: printf ("\tval <<= 1;\n");
2137: printf ("\tif (carry) val |= 1;\n");
2138: genflags (flag_logical, curi->size, "val", "", "");
2139: printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
2140: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2141: break;
2142: case i_RORW:
2143: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2144: start_brace ();
2145: switch (curi->size) {
2146: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2147: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2148: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2149: default: abort ();
2150: }
2151: printf ("\tuae_u32 carry = val & 1;\n");
2152: printf ("\tval >>= 1;\n");
2153: printf ("\tif (carry) val |= %s;\n", cmask (curi->size));
2154: genflags (flag_logical, curi->size, "val", "", "");
2155: printf ("SET_CFLG (carry);\n");
2156: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2157: break;
2158: case i_ROXLW:
2159: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2160: start_brace ();
2161: switch (curi->size) {
2162: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2163: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2164: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2165: default: abort ();
2166: }
2167: printf ("\tuae_u32 carry = val & %s;\n", cmask (curi->size));
2168: printf ("\tval <<= 1;\n");
2169: printf ("\tif (GET_XFLG) val |= 1;\n");
2170: genflags (flag_logical, curi->size, "val", "", "");
2171: printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1);
2172: duplicate_carry ();
2173: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2174: break;
2175: case i_ROXRW:
2176: genamode (curi->smode, "srcreg", curi->size, "data", 1, 0);
2177: start_brace ();
2178: switch (curi->size) {
2179: case sz_byte: printf ("\tuae_u8 val = data;\n"); break;
2180: case sz_word: printf ("\tuae_u16 val = data;\n"); break;
2181: case sz_long: printf ("\tuae_u32 val = data;\n"); break;
2182: default: abort ();
2183: }
2184: printf ("\tuae_u32 carry = val & 1;\n");
2185: printf ("\tval >>= 1;\n");
2186: printf ("\tif (GET_XFLG) val |= %s;\n", cmask (curi->size));
2187: genflags (flag_logical, curi->size, "val", "", "");
2188: printf ("SET_CFLG (carry);\n");
2189: duplicate_carry ();
2190: genastore ("val", curi->smode, "srcreg", curi->size, "data");
2191: break;
2192: case i_MOVEC2:
2193: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
2194: start_brace ();
2195: printf ("\tint regno = (src >> 12) & 15;\n");
2196: printf ("\tuae_u32 *regp = regs.regs + regno;\n");
2197: printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
2198: break;
2199: case i_MOVE2C:
2200: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
2201: start_brace ();
2202: printf ("\tint regno = (src >> 12) & 15;\n");
2203: printf ("\tuae_u32 *regp = regs.regs + regno;\n");
2204: printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr);
2205: break;
2206: case i_CAS:
2207: {
2208: int old_brace_level;
2209: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
2210: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
2211: start_brace ();
2212: printf ("\tint ru = (src >> 6) & 7;\n");
2213: printf ("\tint rc = src & 7;\n");
2214: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst");
2215: printf ("\tif (GET_ZFLG)");
2216: old_brace_level = n_braces;
2217: start_brace ();
2218: genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst");
2219: pop_braces (old_brace_level);
2220: printf ("else");
2221: start_brace ();
2222: printf ("m68k_dreg(regs, rc) = dst;\n");
2223: pop_braces (old_brace_level);
2224: }
2225: break;
2226: case i_CAS2:
2227: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2228: printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n");
2229: printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n");
2230: if (curi->size == sz_word) {
2231: int old_brace_level = n_braces;
2232: printf ("\tuae_u16 dst1 = get_word(rn1), dst2 = get_word(rn2);\n");
2233: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
2234: printf ("\tif (GET_ZFLG) {\n");
2235: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
2236: printf ("\tif (GET_ZFLG) {\n");
2237: printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
2238: printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
2239: printf ("\t}}\n");
2240: pop_braces (old_brace_level);
2241: printf ("\tif (! GET_ZFLG) {\n");
2242: printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n");
2243: printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n");
2244: printf ("\t}\n");
2245: } else {
2246: int old_brace_level = n_braces;
2247: printf ("\tuae_u32 dst1 = get_long(rn1), dst2 = get_long(rn2);\n");
2248: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1");
2249: printf ("\tif (GET_ZFLG) {\n");
2250: genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2");
2251: printf ("\tif (GET_ZFLG) {\n");
2252: printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n");
2253: printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n");
2254: printf ("\t}}\n");
2255: pop_braces (old_brace_level);
2256: printf ("\tif (! GET_ZFLG) {\n");
2257: printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n");
2258: printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n");
2259: printf ("\t}\n");
2260: }
2261: break;
2262: case i_MOVES: /* ignore DFC and SFC because we have no MMU */
2263: {
2264: int old_brace_level;
2265: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2266: printf ("\tif (extra & 0x800)\n");
2267: old_brace_level = n_braces;
2268: start_brace ();
2269: printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n");
2270: genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
2271: genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
2272: pop_braces (old_brace_level);
2273: printf ("else");
2274: start_brace ();
2275: genamode (curi->dmode, "dstreg", curi->size, "src", 1, 0);
2276: printf ("\tif (extra & 0x8000) {\n");
2277: switch (curi->size) {
2278: case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break;
2279: case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break;
2280: case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break;
2281: default: abort ();
2282: }
2283: printf ("\t} else {\n");
2284: genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "");
2285: printf ("\t}\n");
2286: pop_braces (old_brace_level);
2287: }
2288: break;
2289: case i_BKPT: /* only needed for hardware emulators */
2290: sync_m68k_pc ();
2291: printf ("\top_illg(opcode);\n");
2292: break;
2293: case i_CALLM: /* not present in 68030 */
2294: sync_m68k_pc ();
2295: printf ("\top_illg(opcode);\n");
2296: break;
2297: case i_RTM: /* not present in 68030 */
2298: sync_m68k_pc ();
2299: printf ("\top_illg(opcode);\n");
2300: break;
2301: case i_TRAPcc:
2302: if (curi->smode != am_unknown && curi->smode != am_illg)
2303: genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
1.1.1.12 root 2304: printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc(),M68000_EXC_SRC_CPU); goto %s; }\n", curi->cc, endlabelstr);
1.1 root 2305: need_endlabel = 1;
2306: break;
2307: case i_DIVL:
2308: sync_m68k_pc ();
2309: start_brace ();
2310: printf ("\tuaecptr oldpc = m68k_getpc();\n");
2311: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2312: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
2313: sync_m68k_pc ();
2314: printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n");
2315: break;
2316: case i_MULL:
2317: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2318: genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
2319: sync_m68k_pc ();
2320: printf ("\tm68k_mull(opcode, dst, extra);\n");
2321: break;
2322: case i_BFTST:
2323: case i_BFEXTU:
2324: case i_BFCHG:
2325: case i_BFEXTS:
2326: case i_BFCLR:
2327: case i_BFFFO:
2328: case i_BFSET:
2329: case i_BFINS:
2330: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2331: genamode (curi->dmode, "dstreg", sz_long, "dst", 2, 0);
2332: start_brace ();
2333: printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n");
2334: printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n");
2335: if (curi->dmode == Dreg) {
2336: printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg) << (offset & 0x1f);\n");
2337: } else {
2338: printf ("\tuae_u32 tmp,bf0,bf1;\n");
2339: printf ("\tdsta += (offset >> 3) | (offset & 0x80000000 ? ~0x1fffffff : 0);\n");
2340: printf ("\tbf0 = get_long(dsta);bf1 = get_byte(dsta+4) & 0xff;\n");
2341: printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n");
2342: }
2343: printf ("\ttmp >>= (32 - width);\n");
2344: printf ("\tSET_NFLG (tmp & (1 << (width-1)) ? 1 : 0);\n");
2345: printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n");
2346: switch (curi->mnemo) {
2347: case i_BFTST:
2348: break;
2349: case i_BFEXTU:
2350: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
2351: break;
2352: case i_BFCHG:
2353: printf ("\ttmp = ~tmp;\n");
2354: break;
2355: case i_BFEXTS:
2356: printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n");
2357: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n");
2358: break;
2359: case i_BFCLR:
2360: printf ("\ttmp = 0;\n");
2361: break;
2362: case i_BFFFO:
2363: printf ("\t{ uae_u32 mask = 1 << (width-1);\n");
2364: printf ("\twhile (mask) { if (tmp & mask) break; mask >>= 1; offset++; }}\n");
2365: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = offset;\n");
2366: break;
2367: case i_BFSET:
2368: printf ("\ttmp = 0xffffffff;\n");
2369: break;
2370: case i_BFINS:
2371: printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n");
1.1.1.4 root 2372: printf ("\tSET_NFLG (tmp & (1 << (width - 1)) ? 1 : 0);\n");
2373: printf ("\tSET_ZFLG (tmp == 0);\n");
1.1 root 2374: break;
2375: default:
2376: break;
2377: }
2378: if (curi->mnemo == i_BFCHG
2379: || curi->mnemo == i_BFCLR
2380: || curi->mnemo == i_BFSET
2381: || curi->mnemo == i_BFINS)
2382: {
2383: printf ("\ttmp <<= (32 - width);\n");
2384: if (curi->dmode == Dreg) {
2385: printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ((offset & 0x1f) == 0 ? 0 :\n");
2386: printf ("\t\t(0xffffffff << (32 - (offset & 0x1f))))) |\n");
2387: printf ("\t\t(tmp >> (offset & 0x1f)) |\n");
2388: printf ("\t\t(((offset & 0x1f) + width) >= 32 ? 0 :\n");
2389: printf (" (m68k_dreg(regs, dstreg) & ((uae_u32)0xffffffff >> ((offset & 0x1f) + width))));\n");
2390: } else {
2391: printf ("\tbf0 = (bf0 & (0xff000000 << (8 - (offset & 7)))) |\n");
2392: printf ("\t\t(tmp >> (offset & 7)) |\n");
2393: printf ("\t\t(((offset & 7) + width) >= 32 ? 0 :\n");
2394: printf ("\t\t (bf0 & ((uae_u32)0xffffffff >> ((offset & 7) + width))));\n");
2395: printf ("\tput_long(dsta,bf0 );\n");
2396: printf ("\tif (((offset & 7) + width) > 32) {\n");
2397: printf ("\t\tbf1 = (bf1 & (0xff >> (width - 32 + (offset & 7)))) |\n");
2398: printf ("\t\t\t(tmp << (8 - (offset & 7)));\n");
2399: printf ("\t\tput_byte(dsta+4,bf1);\n");
2400: printf ("\t}\n");
2401: }
2402: }
2403: break;
2404: case i_PACK:
2405: if (curi->smode == Dreg) {
2406: printf ("\tuae_u16 val = m68k_dreg(regs, srcreg) + %s;\n", gen_nextiword ());
2407: printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n");
2408: } else {
2409: printf ("\tuae_u16 val;\n");
2410: printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
2411: printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n");
2412: printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
2413: printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg)) << 8)) + %s;\n", gen_nextiword ());
2414: printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
2415: printf ("\tput_byte(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n");
2416: }
2417: break;
2418: case i_UNPK:
2419: if (curi->smode == Dreg) {
2420: printf ("\tuae_u16 val = m68k_dreg(regs, srcreg);\n");
2421: printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
2422: printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n");
2423: } else {
2424: printf ("\tuae_u16 val;\n");
2425: printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n");
2426: printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n");
2427: printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ());
2428: printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
2429: printf ("\tput_byte(m68k_areg(regs, dstreg),val);\n");
2430: printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n");
2431: printf ("\tput_byte(m68k_areg(regs, dstreg),val >> 8);\n");
2432: }
2433: break;
2434: case i_TAS:
2435: genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
2436: genflags (flag_logical, curi->size, "src", "", "");
2437: printf ("\tsrc |= 0x80;\n");
2438: genastore ("src", curi->smode, "srcreg", curi->size, "src");
1.1.1.2 root 2439: if( curi->smode!=Dreg ) insn_n_cycles += 2;
1.1 root 2440: break;
2441: case i_FPP:
2442: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2443: sync_m68k_pc ();
2444: printf ("\tfpp_opp(opcode,extra);\n");
2445: break;
2446: case i_FDBcc:
2447: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2448: sync_m68k_pc ();
2449: printf ("\tfdbcc_opp(opcode,extra);\n");
2450: break;
2451: case i_FScc:
2452: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2453: sync_m68k_pc ();
2454: printf ("\tfscc_opp(opcode,extra);\n");
2455: break;
2456: case i_FTRAPcc:
2457: sync_m68k_pc ();
2458: start_brace ();
2459: printf ("\tuaecptr oldpc = m68k_getpc();\n");
2460: if (curi->smode != am_unknown && curi->smode != am_illg)
2461: genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0);
2462: sync_m68k_pc ();
2463: printf ("\tftrapcc_opp(opcode,oldpc);\n");
2464: break;
2465: case i_FBcc:
2466: sync_m68k_pc ();
2467: start_brace ();
2468: printf ("\tuaecptr pc = m68k_getpc();\n");
2469: genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0);
2470: sync_m68k_pc ();
2471: printf ("\tfbcc_opp(opcode,pc,extra);\n");
2472: break;
2473: case i_FSAVE:
2474: sync_m68k_pc ();
2475: printf ("\tfsave_opp(opcode);\n");
2476: break;
2477: case i_FRESTORE:
2478: sync_m68k_pc ();
2479: printf ("\tfrestore_opp(opcode);\n");
2480: break;
2481:
2482: case i_CINVL:
2483: case i_CINVP:
2484: case i_CINVA:
2485: case i_CPUSHL:
2486: case i_CPUSHP:
2487: case i_CPUSHA:
2488: break;
2489: case i_MOVE16:
1.1.1.4 root 2490: if ((opcode & 0xfff8) == 0xf620) {
2491: /* MOVE16 (Ax)+,(Ay)+ */
2492: printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n");
2493: printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword());
2494: printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n");
2495: printf ("\tput_long(memd, get_long(mems));\n");
2496: printf ("\tput_long(memd+4, get_long(mems+4));\n");
2497: printf ("\tput_long(memd+8, get_long(mems+8));\n");
2498: printf ("\tput_long(memd+12, get_long(mems+12));\n");
2499: printf ("\tif (srcreg != dstreg)\n");
2500: printf ("\tm68k_areg(regs, srcreg) += 16;\n");
2501: printf ("\tm68k_areg(regs, dstreg) += 16;\n");
2502: } else {
2503: /* Other variants */
2504: genamode (curi->smode, "srcreg", curi->size, "mems", 0, 2);
2505: genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2);
2506: printf ("\tmemsa &= ~15;\n");
2507: printf ("\tmemda &= ~15;\n");
2508: printf ("\tput_long(memda, get_long(memsa));\n");
2509: printf ("\tput_long(memda+4, get_long(memsa+4));\n");
2510: printf ("\tput_long(memda+8, get_long(memsa+8));\n");
2511: printf ("\tput_long(memda+12, get_long(memsa+12));\n");
2512: if ((opcode & 0xfff8) == 0xf600)
2513: printf ("\tm68k_areg(regs, srcreg) += 16;\n");
2514: else if ((opcode & 0xfff8) == 0xf608)
2515: printf ("\tm68k_areg(regs, dstreg) += 16;\n");
2516: }
1.1 root 2517: break;
2518:
2519: case i_MMUOP:
2520: genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0);
2521: sync_m68k_pc ();
2522: printf ("\tmmu_op(opcode,extra);\n");
2523: break;
2524: default:
2525: abort ();
2526: break;
2527: }
2528: finish_braces ();
2529: sync_m68k_pc ();
2530: }
2531:
2532: static void generate_includes (FILE * f)
2533: {
2534: fprintf (f, "#include \"sysdeps.h\"\n");
2535: fprintf (f, "#include \"hatari-glue.h\"\n");
2536: fprintf (f, "#include \"maccess.h\"\n");
2537: fprintf (f, "#include \"memory.h\"\n");
2538: fprintf (f, "#include \"newcpu.h\"\n");
2539: fprintf (f, "#include \"cputbl.h\"\n");
2540: fprintf (f, "#define CPUFUNC(x) x##_ff\n"
2541: "#ifdef NOFLAGS\n"
2542: "#include \"noflags.h\"\n"
2543: "#endif\n");
2544: }
2545:
2546: static int postfix;
2547:
2548: static void generate_one_opcode (int rp)
2549: {
2550: int i;
2551: uae_u16 smsk, dmsk;
2552: long int opcode = opcode_map[rp];
2553:
1.1.1.2 root 2554: exactCpuCycles[0] = 0; /* Default: not used */
2555:
1.1 root 2556: if (table68k[opcode].mnemo == i_ILLG
2557: || table68k[opcode].clev > cpu_level)
2558: return;
2559:
2560: for (i = 0; lookuptab[i].name[0]; i++) {
2561: if (table68k[opcode].mnemo == lookuptab[i].mnemo)
2562: break;
2563: }
2564:
2565: if (table68k[opcode].handler != -1)
2566: return;
2567:
2568: if (opcode_next_clev[rp] != cpu_level) {
2569: fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp],
2570: opcode, lookuptab[i].name);
2571: return;
2572: }
2573: fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, lookuptab[i].name);
2574: fprintf (headerfile, "extern cpuop_func op_%lx_%d_nf;\n", opcode, postfix);
2575: fprintf (headerfile, "extern cpuop_func op_%lx_%d_ff;\n", opcode, postfix);
2576: printf ("unsigned long REGPARAM2 CPUFUNC(op_%lx_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name);
2577:
2578: switch (table68k[opcode].stype) {
2579: case 0: smsk = 7; break;
2580: case 1: smsk = 255; break;
2581: case 2: smsk = 15; break;
2582: case 3: smsk = 7; break;
2583: case 4: smsk = 7; break;
2584: case 5: smsk = 63; break;
1.1.1.4 root 2585: case 7: smsk = 3; break;
1.1 root 2586: default: abort ();
2587: }
2588: dmsk = 7;
2589:
2590: next_cpu_level = -1;
2591: if (table68k[opcode].suse
2592: && table68k[opcode].smode != imm && table68k[opcode].smode != imm0
2593: && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2
2594: && table68k[opcode].smode != absw && table68k[opcode].smode != absl
2595: && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16)
2596: {
2597: if (table68k[opcode].spos == -1) {
2598: if (((int) table68k[opcode].sreg) >= 128)
2599: printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].sreg);
2600: else
2601: printf ("\tuae_u32 srcreg = %d;\n", (int) table68k[opcode].sreg);
2602: } else {
2603: char source[100];
2604: int pos = table68k[opcode].spos;
2605:
2606: if (pos)
2607: sprintf (source, "((opcode >> %d) & %d)", pos, smsk);
2608: else
2609: sprintf (source, "(opcode & %d)", smsk);
2610:
2611: if (table68k[opcode].stype == 3)
2612: printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source);
2613: else if (table68k[opcode].stype == 1)
2614: printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source);
2615: else
2616: printf ("\tuae_u32 srcreg = %s;\n", source);
2617: }
2618: }
2619: if (table68k[opcode].duse
2620: /* Yes, the dmode can be imm, in case of LINK or DBcc */
2621: && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0
2622: && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2
2623: && table68k[opcode].dmode != absw && table68k[opcode].dmode != absl)
2624: {
2625: if (table68k[opcode].dpos == -1) {
2626: if (((int) table68k[opcode].dreg) >= 128)
2627: printf ("\tuae_u32 dstreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].dreg);
2628: else
2629: printf ("\tuae_u32 dstreg = %d;\n", (int) table68k[opcode].dreg);
2630: } else {
2631: int pos = table68k[opcode].dpos;
2632: #if 0
2633: /* Check that we can do the little endian optimization safely. */
2634: if (pos < 8 && (dmsk >> (8 - pos)) != 0)
2635: abort ();
2636: #endif
2637: if (pos)
2638: printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
2639: pos, dmsk);
2640: else
2641: printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
2642: }
2643: }
2644: need_endlabel = 0;
2645: endlabelno++;
2646: sprintf (endlabelstr, "endlabel%d", endlabelno);
1.1.1.2 root 2647: if(table68k[opcode].mnemo==i_ASR || table68k[opcode].mnemo==i_ASL || table68k[opcode].mnemo==i_LSR || table68k[opcode].mnemo==i_LSL
2648: || 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 2649: || table68k[opcode].mnemo==i_MVMEL || table68k[opcode].mnemo==i_MVMLE
2650: || table68k[opcode].mnemo==i_MULU || table68k[opcode].mnemo==i_MULS
2651: || table68k[opcode].mnemo==i_DIVU || table68k[opcode].mnemo==i_DIVS )
2652: printf("\tunsigned int retcycles = 0;\n");
1.1 root 2653: gen_opcode (opcode);
2654: if (need_endlabel)
2655: printf ("%s: ;\n", endlabelstr);
1.1.1.8 root 2656:
2657: if (strlen(exactCpuCycles) > 0)
2658: printf("%s\n",exactCpuCycles);
2659: else
2660: printf ("return %d;\n", insn_n_cycles);
2661: /* Now patch in the instruction cycles at the beginning of the function: */
2662: fseek(stdout, nCurInstrCycPos, SEEK_SET);
2663: printf("%d;", insn_n_cycles);
2664: fseek(stdout, 0, SEEK_END);
2665:
1.1 root 2666: printf ("}\n");
2667: opcode_next_clev[rp] = next_cpu_level;
2668: opcode_last_postfix[rp] = postfix;
2669: }
2670:
2671: static void generate_func (void)
2672: {
2673: int i, j, rp;
2674:
2675: using_prefetch = 0;
2676: using_exception_3 = 0;
2677: for (i = 0; i < 6; i++) {
2678: cpu_level = 4 - i;
2679: if (i == 5) {
2680: cpu_level = 0;
2681: using_prefetch = 1;
2682: using_exception_3 = 1;
2683: for (rp = 0; rp < nr_cpuop_funcs; rp++)
2684: opcode_next_clev[rp] = 0;
2685: }
2686:
2687: postfix = i;
1.1.1.7 root 2688: fprintf (stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix);
1.1 root 2689:
2690: /* sam: this is for people with low memory (eg. me :)) */
2691: printf ("\n"
2692: "#if !defined(PART_1) && !defined(PART_2) && "
2693: "!defined(PART_3) && !defined(PART_4) && "
2694: "!defined(PART_5) && !defined(PART_6) && "
2695: "!defined(PART_7) && !defined(PART_8)"
2696: "\n"
2697: "#define PART_1 1\n"
2698: "#define PART_2 1\n"
2699: "#define PART_3 1\n"
2700: "#define PART_4 1\n"
2701: "#define PART_5 1\n"
2702: "#define PART_6 1\n"
2703: "#define PART_7 1\n"
2704: "#define PART_8 1\n"
2705: "#endif\n\n");
2706:
2707: rp = 0;
2708: for(j=1;j<=8;++j) {
2709: int k = (j*nr_cpuop_funcs)/8;
2710: printf ("#ifdef PART_%d\n",j);
2711: for (; rp < k; rp++)
2712: generate_one_opcode (rp);
2713: printf ("#endif\n\n");
2714: }
2715:
2716: fprintf (stblfile, "{ 0, 0, 0 }};\n");
2717: }
2718:
2719: }
2720:
2721: int main (int argc, char **argv)
2722: {
2723: read_table68k ();
2724: do_merges ();
2725:
2726: opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
2727: opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
2728: opcode_next_clev = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
2729: counts = (unsigned long *) malloc (65536 * sizeof (unsigned long));
2730: read_counts ();
2731:
2732: /* It would be a lot nicer to put all in one file (we'd also get rid of
2733: * cputbl.h that way), but cpuopti can't cope. That could be fixed, but
2734: * I don't dare to touch the 68k version. */
2735:
2736: headerfile = fopen ("cputbl.h", "wb");
2737: stblfile = fopen ("cpustbl.c", "wb");
1.1.1.11 root 2738: if (freopen ("cpuemu.c", "wb", stdout) == NULL) {
2739: perror("cpuemu.c");
2740: return -1;
2741: }
1.1 root 2742:
2743: generate_includes (stdout);
2744: generate_includes (stblfile);
2745:
2746: generate_func ();
2747:
2748: free (table68k);
2749: return 0;
2750: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.