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