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