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