1 /*
2 * compiler/gencomp.c - MC680x0 compilation generator
3 *
4 * Based on work Copyright 1995, 1996 Bernd Schmidt
5 * Changes for UAE-JIT Copyright 2000 Bernd Meyer
6 *
7 * Adaptation for ARAnyM/ARM, copyright 2001-2014
8 * Milan Jurik, Jens Heitmann
9 *
10 * Adaptation for Basilisk II and improvements, copyright 2000-2005
11 * Gwenole Beauchesne
12 *
13 * Basilisk II (C) 1997-2005 Christian Bauer
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30 #define CC_FOR_BUILD 1
31 #include "sysconfig.h"
32
33 #include "sysdeps.h"
34 #include "readcpu.h"
35
36 #undef NDEBUG
37 #include <assert.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <ctype.h>
43 #undef abort
44
45 #ifdef UAE
46 /*
47 #define DISABLE_I_OR_AND_EOR
48 #define DISABLE_I_SUB
49 #define DISABLE_I_SUBA
50 #define DISABLE_I_SUBX
51 #define DISABLE_I_ADD
52 #define DISABLE_I_ADDA
53 #define DISABLE_I_ADDX
54 #define DISABLE_I_NEG
55 #define DISABLE_I_NEGX
56 #define DISABLE_I_CLR
57 #define DISABLE_I_NOT
58 #define DISABLE_I_TST
59 #define DISABLE_I_BCHG_BCLR_BSET_BTST
60 #define DISABLE_I_CMPM_CMP
61 #define DISABLE_I_CMPA
62 #define DISABLE_I_MOVE
63 #define DISABLE_I_MOVEA
64 #define DISABLE_I_SWAP
65 #define DISABLE_I_EXG
66 #define DISABLE_I_EXT
67 #define DISABLE_I_MVEL
68 #define DISABLE_I_MVMLE
69 #define DISABLE_I_RTD
70 #define DISABLE_I_LINK
71 #define DISABLE_I_UNLK
72 #define DISABLE_I_RTS
73 #define DISABLE_I_JSR
74 #define DISABLE_I_JMP
75 #define DISABLE_I_BSR
76 #define DISABLE_I_BCC
77 #define DISABLE_I_LEA
78 #define DISABLE_I_PEA
79 #define DISABLE_I_DBCC
80 #define DISABLE_I_SCC
81 #define DISABLE_I_MULU
82 #define DISABLE_I_MULS
83 #define DISABLE_I_ASR
84 #define DISABLE_I_ASL
85 #define DISABLE_I_LSR
86 #define DISABLE_I_LSL
87 #define DISABLE_I_ROL
88 #define DISABLE_I_ROR
89 #define DISABLE_I_MULL
90 #define DISABLE_I_FPP
91 #define DISABLE_I_FBCC
92 #define DISABLE_I_FSCC
93 #define DISABLE_I_MOVE16
94 */
95
96 #endif /* UAE */
97
98 #ifdef UAE
99 #define JIT_PATH "jit/"
100 #ifdef FSUAE
101 #define GEN_PATH "gen/"
102 #else
103 #define GEN_PATH "jit/"
104 #endif
105 #define RETURN "return 0;"
106 #define RETTYPE "uae_u32"
107 #define NEXT_CPU_LEVEL 5
108 #else
109 #define JIT_PATH "compiler/"
110 #define GEN_PATH ""
111 #define RETURN "return;"
112 #define RETTYPE "void"
113 #define NEXT_CPU_LEVEL 4
114 #endif
115
116 #define BOOL_TYPE "int"
117 #define failure global_failure=1
118 #define FAILURE global_failure=1
119 #define isjump global_isjump=1
120 #define is_const_jump global_iscjump=1
121 #define isaddx global_isaddx=1
122 #define uses_cmov global_cmov=1
123 #define mayfail global_mayfail=1
124 #define uses_fpu global_fpu=1
125
126 int hack_opcode;
127
128 static int global_failure;
129 static int global_isjump;
130 static int global_iscjump;
131 static int global_isaddx;
132 static int global_cmov;
133 static int long_opcode;
134 static int global_mayfail;
135 static int global_fpu;
136
137 static char endstr[1000];
138 static char lines[100000];
139 static int comp_index=0;
140
141 #include "flags_x86.h"
142
143 #ifndef __attribute__
144 # ifndef __GNUC__
145 # define __attribute__(x)
146 # endif
147 #endif
148
149
150 static int cond_codes[]={-1,-1,
151 NATIVE_CC_HI,NATIVE_CC_LS,
152 NATIVE_CC_CC,NATIVE_CC_CS,
153 NATIVE_CC_NE,NATIVE_CC_EQ,
154 -1,-1,
155 NATIVE_CC_PL,NATIVE_CC_MI,
156 NATIVE_CC_GE,NATIVE_CC_LT,
157 NATIVE_CC_GT,NATIVE_CC_LE
158 };
159
160 __attribute__((format(printf, 1, 2)))
comprintf(const char * format,...)161 static void comprintf(const char *format, ...)
162 {
163 va_list args;
164
165 va_start(args, format);
166 comp_index += vsprintf(lines + comp_index, format, args);
167 va_end(args);
168 }
169
com_discard(void)170 static void com_discard(void)
171 {
172 comp_index = 0;
173 }
174
com_flush(void)175 static void com_flush(void)
176 {
177 int i;
178 for (i = 0; i < comp_index; i++)
179 putchar(lines[i]);
180 com_discard();
181 }
182
183
184 static FILE *headerfile;
185 static FILE *stblfile;
186
187 static int using_prefetch;
188 static int using_exception_3;
189 static int cpu_level;
190 static int noflags;
191
192 /* For the current opcode, the next lower level that will have different code.
193 * Initialized to -1 for each opcode. If it remains unchanged, indicates we
194 * are done with that opcode. */
195 static int next_cpu_level;
196
197 static int *opcode_map;
198 static int *opcode_next_clev;
199 static int *opcode_last_postfix;
200 static unsigned long *counts;
201
read_counts(void)202 static void read_counts(void)
203 {
204 FILE *file;
205 unsigned long opcode, count, total;
206 char name[20];
207 int nr = 0;
208 memset (counts, 0, 65536 * sizeof *counts);
209
210 file = fopen ("frequent.68k", "r");
211 if (file)
212 {
213 if (fscanf (file, "Total: %lu\n", &total) != 1) {
214 assert(0);
215 }
216 while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3)
217 {
218 opcode_next_clev[nr] = NEXT_CPU_LEVEL;
219 opcode_last_postfix[nr] = -1;
220 opcode_map[nr++] = opcode;
221 counts[opcode] = count;
222 }
223 fclose (file);
224 }
225 if (nr == nr_cpuop_funcs)
226 return;
227 for (opcode = 0; opcode < 0x10000; opcode++)
228 {
229 if (table68k[opcode].handler == -1 && table68k[opcode].mnemo != i_ILLG
230 && counts[opcode] == 0)
231 {
232 opcode_next_clev[nr] = NEXT_CPU_LEVEL;
233 opcode_last_postfix[nr] = -1;
234 opcode_map[nr++] = opcode;
235 counts[opcode] = count;
236 }
237 }
238 assert (nr == nr_cpuop_funcs);
239 }
240
241 static int n_braces = 0;
242 static int insn_n_cycles;
243
244 static void
start_brace(void)245 start_brace (void)
246 {
247 n_braces++;
248 comprintf ("{");
249 }
250
251 static void
close_brace(void)252 close_brace (void)
253 {
254 assert (n_braces > 0);
255 n_braces--;
256 comprintf ("}");
257 }
258
259 static void
finish_braces(void)260 finish_braces (void)
261 {
262 while (n_braces > 0)
263 close_brace ();
264 }
265
gen_update_next_handler(void)266 static inline void gen_update_next_handler(void)
267 {
268 return; /* Can anything clever be done here? */
269 }
270
gen_writebyte(const char * address,const char * source)271 static void gen_writebyte(const char *address, const char *source)
272 {
273 comprintf("\twritebyte(%s, %s, scratchie);\n", address, source);
274 }
275
gen_writeword(const char * address,const char * source)276 static void gen_writeword(const char *address, const char *source)
277 {
278 comprintf("\twriteword(%s, %s, scratchie);\n", address, source);
279 }
280
gen_writelong(const char * address,const char * source)281 static void gen_writelong(const char *address, const char *source)
282 {
283 comprintf("\twritelong(%s, %s, scratchie);\n", address, source);
284 }
285
gen_readbyte(const char * address,const char * dest)286 static void gen_readbyte(const char *address, const char* dest)
287 {
288 comprintf("\treadbyte(%s, %s, scratchie);\n", address, dest);
289 }
290
gen_readword(const char * address,const char * dest)291 static void gen_readword(const char *address, const char *dest)
292 {
293 comprintf("\treadword(%s,%s,scratchie);\n", address, dest);
294 }
295
gen_readlong(const char * address,const char * dest)296 static void gen_readlong(const char *address, const char *dest)
297 {
298 comprintf("\treadlong(%s, %s, scratchie);\n", address, dest);
299 }
300
301
302
303 static const char *
gen_nextilong(void)304 gen_nextilong (void)
305 {
306 static char buffer[80];
307
308 sprintf (buffer, "comp_get_ilong((m68k_pc_offset+=4)-4)");
309 insn_n_cycles += 4;
310
311 long_opcode=1;
312 return buffer;
313 }
314
315 static const char *
gen_nextiword(void)316 gen_nextiword (void)
317 {
318 static char buffer[80];
319
320 sprintf (buffer, "comp_get_iword((m68k_pc_offset+=2)-2)");
321 insn_n_cycles+=2;
322
323 long_opcode=1;
324 return buffer;
325 }
326
327 static const char *
gen_nextibyte(void)328 gen_nextibyte (void)
329 {
330 static char buffer[80];
331
332 sprintf (buffer, "comp_get_ibyte((m68k_pc_offset+=2)-2)");
333 insn_n_cycles += 2;
334
335 long_opcode=1;
336 return buffer;
337 }
338
339
340 static void
swap_opcode(void)341 swap_opcode (void)
342 {
343 #ifdef UAE
344 /* no-op */
345 #else
346 comprintf("#ifdef USE_JIT_FPU\n");
347 comprintf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n");
348 comprintf("\topcode = do_byteswap_16(opcode);\n");
349 comprintf("#endif\n");
350 comprintf("#endif\n");
351 #endif
352 }
353
354 static void
sync_m68k_pc(void)355 sync_m68k_pc (void)
356 {
357 comprintf("\t if (m68k_pc_offset > SYNC_PC_OFFSET) sync_m68k_pc();\n");
358 }
359
360
361 /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0,
362 * the calling routine handles Apdi and Aipi modes.
363 * gb-- movem == 2 means the same thing but for a MOVE16 instruction */
genamode(amodes mode,const char * reg,wordsizes size,const char * name,int getv,int movem)364 static void genamode(amodes mode, const char *reg, wordsizes size, const char *name, int getv, int movem)
365 {
366 start_brace();
367 switch (mode)
368 {
369 case Dreg: /* Do we need to check dodgy here? */
370 assert (!movem);
371 if (getv == 1 || getv == 2)
372 {
373 /* We generate the variable even for getv==2, so we can use
374 it as a destination for MOVE */
375 comprintf("\tint %s = %s;\n", name, reg);
376 }
377 return;
378
379 case Areg:
380 assert (!movem);
381 if (getv == 1 || getv == 2)
382 {
383 /* see above */
384 comprintf("\tint %s = dodgy ? scratchie++ : %s + 8;\n", name, reg);
385 if (getv == 1)
386 {
387 comprintf("\tif (dodgy) \n");
388 comprintf("\t\tmov_l_rr(%s, %s + 8);\n", name, reg);
389 }
390 }
391 return;
392
393 case Aind:
394 comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg);
395 comprintf("\tif (dodgy)\n");
396 comprintf("\t\tmov_l_rr(%sa, %s + 8);\n", name, reg);
397 break;
398 case Aipi:
399 comprintf("\tint %sa = scratchie++;\n", name);
400 comprintf("\tmov_l_rr(%sa, %s + 8);\n", name, reg);
401 break;
402 case Apdi:
403 switch (size)
404 {
405 case sz_byte:
406 if (movem)
407 {
408 comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg);
409 comprintf("\tif (dodgy)\n");
410 comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg);
411 } else
412 {
413 start_brace();
414 comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg);
415 comprintf("\tlea_l_brr(%s + 8, %s + 8, (uae_s32)-areg_byteinc[%s]);\n", reg, reg, reg);
416 comprintf("\tif (dodgy)\n");
417 comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg);
418 }
419 break;
420 case sz_word:
421 if (movem)
422 {
423 comprintf("\tint %sa=dodgy?scratchie++:%s+8;\n", name, reg);
424 comprintf("\tif (dodgy) \n");
425 comprintf("\tmov_l_rr(%sa,8+%s);\n", name, reg);
426 } else
427 {
428 start_brace();
429 comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg);
430 comprintf("\tlea_l_brr(%s + 8, %s + 8, -2);\n", reg, reg);
431 comprintf("\tif (dodgy)\n");
432 comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg);
433 }
434 break;
435 case sz_long:
436 if (movem)
437 {
438 comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg);
439 comprintf("\tif (dodgy)\n");
440 comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg);
441 } else
442 {
443 start_brace();
444 comprintf("\tint %sa = dodgy ? scratchie++ : %s + 8;\n", name, reg);
445 comprintf("\tlea_l_brr(%s + 8, %s + 8, -4);\n", reg, reg);
446 comprintf("\tif (dodgy)\n");
447 comprintf("\t\tmov_l_rr(%sa, 8 + %s);\n", name, reg);
448 }
449 break;
450 default:
451 assert(0);
452 break;
453 }
454 break;
455 case Ad16:
456 comprintf("\tint %sa = scratchie++;\n", name);
457 comprintf("\tmov_l_rr(%sa, 8 + %s);\n", name, reg);
458 comprintf("\tlea_l_brr(%sa, %sa, (uae_s32)(uae_s16)%s);\n", name, name, gen_nextiword());
459 break;
460 case Ad8r:
461 comprintf("\tint %sa = scratchie++;\n", name);
462 comprintf("\tcalc_disp_ea_020(%s + 8, %s, %sa, scratchie);\n", reg, gen_nextiword(), name);
463 break;
464
465 case PC16:
466 comprintf("\tint %sa = scratchie++;\n", name);
467 comprintf("\tuae_u32 address = start_pc + ((char *)comp_pc_p - (char *)start_pc_p) + m68k_pc_offset;\n");
468 comprintf("\tuae_s32 PC16off = (uae_s32)(uae_s16)%s;\n", gen_nextiword());
469 comprintf("\tmov_l_ri(%sa, address + PC16off);\n", name);
470 break;
471
472 case PC8r:
473 comprintf("\tint pctmp = scratchie++;\n");
474 comprintf("\tint %sa = scratchie++;\n", name);
475 comprintf("\tuae_u32 address = start_pc + ((char *)comp_pc_p - (char *)start_pc_p) + m68k_pc_offset;\n");
476 start_brace();
477 comprintf("\tmov_l_ri(pctmp,address);\n");
478
479 comprintf("\tcalc_disp_ea_020(pctmp, %s, %sa, scratchie);\n", gen_nextiword(), name);
480 break;
481 case absw:
482 comprintf("\tint %sa = scratchie++;\n", name);
483 comprintf("\tmov_l_ri(%sa, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword());
484 break;
485 case absl:
486 comprintf("\tint %sa = scratchie++;\n", name);
487 comprintf("\tmov_l_ri(%sa, %s); /* absl */\n", name, gen_nextilong());
488 break;
489 case imm:
490 assert (getv == 1);
491 switch (size)
492 {
493 case sz_byte:
494 comprintf("\tint %s = scratchie++;\n", name);
495 comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s8)%s);\n", name, gen_nextibyte());
496 break;
497 case sz_word:
498 comprintf("\tint %s = scratchie++;\n", name);
499 comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword());
500 break;
501 case sz_long:
502 comprintf("\tint %s = scratchie++;\n", name);
503 comprintf("\tmov_l_ri(%s, %s);\n", name, gen_nextilong());
504 break;
505 default:
506 assert(0);
507 break;
508 }
509 return;
510 case imm0:
511 assert (getv == 1);
512 comprintf("\tint %s = scratchie++;\n", name);
513 comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s8)%s);\n", name, gen_nextibyte());
514 return;
515 case imm1:
516 assert (getv == 1);
517 comprintf("\tint %s = scratchie++;\n", name);
518 comprintf("\tmov_l_ri(%s, (uae_s32)(uae_s16)%s);\n", name, gen_nextiword());
519 return;
520 case imm2:
521 assert (getv == 1);
522 comprintf("\tint %s = scratchie++;\n", name);
523 comprintf("\tmov_l_ri(%s, %s);\n", name, gen_nextilong());
524 return;
525 case immi:
526 assert (getv == 1);
527 comprintf("\tint %s = scratchie++;\n", name);
528 comprintf("\tmov_l_ri(%s, %s);\n", name, reg);
529 return;
530 default:
531 assert(0);
532 break;
533 }
534
535 /* We get here for all non-reg non-immediate addressing modes to
536 * actually fetch the value. */
537 if (getv == 1)
538 {
539 char astring[80];
540 sprintf(astring, "%sa", name);
541 switch (size)
542 {
543 case sz_byte:
544 insn_n_cycles += 2;
545 break;
546 case sz_word:
547 insn_n_cycles += 2;
548 break;
549 case sz_long:
550 insn_n_cycles += 4;
551 break;
552 default:
553 assert(0);
554 break;
555 }
556 start_brace();
557 comprintf("\tint %s = scratchie++;\n", name);
558 switch (size)
559 {
560 case sz_byte:
561 gen_readbyte(astring, name);
562 break;
563 case sz_word:
564 gen_readword(astring, name);
565 break;
566 case sz_long:
567 gen_readlong(astring, name);
568 break;
569 default:
570 assert(0);
571 break;
572 }
573 }
574
575 /* We now might have to fix up the register for pre-dec or post-inc
576 * addressing modes. */
577 if (!movem)
578 {
579 switch (mode)
580 {
581 case Aipi:
582 switch (size)
583 {
584 case sz_byte:
585 comprintf("\tlea_l_brr(%s + 8,%s + 8, areg_byteinc[%s]);\n", reg, reg, reg);
586 break;
587 case sz_word:
588 comprintf("\tlea_l_brr(%s + 8, %s + 8, 2);\n", reg, reg);
589 break;
590 case sz_long:
591 comprintf("\tlea_l_brr(%s + 8, %s + 8, 4);\n", reg, reg);
592 break;
593 default:
594 assert(0);
595 break;
596 }
597 break;
598 case Apdi:
599 break;
600 default:
601 break;
602 }
603 }
604 }
605
genastore(const char * from,amodes mode,const char * reg,wordsizes size,const char * to)606 static void genastore(const char *from, amodes mode, const char *reg, wordsizes size, const char *to)
607 {
608 switch (mode)
609 {
610 case Dreg:
611 switch (size)
612 {
613 case sz_byte:
614 comprintf("\tif(%s != %s)\n", reg, from);
615 comprintf("\t\tmov_b_rr(%s, %s);\n", reg, from);
616 break;
617 case sz_word:
618 comprintf("\tif(%s != %s)\n", reg, from);
619 comprintf("\t\tmov_w_rr(%s, %s);\n", reg, from);
620 break;
621 case sz_long:
622 comprintf("\tif(%s != %s)\n", reg, from);
623 comprintf("\t\tmov_l_rr(%s, %s);\n", reg, from);
624 break;
625 default:
626 assert(0);
627 break;
628 }
629 break;
630 case Areg:
631 switch (size)
632 {
633 case sz_word:
634 comprintf("\tif(%s + 8 != %s)\n", reg, from);
635 comprintf("\t\tmov_w_rr(%s + 8, %s);\n", reg, from);
636 break;
637 case sz_long:
638 comprintf("\tif(%s + 8 != %s)\n", reg, from);
639 comprintf("\t\tmov_l_rr(%s + 8, %s);\n", reg, from);
640 break;
641 default:
642 assert(0);
643 break;
644 }
645 break;
646
647 case Apdi:
648 case absw:
649 case PC16:
650 case PC8r:
651 case Ad16:
652 case Ad8r:
653 case Aipi:
654 case Aind:
655 case absl:
656 {
657 char astring[80];
658 sprintf(astring, "%sa", to);
659
660 switch (size)
661 {
662 case sz_byte:
663 insn_n_cycles += 2;
664 gen_writebyte(astring, from);
665 break;
666 case sz_word:
667 insn_n_cycles += 2;
668 gen_writeword(astring, from);
669 break;
670 case sz_long:
671 insn_n_cycles += 4;
672 gen_writelong(astring, from);
673 break;
674 default:
675 assert(0);
676 break;
677 }
678 }
679 break;
680 case imm:
681 case imm0:
682 case imm1:
683 case imm2:
684 case immi:
685 assert(0);
686 break;
687 default:
688 assert(0);
689 break;
690 }
691 }
692
genmov16(uae_u32 opcode,struct instr * curi)693 static void genmov16(uae_u32 opcode, struct instr *curi)
694 {
695 comprintf("\tint src=scratchie++;\n");
696 comprintf("\tint dst=scratchie++;\n");
697
698 if ((opcode & 0xfff8) == 0xf620) {
699 /* MOVE16 (Ax)+,(Ay)+ */
700 comprintf("\tuae_u16 dstreg=((%s)>>12)&0x07;\n", gen_nextiword());
701 comprintf("\tmov_l_rr(src,8+srcreg);\n");
702 comprintf("\tmov_l_rr(dst,8+dstreg);\n");
703 }
704 else {
705 /* Other variants */
706 genamode (curi->smode, "srcreg", curi->size, "src", 0, 2);
707 genamode (curi->dmode, "dstreg", curi->size, "dst", 0, 2);
708 comprintf("\tmov_l_rr(src,srca);\n");
709 comprintf("\tmov_l_rr(dst,dsta);\n");
710 }
711
712 /* Align on 16-byte boundaries */
713 comprintf("\tand_l_ri(src,~15);\n");
714 comprintf("\tand_l_ri(dst,~15);\n");
715
716 if ((opcode & 0xfff8) == 0xf620) {
717 comprintf("\tif (srcreg != dstreg)\n");
718 comprintf("\tadd_l_ri(srcreg+8,16);\n");
719 comprintf("\tadd_l_ri(dstreg+8,16);\n");
720 }
721 else if ((opcode & 0xfff8) == 0xf600)
722 comprintf("\tadd_l_ri(srcreg+8,16);\n");
723 else if ((opcode & 0xfff8) == 0xf608)
724 comprintf("\tadd_l_ri(dstreg+8,16);\n");
725
726 #ifdef UAE
727 comprintf("\tif (special_mem) {\n");
728 comprintf("\t\tint tmp=scratchie;\n");
729 comprintf("\tscratchie+=4;\n"
730 "\treadlong(src,tmp,scratchie);\n"
731 "\twritelong_clobber(dst,tmp,scratchie);\n"
732 "\tadd_l_ri(src,4);\n"
733 "\tadd_l_ri(dst,4);\n"
734 "\treadlong(src,tmp,scratchie);\n"
735 "\twritelong_clobber(dst,tmp,scratchie);\n"
736 "\tadd_l_ri(src,4);\n"
737 "\tadd_l_ri(dst,4);\n"
738 "\treadlong(src,tmp,scratchie);\n"
739 "\twritelong_clobber(dst,tmp,scratchie);\n"
740 "\tadd_l_ri(src,4);\n"
741 "\tadd_l_ri(dst,4);\n"
742 "\treadlong(src,tmp,scratchie);\n"
743 "\twritelong_clobber(dst,tmp,scratchie);\n");
744 comprintf("\t} else\n");
745 #endif
746 start_brace();
747 comprintf("\tint tmp=scratchie;\n");
748 comprintf("\tscratchie+=4;\n"
749 "\tget_n_addr(src,src,scratchie);\n"
750 "\tget_n_addr(dst,dst,scratchie);\n"
751 "\tmov_l_rR(tmp+0,src,0);\n"
752 "\tmov_l_rR(tmp+1,src,4);\n"
753 "\tmov_l_rR(tmp+2,src,8);\n"
754 "\tmov_l_rR(tmp+3,src,12);\n"
755 "\tmov_l_Rr(dst,tmp+0,0);\n"
756 "\tforget_about(tmp+0);\n"
757 "\tmov_l_Rr(dst,tmp+1,4);\n"
758 "\tforget_about(tmp+1);\n"
759 "\tmov_l_Rr(dst,tmp+2,8);\n"
760 "\tforget_about(tmp+2);\n"
761 "\tmov_l_Rr(dst,tmp+3,12);\n");
762 close_brace();
763 }
764
765 static void
genmovemel(uae_u16 opcode)766 genmovemel (uae_u16 opcode)
767 {
768 comprintf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
769 comprintf ("\tint native=scratchie++;\n");
770 comprintf ("\tint i;\n");
771 comprintf ("\tsigned char offset=0;\n");
772 genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
773 #ifdef UAE
774 if (table68k[opcode].size == sz_long)
775 comprintf("\tif (1 && !special_mem) {\n");
776 else
777 comprintf("\tif (1 && !special_mem) {\n");
778 #endif
779
780 /* Fast but unsafe... */
781 comprintf("\tget_n_addr(srca,native,scratchie);\n");
782
783 comprintf("\tfor (i=0;i<16;i++) {\n"
784 "\t\tif ((mask>>i)&1) {\n");
785 switch(table68k[opcode].size) {
786 case sz_long:
787 comprintf("\t\t\tmov_l_rR(i,native,offset);\n"
788 "\t\t\tmid_bswap_32(i);\n"
789 "\t\t\toffset+=4;\n");
790 break;
791 case sz_word:
792 comprintf("\t\t\tmov_w_rR(i,native,offset);\n"
793 "\t\t\tmid_bswap_16(i);\n"
794 "\t\t\tsign_extend_16_rr(i,i);\n"
795 "\t\t\toffset+=2;\n");
796 break;
797 default: assert(0);
798 }
799 comprintf("\t\t}\n"
800 "\t}");
801 if (table68k[opcode].dmode == Aipi) {
802 comprintf("\t\t\tlea_l_brr(8+dstreg,srca,offset);\n");
803 }
804 /* End fast but unsafe. */
805
806 #ifdef UAE
807 comprintf("\t} else {\n");
808
809 comprintf ("\t\tint tmp=scratchie++;\n");
810
811 comprintf("\t\tmov_l_rr(tmp,srca);\n");
812 comprintf("\t\tfor (i=0;i<16;i++) {\n"
813 "\t\t\tif ((mask>>i)&1) {\n");
814 switch(table68k[opcode].size) {
815 case sz_long:
816 comprintf("\t\t\t\treadlong(tmp,i,scratchie);\n"
817 "\t\t\t\tadd_l_ri(tmp,4);\n");
818 break;
819 case sz_word:
820 comprintf("\t\t\t\treadword(tmp,i,scratchie);\n"
821 "\t\t\t\tadd_l_ri(tmp,2);\n");
822 break;
823 default: assert(0);
824 }
825
826 comprintf("\t\t\t}\n"
827 "\t\t}\n");
828 if (table68k[opcode].dmode == Aipi) {
829 comprintf("\t\tmov_l_rr(8+dstreg,tmp);\n");
830 }
831 comprintf("\t}\n");
832 #endif
833
834 }
835
836
837 static void
genmovemle(uae_u16 opcode)838 genmovemle (uae_u16 opcode)
839 {
840 comprintf ("\tuae_u16 mask = %s;\n", gen_nextiword ());
841 comprintf ("\tint native=scratchie++;\n");
842 comprintf ("\tint i;\n");
843 comprintf ("\tint tmp=scratchie++;\n");
844 comprintf ("\tsigned char offset=0;\n");
845 genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1);
846
847 #ifdef UAE
848 /* *Sigh* Some clever geek realized that the fastest way to copy a
849 buffer from main memory to the gfx card is by using movmle. Good
850 on her, but unfortunately, gfx mem isn't "real" mem, and thus that
851 act of cleverness means that movmle must pay attention to special_mem,
852 or Genetic Species is a rather boring-looking game ;-) */
853 if (table68k[opcode].size == sz_long)
854 comprintf("\tif (1 && !special_mem) {\n");
855 else
856 comprintf("\tif (1 && !special_mem) {\n");
857 #endif
858 comprintf("\tget_n_addr(srca,native,scratchie);\n");
859
860 if (table68k[opcode].dmode!=Apdi) {
861 comprintf("\tfor (i=0;i<16;i++) {\n"
862 "\t\tif ((mask>>i)&1) {\n");
863 switch(table68k[opcode].size) {
864 case sz_long:
865 comprintf("\t\t\tmov_l_rr(tmp,i);\n"
866 "\t\t\tmid_bswap_32(tmp);\n"
867 "\t\t\tmov_l_Rr(native,tmp,offset);\n"
868 "\t\t\toffset+=4;\n");
869 break;
870 case sz_word:
871 comprintf("\t\t\tmov_l_rr(tmp,i);\n"
872 "\t\t\tmid_bswap_16(tmp);\n"
873 "\t\t\tmov_w_Rr(native,tmp,offset);\n"
874 "\t\t\toffset+=2;\n");
875 break;
876 default: assert(0);
877 }
878 }
879 else { /* Pre-decrement */
880 comprintf("\tfor (i=0;i<16;i++) {\n"
881 "\t\tif ((mask>>i)&1) {\n");
882 switch(table68k[opcode].size) {
883 case sz_long:
884 comprintf("\t\t\toffset-=4;\n"
885 "\t\t\tmov_l_rr(tmp,15-i);\n"
886 "\t\t\tmid_bswap_32(tmp);\n"
887 "\t\t\tmov_l_Rr(native,tmp,offset);\n"
888 );
889 break;
890 case sz_word:
891 comprintf("\t\t\toffset-=2;\n"
892 "\t\t\tmov_l_rr(tmp,15-i);\n"
893 "\t\t\tmid_bswap_16(tmp);\n"
894 "\t\t\tmov_w_Rr(native,tmp,offset);\n"
895 );
896 break;
897 default: assert(0);
898 }
899 }
900
901
902 comprintf("\t\t}\n"
903 "\t}");
904 if (table68k[opcode].dmode == Apdi) {
905 comprintf("\t\t\tlea_l_brr(8+dstreg,srca,(uae_s32)offset);\n");
906 }
907 #ifdef UAE
908 comprintf("\t} else {\n");
909
910 if (table68k[opcode].dmode!=Apdi) {
911 comprintf("\tmov_l_rr(tmp,srca);\n");
912 comprintf("\tfor (i=0;i<16;i++) {\n"
913 "\t\tif ((mask>>i)&1) {\n");
914 switch(table68k[opcode].size) {
915 case sz_long:
916 comprintf("\t\t\twritelong(tmp,i,scratchie);\n"
917 "\t\t\tadd_l_ri(tmp,4);\n");
918 break;
919 case sz_word:
920 comprintf("\t\t\twriteword(tmp,i,scratchie);\n"
921 "\t\t\tadd_l_ri(tmp,2);\n");
922 break;
923 default: assert(0);
924 }
925 }
926 else { /* Pre-decrement */
927 comprintf("\tfor (i=0;i<16;i++) {\n"
928 "\t\tif ((mask>>i)&1) {\n");
929 switch(table68k[opcode].size) {
930 case sz_long:
931 comprintf("\t\t\tsub_l_ri(srca,4);\n"
932 "\t\t\twritelong(srca,15-i,scratchie);\n");
933 break;
934 case sz_word:
935 comprintf("\t\t\tsub_l_ri(srca,2);\n"
936 "\t\t\twriteword(srca,15-i,scratchie);\n");
937 break;
938 default: assert(0);
939 }
940 }
941
942
943 comprintf("\t\t}\n"
944 "\t}");
945 if (table68k[opcode].dmode == Apdi) {
946 comprintf("\t\t\tmov_l_rr(8+dstreg,srca);\n");
947 }
948 comprintf("\t}\n");
949 #endif
950 }
951
952
953 static void
duplicate_carry(void)954 duplicate_carry (void)
955 {
956 comprintf ("\tif (needed_flags&FLAG_X) duplicate_carry();\n");
957 }
958
959 typedef enum
960 {
961 flag_logical_noclobber, flag_logical, flag_add, flag_sub, flag_cmp,
962 flag_addx, flag_subx, flag_zn, flag_av, flag_sv, flag_and, flag_or,
963 flag_eor, flag_mov
964 }
965 flagtypes;
966
967
968 static void
genflags(flagtypes type,wordsizes size,const char * value,const char * src,const char * dst)969 genflags (flagtypes type, wordsizes size, const char *value, const char *src, const char *dst)
970 {
971 if (noflags) {
972 switch(type) {
973 case flag_cmp:
974 comprintf("\tdont_care_flags();\n");
975 comprintf("/* Weird --- CMP with noflags ;-) */\n");
976 return;
977 case flag_add:
978 case flag_sub:
979 comprintf("\tdont_care_flags();\n");
980 {
981 const char* op;
982 switch(type) {
983 case flag_add: op="add"; break;
984 case flag_sub: op="sub"; break;
985 default: assert(0);
986 }
987 switch (size)
988 {
989 case sz_byte:
990 comprintf("\t%s_b(%s,%s);\n",op,dst,src);
991 break;
992 case sz_word:
993 comprintf("\t%s_w(%s,%s);\n",op,dst,src);
994 break;
995 case sz_long:
996 comprintf("\t%s_l(%s,%s);\n",op,dst,src);
997 break;
998 }
999 return;
1000 }
1001 break;
1002
1003 case flag_and:
1004 comprintf("\tdont_care_flags();\n");
1005 switch (size)
1006 {
1007 case sz_byte:
1008 comprintf("if (kill_rodent(dst)) {\n");
1009 comprintf("\tzero_extend_8_rr(scratchie,%s);\n",src);
1010 comprintf("\tor_l_ri(scratchie,0xffffff00);\n");
1011 comprintf("\tand_l(%s,scratchie);\n",dst);
1012 comprintf("\tforget_about(scratchie);\n");
1013 comprintf("\t} else \n"
1014 "\tand_b(%s,%s);\n",dst,src);
1015 break;
1016 case sz_word:
1017 comprintf("if (kill_rodent(dst)) {\n");
1018 comprintf("\tzero_extend_16_rr(scratchie,%s);\n",src);
1019 comprintf("\tor_l_ri(scratchie,0xffff0000);\n");
1020 comprintf("\tand_l(%s,scratchie);\n",dst);
1021 comprintf("\tforget_about(scratchie);\n");
1022 comprintf("\t} else \n"
1023 "\tand_w(%s,%s);\n",dst,src);
1024 break;
1025 case sz_long:
1026 comprintf("\tand_l(%s,%s);\n",dst,src);
1027 break;
1028 }
1029 return;
1030
1031 case flag_mov:
1032 comprintf("\tdont_care_flags();\n");
1033 switch (size)
1034 {
1035 case sz_byte:
1036 comprintf("if (kill_rodent(dst)) {\n");
1037 comprintf("\tzero_extend_8_rr(scratchie,%s);\n",src);
1038 comprintf("\tand_l_ri(%s,0xffffff00);\n",dst);
1039 comprintf("\tor_l(%s,scratchie);\n",dst);
1040 comprintf("\tforget_about(scratchie);\n");
1041 comprintf("\t} else \n"
1042 "\tmov_b_rr(%s,%s);\n",dst,src);
1043 break;
1044 case sz_word:
1045 comprintf("if (kill_rodent(dst)) {\n");
1046 comprintf("\tzero_extend_16_rr(scratchie,%s);\n",src);
1047 comprintf("\tand_l_ri(%s,0xffff0000);\n",dst);
1048 comprintf("\tor_l(%s,scratchie);\n",dst);
1049 comprintf("\tforget_about(scratchie);\n");
1050 comprintf("\t} else \n"
1051 "\tmov_w_rr(%s,%s);\n",dst,src);
1052 break;
1053 case sz_long:
1054 comprintf("\tmov_l_rr(%s,%s);\n",dst,src);
1055 break;
1056 }
1057 return;
1058
1059 case flag_or:
1060 case flag_eor:
1061 comprintf("\tdont_care_flags();\n");
1062 start_brace();
1063 {
1064 const char* op;
1065 switch(type) {
1066 case flag_or: op="or"; break;
1067 case flag_eor: op="xor"; break;
1068 default: assert(0);
1069 }
1070 switch (size)
1071 {
1072 case sz_byte:
1073 comprintf("if (kill_rodent(dst)) {\n");
1074 comprintf("\tzero_extend_8_rr(scratchie,%s);\n",src);
1075 comprintf("\t%s_l(%s,scratchie);\n",op,dst);
1076 comprintf("\tforget_about(scratchie);\n");
1077 comprintf("\t} else \n"
1078 "\t%s_b(%s,%s);\n",op,dst,src);
1079 break;
1080 case sz_word:
1081 comprintf("if (kill_rodent(dst)) {\n");
1082 comprintf("\tzero_extend_16_rr(scratchie,%s);\n",src);
1083 comprintf("\t%s_l(%s,scratchie);\n",op,dst);
1084 comprintf("\tforget_about(scratchie);\n");
1085 comprintf("\t} else \n"
1086 "\t%s_w(%s,%s);\n",op,dst,src);
1087 break;
1088 case sz_long:
1089 comprintf("\t%s_l(%s,%s);\n",op,dst,src);
1090 break;
1091 }
1092 close_brace();
1093 return;
1094 }
1095
1096
1097 case flag_addx:
1098 case flag_subx:
1099 comprintf("\tdont_care_flags();\n");
1100 {
1101 const char* op;
1102 switch(type) {
1103 case flag_addx: op="adc"; break;
1104 case flag_subx: op="sbb"; break;
1105 default: assert(0);
1106 }
1107 comprintf("\trestore_carry();\n"); /* Reload the X flag into C */
1108 switch (size)
1109 {
1110 case sz_byte:
1111 comprintf("\t%s_b(%s,%s);\n",op,dst,src);
1112 break;
1113 case sz_word:
1114 comprintf("\t%s_w(%s,%s);\n",op,dst,src);
1115 break;
1116 case sz_long:
1117 comprintf("\t%s_l(%s,%s);\n",op,dst,src);
1118 break;
1119 }
1120 return;
1121 }
1122 break;
1123 default: return;
1124 }
1125 }
1126
1127 /* Need the flags, but possibly not all of them */
1128 switch (type)
1129 {
1130 case flag_logical_noclobber:
1131 failure;
1132 /* fall through */
1133
1134 case flag_and:
1135 case flag_or:
1136 case flag_eor:
1137 comprintf("\tdont_care_flags();\n");
1138 start_brace();
1139 {
1140 const char* op;
1141 switch(type) {
1142 case flag_and: op="and"; break;
1143 case flag_or: op="or"; break;
1144 case flag_eor: op="xor"; break;
1145 default: assert(0);
1146 }
1147 switch (size)
1148 {
1149 case sz_byte:
1150 comprintf("\tstart_needflags();\n"
1151 "\t%s_b(%s,%s);\n",op,dst,src);
1152 break;
1153 case sz_word:
1154 comprintf("\tstart_needflags();\n"
1155 "\t%s_w(%s,%s);\n",op,dst,src);
1156 break;
1157 case sz_long:
1158 comprintf("\tstart_needflags();\n"
1159 "\t%s_l(%s,%s);\n",op,dst,src);
1160 break;
1161 }
1162 comprintf("\tlive_flags();\n");
1163 comprintf("\tend_needflags();\n");
1164 close_brace();
1165 return;
1166 }
1167
1168 case flag_mov:
1169 comprintf("\tdont_care_flags();\n");
1170 start_brace();
1171 {
1172 switch (size)
1173 {
1174 case sz_byte:
1175 comprintf("\tif (%s!=%s) {\n",src,dst);
1176 comprintf("\tmov_b_ri(%s,0);\n"
1177 "\tstart_needflags();\n",dst);
1178 comprintf("\tor_b(%s,%s);\n",dst,src);
1179 comprintf("\t} else {\n");
1180 comprintf("\tmov_b_rr(%s,%s);\n",dst,src);
1181 comprintf("\ttest_b_rr(%s,%s);\n",dst,dst);
1182 comprintf("\t}\n");
1183 break;
1184 case sz_word:
1185 comprintf("\tif (%s!=%s) {\n",src,dst);
1186 comprintf("\tmov_w_ri(%s,0);\n"
1187 "\tstart_needflags();\n",dst);
1188 comprintf("\tor_w(%s,%s);\n",dst,src);
1189 comprintf("\t} else {\n");
1190 comprintf("\tmov_w_rr(%s,%s);\n",dst,src);
1191 comprintf("\ttest_w_rr(%s,%s);\n",dst,dst);
1192 comprintf("\t}\n");
1193 break;
1194 case sz_long:
1195 comprintf("\tif (%s!=%s) {\n",src,dst);
1196 comprintf("\tmov_l_ri(%s,0);\n"
1197 "\tstart_needflags();\n",dst);
1198 comprintf("\tor_l(%s,%s);\n",dst,src);
1199 comprintf("\t} else {\n");
1200 comprintf("\tmov_l_rr(%s,%s);\n",dst,src);
1201 comprintf("\ttest_l_rr(%s,%s);\n",dst,dst);
1202 comprintf("\t}\n");
1203 break;
1204 }
1205 comprintf("\tlive_flags();\n");
1206 comprintf("\tend_needflags();\n");
1207 close_brace();
1208 return;
1209 }
1210
1211 case flag_logical:
1212 comprintf("\tdont_care_flags();\n");
1213 start_brace();
1214 switch (size)
1215 {
1216 case sz_byte:
1217 comprintf("\tstart_needflags();\n"
1218 "\ttest_b_rr(%s,%s);\n",value,value);
1219 break;
1220 case sz_word:
1221 comprintf("\tstart_needflags();\n"
1222 "\ttest_w_rr(%s,%s);\n",value,value);
1223 break;
1224 case sz_long:
1225 comprintf("\tstart_needflags();\n"
1226 "\ttest_l_rr(%s,%s);\n",value,value);
1227 break;
1228 }
1229 comprintf("\tlive_flags();\n");
1230 comprintf("\tend_needflags();\n");
1231 close_brace();
1232 return;
1233
1234
1235 case flag_add:
1236 case flag_sub:
1237 case flag_cmp:
1238 comprintf("\tdont_care_flags();\n");
1239 {
1240 const char* op;
1241 switch(type) {
1242 case flag_add: op="add"; break;
1243 case flag_sub: op="sub"; break;
1244 case flag_cmp: op="cmp"; break;
1245 default: assert(0);
1246 }
1247 switch (size)
1248 {
1249 case sz_byte:
1250 comprintf("\tstart_needflags();\n"
1251 "\t%s_b(%s,%s);\n",op,dst,src);
1252 break;
1253 case sz_word:
1254 comprintf("\tstart_needflags();\n"
1255 "\t%s_w(%s,%s);\n",op,dst,src);
1256 break;
1257 case sz_long:
1258 comprintf("\tstart_needflags();\n"
1259 "\t%s_l(%s,%s);\n",op,dst,src);
1260 break;
1261 }
1262 comprintf("\tlive_flags();\n");
1263 comprintf("\tend_needflags();\n");
1264 if (type!=flag_cmp) {
1265 duplicate_carry();
1266 }
1267 comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n");
1268
1269 return;
1270 }
1271
1272 case flag_addx:
1273 case flag_subx:
1274 uses_cmov;
1275 comprintf("\tdont_care_flags();\n");
1276 {
1277 const char* op;
1278 switch(type) {
1279 case flag_addx: op="adc"; break;
1280 case flag_subx: op="sbb"; break;
1281 default: assert(0);
1282 }
1283 start_brace();
1284 comprintf("\tint zero=scratchie++;\n"
1285 "\tint one=scratchie++;\n"
1286 "\tif (needed_flags&FLAG_Z) {\n"
1287 "\tmov_l_ri(zero,0);\n"
1288 "\tmov_l_ri(one,-1);\n"
1289 "\tmake_flags_live();\n"
1290 "\tcmov_l_rr(zero,one,%d);\n"
1291 "\t}\n",NATIVE_CC_NE);
1292 comprintf("\trestore_carry();\n"); /* Reload the X flag into C */
1293 switch (size)
1294 {
1295 case sz_byte:
1296 comprintf("\tstart_needflags();\n"
1297 "\t%s_b(%s,%s);\n",op,dst,src);
1298 break;
1299 case sz_word:
1300 comprintf("\tstart_needflags();\n"
1301 "\t%s_w(%s,%s);\n",op,dst,src);
1302 break;
1303 case sz_long:
1304 comprintf("\tstart_needflags();\n"
1305 "\t%s_l(%s,%s);\n",op,dst,src);
1306 break;
1307 }
1308 comprintf("\tlive_flags();\n");
1309 comprintf("\tif (needed_flags&FLAG_Z) {\n");
1310 comprintf("\tcmov_l_rr(zero,one,%d);\n", NATIVE_CC_NE);
1311 comprintf("\tset_zero(zero, one);\n"); /* No longer need one */
1312 comprintf("\tlive_flags();\n");
1313 comprintf("\t}\n");
1314 comprintf("\tend_needflags();\n");
1315 duplicate_carry();
1316 comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n");
1317 return;
1318 }
1319 default:
1320 failure;
1321 break;
1322 }
1323 }
1324
1325 static int /* returns zero for success, non-zero for failure */
gen_opcode(unsigned int opcode)1326 gen_opcode (unsigned int opcode)
1327 {
1328 struct instr *curi = table68k + opcode;
1329 const char* ssize=NULL;
1330
1331 insn_n_cycles = 2;
1332 global_failure=0;
1333 long_opcode=0;
1334 global_isjump=0;
1335 global_iscjump=0;
1336 global_isaddx=0;
1337 global_cmov=0;
1338 global_fpu=0;
1339 global_mayfail=0;
1340 hack_opcode=opcode;
1341 endstr[0]=0;
1342
1343 start_brace ();
1344 comprintf("\tuae_u8 scratchie=S1;\n");
1345 switch (curi->plev)
1346 {
1347 case 0: /* not privileged */
1348 break;
1349 case 1: /* unprivileged only on 68000 */
1350 if (cpu_level == 0)
1351 break;
1352 if (next_cpu_level < 0)
1353 next_cpu_level = 0;
1354
1355 /* fall through */
1356 case 2: /* priviledged */
1357 failure; /* Easy ones first */
1358 break;
1359 case 3: /* privileged if size == word */
1360 if (curi->size == sz_byte)
1361 break;
1362 failure;
1363 break;
1364 }
1365 switch (curi->size) {
1366 case sz_byte: ssize="b"; break;
1367 case sz_word: ssize="w"; break;
1368 case sz_long: ssize="l"; break;
1369 default: assert(0);
1370 }
1371 (void)ssize;
1372
1373 switch (curi->mnemo)
1374 {
1375 case i_OR:
1376 case i_AND:
1377 case i_EOR:
1378 #ifdef DISABLE_I_OR_AND_EOR
1379 failure;
1380 #endif
1381 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1382 genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1383 switch(curi->mnemo) {
1384 case i_OR: genflags (flag_or, curi->size, "", "src", "dst"); break;
1385 case i_AND: genflags (flag_and, curi->size, "", "src", "dst"); break;
1386 case i_EOR: genflags (flag_eor, curi->size, "", "src", "dst"); break;
1387 }
1388 genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1389 break;
1390
1391 case i_ORSR:
1392 case i_EORSR:
1393 failure;
1394 isjump;
1395 break;
1396
1397 case i_ANDSR:
1398 failure;
1399 isjump;
1400 break;
1401
1402 case i_SUB:
1403 #ifdef DISABLE_I_SUB
1404 failure;
1405 #endif
1406 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1407 genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1408 genflags (flag_sub, curi->size, "", "src", "dst");
1409 genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1410 break;
1411
1412 case i_SUBA:
1413 #ifdef DISABLE_I_SUBA
1414 failure;
1415 #endif
1416 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1417 genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1418 start_brace();
1419 comprintf("\tint tmp=scratchie++;\n");
1420 switch(curi->size) {
1421 case sz_byte: comprintf("\tsign_extend_8_rr(tmp,src);\n"); break;
1422 case sz_word: comprintf("\tsign_extend_16_rr(tmp,src);\n"); break;
1423 case sz_long: comprintf("\ttmp=src;\n"); break;
1424 default: assert(0);
1425 }
1426 comprintf("\tsub_l(dst,tmp);\n");
1427 genastore ("dst", curi->dmode, "dstreg", sz_long, "dst");
1428 break;
1429
1430 case i_SUBX:
1431 #ifdef DISABLE_I_SUBX
1432 failure;
1433 #endif
1434 isaddx;
1435 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1436 genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1437 genflags (flag_subx, curi->size, "", "src", "dst");
1438 genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1439 break;
1440
1441 case i_SBCD:
1442 failure;
1443 /* I don't think so! */
1444 break;
1445
1446 case i_ADD:
1447 #ifdef DISABLE_I_ADD
1448 failure;
1449 #endif
1450 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1451 genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1452 genflags (flag_add, curi->size, "", "src", "dst");
1453 genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1454 break;
1455
1456 case i_ADDA:
1457 #ifdef DISABLE_I_ADDA
1458 failure;
1459 #endif
1460 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1461 genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1462 start_brace();
1463 comprintf("\tint tmp=scratchie++;\n");
1464 switch(curi->size) {
1465 case sz_byte: comprintf("\tsign_extend_8_rr(tmp,src);\n"); break;
1466 case sz_word: comprintf("\tsign_extend_16_rr(tmp,src);\n"); break;
1467 case sz_long: comprintf("\ttmp=src;\n"); break;
1468 default: assert(0);
1469 }
1470 comprintf("\tadd_l(dst,tmp);\n");
1471 genastore ("dst", curi->dmode, "dstreg", sz_long, "dst");
1472 break;
1473
1474 case i_ADDX:
1475 #ifdef DISABLE_I_ADDX
1476 failure;
1477 #endif
1478 isaddx;
1479 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1480 genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1481 start_brace();
1482 genflags (flag_addx, curi->size, "", "src", "dst");
1483 genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1484 break;
1485
1486 case i_ABCD:
1487 failure;
1488 /* No BCD maths for me.... */
1489 break;
1490
1491 case i_NEG:
1492 #ifdef DISABLE_I_NEG
1493 failure;
1494 #endif
1495 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1496 start_brace ();
1497 comprintf("\tint dst=scratchie++;\n");
1498 comprintf("\tmov_l_ri(dst,0);\n");
1499 genflags (flag_sub, curi->size, "", "src", "dst");
1500 genastore ("dst", curi->smode, "srcreg", curi->size, "src");
1501 break;
1502
1503 case i_NEGX:
1504 #ifdef DISABLE_I_NEGX
1505 failure;
1506 #endif
1507 isaddx;
1508 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1509 start_brace ();
1510 comprintf("\tint dst=scratchie++;\n");
1511 comprintf("\tmov_l_ri(dst,0);\n");
1512 genflags (flag_subx, curi->size, "", "src", "dst");
1513 genastore ("dst", curi->smode, "srcreg", curi->size, "src");
1514 break;
1515
1516 case i_NBCD:
1517 failure;
1518 /* Nope! */
1519 break;
1520
1521 case i_CLR:
1522 #ifdef DISABLE_I_CLR
1523 failure;
1524 #endif
1525 genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
1526 start_brace();
1527 comprintf("\tint dst=scratchie++;\n");
1528 comprintf("\tmov_l_ri(dst,0);\n");
1529 genflags (flag_logical, curi->size, "dst", "", "");
1530 genastore ("dst", curi->smode, "srcreg", curi->size, "src");
1531 break;
1532
1533 case i_NOT:
1534 #ifdef DISABLE_I_NOT
1535 failure;
1536 #endif
1537 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1538 start_brace ();
1539 comprintf("\tint dst=scratchie++;\n");
1540 comprintf("\tmov_l_ri(dst,0xffffffff);\n");
1541 genflags (flag_eor, curi->size, "", "src", "dst");
1542 genastore ("dst", curi->smode, "srcreg", curi->size, "src");
1543 break;
1544
1545 case i_TST:
1546 #ifdef DISABLE_I_TST
1547 failure;
1548 #endif
1549 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1550 genflags (flag_logical, curi->size, "src", "", "");
1551 break;
1552 case i_BCHG:
1553 case i_BCLR:
1554 case i_BSET:
1555 case i_BTST:
1556 #ifdef DISABLE_I_BCHG_BCLR_BSET_BTST
1557 failure;
1558 #endif
1559 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1560 genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1561 start_brace();
1562 comprintf("\tint s=scratchie++;\n"
1563 "\tint tmp=scratchie++;\n"
1564 "\tmov_l_rr(s,src);\n");
1565 if (curi->size == sz_byte)
1566 comprintf("\tand_l_ri(s,7);\n");
1567 else
1568 comprintf("\tand_l_ri(s,31);\n");
1569
1570 {
1571 const char* op;
1572 int need_write=1;
1573
1574 switch(curi->mnemo) {
1575 case i_BCHG: op="btc"; break;
1576 case i_BCLR: op="btr"; break;
1577 case i_BSET: op="bts"; break;
1578 case i_BTST: op="bt"; need_write=0; break;
1579 default: op=""; assert(0);
1580 }
1581 comprintf("\t%s_l_rr(dst,s);\n" /* Answer now in C */
1582 "\tsbb_l(s,s);\n" /* s is 0 if bit was 0, -1 otherwise */
1583 "\tmake_flags_live();\n" /* Get the flags back */
1584 "\tdont_care_flags();\n",op);
1585 if (!noflags) {
1586 comprintf("\tstart_needflags();\n"
1587 "\tset_zero(s,tmp);\n"
1588 "\tlive_flags();\n"
1589 "\tend_needflags();\n");
1590 }
1591 if (need_write)
1592 genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1593 }
1594 break;
1595
1596 case i_CMPM:
1597 case i_CMP:
1598 #ifdef DISABLE_I_CMPM_CMP
1599 failure;
1600 #endif
1601 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1602 genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1603 start_brace ();
1604 genflags (flag_cmp, curi->size, "", "src", "dst");
1605 break;
1606
1607 case i_CMPA:
1608 #ifdef DISABLE_I_CMPA
1609 failure;
1610 #endif
1611 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1612 genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0);
1613 start_brace();
1614 comprintf("\tint tmps=scratchie++;\n");
1615 switch(curi->size) {
1616 case sz_byte: comprintf("\tsign_extend_8_rr(tmps,src);\n"); break;
1617 case sz_word: comprintf("\tsign_extend_16_rr(tmps,src);\n"); break;
1618 case sz_long: comprintf("tmps=src;\n"); break;
1619 default: assert(0);
1620 }
1621 genflags (flag_cmp, sz_long, "", "tmps", "dst");
1622 break;
1623 /* The next two are coded a little unconventional, but they are doing
1624 * weird things... */
1625
1626 case i_MVPRM:
1627 isjump;
1628 failure;
1629 break;
1630
1631 case i_MVPMR:
1632 isjump;
1633 failure;
1634 break;
1635
1636 case i_MOVE:
1637 #ifdef DISABLE_I_MOVE
1638 failure;
1639 #endif
1640 switch(curi->dmode) {
1641 case Dreg:
1642 case Areg:
1643 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1644 genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1645 genflags (flag_mov, curi->size, "", "src", "dst");
1646 genastore ("dst", curi->dmode, "dstreg", curi->size, "dst");
1647 break;
1648 default: /* It goes to memory, not a register */
1649 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1650 genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1651 genflags (flag_logical, curi->size, "src", "", "");
1652 genastore ("src", curi->dmode, "dstreg", curi->size, "dst");
1653 break;
1654 }
1655 break;
1656
1657 case i_MOVEA:
1658 #ifdef DISABLE_I_MOVEA
1659 failure;
1660 #endif
1661 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1662 genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1663
1664 start_brace();
1665 comprintf("\tint tmps=scratchie++;\n");
1666 switch(curi->size) {
1667 case sz_word: comprintf("\tsign_extend_16_rr(dst,src);\n"); break;
1668 case sz_long: comprintf("\tmov_l_rr(dst,src);\n"); break;
1669 default: assert(0);
1670 }
1671 genastore ("dst", curi->dmode, "dstreg", sz_long, "dst");
1672 break;
1673
1674 case i_MVSR2:
1675 isjump;
1676 failure;
1677 break;
1678
1679 case i_MV2SR:
1680 isjump;
1681 failure;
1682 break;
1683
1684 case i_SWAP:
1685 #ifdef DISABLE_I_SWAP
1686 failure;
1687 #endif
1688 genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
1689 comprintf("\tdont_care_flags();\n");
1690 comprintf("\trol_l_ri(src,16);\n");
1691 genflags (flag_logical, sz_long, "src", "", "");
1692 genastore ("src", curi->smode, "srcreg", sz_long, "src");
1693 break;
1694
1695 case i_EXG:
1696 #ifdef DISABLE_I_EXG
1697 failure;
1698 #endif
1699 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1700 genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
1701 start_brace();
1702 comprintf("\tint tmp=scratchie++;\n"
1703 "\tmov_l_rr(tmp,src);\n");
1704 genastore ("dst", curi->smode, "srcreg", curi->size, "src");
1705 genastore ("tmp", curi->dmode, "dstreg", curi->size, "dst");
1706 break;
1707
1708 case i_EXT:
1709 #ifdef DISABLE_I_EXT
1710 failure;
1711 #endif
1712 genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
1713 comprintf("\tdont_care_flags();\n");
1714 start_brace ();
1715 switch (curi->size)
1716 {
1717 case sz_byte:
1718 comprintf ("\tint dst = src;\n"
1719 "\tsign_extend_8_rr(src,src);\n");
1720 break;
1721 case sz_word:
1722 comprintf ("\tint dst = scratchie++;\n"
1723 "\tsign_extend_8_rr(dst,src);\n");
1724 break;
1725 case sz_long:
1726 comprintf ("\tint dst = src;\n"
1727 "\tsign_extend_16_rr(src,src);\n");
1728 break;
1729 default:
1730 assert(0);
1731 }
1732 genflags (flag_logical,
1733 curi->size == sz_word ? sz_word : sz_long, "dst", "", "");
1734 genastore ("dst", curi->smode, "srcreg",
1735 curi->size == sz_word ? sz_word : sz_long, "src");
1736 break;
1737
1738 case i_MVMEL:
1739 #ifdef DISABLE_I_MVEL
1740 failure;
1741 #endif
1742 genmovemel (opcode);
1743 break;
1744
1745 case i_MVMLE:
1746 #ifdef DISABLE_I_MVMLE
1747 failure;
1748 #endif
1749 genmovemle (opcode);
1750 break;
1751
1752 case i_TRAP:
1753 isjump;
1754 failure;
1755 break;
1756
1757 case i_MVR2USP:
1758 isjump;
1759 failure;
1760 break;
1761
1762 case i_MVUSP2R:
1763 isjump;
1764 failure;
1765 break;
1766
1767 case i_RESET:
1768 isjump;
1769 failure;
1770 break;
1771
1772 case i_NOP:
1773 break;
1774
1775 case i_STOP:
1776 isjump;
1777 failure;
1778 break;
1779
1780 case i_RTE:
1781 isjump;
1782 failure;
1783 break;
1784
1785 case i_RTD:
1786 #ifdef DISABLE_I_RTD
1787 failure;
1788 #endif
1789 genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0);
1790 /* offs is constant */
1791 comprintf("\tadd_l_ri(offs,4);\n");
1792 start_brace();
1793 comprintf("\tint newad=scratchie++;\n"
1794 "\treadlong(15,newad,scratchie);\n"
1795 "\tmov_l_mr((uintptr)®s.pc,newad);\n"
1796 "\tget_n_addr_jmp(newad,PC_P,scratchie);\n"
1797 "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n"
1798 "\tm68k_pc_offset=0;\n"
1799 "\tadd_l(15,offs);\n");
1800 gen_update_next_handler();
1801 isjump;
1802 break;
1803
1804 case i_LINK:
1805 #ifdef DISABLE_I_LINK
1806 failure;
1807 #endif
1808 genamode (curi->smode, "srcreg", sz_long, "src", 1, 0);
1809 genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
1810 comprintf("\tsub_l_ri(15,4);\n"
1811 "\twritelong_clobber(15,src,scratchie);\n"
1812 "\tmov_l_rr(src,15);\n");
1813 if (curi->size==sz_word)
1814 comprintf("\tsign_extend_16_rr(offs,offs);\n");
1815 comprintf("\tadd_l(15,offs);\n");
1816 genastore ("src", curi->smode, "srcreg", sz_long, "src");
1817 break;
1818
1819 case i_UNLK:
1820 #ifdef DISABLE_I_UNLK
1821 failure;
1822 #endif
1823 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1824 comprintf("\tmov_l_rr(15,src);\n"
1825 "\treadlong(15,src,scratchie);\n"
1826 "\tadd_l_ri(15,4);\n");
1827 genastore ("src", curi->smode, "srcreg", curi->size, "src");
1828 break;
1829
1830 case i_RTS:
1831 #ifdef DISABLE_I_RTS
1832 failure;
1833 #endif
1834 comprintf("\tint newad=scratchie++;\n"
1835 "\treadlong(15,newad,scratchie);\n"
1836 "\tmov_l_mr((uintptr)®s.pc,newad);\n"
1837 "\tget_n_addr_jmp(newad,PC_P,scratchie);\n"
1838 "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n"
1839 "\tm68k_pc_offset=0;\n"
1840 "\tlea_l_brr(15,15,4);\n");
1841 gen_update_next_handler();
1842 isjump;
1843 break;
1844
1845 case i_TRAPV:
1846 isjump;
1847 failure;
1848 break;
1849
1850 case i_RTR:
1851 isjump;
1852 failure;
1853 break;
1854
1855 case i_JSR:
1856 #ifdef DISABLE_I_JSR
1857 failure;
1858 #endif
1859 isjump;
1860 genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1861 start_brace();
1862 comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n");
1863 comprintf("\tint ret=scratchie++;\n"
1864 "\tmov_l_ri(ret,retadd);\n"
1865 "\tsub_l_ri(15,4);\n"
1866 "\twritelong_clobber(15,ret,scratchie);\n");
1867 comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n"
1868 "\tget_n_addr_jmp(srca,PC_P,scratchie);\n"
1869 "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n"
1870 "\tm68k_pc_offset=0;\n");
1871 gen_update_next_handler();
1872 break;
1873
1874 case i_JMP:
1875 #ifdef DISABLE_I_JMP
1876 failure;
1877 #endif
1878 isjump;
1879 genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1880 comprintf("\tmov_l_mr((uintptr)®s.pc,srca);\n"
1881 "\tget_n_addr_jmp(srca,PC_P,scratchie);\n"
1882 "\tmov_l_mr((uintptr)®s.pc_oldp,PC_P);\n"
1883 "\tm68k_pc_offset=0;\n");
1884 gen_update_next_handler();
1885 break;
1886
1887 case i_BSR:
1888 #ifdef DISABLE_I_BSR
1889 failure;
1890 #endif
1891 is_const_jump;
1892 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1893 start_brace();
1894 comprintf("\tuae_u32 retadd=start_pc+((char *)comp_pc_p-(char *)start_pc_p)+m68k_pc_offset;\n");
1895 comprintf("\tint ret=scratchie++;\n"
1896 "\tmov_l_ri(ret,retadd);\n"
1897 "\tsub_l_ri(15,4);\n"
1898 "\twritelong_clobber(15,ret,scratchie);\n");
1899 comprintf("\tadd_l_ri(src,m68k_pc_offset_thisinst+2);\n");
1900 comprintf("\tm68k_pc_offset=0;\n");
1901 comprintf("\tadd_l(PC_P,src);\n");
1902
1903 comprintf("\tcomp_pc_p=(uae_u8*)(uintptr)get_const(PC_P);\n");
1904 break;
1905
1906 case i_Bcc:
1907 #ifdef DISABLE_I_BCC
1908 failure;
1909 #endif
1910 comprintf("\tuae_u32 v,v1,v2;\n");
1911 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1912 /* That source is an immediate, so we can clobber it with abandon */
1913 switch(curi->size) {
1914 case sz_byte: comprintf("\tsign_extend_8_rr(src,src);\n"); break;
1915 case sz_word: comprintf("\tsign_extend_16_rr(src,src);\n"); break;
1916 case sz_long: break;
1917 }
1918 comprintf("\tsub_l_ri(src,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n");
1919 /* Leave the following as "add" --- it will allow it to be optimized
1920 away due to src being a constant ;-) */
1921 comprintf("\tadd_l_ri(src,(uintptr)comp_pc_p);\n");
1922 comprintf("\tmov_l_ri(PC_P,(uintptr)comp_pc_p);\n");
1923 /* Now they are both constant. Might as well fold in m68k_pc_offset */
1924 comprintf("\tadd_l_ri(src,m68k_pc_offset);\n");
1925 comprintf("\tadd_l_ri(PC_P,m68k_pc_offset);\n");
1926 comprintf("\tm68k_pc_offset=0;\n");
1927
1928 if (curi->cc>=2) {
1929 comprintf("\tv1=get_const(PC_P);\n"
1930 "\tv2=get_const(src);\n"
1931 "\tregister_branch(v1,v2,%d);\n",
1932 cond_codes[curi->cc]);
1933 comprintf("\tmake_flags_live();\n"); /* Load the flags */
1934 isjump;
1935 }
1936 else {
1937 is_const_jump;
1938 }
1939
1940 switch(curi->cc) {
1941 case 0: /* Unconditional jump */
1942 comprintf("\tmov_l_rr(PC_P,src);\n");
1943 comprintf("\tcomp_pc_p=(uae_u8*)(uintptr)get_const(PC_P);\n");
1944 break;
1945 case 1: break; /* This is silly! */
1946 case 8: failure; break; /* Work out details! FIXME */
1947 case 9: failure; break; /* Not critical, though! */
1948
1949 case 2:
1950 case 3:
1951 case 4:
1952 case 5:
1953 case 6:
1954 case 7:
1955 case 10:
1956 case 11:
1957 case 12:
1958 case 13:
1959 case 14:
1960 case 15:
1961 break;
1962 default: assert(0);
1963 }
1964 break;
1965
1966 case i_LEA:
1967 #ifdef DISABLE_I_LEA
1968 failure;
1969 #endif
1970 genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1971 genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0);
1972 genastore ("srca", curi->dmode, "dstreg", curi->size, "dst");
1973 break;
1974
1975 case i_PEA:
1976 #ifdef DISABLE_I_PEA
1977 failure;
1978 #endif
1979 if (table68k[opcode].smode==Areg ||
1980 table68k[opcode].smode==Aind ||
1981 table68k[opcode].smode==Aipi ||
1982 table68k[opcode].smode==Apdi ||
1983 table68k[opcode].smode==Ad16 ||
1984 table68k[opcode].smode==Ad8r)
1985 comprintf("if (srcreg==7) dodgy=1;\n");
1986
1987 genamode (curi->smode, "srcreg", curi->size, "src", 0, 0);
1988 genamode (Apdi, "7", sz_long, "dst", 2, 0);
1989 genastore ("srca", Apdi, "7", sz_long, "dst");
1990 break;
1991
1992 case i_DBcc:
1993 #ifdef DISABLE_I_DBCC
1994 failure;
1995 #endif
1996 isjump;
1997 uses_cmov;
1998 genamode (curi->smode, "srcreg", curi->size, "src", 1, 0);
1999 genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0);
2000
2001 /* That offs is an immediate, so we can clobber it with abandon */
2002 switch(curi->size) {
2003 case sz_word: comprintf("\tsign_extend_16_rr(offs,offs);\n"); break;
2004 default: assert(0); /* Seems this only comes in word flavour */
2005 }
2006 comprintf("\tsub_l_ri(offs,m68k_pc_offset-m68k_pc_offset_thisinst-2);\n");
2007 comprintf("\tadd_l_ri(offs,(uintptr)comp_pc_p);\n"); /* New PC,
2008 once the
2009 offset_68k is
2010 * also added */
2011 /* Let's fold in the m68k_pc_offset at this point */
2012 comprintf("\tadd_l_ri(offs,m68k_pc_offset);\n");
2013 comprintf("\tadd_l_ri(PC_P,m68k_pc_offset);\n");
2014 comprintf("\tm68k_pc_offset=0;\n");
2015
2016 start_brace();
2017 comprintf("\tint nsrc=scratchie++;\n");
2018
2019 if (curi->cc>=2) {
2020 comprintf("\tmake_flags_live();\n"); /* Load the flags */
2021 }
2022
2023 assert (curi->size==sz_word);
2024
2025 switch(curi->cc) {
2026 case 0: /* This is an elaborate nop? */
2027 break;
2028 case 1:
2029 comprintf("\tstart_needflags();\n");
2030 comprintf("\tsub_w_ri(src,1);\n");
2031 comprintf("\t end_needflags();\n");
2032 start_brace();
2033 comprintf("\tuae_u32 v2,v;\n"
2034 "\tuae_u32 v1=get_const(PC_P);\n");
2035 comprintf("\tv2=get_const(offs);\n"
2036 "\tregister_branch(v1,v2,%d);\n", NATIVE_CC_CC);
2037 break;
2038
2039 case 8: failure; break; /* Work out details! FIXME */
2040 case 9: failure; break; /* Not critical, though! */
2041
2042 case 2:
2043 case 3:
2044 case 4:
2045 case 5:
2046 case 6:
2047 case 7:
2048 case 10:
2049 case 11:
2050 case 12:
2051 case 13:
2052 case 14:
2053 case 15:
2054 comprintf("\tmov_l_rr(nsrc,src);\n");
2055 comprintf("\tlea_l_brr(scratchie,src,(uae_s32)-1);\n"
2056 "\tmov_w_rr(src,scratchie);\n");
2057 comprintf("\tcmov_l_rr(offs,PC_P,%d);\n",
2058 cond_codes[curi->cc]);
2059 comprintf("\tcmov_l_rr(src,nsrc,%d);\n",
2060 cond_codes[curi->cc]);
2061 /* OK, now for cc=true, we have src==nsrc and offs==PC_P,
2062 so whether we move them around doesn't matter. However,
2063 if cc=false, we have offs==jump_pc, and src==nsrc-1 */
2064
2065 comprintf("\t start_needflags();\n");
2066 comprintf("\ttest_w_rr(nsrc,nsrc);\n");
2067 comprintf("\t end_needflags();\n");
2068 comprintf("\tcmov_l_rr(PC_P,offs,%d);\n", NATIVE_CC_NE);
2069 break;
2070 default: assert(0);
2071 }
2072 genastore ("src", curi->smode, "srcreg", curi->size, "src");
2073 gen_update_next_handler();
2074 break;
2075
2076 case i_Scc:
2077 #ifdef DISABLE_I_SCC
2078 failure;
2079 #endif
2080 genamode (curi->smode, "srcreg", curi->size, "src", 2, 0);
2081 start_brace ();
2082 comprintf ("\tint val = scratchie++;\n");
2083
2084 /* We set val to 0 if we really should use 255, and to 1 for real 0 */
2085 switch(curi->cc) {
2086 case 0: /* Unconditional set */
2087 comprintf("\tmov_l_ri(val,0);\n");
2088 break;
2089 case 1:
2090 /* Unconditional not-set */
2091 comprintf("\tmov_l_ri(val,1);\n");
2092 break;
2093 case 8: failure; break; /* Work out details! FIXME */
2094 case 9: failure; break; /* Not critical, though! */
2095
2096 case 2:
2097 case 3:
2098 case 4:
2099 case 5:
2100 case 6:
2101 case 7:
2102 case 10:
2103 case 11:
2104 case 12:
2105 case 13:
2106 case 14:
2107 case 15:
2108 comprintf("\tmake_flags_live();\n"); /* Load the flags */
2109 /* All condition codes can be inverted by changing the LSB */
2110 comprintf("\tsetcc(val,%d);\n",
2111 cond_codes[curi->cc]^1); break;
2112 default: assert(0);
2113 }
2114 comprintf("\tsub_b_ri(val,1);\n");
2115 genastore ("val", curi->smode, "srcreg", curi->size, "src");
2116 break;
2117
2118 case i_DIVU:
2119 isjump;
2120 failure;
2121 break;
2122
2123 case i_DIVS:
2124 isjump;
2125 failure;
2126 break;
2127
2128 case i_MULU:
2129 #ifdef DISABLE_I_MULU
2130 failure;
2131 #endif
2132 comprintf("\tdont_care_flags();\n");
2133 genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
2134 genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
2135 /* To do 16x16 unsigned multiplication, we actually use
2136 32x32 signed, and zero-extend the registers first.
2137 That solves the problem of MUL needing dedicated registers
2138 on the x86 */
2139 comprintf("\tzero_extend_16_rr(scratchie,src);\n"
2140 "\tzero_extend_16_rr(dst,dst);\n"
2141 "\timul_32_32(dst,scratchie);\n");
2142 genflags (flag_logical, sz_long, "dst", "", "");
2143 genastore ("dst", curi->dmode, "dstreg", sz_long, "dst");
2144 break;
2145
2146 case i_MULS:
2147 #ifdef DISABLE_I_MULS
2148 failure;
2149 #endif
2150 comprintf("\tdont_care_flags();\n");
2151 genamode (curi->smode, "srcreg", sz_word, "src", 1, 0);
2152 genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0);
2153 comprintf("\tsign_extend_16_rr(scratchie,src);\n"
2154 "\tsign_extend_16_rr(dst,dst);\n"
2155 "\timul_32_32(dst,scratchie);\n");
2156 genflags (flag_logical, sz_long, "dst", "", "");
2157 genastore ("dst", curi->dmode, "dstreg", sz_long, "dst");
2158 break;
2159
2160 case i_CHK:
2161 isjump;
2162 failure;
2163 break;
2164
2165 case i_CHK2:
2166 isjump;
2167 failure;
2168 break;
2169
2170 case i_ASR:
2171 #ifdef DISABLE_I_ASR
2172 failure;
2173 #endif
2174 mayfail;
2175 if (curi->smode==Dreg) {
2176 comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n"
2177 " FAIL(1);\n"
2178 " " RETURN "\n"
2179 "} \n");
2180 start_brace();
2181 }
2182 comprintf("\tdont_care_flags();\n");
2183
2184 genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
2185 genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
2186
2187 start_brace();
2188 if (!noflags)
2189 comprintf("\tstart_needflags();\n");
2190 if (curi->smode!=immi) {
2191 uses_cmov;
2192 start_brace();
2193 comprintf("\tint zero = scratchie++;\n");
2194 comprintf("\tint minus1 = scratchie++;\n");
2195 comprintf("\tand_l_ri(cnt,63);\n");
2196 comprintf("\tmov_l_ri(zero, 0);\n");
2197 comprintf("\tmov_l_ri(minus1, -1);\n");
2198 switch(curi->size) {
2199 case sz_byte:
2200 comprintf("\ttest_b_rr(data,data);\n");
2201 comprintf("\tcmov_l_rr(zero, minus1, NATIVE_CC_MI);\n");
2202 comprintf("\ttest_l_ri(cnt, 0x38);\n");
2203 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2204 comprintf("\tshra_b_rr(data,cnt);\n");
2205 break;
2206 case sz_word:
2207 comprintf("\ttest_w_rr(data,data);\n");
2208 comprintf("\tcmov_l_rr(zero, minus1, NATIVE_CC_MI);\n");
2209 comprintf("\ttest_l_ri(cnt, 0x30);\n");
2210 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2211 comprintf("\tshra_w_rr(data,cnt);\n");
2212 break;
2213 case sz_long:
2214 comprintf("\ttest_l_rr(data,data);\n");
2215 comprintf("\tcmov_l_rr(zero, minus1, NATIVE_CC_MI);\n");
2216 comprintf("\ttest_l_ri(cnt, 0x20);\n");
2217 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2218 comprintf("\tshra_l_rr(data,cnt);\n");
2219 break;
2220 default: assert(0);
2221 }
2222 /* Result of shift is now in data. */
2223 }
2224 else {
2225 switch(curi->size) {
2226 case sz_byte: comprintf("\tshra_b_ri(data,srcreg);\n"); break;
2227 case sz_word: comprintf("\tshra_w_ri(data,srcreg);\n"); break;
2228 case sz_long: comprintf("\tshra_l_ri(data,srcreg);\n"); break;
2229 default: assert(0);
2230 }
2231 }
2232 /* And create the flags */
2233 if (!noflags) {
2234 comprintf("\tlive_flags();\n");
2235 comprintf("\tend_needflags();\n");
2236 if (curi->smode!=immi)
2237 comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4);
2238 else
2239 comprintf("\tduplicate_carry();\n");
2240 comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n");
2241 }
2242 genastore ("data", curi->dmode, "dstreg", curi->size, "data");
2243 break;
2244
2245 case i_ASL:
2246 #ifdef DISABLE_I_ASL
2247 failure;
2248 #endif
2249 mayfail;
2250 if (curi->smode==Dreg) {
2251 comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n"
2252 " FAIL(1);\n"
2253 " " RETURN "\n"
2254 "} \n");
2255 start_brace();
2256 }
2257 comprintf("\tdont_care_flags();\n");
2258 /* Except for the handling of the V flag, this is identical to
2259 LSL. The handling of V is, uhm, unpleasant, so if it's needed,
2260 let the normal emulation handle it. Shoulders of giants kinda
2261 thing ;-) */
2262 comprintf("if (needed_flags & FLAG_V) {\n"
2263 " FAIL(1);\n"
2264 " " RETURN "\n"
2265 "} \n");
2266
2267 genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
2268 genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
2269
2270 if (!noflags)
2271 comprintf("\tstart_needflags();\n");
2272 if (curi->smode!=immi) {
2273 uses_cmov;
2274 start_brace();
2275 comprintf("\tint zero = scratchie++;\n");
2276 comprintf("\tand_l_ri(cnt,63);\n");
2277 comprintf("\tmov_l_ri(zero, 0);\n");
2278 switch(curi->size) {
2279 case sz_byte:
2280 comprintf("\ttest_l_ri(cnt, 0x38);\n");
2281 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2282 comprintf("\tshll_b_rr(data,cnt);\n");
2283 break;
2284 case sz_word:
2285 comprintf("\ttest_l_ri(cnt, 0x30);\n");
2286 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2287 comprintf("\tshll_w_rr(data,cnt);\n");
2288 break;
2289 case sz_long:
2290 comprintf("\ttest_l_ri(cnt, 0x20);\n");
2291 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2292 comprintf("\tshll_l_rr(data,cnt);\n");
2293 break;
2294 default: assert(0);
2295 }
2296 /* Result of shift is now in data. */
2297 }
2298 else {
2299 switch(curi->size) {
2300 case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n"); break;
2301 case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n"); break;
2302 case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n"); break;
2303 default: assert(0);
2304 }
2305 }
2306 /* And create the flags */
2307 if (!noflags) {
2308 comprintf("\tlive_flags();\n");
2309 comprintf("\tend_needflags();\n");
2310 if (curi->smode!=immi)
2311 comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4);
2312 else
2313 comprintf("\tduplicate_carry();\n");
2314 comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n");
2315 }
2316 genastore ("data", curi->dmode, "dstreg", curi->size, "data");
2317 break;
2318
2319 case i_LSR:
2320 #ifdef DISABLE_I_LSR
2321 failure;
2322 #endif
2323 mayfail;
2324 if (curi->smode==Dreg) {
2325 comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n"
2326 " FAIL(1);\n"
2327 " " RETURN "\n"
2328 "} \n");
2329 start_brace();
2330 }
2331 comprintf("\tdont_care_flags();\n");
2332
2333 genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
2334 genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
2335
2336 start_brace();
2337 if (!noflags)
2338 comprintf("\tstart_needflags();\n");
2339 if (curi->smode!=immi) {
2340 uses_cmov;
2341 start_brace();
2342 comprintf("\tint zero = scratchie++;\n");
2343 comprintf("\tand_l_ri(cnt,63);\n");
2344 comprintf("\tmov_l_ri(zero, 0);\n");
2345 switch(curi->size) {
2346 case sz_byte:
2347 comprintf("\ttest_l_ri(cnt, 0x38);\n");
2348 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2349 comprintf("\tshrl_b_rr(data,cnt);\n");
2350 break;
2351 case sz_word:
2352 comprintf("\ttest_l_ri(cnt, 0x30);\n");
2353 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2354 comprintf("\tshrl_w_rr(data,cnt);\n");
2355 break;
2356 case sz_long:
2357 comprintf("\ttest_l_ri(cnt, 0x20);\n");
2358 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2359 comprintf("\tshrl_l_rr(data, cnt);\n");
2360 break;
2361 default: assert(0);
2362 }
2363 /* Result of shift is now in data. */
2364 }
2365 else {
2366 switch(curi->size) {
2367 case sz_byte: comprintf("\tshrl_b_ri(data,srcreg);\n"); break;
2368 case sz_word: comprintf("\tshrl_w_ri(data,srcreg);\n"); break;
2369 case sz_long: comprintf("\tshrl_l_ri(data,srcreg);\n"); break;
2370 default: assert(0);
2371 }
2372 }
2373 /* And create the flags */
2374 if (!noflags) {
2375 comprintf("\tlive_flags();\n");
2376 comprintf("\tend_needflags();\n");
2377 if (curi->smode!=immi)
2378 comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4);
2379 else
2380 comprintf("\tduplicate_carry();\n");
2381 comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n");
2382 }
2383 genastore ("data", curi->dmode, "dstreg", curi->size, "data");
2384 break;
2385
2386 case i_LSL:
2387 #ifdef DISABLE_I_LSL
2388 failure;
2389 #endif
2390 mayfail;
2391 if (curi->smode==Dreg) {
2392 comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n"
2393 " FAIL(1);\n"
2394 " " RETURN "\n"
2395 "} \n");
2396 start_brace();
2397 }
2398 comprintf("\tdont_care_flags();\n");
2399
2400 genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
2401 genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
2402
2403 start_brace();
2404 if (!noflags)
2405 comprintf("\tstart_needflags();\n");
2406 if (curi->smode!=immi) {
2407 uses_cmov;
2408 start_brace();
2409 comprintf("\tint zero = scratchie++;\n");
2410 comprintf("\tand_l_ri(cnt,63);\n");
2411 comprintf("\tmov_l_ri(zero, 0);\n");
2412 switch(curi->size) {
2413 case sz_byte:
2414 comprintf("\ttest_l_ri(cnt, 0x38);\n");
2415 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2416 comprintf("\tshll_b_rr(data,cnt);\n");
2417 break;
2418 case sz_word:
2419 comprintf("\ttest_l_ri(cnt, 0x30);\n");
2420 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2421 comprintf("\tshll_w_rr(data,cnt);\n");
2422 break;
2423 case sz_long:
2424 comprintf("\ttest_l_ri(cnt, 0x20);\n");
2425 comprintf("\tcmov_l_rr(data, zero, NATIVE_CC_NE);\n");
2426 comprintf("\tshll_l_rr(data,cnt);\n");
2427 break;
2428 default: assert(0);
2429 }
2430 /* Result of shift is now in data. */
2431 }
2432 else {
2433 switch(curi->size) {
2434 case sz_byte: comprintf("\tshll_b_ri(data,srcreg);\n"); break;
2435 case sz_word: comprintf("\tshll_w_ri(data,srcreg);\n"); break;
2436 case sz_long: comprintf("\tshll_l_ri(data,srcreg);\n"); break;
2437 default: assert(0);
2438 }
2439 }
2440 /* And create the flags */
2441 if (!noflags) {
2442 comprintf("\tlive_flags();\n");
2443 comprintf("\tend_needflags();\n");
2444 if (curi->smode!=immi)
2445 comprintf("\tsetcc_for_cntzero(cnt, data, %d);\n", curi->size == sz_byte ? 1 : curi->size == sz_word ? 2 : 4);
2446 else
2447 comprintf("\tduplicate_carry();\n");
2448 comprintf("if (!(needed_flags & FLAG_CZNV)) dont_care_flags();\n");
2449 }
2450 genastore ("data", curi->dmode, "dstreg", curi->size, "data");
2451 break;
2452
2453 case i_ROL:
2454 #ifdef DISABLE_I_ROL
2455 failure;
2456 #endif
2457 mayfail;
2458 if (curi->smode==Dreg) {
2459 comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n"
2460 " FAIL(1);\n"
2461 " " RETURN "\n"
2462 "} \n");
2463 start_brace();
2464 }
2465 comprintf("\tdont_care_flags();\n");
2466 genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
2467 genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
2468 start_brace ();
2469
2470 switch(curi->size) {
2471 case sz_long: comprintf("\t rol_l_rr(data,cnt);\n"); break;
2472 case sz_word: comprintf("\t rol_w_rr(data,cnt);\n"); break;
2473 case sz_byte: comprintf("\t rol_b_rr(data,cnt);\n"); break;
2474 }
2475
2476 if (!noflags) {
2477 comprintf("\tstart_needflags();\n");
2478 /*
2479 * x86 ROL instruction does not set ZF/SF, so we need extra checks here
2480 */
2481 comprintf("\tif (needed_flags & FLAG_ZNV)\n");
2482 switch(curi->size) {
2483 case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break;
2484 case sz_word: comprintf("\t test_w_rr(data,data);\n"); break;
2485 case sz_long: comprintf("\t test_l_rr(data,data);\n"); break;
2486 }
2487 comprintf("\t bt_l_ri(data,0x00);\n"); /* Set C */
2488 comprintf("\t live_flags();\n");
2489 comprintf("\t end_needflags();\n");
2490 }
2491 genastore ("data", curi->dmode, "dstreg", curi->size, "data");
2492 break;
2493
2494 case i_ROR:
2495 #ifdef DISABLE_I_ROR
2496 failure;
2497 #endif
2498 mayfail;
2499 if (curi->smode==Dreg) {
2500 comprintf("if ((uae_u32)srcreg==(uae_u32)dstreg) {\n"
2501 " FAIL(1);\n"
2502 " " RETURN "\n"
2503 "} \n");
2504 start_brace();
2505 }
2506 comprintf("\tdont_care_flags();\n");
2507 genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0);
2508 genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0);
2509 start_brace ();
2510
2511 switch(curi->size) {
2512 case sz_long: comprintf("\t ror_l_rr(data,cnt);\n"); break;
2513 case sz_word: comprintf("\t ror_w_rr(data,cnt);\n"); break;
2514 case sz_byte: comprintf("\t ror_b_rr(data,cnt);\n"); break;
2515 }
2516
2517 if (!noflags) {
2518 comprintf("\tstart_needflags();\n");
2519 /*
2520 * x86 ROR instruction does not set ZF/SF, so we need extra checks here
2521 */
2522 comprintf("\tif (needed_flags & FLAG_ZNV)\n");
2523 switch(curi->size) {
2524 case sz_byte: comprintf("\t test_b_rr(data,data);\n"); break;
2525 case sz_word: comprintf("\t test_w_rr(data,data);\n"); break;
2526 case sz_long: comprintf("\t test_l_rr(data,data);\n"); break;
2527 }
2528 switch(curi->size) {
2529 case sz_byte: comprintf("\t bt_l_ri(data,0x07);\n"); break;
2530 case sz_word: comprintf("\t bt_l_ri(data,0x0f);\n"); break;
2531 case sz_long: comprintf("\t bt_l_ri(data,0x1f);\n"); break;
2532 }
2533 comprintf("\t live_flags();\n");
2534 comprintf("\t end_needflags();\n");
2535 }
2536 genastore ("data", curi->dmode, "dstreg", curi->size, "data");
2537 break;
2538
2539 case i_ROXL:
2540 failure;
2541 break;
2542
2543 case i_ROXR:
2544 failure;
2545 break;
2546
2547 case i_ASRW:
2548 failure;
2549 break;
2550
2551 case i_ASLW:
2552 failure;
2553 break;
2554
2555 case i_LSRW:
2556 failure;
2557 break;
2558
2559 case i_LSLW:
2560 failure;
2561 break;
2562
2563 case i_ROLW:
2564 failure;
2565 break;
2566
2567 case i_RORW:
2568 failure;
2569 break;
2570
2571 case i_ROXLW:
2572 failure;
2573 break;
2574
2575 case i_ROXRW:
2576 failure;
2577 break;
2578
2579 case i_MOVEC2:
2580 isjump;
2581 failure;
2582 break;
2583
2584 case i_MOVE2C:
2585 isjump;
2586 failure;
2587 break;
2588
2589 case i_CAS:
2590 failure;
2591 break;
2592
2593 case i_CAS2:
2594 failure;
2595 break;
2596
2597 case i_MOVES: /* ignore DFC and SFC because we have no MMU */
2598 isjump;
2599 failure;
2600 break;
2601
2602 case i_BKPT: /* only needed for hardware emulators */
2603 isjump;
2604 failure;
2605 break;
2606
2607 case i_CALLM: /* not present in 68030 */
2608 isjump;
2609 failure;
2610 break;
2611
2612 case i_RTM: /* not present in 68030 */
2613 isjump;
2614 failure;
2615 break;
2616
2617 case i_TRAPcc:
2618 isjump;
2619 failure;
2620 break;
2621
2622 case i_DIVL:
2623 isjump;
2624 failure;
2625 break;
2626
2627 case i_MULL:
2628 #ifdef DISABLE_I_MULL
2629 failure;
2630 #endif
2631 if (!noflags) {
2632 failure;
2633 break;
2634 }
2635 comprintf("\tuae_u16 extra=%s;\n",gen_nextiword());
2636 comprintf("\tint r2=(extra>>12)&7;\n"
2637 "\tint tmp=scratchie++;\n");
2638
2639 genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0);
2640 /* The two operands are in dst and r2 */
2641 comprintf("\tif (extra&0x0400) {\n" /* Need full 64 bit result */
2642 "\tint r3=(extra&7);\n"
2643 "\tmov_l_rr(r3,dst);\n"); /* operands now in r3 and r2 */
2644 comprintf("\tif (extra&0x0800) { \n" /* signed */
2645 "\t\timul_64_32(r2,r3);\n"
2646 "\t} else { \n"
2647 "\t\tmul_64_32(r2,r3);\n"
2648 "\t} \n");
2649 /* The result is in r2/tmp, with r2 holding the lower 32 bits */
2650 comprintf("\t} else {\n"); /* Only want 32 bit result */
2651 /* operands in dst and r2, result foes into r2 */
2652 /* shouldn't matter whether it's signed or unsigned?!? */
2653 comprintf("\timul_32_32(r2,dst);\n"
2654 "\t}\n");
2655 break;
2656
2657 case i_BFTST:
2658 case i_BFEXTU:
2659 case i_BFCHG:
2660 case i_BFEXTS:
2661 case i_BFCLR:
2662 case i_BFFFO:
2663 case i_BFSET:
2664 case i_BFINS:
2665 failure;
2666 break;
2667
2668 case i_PACK:
2669 failure;
2670 break;
2671
2672 case i_UNPK:
2673 failure;
2674 break;
2675
2676 case i_TAS:
2677 failure;
2678 break;
2679
2680 case i_FPP:
2681 #ifdef DISABLE_I_FPP
2682 failure;
2683 #endif
2684 uses_fpu;
2685 mayfail;
2686 comprintf("#ifdef USE_JIT_FPU\n");
2687 comprintf("\tuae_u16 extra=%s;\n",gen_nextiword());
2688 swap_opcode();
2689 comprintf("\tcomp_fpp_opp(opcode,extra);\n");
2690 comprintf("#else\n");
2691 comprintf("\tfailure = 1;\n");
2692 comprintf("#endif\n");
2693 break;
2694
2695 case i_FBcc:
2696 #ifdef DISABLE_I_FBCC
2697 failure;
2698 #endif
2699 uses_fpu;
2700 isjump;
2701 uses_cmov;
2702 mayfail;
2703 comprintf("#ifdef USE_JIT_FPU\n");
2704 swap_opcode();
2705 comprintf("\tcomp_fbcc_opp(opcode);\n");
2706 comprintf("#else\n");
2707 comprintf("\tfailure = 1;\n");
2708 comprintf("#endif\n");
2709 break;
2710
2711 case i_FDBcc:
2712 uses_fpu;
2713 isjump;
2714 failure;
2715 break;
2716
2717 case i_FScc:
2718 #ifdef DISABLE_I_FSCC
2719 failure;
2720 #endif
2721 uses_fpu;
2722 mayfail;
2723 uses_cmov;
2724 comprintf("#ifdef USE_JIT_FPU\n");
2725 comprintf("\tuae_u16 extra=%s;\n",gen_nextiword());
2726 swap_opcode();
2727 comprintf("\tcomp_fscc_opp(opcode,extra);\n");
2728 comprintf("#else\n");
2729 comprintf("\tfailure = 1;\n");
2730 comprintf("#endif\n");
2731 break;
2732
2733 case i_FTRAPcc:
2734 uses_fpu;
2735 isjump;
2736 failure;
2737 break;
2738
2739 case i_FSAVE:
2740 uses_fpu;
2741 failure;
2742 break;
2743
2744 case i_FRESTORE:
2745 uses_fpu;
2746 failure;
2747 break;
2748
2749 case i_CINVL:
2750 case i_CINVP:
2751 case i_CINVA:
2752 isjump; /* Not really, but it's probably a good idea to stop
2753 translating at this point */
2754 failure;
2755 comprintf ("\tflush_icache();\n"); /* Differentiate a bit more? */
2756 break;
2757
2758 case i_CPUSHL:
2759 case i_CPUSHP:
2760 case i_CPUSHA:
2761 isjump; /* Not really, but it's probably a good idea to stop
2762 translating at this point */
2763 failure;
2764 break;
2765
2766 case i_MOVE16:
2767 #ifdef DISABLE_I_MOVE16
2768 failure;
2769 #endif
2770 genmov16(opcode,curi);
2771 break;
2772
2773 #ifdef UAE
2774 case i_MMUOP030:
2775 case i_PFLUSHN:
2776 case i_PFLUSH:
2777 case i_PFLUSHAN:
2778 case i_PFLUSHA:
2779 case i_PLPAR:
2780 case i_PLPAW:
2781 case i_PTESTR:
2782 case i_PTESTW:
2783 case i_LPSTOP:
2784 isjump;
2785 failure;
2786 break;
2787 #endif
2788
2789 #ifdef WINUAE_ARANYM
2790 case i_EMULOP_RETURN:
2791 isjump;
2792 failure;
2793 break;
2794
2795 case i_EMULOP:
2796 failure;
2797 break;
2798
2799 case i_NATFEAT_ID:
2800 case i_NATFEAT_CALL:
2801 failure;
2802 break;
2803
2804 case i_MMUOP:
2805 isjump;
2806 failure;
2807 break;
2808 #endif
2809
2810 default:
2811 assert(0);
2812 break;
2813 }
2814 comprintf("%s",endstr);
2815 finish_braces ();
2816 sync_m68k_pc ();
2817 if (global_mayfail)
2818 comprintf("\tif (failure) m68k_pc_offset=m68k_pc_offset_thisinst;\n");
2819 return global_failure;
2820 }
2821
2822 static void
generate_includes(FILE * f)2823 generate_includes (FILE * f)
2824 {
2825 fprintf (f, "#include \"sysconfig.h\"\n");
2826 fprintf (f, "#if defined(JIT)\n");
2827 fprintf (f, "#include \"sysdeps.h\"\n");
2828 #ifdef UAE
2829 fprintf (f, "#include \"options.h\"\n");
2830 fprintf (f, "#include \"uae/memory.h\"\n");
2831 #else
2832 fprintf (f, "#include \"m68k.h\"\n");
2833 fprintf (f, "#include \"memory-uae.h\"\n");
2834 #endif
2835 fprintf (f, "#include \"readcpu.h\"\n");
2836 fprintf (f, "#include \"newcpu.h\"\n");
2837 fprintf (f, "#include \"comptbl.h\"\n");
2838 fprintf (f, "#include \"debug.h\"\n");
2839 }
2840
2841 static int postfix;
2842
2843
decodeEA(amodes mode,wordsizes size)2844 static char *decodeEA (amodes mode, wordsizes size)
2845 {
2846 static char buffer[80];
2847
2848 buffer[0] = 0;
2849 switch (mode){
2850 case Dreg:
2851 strcpy (buffer,"Dn");
2852 break;
2853 case Areg:
2854 strcpy (buffer,"An");
2855 break;
2856 case Aind:
2857 strcpy (buffer,"(An)");
2858 break;
2859 case Aipi:
2860 strcpy (buffer,"(An)+");
2861 break;
2862 case Apdi:
2863 strcpy (buffer,"-(An)");
2864 break;
2865 case Ad16:
2866 strcpy (buffer,"(d16,An)");
2867 break;
2868 case Ad8r:
2869 strcpy (buffer,"(d8,An,Xn)");
2870 break;
2871 case PC16:
2872 strcpy (buffer,"(d16,PC)");
2873 break;
2874 case PC8r:
2875 strcpy (buffer,"(d8,PC,Xn)");
2876 break;
2877 case absw:
2878 strcpy (buffer,"(xxx).W");
2879 break;
2880 case absl:
2881 strcpy (buffer,"(xxx).L");
2882 break;
2883 case imm:
2884 switch (size){
2885 case sz_byte:
2886 strcpy (buffer,"#<data>.B");
2887 break;
2888 case sz_word:
2889 strcpy (buffer,"#<data>.W");
2890 break;
2891 case sz_long:
2892 strcpy (buffer,"#<data>.L");
2893 break;
2894 default:
2895 break;
2896 }
2897 break;
2898 case imm0:
2899 strcpy (buffer,"#<data>.B");
2900 break;
2901 case imm1:
2902 strcpy (buffer,"#<data>.W");
2903 break;
2904 case imm2:
2905 strcpy (buffer,"#<data>.L");
2906 break;
2907 case immi:
2908 strcpy (buffer,"#<data>");
2909 break;
2910
2911 default:
2912 break;
2913 }
2914 return buffer;
2915 }
2916
outopcode(const char * name,int opcode)2917 static char *outopcode (const char *name, int opcode)
2918 {
2919 static char out[100];
2920 struct instr *ins;
2921
2922 ins = &table68k[opcode];
2923 strcpy (out, name);
2924 if (ins->smode == immi)
2925 strcat (out, "Q");
2926 if (ins->size == sz_byte)
2927 strcat (out,".B");
2928 if (ins->size == sz_word)
2929 strcat (out,".W");
2930 if (ins->size == sz_long)
2931 strcat (out,".L");
2932 strcat (out," ");
2933 if (ins->suse)
2934 strcat (out, decodeEA (ins->smode, ins->size));
2935 if (ins->duse) {
2936 if (ins->suse) strcat (out,",");
2937 strcat (out, decodeEA (ins->dmode, ins->size));
2938 }
2939 return out;
2940 }
2941
2942
2943 static void
generate_one_opcode(int rp,int noflags)2944 generate_one_opcode (int rp, int noflags)
2945 {
2946 int i;
2947 uae_u16 smsk, dmsk;
2948 unsigned int opcode = opcode_map[rp];
2949 int aborted=0;
2950 int have_srcreg=0;
2951 int have_dstreg=0;
2952 const char *name;
2953
2954 if (table68k[opcode].mnemo == i_ILLG
2955 || table68k[opcode].clev > cpu_level)
2956 return;
2957
2958 for (i = 0; lookuptab[i].name[0]; i++)
2959 {
2960 if (table68k[opcode].mnemo == lookuptab[i].mnemo)
2961 break;
2962 }
2963
2964 if (table68k[opcode].handler != -1)
2965 return;
2966
2967 switch (table68k[opcode].stype)
2968 {
2969 case 0:
2970 smsk = 7;
2971 break;
2972 case 1:
2973 smsk = 255;
2974 break;
2975 case 2:
2976 smsk = 15;
2977 break;
2978 case 3:
2979 smsk = 7;
2980 break;
2981 case 4:
2982 smsk = 7;
2983 break;
2984 case 5:
2985 smsk = 63;
2986 break;
2987 #ifndef UAE
2988 case 6:
2989 smsk = 255;
2990 break;
2991 #endif
2992 case 7:
2993 smsk = 3;
2994 break;
2995 default:
2996 smsk = 0;
2997 assert(0);
2998 }
2999 dmsk = 7;
3000
3001 next_cpu_level = -1;
3002 if (table68k[opcode].suse
3003 && table68k[opcode].smode != imm && table68k[opcode].smode != imm0
3004 && table68k[opcode].smode != imm1 && table68k[opcode].smode != imm2
3005 && table68k[opcode].smode != absw && table68k[opcode].smode != absl
3006 && table68k[opcode].smode != PC8r && table68k[opcode].smode != PC16)
3007 {
3008 have_srcreg=1;
3009 if (table68k[opcode].spos == -1)
3010 {
3011 if (((int) table68k[opcode].sreg) >= 128)
3012 comprintf ("\tuae_s32 srcreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].sreg);
3013 else
3014 comprintf ("\tuae_s32 srcreg = %d;\n", (int) table68k[opcode].sreg);
3015 }
3016 else
3017 {
3018 char source[100];
3019 int pos = table68k[opcode].spos;
3020
3021 #ifndef UAE
3022 comprintf ("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n");
3023
3024 if (pos < 8 && (smsk >> (8 - pos)) != 0)
3025 sprintf (source, "(((opcode >> %d) | (opcode << %d)) & %d)",
3026 pos ^ 8, 8 - pos, dmsk);
3027 else if (pos != 8)
3028 sprintf (source, "((opcode >> %d) & %d)", pos ^ 8, smsk);
3029 else
3030 sprintf (source, "(opcode & %d)", smsk);
3031
3032 if (table68k[opcode].stype == 3)
3033 comprintf ("\tuae_u32 srcreg = imm8_table[%s];\n", source);
3034 else if (table68k[opcode].stype == 1)
3035 comprintf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source);
3036 else
3037 comprintf ("\tuae_u32 srcreg = %s;\n", source);
3038
3039 comprintf ("#else\n");
3040 #endif
3041
3042 if (pos)
3043 sprintf (source, "((opcode >> %d) & %d)", pos, smsk);
3044 else
3045 sprintf (source, "(opcode & %d)", smsk);
3046
3047 if (table68k[opcode].stype == 3)
3048 comprintf ("\tuae_s32 srcreg = imm8_table[%s];\n", source);
3049 else if (table68k[opcode].stype == 1)
3050 comprintf ("\tuae_s32 srcreg = (uae_s32)(uae_s8)%s;\n", source);
3051 else
3052 comprintf ("\tuae_s32 srcreg = %s;\n", source);
3053
3054 #ifndef UAE
3055 comprintf ("#endif\n");
3056 #endif
3057 }
3058 }
3059 if (table68k[opcode].duse
3060 /* Yes, the dmode can be imm, in case of LINK or DBcc */
3061 && table68k[opcode].dmode != imm && table68k[opcode].dmode != imm0
3062 && table68k[opcode].dmode != imm1 && table68k[opcode].dmode != imm2
3063 && table68k[opcode].dmode != absw && table68k[opcode].dmode != absl)
3064 {
3065 have_dstreg=1;
3066 if (table68k[opcode].dpos == -1)
3067 {
3068 if (((int) table68k[opcode].dreg) >= 128)
3069 comprintf ("\tuae_s32 dstreg = (uae_s32)(uae_s8)%d;\n", (int) table68k[opcode].dreg);
3070 else
3071 comprintf ("\tuae_s32 dstreg = %d;\n", (int) table68k[opcode].dreg);
3072 }
3073 else
3074 {
3075 int pos = table68k[opcode].dpos;
3076
3077 #ifndef UAE
3078 comprintf ("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n");
3079
3080 if (pos < 8 && (dmsk >> (8 - pos)) != 0)
3081 comprintf ("\tuae_u32 dstreg = ((opcode >> %d) | (opcode << %d)) & %d;\n",
3082 pos ^ 8, 8 - pos, dmsk);
3083 else if (pos != 8)
3084 comprintf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
3085 pos ^ 8, dmsk);
3086 else
3087 comprintf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
3088
3089 comprintf ("#else\n");
3090 #endif
3091
3092 if (pos)
3093 comprintf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n",
3094 pos, dmsk);
3095 else
3096 comprintf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk);
3097
3098 #ifndef UAE
3099 comprintf ("#endif\n");
3100 #endif
3101 }
3102 }
3103
3104 if (have_srcreg && have_dstreg &&
3105 (table68k[opcode].dmode==Areg ||
3106 table68k[opcode].dmode==Aind ||
3107 table68k[opcode].dmode==Aipi ||
3108 table68k[opcode].dmode==Apdi ||
3109 table68k[opcode].dmode==Ad16 ||
3110 table68k[opcode].dmode==Ad8r) &&
3111 (table68k[opcode].smode==Areg ||
3112 table68k[opcode].smode==Aind ||
3113 table68k[opcode].smode==Aipi ||
3114 table68k[opcode].smode==Apdi ||
3115 table68k[opcode].smode==Ad16 ||
3116 table68k[opcode].smode==Ad8r)
3117 ) {
3118 comprintf("\tuae_u32 dodgy=(srcreg==(uae_s32)dstreg);\n");
3119 }
3120 else {
3121 comprintf("\tuae_u32 dodgy=0;\n");
3122 }
3123 comprintf("\tuae_u32 m68k_pc_offset_thisinst=m68k_pc_offset;\n");
3124 comprintf("\tm68k_pc_offset+=2;\n");
3125
3126 aborted=gen_opcode (opcode);
3127 {
3128 char flags[64 * 6];
3129 *flags = '\0';
3130 if (global_isjump) strcat(flags, "COMP_OPCODE_ISJUMP|");
3131 if (long_opcode) strcat(flags, "COMP_OPCODE_LONG_OPCODE|");
3132 if (global_cmov) strcat(flags, "COMP_OPCODE_CMOV|");
3133 if (global_isaddx) strcat(flags, "COMP_OPCODE_ISADDX|");
3134 if (global_iscjump) strcat(flags, "COMP_OPCODE_ISCJUMP|");
3135 if (global_fpu) strcat(flags, "COMP_OPCODE_USES_FPU|");
3136 if (*flags)
3137 flags[strlen(flags) - 1] = '\0';
3138 else
3139 strcpy(flags, "0");
3140
3141 #ifdef UAE /* RETTYPE != void */
3142 comprintf ("return 0;\n");
3143 #endif
3144 comprintf ("}\n");
3145
3146 name = lookuptab[i].name;
3147 if (aborted) {
3148 fprintf (stblfile, "{ NULL, %u, %s }, /* %s */\n", opcode, flags, name);
3149 com_discard();
3150 } else {
3151 const char *tbl = noflags ? "nf" : "ff";
3152 fprintf (stblfile, "{ op_%x_%d_comp_%s, %u, %s }, /* %s */\n", opcode, postfix, tbl, opcode, flags, name);
3153 fprintf (headerfile, "extern compop_func op_%x_%d_comp_%s;\n", opcode, postfix, tbl);
3154 printf ("/* %s */\n", outopcode (name, opcode));
3155 printf (RETTYPE " REGPARAM2 op_%x_%d_comp_%s(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, tbl, name);
3156 com_flush();
3157 }
3158 }
3159 opcode_next_clev[rp] = next_cpu_level;
3160 opcode_last_postfix[rp] = postfix;
3161 }
3162
3163 static void
generate_func(int noflags)3164 generate_func (int noflags)
3165 {
3166 int i, j, rp;
3167 const char *tbl = noflags ? "nf" : "ff";
3168
3169 using_prefetch = 0;
3170 using_exception_3 = 0;
3171 for (i = 0; i < 1; i++) /* We only do one level! */
3172 {
3173 cpu_level = NEXT_CPU_LEVEL - i;
3174 postfix = i;
3175
3176 fprintf (stblfile, "const struct comptbl op_smalltbl_%d_comp_%s[] = {\n", postfix, tbl);
3177
3178 /* sam: this is for people with low memory (eg. me :)) */
3179 printf ("\n"
3180 "#if !defined(PART_1) && !defined(PART_2) && "
3181 "!defined(PART_3) && !defined(PART_4) && "
3182 "!defined(PART_5) && !defined(PART_6) && "
3183 "!defined(PART_7) && !defined(PART_8)"
3184 "\n"
3185 "#define PART_1 1\n"
3186 "#define PART_2 1\n"
3187 "#define PART_3 1\n"
3188 "#define PART_4 1\n"
3189 "#define PART_5 1\n"
3190 "#define PART_6 1\n"
3191 "#define PART_7 1\n"
3192 "#define PART_8 1\n"
3193 "#endif\n\n");
3194 #ifdef UAE
3195 printf ("extern void comp_fpp_opp();\n"
3196 "extern void comp_fscc_opp();\n"
3197 "extern void comp_fbcc_opp();\n\n");
3198 #endif
3199
3200 rp = 0;
3201 for (j = 1; j <= 8; ++j)
3202 {
3203 int k = (j * nr_cpuop_funcs) / 8;
3204 printf ("#ifdef PART_%d\n", j);
3205 for (; rp < k; rp++)
3206 generate_one_opcode (rp,noflags);
3207 printf ("#endif\n\n");
3208 }
3209
3210 fprintf (stblfile, "{ 0, 65536, 0 }};\n");
3211 }
3212
3213 }
3214
3215 #if (defined(OS_cygwin) || defined(OS_mingw)) && defined(EXTENDED_SIGSEGV)
cygwin_mingw_abort()3216 void cygwin_mingw_abort()
3217 {
3218 #undef abort
3219 abort();
3220 }
3221 #endif
3222
3223 #if defined(FSUAE) && defined (WINDOWS)
3224 #include "windows.h"
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)3225 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
3226 #else
3227 int main(void)
3228 #endif
3229 {
3230 init_table68k ();
3231
3232 opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
3233 opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
3234 opcode_next_clev = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
3235 counts = (unsigned long *) malloc (65536 * sizeof (unsigned long));
3236 read_counts ();
3237
3238 /* It would be a lot nicer to put all in one file (we'd also get rid of
3239 * cputbl.h that way), but cpuopti can't cope. That could be fixed, but
3240 * I don't dare to touch the 68k version. */
3241
3242 headerfile = fopen (GEN_PATH "comptbl.h", "wb");
3243 fprintf (headerfile, ""
3244 "extern const struct comptbl op_smalltbl_0_comp_nf[];\n"
3245 "extern const struct comptbl op_smalltbl_0_comp_ff[];\n"
3246 "");
3247
3248 stblfile = fopen (GEN_PATH "compstbl.cpp", "wb");
3249 if (freopen (GEN_PATH "compemu.cpp", "wb", stdout) == NULL) {
3250 abort();
3251 }
3252
3253 generate_includes (stdout);
3254 generate_includes (stblfile);
3255
3256 printf("#include \"" JIT_PATH "compemu.h\"\n");
3257 printf("#include \"" JIT_PATH "flags_x86.h\"\n");
3258
3259 noflags=0;
3260 generate_func (noflags);
3261
3262 free(opcode_map);
3263 free(opcode_last_postfix);
3264 free(opcode_next_clev);
3265 free(counts);
3266
3267 opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
3268 opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
3269 opcode_next_clev = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
3270 counts = (unsigned long *) malloc (65536 * sizeof (unsigned long));
3271 read_counts ();
3272 noflags=1;
3273 generate_func (noflags);
3274
3275 printf ("#endif\n");
3276 fprintf (stblfile, "#endif\n");
3277
3278 free(opcode_map);
3279 free(opcode_last_postfix);
3280 free(opcode_next_clev);
3281 free(counts);
3282
3283 free (table68k);
3284 fclose (stblfile);
3285 fclose (headerfile);
3286 return 0;
3287 }
3288
3289 #ifdef UAE
write_log(const TCHAR * format,...)3290 void write_log (const TCHAR *format,...)
3291 {
3292 }
3293 #endif
3294