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