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
24 int movep = 0; // Global flag to indicate we're generating a movep instruction
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);
38 int m_lea(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);
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);
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);
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);
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";
293 // Include code tables
295 { 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000, 0, m_badmode }, // 0
297 { 0, 0L, 0L, 0x0000, 0, m_unimp } // Last entry
300 // Register number << 9
302 0, 1 << 9, 2 << 9, 3 << 9, 4 << 9, 5 << 9, 6 << 9, 7 << 9
305 // SIZB==>00, SIZW==>01, SIZL==>10, SIZN==>01 << 6
309 1<<6, (WORD)-1, // SIZW, n/a
310 2<<6, (WORD)-1, (WORD)-1, (WORD)-1, // SIZL, n/a, n/a, n/a
314 // Byte/word/long size for MOVE instrs
318 0x3000, (WORD)-1, // Word
319 0x2000, (WORD)-1, (WORD)-1, (WORD)-1, // Long
320 0x3000 // Word (SIZN)
323 // Word/long size (0=.w, 1=.l) in bit 8
327 0, (WORD)-1, // SIZW, n/a
328 1<<8, (WORD)-1, (WORD)-1, (WORD)-1, // SIZL, n/a, n/a, n/a
332 // Byte/Word/long size (0=.w, 1=.l) in bit 9
336 1<<9, (WORD)-1, // Word
337 1<<10, (WORD)-1, (WORD)-1, (WORD)-1, // Long
341 // Addressing mode in bits 6..11 (register/mode fields are reversed)
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
353 // Control registers lookup table
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)
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)
380 0xFFF // CPU Root Pointer (CRP) - There's no movec with CRP in it, this is just a guard entry
385 int m_unimp(WORD unused1, WORD unused2)
387 return (int)error("unimplemented mnemonic");
391 //int m_badmode(void)
392 int m_badmode(WORD unused1, WORD unused2)
394 return (int)error("inappropriate addressing mode");
398 int m_self(WORD inst, WORD usused)
406 // Do one EA in bits 0..5
408 // Bits in `inst' have the following meaning:
410 // Bit zero specifies which ea (ea0 or ea1) to generate in the lower six bits
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.
417 // If bit two is set, standard size bits are set in the instr in bits 6 and 7.
419 // If bit four is set, bit three specifies which eaXreg to place in bits 9..11
422 int m_ea(WORD inst, WORD siz)
424 WORD flg = inst; // Save flag bits
425 inst &= ~0x3F; // Clobber flag bits in instr
427 // Install "standard" instr size bits
433 // OR-in register number
435 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
437 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
443 inst |= am1 | a1reg; // Get ea1 into instr
444 D_word(inst); // Deposit instr
446 // Generate ea0 if requested
450 ea1gen(siz); // Generate ea1
455 inst |= am0 | a0reg; // Get ea0 into instr
456 D_word(inst); // Deposit instr
457 ea0gen(siz); // Generate ea0
459 // Generate ea1 if requested
469 // Check if lea x(an),an can be optimised to addq.w #x,an--otherwise fall back
472 int m_lea(WORD inst, WORD siz)
474 if (CHECK_OPTS(OPT_LEA_ADDQ)
475 && ((am0 == ADISP) && (a0reg == a1reg) && (a0exattr & DEFINED))
476 && ((a0exval > 0) && (a0exval <= 8)))
478 inst = B16(01010000, 01001000) | (((uint16_t)a0exval & 7) << 9) | (a0reg);
480 warn("lea size(An),An converted to addq #size,An");
484 return m_ea(inst, siz);
488 int m_ea030(WORD inst, WORD siz)
491 WORD flg = inst; // Save flag bits
492 inst &= ~0x3F; // Clobber flag bits in instr
494 // Install "standard" instr size bits
500 // OR-in register number
503 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
507 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
514 inst |= am1 | a1reg; // Get ea1 into instr
515 D_word(inst); // Deposit instr
517 // Generate ea0 if requested
521 ea1gen(siz); // Generate ea1
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
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)
538 else if (am0 == AIND)
541 inst |= a0reg; // Get ea0 into instr
542 D_word(inst); // Deposit instr
543 ea0gen(siz); // Generate ea0
545 // Generate ea1 if requested
555 // Dx,Dy nnnnXXXnssnnnYYY If bit 0 of `inst' is set, install size bits in bits
558 int m_abcd(WORD inst, WORD siz)
567 inst |= a0reg | reg_9[a1reg];
577 int m_adda(WORD inst, WORD siz)
579 inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg];
581 ea0gen(siz); // Generate EA
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.
591 int m_reg(WORD inst, WORD siz)
598 // Install other register (9..11)
599 inst |= reg_9[a1reg];
601 inst &= ~7; // Clear off crufty bits
602 inst |= a0reg; // Install first register
612 int m_imm(WORD inst, WORD siz)
624 int m_imm8(WORD inst, WORD siz)
637 int m_shr(WORD inst, WORD siz)
639 inst |= reg_9[a0reg] | a1reg | siz_6[siz];
649 int m_shi(WORD inst, WORD siz)
651 inst |= a1reg | siz_6[siz];
653 if (a0exattr & DEFINED)
656 return error(range_error);
658 inst |= (a0exval & 7) << 9;
663 AddFixup(FU_QUICK, sloc, a0expr);
672 // {bset, btst, bchg, bclr} -- #immed,ea -- Dn,ea
674 int m_bitop(WORD inst, WORD siz)
676 // Enforce instruction sizes
678 { // X,Dn must be .n or .l
679 if (siz & (SIZB | SIZW))
680 return error(siz_error);
682 else if (siz & (SIZW | SIZL)) // X,ea must be .n or .b
683 return error(siz_error);
685 // Construct instr and EAs
691 ea0gen(SIZB); // Immediate bit number
695 inst |= reg_9[a0reg];
706 int m_dbra(WORD inst, WORD siz)
712 if (a1exattr & DEFINED)
714 if ((a1exattr & TDB) != cursect)
715 return error(rel_error);
717 uint32_t v = a1exval - sloc;
719 if (v + 0x8000 > 0x10000)
720 return error(range_error);
726 AddFixup(FU_WORD | FU_PCREL | FU_ISBRA, sloc, a1expr);
737 int m_exg(WORD inst, WORD siz)
743 if (am0 == DREG && am1 == DREG)
745 else if (am0 == AREG && am1 == AREG)
751 m = a1reg; // Get AREG into a1reg
759 inst |= m | reg_9[a0reg] | a1reg;
769 int m_link(WORD inst, WORD siz)
773 // Is this an error condition???
778 inst &= ~((3 << 9) | (1 << 6) | (1 << 4));
790 WORD extra_addressing[16]=
793 0, //0101 ([bd,An],Xn,od)
794 0x180, //0102 ([bc,An,Xn],od) (111 110 110 111)
796 0, //0104 ([bd,PC],Xn,od)
797 0, //0105 ([bc,PC,Xn],od)
812 // Handle MOVE <C_ALL> <C_ALTDATA>
813 // MOVE <C_ALL> <M_AREG>
815 // Optimize MOVE.L #<smalldata>,D0 to a MOVEQ
817 int m_move(WORD inst, WORD size)
819 // Cast the passed in value to an int
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))
830 m_moveq((WORD)0x7000, (WORD)0);
833 warn("move.l #size,dx converted to moveq");
837 if ((am0 < ABASE) && (am1 < ABASE)) //68000 modes
839 inst |= siz_12[siz] | am_6[am1] | reg_9[a1reg] | am0 | a0reg;
847 ea1gen((WORD)siz | 0x8000); // Tell ea1gen we're move ea,ea
851 inst |= siz_12[siz] | reg_9[a1reg] | extra_addressing[am0 - ABASE];
867 // Handle MOVE <C_ALL030> <C_ALTDATA>
868 // MOVE <C_ALL030> <M_AREG>
870 int m_move30(WORD inst, WORD 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;
890 // move USP,An -- move An,USP
892 int m_usp(WORD inst, WORD siz)
897 inst |= a1reg; // USP, An
899 inst |= a0reg; // An, USP
910 int m_moveq(WORD inst, WORD siz)
914 // Arrange for future fixup
915 if (!(a0exattr & DEFINED))
917 AddFixup(FU_BYTE | FU_SEXT, sloc + 1, a0expr);
920 else if ((uint32_t)a0exval + 0x100 >= 0x200)
921 return error(range_error);
923 inst |= reg_9[a1reg] | (a0exval & 0xFF);
931 // movep Dn, disp(An) -- movep disp(An), Dn
933 int m_movep(WORD inst, WORD siz)
935 // Tell ea0gen to lay off the 0(a0) optimisations on this one
943 inst |= reg_9[a0reg] | a1reg;
953 inst |= reg_9[a1reg] | a0reg;
970 int m_br(WORD inst, WORD siz)
972 if (a0exattr & DEFINED)
974 if ((a0exattr & TDB) != cursect)
976 //printf("m_br(): a0exattr = %X, cursect = %X, a0exval = %X, sloc = %X\n", a0exattr, cursect, a0exval, sloc);
977 return error(rel_error);
980 uint32_t v = (uint32_t)a0exval - (sloc + 2);
982 // Optimize branch instr. size
985 if (CHECK_OPTS(OPT_BSR_BCC_S) && (v != 0) && ((v + 0x80) < 0x100))
992 warn("Bcc.w/BSR.w converted to .s");
999 if ((v + 0x8000) > 0x10000)
1000 return error(range_error);
1008 if (siz == SIZB || siz == SIZS)
1010 if ((v + 0x80) >= 0x100)
1011 return error(range_error);
1018 if ((v + 0x8000) >= 0x10000)
1019 return error(range_error);
1027 else if (siz == SIZN)
1030 if (siz == SIZB || siz == SIZS)
1033 AddFixup(FU_BBRA | FU_PCREL | FU_SEXT, sloc, a0expr);
1041 AddFixup(FU_WORD | FU_PCREL | FU_LBRA | FU_ISBRA, sloc, a0expr);
1052 int m_addq(WORD inst, WORD siz)
1054 inst |= siz_6[siz] | am1 | a1reg;
1056 if (a0exattr & DEFINED)
1058 if ((a0exval > 8) || (a0exval == 0)) // Range in 1..8
1059 return error(range_error);
1061 inst |= (a0exval & 7) << 9;
1066 AddFixup(FU_QUICK, sloc, a0expr);
1079 int m_trap(WORD inst, WORD siz)
1083 if (a0exattr & DEFINED)
1086 return error(abs_error);
1089 return error(range_error);
1095 return error(undef_error);
1102 // movem <rlist>,ea -- movem ea,<rlist>
1104 int m_movem(WORD inst, WORD siz)
1112 return error("bad size suffix");
1119 // Handle #<expr>, ea
1122 if (abs_expr(&eval) != OK)
1125 if (eval >= 0x10000L)
1126 return error(range_error);
1132 if ((*tok >= KW_D0) && (*tok <= KW_A7))
1135 if (reglist(&rmask) < 0)
1140 return error("missing comma");
1145 inst |= am0 | a0reg;
1147 if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
1148 return error("invalid addressing mode");
1150 // If APREDEC, reverse register mask
1156 for(i=0x8000; i; i>>=1, w>>=1)
1157 rmask = (WORD)((rmask << 1) | w & 1);
1166 inst |= 0x0400 | am0 | a0reg;
1169 return error("missing comma");
1172 return error("missing register list");
1179 if (abs_expr(&eval) != OK)
1182 if (eval >= 0x10000)
1183 return error(range_error);
1187 else if (reglist(&rmask) < 0)
1190 if (!(amsktab[am0] & (C_CTRL | M_APOSTINC)))
1191 return error("invalid addressing mode");
1203 // CLR.x An ==> SUBA.x An,An
1205 int m_clra(WORD inst, WORD siz)
1207 inst |= a0reg | reg_9[a0reg] | lwsiz_8[siz];
1214 ////////////////////////////////////////
1216 // 68020/30/40 instructions
1218 ////////////////////////////////////////
1223 int m_br30(WORD inst, WORD siz)
1225 if (a0exattr & DEFINED)
1227 if ((a0exattr & TDB) != cursect)
1228 return error(rel_error);
1230 uint32_t v = (uint32_t)a0exval - (sloc + 2);
1239 AddFixup(FU_LONG | FU_PCREL | FU_SEXT, sloc, a0expr);
1247 // bfchg, bfclr, bfexts, bfextu, bfffo, bfins, bfset
1248 // (68020, 68030, 68040)
1250 int m_bfop(WORD inst, WORD siz)
1252 if ((bfval1 > 31) || (bfval1 < 0))
1253 return error("bfxxx offset: immediate value must be between 0 and 31");
1255 // First instruction word - just the opcode and first EA
1256 // Note: both am1 is ORed because solely of bfins - maybe it's a good idea to make a dedicated function for it?
1263 if (bfval2 > 31 || bfval2 < 0)
1264 return error("bfxxx width: immediate value must be between 0 and 31");
1266 // For Dw both immediate and register number are stuffed
1267 // into the same field O_o
1268 bfparam2 = (bfval2 << 0);
1273 bfparam1 = (bfval1 << 6);
1277 bfparam1 = bfval1 << 12;
1280 D_word((inst | am0 | a0reg | am1 | a1reg));
1281 ea0gen(siz); // Generate EA
1283 // Second instruction word - Dest register (if exists), Do, Offset, Dw, Width
1285 inst = bfparam1 | bfparam2;
1291 inst |= a0reg << 12;
1300 // bkpt (68EC000, 68010, 68020, 68030, 68040, CPU32)
1302 int m_bkpt(WORD inst, WORD siz)
1306 if (a0exattr & DEFINED)
1309 return error(abs_error);
1312 return error(range_error);
1318 return error(undef_error);
1327 int m_callm(WORD inst, WORD siz)
1334 if (a0exattr & DEFINED)
1337 return error(abs_error);
1340 return error(range_error);
1342 inst = (uint16_t)a0exval;
1346 return error(undef_error);
1356 // cas (68020, 68030, 68040)
1358 int m_cas(WORD inst, WORD siz)
1364 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1365 return error(unsupport);
1380 return error("bad size suffix");
1385 if ((*tok < KW_D0) && (*tok > KW_D7))
1386 return error("CAS accepts only data registers");
1388 inst2 = (*tok++) & 7;
1391 return error("missing comma");
1394 if ((*tok < KW_D0) && (*tok > KW_D7))
1395 return error("CAS accepts only data registers");
1397 inst2 |= ((*tok++) & 7) << 6;
1400 return error("missing comma");
1403 if ((modes = amode(1)) < 0)
1407 return error("too many ea fields");
1410 return error("extra (unexpected) text found");
1412 // Reject invalud ea modes
1413 amsk = amsktab[am0];
1415 if ((amsk & (M_AIND | M_APOSTINC | M_APREDEC | M_ADISP | M_AINDEXED | M_ABSW | M_ABSL | M_ABASE | M_MEMPOST | M_MEMPRE)) == 0)
1416 return error("unsupported addressing mode");
1418 inst |= am0 | a0reg;
1428 // cas2 (68020, 68030, 68040)
1430 int m_cas2(WORD inst, WORD siz)
1434 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1435 return error(unsupport);
1450 return error("bad size suffix");
1455 if ((*tok < KW_D0) && (*tok > KW_D7))
1456 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1458 inst2 = (*tok++) & 7;
1461 return error("missing colon");
1464 if ((*tok < KW_D0) && (*tok > KW_D7))
1465 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1467 inst3 = (*tok++) & 7;
1470 return error("missing comma");
1473 if ((*tok < KW_D0) && (*tok > KW_D7))
1474 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1476 inst2 |= ((*tok++) & 7) << 6;
1479 return error("missing colon");
1482 if ((*tok < KW_D0) && (*tok > KW_D7))
1483 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1485 inst3 |= ((*tok++) & 7) << 6;
1488 return error("missing comma");
1492 return error("missing (");
1493 if ((*tok >= KW_D0) && (*tok <= KW_D7))
1494 inst2 |= (((*tok++) & 7) << 12) | (0 << 15);
1495 else if ((*tok >= KW_A0) && (*tok <= KW_A7))
1496 inst2 |= (((*tok++) & 7) << 12) | (1 << 15);
1498 return error("CAS accepts either data or address registers for Rn1:Rn2 pair");
1501 return error("missing (");
1504 return error("missing colon");
1508 return error("missing (");
1509 if ((*tok >= KW_D0) && (*tok <= KW_D7))
1510 inst3 |= (((*tok++) & 7) << 12) | (0 << 15);
1511 else if ((*tok >= KW_A0) && (*tok <= KW_A7))
1512 inst3 |= (((*tok++) & 7) << 12) | (1 << 15);
1514 return error("CAS accepts either data or address registers for Rn1:Rn2 pair");
1517 return error("missing (");
1520 return error("extra (unexpected) text found");
1531 // cmp2 (68020, 68030, 68040, CPU32)
1533 int m_cmp2(WORD inst, WORD siz)
1535 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1536 return error(unsupport);
1538 switch (siz & 0x000F)
1552 WORD flg = inst; // Save flag bits
1553 inst &= ~0x3F; // Clobber flag bits in instr
1555 // Install "standard" instr size bits
1561 // OR-in register number
1563 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1565 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1571 inst |= am1 | a1reg; // Get ea1 into instr
1572 D_word(inst); // Deposit instr
1574 // Generate ea0 if requested
1578 ea1gen(siz); // Generate ea1
1583 inst |= am0 | a0reg; // Get ea0 into instr
1584 D_word(inst); // Deposit instr
1585 ea0gen(siz); // Generate ea0
1587 // Generate ea1 if requested
1592 // If we're called from chk2 then bit 11 of size will be set. This is just
1593 // a dumb mechanism to pass this, required by the extension word. (You might
1594 // have noticed the siz & 15 thing above!)
1595 inst = (a1reg << 12) | (siz & (1 << 11));
1607 // chk2 (68020, 68030, 68040, CPU32)
1609 int m_chk2(WORD inst, WORD siz)
1611 return m_cmp2(inst, siz | (1 << 11));
1616 // cpbcc(68020, 68030)
1618 int m_cpbr(WORD inst, WORD siz)
1620 if ((activecpu & (CPU_68020 | CPU_68030)) == 0)
1621 return error(unsupport);
1623 if (a0exattr & DEFINED)
1625 if ((a0exattr & TDB) != cursect)
1626 return error(rel_error);
1628 uint32_t v = (uint32_t)a0exval - (sloc + 2);
1630 // Optimize branch instr. size
1633 if ((v != 0) && ((v + 0x8000) < 0x10000))
1643 if ((v + 0x8000) >= 0x10000)
1644 return error(range_error);
1652 else if (siz == SIZN)
1659 AddFixup(FU_LONG | FU_PCREL | FU_SEXT, sloc, a0expr);
1667 AddFixup(FU_WORD | FU_PCREL | FU_SEXT, sloc, a0expr);
1676 // cpdbcc(68020, 68030)
1678 int m_cpdbr(WORD inst, WORD siz)
1683 WORD condition = inst & 0x1f; // Grab condition sneakily placed in the lower 5 bits of inst
1684 inst &= 0xffe0; // And then mask them out - you ain't seen me, roit?
1686 inst |= (1 << 9); // Bolt on FPU id
1693 if (a1exattr & DEFINED)
1695 if ((a1exattr & TDB) != cursect)
1696 return error(rel_error);
1698 v = (uint32_t)a1exval - sloc;
1700 if (v + 0x8000 > 0x10000)
1701 return error(range_error);
1707 AddFixup(FU_WORD | FU_PCREL | FU_ISBRA, sloc, a1expr);
1719 int m_divs(WORD inst, WORD siz)
1721 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1722 return error(unsupport);
1724 WORD flg = inst; // Save flag bits
1725 inst &= ~0x3F; // Clobber flag bits in instr
1727 // Install "standard" instr size bits
1733 // OR-in register number
1735 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1737 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1743 inst |= am1 | a1reg; // Get ea1 into instr
1744 D_word(inst); // Deposit instr
1746 // Generate ea0 if requested
1750 ea1gen(siz); // Generate ea1
1755 inst |= am0 | a0reg; // Get ea0 into instr
1756 D_word(inst); // Deposit instr
1757 ea0gen(siz); // Generate ea0
1759 // Generate ea1 if requested
1764 inst = a1reg + (a2reg << 12) + (1 << 11);
1774 int m_muls(WORD inst, WORD siz)
1776 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1777 return error(unsupport);
1779 WORD flg = inst; // Save flag bits
1780 inst &= ~0x3F; // Clobber flag bits in instr
1782 // Install "standard" instr size bits
1788 // OR-in register number
1790 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1792 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1798 inst |= am1 | a1reg; // Get ea1 into instr
1799 D_word(inst); // Deposit instr
1802 inst = a1reg + (a2reg << 12) + (1 << 11);
1803 inst |= mulmode; // add size bit
1806 // Generate ea0 if requested
1810 ea1gen(siz); // Generate ea1
1815 inst |= am0 | a0reg; // Get ea0 into instr
1816 D_word(inst); // Deposit instr
1818 inst = a1reg + (a2reg << 12) + (1 << 11);
1819 inst |= mulmode; // add size bit
1822 ea0gen(siz); // Generate ea0
1824 // Generate ea1 if requested
1839 int m_divu(WORD inst, WORD siz)
1841 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1842 return error(unsupport);
1844 //WARNING("divu.l d0,d1 is actually divul.l d0,d1:d1!!!")
1846 WORD flg = inst; // Save flag bits
1847 inst &= ~0x3F; // Clobber flag bits in instr
1849 // Install "standard" instr size bits
1855 // OR-in register number
1857 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1859 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1865 inst |= am1 | a1reg; // Get ea1 into instr
1866 D_word(inst); // Deposit instr
1868 // Generate ea0 if requested
1872 ea1gen(siz); // Generate ea1
1877 inst |= am0 | a0reg; // Get ea0 into instr
1878 D_word(inst); // Deposit instr
1879 ea0gen(siz); // Generate ea0
1881 // Generate ea1 if requested
1886 inst = a1reg + (a2reg << 12);
1896 int m_mulu(WORD inst, WORD siz)
1898 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1899 return error(unsupport);
1901 WORD flg = inst; // Save flag bits
1902 inst &= ~0x3F; // Clobber flag bits in instr
1904 // Install "standard" instr size bits
1910 // OR-in register number
1912 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1914 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1920 inst |= am1 | a1reg; // Get ea1 into instr
1921 D_word(inst); // Deposit instr
1923 // Generate ea0 if requested
1927 ea1gen(siz); // Generate ea1
1932 inst |= am0 | a0reg; // Get ea0 into instr
1933 D_word(inst); // Deposit instr
1934 ea0gen(siz); // Generate ea0
1936 // Generate ea1 if requested
1941 inst = a1reg + (a2reg << 12);
1942 inst |= mulmode; // add size bit
1952 int m_divsl(WORD inst, WORD siz)
1954 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1955 return error(unsupport);
1957 WORD flg = inst; // Save flag bits
1958 inst &= ~0x3F; // Clobber flag bits in instr
1960 // Install "standard" instr size bits
1966 // OR-in register number
1968 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1970 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1976 inst |= am1 | a1reg; // Get ea1 into instr
1977 D_word(inst); // Deposit instr
1979 // Generate ea0 if requested
1983 ea1gen(siz); // Generate ea1
1988 inst |= am0 | a0reg; // Get ea0 into instr
1989 D_word(inst); // Deposit instr
1990 ea0gen(siz); // Generate ea0
1992 // Generate ea1 if requested
1997 inst = a1reg + (a2reg << 12) + (1 << 11) + (1 << 10);
2006 int m_divul(WORD inst, WORD siz)
2008 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
2009 return error(unsupport);
2011 WORD flg = inst; // Save flag bits
2012 inst &= ~0x3F; // Clobber flag bits in instr
2014 // Install "standard" instr size bits
2020 // OR-in register number
2022 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
2024 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
2030 inst |= am1 | a1reg; // Get ea1 into instr
2031 D_word(inst); // Deposit instr
2033 // Generate ea0 if requested
2037 ea1gen(siz); // Generate ea1
2042 inst |= am0 | a0reg; // Get ea0 into instr
2043 D_word(inst); // Deposit instr
2044 ea0gen(siz); // Generate ea0
2046 // Generate ea1 if requested
2051 inst = a1reg + (a2reg << 12) + (1 << 10);
2059 // move16 (ax)+,(ay)+
2061 int m_move16a(WORD inst, WORD siz)
2063 if ((activecpu & (CPU_68040 | CPU_68060)) == 0)
2064 return error(unsupport);
2068 inst = (1 << 15) + (a1reg << 12);
2076 // move16 with absolute address
2078 int m_move16b(WORD inst, WORD siz)
2080 if ((activecpu & (CPU_68040 | CPU_68060)) == 0)
2081 return error(unsupport);
2087 if (am0 == APOSTINC)
2090 return error("Wasn't this suppose to call m_move16a???");
2093 //move16 (ax)+,(xxx).L
2098 else if (am0 == ABSL)
2102 //move16 (xxx).L,(ax)+
2108 //move16 (xxx).L,(ax)
2113 else if (am0 == AIND)
2115 //move16 (ax),(xxx).L
2128 // pack/unpack (68020/68030/68040)
2130 int m_pack(WORD inst, WORD siz)
2135 return error("bad size suffix");
2137 if (*tok >= KW_D0 && *tok <= KW_D7)
2139 // Dx,Dy,#<adjustment>
2140 inst |= (0 << 3); // R/M
2141 inst |= (*tok++ & 7);
2142 if (*tok != ',' && tok[2] != ',')
2143 return error("missing comma");
2144 if (tok[1] < KW_D0 && tok[1] > KW_D7)
2145 return error(syntax_error);
2146 inst |= ((tok[1] & 7)<<9);
2149 // Fall through for adjustment (common in both valid cases)
2151 else if (*tok == '-')
2153 // -(Ax),-(Ay),#<adjustment>
2154 inst |= (1 << 3); // R/M
2155 tok++; // eat the minus
2156 if ((*tok != '(') && (tok[2]!=')') && (tok[3]!=',') && (tok[4] != '-') && (tok[5] != '(') && (tok[7] != ')') && (tok[8] != ','))
2157 return error(syntax_error);
2158 if (tok[1] < KW_A0 && tok[1] > KW_A7)
2159 return error(syntax_error);
2160 if (tok[5] < KW_A0 && tok[6] > KW_A7)
2161 return error(syntax_error);
2162 inst |= ((tok[1] & 7) << 0);
2163 inst |= ((tok[6] & 7) << 9);
2166 // Fall through for adjustment (common in both valid cases)
2169 return error("invalid syntax");
2172 if ((*tok != CONST) && (*tok != SYMBOL) && (*tok != '-'))
2173 return error(syntax_error);
2175 if (expr(a0expr, &a0exval, &a0exattr, &a0esym)==ERROR)
2178 if ((a0exattr & DEFINED) == 0)
2179 return error(undef_error);
2181 if (a0exval + 0x8000 > 0x10000)
2185 return error(extra_stuff);
2187 D_word((a0exval & 0xffff));
2199 int m_rtm(WORD inst, WORD siz)
2207 else if (am0 == AREG)
2209 inst |= (1 << 3) + a0reg;
2212 return error("rtm only allows data or address registers.");
2223 int m_rtd(WORD inst, WORD siz)
2227 if (a0exattr & DEFINED)
2230 return error(abs_error);
2232 if ((a0exval + 0x8000) <= 0x7FFF)
2233 return error(range_error);
2239 return error(undef_error);
2248 int m_trapcc(WORD inst, WORD siz)
2256 else if (am0 == IMMED)
2260 if (a0exval < 0x10000)
2267 return error("Immediate value too big");
2277 return error("Invalid parameter for trapcc");
2284 // cinvl/p/a (68040)
2286 int m_cinv(WORD inst, WORD siz)
2291 inst |= (0 << 6) | (a1reg);
2295 inst |= (2 << 6) | (a1reg);
2298 inst |= (1 << 6) | (a1reg);
2301 inst |= (3 << 6) | (a1reg);
2311 // cpRESTORE (68020, 68030)
2313 int m_cprest(WORD inst, WORD siz)
2315 if (activecpu & !(CPU_68020 | CPU_68030))
2316 return error(unsupport);
2318 inst |= am0 | a0reg;
2327 // movec (68010, 68020, 68030, 68040, CPU32)
2329 int m_movec(WORD inst, WORD siz)
2333 if (am0 == DREG || am0 == AREG)
2341 inst = (0 << 15) + (a0reg << 12) + CREGlut[a1reg];
2346 inst = (1 << 15) + (a0reg << 12) + CREGlut[a1reg];
2357 inst = (0 << 15) + (a1reg << 12) + CREGlut[a0reg];
2362 inst = (1 << 15) + (a1reg << 12) + CREGlut[a0reg];
2372 // moves (68010, 68020, 68030, 68040, CPU32)
2374 int m_moves(WORD inst, WORD siz)
2376 if (activecpu & !(CPU_68020 | CPU_68030 | CPU_68040))
2377 return error(unsupport);
2383 else if (siz == SIZL)
2394 inst |= am1 | a1reg;
2396 inst = (a0reg << 12) | (1 << 11) | (0 << 15);
2399 else if (am0 == AREG)
2401 inst |= am1 | a1reg;
2403 inst = (a0reg << 12) | (1 << 11) | (1 << 15);
2410 inst |= am0 | a0reg;
2412 inst = (a1reg << 12) | (0 << 11) | (0 << 15);
2417 inst |= am0 | a0reg;
2419 inst = (a1reg << 12) | (0 << 11) | (1 << 15);
2431 int m_pbcc(WORD inst, WORD siz)
2434 return error("Not implemented yet.");
2439 // pflusha (68030, 68040)
2441 int m_pflusha(WORD inst, WORD siz)
2443 if (activecpu == CPU_68030)
2446 inst = (1 << 13) | (1 << 10) | (0 << 5) | 0;
2450 else if (activecpu == CPU_68040)
2452 inst = B16(11110101, 00011000);
2457 return error(unsupport);
2465 // pflush (68030, 68040, 68060)
2467 int m_pflush(WORD inst, WORD siz)
2469 if (activecpu == CPU_68030)
2472 // PFLUSH FC, MASK, < ea >
2478 if (*tok != CONST && *tok != SYMBOL)
2479 return error("function code should be an expression");
2480 if (expr(a0expr, &a0exval, &a0exattr, &a0esym) == ERROR)
2482 if ((a0exattr & DEFINED) == 0)
2483 return error("function code immediate should be defined");
2484 if (a0exval > 7 && a0exval < 0)
2485 return error("function code out of range (0-7)");
2486 fc = (uint16_t)a0exval;
2496 fc = (1 << 4) | (*tok++ & 7);
2507 return error(syntax_error);
2511 return error("comma exptected");
2514 return error("mask should be an immediate value");
2515 if (*tok != CONST && *tok != SYMBOL)
2516 return error("mask is supposed to be immediate");
2517 if (expr(a0expr, &a0exval, &a0exattr, &a0esym) == ERROR)
2519 if ((a0exattr & DEFINED) == 0)
2520 return error("mask immediate value should be defined");
2521 if (a0exval > 7 && a0exval < 0)
2522 return error("function code out of range (0-7)");
2523 mask = (uint16_t)a0exval << 5;
2529 inst = (1 << 13) | fc | mask | (4 << 10);
2533 else if (*tok == ',')
2535 // PFLUSH FC, MASK, < ea >
2537 if (amode(0) == ERROR)
2540 return error(extra_stuff);
2541 if (am0 == AIND || am0 == ABSW || am0 == ABSL || am0 == ADISP || am0 == ADISP || am0 == AINDEXED || am0 == ABASE || am0 == MEMPOST || am0 == MEMPRE)
2543 inst |= am0 | a0reg;
2545 inst = (1 << 13) | fc | mask | (6 << 10);
2551 return error("unsupported addressing mode");
2555 return error(syntax_error);
2560 else if (activecpu == CPU_68040 || activecpu == CPU_68060)
2564 if (*tok != '(' && tok[2] != ')')
2565 return error(syntax_error);
2566 if (tok[1] < KW_A0 && tok[1] > KW_A7)
2567 return error("expected (An)");
2568 if ((inst & 7) == 7)
2569 // With pflushn/pflush there's no easy way to
2570 // distinguish between the two in 68040 mode.
2571 // Ideally the opcode bitfields would have been
2572 // hardcoded in 68ktab but there is aliasing
2573 // between 68030 and 68040 opcode. So we just
2574 // set the 3 lower bits to 1 in pflushn inside
2575 // 68ktab and detect it here.
2576 inst = (inst & 0xff8) | 8;
2577 inst |= (tok[1] & 7) | (5 << 8);
2579 return error(extra_stuff);
2583 return error(unsupport);
2592 int m_pflushr(WORD inst, WORD siz)
2596 WORD flg = inst; // Save flag bits
2597 inst &= ~0x3F; // Clobber flag bits in instr
2599 // Install "standard" instr size bits
2605 // OR-in register number
2607 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
2609 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
2615 inst |= am1 | a1reg; // Get ea1 into instr
2616 D_word(inst); // Deposit instr
2618 // Generate ea0 if requested
2622 ea1gen(siz); // Generate ea1
2627 inst |= am0 | a0reg; // Get ea0 into instr
2628 D_word(inst); // Deposit instr
2629 ea0gen(siz); // Generate ea0
2631 // Generate ea1 if requested
2636 D_word(B16(10100000, 00000000));
2642 // ploadr, ploadw (68030)
2644 int m_pload(WORD inst, WORD siz, WORD extension)
2646 // TODO: 68551 support is not added yet.
2647 // None of the ST series of computers had
2648 // a 68020 + 68551 socket and since this is
2649 // an Atari targetted assembler....
2659 if (a0reg == KW_SFC - KW_SFC)
2663 else if (a0reg == KW_DFC - KW_SFC)
2668 return error("illegal control register specified");
2671 inst = (1 << 3) | a0reg;
2674 if ((a0exattr & DEFINED) == 0)
2675 return error("constant value must be defined");
2676 inst = (2 << 3) | (uint16_t)a0exval;
2680 inst |= extension | (1 << 13);
2688 int m_ploadr(WORD inst, WORD siz)
2690 return m_pload(inst, siz, 1 << 9);
2693 int m_ploadw(WORD inst, WORD siz)
2695 return m_pload(inst, siz, 0 << 9);
2699 // pmove (68030/68551)
2701 int m_pmove(WORD inst, WORD siz)
2705 // TODO: 68551 support is not added yet.
2706 // None of the ST series of computers had
2707 // a 68020 + 68551 socket and since this is
2708 // an Atari targetted assembler....
2709 // (same for 68EC030)
2712 inst2 = inst & (1 << 8); //Copy the flush bit over to inst2 in case we're called from m_pmovefd
2713 inst &= ~(1 << 8); //And mask it out
2720 else if (am1 == CREG)
2726 return error("pmove sez: Wut?");
2728 // The instruction is a quad-word (8 byte) operation
2729 // for the CPU root pointer and the supervisor root pointer.
2730 // It is a long - word operation for the translation control register
2731 // and the transparent translation registers(TT0 and TT1).
2732 // It is a word operation for the MMU status register.
2734 if (((reg == (KW_URP - KW_SFC)) || (reg == (KW_SRP - KW_SFC)))
2735 && ((siz != SIZD) && (siz != SIZN)))
2736 return error(siz_error);
2738 if (((reg == (KW_TC - KW_SFC)) || (reg == (KW_TT0 - KW_SFC)) || (reg == (KW_TT1 - KW_SFC)))
2739 && ((siz != SIZL) && (siz != SIZN)))
2740 return error(siz_error);
2742 if ((reg == (KW_MMUSR - KW_SFC)) && ((siz != SIZW) && (siz != SIZN)))
2743 return error(siz_error);
2748 inst |= am1 | a1reg;
2751 else if (am1 == CREG)
2753 inst |= am0 | a0reg;
2757 switch (reg + KW_SFC)
2760 inst2 |= (0 << 10) + (1 << 14); break;
2762 inst2 |= (2 << 10) + (1 << 14); break;
2764 inst2 |= (3 << 10) + (1 << 14); break;
2766 inst2 |= (2 << 10) + (0 << 13); break;
2768 inst2 |= (3 << 10) + (0 << 13); break;
2771 inst2 |= (1 << 9) + (3 << 13);
2773 inst2 |= (0 << 9) + (3 << 13);
2776 return error("unsupported register");
2786 else if (am1 == CREG)
2798 int m_pmovefd(WORD inst, WORD siz)
2802 return m_pmove(inst | (1 << 8), siz);
2808 #define gen_ptrapcc(name,opcode) \
2809 int m_##name(WORD inst, WORD siz) \
2815 D_word(B8(opcode)); \
2822 D_word(B8(opcode)); \
2827 int m_##name##n(WORD inst, WORD siz) \
2831 D_word(B8(opcode)); \
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)
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; }
2887 // ptestr, ptestw (68030)
2889 int m_ptest(WORD inst, WORD siz)
2893 if (activecpu == CPU_68030)
2894 return error("Not implemented yet.");
2895 else if (activecpu == CPU_68040)
2896 return error("Not implemented yet.");
2902 #define FPU_NOWARN 0
2903 #define FPU_P_EMUL 1
2904 #define FPU_P2_EMU 2
2909 // Generate a FPU opcode
2911 static inline int gen_fpu(WORD inst, WORD siz, WORD opmode, WORD emul)
2913 if (am0 < AM_NONE) // Check first operand for ea or fp - is this right?
2915 inst |= (1 << 9); // Bolt on FPU id
2922 inst = 1 << 14; // R/M field (we have ea so have to set this to 1)
2926 case SIZB: inst |= (6 << 10); break;
2927 case SIZW: inst |= (4 << 10); break;
2928 case SIZL: inst |= (0 << 10); break;
2930 case SIZS: inst |= (1 << 10); break;
2931 case SIZD: inst |= (5 << 10); break;
2932 case SIZX: inst |= (2 << 10); break;
2937 warn("This encoding will cause an unimplemented data type exception in the MC68040 to allow emulation in software.");
2941 return error("Something bad happened, possibly, in gen_fpu.");
2945 inst |= (a1reg << 7);
2952 inst |= (1 << 9); //Bolt on FPU id
2956 inst |= (a1reg << 7);
2961 if ((emul & FPU_FPSP) && (activefpu == FPU_68040))
2962 warn("Instruction is emulated in 68040");
2969 // fabs, fsabs, fdabs (6888X, 68040)
2971 int m_fabs(WORD inst, WORD siz)
2973 return gen_fpu(inst, siz, B8(00011000), FPU_P_EMUL);
2977 int m_fsabs(WORD inst, WORD siz)
2979 if (activefpu == FPU_68040)
2980 return gen_fpu(inst, siz, B8(01011000), FPU_P_EMUL);
2982 return error("Unsupported in current FPU");
2986 int m_fdabs(WORD inst, WORD siz)
2988 if (activefpu == FPU_68040)
2989 return gen_fpu(inst, siz, B8(01011100), FPU_P_EMUL);
2991 return error("Unsupported in current FPU");
2996 // facos (6888X, 68040FPSP)
2998 int m_facos(WORD inst, WORD siz)
3000 return gen_fpu(inst, siz, B8(00011100), FPU_FPSP);
3005 // fadd (6888X, 68040FPSP)
3007 int m_fadd(WORD inst, WORD siz)
3009 return gen_fpu(inst, siz, B8(00100010), FPU_P_EMUL);
3013 int m_fsadd(WORD inst, WORD siz)
3015 if (activefpu == FPU_68040)
3016 return gen_fpu(inst, siz, B8(01100010), FPU_P_EMUL);
3018 return error("Unsupported in current FPU");
3022 int m_fdadd(WORD inst, WORD siz)
3024 if (activefpu == FPU_68040)
3025 return gen_fpu(inst, siz, B8(01100110), FPU_P_EMUL);
3027 return error("Unsupported in current FPU");
3032 // fasin (6888X, 68040FPSP)f
3034 int m_fasin(WORD inst, WORD siz)
3036 return gen_fpu(inst, siz, B8(00001100), FPU_FPSP);
3041 // fatan (6888X, 68040FPSP)
3043 int m_fatan(WORD inst, WORD siz)
3045 return gen_fpu(inst, siz, B8(00001010), FPU_FPSP);
3050 // fatanh (6888X, 68040FPSP)
3052 int m_fatanh(WORD inst, WORD siz)
3054 return gen_fpu(inst, siz, B8(00001101), FPU_FPSP);
3059 // fcmp (6888X, 68040)
3061 int m_fcmp(WORD inst, WORD siz)
3063 return gen_fpu(inst, siz, B8(00111000), FPU_P_EMUL);
3068 // fcos (6888X, 68040FPSP)
3070 int m_fcos(WORD inst, WORD siz)
3072 return gen_fpu(inst, siz, B8(00011101), FPU_FPSP);
3077 // fcosh (6888X, 68040FPSP)
3079 int m_fcosh(WORD inst, WORD siz)
3081 return gen_fpu(inst, siz, B8(00011001), FPU_FPSP);
3086 // fdbcc (6888X, 68040)
3088 int m_fdbcc(WORD inst, WORD siz)
3090 WORD opcode = inst & 0x3F; //Grab conditional bitfield
3100 if (a1exattr & DEFINED)
3102 if ((a1exattr & TDB) != cursect)
3103 return error(rel_error);
3105 uint32_t v = (uint32_t)a1exval - sloc;
3107 if ((v + 0x8000) > 0x10000)
3108 return error(range_error);
3114 AddFixup(FU_WORD | FU_PCREL | FU_ISBRA, sloc, a1expr);
3123 // fdiv (6888X, 68040)
3125 int m_fdiv(WORD inst, WORD siz)
3127 return gen_fpu(inst, siz, B8(00100000), FPU_P_EMUL);
3131 int m_fsdiv(WORD inst, WORD siz)
3133 if (activefpu == FPU_68040)
3134 return gen_fpu(inst, siz, B8(01100000), FPU_P_EMUL);
3136 return error("Unsupported in current FPU");
3140 int m_fddiv(WORD inst, WORD siz)
3142 if (activefpu == FPU_68040)
3143 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
3145 return error("Unsupported in current FPU");
3150 // fetox (6888X, 68040FPSP)
3152 int m_fetox(WORD inst, WORD siz)
3154 return gen_fpu(inst, siz, B8(00010000), FPU_FPSP);
3159 // fetoxm1 (6888X, 68040FPSP)
3161 int m_fetoxm1(WORD inst, WORD siz)
3163 return gen_fpu(inst, siz, B8(00001000), FPU_FPSP);
3168 // fgetexp (6888X, 68040FPSP)
3170 int m_fgetexp(WORD inst, WORD siz)
3172 return gen_fpu(inst, siz, B8(00011110), FPU_FPSP);
3177 // fgetman (6888X, 68040FPSP)
3179 int m_fgetman(WORD inst, WORD siz)
3181 return gen_fpu(inst, siz, B8(00011111), FPU_FPSP);
3186 // fint (6888X, 68040FPSP)
3188 int m_fint(WORD inst, WORD siz)
3191 // special case - fint fpx = fint fpx,fpx
3194 return gen_fpu(inst, siz, B8(00000001), FPU_FPSP);
3199 // fintrz (6888X, 68040FPSP)
3201 int m_fintrz(WORD inst, WORD siz)
3204 // special case - fintrz fpx = fintrz fpx,fpx
3207 return gen_fpu(inst, siz, B8(00000011), FPU_FPSP);
3212 // flog10 (6888X, 68040FPSP)
3214 int m_flog10(WORD inst, WORD siz)
3216 return gen_fpu(inst, siz, B8(00010101), FPU_FPSP);
3221 // flog2 (6888X, 68040FPSP)
3223 int m_flog2(WORD inst, WORD siz)
3225 return gen_fpu(inst, siz, B8(00010110), FPU_FPSP);
3230 // flogn (6888X, 68040FPSP)
3232 int m_flogn(WORD inst, WORD siz)
3234 return gen_fpu(inst, siz, B8(00010100), FPU_FPSP);
3239 // flognp1 (6888X, 68040FPSP)
3241 int m_flognp1(WORD inst, WORD siz)
3243 return gen_fpu(inst, siz, B8(00000110), FPU_FPSP);
3248 // fmod (6888X, 68040FPSP)
3250 int m_fmod(WORD inst, WORD siz)
3252 return gen_fpu(inst, siz, B8(00100001), FPU_FPSP);
3257 // fmove (6888X, 68040)
3259 int m_fmove(WORD inst, WORD siz)
3263 if ((am0 == FREG) && (am1 < AM_USP))
3267 inst |= am1 | a1reg;
3276 case SIZB: inst |= (6 << 10); break;
3277 case SIZW: inst |= (4 << 10); break;
3278 case SIZL: inst |= (0 << 10); break;
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
3291 inst |= bfval1 << 4;
3296 if (bfval1>63 && bfval1<-64)
3297 return error("K-factor must be between -64 and 63");
3298 inst |= bfval1 & 127;
3303 return error("Something bad happened, possibly.");
3308 // Destination specifier
3309 inst |= (a0reg << 7);
3317 else if ((am0 < AM_USP) && (am1 == FREG))
3322 inst |= am0 | a0reg;
3331 case SIZB: inst |= (6 << 10); break;
3332 case SIZW: inst |= (4 << 10); break;
3333 case SIZL: inst |= (0 << 10); break;
3335 case SIZS: inst |= (1 << 10); break;
3336 case SIZD: inst |= (5 << 10); break;
3337 case SIZX: inst |= (2 << 10); break;
3338 case SIZP: inst |= (3 << 10); break;
3340 return error("Something bad happened, possibly.");
3344 // Destination specifier
3345 inst |= (a1reg << 7);
3353 else if ((am0 == FREG) && (am1 == FREG))
3355 // register-to-register
3356 // Essentially ea to register with R/0=0
3366 return error("Invalid size");
3369 inst |= (a0reg << 10);
3371 // Destination register
3372 inst |= (a1reg << 7);
3382 // fmove (6888X, 68040)
3384 int m_fmovescr(WORD inst, WORD siz)
3386 // Move Floating-Point System Control Register (FPCR)
3390 if ((am0 == FPSCR) && (am1 < AM_USP))
3392 inst |= am1 | a1reg;
3394 inst = (1 << 13) + (1 << 15);
3400 else if ((am1 == FPSCR) && (am0 < AM_USP))
3402 inst |= am0 | a0reg;
3404 inst = (0 << 13) + (1 << 15);
3411 return error("m_fmovescr says: wut?");
3415 // fsmove/fdmove (68040)
3417 int m_fsmove(WORD inst, WORD siz)
3419 return error("Not implemented yet.");
3422 if (activefpu == FPU_68040)
3423 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
3425 return error("Unsupported in current FPU");
3430 int m_fdmove(WORD inst, WORD siz)
3432 return error("Not implemented yet.");
3435 if (activefpu == FPU_68040)
3436 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
3438 return error("Unsupported in current FPU");
3444 // fmovecr (6888X, 68040FPSP)
3446 int m_fmovecr(WORD inst, WORD siz)
3454 if (activefpu == FPU_68040)
3455 warn("Instruction is emulated in 68040");
3462 // fmovem (6888X, 68040)
3464 int m_fmovem(WORD inst, WORD siz)
3469 if (siz == SIZX || siz==SIZN)
3471 if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
3473 //fmovem.x <rlist>,ea
3474 if (fpu_reglist_left(®mask) < 0)
3478 return error("missing comma");
3483 inst |= am0 | a0reg;
3485 if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
3486 return error("invalid addressing mode");
3489 inst = (1 << 15) | (1 << 14) | (1 << 13) | (0 << 11) | regmask;
3494 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
3497 datareg = (*tok++ & 7) << 10;
3500 return error("missing comma");
3505 inst |= am0 | a0reg;
3507 if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
3508 return error("invalid addressing mode");
3511 inst = (1 << 15) | (1 << 14) | (1 << 13) | (1 << 11) | (datareg << 4);
3522 inst |= am0 | a0reg;
3525 return error("missing comma");
3527 if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
3529 //fmovem.x ea,<rlist>
3530 if (fpu_reglist_right(®mask) < 0)
3534 inst = (1 << 15) | (1 << 14) | (0 << 13) | (2 << 11) | regmask;
3542 datareg = (*tok++ & 7) << 10;
3544 inst = (1 << 15) | (1 << 14) | (0 << 13) | (3 << 11) | (datareg << 4);
3551 else if (siz == SIZL)
3553 if ((*tok == KW_FPCR) || (*tok == KW_FPSR) || (*tok == KW_FPIAR))
3555 //fmovem.l <rlist>,ea
3556 regmask = (1 << 15) | (1 << 13);
3558 if (*tok == KW_FPCR)
3560 regmask |= (1 << 12);
3565 if (*tok == KW_FPSR)
3567 regmask |= (1 << 11);
3572 if (*tok == KW_FPIAR)
3574 regmask |= (1 << 10);
3579 if ((*tok == '/') || (*tok == '-'))
3586 return error("missing comma");
3591 inst |= am0 | a0reg;
3598 //fmovem.l ea,<rlist>
3602 inst |= am0 | a0reg;
3605 return error("missing comma");
3607 regmask = (1 << 15) | (0 << 13);
3610 if (*tok == KW_FPCR)
3612 regmask |= (1 << 12);
3617 if (*tok == KW_FPSR)
3619 regmask |= (1 << 11);
3624 if (*tok == KW_FPIAR)
3626 regmask |= (1 << 10);
3631 if ((*tok == '/') || (*tok == '-'))
3638 return error("extra (unexpected) text found");
3640 inst |= am0 | a0reg;
3647 return error("bad size suffix");
3654 // fmul (6888X, 68040)
3656 int m_fmul(WORD inst, WORD siz)
3658 return gen_fpu(inst, siz, B8(00100011), FPU_P_EMUL);
3662 int m_fsmul(WORD inst, WORD siz)
3664 if (activefpu == FPU_68040)
3665 return gen_fpu(inst, siz, B8(01100011), FPU_P_EMUL);
3667 return error("Unsupported in current FPU");
3671 int m_fdmul(WORD inst, WORD siz)
3673 if (activefpu == FPU_68040)
3674 return gen_fpu(inst, siz, B8(01100111), FPU_P_EMUL);
3676 return error("Unsupported in current FPU");
3681 // fneg (6888X, 68040)
3683 int m_fneg(WORD inst, WORD siz)
3685 return gen_fpu(inst, siz, B8(00011010), FPU_P_EMUL);
3689 int m_fsneg(WORD inst, WORD siz)
3691 if (activefpu == FPU_68040)
3692 return gen_fpu(inst, siz, B8(01011010), FPU_P_EMUL);
3694 return error("Unsupported in current FPU");
3698 int m_fdneg(WORD inst, WORD siz)
3700 if (activefpu == FPU_68040)
3701 return gen_fpu(inst, siz, B8(01011110), FPU_P_EMUL);
3703 return error("Unsupported in current FPU");
3708 // fnop (6888X, 68040)
3710 int m_fnop(WORD inst, WORD siz)
3712 return gen_fpu(inst, siz, B8(00000000), FPU_P_EMUL);
3717 // frem (6888X, 68040FPSP)
3719 int m_frem(WORD inst, WORD siz)
3721 return gen_fpu(inst, siz, B8(00100101), FPU_FPSP);
3726 // fscale (6888X, 68040FPSP)
3728 int m_fscale(WORD inst, WORD siz)
3730 return gen_fpu(inst, siz, B8(00100110), FPU_FPSP);
3735 // FScc (6888X, 68040)
3737 //int m_fseq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000001)); return OK;}
3738 //int m_fsne (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001110)); return OK;}
3739 //int m_fsgt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010010)); return OK;}
3740 //int m_fsngt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011101)); return OK;}
3741 //int m_fsge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010011)); return OK;}
3742 //int m_fsnge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011100)); return OK;}
3743 //int m_fslt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010100)); return OK;}
3744 //int m_fsnlt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011011)); return OK;}
3745 //int m_fsle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010101)); return OK;}
3746 //int m_fsnle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011010)); return OK;}
3747 //int m_fsgl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010110)); return OK;}
3748 //int m_fsngl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011001)); return OK;}
3749 //int m_fsgle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010111)); return OK;}
3750 //int m_fsngle(WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011000)); return OK;}
3751 //int m_fsogt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000010)); return OK;}
3752 //int m_fsule (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001101)); return OK;}
3753 //int m_fsoge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000011)); return OK;}
3754 //int m_fsult (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001100)); return OK;}
3755 //int m_fsolt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000100)); return OK;}
3756 //int m_fsuge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001011)); return OK;}
3757 //int m_fsole (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000101)); return OK;}
3758 //int m_fsugt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001010)); return OK;}
3759 //int m_fsogl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000110)); return OK;}
3760 //int m_fsueq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001001)); return OK;}
3761 //int m_fsor (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000111)); return OK;}
3762 //int m_fsun (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001000)); return OK;}
3763 //int m_fsf (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000000)); return OK;}
3764 //int m_fst (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001111)); return OK;}
3765 //int m_fssf (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010000)); return OK;}
3766 //int m_fsst (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011111)); return OK;}
3767 //int m_fsseq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010001)); return OK;}
3768 //int m_fssne (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011110)); return OK;}
3770 #define gen_FScc(name, opcode) int m_##name (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(opcode)); return OK;}
3771 gen_FScc(fseq , 00000001);
3772 gen_FScc(fsne , 00001110);
3773 gen_FScc(fsgt , 00010010);
3774 gen_FScc(fsngt , 00011101);
3775 gen_FScc(fsge , 00010011);
3776 gen_FScc(fsnge , 00011100);
3777 gen_FScc(fslt , 00010100);
3778 gen_FScc(fsnlt , 00011011);
3779 gen_FScc(fsle , 00010101);
3780 gen_FScc(fsnle , 00011010);
3781 gen_FScc(fsgl , 00010110);
3782 gen_FScc(fsngl , 00011001);
3783 gen_FScc(fsgle , 00010111);
3784 gen_FScc(fsngle, 00011000);
3785 gen_FScc(fsogt , 00000010);
3786 gen_FScc(fsule , 00001101);
3787 gen_FScc(fsoge , 00000011);
3788 gen_FScc(fsult , 00001100);
3789 gen_FScc(fsolt , 00000100);
3790 gen_FScc(fsuge , 00001011);
3791 gen_FScc(fsole , 00000101);
3792 gen_FScc(fsugt , 00001010);
3793 gen_FScc(fsogl , 00000110);
3794 gen_FScc(fsueq , 00001001);
3795 gen_FScc(fsor , 00000111);
3796 gen_FScc(fsun , 00001000);
3797 gen_FScc(fsf , 00000000);
3798 gen_FScc(fst , 00001111);
3799 gen_FScc(fssf , 00010000);
3800 gen_FScc(fsst , 00011111);
3801 gen_FScc(fsseq , 00010001);
3802 gen_FScc(fssne , 00011110);
3805 // FTRAPcc (6888X, 68040)
3807 //int m_ftrapeq (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000001)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000001)); D_long(a0exval); } return OK;}
3808 //int m_ftrapne (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001110)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001110)); D_long(a0exval); } return OK;}
3809 //int m_ftrapgt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010010)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010010)); D_long(a0exval); } return OK;}
3810 //int m_ftrapngt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011101)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011101)); D_long(a0exval); } return OK;}
3811 //int m_ftrapge (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010011)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010011)); D_long(a0exval); } return OK;}
3812 //int m_ftrapnge (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011100)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011100)); D_long(a0exval); } return OK;}
3813 //int m_ftraplt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010100)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010100)); D_long(a0exval); } return OK;}
3814 //int m_ftrapnlt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011011)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011011)); D_long(a0exval); } return OK;}
3815 //int m_ftraple (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010101)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010101)); D_long(a0exval); } return OK;}
3816 //int m_ftrapnle (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011010)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011010)); D_long(a0exval); } return OK;}
3817 //int m_ftrapgl (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010110)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010110)); D_long(a0exval); } return OK;}
3818 //int m_ftrapngl (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011001)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011001)); D_long(a0exval); } return OK;}
3819 //int m_ftrapgle (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010111)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010111)); D_long(a0exval); } return OK;}
3820 //int m_ftrapngle(WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011000)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011000)); D_long(a0exval); } return OK;}
3821 //int m_ftrapogt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000010)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000010)); D_long(a0exval); } return OK;}
3822 //int m_ftrapule (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001101)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001101)); D_long(a0exval); } return OK;}
3823 //int m_ftrapoge (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000011)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000011)); D_long(a0exval); } return OK;}
3824 //int m_ftrapult (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001100)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001100)); D_long(a0exval); } return OK;}
3825 //int m_ftrapolt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000100)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000100)); D_long(a0exval); } return OK;}
3826 //int m_ftrapuge (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001011)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001011)); D_long(a0exval); } return OK;}
3827 //int m_ftrapole (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000101)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000101)); D_long(a0exval); } return OK;}
3828 //int m_ftrapugt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001010)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001010)); D_long(a0exval); } return OK;}
3829 //int m_ftrapogl (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000110)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000110)); D_long(a0exval); } return OK;}
3830 //int m_ftrapueq (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001001)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001001)); D_long(a0exval); } return OK;}
3831 //int m_ftrapor (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000111)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000111)); D_long(a0exval); } return OK;}
3832 //int m_ftrapun (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001000)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001000)); D_long(a0exval); } return OK;}
3833 //int m_ftrapf (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00000000)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00000000)); D_long(a0exval); } return OK;}
3834 //int m_ftrapt (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00001111)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00001111)); D_long(a0exval); } return OK;}
3835 //int m_ftrapsf (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010000)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010000)); D_long(a0exval); } return OK;}
3836 //int m_ftrapst (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011111)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011111)); D_long(a0exval); } return OK;}
3837 //int m_ftrapseq (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00010001)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00010001)); D_long(a0exval); } return OK;}
3838 //int m_ftrapsne (WORD inst, WORD siz) { if (siz==SIZW) { D_word(inst); D_word(B8(00011110)); D_word(a0exval); } else { inst|=3; D_word(inst); D_word(B8(00011110)); D_long(a0exval); } return OK;}
3840 //int m_ftrapeqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000001)); return OK;}
3841 //int m_ftrapnen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001110)); return OK;}
3842 //int m_ftrapgtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010010)); return OK;}
3843 //int m_ftrapngtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011101)); return OK;}
3844 //int m_ftrapgen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010011)); return OK;}
3845 //int m_ftrapngen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011100)); return OK;}
3846 //int m_ftrapltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010100)); return OK;}
3847 //int m_ftrapnltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011011)); return OK;}
3848 //int m_ftraplen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010101)); return OK;}
3849 //int m_ftrapnlen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011010)); return OK;}
3850 //int m_ftrapgln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010110)); return OK;}
3851 //int m_ftrapngln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011001)); return OK;}
3852 //int m_ftrapglen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010111)); return OK;}
3853 //int m_ftrapnglen(WORD inst, WORD siz) { D_word(inst); D_word(B8(00011000)); return OK;}
3854 //int m_ftrapogtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000010)); return OK;}
3855 //int m_ftrapulen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001101)); return OK;}
3856 //int m_ftrapogen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000011)); return OK;}
3857 //int m_ftrapultn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001100)); return OK;}
3858 //int m_ftrapoltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000100)); return OK;}
3859 //int m_ftrapugen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001011)); return OK;}
3860 //int m_ftrapolen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000101)); return OK;}
3861 //int m_ftrapugtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001010)); return OK;}
3862 //int m_ftrapogln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000110)); return OK;}
3863 //int m_ftrapueqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001001)); return OK;}
3864 //int m_ftraporn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000111)); return OK;}
3865 //int m_ftrapunn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001000)); return OK;}
3866 //int m_ftrapfn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000000)); return OK;}
3867 //int m_ftraptn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001111)); return OK;}
3868 //int m_ftrapsfn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010000)); return OK;}
3869 //int m_ftrapstn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011111)); return OK;}
3870 //int m_ftrapseqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010001)); return OK;}
3871 //int m_ftrapsnen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011110)); return OK;}
3873 #define gen_FTRAPcc(name,opcode) \
3874 int m_##name (WORD inst, WORD siz) \
3879 D_word(B8(opcode)); \
3886 D_word(B8(opcode)); \
3891 int m_##name##n (WORD inst, WORD siz) \
3894 D_word(B8(opcode)); \
3898 gen_FTRAPcc(ftrapeq ,00000001)
3899 gen_FTRAPcc(ftrapne ,00001110)
3900 gen_FTRAPcc(ftrapgt ,00010010)
3901 gen_FTRAPcc(ftrapngt ,00011101)
3902 gen_FTRAPcc(ftrapge ,00010011)
3903 gen_FTRAPcc(ftrapnge ,00011100)
3904 gen_FTRAPcc(ftraplt ,00010100)
3905 gen_FTRAPcc(ftrapnlt ,00011011)
3906 gen_FTRAPcc(ftraple ,00010101)
3907 gen_FTRAPcc(ftrapnle ,00011010)
3908 gen_FTRAPcc(ftrapgl ,00010110)
3909 gen_FTRAPcc(ftrapngl ,00011001)
3910 gen_FTRAPcc(ftrapgle ,00010111)
3911 gen_FTRAPcc(ftrapngle ,00011000)
3912 gen_FTRAPcc(ftrapogt ,00000010)
3913 gen_FTRAPcc(ftrapule ,00001101)
3914 gen_FTRAPcc(ftrapoge ,00000011)
3915 gen_FTRAPcc(ftrapult ,00001100)
3916 gen_FTRAPcc(ftrapolt ,00000100)
3917 gen_FTRAPcc(ftrapuge ,00001011)
3918 gen_FTRAPcc(ftrapole ,00000101)
3919 gen_FTRAPcc(ftrapugt ,00001010)
3920 gen_FTRAPcc(ftrapogl ,00000110)
3921 gen_FTRAPcc(ftrapueq ,00001001)
3922 gen_FTRAPcc(ftrapor ,00000111)
3923 gen_FTRAPcc(ftrapun ,00001000)
3924 gen_FTRAPcc(ftrapf ,00000000)
3925 gen_FTRAPcc(ftrapt ,00001111)
3926 gen_FTRAPcc(ftrapsf ,00010000)
3927 gen_FTRAPcc(ftrapst ,00011111)
3928 gen_FTRAPcc(ftrapseq ,00010001)
3929 gen_FTRAPcc(ftrapsne ,00011110)
3932 // fsgldiv (6888X, 68040)
3934 int m_fsgldiv(WORD inst, WORD siz)
3936 return gen_fpu(inst, siz, B8(00100100), FPU_P_EMUL);
3941 // fsglmul (6888X, 68040)
3943 int m_fsglmul(WORD inst, WORD siz)
3945 return gen_fpu(inst, siz, B8(00100111), FPU_P_EMUL);
3950 // fsin (6888X, 68040FPSP)
3952 int m_fsin(WORD inst, WORD siz)
3954 return gen_fpu(inst, siz, B8(00001110), FPU_FPSP);
3959 // fsincos (6888X, 68040FPSP)
3961 int m_fsincos(WORD inst, WORD siz)
3963 if (gen_fpu(inst, siz, B8(00110000), FPU_FPSP) == OK)
3974 // fsin (6888X, 68040FPSP)
3976 int m_fsinh(WORD inst, WORD siz)
3978 return gen_fpu(inst, siz, B8(00000010), FPU_FPSP);
3983 // fsqrt (6888X, 68040)
3985 int m_fsqrt(WORD inst, WORD siz)
3987 return gen_fpu(inst, siz, B8(00000100), FPU_P_EMUL);
3991 int m_fsfsqrt(WORD inst, WORD siz)
3993 if (activefpu == FPU_68040)
3994 return gen_fpu(inst, siz, B8(01000001), FPU_P_EMUL);
3996 return error("Unsupported in current FPU");
4000 int m_fdfsqrt(WORD inst, WORD siz)
4002 if (activefpu == FPU_68040)
4003 return gen_fpu(inst, siz, B8(01000101), FPU_P_EMUL);
4005 return error("Unsupported in current FPU");
4010 // fsub (6888X, 68040)
4012 int m_fsub(WORD inst, WORD siz)
4014 return gen_fpu(inst, siz, B8(00101000), FPU_P_EMUL);
4018 int m_fsfsub(WORD inst, WORD siz)
4020 if (activefpu == FPU_68040)
4021 return gen_fpu(inst, siz, B8(01101000), FPU_P_EMUL);
4023 return error("Unsupported in current FPU");
4027 int m_fdsub(WORD inst, WORD siz)
4029 if (activefpu == FPU_68040)
4030 return gen_fpu(inst, siz, B8(01101100), FPU_P_EMUL);
4032 return error("Unsupported in current FPU");
4037 // ftan (6888X, 68040FPSP)
4039 int m_ftan(WORD inst, WORD siz)
4041 return gen_fpu(inst, siz, B8(00001111), FPU_FPSP);
4046 // ftanh (6888X, 68040FPSP)
4048 int m_ftanh(WORD inst, WORD siz)
4050 return gen_fpu(inst, siz, B8(00001001), FPU_FPSP);
4055 // ftentox (6888X, 68040FPSP)
4057 int m_ftentox(WORD inst, WORD siz)
4059 return gen_fpu(inst, siz, B8(00010010), FPU_FPSP);
4064 // ftst (6888X, 68040)
4066 int m_ftst(WORD inst, WORD siz)
4068 return gen_fpu(inst, siz, B8(00111010), FPU_P_EMUL);
4073 // ftwotox (6888X, 68040FPSP)
4075 int m_ftwotox(WORD inst, WORD siz)
4077 return gen_fpu(inst, siz, B8(00010001), FPU_FPSP);