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