ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/gencomp.c
Revision: 1.12
Committed: 2007-06-29T16:53:04Z (16 years, 10 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.11: +101 -95 lines
Log Message:
Fix LSL & LSR instructions so that they preserve the X flags when the
shift count is 0. Likewise for ASR + another improvement to avoid shifting
by halves (propagated bit is reset to original's when necessary).

File Contents

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