ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/gencomp.c
Revision: 1.4
Committed: 2003-03-13T15:57:01Z (21 years, 8 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
Changes since 1.3: +15 -9 lines
Log Message:
Workaround change in flags handling for BSF instruction on Pentium 4.
i.e. currently disable translation of ADDX/SUBX/B<CHG,CLR,SET,TST> instructions
in that case. That is to say, better (much?) slower than inaccurate. :-(

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