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