Initial commit for 68020/30/40/60/68881/68882/68851 support.
[rmac] / mach.c
1 //
2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // MACH.C - Code Generation
4 // Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
7 //
8
9 #include "mach.h"
10 #include "eagen.h"
11 #include "error.h"
12 #include "direct.h"
13 #include "procln.h"
14 #include "riscasm.h"
15 #include "rmac.h"
16 #include "sect.h"
17 #include "token.h"
18
19 #define DEF_KW
20 #include "kwtab.h"
21
22 // Exported variables
23 int movep = 0; // Global flag to indicate we're generating a movep instruction
24
25 // Common error messages
26 char range_error[] = "expression out of range";
27 char abs_error[] = "illegal absolute expression";
28 char seg_error[] = "bad (section) expression";
29 char rel_error[] = "illegal relative address";
30 char siz_error[] = "bad size specified";
31 char undef_error[] = "undefined expression";
32 char fwd_error[] = "forward or undefined expression";
33 char unsupport[] = "unsupported for selected CPU";
34
35 extern int ea0gen(WORD);
36 extern int ea1gen(WORD);
37 extern int mulmode;
38
39 // Include code tables
40 MNTAB machtab[] = {
41 //   { (WORD)-1, (unsigned long)-1L, (unsigned long)-1L, 0x0000, 0, m_badmode }, // 0
42    { 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000, 0, m_badmode }, // 0
43    #include "68ktab.h"
44    {  0,  0L,  0L, 0x0000, 0, m_unimp   }            // Last entry
45 };
46
47 // Register number << 9
48 WORD reg_9[8] = {
49         0, 1 << 9, 2 << 9, 3 << 9, 4 << 9, 5 << 9, 6 << 9, 7 << 9
50 };
51
52 // SIZB==>00, SIZW==>01, SIZL==>10, SIZN==>01 << 6
53 WORD siz_6[] = {
54         (WORD)-1,                                        // n/a
55         0,                                               // SIZB
56         1<<6, (WORD)-1,                                  // SIZW, n/a
57         2<<6, (WORD)-1, (WORD)-1, (WORD)-1,              // SIZL, n/a, n/a, n/a
58         1<<6                                             // SIZN
59 };
60
61 // Byte/word/long size for MOVE instrs
62 WORD siz_12[] = {
63    (WORD)-1,
64    0x1000,                                           // Byte
65    0x3000, (WORD)-1,                                 // Word
66    0x2000, (WORD)-1, (WORD)-1, (WORD)-1,             // Long
67    0x3000                                            // Word (SIZN)
68 };
69
70 // Word/long size (0=.w, 1=.l) in bit 8
71 WORD lwsiz_8[] = {
72    (WORD)-1,                                         // n/a
73    (WORD)-1,                                         // SIZB
74    0, (WORD)-1,                                      // SIZW, n/a
75    1<<8, (WORD)-1, (WORD)-1, (WORD)-1,               // SIZL, n/a, n/a, n/a
76    0                                                 // SIZN
77 };
78
79 // Byte/Word/long size (0=.w, 1=.l) in bit 9
80 WORD lwsiz_9[] = {
81         (WORD)-1,
82         0,                                                      // Byte 
83         1<<9, (WORD)-1,                                         // Word 
84         1<<10, (WORD)-1, (WORD)-1, (WORD)-1,                    // Long
85         1<<9                                                    // Word (SIZN)
86 };
87
88 // Addressing mode in bits 6..11 (register/mode fields are reversed)
89 WORD am_6[] = {
90    00000, 01000, 02000, 03000, 04000, 05000, 06000, 07000,
91    00100, 01100, 02100, 03100, 04100, 05100, 06100, 07100,
92    00200, 01200, 02200, 03200, 04200, 05200, 06200, 07200,
93    00300, 01300, 02300, 03300, 04300, 05300, 06300, 07300,
94    00400, 01400, 02400, 03400, 04400, 05400, 06400, 07400,
95    00500, 01500, 02500, 03500, 04500, 05500, 06500, 07500,
96    00600, 01600, 02600, 03600, 04600, 05600, 06600, 07600,
97    00700, 01700, 02700, 03700, 04700, 05700, 06700, 07700
98 };
99
100 // Control registers lookup table
101 WORD CREGlut[21] = {
102         // MC68010/MC68020/MC68030/MC68040/CPU32
103         0x000,          // Source Function Code(SFC)
104         0x001,          // Destination Function Code(DFC)
105         0x800,          // User Stack Pointer(USP)
106         0x801,          // Vector Base Register(VBR)
107         // MC68020 / MC68030 / MC68040
108         0x002,          // Cache Control Register(CACR)
109         0x802,          // Cache Address Register(CAAR) (020/030 only)
110         0x803,          // Master Stack Pointer(MSP)
111         0x804,          // Interrupt Stack Pointer(ISP)
112         // MC68040 / MC68LC040
113         0x003,          // MMU Translation Control Register(TC)
114         0x004,          // Instruction Transparent Translation Register 0 (ITT0)
115         0x005,          // Instruction Transparent Translation Register 1 (ITT1)
116         0x006,          // Data Transparent Translation Register 0 (DTT0)
117         0x007,          // Data Transparent Translation Register 1 (DTT1)
118         0x805,          // MMU Status Register(MMUSR)
119         0x806,          // User Root Pointer(URP)
120         0x807,          // Supervisor Root Pointer(SRP)
121         // MC68EC040 only
122         0x004,          // Instruction Access Control Register 0 (IACR0)
123         0x005,          // Instruction Access Control Register 1 (IACR1)
124         0x006,          // Data Access Control Register 0 (DACR1)
125         0x007,          // Data Access Control Register 1 (DACR1)
126         // 68851 only
127         0xfff           // CPU Root Pointer (CRP) - There's no movec with CRP in it, this is just a guard entry
128 };
129
130 // Error messages
131 int m_unimp(WORD unused1, WORD unused2)
132 {
133         return (int)error("unimplemented mnemonic");
134 }
135
136
137 //int m_badmode(void)
138 int m_badmode(WORD unused1, WORD unused2)
139 {
140         return (int)error("inappropriate addressing mode");
141 }
142
143
144 int m_self(WORD inst, WORD usused)
145 {
146         D_word(inst);
147         return OK;
148 }
149
150
151 //
152 // Do one EA in bits 0..5
153 //
154 // Bits in `inst' have the following meaning:
155 //
156 // Bit zero specifies which ea (ea0 or ea1) to generate in the lower six bits
157 // of the instr.
158 //
159 // If bit one is set, the OTHER ea (the one that wasn't generated by bit zero)
160 // is generated after the instruction. Regardless of bit 0's value, ea0 is
161 // always deposited in memory before ea1.
162 //
163 // If bit two is set, standard size bits are set in the instr in bits 6 and 7.
164 //
165 // If bit four is set, bit three specifies which eaXreg to place in bits 9..11
166 // of the instr.
167 //
168 int m_ea(WORD inst, WORD siz)
169 {
170         WORD flg = inst;                                        // Save flag bits
171         inst &= ~0x3F;                                          // Clobber flag bits in instr
172
173         // Install "standard" instr size bits
174         if (flg & 4)
175                 inst |= siz_6[siz];
176
177         if (flg & 16)
178         {
179                 // OR-in register number
180                 if (flg & 8)
181                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11
182                 else
183                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11
184         }
185
186         if (flg & 1)
187         {
188                 // Use am1
189                 inst |= am1 | a1reg;                    // Get ea1 into instr
190                 D_word(inst);                                   // Deposit instr
191
192                 // Generate ea0 if requested
193                 if (flg & 2)
194                         ea0gen(siz);
195
196                 ea1gen(siz);                                    // Generate ea1
197         }
198         else
199         {
200                 // Use am0
201                 inst |= am0 | a0reg;                    // Get ea0 into instr
202                 D_word(inst);                                   // Deposit instr
203                 ea0gen(siz);                                    // Generate ea0
204
205                 // Generate ea1 if requested
206                 if (flg & 2)
207                         ea1gen(siz);
208         }
209
210         return OK;
211 }
212
213 //
214 // Check if lea x(an),an can be optimised to
215 // addq.w #x,an - otherwise fall back to m_ea.
216 //
217 int m_lea(WORD inst, WORD siz)
218 {
219     if (optim_flags[OPT_LEA_ADDQ])
220         if (am0==ADISP && a0reg==a1reg && (a0exattr & DEFINED))
221             if (a0exval>0 && a0exval<=8)
222             {
223                 inst=B16(01010000,01001000)|((a0exval&7)<<9)|(a0reg);
224                 D_word(inst);
225                 warn("lea size(An),An converted to addq #size,An");
226                 return OK;
227             }
228
229     return m_ea(inst,siz);
230 }
231
232 int m_ea030(WORD inst, WORD siz)
233 {
234     CHECK00;
235
236         WORD flg = inst;                                        // Save flag bits 
237         inst &= ~0x3F;                                          // Clobber flag bits in instr 
238
239         // Install "standard" instr size bits 
240         if (flg & 4)
241                 inst |= siz_6[siz];
242
243         if (flg & 16)
244         {
245                 // OR-in register number 
246                 if (flg & 8)
247                 {
248                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11 
249                 }
250                 else
251                 {
252                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11 
253                 }
254         }
255
256         if (flg & 1)
257         {
258                 // Use am1 
259                 inst |= am1 | a1reg;                    // Get ea1 into instr 
260                 D_word(inst);                                   // Deposit instr 
261
262                 // Generate ea0 if requested 
263                 if (flg & 2)
264                         ea0gen(siz);
265
266                 ea1gen(siz);                                    // Generate ea1 
267         }
268         else
269         {
270                 // Use am0 
271                 //inst |= am0 | a0reg;                  // Get ea0 into instr 
272         if (am0 == AREG)
273             //We get here if we're doing 020+ addressing and an address register is used.
274             //For example, something like "tst a0". A bit of a corner case, so kludge it
275             a0reg = a0reg + 8;
276         else if (am0 == PCDISP)
277             //Another corner case (possibly!), so kludge ahoy
278             inst |= am0;                        // Get ea0 into instr 
279         else if (am0 == IMMED)
280             inst |= am0 | a0reg;                        // Get ea0 into instr 
281         else if (am0 == AM_CCR)
282             inst |= am1 | a1reg;
283         else if (am0 == AIND)
284             inst |= am0;
285
286                 inst |= a0reg;                  // Get ea0 into instr 
287                 D_word(inst);                                   // Deposit instr 
288                 ea0gen(siz);                                    // Generate ea0 
289
290                 // Generate ea1 if requested 
291                 if (flg & 2)
292                         ea1gen(siz);
293         }
294
295         return OK;
296 }
297
298
299 //
300 // Dx,Dy nnnnXXXnssnnnYYY If bit 0 of `inst' is set, install size bits in bits
301 // 6..7
302 //
303 int m_abcd(WORD inst, WORD siz)
304 {
305         if (inst & 1)
306         {
307                 // Install size bits
308                 inst--;
309                 inst |= siz_6[siz];
310         }
311
312         inst |= a0reg | reg_9[a1reg];
313         D_word(inst);
314
315         return OK;
316 }
317
318
319 //
320 // {adda} ea,AREG
321 //
322 int m_adda(WORD inst, WORD siz)
323 {
324         inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg];
325         D_word(inst);
326         ea0gen(siz);    // Generate EA
327
328         return OK;
329 }
330
331
332 //
333 // If bit 0 of `inst' is 1, install size bits in bits 6..7 of instr.
334 // If bit 1 of `inst' is 1, install a1reg in bits 9..11 of instr.
335 //
336 int m_reg(WORD inst, WORD siz)
337 {
338         if (inst & 1)
339                 // Install size bits
340                 inst |= siz_6[siz];
341
342         if (inst & 2)
343                 // Install other register (9..11)
344                 inst |= reg_9[a1reg];
345
346         inst &= ~7;                     // Clear off crufty bits
347         inst |= a0reg;          // Install first register
348         D_word(inst);
349
350         return OK;
351 }
352
353
354 //
355 // <op> #expr
356 //
357 int m_imm(WORD inst, WORD siz)
358 {
359         D_word(inst);
360         ea0gen(siz);
361
362         return OK;
363 }
364
365
366 //
367 // <op>.b #expr
368 //
369 int m_imm8(WORD inst, WORD siz)
370 {
371         siz = siz;
372         D_word(inst);
373         ea0gen(SIZB);
374
375         return OK;
376 }
377
378
379 //
380 // <shift> Dn,Dn
381 //
382 int m_shr(WORD inst, WORD siz)
383 {
384         inst |= reg_9[a0reg] | a1reg | siz_6[siz];
385         D_word(inst);
386
387         return OK;
388 }
389
390
391 //
392 // <shift> #n,Dn
393 //
394 int m_shi(WORD inst, WORD siz)
395 {
396         inst |= a1reg | siz_6[siz];
397
398         if (a0exattr & DEFINED)
399         {
400                 if (a0exval > 8)
401                         return error(range_error);
402
403                 inst |= (a0exval & 7) << 9;
404                 D_word(inst);
405         }
406         else
407         {
408                 AddFixup(FU_QUICK, sloc, a0expr);
409                 D_word(inst);
410         }
411
412         return OK;
413 }
414
415
416 //
417 // {bset, btst, bchg, bclr} -- #immed,ea -- Dn,ea
418 //
419 int m_bitop(WORD inst, WORD siz)
420 {
421         // Enforce instruction sizes
422         if (am1 == DREG)
423         {                               // X,Dn must be .n or .l
424                 if (siz & (SIZB | SIZW))
425                         return error(siz_error);
426         }
427         else if (siz & (SIZW | SIZL))   // X,ea must be .n or .b
428                 return error(siz_error);
429
430         // Construct instr and EAs
431         inst |= am1 | a1reg;
432
433         if (am0 == IMMED)
434         {
435                 D_word(inst);
436                 ea0gen(SIZB);                           // Immediate bit number
437         }
438         else
439         {
440                 inst |= reg_9[a0reg];
441                 D_word(inst);
442         }
443
444         // ea to bit-munch
445         ea1gen(SIZB);
446
447         return OK;
448 }
449
450
451 int m_dbra(WORD inst, WORD siz)
452 {
453         VALUE v;
454
455         siz = siz;
456         inst |= a0reg;
457         D_word(inst);
458
459         if (a1exattr & DEFINED)
460         {
461                 if ((a1exattr & TDB) != cursect)
462                         return error(rel_error);
463
464                 v = a1exval - sloc;
465
466                 if (v + 0x8000 > 0x10000)
467                         return error(range_error);
468
469                 D_word(v);
470         }
471         else
472         {
473                 AddFixup(FU_WORD | FU_PCREL | FU_ISBRA, sloc, a1expr);
474                 D_word(0);
475         }
476
477         return OK;
478 }
479
480
481 //
482 // EXG
483 //
484 int m_exg(WORD inst, WORD siz)
485 {
486         int m;
487
488         siz = siz;
489
490         if (am0 == DREG && am1 == DREG)
491                 m = 0x0040;                                           // Dn,Dn
492         else if (am0 == AREG && am1 == AREG)
493                 m = 0x0048;                                           // An,An
494         else
495         {
496                 if (am0 == AREG)
497                 {                                     // Dn,An or An,Dn
498                         m = a1reg;                                         // Get AREG into a1reg
499                         a1reg = a0reg;
500                         a0reg = m;
501                 }
502
503                 m = 0x0088;
504         }
505
506         inst |= m | reg_9[a0reg] | a1reg;
507         D_word(inst);
508
509         return OK;
510 }
511
512
513 //
514 // LINK
515 //
516 int m_link(WORD inst, WORD siz)
517 {
518     if (siz != SIZL)
519     {
520     }
521     else
522     {
523         CHECK00;
524         inst &= ~((3 << 9)|(1<<6)|(1<<4));
525         inst |= 1 << 3;
526     }
527         inst |= a0reg;
528         D_word(inst);
529         ea1gen(siz);
530
531         return OK;
532 }
533
534 WORD extra_addressing[16]=
535 {
536         0,     //0100 (bd,An,Xn)
537         0,     //0101 ([bd,An],Xn,od)
538         0x180, //0102 ([bc,An,Xn],od) (111 110 110 111)
539         0,     //0103 (bd,PC,Xn)
540         0,     //0104 ([bd,PC],Xn,od)
541         0,     //0105 ([bc,PC,Xn],od)
542         0,     //0106
543         0,     //0107
544         0,     //0110
545         0,     //0111 Nothing
546         0x30,  //0112 (Dn.w)
547         0x30,  //0113 (Dn.l)
548         0,     //0114
549         0,     //0115
550         0,     //0116
551         0      //0117
552         
553 };
554
555 //
556 // Handle MOVE <C_ALL> <C_ALTDATA>
557 //        MOVE <C_ALL> <M_AREG>
558 //
559 // Optimize MOVE.L #<smalldata>,D0 to a MOVEQ
560 //
561 int m_move(WORD inst, WORD size)
562 {
563         // Cast the passed in value to an int
564         int siz = (int)size;
565
566         // Try to optimize to MOVEQ
567         if (optim_flags[OPT_MOVEL_MOVEQ] && siz == SIZL && am0 == IMMED && am1 == DREG
568                 && (a0exattr & (TDB|DEFINED)) == DEFINED && a0exval + 0x80 < 0x100)
569         {
570                 m_moveq((WORD)0x7000, (WORD)0);
571
572                 if (sbra_flag)
573                         warn("move.l #size,dx converted to moveq");
574         }
575         else
576         {
577                 if (am0<ABASE && am1<ABASE)                     //68000 modes
578                 {
579                 inst |= siz_12[siz] | am_6[am1] | reg_9[a1reg] | am0 | a0reg;
580
581                 D_word(inst);
582
583                 if (am0 >= ADISP)
584                         ea0gen((WORD)siz);
585
586                 if (am1 >= ADISP)
587                         ea1gen((WORD)siz | 0x8000);   // Tell ea1gen we're move ea,ea
588         }
589                 else                                    //68020+ modes
590                 {
591                         inst |= siz_12[siz] | reg_9[a1reg] | extra_addressing[am0-ABASE];
592
593                         D_word(inst);
594
595                         if (am0 >= ADISP)
596                                 ea0gen((WORD)siz);
597
598                         if (am1 >= ADISP)
599                                 ea1gen((WORD)siz);
600                 }
601         }
602
603         return OK;
604 }
605
606 //
607 // Handle MOVE <C_ALL030> <C_ALTDATA>
608 //        MOVE <C_ALL030> <M_AREG>
609 // 
610 int m_move30(WORD inst, WORD size)
611 {
612         // Cast the passed in value to an int
613         int siz = (int)size;
614
615         /*if (am0<ABASE && am1<ABASE)                   //68000 modes
616         {
617                 inst |= siz_12[siz] | am_6[am1] | reg_9[a1reg] | am0 | a0reg;
618
619                 D_word(inst);
620
621                 if (am0 >= ADISP)
622                         ea0gen((WORD)siz);
623
624                 if (am1 >= ADISP)
625  | 0x8000);   // Tell ea1gen we're move ea,ea
626         }
627         else                                    //68020+ modes
628         {*/
629         inst |= siz_12[siz] | reg_9[a1reg&7] | a0reg | extra_addressing[am0-ABASE];
630
631                 D_word(inst);
632
633                 if (am0 >= ADISP)
634                         ea0gen((WORD)siz);
635
636                 if (am1 >= ADISP)
637                         ea1gen((WORD)siz);                      
638         /*}*/
639
640         return OK;
641 }
642
643
644 //
645 // move USP,An -- move An,USP
646 //
647 int m_usp(WORD inst, WORD siz)
648 {
649         siz = siz;
650
651         if (am0 == AM_USP)
652                 inst |= a1reg;          // USP, An
653         else
654                 inst |= a0reg;          // An, USP
655
656         D_word(inst);
657
658         return OK;
659 }
660
661
662 //
663 // moveq
664 //
665 int m_moveq(WORD inst, WORD siz)
666 {
667         siz = siz;
668
669         // Arrange for future fixup
670         if (!(a0exattr & DEFINED))
671         {
672                 AddFixup(FU_BYTE | FU_SEXT, sloc + 1, a0expr);
673                 a0exval = 0;
674         }
675         else if (a0exval + 0x100 >= 0x200)
676                 return error(range_error);
677
678         inst |= reg_9[a1reg] | (a0exval & 0xFF);
679         D_word(inst);
680
681         return OK;
682 }
683
684 //
685 // movep Dn, disp(An) -- movep disp(An), Dn
686 //
687 int m_movep(WORD inst, WORD siz)
688 {
689     movep = 1;          // Tell ea0gen to lay off the 0(a0) optimisations on this one
690         if (siz == SIZL)
691                 inst |= 0x0040;
692
693         if (am0 == DREG)
694         {
695                 inst |= reg_9[a0reg] | a1reg;
696                 D_word(inst);
697
698                 if (am1 == AIND)
699                         D_word(0)
700                 else
701                         ea1gen(siz);
702         }
703         else
704         {
705                 inst |= reg_9[a1reg] | a0reg;
706                 D_word(inst);
707
708                 if (am0 == AIND)
709                         D_word(0)
710                 else
711                         ea0gen(siz);
712         }
713
714     movep = 0;
715         return 0;
716 }
717
718
719 //
720 // Bcc -- BSR
721 //
722 int m_br(WORD inst, WORD siz)
723 {
724         VALUE v;
725
726         if (a0exattr & DEFINED)
727         {
728                 if ((a0exattr & TDB) != cursect)
729 //{
730 //printf("m_br(): a0exattr = %X, cursect = %X, a0exval = %X, sloc = %X\n", a0exattr, cursect, a0exval, sloc);
731                         return error(rel_error);
732 //}
733
734                 v = a0exval - (sloc + 2);
735
736                 // Optimize branch instr. size
737                 if (siz == SIZN)
738                 {
739                         if (optim_flags[OPT_BSR_BCC_S] && v != 0 && v + 0x80 < 0x100)
740                         {
741                                 // Fits in .B
742                                 inst |= v & 0xFF;
743                                 D_word(inst);
744                                 if (sbra_flag)
745                                         warn("Bcc.w/BSR.w converted to .s");
746                                 return OK;
747                         }
748                         else
749                         {
750                                 // Fits in .W
751                                 if (v + 0x8000 > 0x10000)
752                                         return error(range_error);
753
754                                 D_word(inst);
755                                 D_word(v);
756                                 return OK;
757                         }
758                 }
759
760                 if (siz == SIZB || siz == SIZS)
761                 {
762                         if (v + 0x80 >= 0x100)
763                                 return error(range_error);
764
765                         inst |= v & 0xFF;
766                         D_word(inst);
767                 }
768                 else
769                 {
770                         if (v + 0x8000 >= 0x10000)
771                                 return error(range_error);
772
773                         D_word(inst);
774                         D_word(v);
775                 }
776
777                 return OK;
778         }
779         else if (siz == SIZN)
780                 siz = SIZW;
781
782         if (siz == SIZB || siz == SIZS)
783         {
784                 // .B
785                 AddFixup(FU_BBRA | FU_PCREL | FU_SEXT, sloc, a0expr);
786                 D_word(inst);
787                 return OK;
788         }
789         else
790         {
791                 // .W
792                 D_word(inst);
793                 AddFixup(FU_WORD | FU_PCREL | FU_LBRA | FU_ISBRA, sloc, a0expr);
794                 D_word(0);
795         }
796
797         return OK;
798 }
799
800
801 //
802 // ADDQ -- SUBQ
803 //
804 int m_addq(WORD inst, WORD siz)
805 {
806         inst |= siz_6[siz] | am1 | a1reg;
807
808         if (a0exattr & DEFINED)
809         {
810                 if (a0exval > 8 ||      a0exval == 0)                       // Range in 1..8
811                         return error(range_error);
812
813                 inst |= (a0exval & 7) << 9;
814                 D_word(inst);
815         }
816         else
817         {
818                 AddFixup(FU_QUICK, sloc, a0expr);
819                 D_word(inst);
820         }
821
822         ea1gen(siz);
823
824         return OK;
825 }
826
827
828 //
829 // trap #n
830 //
831 int m_trap(WORD inst, WORD siz)
832 {
833         siz = siz;
834
835         if (a0exattr & DEFINED)
836         {
837                 if (a0exattr & TDB)
838                         return error(abs_error);
839
840                 if (a0exval >= 16)
841                         return error(range_error);
842
843                 inst |= a0exval;
844                 D_word(inst);
845         }
846         else
847                 return error(undef_error);
848
849         return OK;
850 }
851
852
853 //
854 // movem <rlist>,ea -- movem ea,<rlist>
855 //
856 int m_movem(WORD inst, WORD siz)
857 {
858         VALUE eval;
859         WORD i;
860         WORD w;
861         WORD rmask;
862
863         if (siz & SIZB)
864                 return error("bad size suffix");
865
866         if (siz == SIZL)
867                 inst |= 0x0040;
868
869         if (*tok == '#')
870         {
871                 // Handle #<expr>, ea
872                 tok++;
873
874                 if (abs_expr(&eval) != OK)
875                         return OK;
876
877                 if (eval >= 0x10000L)
878                         return error(range_error);
879
880                 rmask = (WORD)eval;
881                 goto immed1;
882         }
883
884         if (*tok >= KW_D0 && *tok <= KW_A7)
885         {
886                 // <rlist>, ea
887                 if (reglist(&rmask) < 0)
888                         return OK;
889
890 immed1:
891                 if (*tok++ != ',')
892                         return error("missing comma");
893
894                 if (amode(0) < 0)
895                         return OK;
896
897                 inst |= am0 | a0reg;
898
899                 if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
900                         return error("invalid addressing mode");
901
902                 // If APREDEC, reverse register mask
903                 if (am0 == APREDEC)
904                 {
905                         w = rmask;
906                         rmask = 0;
907
908                         for(i=0x8000; i; i>>=1, w>>=1)
909                                 rmask = (WORD)((rmask << 1) | w & 1);
910                 }
911         }
912         else
913         {
914                 // ea, <rlist>
915                 if (amode(0) < 0)
916                         return OK;
917
918                 inst |= 0x0400 | am0 | a0reg;
919
920                 if (*tok++ != ',')
921                         return error("missing comma");
922
923                 if (*tok == EOL)
924                         return error("missing register list");
925
926                 if (*tok == '#')
927                 {
928                         // ea, #<expr>
929                         tok++;
930
931                         if (abs_expr(&eval) != OK)
932                                 return OK;
933
934                         if (eval >= 0x10000)
935                                 return error(range_error);
936
937                         rmask = (WORD)eval;
938                 }
939                 else if (reglist(&rmask) < 0)
940                         return OK;
941
942                 if (!(amsktab[am0] & (C_CTRL | M_APOSTINC)))
943                         return error("invalid addressing mode");
944         }
945
946         D_word(inst);
947         D_word(rmask);
948         ea0gen(siz);
949
950         return OK;
951 }
952
953
954 //
955 // CLR.x An ==> SUBA.x An,An
956 //
957 int m_clra(WORD inst, WORD siz)
958 {
959         inst |= a0reg | reg_9[a0reg] | lwsiz_8[siz];
960         D_word(inst);
961
962         return OK;
963 }
964
965 ////////////////////////////////////////
966 //
967 // 68020/30/40 instructions
968 //
969 ////////////////////////////////////////
970
971 //
972 // Bcc.l -- BSR.l
973 //
974 int m_br30(WORD inst, WORD siz)
975 {
976     VALUE v;
977
978     if (a0exattr & DEFINED)
979     {
980         if ((a0exattr & TDB) != cursect)
981             //{
982             //printf("m_br(): a0exattr = %X, cursect = %X, a0exval = %X, sloc = %X\n", a0exattr, cursect, a0exval, sloc);
983             return error(rel_error);
984         //}
985
986         v = a0exval - (sloc + 2);
987
988         D_word(inst);
989         D_long(v);
990
991         return OK;
992     }
993     else
994     {
995         // .L 
996         AddFixup(FU_LONG | FU_PCREL | FU_SEXT, sloc, a0expr);
997         D_word(inst);
998         return OK;
999     }
1000 }
1001
1002 //
1003 // bfchg, bfclr, bfexts, bfextu, bfffo, bfins, bfset
1004 // (68020, 68030, 68040)
1005 //
1006 int m_bfop(WORD inst, WORD siz)
1007 {
1008         //TODO: is this needed or can we put that in the mask in 68ktab???
1009         if (am0 == AREG || am0== APOSTINC || am0 == APREDEC || am0 == IMMED|| am0 == ABASE || am0 == MEMPOST || am0 == MEMPRE || am0 == PCBASE || am0 == PCMPOST || am0 == PCMPRE)
1010                 return m_badmode(inst, siz);
1011
1012         //First instruction word - just the opcode and first EA
1013         //Note: both am1 is ORed because solely of bfins - maybe it's a good idea to make a dedicated function for it?
1014     if (am1 == AM_NONE)
1015         am1 = 0;
1016         D_word((inst|am0|a0reg|am1|a1reg));
1017         ea0gen(siz);    // Generate EA 
1018
1019         //Second instruction word - Dest register (if exists), Do, Offset, Dw, Width
1020         inst = bfparam1 | bfparam2;
1021         if (am1 == DREG)
1022                 inst |= a1reg << 12;
1023         if (am0 == DREG)
1024                 inst |= a0reg << 12;
1025         D_word(inst);
1026
1027         return OK;
1028 }
1029
1030 //
1031 // bkpt (68EC000, 68010, 68020, 68030, 68040, CPU32)
1032 //
1033 int m_bkpt(WORD inst, WORD siz)
1034 {
1035     CHECK00;
1036
1037         if (a0exattr & DEFINED)
1038         {
1039                 if (a0exattr & TDB)
1040                         return error(abs_error);
1041
1042                 if (a0exval >= 8)
1043                         return error(range_error);
1044
1045                 inst |= a0exval;
1046                 D_word(inst);
1047         }
1048         else 
1049                 return error(undef_error);
1050
1051         return OK;
1052 }
1053
1054 //
1055 // callm (68020)
1056 //
1057 int m_callm(WORD inst, WORD siz)
1058 {
1059     CHECKNO20;
1060
1061     inst |= am1;
1062         D_word(inst);
1063
1064         if (a0exattr & DEFINED)
1065         {
1066                 if (a0exattr & TDB)
1067                         return error(abs_error);
1068
1069                 if (a0exval > 255)
1070                         return error(range_error);
1071
1072                 inst = a0exval;
1073                 D_word(inst);
1074         }
1075         else 
1076                 return error(undef_error);
1077
1078     ea1gen(siz);
1079
1080         return OK;
1081
1082 }
1083
1084 //
1085 // cas (68020, 68030, 68040)
1086 //
1087 int m_cas(WORD inst, WORD siz)
1088 {
1089     WORD inst2;
1090     LONG amsk;
1091     int modes;
1092
1093     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1094         return error(unsupport);
1095
1096     switch (siz)
1097     {
1098     case SIZB:
1099         inst |= 1 << 9;
1100         break;
1101     case SIZW:
1102     case SIZN:
1103         inst |= 2 << 9;
1104         break;
1105     case SIZL:
1106         inst |= 3 << 9;
1107         break;
1108     default:
1109         return error("bad size suffix");
1110         break;
1111     }
1112
1113     // Dc
1114     if ((*tok < KW_D0) && (*tok > KW_D7))
1115         return error("CAS accepts only data registers");
1116     inst2 = (*tok++) & 7;
1117
1118     if (*tok++ != ',')
1119         return error("missing comma");
1120
1121     // Du
1122     if ((*tok < KW_D0) && (*tok > KW_D7))
1123         return error("CAS accepts only data registers");
1124     inst2 |= ((*tok++) & 7)<<6;
1125
1126     if (*tok++ != ',')
1127         return error("missing comma");
1128
1129     // ea
1130     if ((modes=amode(1)) < 0)
1131         return OK;
1132
1133     if (modes > 1)
1134         return error("too many ea fields");
1135
1136     if (*tok!=EOL)
1137         return error("extra (unexpected) text found");
1138
1139     // Reject invalud ea modes
1140     amsk = amsktab[am0];
1141     if (amsk&(M_AIND | M_APOSTINC | M_APREDEC | M_ADISP | M_AINDEXED | M_ABSW | M_ABSL | M_ABASE | M_MEMPOST | M_MEMPRE) == 0)
1142         return error("unsupported addressing mode");
1143
1144     inst |= am0 | a0reg;
1145     D_word(inst);
1146     D_word(inst2);
1147     ea0gen(siz);
1148
1149     return OK;
1150 }
1151
1152 //
1153 // cas2 (68020, 68030, 68040)
1154 //
1155 int m_cas2(WORD inst, WORD siz)
1156 {
1157     WORD inst2, inst3;
1158     LONG amsk;
1159
1160     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1161         return error(unsupport);
1162
1163     switch (siz)
1164     {
1165     case SIZB:
1166         inst |= 1 << 9;
1167         break;
1168     case SIZW:
1169     case SIZN:
1170         inst |= 2 << 9;
1171         break;
1172     case SIZL:
1173         inst |= 3 << 9;
1174         break;
1175     default:
1176         return error("bad size suffix");
1177         break;
1178     }
1179
1180     // Dc1
1181     if ((*tok < KW_D0) && (*tok > KW_D7))
1182         return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1183     inst2 = (*tok++) & 7;
1184
1185     if (*tok++ != ':')
1186         return error("missing colon");
1187     
1188     // Dc2
1189     if ((*tok < KW_D0) && (*tok > KW_D7))
1190         return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1191     inst3 = (*tok++) & 7;
1192
1193     if (*tok++ != ',')
1194         return error("missing comma");
1195
1196     // Du1
1197     if ((*tok < KW_D0) && (*tok > KW_D7))
1198         return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1199     inst2 |= ((*tok++) & 7)<<6;
1200
1201     if (*tok++ != ':')
1202         return error("missing colon");
1203
1204     // Du2
1205     if ((*tok < KW_D0) && (*tok > KW_D7))
1206         return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1207     inst3 |= ((*tok++) & 7) << 6;
1208
1209     if (*tok++ != ',')
1210         return error("missing comma");
1211
1212     // Rn1
1213     if (*tok++ != '(')
1214         return error("missing (");
1215     if ((*tok >= KW_D0) && (*tok <= KW_D7))
1216         inst2 |= (((*tok++) & 7) << 12) | (0 << 15);
1217     else if ((*tok >= KW_A0) && (*tok <= KW_A7))
1218         inst2 |= (((*tok++) & 7) << 12) | (1 << 15);
1219     else
1220         return error("CAS accepts either data or address registers for Rn1:Rn2 pair");
1221
1222     if (*tok++ != ')')
1223         return error("missing (");
1224
1225     if (*tok++ != ':')
1226         return error("missing colon");
1227
1228     // Rn2
1229     if (*tok++ != '(')
1230         return error("missing (");
1231     if ((*tok >= KW_D0) && (*tok <= KW_D7))
1232         inst3 |= (((*tok++) & 7) << 12) | (0 << 15);
1233     else if ((*tok >= KW_A0) && (*tok <= KW_A7))
1234         inst3 |= (((*tok++) & 7) << 12) | (1 << 15);
1235     else
1236         return error("CAS accepts either data or address registers for Rn1:Rn2 pair");
1237
1238     if (*tok++ != ')')
1239         return error("missing (");
1240
1241     if (*tok != EOL)
1242         return error("extra (unexpected) text found");
1243
1244     D_word(inst);
1245     D_word(inst2);
1246     D_word(inst3);
1247
1248     return OK;
1249 }
1250
1251 //
1252 // cmp2 (68020, 68030, 68040, CPU32)
1253 //
1254 int m_cmp2(WORD inst, WORD siz)
1255 {
1256     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1257         return error(unsupport);
1258
1259     switch (siz&15)
1260     {
1261     case SIZW:
1262     case SIZN:
1263         inst |= 1 << 9;
1264         break;
1265     case SIZL:
1266         inst |= 2 << 9;
1267         break;
1268     default:
1269         // SIZB
1270         break;
1271     }
1272
1273     WORD flg = inst;                                    // Save flag bits 
1274     inst &= ~0x3F;                                              // Clobber flag bits in instr 
1275
1276                                         // Install "standard" instr size bits 
1277     if (flg & 4)
1278         inst |= siz_6[siz];
1279
1280     if (flg & 16)
1281     {
1282         // OR-in register number 
1283         if (flg & 8)
1284             inst |= reg_9[a1reg];               // ea1reg in bits 9..11 
1285         else
1286             inst |= reg_9[a0reg];               // ea0reg in bits 9..11 
1287     }
1288
1289     if (flg & 1)
1290     {
1291         // Use am1 
1292         inst |= am1 | a1reg;                    // Get ea1 into instr 
1293         D_word(inst);                                   // Deposit instr 
1294
1295                                         // Generate ea0 if requested 
1296         if (flg & 2)
1297             ea0gen(siz);
1298
1299         ea1gen(siz);                                    // Generate ea1 
1300     }
1301     else
1302     {
1303         // Use am0 
1304         inst |= am0 | a0reg;                    // Get ea0 into instr 
1305         D_word(inst);                                   // Deposit instr 
1306         ea0gen(siz);                                    // Generate ea0 
1307
1308                                         // Generate ea1 if requested 
1309         if (flg & 2)
1310             ea1gen(siz);
1311     }
1312
1313     // If we're called from chk2 then bit 11 of size will be set.
1314     // This is just a dumb mechanism to pass this, required by the extension word.
1315     // (you might have noticed the siz&15 thing above!)
1316         inst = (a1reg << 12)|(siz&(1<<11));
1317     if (am1 == AREG)
1318         inst |= 1 << 15;
1319
1320         D_word(inst);
1321
1322         return OK;
1323 }
1324
1325 //
1326 // chk2 (68020, 68030, 68040, CPU32)
1327 //
1328 int m_chk2(WORD inst, WORD siz)
1329 {
1330     return m_cmp2(inst, siz | (1 << 11));
1331 }
1332
1333 //
1334 // cpbcc(68020, 68030)
1335 //
1336 int m_cpbr(WORD inst, WORD siz)
1337 {
1338     if ((activecpu & (CPU_68020 | CPU_68030)) == 0)
1339         return error(unsupport);
1340
1341     VALUE v;
1342
1343         if (a0exattr & DEFINED)
1344         {
1345                 if ((a0exattr & TDB) != cursect)
1346 //{
1347 //printf("m_br(): a0exattr = %X, cursect = %X, a0exval = %X, sloc = %X\n", a0exattr, cursect, a0exval, sloc);
1348                         return error(rel_error);
1349 //}
1350
1351                 v = a0exval - (sloc + 2);
1352
1353                 // Optimize branch instr. size
1354                 if (siz == SIZL)
1355                 {
1356                         if (v != 0 && v + 0x8000 < 0x10000)
1357                         {
1358                 inst |= (1 << 6);
1359                                 D_word(inst);
1360                                 WARNING(check what s "optional coprocessor-defined extension words!")
1361                                 D_long(v);
1362                                 return OK;
1363                         }
1364                 }
1365         else // SIZW/SIZN
1366                 {
1367                         if (v + 0x8000 >= 0x10000)
1368                                 return error(range_error);
1369                         D_word(inst);
1370                         WARNING(check what s "optional coprocessor-defined extension words!")
1371                         D_word(v);
1372                 }
1373
1374                 return OK;
1375         }
1376         else if (siz == SIZN)
1377                 siz = SIZW;
1378
1379         if (siz == SIZL)
1380         {
1381                 // .L
1382         D_word(inst);
1383         AddFixup(FU_LONG | FU_PCREL | FU_SEXT, sloc, a0expr);
1384         D_long(0);
1385                 return OK;
1386         }
1387         else
1388         {
1389                 // .W 
1390                 D_word(inst);
1391                 AddFixup(FU_WORD | FU_PCREL | FU_SEXT, sloc, a0expr);
1392                 D_word(0);
1393         }
1394
1395         return OK;
1396 }
1397
1398 //
1399 // cpdbcc(68020, 68030)
1400 //
1401 int m_cpdbr(WORD inst, WORD siz)
1402 {
1403     if ((activecpu & (CPU_68020 | CPU_68030)) == 0)
1404         return error(unsupport);
1405
1406     return error("Not implemented yet.");
1407
1408         //return OK;
1409 }
1410
1411 //
1412 // divs.l
1413 //
1414 int m_divs(WORD inst, WORD siz)
1415 {
1416     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1417         return error(unsupport);
1418
1419     WORD flg = inst;                                    // Save flag bits 
1420     inst &= ~0x3F;                                              // Clobber flag bits in instr 
1421
1422                                         // Install "standard" instr size bits 
1423     if (flg & 4)
1424         inst |= siz_6[siz];
1425
1426     if (flg & 16)
1427     {
1428         // OR-in register number 
1429         if (flg & 8)
1430             inst |= reg_9[a1reg];               // ea1reg in bits 9..11 
1431         else
1432             inst |= reg_9[a0reg];               // ea0reg in bits 9..11 
1433     }
1434
1435     if (flg & 1)
1436     {
1437         // Use am1 
1438         inst |= am1 | a1reg;                    // Get ea1 into instr 
1439         D_word(inst);                                   // Deposit instr 
1440
1441                                         // Generate ea0 if requested 
1442         if (flg & 2)
1443             ea0gen(siz);
1444
1445         ea1gen(siz);                                    // Generate ea1 
1446     }
1447     else
1448     {
1449         // Use am0 
1450         inst |= am0 | a0reg;                    // Get ea0 into instr 
1451         D_word(inst);                                   // Deposit instr 
1452         ea0gen(siz);                                    // Generate ea0 
1453
1454                                         // Generate ea1 if requested 
1455         if (flg & 2)
1456             ea1gen(siz);
1457     }
1458
1459         //D_word(inst);
1460         //ea0gen(siz);
1461         inst=a1reg+(a2reg<<12)+(1<<11);
1462         D_word(inst);
1463         
1464         return OK;
1465 }
1466 //
1467 // muls.l
1468 //
1469 int m_muls(WORD inst, WORD siz)
1470 {
1471     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1472         return error(unsupport);
1473
1474     WORD flg = inst;                                    // Save flag bits 
1475     inst &= ~0x3F;                                              // Clobber flag bits in instr 
1476
1477                                         // Install "standard" instr size bits 
1478     if (flg & 4)
1479         inst |= siz_6[siz];
1480
1481     if (flg & 16)
1482     {
1483         // OR-in register number 
1484         if (flg & 8)
1485             inst |= reg_9[a1reg];               // ea1reg in bits 9..11 
1486         else
1487             inst |= reg_9[a0reg];               // ea0reg in bits 9..11 
1488     }
1489
1490     if (flg & 1)
1491     {
1492         // Use am1 
1493         inst |= am1 | a1reg;                    // Get ea1 into instr 
1494         D_word(inst);                                   // Deposit instr 
1495
1496                                         // Generate ea0 if requested 
1497         if (flg & 2)
1498             ea0gen(siz);
1499
1500         ea1gen(siz);                                    // Generate ea1 
1501     }
1502     else
1503     {
1504         // Use am0 
1505         inst |= am0 | a0reg;                    // Get ea0 into instr 
1506         D_word(inst);                                   // Deposit instr 
1507         ea0gen(siz);                                    // Generate ea0 
1508
1509                                         // Generate ea1 if requested 
1510         if (flg & 2)
1511             ea1gen(siz);
1512     }
1513
1514     //D_word(inst);
1515         //ea0gen(siz);
1516         inst=a1reg+(a2reg<<12)+(1<<11);
1517     inst|=mulmode;  // add size bit
1518         D_word(inst);
1519         
1520         return OK;
1521 }
1522 //
1523 // divu.l
1524 //
1525 int m_divu(WORD inst, WORD siz)
1526 {
1527     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1528         return error(unsupport);
1529
1530     //WARNING("divu.l d0,d1 is actually divul.l d0,d1:d1!!!")
1531
1532     WORD flg = inst;                                    // Save flag bits 
1533     inst &= ~0x3F;                                              // Clobber flag bits in instr 
1534
1535                                         // Install "standard" instr size bits 
1536     if (flg & 4)
1537         inst |= siz_6[siz];
1538
1539     if (flg & 16)
1540     {
1541         // OR-in register number 
1542         if (flg & 8)
1543             inst |= reg_9[a1reg];               // ea1reg in bits 9..11 
1544         else
1545             inst |= reg_9[a0reg];               // ea0reg in bits 9..11 
1546     }
1547
1548     if (flg & 1)
1549     {
1550         // Use am1 
1551         inst |= am1 | a1reg;                    // Get ea1 into instr 
1552         D_word(inst);                                   // Deposit instr 
1553
1554                                         // Generate ea0 if requested 
1555         if (flg & 2)
1556             ea0gen(siz);
1557
1558         ea1gen(siz);                                    // Generate ea1 
1559     }
1560     else
1561     {
1562         // Use am0 
1563         inst |= am0 | a0reg;                    // Get ea0 into instr 
1564         D_word(inst);                                   // Deposit instr 
1565         ea0gen(siz);                                    // Generate ea0 
1566
1567                                         // Generate ea1 if requested 
1568         if (flg & 2)
1569             ea1gen(siz);
1570     }
1571
1572         //D_word(inst);
1573         //ea0gen(siz);
1574         inst=a1reg+(a2reg<<12);
1575         D_word(inst);
1576         
1577         return OK;
1578 }
1579 //
1580 // mulu.l
1581 //
1582 int m_mulu(WORD inst, WORD siz)
1583 {
1584     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1585         return error(unsupport);
1586
1587     WORD flg = inst;                                    // Save flag bits 
1588     inst &= ~0x3F;                                              // Clobber flag bits in instr 
1589
1590                                         // Install "standard" instr size bits 
1591     if (flg & 4)
1592         inst |= siz_6[siz];
1593
1594     if (flg & 16)
1595     {
1596         // OR-in register number 
1597         if (flg & 8)
1598             inst |= reg_9[a1reg];               // ea1reg in bits 9..11 
1599         else
1600             inst |= reg_9[a0reg];               // ea0reg in bits 9..11 
1601     }
1602
1603     if (flg & 1)
1604     {
1605         // Use am1 
1606         inst |= am1 | a1reg;                    // Get ea1 into instr 
1607         D_word(inst);                                   // Deposit instr 
1608
1609                                         // Generate ea0 if requested 
1610         if (flg & 2)
1611             ea0gen(siz);
1612
1613         ea1gen(siz);                                    // Generate ea1 
1614     }
1615     else
1616     {
1617         // Use am0 
1618         inst |= am0 | a0reg;                    // Get ea0 into instr 
1619         D_word(inst);                                   // Deposit instr 
1620         ea0gen(siz);                                    // Generate ea0 
1621
1622                                         // Generate ea1 if requested 
1623         if (flg & 2)
1624             ea1gen(siz);
1625     }
1626
1627     //D_word(inst);
1628         //ea0gen(siz);
1629         inst=a1reg+(a2reg<<12);
1630     inst|=mulmode;  // add size bit
1631         D_word(inst);
1632         
1633         return OK;
1634 }
1635
1636 //
1637 // divsl.l
1638 //
1639 int m_divsl(WORD inst, WORD siz)
1640 {
1641     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1642         return error(unsupport);
1643
1644     WORD flg = inst;                                    // Save flag bits 
1645     inst &= ~0x3F;                                              // Clobber flag bits in instr 
1646
1647                                         // Install "standard" instr size bits 
1648     if (flg & 4)
1649         inst |= siz_6[siz];
1650
1651     if (flg & 16)
1652     {
1653         // OR-in register number 
1654         if (flg & 8)
1655             inst |= reg_9[a1reg];               // ea1reg in bits 9..11 
1656         else
1657             inst |= reg_9[a0reg];               // ea0reg in bits 9..11 
1658     }
1659
1660     if (flg & 1)
1661     {
1662         // Use am1 
1663         inst |= am1 | a1reg;                    // Get ea1 into instr 
1664         D_word(inst);                                   // Deposit instr 
1665
1666                                         // Generate ea0 if requested 
1667         if (flg & 2)
1668             ea0gen(siz);
1669
1670         ea1gen(siz);                                    // Generate ea1 
1671     }
1672     else
1673     {
1674         // Use am0 
1675         inst |= am0 | a0reg;                    // Get ea0 into instr 
1676         D_word(inst);                                   // Deposit instr 
1677         ea0gen(siz);                                    // Generate ea0 
1678
1679                                         // Generate ea1 if requested 
1680         if (flg & 2)
1681             ea1gen(siz);
1682     }
1683
1684     //D_word(inst);
1685         //ea0gen(siz);
1686         inst=a1reg+(a2reg<<12)+(1<<11)+(1<<10);
1687         D_word(inst);
1688
1689         return OK;
1690 }
1691
1692 //
1693 // divul.l
1694 //
1695 int m_divul(WORD inst, WORD siz)
1696 {
1697     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1698         return error(unsupport);
1699
1700     WORD flg = inst;                                    // Save flag bits 
1701     inst &= ~0x3F;                                              // Clobber flag bits in instr 
1702
1703                                         // Install "standard" instr size bits 
1704     if (flg & 4)
1705         inst |= siz_6[siz];
1706
1707     if (flg & 16)
1708     {
1709         // OR-in register number 
1710         if (flg & 8)
1711             inst |= reg_9[a1reg];               // ea1reg in bits 9..11 
1712         else
1713             inst |= reg_9[a0reg];               // ea0reg in bits 9..11 
1714     }
1715
1716     if (flg & 1)
1717     {
1718         // Use am1 
1719         inst |= am1 | a1reg;                    // Get ea1 into instr 
1720         D_word(inst);                                   // Deposit instr 
1721
1722                                         // Generate ea0 if requested 
1723         if (flg & 2)
1724             ea0gen(siz);
1725
1726         ea1gen(siz);                                    // Generate ea1 
1727     }
1728     else
1729     {
1730         // Use am0 
1731         inst |= am0 | a0reg;                    // Get ea0 into instr 
1732         D_word(inst);                                   // Deposit instr 
1733         ea0gen(siz);                                    // Generate ea0 
1734
1735                                         // Generate ea1 if requested 
1736         if (flg & 2)
1737             ea1gen(siz);
1738     }
1739
1740     //D_word(inst);
1741         //ea0gen(siz);
1742         inst=a1reg+(a2reg<<12)+(1<<10);
1743         D_word(inst);
1744
1745         return OK;
1746 }
1747
1748 //
1749 // move16 (ax)+,(ay)+
1750 //
1751 int m_move16a(WORD inst, WORD siz)
1752 {
1753     if ((activecpu & (CPU_68040 | CPU_68060)) == 0)
1754         return error(unsupport);
1755
1756     inst|=a0reg;
1757         D_word(inst);
1758         inst=(1<<15)+(a1reg<<12);
1759         D_word(inst);
1760
1761         return OK;
1762 }
1763
1764 //
1765 // move16 with absolute address
1766 //
1767 int m_move16b(WORD inst, WORD siz)
1768 {
1769     if ((activecpu & (CPU_68040 | CPU_68060)) == 0)
1770         return error(unsupport);
1771
1772     int v;
1773         inst|=a1reg;
1774         D_word(inst);
1775
1776         if (am0==APOSTINC)
1777                 if (am1==AIND)
1778                         return error("Wasn't this suppose to call m_move16a???");
1779                 else
1780                 {
1781                         //move16 (ax)+,(xxx).L
1782                         inst|=0<<3;
1783                         v=a1exval;
1784                 }
1785         else if (am0==ABSL)
1786                 if (am1==AIND)
1787                 {
1788                         //move16 (xxx).L,(ax)+
1789                         inst|=1<<3;
1790                         v=a0exval;
1791                 }
1792                 else //APOSTINC
1793                 {
1794                         //move16 (xxx).L,(ax)
1795                         inst|=3<<3;
1796                         v=a0exval;
1797                 }
1798         else if (am0==AIND)
1799         {
1800                 //move16 (ax),(xxx).L
1801                 inst|=2<<3;
1802                 v=a1exval;
1803         }
1804         D_word(inst);
1805         D_long(v);
1806         return OK;
1807 }
1808
1809 //
1810 // pack/unpack
1811 //
1812 int m_pack(WORD inst, WORD siz)
1813 {
1814     if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1815         return error(unsupport);
1816
1817     WARNING(Parsing stuff by hand here might be better)
1818
1819     //if (am0==DREG && am1==DREG)
1820         //{
1821         //      inst|=(1<<3)+(a0reg<<9)+(a1reg);
1822         //}
1823         //else if (am0==APREDEC && am1==APREDEC)
1824         //{
1825         //      inst|=(a0reg<<9)+(a1reg);
1826         //}
1827         //else
1828         //      return error("Only allowed combinations for pack/unpack are -(ax),-(ay) and dx,dy.");
1829     //
1830         //D_word(inst);
1831
1832         return OK;
1833 }
1834
1835 //
1836 // rtm Rn
1837 //
1838 int m_rtm(WORD inst, WORD siz)
1839 {
1840     CHECKNO20;
1841
1842         if (am0==DREG)
1843         {
1844                 inst|=a0reg;
1845         }
1846         else if (am0==AREG)
1847         {
1848                 inst|=(1<<3)+a0reg;
1849         }
1850         else
1851                 return error("rtm only allows data or address registers.");
1852
1853         D_word(inst);
1854
1855         return OK;
1856 }
1857
1858 //
1859 // rtd #n
1860 //
1861 int m_rtd(WORD inst, WORD siz)
1862 {
1863     CHECK00;
1864
1865     if (a0exattr & DEFINED)
1866     {
1867         if (a0exattr & TDB)
1868             return error(abs_error);
1869
1870         if (a0exval+0x8000 <= 0x7fff)
1871             return error(range_error);
1872
1873         D_word(inst);
1874         D_word(a0exval);
1875     }
1876     else
1877         return error(undef_error);
1878
1879     return OK;
1880 }
1881
1882
1883 //
1884 // trapcc
1885 //
1886 int m_trapcc(WORD inst, WORD siz)
1887 {
1888     CHECK00;
1889     
1890     if (am0==AM_NONE)
1891         {
1892                 D_word(inst);
1893         }
1894         else if (am0==IMMED)
1895         {
1896         if (siz==SIZW)
1897         {
1898                 if (a0exval<0x10000)
1899                 {
1900             inst|=2;
1901                     D_word(inst);
1902             D_word(a0exval);
1903                 }
1904         else
1905         {
1906             return error("Immediate value too big");
1907         }
1908         }
1909         else //DOTL
1910         {
1911             inst|=3;
1912                         D_word(inst);
1913                         D_long(a0exval);
1914                 }
1915         }
1916         else
1917                 return error("Invalid parameter for trapcc");
1918
1919         return OK;
1920 }
1921
1922 //
1923 // cinv (68040)
1924 //
1925 int m_cinv(WORD inst, WORD siz)
1926 {
1927     CHECKNO40;
1928
1929         WARNING("cinvl ,(an) / cinvp ,(an) / cinva should work!")
1930         if (am0==AM_NONE)
1931                 inst|=(0<<6)|(a1reg);
1932         else if (am0==KW_IC40)
1933                 inst|=(2<<6)|(a1reg);
1934         else if (am0==KW_DC40)
1935                 inst|=(1<<6)|(a1reg);
1936         else if (am0==KW_BC40)
1937                 inst|=(3<<6)|(a1reg);
1938
1939         D_word(inst);
1940         return OK;
1941         
1942 }
1943
1944 //
1945 // cpRESTORE (68020, 68030)
1946 //
1947 int m_cprest(WORD inst, WORD siz)
1948 {
1949     if (activecpu & !(CPU_68020|CPU_68030))
1950         return error(unsupport);
1951
1952     inst|=am0|a0reg;
1953         D_word(inst);
1954         ea0gen(siz);
1955
1956         return OK;
1957 }
1958
1959 //
1960 // movec (68010, 68020, 68030, 68040, CPU32)
1961 //
1962 int m_movec(WORD inst, WORD siz)
1963 {
1964     CHECK00;
1965
1966     if (am0 == DREG || am0 == AREG)
1967         {
1968                 // movec Rn,Rc
1969                 inst|=1;
1970                 D_word(inst);
1971                 if (am0 == DREG)
1972                 {
1973                         inst = (0 << 15) + (a0reg << 12) + CREGlut[a1reg];
1974                         D_word(inst);
1975                 }
1976                 else
1977                 {
1978                         inst = (1 << 15) + (a0reg << 12) + CREGlut[a1reg];
1979                         D_word(inst);
1980                 }
1981         }
1982         else
1983         {
1984                 // movec Rc,Rn
1985                 D_word(inst);
1986                 if (am1 == DREG)
1987                 {
1988                         inst = (0 << 15) + (a1reg << 12) + CREGlut[a0reg];
1989                         D_word(inst);
1990                 }
1991                 else
1992                 {
1993                         inst = (1 << 15) + (a1reg << 12) + CREGlut[a0reg];
1994                         D_word(inst);
1995                 }
1996         }
1997
1998         return OK;
1999 }
2000
2001 //
2002 // moves (68010, 68020, 68030, 68040, CPU32)
2003 //
2004 int m_moves(WORD inst, WORD siz)
2005 {
2006     if (activecpu & !(CPU_68020 | CPU_68030 | CPU_68040))
2007         return error(unsupport);
2008
2009     if (siz == SIZB)
2010     {
2011         inst |= 0 << 6;
2012     }
2013     else if (siz == SIZL)
2014     {
2015         inst |= 2 << 6;
2016     }
2017     else // SIZW/SIZN
2018     {
2019         inst |= 1 << 6;
2020     }
2021
2022     if (am0 == DREG)
2023     {
2024         inst |= am1 | a1reg;
2025         D_word(inst);
2026         inst = (a0reg << 12) | (1 << 11) | (0 << 15);
2027         D_word(inst);
2028     }
2029     else if (am0 == AREG)
2030     {
2031         inst |= am1 | a1reg;
2032         D_word(inst);
2033         inst = (a0reg << 12) | (1 << 11) | (1 << 15);
2034         D_word(inst);
2035     }
2036     else
2037     {
2038         if (am1 == DREG)
2039         {
2040             inst |= am0 | a0reg;
2041             D_word(inst);
2042             inst = (a1reg << 12) | (0 << 11) | (0 << 15);
2043             D_word(inst);
2044         }
2045         else
2046         {
2047             inst |= am0 | a0reg;
2048             D_word(inst);
2049             inst = (a1reg << 12) | (0 << 11) | (1 << 15);
2050             D_word(inst);
2051         }
2052     }
2053
2054     return OK;
2055     
2056 }
2057
2058 //
2059 // PBcc (MC68851)
2060 //
2061 int m_pbcc(WORD inst, WORD siz)
2062 {
2063     CHECKNO20;
2064     return error("Not implemented yet.");
2065 }
2066
2067 //
2068 // pflusha (68030)
2069 //
2070 int m_pflusha(WORD inst, WORD siz)
2071 {
2072     CHECKNO30;
2073
2074         D_word(inst);
2075         inst=((1 << 13) | (1 << 10)) | (0 << 5) | 0;
2076         D_word(inst);
2077         return OK;
2078 }
2079
2080 //
2081 // pflush (68030, 68040, 68060)
2082 //
2083 int m_pflush(WORD inst, WORD siz)
2084 {
2085         if (activecpu == CPU_68030)
2086         {
2087                 D_word(inst);
2088                 D_word(((1 << 13) | (1 << 10)) | (0 << 5) | 0);
2089         }
2090         else if (activecpu == CPU_68040 || activecpu == CPU_68060)
2091         {
2092                 D_word(0xf918);
2093         }
2094         else
2095                 return error(unsupport);
2096
2097         return OK;
2098 }
2099
2100 //
2101 // pflushr (68551)
2102 //
2103 int m_pflushr(WORD inst, WORD siz)
2104 {
2105     CHECKNO20;
2106
2107     WORD flg = inst;                                    // Save flag bits 
2108     inst &= ~0x3F;                                              // Clobber flag bits in instr 
2109
2110                                         // Install "standard" instr size bits 
2111     if (flg & 4)
2112         inst |= siz_6[siz];
2113
2114     if (flg & 16)
2115     {
2116         // OR-in register number 
2117         if (flg & 8)
2118             inst |= reg_9[a1reg];               // ea1reg in bits 9..11 
2119         else
2120             inst |= reg_9[a0reg];               // ea0reg in bits 9..11 
2121     }
2122
2123     if (flg & 1)
2124     {
2125         // Use am1 
2126         inst |= am1 | a1reg;                    // Get ea1 into instr 
2127         D_word(inst);                                   // Deposit instr 
2128
2129                                         // Generate ea0 if requested 
2130         if (flg & 2)
2131             ea0gen(siz);
2132
2133         ea1gen(siz);                                    // Generate ea1 
2134     }
2135     else
2136     {
2137         // Use am0 
2138         inst |= am0 | a0reg;                    // Get ea0 into instr 
2139         D_word(inst);                                   // Deposit instr 
2140         ea0gen(siz);                                    // Generate ea0 
2141
2142                                         // Generate ea1 if requested 
2143         if (flg & 2)
2144             ea1gen(siz);
2145     }
2146
2147     D_word(B16(10100000, 00000000));
2148 }
2149
2150 //
2151 // ploadr, ploadw (68030)
2152 //
2153 int m_pload(WORD inst, WORD siz)
2154 {
2155     CHECKNO30;
2156     return error("Not implemented yet.");
2157 }
2158
2159 //
2160 // pmove (68030)
2161 //
2162 int m_pmove(WORD inst, WORD siz)
2163 {
2164         int inst2,reg;
2165
2166     CHECKNO30;
2167
2168     inst2 = inst&(1 << 8); //Copy the flush bit over to inst2 in case we're called from m_pmovefd
2169         inst &= ~(1 << 8);              //And mask it out
2170         if (am0 == CREG)
2171         {
2172                 reg=a0reg;
2173                 inst2|= (1<<9);
2174         }
2175         else if (am1 == CREG)
2176         {
2177                 reg = a1reg;
2178                 inst2|=0;
2179         }
2180         else
2181                 return error("pmove sez: Wut?");
2182
2183         if ((reg == KW_URP-KW_SFC || reg == KW_SRP-KW_SFC) && ((siz != SIZD) && (siz!=SIZN)))
2184                 return error(siz_error);
2185         if ((reg == KW_TC-KW_SFC || reg == KW_TT0-KW_SFC || reg == KW_TT1-KW_SFC) && ((siz != SIZL)&&(siz!=SIZN)))
2186                 return error(siz_error);
2187         if ((reg == KW_MMUSR-KW_SFC) && ((siz != SIZW)&&(siz!=SIZN)))
2188                 return error(siz_error);
2189
2190         WARNING(Not all addressing modes are legal here!)
2191                 if (am0 == CREG)
2192                 {
2193                         inst|=am1;
2194                         D_word(inst);
2195                         ea1gen(siz);
2196                 }
2197                 else if (am1 == CREG)
2198                 {
2199                         inst|=am0;
2200                         D_word(inst);
2201                         ea0gen(siz);
2202                 }
2203
2204         switch (reg)
2205         {
2206         case (KW_URP-KW_SFC):
2207                 inst2 |= (3 << 10) + (2 << 13); break;
2208         case (KW_SRP-KW_SFC):
2209                 inst2 |= (2 << 10) + (2 << 13); break;
2210         case (KW_TC-KW_SFC):
2211                 inst2 |= (0 << 10) + (2 << 13); break;
2212         case (KW_TT0-KW_SFC):
2213                 inst2 |= (2 << 10) + (0 << 13); break;
2214         case (KW_TT1-KW_SFC):
2215                 inst2 |= (3 << 10) + (0 << 13); break;
2216         case (KW_MMUSR-KW_SFC):
2217                 inst2 |= (3 << 10) + (3 << 13); break;
2218         case (KW_CRP-KW_SFC) :  //68851 only
2219                 inst2 |= (3 << 10) + (2 << 13); break;
2220         }
2221
2222         D_word(inst2);
2223
2224         return OK;
2225 }
2226
2227 //
2228 // pmovefd (68030)
2229 //
2230 int m_pmovefd(WORD inst, WORD siz)
2231 {
2232     CHECKNO30;
2233
2234     return m_pmove(inst|(1<<8),siz);
2235 }
2236
2237 //
2238 // ptrapcc (68851)
2239 //
2240 int m_ptrapbs(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00000000)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00000000)); D_long(a0exval); } return OK; }
2241 int m_ptrapbc(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00000001)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00000001)); D_long(a0exval); } return OK; }
2242 int m_ptrapls(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00000010)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00000010)); D_long(a0exval); } return OK; }
2243 int m_ptraplc(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00000011)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00000011)); D_long(a0exval); } return OK; }
2244 int m_ptrapss(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00000100)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00000100)); D_long(a0exval); } return OK; }
2245 int m_ptrapsc(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00000101)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00000101)); D_long(a0exval); } return OK; }
2246 int m_ptrapas(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00000110)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00000110)); D_long(a0exval); } return OK; }
2247 int m_ptrapac(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00000111)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00000111)); D_long(a0exval); } return OK; }
2248 int m_ptrapws(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00001000)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00001000)); D_long(a0exval); } return OK; }
2249 int m_ptrapwc(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00001001)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00001001)); D_long(a0exval); } return OK; }
2250 int m_ptrapis(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00001010)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00001010)); D_long(a0exval); } return OK; }
2251 int m_ptrapic(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00001011)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00001011)); D_long(a0exval); } return OK; }
2252 int m_ptrapgc(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00001100)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00001100)); D_long(a0exval); } return OK; }
2253 int m_ptrapgs(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00001101)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00001101)); D_long(a0exval); } return OK; }
2254 int m_ptrapcs(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00001110)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00001110)); D_long(a0exval); } return OK; }
2255 int m_ptrapcc(WORD inst, WORD siz) { CHECKNO20; if (siz == SIZW) { D_word(inst); D_word(B8(00001111)); D_word(a0exval); } else { inst |= 3; D_word(inst); D_word(B8(00001111)); D_long(a0exval); } return OK; }
2256 int m_ptrapbsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000000)); return OK; }
2257 int m_ptrapbcn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000001)); return OK; }
2258 int m_ptraplsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000010)); return OK; }
2259 int m_ptraplcn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000011)); return OK; }
2260 int m_ptrapssn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000100)); return OK; }
2261 int m_ptrapscn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000101)); return OK; }
2262 int m_ptrapasn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000110)); return OK; }
2263 int m_ptrapacn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000111)); return OK; }
2264 int m_ptrapwsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001000)); return OK; }
2265 int m_ptrapwcn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001001)); return OK; }
2266 int m_ptrapisn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001010)); return OK; }
2267 int m_ptrapicn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001011)); return OK; }
2268 int m_ptrapgsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001100)); return OK; }
2269 int m_ptrapgcn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001101)); return OK; }
2270 int m_ptrapcsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001110)); return OK; }
2271 int m_ptrapccn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001111)); return OK; }
2272
2273 //
2274 // ptestr, ptestw (68030)
2275 //
2276 int m_ptest(WORD inst, WORD siz)
2277 {
2278     CHECKNO30;
2279         if (activecpu == CPU_68030)
2280                 return error("Not implemented yet.");
2281         else if (activecpu == CPU_68040)
2282                 return error("Not implemented yet.");
2283         return ERROR;
2284 }
2285
2286 #define FPU_NOWARN 0
2287 #define FPU_P_EMUL 1
2288 #define FPU_P2_EMU 2
2289 #define FPU_FPSP   4
2290
2291 //
2292 // Generate a FPU opcode
2293 //
2294 static inline int gen_fpu(WORD inst, WORD siz, WORD opmode, WORD emul)
2295 {
2296         if (am0<AM_NONE)        // Check first operand for ea or fp - is this right?
2297         {
2298                 inst|=(1<<9);   // Bolt on FPU id
2299                 inst|=am0;
2300         if (am0==DREG)
2301             inst|=a0reg;
2302                 D_word(inst);
2303                 inst = 1 << 14; // R/M field (we have ea so have to set this to 1)
2304                 switch (siz)
2305                 {
2306                 case SIZB:      inst |= (6<<10); break;
2307                 case SIZW:      inst |= (4<<10); break;
2308                 case SIZL:      inst |= (0<<10); break;
2309                 case SIZN:
2310                 case SIZS:      inst |= (1<<10); break;
2311                 case SIZD:      inst |= (5<<10); break;
2312                 case SIZX:      inst |= (2<<10); break;
2313                 case SIZP:
2314                 {
2315                         inst |= (3<<10);
2316                         if (emul)
2317                                 warn("This encoding will cause an unimplemented data type exception in the MC68040 to allow emulation in software.");
2318                 }
2319                 break;
2320                 default: return error("Something bad happened, possibly, in gen_fpu."); break;
2321                 }
2322                 inst |= (a1reg << 7);
2323                 inst |= opmode;
2324                 D_word(inst);
2325                 ea0gen(siz);
2326         }
2327         else
2328         {
2329                 inst|=(1<<9);   //Bolt on FPU id
2330                 D_word(inst);
2331                 inst = 0;
2332                 inst = a0reg << 10;
2333                 inst |= (a1reg << 7);
2334                 inst |= opmode;
2335                 D_word(inst);
2336         }
2337         if (emul&FPU_FPSP && activefpu==FPU_68040)
2338                 warn("Instruction is emulated in 68040");
2339
2340         return OK;
2341 }
2342
2343 //
2344 // fabs, fsabs, fdabs (6888X, 68040)
2345 //
2346 int m_fabs(WORD inst, WORD siz)
2347 {
2348         return gen_fpu(inst, siz, B8(00011000), FPU_P_EMUL);
2349 }
2350 int m_fsabs(WORD inst, WORD siz)
2351 {
2352         if (activefpu == FPU_68040)
2353                 return gen_fpu(inst, siz, B8(01011000), FPU_P_EMUL);
2354         else
2355                 return error("Unsupported in current FPU");
2356 }
2357 int m_fdabs(WORD inst, WORD siz)
2358 {
2359         if (activefpu == FPU_68040)
2360                 return gen_fpu(inst, siz, B8(01011100), FPU_P_EMUL);
2361         else
2362                 return error("Unsupported in current FPU");
2363 }
2364
2365 //
2366 // facos (6888X, 68040FPSP)
2367 //
2368 int m_facos(WORD inst, WORD siz)
2369 {
2370         return gen_fpu(inst, siz, B8(00011100), FPU_FPSP);
2371 }
2372
2373 //
2374 // fadd (6888X, 68040FPSP)
2375 //
2376 int m_fadd(WORD inst, WORD siz)
2377 {
2378         return gen_fpu(inst, siz, B8(00100010), FPU_P_EMUL);
2379 }
2380 int m_fsadd(WORD inst, WORD siz)
2381 {
2382         if (activefpu == FPU_68040)
2383                 return gen_fpu(inst, siz, B8(01100010), FPU_P_EMUL);
2384         else
2385                 return error("Unsupported in current FPU");
2386 }
2387 int m_fdadd(WORD inst, WORD siz)
2388 {
2389         if (activefpu == FPU_68040)
2390                 return gen_fpu(inst, siz, B8(01100110), FPU_P_EMUL);
2391         else
2392                 return error("Unsupported in current FPU");
2393 }
2394
2395 //
2396 // fasin (6888X, 68040FPSP)f
2397 //
2398 int m_fasin(WORD inst, WORD siz)
2399 {
2400         return gen_fpu(inst, siz, B8(00001100), FPU_FPSP);
2401 }
2402
2403 //
2404 // fatan (6888X, 68040FPSP)
2405 //
2406 int m_fatan(WORD inst, WORD siz)
2407 {
2408         return gen_fpu(inst, siz, B8(00001010), FPU_FPSP);
2409 }
2410
2411 //
2412 // fatanh (6888X, 68040FPSP)
2413 //
2414 int m_fatanh(WORD inst, WORD siz)
2415 {
2416         return gen_fpu(inst, siz, B8(00001101), FPU_FPSP);
2417 }
2418
2419 //
2420 // fcmp (6888X, 68040)
2421 //
2422 int m_fcmp(WORD inst, WORD siz)
2423 {
2424         return gen_fpu(inst, siz, B8(00111000), FPU_P_EMUL);
2425 }
2426
2427 //
2428 // fcos (6888X, 68040FPSP)
2429 //
2430 int m_fcos(WORD inst, WORD siz)
2431 {
2432         return gen_fpu(inst, siz, B8(00011101), FPU_FPSP);
2433 }
2434
2435 //
2436 // fcosh (6888X, 68040FPSP)
2437 //
2438 int m_fcosh(WORD inst, WORD siz)
2439 {
2440         return gen_fpu(inst, siz, B8(00011001), FPU_FPSP);
2441 }
2442
2443 //
2444 // fdbcc (6888X, 68040)
2445 //
2446 int m_fdbcc(WORD inst, WORD siz)
2447 {
2448         VALUE v;
2449
2450         WORD opcode=inst&0x3f;  //Grab conditional bitfield
2451
2452         inst&=~0x3f;
2453         inst|=1<<3;
2454
2455         siz = siz;
2456         inst |= a0reg;
2457         D_word(inst);
2458
2459         D_word(opcode);
2460
2461         if (a1exattr & DEFINED)
2462         {
2463                 if ((a1exattr & TDB) != cursect)
2464                         return error(rel_error);
2465
2466                 v = a1exval - sloc;
2467
2468                 if (v + 0x8000 > 0x10000)
2469                         return error(range_error);
2470
2471                 D_word(v);
2472         }
2473         else
2474         {
2475                 AddFixup(FU_WORD | FU_PCREL | FU_ISBRA, sloc, a1expr);
2476                 D_word(0);
2477         }
2478
2479         return OK;
2480 }
2481
2482
2483
2484
2485 //
2486 // fdiv (6888X, 68040)
2487 //
2488 int m_fdiv(WORD inst, WORD siz)
2489 {
2490         return gen_fpu(inst, siz, B8(00100000), FPU_P_EMUL);
2491 }
2492 int m_fsdiv(WORD inst, WORD siz)
2493 {
2494         if (activefpu == FPU_68040)
2495                 return gen_fpu(inst, siz, B8(01100000), FPU_P_EMUL);
2496         else
2497                 return error("Unsupported in current FPU");
2498 }
2499 int m_fddiv(WORD inst, WORD siz)
2500 {
2501         if (activefpu == FPU_68040)
2502                 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
2503         else
2504                 return error("Unsupported in current FPU");
2505 }
2506
2507 //
2508 // fetox (6888X, 68040FPSP)
2509 //
2510 int m_fetox(WORD inst, WORD siz)
2511 {
2512         return gen_fpu(inst, siz, B8(00010000), FPU_FPSP);
2513 }
2514
2515 //
2516 // fetoxm1 (6888X, 68040FPSP)
2517 //
2518 int m_fetoxm1(WORD inst, WORD siz)
2519 {
2520         return gen_fpu(inst, siz, B8(00001000), FPU_FPSP);
2521 }
2522
2523 //
2524 // fgetexp (6888X, 68040FPSP)
2525 //
2526 int m_fgetexp(WORD inst, WORD siz)
2527 {
2528         return gen_fpu(inst, siz, B8(00011110), FPU_FPSP);
2529 }
2530
2531 //
2532 // fgetman (6888X, 68040FPSP)
2533 //
2534 int m_fgetman(WORD inst, WORD siz)
2535 {
2536         return gen_fpu(inst, siz, B8(00011111), FPU_FPSP);
2537 }
2538
2539 //
2540 // fint (6888X, 68040FPSP)
2541 //
2542 int m_fint(WORD inst, WORD siz)
2543 {
2544     if (am1==AM_NONE)
2545         // special case - fint fpx = fint fpx,fpx
2546         a1reg=a0reg;
2547         return gen_fpu(inst, siz, B8(00000001), FPU_FPSP);
2548 }
2549
2550 //
2551 // fintrz (6888X, 68040FPSP)
2552 //
2553 int m_fintrz(WORD inst, WORD siz)
2554 {
2555     if (am1==AM_NONE)
2556         // special case - fintrz fpx = fintrz fpx,fpx
2557         a1reg=a0reg;
2558         return gen_fpu(inst, siz, B8(00000011), FPU_FPSP);
2559 }
2560
2561 //
2562 // flog10 (6888X, 68040FPSP)
2563 //
2564 int m_flog10(WORD inst, WORD siz)
2565 {
2566         return gen_fpu(inst, siz, B8(00010101), FPU_FPSP);
2567 }
2568
2569 //
2570 // flog2 (6888X, 68040FPSP)
2571 //
2572 int m_flog2(WORD inst, WORD siz)
2573 {
2574         return gen_fpu(inst, siz, B8(00010110), FPU_FPSP);
2575 }
2576
2577 //
2578 // flogn (6888X, 68040FPSP)
2579 //
2580 int m_flogn(WORD inst, WORD siz)
2581 {
2582         return gen_fpu(inst, siz, B8(00010100), FPU_FPSP);
2583 }
2584
2585 //
2586 // flognp1 (6888X, 68040FPSP)
2587 //
2588 int m_flognp1(WORD inst, WORD siz)
2589 {
2590         return gen_fpu(inst, siz, B8(00000110), FPU_FPSP);
2591 }
2592
2593 //
2594 // fmod (6888X, 68040FPSP)
2595 //
2596 int m_fmod(WORD inst, WORD siz)
2597 {
2598         return gen_fpu(inst, siz, B8(00100001), FPU_FPSP);
2599 }
2600
2601 //
2602 // fmove (6888X, 68040)
2603 //
2604 int m_fmove(WORD inst, WORD siz)
2605 {
2606
2607         ////////////ea to register
2608         if (am0==FREG&&am1<AM_USP)
2609         {
2610         //fpx->ea
2611
2612                 //ea
2613                 inst|=am1|a1reg;
2614                 D_word(inst);
2615
2616                 //r/m
2617                 //if (am0==DREG)
2618                         inst=3<<13;
2619                 //else
2620                 //      inst=0;
2621
2622                 WARNING("K-factor logic is totally bogus - fix!")
2623
2624                 //source specifier
2625                 switch (siz)
2626                 {
2627                 case SIZB:      inst |= (6<<10); break;
2628                 case SIZW:      inst |= (4<<10); break;
2629                 case SIZL:      inst |= (0<<10); break;
2630                 case SIZN:
2631                 case SIZS:      inst |= (1<<10); break;
2632                 case SIZD:      inst |= (5<<10); break;
2633                 case SIZX:      inst |= (2<<10); break;
2634                 case SIZP:  inst |= (3<<10); if (bfparam1) inst|=1<<12; inst|=(bfparam1&0x7ff)>>2; break;
2635                 default: return error("Something bad happened, possibly."); break;
2636                 }
2637
2638                 //immediate {} value
2639                 if (bf0exval>=1<<6)
2640                         return error("K-factor must be between 0 and 31");
2641                 if ((!bfparam1) && siz==SIZP)
2642             inst|=bf0exval;
2643
2644                 //destination specifier
2645                 inst|=(a0reg<<7);
2646
2647                 //opmode
2648                 inst|=0;
2649
2650                 D_word(inst);
2651         ea1gen(siz);
2652
2653         }
2654         else if (am0<AM_USP&&am1==FREG)
2655         {
2656         //ea->fpx
2657
2658                 //ea
2659                 inst|=am0|a0reg;
2660                 D_word(inst);
2661
2662                 //r/m
2663                 //if (am0==DREG)
2664                         inst=1<<14;
2665                 //else
2666                 //      inst=0;
2667
2668                 //source specifier
2669                 switch (siz)
2670                 {
2671                 case SIZB:      inst |= (6<<10); break;
2672                 case SIZW:      inst |= (4<<10); break;
2673                 case SIZL:      inst |= (0<<10); break;
2674                 case SIZN:
2675                 case SIZS:      inst |= (1<<10); break;
2676                 case SIZD:      inst |= (5<<10); break;
2677                 case SIZX:      inst |= (2<<10); break;
2678                 case SIZP:  inst |= (3<<10); break;
2679                 default: return error("Something bad happened, possibly."); break;
2680                 }
2681
2682                 //destination specifier
2683                 inst|=(a1reg<<7);
2684
2685                 //opmode
2686                 inst|=0;
2687
2688                 D_word(inst);
2689         ea0gen(siz);
2690
2691         }
2692         else if (am0==FREG&&am1==FREG)
2693         {
2694                 //ea
2695                 D_word(inst);
2696
2697                 //r/m
2698                 inst=0<<14;
2699
2700                 //source specifier
2701                 if (siz!=SIZX)
2702                         return error("Invalid size");
2703
2704         //source register
2705                 inst|=(a0reg<<10);
2706
2707         //destination register
2708                 inst|=(a1reg<<7);
2709
2710                 D_word(inst);
2711         }
2712
2713     return OK;
2714         ///////////register to memory
2715         //ea
2716         //destination format
2717         //source register
2718         //k-factor (if required)
2719
2720
2721         //return error("Not implemented yet.");
2722         //return gen_fpu(inst, siz, B8(00101101), FPU_P_EMUL);
2723 }
2724
2725 //
2726 // fmove (6888X, 68040)
2727 //
2728 int m_fmovescr(WORD inst, WORD siz)
2729 {
2730         ///////////Move Floating-Point System Control Register (FPCR)
2731         //ea
2732         //dr
2733         //register select
2734         if (am0==FPSCR&&am1<AM_USP)
2735         {
2736                 inst|=am1|a1reg;
2737                 D_word(inst);
2738                 inst=(1<<13)+(1<<15);
2739                 inst|=a0reg;
2740                 D_word(inst);
2741                 ea1gen(siz);
2742         return OK;
2743         }
2744         else if (am1==FPSCR&&am0<AM_USP)
2745         {
2746                 inst|=am0|a0reg;
2747                 D_word(inst);
2748                 inst=(0<<13)+(1<<15);
2749                 inst|=a1reg;
2750                 D_word(inst);
2751                 ea0gen(siz);
2752         return OK;
2753         }
2754         else
2755             return error("m_fmovescr says: wut?");
2756 }
2757
2758 //
2759 // fsmove/fdmove (68040)
2760 //
2761 int m_fsmove(WORD inst, WORD siz)
2762 {
2763         return error("Not implemented yet.");
2764         if (activefpu == FPU_68040)
2765                 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
2766         else
2767                 return error("Unsupported in current FPU");
2768 }
2769 int m_fdmove(WORD inst, WORD siz)
2770 {
2771         return error("Not implemented yet.");
2772         if (activefpu == FPU_68040)
2773                 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
2774         else
2775                 return error("Unsupported in current FPU");
2776 }
2777 //
2778 // fmovecr (6888X, 68040FPSP)
2779 //
2780 int m_fmovecr(WORD inst, WORD siz)
2781 {
2782         D_word(inst);
2783         inst = 0x5c00;
2784         inst |= a1reg << 7;
2785         inst |= a0exval;
2786         D_word(inst);
2787         if (activefpu == FPU_68040)
2788                 warn("Instruction is emulated in 68040");
2789         return OK;
2790 }
2791
2792 //
2793 // fmovem (6888X, 68040)
2794 //
2795 int m_fmovem(WORD inst, WORD siz)
2796 {
2797     WORD regmask;
2798     WORD datareg;
2799
2800     if (siz == SIZX)
2801     {
2802         if (*tok>=KW_FP0 && *tok<=KW_FP7)
2803         {
2804             //fmovem.x <rlist>,ea
2805                 if (fpu_reglist_left(&regmask) < 0)
2806                     return OK;
2807                 if (*tok++ != ',')
2808                         return error("missing comma");
2809                 if (amode(0) < 0)
2810                         return OK;
2811             inst|=am0|a0reg;
2812                 if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
2813                 return error("invalid addressing mode");
2814             D_word(inst);
2815             inst=((1<<15)|(1<<14))|(1<<13)|(0<<11)|regmask;
2816             D_word(inst);
2817             ea0gen(siz);
2818             return OK;
2819         }
2820         else if (*tok >= KW_D0 && *tok <= KW_D7)
2821         {
2822             //fmovem.x Dn,ea
2823             datareg=(*tok++&7)<<10;
2824                 if (*tok++ != ',')
2825                         return error("missing comma");
2826                 if (amode(0) < 0)
2827                         return OK;
2828             inst|=am0|a0reg;
2829                 if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
2830                 return error("invalid addressing mode");
2831             D_word(inst);
2832             inst=((1<<15)|(1<<14))|(1<<13)|(1<<11)|(datareg<<4);
2833             D_word(inst);
2834             ea0gen(siz);
2835             return OK;
2836         }
2837         else
2838         {
2839             //fmovem.x ea,...
2840                 if (amode(0) < 0)
2841                         return OK;
2842             inst|=am0|a0reg;
2843                 if (*tok++ != ',')
2844                         return error("missing comma");
2845             if (*tok>=KW_FP0 && *tok<=KW_FP7)
2846             {
2847                 //fmovem.x ea,<rlist>
2848                 if (fpu_reglist_right(&regmask) < 0)
2849                     return OK;
2850                 D_word(inst);
2851                 inst=((1<<15)|(1<<14))|(0<<13)|(2<<11)|regmask;
2852                 D_word(inst);
2853                 ea0gen(siz);
2854                 return OK;
2855             }
2856             else
2857             {
2858                 //fmovem.x ea,Dn
2859                 datareg=(*tok++&7)<<10;
2860                 D_word(inst);
2861                 inst=((1<<15)|(1<<14))|(0<<13)|(3<<11)|(datareg<<4);
2862                 D_word(inst);
2863                 ea0gen(siz);
2864                 return OK;
2865             }
2866         }
2867     }
2868     else if (siz == SIZL||siz==SIZN)
2869     {
2870         if (*tok==KW_FPCR || *tok==KW_FPSR || *tok==KW_FPIAR)
2871         {
2872             //fmovem.l <rlist>,ea
2873             regmask=(1<<15)|(1<<13);
2874 fmovem_loop_1:
2875             if (*tok==KW_FPCR)
2876             {
2877                 regmask|=(1<<12);
2878                 tok++;
2879                 goto fmovem_loop_1;
2880             }
2881             if (*tok==KW_FPSR)
2882             {
2883                 regmask|=(1<<11);
2884                 tok++;
2885                 goto fmovem_loop_1;
2886             }
2887             if (*tok==KW_FPIAR)
2888             {
2889                 regmask|=(1<<10);
2890                 tok++;
2891                 goto fmovem_loop_1;
2892             }
2893             if (*tok=='/' || *tok=='-')
2894             {
2895                 tok++;
2896                 goto fmovem_loop_1;
2897             }
2898                 if (*tok++ != ',')
2899                         return error("missing comma");
2900             if (amode(0) < 0)
2901                         return OK;
2902             inst|=am0|a0reg;
2903             D_word(inst);
2904             D_word(regmask);
2905             ea0gen(siz);
2906         }
2907         else
2908         {
2909             //fmovem.l ea,<rlist>
2910             if (amode(0) < 0)
2911                         return OK;
2912             inst|=am0|a0reg;
2913                 if (*tok++ != ',')
2914                         return error("missing comma");
2915             regmask=(1<<15)|(0<<13);
2916 fmovem_loop_2:
2917             if (*tok==KW_FPCR)
2918             {
2919                 regmask|=(1<<12);
2920                 tok++;
2921                 goto fmovem_loop_2;
2922             }
2923             if (*tok==KW_FPSR)
2924             {
2925                 regmask|=(1<<11);
2926                 tok++;
2927                 goto fmovem_loop_2;
2928             }
2929             if (*tok==KW_FPIAR)
2930             {
2931                 regmask|=(1<<10);
2932                 tok++;
2933                 goto fmovem_loop_2;
2934             }
2935             if (*tok=='/' || *tok=='-')
2936             {
2937                 tok++;
2938                 goto fmovem_loop_2;
2939             }
2940             if (*tok!=EOL)
2941                 return error("extra (unexpected) text found");
2942             inst|=am0|a0reg;
2943             D_word(inst);
2944             D_word(regmask);
2945             ea0gen(siz);
2946         }
2947     }
2948     else
2949                 return error("bad size suffix");
2950
2951     return OK;
2952 }
2953
2954 //
2955 // fmul (6888X, 68040)
2956 //
2957 int m_fmul(WORD inst, WORD siz)
2958 {
2959         return gen_fpu(inst, siz, B8(00100011), FPU_P_EMUL);
2960 }
2961 int m_fsmul(WORD inst, WORD siz)
2962 {
2963         if (activefpu == FPU_68040)
2964                 return gen_fpu(inst, siz, B8(01100011), FPU_P_EMUL);
2965         else
2966                 return error("Unsupported in current FPU");
2967 }
2968 int m_fdmul(WORD inst, WORD siz)
2969 {
2970         if (activefpu == FPU_68040)
2971                 return gen_fpu(inst, siz, B8(01100111), FPU_P_EMUL);
2972         else
2973                 return error("Unsupported in current FPU");
2974 }
2975
2976 //
2977 // fneg (6888X, 68040)
2978 //
2979 int m_fneg(WORD inst, WORD siz)
2980 {
2981         return gen_fpu(inst, siz, B8(00011010), FPU_P_EMUL);
2982 }
2983 int m_fsneg(WORD inst, WORD siz)
2984 {
2985         if (activefpu == FPU_68040)
2986                 return gen_fpu(inst, siz, B8(01011010), FPU_P_EMUL);
2987         else
2988                 return error("Unsupported in current FPU");
2989 }
2990 int m_fdneg(WORD inst, WORD siz)
2991 {
2992         if (activefpu == FPU_68040)
2993                 return gen_fpu(inst, siz, B8(01011110), FPU_P_EMUL);
2994         else
2995                 return error("Unsupported in current FPU");
2996 }
2997
2998 //
2999 // fnop (6888X, 68040)
3000 //
3001 int m_fnop(WORD inst, WORD siz)
3002 {
3003         return gen_fpu(inst, siz, B8(00000000), FPU_P_EMUL);
3004 }
3005
3006 //
3007 // frem (6888X, 68040FPSP)
3008 //
3009 int m_frem(WORD inst, WORD siz)
3010 {
3011         return gen_fpu(inst, siz, B8(00100101), FPU_FPSP);
3012 }
3013
3014 //
3015 // fscale (6888X, 68040FPSP)
3016 //
3017 int m_fscale(WORD inst, WORD siz)
3018 {
3019         return gen_fpu(inst, siz, B8(00100110), FPU_FPSP);
3020 }
3021
3022 //
3023 // FScc (6888X, 68040)
3024 //
3025 int m_fseq  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000001)); return OK;}
3026 int m_fsne  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001110)); return OK;}
3027 int m_fsgt  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010010)); return OK;}
3028 int m_fsngt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011101)); return OK;}
3029 int m_fsge  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010011)); return OK;}
3030 int m_fsnge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011100)); return OK;}
3031 int m_fslt  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010100)); return OK;}
3032 int m_fsnlt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011011)); return OK;}
3033 int m_fsle  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010101)); return OK;}
3034 int m_fsnle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011010)); return OK;}
3035 int m_fsgl  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010110)); return OK;}
3036 int m_fsngl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011001)); return OK;}
3037 int m_fsgle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010111)); return OK;}
3038 int m_fsngle(WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011000)); return OK;}
3039 int m_fsogt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000010)); return OK;}
3040 int m_fsule (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001101)); return OK;}
3041 int m_fsoge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000011)); return OK;}
3042 int m_fsult (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001100)); return OK;}
3043 int m_fsolt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000100)); return OK;}
3044 int m_fsuge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001011)); return OK;}
3045 int m_fsole (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000101)); return OK;}
3046 int m_fsugt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001010)); return OK;}
3047 int m_fsogl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000110)); return OK;}
3048 int m_fsueq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001001)); return OK;}
3049 int m_fsor  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000111)); return OK;}
3050 int m_fsun  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001000)); return OK;}
3051 int m_fsf   (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000000)); return OK;}
3052 int m_fst   (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001111)); return OK;}
3053 int m_fssf  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010000)); return OK;}
3054 int m_fsst  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011111)); return OK;}
3055 int m_fsseq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010001)); return OK;}
3056 int m_fssne (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011110)); return OK;}
3057
3058 //
3059 // FTRAPcc (6888X, 68040)
3060 //
3061
3062 int m_ftrapeq  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000001)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000001)); D_long(a0exval); } return OK;}
3063 int m_ftrapne  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001110)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001110)); D_long(a0exval); } return OK;}
3064 int m_ftrapgt  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010010)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010010)); D_long(a0exval); } return OK;}
3065 int m_ftrapngt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011101)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011101)); D_long(a0exval); } return OK;}
3066 int m_ftrapge  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010011)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010011)); D_long(a0exval); } return OK;}
3067 int m_ftrapnge (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011100)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011100)); D_long(a0exval); } return OK;}
3068 int m_ftraplt  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010100)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010100)); D_long(a0exval); } return OK;}
3069 int m_ftrapnlt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011011)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011011)); D_long(a0exval); } return OK;}
3070 int m_ftraple  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010101)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010101)); D_long(a0exval); } return OK;}
3071 int m_ftrapnle (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011010)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011010)); D_long(a0exval); } return OK;}
3072 int m_ftrapgl  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010110)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010110)); D_long(a0exval); } return OK;}
3073 int m_ftrapngl (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011001)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011001)); D_long(a0exval); } return OK;}
3074 int m_ftrapgle (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010111)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010111)); D_long(a0exval); } return OK;}
3075 int m_ftrapngle(WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011000)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011000)); D_long(a0exval); } return OK;}
3076 int m_ftrapogt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000010)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000010)); D_long(a0exval); } return OK;}
3077 int m_ftrapule (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001101)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001101)); D_long(a0exval); } return OK;}
3078 int m_ftrapoge (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000011)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000011)); D_long(a0exval); } return OK;}
3079 int m_ftrapult (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001100)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001100)); D_long(a0exval); } return OK;}
3080 int m_ftrapolt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000100)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000100)); D_long(a0exval); } return OK;}
3081 int m_ftrapuge (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001011)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001011)); D_long(a0exval); } return OK;}
3082 int m_ftrapole (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000101)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000101)); D_long(a0exval); } return OK;}
3083 int m_ftrapugt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001010)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001010)); D_long(a0exval); } return OK;}
3084 int m_ftrapogl (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000110)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000110)); D_long(a0exval); } return OK;}
3085 int m_ftrapueq (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001001)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001001)); D_long(a0exval); } return OK;}
3086 int m_ftrapor  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000111)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000111)); D_long(a0exval); } return OK;}
3087 int m_ftrapun  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001000)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001000)); D_long(a0exval); } return OK;}
3088 int m_ftrapf   (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000000)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000000)); D_long(a0exval); } return OK;}
3089 int m_ftrapt   (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001111)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001111)); D_long(a0exval); } return OK;}
3090 int m_ftrapsf  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010000)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010000)); D_long(a0exval); } return OK;}
3091 int m_ftrapst  (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011111)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011111)); D_long(a0exval); } return OK;}
3092 int m_ftrapseq (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010001)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010001)); D_long(a0exval); } return OK;}
3093 int m_ftrapsne (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011110)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011110)); D_long(a0exval); } return OK;}
3094
3095 int m_ftrapeqn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000001)); return OK;}
3096 int m_ftrapnen  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001110)); return OK;}
3097 int m_ftrapgtn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010010)); return OK;}
3098 int m_ftrapngtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011101)); return OK;}
3099 int m_ftrapgen  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010011)); return OK;}
3100 int m_ftrapngen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011100)); return OK;}
3101 int m_ftrapltn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010100)); return OK;}
3102 int m_ftrapnltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011011)); return OK;}
3103 int m_ftraplen  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010101)); return OK;}
3104 int m_ftrapnlen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011010)); return OK;}
3105 int m_ftrapgln  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010110)); return OK;}
3106 int m_ftrapngln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011001)); return OK;}
3107 int m_ftrapglen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010111)); return OK;}
3108 int m_ftrapnglen(WORD inst, WORD siz) { D_word(inst); D_word(B8(00011000)); return OK;}
3109 int m_ftrapogtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000010)); return OK;}
3110 int m_ftrapulen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001101)); return OK;}
3111 int m_ftrapogen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000011)); return OK;}
3112 int m_ftrapultn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001100)); return OK;}
3113 int m_ftrapoltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000100)); return OK;}
3114 int m_ftrapugen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001011)); return OK;}
3115 int m_ftrapolen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000101)); return OK;}
3116 int m_ftrapugtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001010)); return OK;}
3117 int m_ftrapogln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000110)); return OK;}
3118 int m_ftrapueqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001001)); return OK;}
3119 int m_ftraporn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000111)); return OK;}
3120 int m_ftrapunn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001000)); return OK;}
3121 int m_ftrapfn   (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000000)); return OK;}
3122 int m_ftraptn   (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001111)); return OK;}
3123 int m_ftrapsfn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010000)); return OK;}
3124 int m_ftrapstn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011111)); return OK;}
3125 int m_ftrapseqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010001)); return OK;}
3126 int m_ftrapsnen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011110)); return OK;}
3127
3128
3129 //
3130 // fsgldiv (6888X, 68040)
3131 //
3132 int m_fsgldiv(WORD inst, WORD siz)
3133 {
3134         return gen_fpu(inst, siz, B8(00100100), FPU_P_EMUL);
3135 }
3136
3137 //
3138 // fsglmul (6888X, 68040)
3139 //
3140 int m_fsglmul(WORD inst, WORD siz)
3141 {
3142         return gen_fpu(inst, siz, B8(00100111), FPU_P_EMUL);
3143 }
3144
3145 //
3146 // fsin (6888X, 68040FPSP)
3147 //
3148 int m_fsin(WORD inst, WORD siz)
3149 {
3150         return gen_fpu(inst, siz, B8(00001110), FPU_FPSP);
3151 }
3152
3153 //
3154 // fsincos (6888X, 68040FPSP)
3155 //
3156 int m_fsincos(WORD inst, WORD siz)
3157 {
3158     int temp;
3159         if (gen_fpu(inst, siz, B8(00110000), FPU_FPSP)==OK)
3160         {
3161                 chptr[-1] |= a2reg;
3162                 return OK;
3163         }
3164         else
3165                 return ERROR;
3166 }
3167
3168 //
3169 // fsin (6888X, 68040FPSP)
3170 //
3171 int m_fsinh(WORD inst, WORD siz)
3172 {
3173         return gen_fpu(inst, siz, B8(00000010), FPU_FPSP);
3174 }
3175
3176 //
3177 // fsqrt (6888X, 68040)
3178 //
3179 int m_fsqrt(WORD inst, WORD siz)
3180 {
3181         return gen_fpu(inst, siz, B8(00000100), FPU_P_EMUL);
3182 }
3183 int m_fsfsqrt(WORD inst, WORD siz)
3184 {
3185         if (activefpu == FPU_68040)
3186                 return gen_fpu(inst, siz, B8(01000001), FPU_P_EMUL);
3187         else
3188                 return error("Unsupported in current FPU");
3189 }
3190 int m_fdfsqrt(WORD inst, WORD siz)
3191 {
3192         if (activefpu == FPU_68040)
3193                 return gen_fpu(inst, siz, B8(01000101), FPU_P_EMUL);
3194         else
3195                 return error("Unsupported in current FPU");
3196 }
3197
3198 //
3199 // fsub (6888X, 68040)
3200 //
3201 int m_fsub(WORD inst, WORD siz)
3202 {
3203         return gen_fpu(inst, siz, B8(00101000), FPU_P_EMUL);
3204 }
3205 int m_fsfsub(WORD inst, WORD siz)
3206 {
3207         if (activefpu == FPU_68040)
3208                 return gen_fpu(inst, siz, B8(01101000), FPU_P_EMUL);
3209         else
3210                 return error("Unsupported in current FPU");
3211 }
3212 int m_fdsub(WORD inst, WORD siz)
3213 {
3214         if (activefpu == FPU_68040)
3215                 return gen_fpu(inst, siz, B8(01101100), FPU_P_EMUL);
3216         else
3217                 return error("Unsupported in current FPU");
3218 }
3219
3220 //
3221 // ftan (6888X, 68040FPSP)
3222 //
3223 int m_ftan(WORD inst, WORD siz)
3224 {
3225         return gen_fpu(inst, siz, B8(00001111), FPU_FPSP);
3226 }
3227
3228 //
3229 // ftanh (6888X, 68040FPSP)
3230 //
3231 int m_ftanh(WORD inst, WORD siz)
3232 {
3233         return gen_fpu(inst, siz, B8(00001001), FPU_FPSP);
3234 }
3235
3236 //
3237 // ftentox (6888X, 68040FPSP)
3238 //
3239 int m_ftentox(WORD inst, WORD siz)
3240 {
3241         return gen_fpu(inst, siz, B8(00010010), FPU_FPSP);
3242 }
3243
3244 //
3245 // ftst (6888X, 68040)
3246 //
3247 int m_ftst(WORD inst, WORD siz)
3248 {
3249         return gen_fpu(inst, siz, B8(00111010), FPU_P_EMUL);
3250 }
3251
3252 //
3253 // ftwotox (6888X, 68040FPSP)
3254 //
3255 int m_ftwotox(WORD inst, WORD siz)
3256 {
3257         return gen_fpu(inst, siz, B8(00010001), FPU_FPSP);
3258 }
3259