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