1 /* $Id: m68k-insns.c,v 1.16 2007/08/25 22:05:02 fredette Exp $ */
2
3 /* ic/m68k/m68k-insns.c - m68k instruction functions: */
4
5 /*
6 * Copyright (c) 2002, 2003 Matt Fredette
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Matt Fredette.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 /* includes: */
37 #include "m68k-impl.h"
38
39 _TME_RCSID("$Id: m68k-insns.c,v 1.16 2007/08/25 22:05:02 fredette Exp $");
40
41 #define TME_M68K_STD_FLAGS \
42 do { \
43 ic->tme_m68k_ireg_ccr = ((ic->tme_m68k_ireg_ccr \
44 & TME_M68K_FLAG_X) \
45 | (res < 0 ? TME_M68K_FLAG_N : 0) \
46 | (res == 0 ? TME_M68K_FLAG_Z : 0)); \
47 } while (/* CONSTCOND */ 0)
48
49 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_exg)50 TME_M68K_INSN(tme_m68k_exg)
51 {
52 tme_uint32_t tmp;
53 tmp = TME_M68K_INSN_OP0(tme_uint32_t);
54 TME_M68K_INSN_OP0(tme_uint32_t) = TME_M68K_INSN_OP1(tme_uint32_t);
55 TME_M68K_INSN_OP1(tme_uint32_t) = tmp;
56 TME_M68K_INSN_OK;
57 }
58
59 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_extw)60 TME_M68K_INSN(tme_m68k_extw)
61 {
62 tme_int16_t res;
63 res = TME_EXT_S8_S16((tme_int8_t) TME_M68K_INSN_OP1(tme_int16_t));
64 TME_M68K_INSN_OP1(tme_int16_t) = res;
65 TME_M68K_STD_FLAGS;
66 TME_M68K_INSN_OK;
67 }
68
69 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_extl)70 TME_M68K_INSN(tme_m68k_extl)
71 {
72 tme_int32_t res;
73 res = TME_EXT_S16_S32((tme_int16_t) TME_M68K_INSN_OP1(tme_int32_t));
74 TME_M68K_INSN_OP1(tme_int32_t) = res;
75 TME_M68K_STD_FLAGS;
76 TME_M68K_INSN_OK;
77 }
78
79 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_extbl)80 TME_M68K_INSN(tme_m68k_extbl)
81 {
82 tme_int32_t res;
83 res = TME_EXT_S8_S32((tme_int8_t) TME_M68K_INSN_OP1(tme_int32_t));
84 TME_M68K_INSN_OP1(tme_int32_t) = res;
85 TME_M68K_STD_FLAGS;
86 TME_M68K_INSN_OK;
87 }
88
89 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_lea)90 TME_M68K_INSN(tme_m68k_lea)
91 {
92 TME_M68K_INSN_OP0(tme_uint32_t) = TME_M68K_INSN_OP1(tme_uint32_t);
93 TME_M68K_INSN_OK;
94 }
95
96 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_move_from_ccr)97 TME_M68K_INSN(tme_m68k_move_from_ccr)
98 {
99 TME_M68K_INSN_OP1(tme_uint16_t) = ic->tme_m68k_ireg_ccr;
100 TME_M68K_INSN_OK;
101 }
102
103 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_move_from_sr)104 TME_M68K_INSN(tme_m68k_move_from_sr)
105 {
106 TME_M68K_INSN_PRIV;
107 TME_M68K_INSN_OP1(tme_uint16_t) = ic->tme_m68k_ireg_sr;
108 TME_M68K_INSN_OK;
109 }
110
111 /* this cannot fault: */
112 /* this is the 68000 version, which isn't privileged: */
TME_M68K_INSN(tme_m68k_move_from_sr0)113 TME_M68K_INSN(tme_m68k_move_from_sr0)
114 {
115 TME_M68K_INSN_OP1(tme_uint16_t) = ic->tme_m68k_ireg_sr;
116 TME_M68K_INSN_OK;
117 }
118
119 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_swap)120 TME_M68K_INSN(tme_m68k_swap)
121 {
122 tme_uint32_t tmp;
123 tme_int32_t res;
124 tmp = TME_M68K_INSN_OP1(tme_uint32_t);
125 tmp = (TME_FIELD_EXTRACTU(tmp, 0, 16) << 16) | TME_FIELD_EXTRACTU(tmp, 16, 16);
126 TME_M68K_INSN_OP1(tme_uint32_t) = tmp;
127 res = (tme_int32_t) tmp;
128 TME_M68K_STD_FLAGS;
129 TME_M68K_INSN_OK;
130 }
131
132 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_nop)133 TME_M68K_INSN(tme_m68k_nop)
134 {
135 TME_M68K_INSN_OK;
136 }
137
138 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_scc)139 TME_M68K_INSN(tme_m68k_scc)
140 {
141 TME_M68K_INSN_OP1(tme_uint8_t) =
142 (TME_M68K_COND_TRUE(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 8, 4))
143 ? 0xff
144 : 0x00);
145 TME_M68K_INSN_OK;
146 }
147
148 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_dbcc)149 TME_M68K_INSN(tme_m68k_dbcc)
150 {
151 if (!TME_M68K_COND_TRUE(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 8, 4))) {
152 if (--TME_M68K_INSN_OP0(tme_int16_t) != -1) {
153 TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc
154 + 2
155 + TME_EXT_S16_U32(TME_M68K_INSN_OP1(tme_int16_t)));
156 }
157 }
158 TME_M68K_INSN_OK;
159 }
160
161 /* this cannot fault: */
162 static void
_tme_m68k_bcc(struct tme_m68k * ic,tme_int32_t disp)163 _tme_m68k_bcc(struct tme_m68k *ic, tme_int32_t disp)
164 {
165 if (TME_M68K_COND_TRUE(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 8, 4))) {
166 TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc + 2 + disp);
167 }
168 TME_M68K_INSN_OK;
169 }
TME_M68K_INSN(tme_m68k_bcc)170 TME_M68K_INSN(tme_m68k_bcc)
171 {
172 _tme_m68k_bcc(ic, TME_EXT_S8_S32((tme_int8_t) TME_M68K_INSN_OPCODE));
173 }
TME_M68K_INSN(tme_m68k_bccl)174 TME_M68K_INSN(tme_m68k_bccl)
175 {
176 _tme_m68k_bcc(ic, TME_M68K_INSN_OP0(tme_int32_t));
177 }
178
179 /* this can fault: */
180 static void
_tme_m68k_bsr(struct tme_m68k * ic,tme_int32_t disp)181 _tme_m68k_bsr(struct tme_m68k *ic, tme_int32_t disp)
182 {
183 TME_M68K_INSN_CANFAULT;
184 tme_m68k_push32(ic, ic->tme_m68k_ireg_pc_next);
185 /* while the above push can fault, we don't have to worry about
186 restarting here, because after this point, nothing can fault for
187 the remainder of this instruction (the executor makes no stores
188 on behalf of a bsr): */
189 tme_m68k_log(ic, 250, TME_OK,
190 (TME_M68K_LOG_HANDLE(ic),
191 _("bsr 0x%08x"),
192 (ic->tme_m68k_ireg_pc + 2 + disp)));
193 TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc + 2 + disp);
194 TME_M68K_INSN_OK;
195 }
TME_M68K_INSN(tme_m68k_bsr)196 TME_M68K_INSN(tme_m68k_bsr)
197 {
198 _tme_m68k_bsr(ic, TME_EXT_S8_S32((tme_int8_t) TME_M68K_INSN_OPCODE));
199 }
TME_M68K_INSN(tme_m68k_bsrl)200 TME_M68K_INSN(tme_m68k_bsrl)
201 {
202 _tme_m68k_bsr(ic, TME_M68K_INSN_OP0(tme_int32_t));
203 }
204
205 /* this can fault: */
TME_M68K_INSN(tme_m68k_pea)206 TME_M68K_INSN(tme_m68k_pea)
207 {
208 TME_M68K_INSN_CANFAULT;
209 tme_m68k_push32(ic, TME_M68K_INSN_OP1(tme_uint32_t));
210 /* while the above push can fault, we don't have to worry about
211 restarting here, because after this point, nothing can fault for
212 the remainder of this instruction (the executor makes no stores
213 on behalf of a pea): */
214 TME_M68K_INSN_OK;
215 }
216
217 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_bkpt)218 TME_M68K_INSN(tme_m68k_bkpt)
219 {
220 TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
221 }
222
223 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_illegal)224 TME_M68K_INSN(tme_m68k_illegal)
225 {
226 TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
227 }
228
229 /* this can fault: */
TME_M68K_INSN(tme_m68k_tas)230 TME_M68K_INSN(tme_m68k_tas)
231 {
232 struct tme_m68k_rmw rmw;
233 struct tme_m68k_tlb *tlb;
234 tme_shared tme_int8_t *mem;
235 tme_uint8_t flags;
236 tme_int8_t value;
237 tme_int8_t value_written;
238 tme_int8_t value_verify;
239
240 /* start the read/modify/write cycle: */
241 rmw.tme_m68k_rmw_addresses[0] = ic->_tme_m68k_ea_address;
242 rmw.tme_m68k_rmw_address_count = 1;
243 rmw.tme_m68k_rmw_size = sizeof(tme_uint8_t);
244 if (tme_m68k_rmw_start(ic,
245 &rmw))
246 TME_M68K_INSN_OK;
247
248 /* if this TLB entry allows fast reading: */
249 if (!rmw.tme_m68k_rmw_slow_reads[0]) {
250
251 /* get this TLB entry: */
252 tlb = rmw.tme_m68k_rmw_tlbs[0];
253
254 /* make the emulator memory pointer: */
255 mem = (tme_shared tme_int8_t *) (tlb->tme_m68k_tlb_emulator_off_read + ic->_tme_m68k_ea_address);
256
257 /* read memory: */
258 value
259 = tme_memory_atomic_read8((tme_shared tme_uint8_t *) mem,
260 tlb->tme_m68k_tlb_bus_rwlock,
261 sizeof(tme_uint8_t));
262
263 /* spin the tas in a compare-and-exchange loop: */
264 for (;;) {
265
266 /* make the value to write: */
267 value_written = value | 0x80;
268
269 /* try the compare-and-exchange: */
270 value_verify
271 = tme_memory_atomic_cx8((tme_shared tme_uint8_t *) mem,
272 value,
273 value_written,
274 tlb->tme_m68k_tlb_bus_rwlock,
275 sizeof(tme_uint8_t));
276
277 /* if the compare-and-exchange failed: */
278 if (__tme_predict_false(value_verify != value)) {
279
280 /* loop with the new value read from the memory: */
281 value = value_verify;
282 continue;
283 }
284
285 /* stop now: */
286 break;
287 }
288
289 /* store the value read: */
290 ic->tme_m68k_ireg_memx8 = value;
291 }
292
293 /* the modify part of the read/modify/write cycle: */
294 value = ic->tme_m68k_ireg_memx8;
295 flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
296 if (value < 0) flags |= TME_M68K_FLAG_N;
297 if (value == 0) flags |= TME_M68K_FLAG_Z;
298 ic->tme_m68k_ireg_ccr = flags;
299 ic->tme_m68k_ireg_memx8 |= 0x80;
300
301 /* finish the read/modify/write cycle: */
302 tme_m68k_rmw_finish(ic,
303 &rmw,
304 TRUE);
305
306 TME_M68K_INSN_OK;
307 }
308
309 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_tas_r)310 TME_M68K_INSN(tme_m68k_tas_r)
311 {
312 tme_uint8_t flags;
313 tme_int8_t value;
314 value = TME_M68K_INSN_OP1(tme_int8_t);
315 flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
316 if (value < 0) flags |= TME_M68K_FLAG_N;
317 if (value == 0) flags |= TME_M68K_FLAG_Z;
318 ic->tme_m68k_ireg_ccr = flags;
319 TME_M68K_INSN_OP1(tme_int8_t) = value | 0x80;
320 TME_M68K_INSN_OK;
321 }
322
323 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_move_usp)324 TME_M68K_INSN(tme_m68k_move_usp)
325 {
326 TME_M68K_INSN_PRIV;
327 if (TME_M68K_INSN_OPCODE & TME_BIT(3)) {
328 TME_M68K_INSN_OP1(tme_uint32_t) = ic->tme_m68k_ireg_usp;
329 }
330 else {
331 ic->tme_m68k_ireg_usp = TME_M68K_INSN_OP1(tme_uint32_t);
332 }
333 TME_M68K_INSN_OK;
334 }
335
336 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_trap)337 TME_M68K_INSN(tme_m68k_trap)
338 {
339 ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
340 TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP_0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 4)));
341 }
342
343 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_trapv)344 TME_M68K_INSN(tme_m68k_trapv)
345 {
346 if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_V) {
347 ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
348 ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
349 TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP));
350 }
351 TME_M68K_INSN_OK;
352 }
353
354 /* this can fault: */
TME_M68K_INSN(tme_m68k_link)355 TME_M68K_INSN(tme_m68k_link)
356 {
357 TME_M68K_INSN_CANFAULT;
358 tme_m68k_push32(ic, TME_M68K_INSN_OP1(tme_uint32_t));
359 TME_M68K_INSN_OP1(tme_uint32_t) = ic->tme_m68k_ireg_a7;
360 ic->tme_m68k_ireg_a7 += TME_M68K_INSN_OP0(tme_uint32_t);
361 TME_M68K_INSN_OK;
362 }
363
364 /* this can fault: */
TME_M68K_INSN(tme_m68k_unlk)365 TME_M68K_INSN(tme_m68k_unlk)
366 {
367 TME_M68K_INSN_CANFAULT;
368 ic->tme_m68k_ireg_a7 = TME_M68K_INSN_OP0(tme_uint32_t);
369 tme_m68k_pop32(ic, &TME_M68K_INSN_OP0(tme_uint32_t));
370 TME_M68K_INSN_OK;
371 }
372
373 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_movec)374 TME_M68K_INSN(tme_m68k_movec)
375 {
376 int ireg;
377 tme_uint32_t *creg;
378 tme_uint32_t mask;
379 int illegal;
380 TME_M68K_INSN_PRIV;
381 /* in case we're reading the msp or isp and we're on that stack,
382 this flushes %a7 to that register: */
383 tme_m68k_change_sr(ic, ic->tme_m68k_ireg_sr);
384 ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);
385 mask = 0xffffffff;
386 illegal = FALSE;
387 switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 12)) {
388 case 0x000: creg = &ic->tme_m68k_ireg_sfc; mask = TME_M68K_FC_7; break;
389 case 0x001: creg = &ic->tme_m68k_ireg_dfc; mask = TME_M68K_FC_7; break;
390 case 0x002: creg = &ic->tme_m68k_ireg_cacr; mask = 0x3; illegal = (ic->tme_m68k_type < TME_M68K_M68020); break;
391 case 0x800: creg = &ic->tme_m68k_ireg_usp; break;
392 case 0x801: creg = &ic->tme_m68k_ireg_vbr; break;
393 case 0x802: creg = &ic->tme_m68k_ireg_caar; illegal = (ic->tme_m68k_type != TME_M68K_M68020); break;
394 case 0x803: creg = &ic->tme_m68k_ireg_msp; illegal = (ic->tme_m68k_type < TME_M68K_M68020); break;
395 case 0x804: creg = &ic->tme_m68k_ireg_isp; illegal = (ic->tme_m68k_type < TME_M68K_M68020); break;
396 default: illegal = TRUE; creg = NULL;
397 }
398 if (illegal) {
399 TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
400 }
401 if (TME_M68K_INSN_OPCODE & TME_BIT(0)) {
402 *creg = ic->tme_m68k_ireg_uint32(ireg) & mask;
403 }
404 else {
405 ic->tme_m68k_ireg_uint32(ireg) = *creg;
406 }
407 /* in case we're writing the msp or isp and we're on that stack,
408 this flushes that register to %a7: */
409 tme_m68k_change_sr(ic, ic->tme_m68k_ireg_sr);
410 TME_M68K_INSN_OK;
411 }
412
413 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_reset)414 TME_M68K_INSN(tme_m68k_reset)
415 {
416 struct tme_bus_connection *conn_bus;
417 int rc;
418
419 TME_M68K_INSN_PRIV;
420
421 /* get the bus connection: */
422 conn_bus = &ic->_tme_m68k_bus_connection->tme_m68k_bus_connection;
423
424 /* unlock for the callout: */
425 tme_m68k_callout_unlock(ic);
426
427 /* assert the RESET line: */
428 rc = (*conn_bus->tme_bus_signal)
429 (conn_bus,
430 (TME_BUS_SIGNAL_RESET
431 | TME_BUS_SIGNAL_LEVEL_ASSERTED));
432 assert (rc == TME_OK);
433
434 /* XXX RESET is supposed to be asserted for 512 clocks,
435 so a sleep is needed here: */
436
437 /* negate the RESET line: */
438 rc = (*conn_bus->tme_bus_signal)
439 (conn_bus,
440 (TME_BUS_SIGNAL_RESET
441 | TME_BUS_SIGNAL_LEVEL_NEGATED));
442 assert (rc == TME_OK);
443
444 /* relock after the callout: */
445 tme_m68k_callout_relock(ic);
446
447 TME_M68K_INSN_OK;
448 }
449
450 /* this can fault: */
TME_M68K_INSN(tme_m68k_rtd)451 TME_M68K_INSN(tme_m68k_rtd)
452 {
453 TME_M68K_INSN_CANFAULT;
454 tme_m68k_pop32(ic, &ic->tme_m68k_ireg_memx32);
455 /* while the above pop can fault, we don't have to worry about
456 restarting here, because after this point, nothing can fault for
457 the remainder of this instruction (the executor makes no stores
458 on behalf of an rtd): */
459 ic->tme_m68k_ireg_a7 += TME_M68K_INSN_OP0(tme_uint32_t);
460 TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_memx32);
461 TME_M68K_INSN_OK;
462 }
463
464 /* this can fault: */
TME_M68K_INSN(tme_m68k_rtr)465 TME_M68K_INSN(tme_m68k_rtr)
466 {
467 TME_M68K_INSN_CANFAULT;
468 tme_m68k_pop16(ic, &ic->tme_m68k_ireg_memx16);
469 if (!TME_M68K_SEQUENCE_RESTARTING) {
470 ic->tme_m68k_ireg_ccr = ic->tme_m68k_ireg_memx8 & TME_M68K_FLAG_CCR;
471 }
472 tme_m68k_pop32(ic, &ic->tme_m68k_ireg_memx32);
473 /* while the above pop can fault, we don't have to worry about
474 restarting here, because after this point, nothing can fault for
475 the remainder of this instruction (the executor makes no stores
476 on behalf of an rtr): */
477 TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_memx32);
478 TME_M68K_INSN_OK;
479 }
480
481 /* this can fault: */
TME_M68K_INSN(tme_m68k_rts)482 TME_M68K_INSN(tme_m68k_rts)
483 {
484 TME_M68K_INSN_CANFAULT;
485 tme_m68k_pop32(ic, &ic->tme_m68k_ireg_memx32);
486 tme_m68k_log(ic, 250, TME_OK,
487 (TME_M68K_LOG_HANDLE(ic),
488 _("rts 0x%08x"),
489 ic->tme_m68k_ireg_memx32));
490 TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_memx32);
491 TME_M68K_INSN_OK;
492 }
493
494 /* this can fault: */
TME_M68K_INSN(tme_m68k_jsr)495 TME_M68K_INSN(tme_m68k_jsr)
496 {
497 TME_M68K_INSN_CANFAULT;
498 tme_m68k_push32(ic, ic->tme_m68k_ireg_pc_next);
499 tme_m68k_log(ic, 250, TME_OK,
500 (TME_M68K_LOG_HANDLE(ic),
501 _("jsr 0x%08x"),
502 ic->_tme_m68k_ea_address));
503 TME_M68K_INSN_BRANCH(ic->_tme_m68k_ea_address);
504 TME_M68K_INSN_OK;
505 }
506
507 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_jmp)508 TME_M68K_INSN(tme_m68k_jmp)
509 {
510 TME_M68K_INSN_BRANCH(ic->_tme_m68k_ea_address);
511 TME_M68K_INSN_OK;
512 }
513
514 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_rte)515 TME_M68K_INSN(tme_m68k_rte)
516 {
517 TME_M68K_INSN_PRIV;
518 ic->_tme_m68k_mode = TME_M68K_MODE_RTE;
519 TME_M68K_SEQUENCE_START;
520 tme_m68k_redispatch(ic);
521 }
522
523 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_stop)524 TME_M68K_INSN(tme_m68k_stop)
525 {
526 TME_M68K_INSN_PRIV;
527 ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
528 ic->tme_m68k_ireg_sr = TME_M68K_INSN_SPECOP;
529 ic->_tme_m68k_mode = TME_M68K_MODE_STOP;
530 TME_M68K_SEQUENCE_START;
531 tme_m68k_redispatch(ic);
532 }
533
534 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_priv)535 TME_M68K_INSN(tme_m68k_priv)
536 {
537 TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_PRIV);
538 }
539
540 /* this can fault: */
TME_M68K_INSN(tme_m68k_cmp2_chk2)541 TME_M68K_INSN(tme_m68k_cmp2_chk2)
542 {
543 tme_uint32_t ireg;
544 unsigned int size_bytes, size_name, size_ireg;
545 tme_uint32_t uvalue, ulower, uupper;
546
547 TME_M68K_INSN_CANFAULT;
548
549 /* get the register to check and the operand size: */
550 ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);
551 size_bytes = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 2);
552 size_ireg = 2 - size_bytes;
553 size_bytes = 1 << size_bytes;
554 #if TME_M68K_SIZE_8 != 1
555 #error "TME_M68K_SIZE_8 must be 1"
556 #endif
557 #if TME_M68K_SIZE_16 != 2
558 #error "TME_M68K_SIZE_16 must be 2"
559 #endif
560 #if TME_M68K_SIZE_32 != 4
561 #error "TME_M68K_SIZE_32 must be 4"
562 #endif
563 size_name = size_bytes;
564
565 /* read in the two bounds: */
566 (*_tme_m68k_read_mem[size_name])(ic, TME_M68K_IREG_MEMX32 << size_ireg);
567 if (!TME_M68K_SEQUENCE_RESTARTING) {
568 ic->_tme_m68k_ea_address += size_bytes;
569 }
570 (*_tme_m68k_read_mem[size_name])(ic, TME_M68K_IREG_MEMY32 << size_ireg);
571
572 /* if we have an address register, sign-extend the bounds to 32
573 bits: */
574 if (ireg >= TME_M68K_IREG_A0) {
575 if (size_name == TME_M68K_SIZE_8) {
576 ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = TME_EXT_S8_S32(ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMX8));
577 ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32) = TME_EXT_S8_S32(ic->tme_m68k_ireg_int8(TME_M68K_IREG_MEMY8));
578 }
579 else if (size_name == TME_M68K_SIZE_16) {
580 ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = TME_EXT_S16_S32(ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMX16));
581 ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMY32) = TME_EXT_S16_S32(ic->tme_m68k_ireg_int16(TME_M68K_IREG_MEMY16));
582 }
583 size_bytes = sizeof(tme_uint32_t);
584 size_name = TME_M68K_SIZE_32;
585 }
586
587 /* get the values to check: */
588 switch (size_name) {
589 case TME_M68K_SIZE_8:
590 uvalue = ic->tme_m68k_ireg_uint8(ireg << 2);
591 ulower = ic->tme_m68k_ireg_uint8(TME_M68K_IREG_MEMX8);
592 uupper = ic->tme_m68k_ireg_uint8(TME_M68K_IREG_MEMY8);
593 break;
594 case TME_M68K_SIZE_16:
595 uvalue = ic->tme_m68k_ireg_uint16(ireg << 1);
596 ulower = ic->tme_m68k_ireg_uint16(TME_M68K_IREG_MEMX16);
597 uupper = ic->tme_m68k_ireg_uint16(TME_M68K_IREG_MEMY16);
598 break;
599 case TME_M68K_SIZE_32:
600 uvalue = ic->tme_m68k_ireg_uint32(ireg);
601 ulower = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_MEMX32);
602 uupper = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_MEMY32);
603 break;
604 default: abort();
605 }
606
607 /* do the comparison. if the value is out-of-bounds and this is
608 a chk2 instruction, trap: */
609 ic->tme_m68k_ireg_ccr = (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
610 if (uvalue == ulower
611 || uvalue == uupper) {
612 ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
613 }
614 else if ((ulower > uupper)
615 ? (uvalue < ulower && uvalue > uupper)
616 : (uvalue < ulower || uvalue > uupper)) {
617 ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_C;
618 if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {
619 ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
620 ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
621 TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));
622 }
623 }
624
625 TME_M68K_INSN_OK;
626 }
627
TME_M68K_INSN(tme_m68k_callm)628 TME_M68K_INSN(tme_m68k_callm)
629 {
630 /* TBD */
631 abort();
632 }
633
TME_M68K_INSN(tme_m68k_rtm)634 TME_M68K_INSN(tme_m68k_rtm)
635 {
636 /* TBD */
637 abort();
638 }
639
640 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_trapcc)641 TME_M68K_INSN(tme_m68k_trapcc)
642 {
643 if (TME_M68K_COND_TRUE(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 8, 4))) {
644 ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
645 ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
646 TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP));
647 }
648 TME_M68K_INSN_OK;
649 }
650
651 /* the bitfield helper functions handle faults: */
TME_M68K_INSN(tme_m68k_bfchg)652 TME_M68K_INSN(tme_m68k_bfchg)
653 {
654 tme_uint32_t bf_value;
655 bf_value = tme_m68k_bitfield_read_unsigned(ic);
656 tme_m68k_bitfield_write_unsigned(ic, ~bf_value, FALSE);
657 TME_M68K_INSN_OK;
658 }
659
660 /* the bitfield helper functions handle faults: */
TME_M68K_INSN(tme_m68k_bfclr)661 TME_M68K_INSN(tme_m68k_bfclr)
662 {
663 (void) tme_m68k_bitfield_read_unsigned(ic);
664 tme_m68k_bitfield_write_unsigned(ic, 0, FALSE);
665 TME_M68K_INSN_OK;
666 }
667
668 /* the bitfield helper functions handle faults: */
TME_M68K_INSN(tme_m68k_bfexts)669 TME_M68K_INSN(tme_m68k_bfexts)
670 {
671 tme_int32_t bf_value;
672 bf_value = tme_m68k_bitfield_read_signed(ic);
673 ic->tme_m68k_ireg_int32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3))
674 = bf_value;
675 TME_M68K_INSN_OK;
676 }
677
678 /* the bitfield helper functions handle faults: */
TME_M68K_INSN(tme_m68k_bfextu)679 TME_M68K_INSN(tme_m68k_bfextu)
680 {
681 tme_uint32_t bf_value;
682 bf_value = tme_m68k_bitfield_read_unsigned(ic);
683 ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3))
684 = bf_value;
685 TME_M68K_INSN_OK;
686 }
687
688 /* the bitfield helper functions handle faults: */
TME_M68K_INSN(tme_m68k_bfffo)689 TME_M68K_INSN(tme_m68k_bfffo)
690 {
691 tme_int16_t specop;
692 tme_int32_t bf_offset;
693 unsigned int bf_width;
694 tme_uint32_t bf_value;
695 unsigned int bf_pos;
696
697 /* get the bitfield offset from a data register or as an immediate: */
698 specop = TME_M68K_INSN_SPECOP;
699 bf_offset = ((specop & TME_BIT(11))
700 ? ic->tme_m68k_ireg_int32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 6, 3))
701 : (tme_int32_t) TME_FIELD_EXTRACTU(specop, 6, 5));
702
703 /* get the bitfield width: */
704 bf_width = tme_m68k_bitfield_width(ic);
705
706 /* get the bitfield value: */
707 bf_value = tme_m68k_bitfield_read_unsigned(ic);
708
709 /* find the first set bit: */
710 for (bf_pos = 0, bf_value <<= (32 - bf_width);
711 bf_pos < bf_width && !(bf_value & 0x80000000);
712 bf_pos++, bf_value <<= 1);
713
714 /* set the result: */
715 ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specop, 12, 3))
716 = bf_offset + bf_pos;
717
718 TME_M68K_INSN_OK;
719 }
720
721 /* the bitfield helper functions handle faults: */
TME_M68K_INSN(tme_m68k_bfins)722 TME_M68K_INSN(tme_m68k_bfins)
723 {
724 tme_m68k_bitfield_write_unsigned(ic,
725 ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0
726 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3)),
727 TRUE);
728 TME_M68K_INSN_OK;
729 }
730
731 /* the bitfield helper functions handle faults: */
TME_M68K_INSN(tme_m68k_bfset)732 TME_M68K_INSN(tme_m68k_bfset)
733 {
734 (void) tme_m68k_bitfield_read_unsigned(ic);
735 tme_m68k_bitfield_write_unsigned(ic, 0xffffffff, FALSE);
736 TME_M68K_INSN_OK;
737 }
738
739 /* the bitfield helper functions handle faults: */
TME_M68K_INSN(tme_m68k_bftst)740 TME_M68K_INSN(tme_m68k_bftst)
741 {
742 (void) tme_m68k_bitfield_read_unsigned(ic);
743 TME_M68K_INSN_OK;
744 }
745
746 /* this can fault: */
TME_M68K_INSN(tme_m68k_pack)747 TME_M68K_INSN(tme_m68k_pack)
748 {
749 int ireg_x, ireg_y;
750 tme_uint16_t value;
751
752 TME_M68K_INSN_CANFAULT;
753
754 /* get the two registers: */
755 ireg_x = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
756 ireg_y = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
757
758 /* if this is a memory pack: */
759 if (TME_M68K_INSN_OPCODE & TME_BIT(3)) {
760 ireg_x += TME_M68K_IREG_A0;
761 ireg_y += TME_M68K_IREG_A0;
762
763 /* do the predecrement read of two bytes: */
764 if (!TME_M68K_SEQUENCE_RESTARTING) {
765 ic->tme_m68k_ireg_uint32(ireg_x) -= sizeof(tme_uint16_t);
766 ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
767 ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_x);
768 }
769 tme_m68k_read_memx16(ic);
770
771 /* get the two bytes and add the extension: */
772 value = ic->tme_m68k_ireg_memx16 + TME_M68K_INSN_SPECOP;
773
774 /* do the predecrement write of one byte: */
775 if (!TME_M68K_SEQUENCE_RESTARTING) {
776 ic->tme_m68k_ireg_uint32(ireg_y) -= sizeof(tme_uint8_t);
777 ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
778 ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_y);
779 ic->tme_m68k_ireg_memx8 = (tme_uint8_t) ((value & 0x0f) | (value >> 4));
780 }
781 tme_m68k_write_memx8(ic);
782 }
783
784 /* if this is a register pack: */
785 else {
786 ireg_x += TME_M68K_IREG_D0;
787 ireg_y += TME_M68K_IREG_D0;
788 value = ic->tme_m68k_ireg_uint16(ireg_x << 1) + TME_M68K_INSN_SPECOP;
789 ic->tme_m68k_ireg_uint8(ireg_y << 2) = (tme_uint8_t) ((value & 0x0f) | (value >> 4));
790 }
791
792 TME_M68K_INSN_OK;
793 }
794
795 /* this can fault: */
TME_M68K_INSN(tme_m68k_unpk)796 TME_M68K_INSN(tme_m68k_unpk)
797 {
798 int ireg_x, ireg_y;
799 tme_uint16_t value;
800
801 TME_M68K_INSN_CANFAULT;
802
803 /* get the two registers: */
804 ireg_x = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
805 ireg_y = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
806
807 /* if this is a memory pack: */
808 if (TME_M68K_INSN_OPCODE & TME_BIT(3)) {
809 ireg_x += TME_M68K_IREG_A0;
810 ireg_y += TME_M68K_IREG_A0;
811
812 /* do the predecrement read of one byte: */
813 if (!TME_M68K_SEQUENCE_RESTARTING) {
814 ic->tme_m68k_ireg_uint32(ireg_x) -= sizeof(tme_uint8_t);
815 ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
816 ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_x);
817 }
818 tme_m68k_read_memx8(ic);
819
820 /* unpack the byte and add the extension: */
821 value = ic->tme_m68k_ireg_memx8;
822 value = ((value & 0x0f) | ((value & 0xf0) << 4)) + TME_M68K_INSN_SPECOP;
823
824 /* do the predecrement write of two bytes: */
825 if (!TME_M68K_SEQUENCE_RESTARTING) {
826 ic->tme_m68k_ireg_uint32(ireg_y) -= sizeof(tme_uint16_t);
827 ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
828 ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ireg_y);
829 ic->tme_m68k_ireg_memx16 = value;
830 }
831 tme_m68k_write_memx16(ic);
832 }
833
834 /* if this is a register pack: */
835 else {
836 ireg_x += TME_M68K_IREG_D0;
837 ireg_y += TME_M68K_IREG_D0;
838 value = ic->tme_m68k_ireg_uint8(ireg_x << 2);
839 value = ((value & 0x0f) | ((value & 0xf0) << 4)) + TME_M68K_INSN_SPECOP;
840 ic->tme_m68k_ireg_uint16(ireg_y << 1) = value;
841 }
842
843 TME_M68K_INSN_OK;
844 }
845
846 /* these just redispatch into one of the multiply or divide insns: */
TME_M68K_INSN(tme_m68k_mull)847 TME_M68K_INSN(tme_m68k_mull)
848 {
849 if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {
850 tme_m68k_mulsl(ic, _op0, _op1);
851 }
852 else {
853 tme_m68k_mulul(ic, _op0, _op1);
854 }
855 }
TME_M68K_INSN(tme_m68k_divl)856 TME_M68K_INSN(tme_m68k_divl)
857 {
858 if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {
859 tme_m68k_divsl(ic, _op0, _op1);
860 }
861 else {
862 tme_m68k_divul(ic, _op0, _op1);
863 }
864 }
865
866 #include "m68k-bus-auto.c"
867
868 #include "m68k-insns-auto.c"
869