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