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