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