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