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