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, (TOKENPTR)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, (TOKENPTR)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, (TOKENPTR)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, (TOKENPTR)a0expr);
1041 AddFixup(FU_WORD | FU_PCREL | FU_LBRA | FU_ISBRA, sloc, (TOKENPTR)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, (TOKENPTR)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");
1117 if (*tok.u32 == '#')
1119 // Handle #<expr>, ea
1122 if (abs_expr(&eval) != OK)
1125 if (eval >= 0x10000L)
1126 return error(range_error);
1132 if ((*tok.u32 >= KW_D0) && (*tok.u32 <= KW_A7))
1135 if (reglist(&rmask) < 0)
1139 if (*tok.u32++ != ',')
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;
1168 if (*tok.u32++ != ',')
1169 return error("missing comma");
1171 if (*tok.u32 == EOL)
1172 return error("missing register list");
1174 if (*tok.u32 == '#')
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, (TOKENPTR)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
1257 // to make a dedicated function for it?
1264 if (bfval2 > 31 || bfval2 < 0)
1265 return error("bfxxx width: immediate value must be between 0 and 31");
1267 // For Dw both immediate and register number are stuffed
1268 // into the same field O_o
1269 bfparam2 = (bfval2 << 0);
1273 bfparam1 = (bfval1 << 6);
1275 bfparam1 = bfval1 << 12;
1277 D_word((inst | am0 | a0reg | am1 | a1reg));
1278 ea0gen(siz); // Generate EA
1280 // Second instruction word - Dest register (if exists), Do, Offset, Dw, Width
1281 inst = bfparam1 | bfparam2;
1287 inst |= a0reg << 12;
1296 // bkpt (68EC000, 68010, 68020, 68030, 68040, CPU32)
1298 int m_bkpt(WORD inst, WORD siz)
1302 if (a0exattr & DEFINED)
1305 return error(abs_error);
1308 return error(range_error);
1314 return error(undef_error);
1323 int m_callm(WORD inst, WORD siz)
1330 if (a0exattr & DEFINED)
1333 return error(abs_error);
1336 return error(range_error);
1338 inst = (uint16_t)a0exval;
1342 return error(undef_error);
1352 // cas (68020, 68030, 68040)
1354 int m_cas(WORD inst, WORD siz)
1360 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1361 return error(unsupport);
1376 return error("bad size suffix");
1381 if ((*tok.u32 < KW_D0) && (*tok.u32 > KW_D7))
1382 return error("CAS accepts only data registers");
1384 inst2 = (*tok.u32++) & 7;
1386 if (*tok.u32++ != ',')
1387 return error("missing comma");
1390 if ((*tok.u32 < KW_D0) && (*tok.u32 > KW_D7))
1391 return error("CAS accepts only data registers");
1393 inst2 |= ((*tok.u32++) & 7) << 6;
1395 if (*tok.u32++ != ',')
1396 return error("missing comma");
1399 if ((modes = amode(1)) < 0)
1403 return error("too many ea fields");
1405 if (*tok.u32 != EOL)
1406 return error("extra (unexpected) text found");
1408 // Reject invalud ea modes
1409 amsk = amsktab[am0];
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");
1414 inst |= am0 | a0reg;
1424 // cas2 (68020, 68030, 68040)
1426 int m_cas2(WORD inst, WORD siz)
1430 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1431 return error(unsupport);
1446 return error("bad size suffix");
1451 if ((*tok.u32 < KW_D0) && (*tok.u32 > KW_D7))
1452 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1454 inst2 = (*tok.u32++) & 7;
1456 if (*tok.u32++ != ':')
1457 return error("missing colon");
1460 if ((*tok.u32 < KW_D0) && (*tok.u32 > KW_D7))
1461 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1463 inst3 = (*tok.u32++) & 7;
1465 if (*tok.u32++ != ',')
1466 return error("missing comma");
1469 if ((*tok.u32 < KW_D0) && (*tok.u32 > KW_D7))
1470 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1472 inst2 |= ((*tok.u32++) & 7) << 6;
1474 if (*tok.u32++ != ':')
1475 return error("missing colon");
1478 if ((*tok.u32 < KW_D0) && (*tok.u32 > KW_D7))
1479 return error("CAS2 accepts only data registers for Dx1:Dx2 pairs");
1481 inst3 |= ((*tok.u32++) & 7) << 6;
1483 if (*tok.u32++ != ',')
1484 return error("missing comma");
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);
1494 return error("CAS accepts either data or address registers for Rn1:Rn2 pair");
1496 if (*tok.u32++ != ')')
1497 return error("missing (");
1499 if (*tok.u32++ != ':')
1500 return error("missing colon");
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);
1510 return error("CAS accepts either data or address registers for Rn1:Rn2 pair");
1512 if (*tok.u32++ != ')')
1513 return error("missing (");
1515 if (*tok.u32 != EOL)
1516 return error("extra (unexpected) text found");
1527 // cmp2 (68020, 68030, 68040, CPU32)
1529 int m_cmp2(WORD inst, WORD siz)
1531 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1532 return error(unsupport);
1534 switch (siz & 0x000F)
1548 WORD flg = inst; // Save flag bits
1549 inst &= ~0x3F; // Clobber flag bits in instr
1551 // Install "standard" instr size bits
1557 // OR-in register number
1559 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1561 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1567 inst |= am1 | a1reg; // Get ea1 into instr
1568 D_word(inst); // Deposit instr
1570 // Generate ea0 if requested
1574 ea1gen(siz); // Generate ea1
1579 inst |= am0 | a0reg; // Get ea0 into instr
1580 D_word(inst); // Deposit instr
1581 ea0gen(siz); // Generate ea0
1583 // Generate ea1 if requested
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));
1603 // chk2 (68020, 68030, 68040, CPU32)
1605 int m_chk2(WORD inst, WORD siz)
1607 return m_cmp2(inst, siz | (1 << 11));
1612 // cpbcc(68020, 68030)
1614 int m_cpbr(WORD inst, WORD siz)
1616 if ((activecpu & (CPU_68020 | CPU_68030)) == 0)
1617 return error(unsupport);
1619 if (a0exattr & DEFINED)
1621 if ((a0exattr & TDB) != cursect)
1622 return error(rel_error);
1624 uint32_t v = (uint32_t)a0exval - (sloc + 2);
1626 // Optimize branch instr. size
1629 if ((v != 0) && ((v + 0x8000) < 0x10000))
1639 if ((v + 0x8000) >= 0x10000)
1640 return error(range_error);
1648 else if (siz == SIZN)
1655 AddFixup(FU_LONG | FU_PCREL | FU_SEXT, sloc, (TOKENPTR)a0expr);
1663 AddFixup(FU_WORD | FU_PCREL | FU_SEXT, sloc, (TOKENPTR)a0expr);
1672 // cpdbcc(68020, 68030)
1674 int m_cpdbr(WORD inst, WORD siz)
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?
1682 inst |= (1 << 9); // Bolt on FPU id
1689 if (a1exattr & DEFINED)
1691 if ((a1exattr & TDB) != cursect)
1692 return error(rel_error);
1694 v = (uint32_t)a1exval - sloc;
1696 if (v + 0x8000 > 0x10000)
1697 return error(range_error);
1703 AddFixup(FU_WORD | FU_PCREL | FU_ISBRA, sloc, (TOKENPTR)a1expr);
1714 int m_divs(WORD inst, WORD siz)
1716 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1717 return error(unsupport);
1719 WORD flg = inst; // Save flag bits
1720 inst &= ~0x3F; // Clobber flag bits in instr
1722 // Install "standard" instr size bits
1728 // OR-in register number
1730 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1732 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1738 inst |= am1 | a1reg; // Get ea1 into instr
1739 D_word(inst); // Deposit instr
1741 // Generate ea0 if requested
1745 ea1gen(siz); // Generate ea1
1750 inst |= am0 | a0reg; // Get ea0 into instr
1751 D_word(inst); // Deposit instr
1752 ea0gen(siz); // Generate ea0
1754 // Generate ea1 if requested
1759 inst = a1reg + (a2reg << 12) + (1 << 11);
1769 int m_muls(WORD inst, WORD siz)
1771 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1772 return error(unsupport);
1774 WORD flg = inst; // Save flag bits
1775 inst &= ~0x3F; // Clobber flag bits in instr
1777 // Install "standard" instr size bits
1783 // OR-in register number
1785 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1787 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1793 inst |= am1 | a1reg; // Get ea1 into instr
1794 D_word(inst); // Deposit instr
1797 inst = a1reg + (a2reg << 12) + (1 << 11);
1798 inst |= mulmode; // add size bit
1801 // Generate ea0 if requested
1805 ea1gen(siz); // Generate ea1
1810 inst |= am0 | a0reg; // Get ea0 into instr
1811 D_word(inst); // Deposit instr
1813 inst = a1reg + (a2reg << 12) + (1 << 11);
1814 inst |= mulmode; // add size bit
1817 ea0gen(siz); // Generate ea0
1819 // Generate ea1 if requested
1834 int m_divu(WORD inst, WORD siz)
1836 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1837 return error(unsupport);
1839 //WARNING("divu.l d0,d1 is actually divul.l d0,d1:d1!!!")
1841 WORD flg = inst; // Save flag bits
1842 inst &= ~0x3F; // Clobber flag bits in instr
1844 // Install "standard" instr size bits
1850 // OR-in register number
1852 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1854 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1860 inst |= am1 | a1reg; // Get ea1 into instr
1861 D_word(inst); // Deposit instr
1863 // Generate ea0 if requested
1867 ea1gen(siz); // Generate ea1
1872 inst |= am0 | a0reg; // Get ea0 into instr
1873 D_word(inst); // Deposit instr
1874 ea0gen(siz); // Generate ea0
1876 // Generate ea1 if requested
1881 inst = a1reg + (a2reg << 12);
1891 int m_mulu(WORD inst, WORD siz)
1893 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1894 return error(unsupport);
1896 WORD flg = inst; // Save flag bits
1897 inst &= ~0x3F; // Clobber flag bits in instr
1899 // Install "standard" instr size bits
1905 // OR-in register number
1907 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1909 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1915 inst |= am1 | a1reg; // Get ea1 into instr
1916 D_word(inst); // Deposit instr
1918 // Generate ea0 if requested
1922 ea1gen(siz); // Generate ea1
1927 inst |= am0 | a0reg; // Get ea0 into instr
1928 D_word(inst); // Deposit instr
1929 ea0gen(siz); // Generate ea0
1931 // Generate ea1 if requested
1936 inst = a1reg + (a2reg << 12);
1937 inst |= mulmode; // add size bit
1947 int m_divsl(WORD inst, WORD siz)
1949 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
1950 return error(unsupport);
1952 WORD flg = inst; // Save flag bits
1953 inst &= ~0x3F; // Clobber flag bits in instr
1955 // Install "standard" instr size bits
1961 // OR-in register number
1963 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
1965 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
1971 inst |= am1 | a1reg; // Get ea1 into instr
1972 D_word(inst); // Deposit instr
1974 // Generate ea0 if requested
1978 ea1gen(siz); // Generate ea1
1983 inst |= am0 | a0reg; // Get ea0 into instr
1984 D_word(inst); // Deposit instr
1985 ea0gen(siz); // Generate ea0
1987 // Generate ea1 if requested
1992 inst = a1reg + (a2reg << 12) + (1 << 11) + (1 << 10);
2001 int m_divul(WORD inst, WORD siz)
2003 if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0)
2004 return error(unsupport);
2006 WORD flg = inst; // Save flag bits
2007 inst &= ~0x3F; // Clobber flag bits in instr
2009 // Install "standard" instr size bits
2015 // OR-in register number
2017 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
2019 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
2025 inst |= am1 | a1reg; // Get ea1 into instr
2026 D_word(inst); // Deposit instr
2028 // Generate ea0 if requested
2032 ea1gen(siz); // Generate ea1
2037 inst |= am0 | a0reg; // Get ea0 into instr
2038 D_word(inst); // Deposit instr
2039 ea0gen(siz); // Generate ea0
2041 // Generate ea1 if requested
2046 inst = a1reg + (a2reg << 12) + (1 << 10);
2054 // move16 (ax)+,(ay)+
2056 int m_move16a(WORD inst, WORD siz)
2058 if ((activecpu & (CPU_68040 | CPU_68060)) == 0)
2059 return error(unsupport);
2063 inst = (1 << 15) + (a1reg << 12);
2071 // move16 with absolute address
2073 int m_move16b(WORD inst, WORD siz)
2075 if ((activecpu & (CPU_68040 | CPU_68060)) == 0)
2076 return error(unsupport);
2082 if (am0 == APOSTINC)
2085 return error("Wasn't this suppose to call m_move16a???");
2088 //move16 (ax)+,(xxx).L
2093 else if (am0 == ABSL)
2097 //move16 (xxx).L,(ax)+
2103 //move16 (xxx).L,(ax)
2108 else if (am0 == AIND)
2110 //move16 (ax),(xxx).L
2123 // pack/unpack (68020/68030/68040)
2125 int m_pack(WORD inst, WORD siz)
2130 return error("bad size suffix");
2132 if (*tok.u32 >= KW_D0 && *tok.u32 <= KW_D7)
2134 // Dx,Dy,#<adjustment>
2135 inst |= (0 << 3); // R/M
2136 inst |= (*tok.u32++ & 7);
2138 if (*tok.u32 != ',' && tok.u32[2] != ',')
2139 return error("missing comma");
2141 if (tok.u32[1] < KW_D0 && tok.u32[1] > KW_D7)
2142 return error(syntax_error);
2144 inst |= ((tok.u32[1] & 7)<<9);
2145 tok.u32 = tok.u32 + 3;
2147 // Fall through for adjustment (common in both valid cases)
2149 else if (*tok.u32 == '-')
2151 // -(Ax),-(Ay),#<adjustment>
2152 inst |= (1 << 3); // R/M
2153 tok.u32++; // eat the minus
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);
2158 if (tok.u32[1] < KW_A0 && tok.u32[1] > KW_A7)
2159 return error(syntax_error);
2161 if (tok.u32[5] < KW_A0 && tok.u32[6] > KW_A7)
2162 return error(syntax_error);
2164 inst |= ((tok.u32[1] & 7) << 0);
2165 inst |= ((tok.u32[6] & 7) << 9);
2166 tok.u32 = tok.u32 + 9;
2168 // Fall through for adjustment (common in both valid cases)
2171 return error("invalid syntax");
2173 if ((*tok.u32 != CONST) && (*tok.u32 != SYMBOL) && (*tok.u32 != '-'))
2174 return error(syntax_error);
2176 if (expr((TOKENPTR)a0expr, &a0exval, &a0exattr, &a0esym) == ERROR)
2179 if ((a0exattr & DEFINED) == 0)
2180 return error(undef_error);
2182 if (a0exval + 0x8000 > 0x10000)
2185 if (*tok.u32 != EOL)
2186 return error(extra_stuff);
2188 D_word((a0exval & 0xFFFF));
2197 int m_rtm(WORD inst, WORD siz)
2205 else if (am0 == AREG)
2207 inst |= (1 << 3) + a0reg;
2210 return error("rtm only allows data or address registers.");
2221 int m_rtd(WORD inst, WORD siz)
2225 if (a0exattr & DEFINED)
2228 return error(abs_error);
2230 if ((a0exval + 0x8000) <= 0x7FFF)
2231 return error(range_error);
2237 return error(undef_error);
2246 int m_trapcc(WORD inst, WORD siz)
2254 else if (am0 == IMMED)
2258 if (a0exval < 0x10000)
2265 return error("Immediate value too big");
2275 return error("Invalid parameter for trapcc");
2282 // cinvl/p/a (68040)
2284 int m_cinv(WORD inst, WORD siz)
2289 inst |= (0 << 6) | (a1reg);
2293 inst |= (2 << 6) | (a1reg);
2296 inst |= (1 << 6) | (a1reg);
2299 inst |= (3 << 6) | (a1reg);
2309 // cpRESTORE (68020, 68030)
2311 int m_cprest(WORD inst, WORD siz)
2313 if (activecpu & !(CPU_68020 | CPU_68030))
2314 return error(unsupport);
2316 inst |= am0 | a0reg;
2325 // movec (68010, 68020, 68030, 68040, CPU32)
2327 int m_movec(WORD inst, WORD siz)
2331 if (am0 == DREG || am0 == AREG)
2339 inst = (0 << 15) + (a0reg << 12) + CREGlut[a1reg];
2344 inst = (1 << 15) + (a0reg << 12) + CREGlut[a1reg];
2355 inst = (0 << 15) + (a1reg << 12) + CREGlut[a0reg];
2360 inst = (1 << 15) + (a1reg << 12) + CREGlut[a0reg];
2370 // moves (68010, 68020, 68030, 68040, CPU32)
2372 int m_moves(WORD inst, WORD siz)
2374 if (activecpu & !(CPU_68020 | CPU_68030 | CPU_68040))
2375 return error(unsupport);
2379 else if (siz == SIZL)
2386 inst |= am1 | a1reg;
2388 inst = (a0reg << 12) | (1 << 11) | (0 << 15);
2391 else if (am0 == AREG)
2393 inst |= am1 | a1reg;
2395 inst = (a0reg << 12) | (1 << 11) | (1 << 15);
2402 inst |= am0 | a0reg;
2404 inst = (a1reg << 12) | (0 << 11) | (0 << 15);
2409 inst |= am0 | a0reg;
2411 inst = (a1reg << 12) | (0 << 11) | (1 << 15);
2423 int m_pbcc(WORD inst, WORD siz)
2426 return error("Not implemented yet.");
2431 // pflusha (68030, 68040)
2433 int m_pflusha(WORD inst, WORD siz)
2435 if (activecpu == CPU_68030)
2438 inst = (1 << 13) | (1 << 10) | (0 << 5) | 0;
2442 else if (activecpu == CPU_68040)
2444 inst = B16(11110101, 00011000);
2449 return error(unsupport);
2456 // pflush (68030, 68040, 68060)
2458 int m_pflush(WORD inst, WORD siz)
2460 if (activecpu == CPU_68030)
2463 // PFLUSH FC, MASK, < ea >
2466 switch ((int)*tok.u32)
2471 if (*tok.u32 != CONST && *tok.u32 != SYMBOL)
2472 return error("function code should be an expression");
2474 if (expr((TOKENPTR)a0expr, &a0exval, &a0exattr, &a0esym) == ERROR)
2477 if ((a0exattr & DEFINED) == 0)
2478 return error("function code immediate should be defined");
2480 if (a0exval > 7 && a0exval < 0)
2481 return error("function code out of range (0-7)");
2483 fc = (uint16_t)a0exval;
2493 fc = (1 << 4) | (*tok.u32++ & 7);
2504 return error(syntax_error);
2507 if (*tok.u32++ != ',')
2508 return error("comma exptected");
2510 if (*tok.u32++ != '#')
2511 return error("mask should be an immediate value");
2513 if (*tok.u32 != CONST && *tok.u32 != SYMBOL)
2514 return error("mask is supposed to be immediate");
2516 if (expr((TOKENPTR)a0expr, &a0exval, &a0exattr, &a0esym) == ERROR)
2519 if ((a0exattr & DEFINED) == 0)
2520 return error("mask immediate value should be defined");
2522 if (a0exval > 7 && a0exval < 0)
2523 return error("function code out of range (0-7)");
2525 mask = (uint16_t)a0exval << 5;
2527 if (*tok.u32 == EOL)
2531 inst = (1 << 13) | fc | mask | (4 << 10);
2535 else if (*tok.u32 == ',')
2537 // PFLUSH FC, MASK, < ea >
2540 if (amode(0) == ERROR)
2543 if (*tok.u32 != EOL)
2544 return error(extra_stuff);
2546 if (am0 == AIND || am0 == ABSW || am0 == ABSL || am0 == ADISP || am0 == ADISP || am0 == AINDEXED || am0 == ABASE || am0 == MEMPOST || am0 == MEMPRE)
2548 inst |= am0 | a0reg;
2550 inst = (1 << 13) | fc | mask | (6 << 10);
2556 return error("unsupported addressing mode");
2560 return error(syntax_error);
2564 else if (activecpu == CPU_68040 || activecpu == CPU_68060)
2568 if (*tok.u32 != '(' && tok.u32[2] != ')')
2569 return error(syntax_error);
2571 if (tok.u32[1] < KW_A0 && tok.u32[1] > KW_A7)
2572 return error("expected (An)");
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;
2582 inst |= (tok.u32[1] & 7) | (5 << 8);
2584 if (tok.u32[3] != EOL)
2585 return error(extra_stuff);
2590 return error(unsupport);
2599 int m_pflushr(WORD inst, WORD siz)
2603 WORD flg = inst; // Save flag bits
2604 inst &= ~0x3F; // Clobber flag bits in instr
2606 // Install "standard" instr size bits
2612 // OR-in register number
2614 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
2616 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
2622 inst |= am1 | a1reg; // Get ea1 into instr
2623 D_word(inst); // Deposit instr
2625 // Generate ea0 if requested
2629 ea1gen(siz); // Generate ea1
2634 inst |= am0 | a0reg; // Get ea0 into instr
2635 D_word(inst); // Deposit instr
2636 ea0gen(siz); // Generate ea0
2638 // Generate ea1 if requested
2643 D_word(B16(10100000, 00000000));
2649 // ploadr, ploadw (68030)
2651 int m_pload(WORD inst, WORD siz, WORD extension)
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...
2665 if (a0reg == KW_SFC - KW_SFC)
2667 else if (a0reg == KW_DFC - KW_SFC)
2670 return error("illegal control register specified");
2674 inst = (1 << 3) | a0reg;
2677 if ((a0exattr & DEFINED) == 0)
2678 return error("constant value must be defined");
2680 inst = (2 << 3) | (uint16_t)a0exval;
2684 inst |= extension | (1 << 13);
2692 int m_ploadr(WORD inst, WORD siz)
2694 return m_pload(inst, siz, 1 << 9);
2697 int m_ploadw(WORD inst, WORD siz)
2699 return m_pload(inst, siz, 0 << 9);
2703 // pmove (68030/68551)
2705 int m_pmove(WORD inst, WORD siz)
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)
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
2724 else if (am1 == CREG)
2730 return error("pmove sez: Wut?");
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.
2738 if (((reg == (KW_URP - KW_SFC)) || (reg == (KW_SRP - KW_SFC)))
2739 && ((siz != SIZD) && (siz != SIZN)))
2740 return error(siz_error);
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);
2746 if ((reg == (KW_MMUSR - KW_SFC)) && ((siz != SIZW) && (siz != SIZN)))
2747 return error(siz_error);
2752 inst |= am1 | a1reg;
2755 else if (am1 == CREG)
2757 inst |= am0 | a0reg;
2761 switch (reg + KW_SFC)
2764 inst2 |= (0 << 10) + (1 << 14); break;
2766 inst2 |= (2 << 10) + (1 << 14); break;
2768 inst2 |= (3 << 10) + (1 << 14); break;
2770 inst2 |= (2 << 10) + (0 << 13); break;
2772 inst2 |= (3 << 10) + (0 << 13); break;
2775 inst2 |= (1 << 9) + (3 << 13);
2777 inst2 |= (0 << 9) + (3 << 13);
2780 return error("unsupported register");
2788 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, (TOKENPTR)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");
3299 inst |= bfval1 & 127;
3304 return error("Something bad happened, possibly.");
3309 // Destination specifier
3310 inst |= (a0reg << 7);
3318 else if ((am0 < AM_USP) && (am1 == FREG))
3323 inst |= am0 | a0reg;
3332 case SIZB: inst |= (6 << 10); break;
3333 case SIZW: inst |= (4 << 10); break;
3334 case SIZL: inst |= (0 << 10); break;
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;
3341 return error("Something bad happened, possibly.");
3345 // Destination specifier
3346 inst |= (a1reg << 7);
3354 else if ((am0 == FREG) && (am1 == FREG))
3356 // register-to-register
3357 // Essentially ea to register with R/0=0
3367 return error("Invalid size");
3370 inst |= (a0reg << 10);
3372 // Destination register
3373 inst |= (a1reg << 7);
3383 // fmove (6888X, 68040)
3385 int m_fmovescr(WORD inst, WORD siz)
3387 // Move Floating-Point System Control Register (FPCR)
3391 if ((am0 == FPSCR) && (am1 < AM_USP))
3393 inst |= am1 | a1reg;
3395 inst = (1 << 13) + (1 << 15);
3401 else if ((am1 == FPSCR) && (am0 < AM_USP))
3403 inst |= am0 | a0reg;
3405 inst = (0 << 13) + (1 << 15);
3412 return error("m_fmovescr says: wut?");
3416 // fsmove/fdmove (68040)
3418 int m_fsmove(WORD inst, WORD siz)
3420 return error("Not implemented yet.");
3423 if (activefpu == FPU_68040)
3424 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
3426 return error("Unsupported in current FPU");
3431 int m_fdmove(WORD inst, WORD siz)
3433 return error("Not implemented yet.");
3436 if (activefpu == FPU_68040)
3437 return gen_fpu(inst, siz, B8(01100100), FPU_P_EMUL);
3439 return error("Unsupported in current FPU");
3445 // fmovecr (6888X, 68040FPSP)
3447 int m_fmovecr(WORD inst, WORD siz)
3455 if (activefpu == FPU_68040)
3456 warn("Instruction is emulated in 68040");
3463 // fmovem (6888X, 68040)
3465 int m_fmovem(WORD inst, WORD siz)
3470 if (siz == SIZX || siz==SIZN)
3472 if ((*tok.u32 >= KW_FP0) && (*tok.u32 <= KW_FP7))
3474 //fmovem.x <rlist>,ea
3475 if (fpu_reglist_left(®mask) < 0)
3478 if (*tok.u32++ != ',')
3479 return error("missing comma");
3484 inst |= am0 | a0reg;
3486 if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
3487 return error("invalid addressing mode");
3490 inst = (1 << 15) | (1 << 14) | (1 << 13) | (0 << 11) | regmask;
3495 else if ((*tok.u32 >= KW_D0) && (*tok.u32 <= KW_D7))
3498 datareg = (*tok.u32++ & 7) << 10;
3500 if (*tok.u32++ != ',')
3501 return error("missing comma");
3506 inst |= am0 | a0reg;
3508 if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
3509 return error("invalid addressing mode");
3512 inst = (1 << 15) | (1 << 14) | (1 << 13) | (1 << 11) | (datareg << 4);
3523 inst |= am0 | a0reg;
3525 if (*tok.u32++ != ',')
3526 return error("missing comma");
3528 if ((*tok.u32 >= KW_FP0) && (*tok.u32 <= KW_FP7))
3530 //fmovem.x ea,<rlist>
3531 if (fpu_reglist_right(®mask) < 0)
3535 inst = (1 << 15) | (1 << 14) | (0 << 13) | (2 << 11) | regmask;
3543 datareg = (*tok.u32++ & 7) << 10;
3545 inst = (1 << 15) | (1 << 14) | (0 << 13) | (3 << 11) | (datareg << 4);
3552 else if (siz == SIZL)
3554 if ((*tok.u32 == KW_FPCR) || (*tok.u32 == KW_FPSR) || (*tok.u32 == KW_FPIAR))
3556 //fmovem.l <rlist>,ea
3557 regmask = (1 << 15) | (1 << 13);
3559 if (*tok.u32 == KW_FPCR)
3561 regmask |= (1 << 12);
3566 if (*tok.u32 == KW_FPSR)
3568 regmask |= (1 << 11);
3573 if (*tok.u32 == KW_FPIAR)
3575 regmask |= (1 << 10);
3580 if ((*tok.u32 == '/') || (*tok.u32 == '-'))
3586 if (*tok.u32++ != ',')
3587 return error("missing comma");
3592 inst |= am0 | a0reg;
3599 //fmovem.l ea,<rlist>
3603 inst |= am0 | a0reg;
3605 if (*tok.u32++ != ',')
3606 return error("missing comma");
3608 regmask = (1 << 15) | (0 << 13);
3611 if (*tok.u32 == KW_FPCR)
3613 regmask |= (1 << 12);
3618 if (*tok.u32 == KW_FPSR)
3620 regmask |= (1 << 11);
3625 if (*tok.u32 == KW_FPIAR)
3627 regmask |= (1 << 10);
3632 if ((*tok.u32 == '/') || (*tok.u32 == '-'))
3638 if (*tok.u32 != EOL)
3639 return error("extra (unexpected) text found");
3641 inst |= am0 | a0reg;
3648 return error("bad size suffix");
3655 // fmul (6888X, 68040)
3657 int m_fmul(WORD inst, WORD siz)
3659 return gen_fpu(inst, siz, B8(00100011), FPU_P_EMUL);
3663 int m_fsmul(WORD inst, WORD siz)
3665 if (activefpu == FPU_68040)
3666 return gen_fpu(inst, siz, B8(01100011), FPU_P_EMUL);
3668 return error("Unsupported in current FPU");
3672 int m_fdmul(WORD inst, WORD siz)
3674 if (activefpu == FPU_68040)
3675 return gen_fpu(inst, siz, B8(01100111), FPU_P_EMUL);
3677 return error("Unsupported in current FPU");
3682 // fneg (6888X, 68040)
3684 int m_fneg(WORD inst, WORD siz)
3686 return gen_fpu(inst, siz, B8(00011010), FPU_P_EMUL);
3690 int m_fsneg(WORD inst, WORD siz)
3692 if (activefpu == FPU_68040)
3693 return gen_fpu(inst, siz, B8(01011010), FPU_P_EMUL);
3695 return error("Unsupported in current FPU");
3699 int m_fdneg(WORD inst, WORD siz)
3701 if (activefpu == FPU_68040)
3702 return gen_fpu(inst, siz, B8(01011110), FPU_P_EMUL);
3704 return error("Unsupported in current FPU");
3709 // fnop (6888X, 68040)
3711 int m_fnop(WORD inst, WORD siz)
3713 return gen_fpu(inst, siz, B8(00000000), FPU_P_EMUL);
3718 // frem (6888X, 68040FPSP)
3720 int m_frem(WORD inst, WORD siz)
3722 return gen_fpu(inst, siz, B8(00100101), FPU_FPSP);
3727 // fscale (6888X, 68040FPSP)
3729 int m_fscale(WORD inst, WORD siz)
3731 return gen_fpu(inst, siz, B8(00100110), FPU_FPSP);
3736 // FScc (6888X, 68040)
3738 //int m_fseq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000001)); return OK;}
3739 //int m_fsne (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001110)); return OK;}
3740 //int m_fsgt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010010)); return OK;}
3741 //int m_fsngt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011101)); return OK;}
3742 //int m_fsge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010011)); return OK;}
3743 //int m_fsnge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011100)); return OK;}
3744 //int m_fslt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010100)); return OK;}
3745 //int m_fsnlt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011011)); return OK;}
3746 //int m_fsle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010101)); return OK;}
3747 //int m_fsnle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011010)); return OK;}
3748 //int m_fsgl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010110)); return OK;}
3749 //int m_fsngl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011001)); return OK;}
3750 //int m_fsgle (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010111)); return OK;}
3751 //int m_fsngle(WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011000)); return OK;}
3752 //int m_fsogt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000010)); return OK;}
3753 //int m_fsule (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001101)); return OK;}
3754 //int m_fsoge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000011)); return OK;}
3755 //int m_fsult (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001100)); return OK;}
3756 //int m_fsolt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000100)); return OK;}
3757 //int m_fsuge (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001011)); return OK;}
3758 //int m_fsole (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000101)); return OK;}
3759 //int m_fsugt (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001010)); return OK;}
3760 //int m_fsogl (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000110)); return OK;}
3761 //int m_fsueq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001001)); return OK;}
3762 //int m_fsor (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000111)); return OK;}
3763 //int m_fsun (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001000)); return OK;}
3764 //int m_fsf (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00000000)); return OK;}
3765 //int m_fst (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00001111)); return OK;}
3766 //int m_fssf (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010000)); return OK;}
3767 //int m_fsst (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011111)); return OK;}
3768 //int m_fsseq (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00010001)); return OK;}
3769 //int m_fssne (WORD inst, WORD siz) { inst|=am0|a0reg; D_word(inst); ea0gen(siz); D_word(B8(00011110)); return OK;}
3771 #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;}
3772 gen_FScc(fseq , 00000001);
3773 gen_FScc(fsne , 00001110);
3774 gen_FScc(fsgt , 00010010);
3775 gen_FScc(fsngt , 00011101);
3776 gen_FScc(fsge , 00010011);
3777 gen_FScc(fsnge , 00011100);
3778 gen_FScc(fslt , 00010100);
3779 gen_FScc(fsnlt , 00011011);
3780 gen_FScc(fsle , 00010101);
3781 gen_FScc(fsnle , 00011010);
3782 gen_FScc(fsgl , 00010110);
3783 gen_FScc(fsngl , 00011001);
3784 gen_FScc(fsgle , 00010111);
3785 gen_FScc(fsngle, 00011000);
3786 gen_FScc(fsogt , 00000010);
3787 gen_FScc(fsule , 00001101);
3788 gen_FScc(fsoge , 00000011);
3789 gen_FScc(fsult , 00001100);
3790 gen_FScc(fsolt , 00000100);
3791 gen_FScc(fsuge , 00001011);
3792 gen_FScc(fsole , 00000101);
3793 gen_FScc(fsugt , 00001010);
3794 gen_FScc(fsogl , 00000110);
3795 gen_FScc(fsueq , 00001001);
3796 gen_FScc(fsor , 00000111);
3797 gen_FScc(fsun , 00001000);
3798 gen_FScc(fsf , 00000000);
3799 gen_FScc(fst , 00001111);
3800 gen_FScc(fssf , 00010000);
3801 gen_FScc(fsst , 00011111);
3802 gen_FScc(fsseq , 00010001);
3803 gen_FScc(fssne , 00011110);
3806 // FTRAPcc (6888X, 68040)
3808 //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;}
3809 //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;}
3810 //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;}
3811 //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;}
3812 //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;}
3813 //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;}
3814 //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;}
3815 //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;}
3816 //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;}
3817 //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;}
3818 //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;}
3819 //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;}
3820 //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;}
3821 //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;}
3822 //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;}
3823 //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;}
3824 //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;}
3825 //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;}
3826 //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;}
3827 //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;}
3828 //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;}
3829 //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;}
3830 //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;}
3831 //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;}
3832 //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;}
3833 //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;}
3834 //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;}
3835 //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;}
3836 //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;}
3837 //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;}
3838 //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;}
3839 //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;}
3841 //int m_ftrapeqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000001)); return OK;}
3842 //int m_ftrapnen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001110)); return OK;}
3843 //int m_ftrapgtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010010)); return OK;}
3844 //int m_ftrapngtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011101)); return OK;}
3845 //int m_ftrapgen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010011)); return OK;}
3846 //int m_ftrapngen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011100)); return OK;}
3847 //int m_ftrapltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010100)); return OK;}
3848 //int m_ftrapnltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011011)); return OK;}
3849 //int m_ftraplen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010101)); return OK;}
3850 //int m_ftrapnlen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011010)); return OK;}
3851 //int m_ftrapgln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010110)); return OK;}
3852 //int m_ftrapngln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011001)); return OK;}
3853 //int m_ftrapglen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010111)); return OK;}
3854 //int m_ftrapnglen(WORD inst, WORD siz) { D_word(inst); D_word(B8(00011000)); return OK;}
3855 //int m_ftrapogtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000010)); return OK;}
3856 //int m_ftrapulen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001101)); return OK;}
3857 //int m_ftrapogen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000011)); return OK;}
3858 //int m_ftrapultn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001100)); return OK;}
3859 //int m_ftrapoltn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000100)); return OK;}
3860 //int m_ftrapugen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001011)); return OK;}
3861 //int m_ftrapolen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000101)); return OK;}
3862 //int m_ftrapugtn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001010)); return OK;}
3863 //int m_ftrapogln (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000110)); return OK;}
3864 //int m_ftrapueqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001001)); return OK;}
3865 //int m_ftraporn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000111)); return OK;}
3866 //int m_ftrapunn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001000)); return OK;}
3867 //int m_ftrapfn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00000000)); return OK;}
3868 //int m_ftraptn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00001111)); return OK;}
3869 //int m_ftrapsfn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010000)); return OK;}
3870 //int m_ftrapstn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011111)); return OK;}
3871 //int m_ftrapseqn (WORD inst, WORD siz) { D_word(inst); D_word(B8(00010001)); return OK;}
3872 //int m_ftrapsnen (WORD inst, WORD siz) { D_word(inst); D_word(B8(00011110)); return OK;}
3874 #define gen_FTRAPcc(name,opcode) \
3875 int m_##name (WORD inst, WORD siz) \
3880 D_word(B8(opcode)); \
3887 D_word(B8(opcode)); \
3892 int m_##name##n (WORD inst, WORD siz) \
3895 D_word(B8(opcode)); \
3899 gen_FTRAPcc(ftrapeq ,00000001)
3900 gen_FTRAPcc(ftrapne ,00001110)
3901 gen_FTRAPcc(ftrapgt ,00010010)
3902 gen_FTRAPcc(ftrapngt ,00011101)
3903 gen_FTRAPcc(ftrapge ,00010011)
3904 gen_FTRAPcc(ftrapnge ,00011100)
3905 gen_FTRAPcc(ftraplt ,00010100)
3906 gen_FTRAPcc(ftrapnlt ,00011011)
3907 gen_FTRAPcc(ftraple ,00010101)
3908 gen_FTRAPcc(ftrapnle ,00011010)
3909 gen_FTRAPcc(ftrapgl ,00010110)
3910 gen_FTRAPcc(ftrapngl ,00011001)
3911 gen_FTRAPcc(ftrapgle ,00010111)
3912 gen_FTRAPcc(ftrapngle ,00011000)
3913 gen_FTRAPcc(ftrapogt ,00000010)
3914 gen_FTRAPcc(ftrapule ,00001101)
3915 gen_FTRAPcc(ftrapoge ,00000011)
3916 gen_FTRAPcc(ftrapult ,00001100)
3917 gen_FTRAPcc(ftrapolt ,00000100)
3918 gen_FTRAPcc(ftrapuge ,00001011)
3919 gen_FTRAPcc(ftrapole ,00000101)
3920 gen_FTRAPcc(ftrapugt ,00001010)
3921 gen_FTRAPcc(ftrapogl ,00000110)
3922 gen_FTRAPcc(ftrapueq ,00001001)
3923 gen_FTRAPcc(ftrapor ,00000111)
3924 gen_FTRAPcc(ftrapun ,00001000)
3925 gen_FTRAPcc(ftrapf ,00000000)
3926 gen_FTRAPcc(ftrapt ,00001111)
3927 gen_FTRAPcc(ftrapsf ,00010000)
3928 gen_FTRAPcc(ftrapst ,00011111)
3929 gen_FTRAPcc(ftrapseq ,00010001)
3930 gen_FTRAPcc(ftrapsne ,00011110)
3933 // fsgldiv (6888X, 68040)
3935 int m_fsgldiv(WORD inst, WORD siz)
3937 return gen_fpu(inst, siz, B8(00100100), FPU_P_EMUL);
3942 // fsglmul (6888X, 68040)
3944 int m_fsglmul(WORD inst, WORD siz)
3946 return gen_fpu(inst, siz, B8(00100111), FPU_P_EMUL);
3951 // fsin (6888X, 68040FPSP)
3953 int m_fsin(WORD inst, WORD siz)
3955 return gen_fpu(inst, siz, B8(00001110), FPU_FPSP);
3960 // fsincos (6888X, 68040FPSP)
3962 int m_fsincos(WORD inst, WORD siz)
3964 if (gen_fpu(inst, siz, B8(00110000), FPU_FPSP) == OK)
3975 // fsin (6888X, 68040FPSP)
3977 int m_fsinh(WORD inst, WORD siz)
3979 return gen_fpu(inst, siz, B8(00000010), FPU_FPSP);
3984 // fsqrt (6888X, 68040)
3986 int m_fsqrt(WORD inst, WORD siz)
3988 return gen_fpu(inst, siz, B8(00000100), FPU_P_EMUL);
3992 int m_fsfsqrt(WORD inst, WORD siz)
3994 if (activefpu == FPU_68040)
3995 return gen_fpu(inst, siz, B8(01000001), FPU_P_EMUL);
3997 return error("Unsupported in current FPU");
4001 int m_fdfsqrt(WORD inst, WORD siz)
4003 if (activefpu == FPU_68040)
4004 return gen_fpu(inst, siz, B8(01000101), FPU_P_EMUL);
4006 return error("Unsupported in current FPU");
4011 // fsub (6888X, 68040)
4013 int m_fsub(WORD inst, WORD siz)
4015 return gen_fpu(inst, siz, B8(00101000), FPU_P_EMUL);
4019 int m_fsfsub(WORD inst, WORD siz)
4021 if (activefpu == FPU_68040)
4022 return gen_fpu(inst, siz, B8(01101000), FPU_P_EMUL);
4024 return error("Unsupported in current FPU");
4028 int m_fdsub(WORD inst, WORD siz)
4030 if (activefpu == FPU_68040)
4031 return gen_fpu(inst, siz, B8(01101100), FPU_P_EMUL);
4033 return error("Unsupported in current FPU");
4038 // ftan (6888X, 68040FPSP)
4040 int m_ftan(WORD inst, WORD siz)
4042 return gen_fpu(inst, siz, B8(00001111), FPU_FPSP);
4047 // ftanh (6888X, 68040FPSP)
4049 int m_ftanh(WORD inst, WORD siz)
4051 return gen_fpu(inst, siz, B8(00001001), FPU_FPSP);
4056 // ftentox (6888X, 68040FPSP)
4058 int m_ftentox(WORD inst, WORD siz)
4060 return gen_fpu(inst, siz, B8(00010010), FPU_FPSP);
4065 // ftst (6888X, 68040)
4067 int m_ftst(WORD inst, WORD siz)
4069 return gen_fpu(inst, siz, B8(00111010), FPU_P_EMUL);
4074 // ftwotox (6888X, 68040FPSP)
4076 int m_ftwotox(WORD inst, WORD siz)
4078 return gen_fpu(inst, siz, B8(00010001), FPU_FPSP);