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