]> Shamusworld >> Repos - rmac/blob - mach.c
Fix for bug #101 (bad macro handling).
[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         LONG amsk;
1413
1414         if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1415                 return error(unsupport);
1416
1417         switch (siz)
1418         {
1419         case SIZB:
1420                 inst |= 1 << 9;
1421                 break;
1422         case SIZW:
1423         case SIZN:
1424                 inst |= 2 << 9;
1425                 break;
1426         case SIZL:
1427                 inst |= 3 << 9;
1428                 break;
1429         default:
1430                 return error("bad size suffix");
1431                 break;
1432         }
1433
1434         // Dc1
1435         if ((*tok < KW_D0) && (*tok > KW_D7))
1436                 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1437
1438         inst2 = (*tok++) & 7;
1439
1440         if (*tok++ != ':')
1441                 return error("missing colon");
1442
1443         // Dc2
1444         if ((*tok < KW_D0) && (*tok > KW_D7))
1445                 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1446
1447         inst3 = (*tok++) & 7;
1448
1449         if (*tok++ != ',')
1450                 return error("missing comma");
1451
1452         // Du1
1453         if ((*tok < KW_D0) && (*tok > KW_D7))
1454                 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1455
1456         inst2 |= ((*tok++) & 7) << 6;
1457
1458         if (*tok++ != ':')
1459                 return error("missing colon");
1460
1461         // Du2
1462         if ((*tok < KW_D0) && (*tok > KW_D7))
1463                 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1464
1465         inst3 |= ((*tok++) & 7) << 6;
1466
1467         if (*tok++ != ',')
1468                 return error("missing comma");
1469
1470         // Rn1
1471         if (*tok++ != '(')
1472                 return error("missing (");
1473         if ((*tok >= KW_D0) && (*tok <= KW_D7))
1474                 inst2 |= (((*tok++) & 7) << 12) | (0 << 15);
1475         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
1476                 inst2 |= (((*tok++) & 7) << 12) | (1 << 15);
1477         else
1478                 return error("CAS accepts either data or address registers for Rn1:Rn2 pair");
1479
1480         if (*tok++ != ')')
1481                 return error("missing (");
1482
1483         if (*tok++ != ':')
1484                 return error("missing colon");
1485
1486         // Rn2
1487         if (*tok++ != '(')
1488                 return error("missing (");
1489         if ((*tok >= KW_D0) && (*tok <= KW_D7))
1490                 inst3 |= (((*tok++) & 7) << 12) | (0 << 15);
1491         else if ((*tok >= KW_A0) && (*tok <= KW_A7))
1492                 inst3 |= (((*tok++) & 7) << 12) | (1 << 15);
1493         else
1494                 return error("CAS accepts either data or address registers for Rn1:Rn2 pair");
1495
1496         if (*tok++ != ')')
1497                 return error("missing (");
1498
1499         if (*tok != EOL)
1500                 return error("extra (unexpected) text found");
1501
1502         D_word(inst);
1503         D_word(inst2);
1504         D_word(inst3);
1505
1506         return OK;
1507 }
1508
1509
1510 //
1511 // cmp2 (68020, 68030, 68040, CPU32)
1512 //
1513 int m_cmp2(WORD inst, WORD siz)
1514 {
1515         if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1516                 return error(unsupport);
1517
1518         switch (siz & 0x000F)
1519         {
1520         case SIZW:
1521         case SIZN:
1522                 inst |= 1 << 9;
1523                 break;
1524         case SIZL:
1525                 inst |= 2 << 9;
1526                 break;
1527         default:
1528                 // SIZB
1529                 break;
1530         }
1531
1532         WORD flg = inst;                                        // Save flag bits
1533         inst &= ~0x3F;                                          // Clobber flag bits in instr
1534
1535         // Install "standard" instr size bits
1536         if (flg & 4)
1537                 inst |= siz_6[siz];
1538
1539         if (flg & 16)
1540         {
1541                 // OR-in register number
1542                 if (flg & 8)
1543                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11
1544                 else
1545                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11
1546         }
1547
1548         if (flg & 1)
1549         {
1550                 // Use am1
1551                 inst |= am1 | a1reg;                    // Get ea1 into instr
1552                 D_word(inst);                                   // Deposit instr
1553
1554                 // Generate ea0 if requested
1555                 if (flg & 2)
1556                         ea0gen(siz);
1557
1558                 ea1gen(siz);                                    // Generate ea1
1559         }
1560         else
1561         {
1562                 // Use am0
1563                 inst |= am0 | a0reg;                    // Get ea0 into instr
1564                 D_word(inst);                                   // Deposit instr
1565                 ea0gen(siz);                                    // Generate ea0
1566
1567                 // Generate ea1 if requested
1568                 if (flg & 2)
1569                         ea1gen(siz);
1570         }
1571
1572         // If we're called from chk2 then bit 11 of size will be set. This is just
1573         // a dumb mechanism to pass this, required by the extension word. (You might
1574         // have noticed the siz & 15 thing above!)
1575         inst = (a1reg << 12) | (siz & (1 << 11));
1576
1577         if (am1 == AREG)
1578                 inst |= 1 << 15;
1579
1580         D_word(inst);
1581
1582         return OK;
1583 }
1584
1585
1586 //
1587 // chk2 (68020, 68030, 68040, CPU32)
1588 //
1589 int m_chk2(WORD inst, WORD siz)
1590 {
1591         return m_cmp2(inst, siz | (1 << 11));
1592 }
1593
1594
1595 //
1596 // cpbcc(68020, 68030)
1597 //
1598 int m_cpbr(WORD inst, WORD siz)
1599 {
1600         if ((activecpu & (CPU_68020 | CPU_68030)) == 0)
1601                 return error(unsupport);
1602
1603         if (a0exattr & DEFINED)
1604         {
1605                 if ((a0exattr & TDB) != cursect)
1606                         return error(rel_error);
1607
1608                 VALUE v = a0exval - (sloc + 2);
1609
1610                 // Optimize branch instr. size
1611                 if (siz == SIZL)
1612                 {
1613                         if ((v != 0) && ((v + 0x8000) < 0x10000))
1614                         {
1615                                 inst |= (1 << 6);
1616                                 D_word(inst);
1617                                 WARNING(check what s "optional coprocessor-defined extension words!")
1618                                 D_long(v);
1619                                 return OK;
1620                         }
1621                 }
1622         else // SIZW/SIZN
1623                 {
1624                         if ((v + 0x8000) >= 0x10000)
1625                                 return error(range_error);
1626
1627                         D_word(inst);
1628                         WARNING(check what s "optional coprocessor-defined extension words!")
1629                         D_word(v);
1630                 }
1631
1632                 return OK;
1633         }
1634         else if (siz == SIZN)
1635                 siz = SIZW;
1636
1637         if (siz == SIZL)
1638         {
1639                 // .L
1640         D_word(inst);
1641         AddFixup(FU_LONG | FU_PCREL | FU_SEXT, sloc, a0expr);
1642         D_long(0);
1643                 return OK;
1644         }
1645         else
1646         {
1647                 // .W
1648                 D_word(inst);
1649                 AddFixup(FU_WORD | FU_PCREL | FU_SEXT, sloc, a0expr);
1650                 D_word(0);
1651         }
1652
1653         return OK;
1654 }
1655
1656
1657 //
1658 // cpdbcc(68020, 68030)
1659 //
1660 int m_cpdbr(WORD inst, WORD siz)
1661 {
1662         if ((activecpu & (CPU_68020 | CPU_68030)) == 0)
1663                 return error(unsupport);
1664
1665         return error("Not implemented yet.");
1666
1667         //return OK;
1668 }
1669
1670
1671 //
1672 // divs.l
1673 //
1674 int m_divs(WORD inst, WORD siz)
1675 {
1676         if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1677                 return error(unsupport);
1678
1679         WORD flg = inst;                                        // Save flag bits
1680         inst &= ~0x3F;                                          // Clobber flag bits in instr
1681
1682         // Install "standard" instr size bits
1683         if (flg & 4)
1684                 inst |= siz_6[siz];
1685
1686         if (flg & 16)
1687         {
1688                 // OR-in register number
1689                 if (flg & 8)
1690                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11
1691                 else
1692                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11
1693         }
1694
1695         if (flg & 1)
1696         {
1697                 // Use am1
1698                 inst |= am1 | a1reg;                    // Get ea1 into instr
1699                 D_word(inst);                                   // Deposit instr
1700
1701                 // Generate ea0 if requested
1702                 if (flg & 2)
1703                         ea0gen(siz);
1704
1705                 ea1gen(siz);                                    // Generate ea1
1706         }
1707         else
1708         {
1709                 // Use am0
1710                 inst |= am0 | a0reg;                    // Get ea0 into instr
1711                 D_word(inst);                                   // Deposit instr
1712                 ea0gen(siz);                                    // Generate ea0
1713
1714                 // Generate ea1 if requested
1715                 if (flg & 2)
1716                         ea1gen(siz);
1717         }
1718
1719         inst = a1reg + (a2reg << 12) + (1 << 11);
1720         D_word(inst);
1721
1722         return OK;
1723 }
1724
1725
1726 //
1727 // muls.l
1728 //
1729 int m_muls(WORD inst, WORD siz)
1730 {
1731         if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1732                 return error(unsupport);
1733
1734         WORD flg = inst;                                        // Save flag bits
1735         inst &= ~0x3F;                                          // Clobber flag bits in instr
1736
1737         // Install "standard" instr size bits
1738         if (flg & 4)
1739                 inst |= siz_6[siz];
1740
1741         if (flg & 16)
1742         {
1743                 // OR-in register number
1744                 if (flg & 8)
1745                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11
1746                 else
1747                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11
1748         }
1749
1750         if (flg & 1)
1751         {
1752                 // Use am1
1753                 inst |= am1 | a1reg;                    // Get ea1 into instr
1754                 D_word(inst);                                   // Deposit instr
1755
1756                 // Generate ea0 if requested
1757                 if (flg & 2)
1758                         ea0gen(siz);
1759
1760                 ea1gen(siz);                                    // Generate ea1
1761         }
1762         else
1763         {
1764                 // Use am0
1765                 inst |= am0 | a0reg;                    // Get ea0 into instr
1766                 D_word(inst);                                   // Deposit instr
1767                 ea0gen(siz);                                    // Generate ea0
1768
1769                 // Generate ea1 if requested
1770                 if (flg & 2)
1771                         ea1gen(siz);
1772         }
1773
1774         inst = a1reg + (a2reg << 12) + (1 << 11);
1775         inst |= mulmode;  // add size bit
1776         D_word(inst);
1777
1778         return OK;
1779 }
1780
1781
1782 //
1783 // divu.l
1784 //
1785 int m_divu(WORD inst, WORD siz)
1786 {
1787         if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1788                 return error(unsupport);
1789
1790         //WARNING("divu.l d0,d1 is actually divul.l d0,d1:d1!!!")
1791
1792         WORD flg = inst;                                        // Save flag bits
1793         inst &= ~0x3F;                                          // Clobber flag bits in instr
1794
1795         // Install "standard" instr size bits
1796         if (flg & 4)
1797                 inst |= siz_6[siz];
1798
1799         if (flg & 16)
1800         {
1801                 // OR-in register number
1802                 if (flg & 8)
1803                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11
1804                 else
1805                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11
1806         }
1807
1808         if (flg & 1)
1809         {
1810                 // Use am1
1811                 inst |= am1 | a1reg;                    // Get ea1 into instr
1812                 D_word(inst);                                   // Deposit instr
1813
1814                 // Generate ea0 if requested
1815                 if (flg & 2)
1816                         ea0gen(siz);
1817
1818                 ea1gen(siz);                                    // Generate ea1
1819         }
1820         else
1821         {
1822                 // Use am0
1823                 inst |= am0 | a0reg;                    // Get ea0 into instr
1824                 D_word(inst);                                   // Deposit instr
1825                 ea0gen(siz);                                    // Generate ea0
1826
1827                                                                                 // Generate ea1 if requested
1828                 if (flg & 2)
1829                         ea1gen(siz);
1830         }
1831
1832         inst = a1reg + (a2reg << 12);
1833         D_word(inst);
1834
1835         return OK;
1836 }
1837
1838
1839 //
1840 // mulu.l
1841 //
1842 int m_mulu(WORD inst, WORD siz)
1843 {
1844         if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1845                 return error(unsupport);
1846
1847         WORD flg = inst;                                        // Save flag bits
1848         inst &= ~0x3F;                                          // Clobber flag bits in instr
1849
1850         // Install "standard" instr size bits
1851         if (flg & 4)
1852                 inst |= siz_6[siz];
1853
1854         if (flg & 16)
1855         {
1856                 // OR-in register number
1857                 if (flg & 8)
1858                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11
1859                 else
1860                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11
1861         }
1862
1863         if (flg & 1)
1864         {
1865                 // Use am1
1866                 inst |= am1 | a1reg;                    // Get ea1 into instr
1867                 D_word(inst);                                   // Deposit instr
1868
1869                 // Generate ea0 if requested
1870                 if (flg & 2)
1871                         ea0gen(siz);
1872
1873                 ea1gen(siz);                                    // Generate ea1
1874         }
1875         else
1876         {
1877                 // Use am0
1878                 inst |= am0 | a0reg;                    // Get ea0 into instr
1879                 D_word(inst);                                   // Deposit instr
1880                 ea0gen(siz);                                    // Generate ea0
1881
1882                 // Generate ea1 if requested
1883                 if (flg & 2)
1884                         ea1gen(siz);
1885         }
1886
1887         inst = a1reg + (a2reg << 12);
1888     inst |= mulmode;  // add size bit
1889         D_word(inst);
1890
1891         return OK;
1892 }
1893
1894
1895 //
1896 // divsl.l
1897 //
1898 int m_divsl(WORD inst, WORD siz)
1899 {
1900         if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1901                 return error(unsupport);
1902
1903         WORD flg = inst;                                        // Save flag bits
1904         inst &= ~0x3F;                                          // Clobber flag bits in instr
1905
1906         // Install "standard" instr size bits
1907         if (flg & 4)
1908                 inst |= siz_6[siz];
1909
1910         if (flg & 16)
1911         {
1912                 // OR-in register number
1913                 if (flg & 8)
1914                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11
1915                 else
1916                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11
1917         }
1918
1919         if (flg & 1)
1920         {
1921                 // Use am1
1922                 inst |= am1 | a1reg;                    // Get ea1 into instr
1923                 D_word(inst);                                   // Deposit instr
1924
1925                 // Generate ea0 if requested
1926                 if (flg & 2)
1927                         ea0gen(siz);
1928
1929                 ea1gen(siz);                                    // Generate ea1
1930         }
1931         else
1932         {
1933                 // Use am0
1934                 inst |= am0 | a0reg;                    // Get ea0 into instr
1935                 D_word(inst);                                   // Deposit instr
1936                 ea0gen(siz);                                    // Generate ea0
1937
1938                 // Generate ea1 if requested
1939                 if (flg & 2)
1940                         ea1gen(siz);
1941         }
1942
1943         inst = a1reg + (a2reg << 12) + (1 << 11) + (1 << 10);
1944         D_word(inst);
1945
1946         return OK;
1947 }
1948
1949 //
1950 // divul.l
1951 //
1952 int m_divul(WORD inst, WORD siz)
1953 {
1954         if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1955                 return error(unsupport);
1956
1957         WORD flg = inst;                                        // Save flag bits
1958         inst &= ~0x3F;                                          // Clobber flag bits in instr
1959
1960         // Install "standard" instr size bits
1961         if (flg & 4)
1962                 inst |= siz_6[siz];
1963
1964         if (flg & 16)
1965         {
1966                 // OR-in register number
1967                 if (flg & 8)
1968                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11
1969                 else
1970                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11
1971         }
1972
1973         if (flg & 1)
1974         {
1975                 // Use am1
1976                 inst |= am1 | a1reg;                    // Get ea1 into instr
1977                 D_word(inst);                                   // Deposit instr
1978
1979                 // Generate ea0 if requested
1980                 if (flg & 2)
1981                         ea0gen(siz);
1982
1983                 ea1gen(siz);                                    // Generate ea1
1984         }
1985         else
1986         {
1987                 // Use am0
1988                 inst |= am0 | a0reg;                    // Get ea0 into instr
1989                 D_word(inst);                                   // Deposit instr
1990                 ea0gen(siz);                                    // Generate ea0
1991
1992                 // Generate ea1 if requested
1993                 if (flg & 2)
1994                         ea1gen(siz);
1995         }
1996
1997         inst = a1reg + (a2reg << 12) + (1 << 10);
1998         D_word(inst);
1999
2000         return OK;
2001 }
2002
2003
2004 //
2005 // move16 (ax)+,(ay)+
2006 //
2007 int m_move16a(WORD inst, WORD siz)
2008 {
2009         if ((activecpu & (CPU_68040 | CPU_68060)) == 0)
2010                 return error(unsupport);
2011
2012         inst |= a0reg;
2013         D_word(inst);
2014         inst = (1 << 15) + (a1reg << 12);
2015         D_word(inst);
2016
2017         return OK;
2018 }
2019
2020
2021 //
2022 // move16 with absolute address
2023 //
2024 int m_move16b(WORD inst, WORD siz)
2025 {
2026         if ((activecpu & (CPU_68040 | CPU_68060)) == 0)
2027                 return error(unsupport);
2028
2029         int v;
2030         inst |= a1reg;
2031         D_word(inst);
2032
2033         if (am0 == APOSTINC)
2034         {
2035                 if (am1 == AIND)
2036                         return error("Wasn't this suppose to call m_move16a???");
2037                 else
2038                 {
2039                         //move16 (ax)+,(xxx).L
2040                         inst |= 0 << 3;
2041                         v = a1exval;
2042                 }
2043         }
2044         else if (am0 == ABSL)
2045         {
2046                 if (am1 == AIND)
2047                 {
2048                         //move16 (xxx).L,(ax)+
2049                         inst |= 1 << 3;
2050                         v = a0exval;
2051                 }
2052                 else //APOSTINC
2053                 {
2054                         //move16 (xxx).L,(ax)
2055                         inst |= 3 << 3;
2056                         v = a0exval;
2057                 }
2058         }
2059         else if (am0 == AIND)
2060         {
2061                 //move16 (ax),(xxx).L
2062                 inst |= 2 << 3;
2063                 v = a1exval;
2064         }
2065
2066         D_word(inst);
2067         D_long(v);
2068
2069         return OK;
2070 }
2071
2072
2073 //
2074 // pack/unpack
2075 //
2076 int m_pack(WORD inst, WORD siz)
2077 {
2078         if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
2079                 return error(unsupport);
2080
2081         WARNING(Parsing stuff by hand here might be better)
2082
2083 #if 0
2084         if ((am0 == DREG) && (am1 == DREG))
2085         {
2086                 inst |= (1 << 3) + (a0reg << 9) + (a1reg);
2087         }
2088         else if ((am0 == APREDEC) && (am1 == APREDEC))
2089         {
2090                 inst |= (a0reg << 9) + (a1reg);
2091         }
2092         else
2093                 return error("Only allowed combinations for pack/unpack are -(ax),-(ay) and dx,dy.");
2094
2095         D_word(inst);
2096 #endif
2097
2098         return OK;
2099 }
2100
2101
2102 //
2103 // rtm Rn
2104 //
2105 int m_rtm(WORD inst, WORD siz)
2106 {
2107         CHECKNO20;
2108
2109         if (am0 == DREG)
2110         {
2111                 inst |= a0reg;
2112         }
2113         else if (am0 == AREG)
2114         {
2115                 inst |= (1 << 3) + a0reg;
2116         }
2117         else
2118                 return error("rtm only allows data or address registers.");
2119
2120         D_word(inst);
2121
2122         return OK;
2123 }
2124
2125
2126 //
2127 // rtd #n
2128 //
2129 int m_rtd(WORD inst, WORD siz)
2130 {
2131         CHECK00;
2132
2133         if (a0exattr & DEFINED)
2134         {
2135                 if (a0exattr & TDB)
2136                         return error(abs_error);
2137
2138                 if ((a0exval + 0x8000) <= 0x7FFF)
2139                         return error(range_error);
2140
2141                 D_word(inst);
2142                 D_word(a0exval);
2143         }
2144         else
2145                 return error(undef_error);
2146
2147         return OK;
2148 }
2149
2150
2151 //
2152 // trapcc
2153 //
2154 int m_trapcc(WORD inst, WORD siz)
2155 {
2156         CHECK00;
2157
2158         if (am0 == AM_NONE)
2159         {
2160                 D_word(inst);
2161         }
2162         else if (am0 == IMMED)
2163         {
2164                 if (siz == SIZW)
2165                 {
2166                         if (a0exval < 0x10000)
2167                         {
2168                                 inst |= 2;
2169                                 D_word(inst);
2170                                 D_word(a0exval);
2171                         }
2172                         else
2173                                 return error("Immediate value too big");
2174                 }
2175                 else //DOTL
2176                 {
2177                         inst |= 3;
2178                         D_word(inst);
2179                         D_long(a0exval);
2180                 }
2181         }
2182         else
2183                 return error("Invalid parameter for trapcc");
2184
2185         return OK;
2186 }
2187
2188
2189 //
2190 // cinv (68040)
2191 //
2192 int m_cinv(WORD inst, WORD siz)
2193 {
2194         CHECKNO40;
2195         WARNING("cinvl ,(an) / cinvp ,(an) / cinva should work!")
2196
2197         if (am0 == AM_NONE)
2198                 inst |= (0 << 6) | (a1reg);
2199         else if (am0 == KW_IC40)
2200                 inst |= (2 << 6) | (a1reg);
2201         else if (am0 == KW_DC40)
2202                 inst |= (1 << 6) | (a1reg);
2203         else if (am0 == KW_BC40)
2204                 inst |= (3 << 6) | (a1reg);
2205
2206         D_word(inst);
2207         return OK;
2208 }
2209
2210
2211 //
2212 // cpRESTORE (68020, 68030)
2213 //
2214 int m_cprest(WORD inst, WORD siz)
2215 {
2216         if (activecpu & !(CPU_68020 | CPU_68030))
2217                 return error(unsupport);
2218
2219         inst |= am0 | a0reg;
2220         D_word(inst);
2221         ea0gen(siz);
2222
2223         return OK;
2224 }
2225
2226
2227 //
2228 // movec (68010, 68020, 68030, 68040, CPU32)
2229 //
2230 int m_movec(WORD inst, WORD siz)
2231 {
2232         CHECK00;
2233
2234         if (am0 == DREG || am0 == AREG)
2235         {
2236                 // movec Rn,Rc
2237                 inst |= 1;
2238                 D_word(inst);
2239
2240                 if (am0 == DREG)
2241                 {
2242                         inst = (0 << 15) + (a0reg << 12) + CREGlut[a1reg];
2243                         D_word(inst);
2244                 }
2245                 else
2246                 {
2247                         inst = (1 << 15) + (a0reg << 12) + CREGlut[a1reg];
2248                         D_word(inst);
2249                 }
2250         }
2251         else
2252         {
2253                 // movec Rc,Rn
2254                 D_word(inst);
2255
2256                 if (am1 == DREG)
2257                 {
2258                         inst = (0 << 15) + (a1reg << 12) + CREGlut[a0reg];
2259                         D_word(inst);
2260                 }
2261                 else
2262                 {
2263                         inst = (1 << 15) + (a1reg << 12) + CREGlut[a0reg];
2264                         D_word(inst);
2265                 }
2266         }
2267
2268         return OK;
2269 }
2270
2271
2272 //
2273 // moves (68010, 68020, 68030, 68040, CPU32)
2274 //
2275 int m_moves(WORD inst, WORD siz)
2276 {
2277         if (activecpu & !(CPU_68020 | CPU_68030 | CPU_68040))
2278                 return error(unsupport);
2279
2280         if (siz == SIZB)
2281         {
2282                 inst |= 0 << 6;
2283         }
2284         else if (siz == SIZL)
2285         {
2286                 inst |= 2 << 6;
2287         }
2288         else // SIZW/SIZN
2289         {
2290                 inst |= 1 << 6;
2291         }
2292
2293         if (am0 == DREG)
2294         {
2295                 inst |= am1 | a1reg;
2296                 D_word(inst);
2297                 inst = (a0reg << 12) | (1 << 11) | (0 << 15);
2298                 D_word(inst);
2299         }
2300         else if (am0 == AREG)
2301         {
2302                 inst |= am1 | a1reg;
2303                 D_word(inst);
2304                 inst = (a0reg << 12) | (1 << 11) | (1 << 15);
2305                 D_word(inst);
2306         }
2307         else
2308         {
2309                 if (am1 == DREG)
2310                 {
2311                         inst |= am0 | a0reg;
2312                         D_word(inst);
2313                         inst = (a1reg << 12) | (0 << 11) | (0 << 15);
2314                         D_word(inst);
2315                 }
2316                 else
2317                 {
2318                         inst |= am0 | a0reg;
2319                         D_word(inst);
2320                         inst = (a1reg << 12) | (0 << 11) | (1 << 15);
2321                         D_word(inst);
2322                 }
2323         }
2324
2325         return OK;
2326 }
2327
2328
2329 //
2330 // PBcc (MC68851)
2331 //
2332 int m_pbcc(WORD inst, WORD siz)
2333 {
2334         CHECKNO20;
2335         return error("Not implemented yet.");
2336 }
2337
2338
2339 //
2340 // pflusha (68030)
2341 //
2342 int m_pflusha(WORD inst, WORD siz)
2343 {
2344         CHECKNO30;
2345
2346         D_word(inst);
2347         inst = (1 << 13) | (1 << 10) | (0 << 5) | 0;
2348         D_word(inst);
2349         return OK;
2350 }
2351
2352
2353 //
2354 // pflush (68030, 68040, 68060)
2355 //
2356 int m_pflush(WORD inst, WORD siz)
2357 {
2358         if (activecpu == CPU_68030)
2359         {
2360                 D_word(inst);
2361                 D_word((1 << 13) | (1 << 10) | (0 << 5) | 0);
2362         }
2363         else if (activecpu == CPU_68040 || activecpu == CPU_68060)
2364         {
2365                 D_word(0xf918);
2366         }
2367         else
2368                 return error(unsupport);
2369
2370         return OK;
2371 }
2372
2373
2374 //
2375 // pflushr (68551)
2376 //
2377 int m_pflushr(WORD inst, WORD siz)
2378 {
2379         CHECKNO20;
2380
2381         WORD flg = inst;                                        // Save flag bits
2382         inst &= ~0x3F;                                          // Clobber flag bits in instr
2383
2384         // Install "standard" instr size bits
2385         if (flg & 4)
2386                 inst |= siz_6[siz];
2387
2388         if (flg & 16)
2389         {
2390                 // OR-in register number
2391                 if (flg & 8)
2392                         inst |= reg_9[a1reg];           // ea1reg in bits 9..11
2393                 else
2394                         inst |= reg_9[a0reg];           // ea0reg in bits 9..11
2395         }
2396
2397         if (flg & 1)
2398         {
2399                 // Use am1
2400                 inst |= am1 | a1reg;                    // Get ea1 into instr
2401                 D_word(inst);                                   // Deposit instr
2402
2403                 // Generate ea0 if requested
2404                 if (flg & 2)
2405                         ea0gen(siz);
2406
2407                 ea1gen(siz);                                    // Generate ea1
2408         }
2409         else
2410         {
2411                 // Use am0
2412                 inst |= am0 | a0reg;                    // Get ea0 into instr
2413                 D_word(inst);                                   // Deposit instr
2414                 ea0gen(siz);                                    // Generate ea0
2415
2416                 // Generate ea1 if requested
2417                 if (flg & 2)
2418                         ea1gen(siz);
2419         }
2420
2421         D_word(B16(10100000, 00000000));
2422 }
2423
2424
2425 //
2426 // ploadr, ploadw (68030)
2427 //
2428 int m_pload(WORD inst, WORD siz)
2429 {
2430         CHECKNO30;
2431         return error("Not implemented yet.");
2432 }
2433
2434
2435 //
2436 // pmove (68030)
2437 //
2438 int m_pmove(WORD inst, WORD siz)
2439 {
2440         int inst2,reg;
2441
2442         CHECKNO30;
2443
2444         inst2 = inst & (1 << 8); //Copy the flush bit over to inst2 in case we're called from m_pmovefd
2445         inst &= ~(1 << 8);              //And mask it out
2446
2447         if (am0 == CREG)
2448         {
2449                 reg = a0reg;
2450                 inst2 |= (1 << 9);
2451         }
2452         else if (am1 == CREG)
2453         {
2454                 reg = a1reg;
2455                 inst2 |= 0;
2456         }
2457         else
2458                 return error("pmove sez: Wut?");
2459
2460         if (((reg == (KW_URP - KW_SFC)) || (reg == (KW_SRP - KW_SFC)))
2461                 && ((siz != SIZD) && (siz != SIZN)))
2462                 return error(siz_error);
2463
2464         if (((reg == (KW_TC - KW_SFC)) || (reg == (KW_TT0 - KW_SFC)) || (reg == (KW_TT1 - KW_SFC)))
2465                 && ((siz != SIZL) && (siz != SIZN)))
2466                 return error(siz_error);
2467
2468         if ((reg == (KW_MMUSR - KW_SFC)) && ((siz != SIZW) && (siz != SIZN)))
2469                 return error(siz_error);
2470
2471         WARNING(Not all addressing modes are legal here!)
2472
2473         if (am0 == CREG)
2474         {
2475                 inst |= am1;
2476                 D_word(inst);
2477                 ea1gen(siz);
2478         }
2479         else if (am1 == CREG)
2480         {
2481                 inst |= am0;
2482                 D_word(inst);
2483                 ea0gen(siz);
2484         }
2485
2486         switch (reg)
2487         {
2488         case (KW_URP - KW_SFC):
2489                 inst2 |= (3 << 10) + (2 << 13); break;
2490         case (KW_SRP - KW_SFC):
2491                 inst2 |= (2 << 10) + (2 << 13); break;
2492         case (KW_TC - KW_SFC):
2493                 inst2 |= (0 << 10) + (2 << 13); break;
2494         case (KW_TT0 - KW_SFC):
2495                 inst2 |= (2 << 10) + (0 << 13); break;
2496         case (KW_TT1 - KW_SFC):
2497                 inst2 |= (3 << 10) + (0 << 13); break;
2498         case (KW_MMUSR - KW_SFC):
2499                 inst2 |= (3 << 10) + (3 << 13); break;
2500         case (KW_CRP - KW_SFC) :        //68851 only
2501                 inst2 |= (3 << 10) + (2 << 13); break;
2502         }
2503
2504         D_word(inst2);
2505
2506         return OK;
2507 }
2508
2509
2510 //
2511 // pmovefd (68030)
2512 //
2513 int m_pmovefd(WORD inst, WORD siz)
2514 {
2515         CHECKNO30;
2516
2517         return m_pmove(inst | (1 << 8), siz);
2518 }
2519
2520
2521 //
2522 // ptrapcc (68851)
2523 //
2524 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; }
2525 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; }
2526 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; }
2527 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; }
2528 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; }
2529 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; }
2530 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; }
2531 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; }
2532 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; }
2533 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; }
2534 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; }
2535 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; }
2536 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; }
2537 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; }
2538 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; }
2539 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; }
2540 int m_ptrapbsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000000)); return OK; }
2541 int m_ptrapbcn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000001)); return OK; }
2542 int m_ptraplsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000010)); return OK; }
2543 int m_ptraplcn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000011)); return OK; }
2544 int m_ptrapssn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000100)); return OK; }
2545 int m_ptrapscn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000101)); return OK; }
2546 int m_ptrapasn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000110)); return OK; }
2547 int m_ptrapacn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00000111)); return OK; }
2548 int m_ptrapwsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001000)); return OK; }
2549 int m_ptrapwcn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001001)); return OK; }
2550 int m_ptrapisn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001010)); return OK; }
2551 int m_ptrapicn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001011)); return OK; }
2552 int m_ptrapgsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001100)); return OK; }
2553 int m_ptrapgcn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001101)); return OK; }
2554 int m_ptrapcsn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001110)); return OK; }
2555 int m_ptrapccn(WORD inst, WORD siz) { CHECKNO20; D_word(inst); D_word(B8(00001111)); return OK; }
2556
2557
2558 //
2559 // ptestr, ptestw (68030)
2560 //
2561 int m_ptest(WORD inst, WORD siz)
2562 {
2563         CHECKNO30;
2564
2565         if (activecpu == CPU_68030)
2566                 return error("Not implemented yet.");
2567         else if (activecpu == CPU_68040)
2568                 return error("Not implemented yet.");
2569
2570         return ERROR;
2571 }
2572
2573
2574 #define FPU_NOWARN 0
2575 #define FPU_P_EMUL 1
2576 #define FPU_P2_EMU 2
2577 #define FPU_FPSP   4
2578
2579
2580 //
2581 // Generate a FPU opcode
2582 //
2583 static inline int gen_fpu(WORD inst, WORD siz, WORD opmode, WORD emul)
2584 {
2585         if (am0 < AM_NONE)      // Check first operand for ea or fp - is this right?
2586         {
2587                 inst |= (1 << 9);       // Bolt on FPU id
2588                 inst |= am0;
2589
2590                 if (am0 == DREG)
2591             inst |= a0reg;
2592
2593                 D_word(inst);
2594                 inst = 1 << 14; // R/M field (we have ea so have to set this to 1)
2595
2596                 switch (siz)
2597                 {
2598                 case SIZB:      inst |= (6 << 10); break;
2599                 case SIZW:      inst |= (4 << 10); break;
2600                 case SIZL:      inst |= (0 << 10); break;
2601                 case SIZN:
2602                 case SIZS:      inst |= (1 << 10); break;
2603                 case SIZD:      inst |= (5 << 10); break;
2604                 case SIZX:      inst |= (2 << 10); break;
2605                 case SIZP:
2606                         inst |= (3 << 10);
2607
2608                         if (emul)
2609                                 warn("This encoding will cause an unimplemented data type exception in the MC68040 to allow emulation in software.");
2610
2611                         break;
2612                 default:
2613                         return error("Something bad happened, possibly, in gen_fpu.");
2614                         break;
2615                 }
2616
2617                 inst |= (a1reg << 7);
2618                 inst |= opmode;
2619                 D_word(inst);
2620                 ea0gen(siz);
2621         }
2622         else
2623         {
2624                 inst |= (1 << 9);       //Bolt on FPU id
2625                 D_word(inst);
2626                 inst = 0;
2627                 inst = a0reg << 10;
2628                 inst |= (a1reg << 7);
2629                 inst |= opmode;
2630                 D_word(inst);
2631         }
2632
2633         if ((emul & FPU_FPSP) && (activefpu == FPU_68040))
2634                 warn("Instruction is emulated in 68040");
2635
2636         return OK;
2637 }
2638
2639
2640 //
2641 // fabs, fsabs, fdabs (6888X, 68040)
2642 //
2643 int m_fabs(WORD inst, WORD siz)
2644 {
2645         return gen_fpu(inst, siz, B8(00011000), FPU_P_EMUL);
2646 }
2647
2648
2649 int m_fsabs(WORD inst, WORD siz)
2650 {
2651         if (activefpu == FPU_68040)
2652                 return gen_fpu(inst, siz, B8(01011000), FPU_P_EMUL);
2653         else
2654                 return error("Unsupported in current FPU");
2655 }
2656
2657
2658 int m_fdabs(WORD inst, WORD siz)
2659 {
2660         if (activefpu == FPU_68040)
2661                 return gen_fpu(inst, siz, B8(01011100), FPU_P_EMUL);
2662         else
2663                 return error("Unsupported in current FPU");
2664 }
2665
2666
2667 //
2668 // facos (6888X, 68040FPSP)
2669 //
2670 int m_facos(WORD inst, WORD siz)
2671 {
2672         return gen_fpu(inst, siz, B8(00011100), FPU_FPSP);
2673 }
2674
2675
2676 //
2677 // fadd (6888X, 68040FPSP)
2678 //
2679 int m_fadd(WORD inst, WORD siz)
2680 {
2681         return gen_fpu(inst, siz, B8(00100010), FPU_P_EMUL);
2682 }
2683
2684
2685 int m_fsadd(WORD inst, WORD siz)
2686 {
2687         if (activefpu == FPU_68040)
2688                 return gen_fpu(inst, siz, B8(01100010), FPU_P_EMUL);
2689         else
2690                 return error("Unsupported in current FPU");
2691 }
2692
2693
2694 int m_fdadd(WORD inst, WORD siz)
2695 {
2696         if (activefpu == FPU_68040)
2697                 return gen_fpu(inst, siz, B8(01100110), FPU_P_EMUL);
2698         else
2699                 return error("Unsupported in current FPU");
2700 }
2701
2702
2703 //
2704 // fasin (6888X, 68040FPSP)f
2705 //
2706 int m_fasin(WORD inst, WORD siz)
2707 {
2708         return gen_fpu(inst, siz, B8(00001100), FPU_FPSP);
2709 }
2710
2711
2712 //
2713 // fatan (6888X, 68040FPSP)
2714 //
2715 int m_fatan(WORD inst, WORD siz)
2716 {
2717         return gen_fpu(inst, siz, B8(00001010), FPU_FPSP);
2718 }
2719
2720
2721 //
2722 // fatanh (6888X, 68040FPSP)
2723 //
2724 int m_fatanh(WORD inst, WORD siz)
2725 {
2726         return gen_fpu(inst, siz, B8(00001101), FPU_FPSP);
2727 }
2728
2729
2730 //
2731 // fcmp (6888X, 68040)
2732 //
2733 int m_fcmp(WORD inst, WORD siz)
2734 {
2735         return gen_fpu(inst, siz, B8(00111000), FPU_P_EMUL);
2736 }
2737
2738
2739 //
2740 // fcos (6888X, 68040FPSP)
2741 //
2742 int m_fcos(WORD inst, WORD siz)
2743 {
2744         return gen_fpu(inst, siz, B8(00011101), FPU_FPSP);
2745 }
2746
2747
2748 //
2749 // fcosh (6888X, 68040FPSP)
2750 //
2751 int m_fcosh(WORD inst, WORD siz)
2752 {
2753         return gen_fpu(inst, siz, B8(00011001), FPU_FPSP);
2754 }
2755
2756
2757 //
2758 // fdbcc (6888X, 68040)
2759 //
2760 int m_fdbcc(WORD inst, WORD siz)
2761 {
2762         WORD opcode = inst & 0x3F;      //Grab conditional bitfield
2763
2764         inst &= ~0x3F;
2765         inst |= 1 << 3;
2766
2767         siz = siz;
2768         inst |= a0reg;
2769         D_word(inst);
2770         D_word(opcode);
2771
2772         if (a1exattr & DEFINED)
2773         {
2774                 if ((a1exattr & TDB) != cursect)
2775                         return error(rel_error);
2776
2777                 VALUE v = a1exval - sloc;
2778
2779                 if ((v + 0x8000) > 0x10000)
2780                         return error(range_error);
2781
2782                 D_word(v);
2783         }
2784         else
2785         {
2786                 AddFixup(FU_WORD | FU_PCREL | FU_ISBRA, sloc, a1expr);
2787                 D_word(0);
2788         }
2789
2790         return OK;
2791 }
2792
2793
2794 //
2795 // fdiv (6888X, 68040)
2796 //
2797 int m_fdiv(WORD inst, WORD siz)
2798 {
2799         return gen_fpu(inst, siz, B8(00100000), FPU_P_EMUL);
2800 }
2801
2802
2803 int m_fsdiv(WORD inst, WORD siz)
2804 {
2805         if (activefpu == FPU_68040)
2806                 return gen_fpu(inst, siz, B8(01100000), FPU_P_EMUL);
2807         else
2808                 return error("Unsupported in current FPU");
2809 }
2810
2811
2812 int m_fddiv(WORD inst, WORD siz)
2813 {
2814         if (activefpu == FPU_68040)
2815                 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
2816         else
2817                 return error("Unsupported in current FPU");
2818 }
2819
2820
2821 //
2822 // fetox (6888X, 68040FPSP)
2823 //
2824 int m_fetox(WORD inst, WORD siz)
2825 {
2826         return gen_fpu(inst, siz, B8(00010000), FPU_FPSP);
2827 }
2828
2829
2830 //
2831 // fetoxm1 (6888X, 68040FPSP)
2832 //
2833 int m_fetoxm1(WORD inst, WORD siz)
2834 {
2835         return gen_fpu(inst, siz, B8(00001000), FPU_FPSP);
2836 }
2837
2838
2839 //
2840 // fgetexp (6888X, 68040FPSP)
2841 //
2842 int m_fgetexp(WORD inst, WORD siz)
2843 {
2844         return gen_fpu(inst, siz, B8(00011110), FPU_FPSP);
2845 }
2846
2847
2848 //
2849 // fgetman (6888X, 68040FPSP)
2850 //
2851 int m_fgetman(WORD inst, WORD siz)
2852 {
2853         return gen_fpu(inst, siz, B8(00011111), FPU_FPSP);
2854 }
2855
2856
2857 //
2858 // fint (6888X, 68040FPSP)
2859 //
2860 int m_fint(WORD inst, WORD siz)
2861 {
2862         if (am1 == AM_NONE)
2863                 // special case - fint fpx = fint fpx,fpx
2864                 a1reg = a0reg;
2865
2866         return gen_fpu(inst, siz, B8(00000001), FPU_FPSP);
2867 }
2868
2869
2870 //
2871 // fintrz (6888X, 68040FPSP)
2872 //
2873 int m_fintrz(WORD inst, WORD siz)
2874 {
2875         if (am1 == AM_NONE)
2876                 // special case - fintrz fpx = fintrz fpx,fpx
2877                 a1reg = a0reg;
2878
2879         return gen_fpu(inst, siz, B8(00000011), FPU_FPSP);
2880 }
2881
2882
2883 //
2884 // flog10 (6888X, 68040FPSP)
2885 //
2886 int m_flog10(WORD inst, WORD siz)
2887 {
2888         return gen_fpu(inst, siz, B8(00010101), FPU_FPSP);
2889 }
2890
2891
2892 //
2893 // flog2 (6888X, 68040FPSP)
2894 //
2895 int m_flog2(WORD inst, WORD siz)
2896 {
2897         return gen_fpu(inst, siz, B8(00010110), FPU_FPSP);
2898 }
2899
2900
2901 //
2902 // flogn (6888X, 68040FPSP)
2903 //
2904 int m_flogn(WORD inst, WORD siz)
2905 {
2906         return gen_fpu(inst, siz, B8(00010100), FPU_FPSP);
2907 }
2908
2909
2910 //
2911 // flognp1 (6888X, 68040FPSP)
2912 //
2913 int m_flognp1(WORD inst, WORD siz)
2914 {
2915         return gen_fpu(inst, siz, B8(00000110), FPU_FPSP);
2916 }
2917
2918
2919 //
2920 // fmod (6888X, 68040FPSP)
2921 //
2922 int m_fmod(WORD inst, WORD siz)
2923 {
2924         return gen_fpu(inst, siz, B8(00100001), FPU_FPSP);
2925 }
2926
2927
2928 //
2929 // fmove (6888X, 68040)
2930 //
2931 int m_fmove(WORD inst, WORD siz)
2932 {
2933
2934         // EA to register
2935         if ((am0 == FREG) && (am1 < AM_USP))
2936         {
2937                 // EA
2938                 inst |= am1 | a1reg;
2939                 D_word(inst);
2940
2941                 // R/M
2942                 inst = 3 << 13;
2943
2944                 WARNING("K-factor logic is totally bogus - fix!")
2945
2946                 // Source specifier
2947                 switch (siz)
2948                 {
2949                 case SIZB:      inst |= (6 << 10); break;
2950                 case SIZW:      inst |= (4 << 10); break;
2951                 case SIZL:      inst |= (0 << 10); break;
2952                 case SIZN:
2953                 case SIZS:      inst |= (1 << 10); break;
2954                 case SIZD:      inst |= (5 << 10); break;
2955                 case SIZX:      inst |= (2 << 10); break;
2956                 case SIZP:  inst |= (3 << 10);
2957                         if (bfparam1)
2958                                 inst |= 1 << 12;
2959
2960                         inst |= (bfparam1 & 0x7FF) >> 2;
2961                         break;
2962                 default:
2963                         return error("Something bad happened, possibly.");
2964                         break;
2965                 }
2966
2967                 // Immediate {} value
2968                 if (bf0exval >= (1 << 6))
2969                         return error("K-factor must be between 0 and 31");
2970
2971                 if (!bfparam1 && (siz == SIZP))
2972             inst |= bf0exval;
2973
2974                 // Destination specifier
2975                 inst |= (a0reg << 7);
2976
2977                 // Opmode
2978                 inst |= 0;
2979
2980                 D_word(inst);
2981                 ea1gen(siz);
2982         }
2983         else if ((am0 < AM_USP) && (am1 == FREG))
2984         {
2985                 // EA
2986                 inst |= am0 | a0reg;
2987                 D_word(inst);
2988
2989                 // R/M
2990                 inst = 1 << 14;
2991
2992                 // Source specifier
2993                 switch (siz)
2994                 {
2995                 case SIZB:      inst |= (6 << 10); break;
2996                 case SIZW:      inst |= (4 << 10); break;
2997                 case SIZL:      inst |= (0 << 10); break;
2998                 case SIZN:
2999                 case SIZS:      inst |= (1 << 10); break;
3000                 case SIZD:      inst |= (5 << 10); break;
3001                 case SIZX:      inst |= (2 << 10); break;
3002                 case SIZP:  inst |= (3 << 10); break;
3003                 default:
3004                         return error("Something bad happened, possibly.");
3005                         break;
3006                 }
3007
3008                 // Destination specifier
3009                 inst |= (a1reg << 7);
3010
3011                 // Opmode
3012                 inst |= 0;
3013
3014                 D_word(inst);
3015                 ea0gen(siz);
3016         }
3017         else if ((am0 == FREG) && (am1 == FREG))
3018         {
3019                 // EA
3020                 D_word(inst);
3021
3022                 // R/M
3023                 inst = 0 << 14;
3024
3025                 // Source specifier
3026                 if (siz != SIZX)
3027                         return error("Invalid size");
3028
3029                 // Source register
3030                 inst |= (a0reg << 10);
3031
3032         // Destination register
3033                 inst |= (a1reg << 7);
3034
3035                 D_word(inst);
3036         }
3037
3038         return OK;
3039 }
3040
3041
3042 //
3043 // fmove (6888X, 68040)
3044 //
3045 int m_fmovescr(WORD inst, WORD siz)
3046 {
3047         // Move Floating-Point System Control Register (FPCR)
3048         // ea
3049         // dr
3050         // Register select
3051         if ((am0 == FPSCR) && (am1 < AM_USP))
3052         {
3053                 inst |= am1 | a1reg;
3054                 D_word(inst);
3055                 inst = (1 << 13) + (1 << 15);
3056                 inst |= a0reg;
3057                 D_word(inst);
3058                 ea1gen(siz);
3059                 return OK;
3060         }
3061         else if ((am1 == FPSCR) && (am0 < AM_USP))
3062         {
3063                 inst |= am0 | a0reg;
3064                 D_word(inst);
3065                 inst = (0 << 13) + (1 << 15);
3066                 inst |= a1reg;
3067                 D_word(inst);
3068                 ea0gen(siz);
3069                 return OK;
3070         }
3071         else
3072                 return error("m_fmovescr says: wut?");
3073 }
3074
3075
3076 //
3077 // fsmove/fdmove (68040)
3078 //
3079 int m_fsmove(WORD inst, WORD siz)
3080 {
3081         return error("Not implemented yet.");
3082
3083 #if 0
3084         if (activefpu == FPU_68040)
3085                 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
3086         else
3087                 return error("Unsupported in current FPU");
3088 #endif
3089 }
3090
3091
3092 int m_fdmove(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 //
3106 // fmovecr (6888X, 68040FPSP)
3107 //
3108 int m_fmovecr(WORD inst, WORD siz)
3109 {
3110         D_word(inst);
3111         inst = 0x5c00;
3112         inst |= a1reg << 7;
3113         inst |= a0exval;
3114         D_word(inst);
3115
3116         if (activefpu == FPU_68040)
3117                 warn("Instruction is emulated in 68040");
3118
3119         return OK;
3120 }
3121
3122
3123 //
3124 // fmovem (6888X, 68040)
3125 //
3126 int m_fmovem(WORD inst, WORD siz)
3127 {
3128         WORD regmask;
3129         WORD datareg;
3130
3131         if (siz == SIZX)
3132         {
3133                 if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
3134                 {
3135                         // fmovem.x <rlist>,ea
3136                         if (fpu_reglist_left(&regmask) < 0)
3137                                 return OK;
3138
3139                         if (*tok++ != ',')
3140                                 return error("missing comma");
3141
3142                         if (amode(0) < 0)
3143                                 return OK;
3144
3145                         inst |= am0 | a0reg;
3146
3147                         if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
3148                                 return error("invalid addressing mode");
3149
3150                         D_word(inst);
3151                         inst = (1 << 15) | (1 << 14) | (1 << 13) | (0 << 11) | regmask;
3152                         D_word(inst);
3153                         ea0gen(siz);
3154                         return OK;
3155                 }
3156                 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
3157                 {
3158                         // fmovem.x Dn,ea
3159                         datareg = (*tok++ & 7) << 10;
3160
3161                         if (*tok++ != ',')
3162                                 return error("missing comma");
3163
3164                         if (amode(0) < 0)
3165                                 return OK;
3166
3167                         inst |= am0 | a0reg;
3168
3169                         if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
3170                                 return error("invalid addressing mode");
3171
3172                         D_word(inst);
3173                         inst = (1 << 15) | (1 << 14) | (1 << 13) | (1 << 11) | (datareg << 4);
3174                         D_word(inst);
3175                         ea0gen(siz);
3176                         return OK;
3177                 }
3178                 else
3179                 {
3180                         // fmovem.x ea,...
3181                         if (amode(0) < 0)
3182                                 return OK;
3183
3184                         inst |= am0 | a0reg;
3185
3186                         if (*tok++ != ',')
3187                                 return error("missing comma");
3188
3189                         if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
3190                         {
3191                                 //fmovem.x ea,<rlist>
3192                                 if (fpu_reglist_right(&regmask) < 0)
3193                                         return OK;
3194
3195                                 D_word(inst);
3196                                 inst = (1 << 15) | (1 << 14) | (0 << 13) | (2 << 11) | regmask;
3197                                 D_word(inst);
3198                                 ea0gen(siz);
3199                                 return OK;
3200                         }
3201                         else
3202                         {
3203                                 // fmovem.x ea,Dn
3204                                 datareg = (*tok++ & 7) << 10;
3205                                 D_word(inst);
3206                                 inst = (1 << 15) | (1 << 14) | (0 << 13) | (3 << 11) | (datareg << 4);
3207                                 D_word(inst);
3208                                 ea0gen(siz);
3209                                 return OK;
3210                         }
3211                 }
3212         }
3213         else if ((siz == SIZL) || (siz==SIZN))
3214         {
3215                 if ((*tok == KW_FPCR) || (*tok == KW_FPSR) || (*tok == KW_FPIAR))
3216                 {
3217                         //fmovem.l <rlist>,ea
3218                         regmask = (1 << 15) | (1 << 13);
3219 fmovem_loop_1:
3220                         if (*tok == KW_FPCR)
3221                         {
3222                                 regmask |= (1 << 12);
3223                                 tok++;
3224                                 goto fmovem_loop_1;
3225                         }
3226
3227                         if (*tok == KW_FPSR)
3228                         {
3229                                 regmask |= (1 << 11);
3230                                 tok++;
3231                                 goto fmovem_loop_1;
3232                         }
3233
3234                         if (*tok == KW_FPIAR)
3235                         {
3236                                 regmask |= (1 << 10);
3237                                 tok++;
3238                                 goto fmovem_loop_1;
3239                         }
3240
3241                         if ((*tok == '/') || (*tok == '-'))
3242                         {
3243                                 tok++;
3244                                 goto fmovem_loop_1;
3245                         }
3246
3247                         if (*tok++ != ',')
3248                                 return error("missing comma");
3249
3250                         if (amode(0) < 0)
3251                                 return OK;
3252
3253                         inst |= am0 | a0reg;
3254                         D_word(inst);
3255                         D_word(regmask);
3256                         ea0gen(siz);
3257                 }
3258                 else
3259                 {
3260                         //fmovem.l ea,<rlist>
3261                         if (amode(0) < 0)
3262                                 return OK;
3263
3264                         inst |= am0 | a0reg;
3265
3266                         if (*tok++ != ',')
3267                                 return error("missing comma");
3268
3269                         regmask = (1 << 15) | (0 << 13);
3270
3271 fmovem_loop_2:
3272                         if (*tok == KW_FPCR)
3273                         {
3274                                 regmask |= (1 << 12);
3275                                 tok++;
3276                                 goto fmovem_loop_2;
3277                         }
3278
3279                         if (*tok == KW_FPSR)
3280                         {
3281                                 regmask |= (1 << 11);
3282                                 tok++;
3283                                 goto fmovem_loop_2;
3284                         }
3285
3286                         if (*tok == KW_FPIAR)
3287                         {
3288                                 regmask |= (1 << 10);
3289                                 tok++;
3290                                 goto fmovem_loop_2;
3291                         }
3292
3293                         if ((*tok == '/') || (*tok == '-'))
3294                         {
3295                                 tok++;
3296                                 goto fmovem_loop_2;
3297                         }
3298
3299                         if (*tok!=EOL)
3300                                 return error("extra (unexpected) text found");
3301
3302                         inst |= am0 | a0reg;
3303                         D_word(inst);
3304                         D_word(regmask);
3305                         ea0gen(siz);
3306                 }
3307         }
3308         else
3309                 return error("bad size suffix");
3310
3311         return OK;
3312 }
3313
3314
3315 //
3316 // fmul (6888X, 68040)
3317 //
3318 int m_fmul(WORD inst, WORD siz)
3319 {
3320         return gen_fpu(inst, siz, B8(00100011), FPU_P_EMUL);
3321 }
3322
3323
3324 int m_fsmul(WORD inst, WORD siz)
3325 {
3326         if (activefpu == FPU_68040)
3327                 return gen_fpu(inst, siz, B8(01100011), FPU_P_EMUL);
3328         else
3329                 return error("Unsupported in current FPU");
3330 }
3331
3332
3333 int m_fdmul(WORD inst, WORD siz)
3334 {
3335         if (activefpu == FPU_68040)
3336                 return gen_fpu(inst, siz, B8(01100111), FPU_P_EMUL);
3337         else
3338                 return error("Unsupported in current FPU");
3339 }
3340
3341
3342 //
3343 // fneg (6888X, 68040)
3344 //
3345 int m_fneg(WORD inst, WORD siz)
3346 {
3347         return gen_fpu(inst, siz, B8(00011010), FPU_P_EMUL);
3348 }
3349
3350
3351 int m_fsneg(WORD inst, WORD siz)
3352 {
3353         if (activefpu == FPU_68040)
3354                 return gen_fpu(inst, siz, B8(01011010), FPU_P_EMUL);
3355         else
3356                 return error("Unsupported in current FPU");
3357 }
3358
3359
3360 int m_fdneg(WORD inst, WORD siz)
3361 {
3362         if (activefpu == FPU_68040)
3363                 return gen_fpu(inst, siz, B8(01011110), FPU_P_EMUL);
3364         else
3365                 return error("Unsupported in current FPU");
3366 }
3367
3368
3369 //
3370 // fnop (6888X, 68040)
3371 //
3372 int m_fnop(WORD inst, WORD siz)
3373 {
3374         return gen_fpu(inst, siz, B8(00000000), FPU_P_EMUL);
3375 }
3376
3377
3378 //
3379 // frem (6888X, 68040FPSP)
3380 //
3381 int m_frem(WORD inst, WORD siz)
3382 {
3383         return gen_fpu(inst, siz, B8(00100101), FPU_FPSP);
3384 }
3385
3386
3387 //
3388 // fscale (6888X, 68040FPSP)
3389 //
3390 int m_fscale(WORD inst, WORD siz)
3391 {
3392         return gen_fpu(inst, siz, B8(00100110), FPU_FPSP);
3393 }
3394
3395
3396 //
3397 // FScc (6888X, 68040)
3398 //
3399 int m_fseq  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000001)); return OK;}
3400 int m_fsne  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001110)); return OK;}
3401 int m_fsgt  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010010)); return OK;}
3402 int m_fsngt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011101)); return OK;}
3403 int m_fsge  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010011)); return OK;}
3404 int m_fsnge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011100)); return OK;}
3405 int m_fslt  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010100)); return OK;}
3406 int m_fsnlt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011011)); return OK;}
3407 int m_fsle  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010101)); return OK;}
3408 int m_fsnle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011010)); return OK;}
3409 int m_fsgl  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010110)); return OK;}
3410 int m_fsngl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011001)); return OK;}
3411 int m_fsgle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010111)); return OK;}
3412 int m_fsngle(WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011000)); return OK;}
3413 int m_fsogt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000010)); return OK;}
3414 int m_fsule (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001101)); return OK;}
3415 int m_fsoge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000011)); return OK;}
3416 int m_fsult (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001100)); return OK;}
3417 int m_fsolt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000100)); return OK;}
3418 int m_fsuge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001011)); return OK;}
3419 int m_fsole (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000101)); return OK;}
3420 int m_fsugt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001010)); return OK;}
3421 int m_fsogl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000110)); return OK;}
3422 int m_fsueq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001001)); return OK;}
3423 int m_fsor  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000111)); return OK;}
3424 int m_fsun  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001000)); return OK;}
3425 int m_fsf   (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000000)); return OK;}
3426 int m_fst   (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001111)); return OK;}
3427 int m_fssf  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010000)); return OK;}
3428 int m_fsst  (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011111)); return OK;}
3429 int m_fsseq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010001)); return OK;}
3430 int m_fssne (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011110)); return OK;}
3431
3432
3433 //
3434 // FTRAPcc (6888X, 68040)
3435 //
3436 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;}
3437 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;}
3438 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;}
3439 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;}
3440 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;}
3441 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;}
3442 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;}
3443 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;}
3444 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;}
3445 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;}
3446 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;}
3447 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;}
3448 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;}
3449 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;}
3450 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;}
3451 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;}
3452 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;}
3453 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;}
3454 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;}
3455 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;}
3456 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;}
3457 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;}
3458 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;}
3459 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;}
3460 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;}
3461 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;}
3462 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;}
3463 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;}
3464 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;}
3465 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;}
3466 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;}
3467 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;}
3468
3469 int m_ftrapeqn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000001)); return OK;}
3470 int m_ftrapnen  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001110)); return OK;}
3471 int m_ftrapgtn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010010)); return OK;}
3472 int m_ftrapngtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011101)); return OK;}
3473 int m_ftrapgen  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010011)); return OK;}
3474 int m_ftrapngen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011100)); return OK;}
3475 int m_ftrapltn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010100)); return OK;}
3476 int m_ftrapnltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011011)); return OK;}
3477 int m_ftraplen  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010101)); return OK;}
3478 int m_ftrapnlen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011010)); return OK;}
3479 int m_ftrapgln  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010110)); return OK;}
3480 int m_ftrapngln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011001)); return OK;}
3481 int m_ftrapglen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010111)); return OK;}
3482 int m_ftrapnglen(WORD inst, WORD siz) { D_word(inst); D_word(B8(00011000)); return OK;}
3483 int m_ftrapogtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000010)); return OK;}
3484 int m_ftrapulen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001101)); return OK;}
3485 int m_ftrapogen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000011)); return OK;}
3486 int m_ftrapultn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001100)); return OK;}
3487 int m_ftrapoltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000100)); return OK;}
3488 int m_ftrapugen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001011)); return OK;}
3489 int m_ftrapolen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000101)); return OK;}
3490 int m_ftrapugtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001010)); return OK;}
3491 int m_ftrapogln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000110)); return OK;}
3492 int m_ftrapueqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001001)); return OK;}
3493 int m_ftraporn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000111)); return OK;}
3494 int m_ftrapunn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001000)); return OK;}
3495 int m_ftrapfn   (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000000)); return OK;}
3496 int m_ftraptn   (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001111)); return OK;}
3497 int m_ftrapsfn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010000)); return OK;}
3498 int m_ftrapstn  (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011111)); return OK;}
3499 int m_ftrapseqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010001)); return OK;}
3500 int m_ftrapsnen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011110)); return OK;}
3501
3502
3503 //
3504 // fsgldiv (6888X, 68040)
3505 //
3506 int m_fsgldiv(WORD inst, WORD siz)
3507 {
3508         return gen_fpu(inst, siz, B8(00100100), FPU_P_EMUL);
3509 }
3510
3511
3512 //
3513 // fsglmul (6888X, 68040)
3514 //
3515 int m_fsglmul(WORD inst, WORD siz)
3516 {
3517         return gen_fpu(inst, siz, B8(00100111), FPU_P_EMUL);
3518 }
3519
3520
3521 //
3522 // fsin (6888X, 68040FPSP)
3523 //
3524 int m_fsin(WORD inst, WORD siz)
3525 {
3526         return gen_fpu(inst, siz, B8(00001110), FPU_FPSP);
3527 }
3528
3529
3530 //
3531 // fsincos (6888X, 68040FPSP)
3532 //
3533 int m_fsincos(WORD inst, WORD siz)
3534 {
3535         if (gen_fpu(inst, siz, B8(00110000), FPU_FPSP) == OK)
3536         {
3537                 chptr[-1] |= a2reg;
3538                 return OK;
3539         }
3540         else
3541                 return ERROR;
3542 }
3543
3544
3545 //
3546 // fsin (6888X, 68040FPSP)
3547 //
3548 int m_fsinh(WORD inst, WORD siz)
3549 {
3550         return gen_fpu(inst, siz, B8(00000010), FPU_FPSP);
3551 }
3552
3553
3554 //
3555 // fsqrt (6888X, 68040)
3556 //
3557 int m_fsqrt(WORD inst, WORD siz)
3558 {
3559         return gen_fpu(inst, siz, B8(00000100), FPU_P_EMUL);
3560 }
3561
3562
3563 int m_fsfsqrt(WORD inst, WORD siz)
3564 {
3565         if (activefpu == FPU_68040)
3566                 return gen_fpu(inst, siz, B8(01000001), FPU_P_EMUL);
3567         else
3568                 return error("Unsupported in current FPU");
3569 }
3570
3571
3572 int m_fdfsqrt(WORD inst, WORD siz)
3573 {
3574         if (activefpu == FPU_68040)
3575                 return gen_fpu(inst, siz, B8(01000101), FPU_P_EMUL);
3576         else
3577                 return error("Unsupported in current FPU");
3578 }
3579
3580
3581 //
3582 // fsub (6888X, 68040)
3583 //
3584 int m_fsub(WORD inst, WORD siz)
3585 {
3586         return gen_fpu(inst, siz, B8(00101000), FPU_P_EMUL);
3587 }
3588
3589
3590 int m_fsfsub(WORD inst, WORD siz)
3591 {
3592         if (activefpu == FPU_68040)
3593                 return gen_fpu(inst, siz, B8(01101000), FPU_P_EMUL);
3594         else
3595                 return error("Unsupported in current FPU");
3596 }
3597
3598
3599 int m_fdsub(WORD inst, WORD siz)
3600 {
3601         if (activefpu == FPU_68040)
3602                 return gen_fpu(inst, siz, B8(01101100), FPU_P_EMUL);
3603         else
3604                 return error("Unsupported in current FPU");
3605 }
3606
3607
3608 //
3609 // ftan (6888X, 68040FPSP)
3610 //
3611 int m_ftan(WORD inst, WORD siz)
3612 {
3613         return gen_fpu(inst, siz, B8(00001111), FPU_FPSP);
3614 }
3615
3616
3617 //
3618 // ftanh (6888X, 68040FPSP)
3619 //
3620 int m_ftanh(WORD inst, WORD siz)
3621 {
3622         return gen_fpu(inst, siz, B8(00001001), FPU_FPSP);
3623 }
3624
3625
3626 //
3627 // ftentox (6888X, 68040FPSP)
3628 //
3629 int m_ftentox(WORD inst, WORD siz)
3630 {
3631         return gen_fpu(inst, siz, B8(00010010), FPU_FPSP);
3632 }
3633
3634
3635 //
3636 // ftst (6888X, 68040)
3637 //
3638 int m_ftst(WORD inst, WORD siz)
3639 {
3640         return gen_fpu(inst, siz, B8(00111010), FPU_P_EMUL);
3641 }
3642
3643
3644 //
3645 // ftwotox (6888X, 68040FPSP)
3646 //
3647 int m_ftwotox(WORD inst, WORD siz)
3648 {
3649         return gen_fpu(inst, siz, B8(00010001), FPU_FPSP);
3650 }
3651