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