1 /* automatically generated by m68k-insns-auto.sh, do not edit! */
2 _TME_RCSID("$Id: m68k-insns-auto.sh,v 1.26 2009/08/29 19:38:23 fredette Exp $");
3 
4 #include "m68k-impl.h"
5 
6 
7 /* this does a 8-bit "add SRC, DST": */
TME_M68K_INSN(tme_m68k_add8)8 TME_M68K_INSN(tme_m68k_add8)
9 {
10   tme_uint8_t res, op0, op1;
11   tme_uint8_t flags;
12 
13   /* load the operand(s): */
14   op0 = *((tme_uint8_t *) _op0);
15   op1 = *((tme_uint8_t *) _op1);
16 
17   /* perform the operation: */
18   res = op1 + op0;
19 
20   /* store the result: */
21   *((tme_uint8_t *) _op1) = res;
22 
23   /* set the flags: */
24   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
25   if (res == 0) flags |= TME_M68K_FLAG_Z;
26   flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xff) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V;
27   if (op0 > (op1 ^ 0xff)) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
28   ic->tme_m68k_ireg_ccr = flags;
29 
30   TME_M68K_INSN_OK;
31 }
32 
33 /* this does a 8-bit "sub SRC, DST": */
TME_M68K_INSN(tme_m68k_sub8)34 TME_M68K_INSN(tme_m68k_sub8)
35 {
36   tme_uint8_t res, op0, op1;
37   tme_uint8_t flags;
38 
39   /* load the operand(s): */
40   op0 = *((tme_uint8_t *) _op0);
41   op1 = *((tme_uint8_t *) _op1);
42 
43   /* perform the operation: */
44   res = op1 - op0;
45 
46   /* store the result: */
47   *((tme_uint8_t *) _op1) = res;
48 
49   /* set the flags: */
50   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
51   if (res == 0) flags |= TME_M68K_FLAG_Z;
52   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V;
53   if (op0 > op1) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
54   ic->tme_m68k_ireg_ccr = flags;
55 
56   TME_M68K_INSN_OK;
57 }
58 
59 /* this does a 8-bit "cmp SRC, DST": */
TME_M68K_INSN(tme_m68k_cmp8)60 TME_M68K_INSN(tme_m68k_cmp8)
61 {
62   tme_uint8_t res, op0, op1;
63   tme_uint8_t flags;
64 
65   /* load the operand(s): */
66   op0 = *((tme_uint8_t *) _op0);
67   op1 = *((tme_uint8_t *) _op1);
68 
69   /* perform the operation: */
70   res = op1 - op0;
71 
72   /* set the flags: */
73   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
74   if (res == 0) flags |= TME_M68K_FLAG_Z;
75   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V;
76   if (op0 > op1) flags |= TME_M68K_FLAG_C;
77   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
78   ic->tme_m68k_ireg_ccr = flags;
79 
80   TME_M68K_INSN_OK;
81 }
82 
83 /* this does a 8-bit "neg DST": */
TME_M68K_INSN(tme_m68k_neg8)84 TME_M68K_INSN(tme_m68k_neg8)
85 {
86   tme_uint8_t res, op1;
87   tme_uint8_t flags;
88 
89   /* load the operand(s): */
90   op1 = *((tme_uint8_t *) _op1);
91 
92   /* perform the operation: */
93   res = 0 - op1;
94 
95   /* store the result: */
96   *((tme_uint8_t *) _op1) = res;
97 
98   /* set the flags: */
99   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
100   if (res == 0) flags |= TME_M68K_FLAG_Z;
101   flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V;
102   if (op1 > 0) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
103   ic->tme_m68k_ireg_ccr = flags;
104 
105   TME_M68K_INSN_OK;
106 }
107 
108 /* this does a 8-bit "or SRC, DST": */
TME_M68K_INSN(tme_m68k_or8)109 TME_M68K_INSN(tme_m68k_or8)
110 {
111   tme_uint8_t res, op0, op1;
112   tme_uint8_t flags;
113 
114   /* load the operand(s): */
115   op0 = *((tme_uint8_t *) _op0);
116   op1 = *((tme_uint8_t *) _op1);
117 
118   /* perform the operation: */
119   res = op1 | op0;
120 
121   /* store the result: */
122   *((tme_uint8_t *) _op1) = res;
123 
124   /* set the flags: */
125   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
126   if (res == 0) flags |= TME_M68K_FLAG_Z;
127   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
128   ic->tme_m68k_ireg_ccr = flags;
129 
130   TME_M68K_INSN_OK;
131 }
132 
133 /* this does a 8-bit "and SRC, DST": */
TME_M68K_INSN(tme_m68k_and8)134 TME_M68K_INSN(tme_m68k_and8)
135 {
136   tme_uint8_t res, op0, op1;
137   tme_uint8_t flags;
138 
139   /* load the operand(s): */
140   op0 = *((tme_uint8_t *) _op0);
141   op1 = *((tme_uint8_t *) _op1);
142 
143   /* perform the operation: */
144   res = op1 & op0;
145 
146   /* store the result: */
147   *((tme_uint8_t *) _op1) = res;
148 
149   /* set the flags: */
150   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
151   if (res == 0) flags |= TME_M68K_FLAG_Z;
152   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
153   ic->tme_m68k_ireg_ccr = flags;
154 
155   TME_M68K_INSN_OK;
156 }
157 
158 /* this does a 8-bit "eor SRC, DST": */
TME_M68K_INSN(tme_m68k_eor8)159 TME_M68K_INSN(tme_m68k_eor8)
160 {
161   tme_uint8_t res, op0, op1;
162   tme_uint8_t flags;
163 
164   /* load the operand(s): */
165   op0 = *((tme_uint8_t *) _op0);
166   op1 = *((tme_uint8_t *) _op1);
167 
168   /* perform the operation: */
169   res = op1 ^ op0;
170 
171   /* store the result: */
172   *((tme_uint8_t *) _op1) = res;
173 
174   /* set the flags: */
175   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
176   if (res == 0) flags |= TME_M68K_FLAG_Z;
177   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
178   ic->tme_m68k_ireg_ccr = flags;
179 
180   TME_M68K_INSN_OK;
181 }
182 
183 /* this does a 8-bit "not DST": */
TME_M68K_INSN(tme_m68k_not8)184 TME_M68K_INSN(tme_m68k_not8)
185 {
186   tme_uint8_t res, op1;
187   tme_uint8_t flags;
188 
189   /* load the operand(s): */
190   op1 = *((tme_uint8_t *) _op1);
191 
192   /* perform the operation: */
193   res = ~ op1;
194 
195   /* store the result: */
196   *((tme_uint8_t *) _op1) = res;
197 
198   /* set the flags: */
199   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
200   if (res == 0) flags |= TME_M68K_FLAG_Z;
201   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
202   ic->tme_m68k_ireg_ccr = flags;
203 
204   TME_M68K_INSN_OK;
205 }
206 
207 /* this does a 8-bit "tst DST": */
TME_M68K_INSN(tme_m68k_tst8)208 TME_M68K_INSN(tme_m68k_tst8)
209 {
210   tme_uint8_t res, op1;
211   tme_uint8_t flags;
212 
213   /* load the operand(s): */
214   op1 = *((tme_uint8_t *) _op1);
215 
216   /* perform the operation: */
217   res = op1;
218 
219   /* set the flags: */
220   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
221   if (res == 0) flags |= TME_M68K_FLAG_Z;
222   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
223   ic->tme_m68k_ireg_ccr = flags;
224 
225   TME_M68K_INSN_OK;
226 }
227 
228 /* this does a 8-bit "move DST": */
TME_M68K_INSN(tme_m68k_move8)229 TME_M68K_INSN(tme_m68k_move8)
230 {
231   tme_uint8_t res, op1;
232   tme_uint8_t flags;
233 
234   /* load the operand(s): */
235   op1 = *((tme_uint8_t *) _op1);
236 
237   /* perform the operation: */
238   res = op1;
239 
240   /* store the result: */
241   *((tme_uint8_t *) _op0) = res;
242 
243   /* set the flags: */
244   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
245   if (res == 0) flags |= TME_M68K_FLAG_Z;
246   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
247   ic->tme_m68k_ireg_ccr = flags;
248 
249   TME_M68K_INSN_OK;
250 }
251 
252 /* this does a 8-bit "clr DST": */
TME_M68K_INSN(tme_m68k_clr8)253 TME_M68K_INSN(tme_m68k_clr8)
254 {
255   tme_uint8_t res;
256   tme_uint8_t flags;
257 
258   /* load the operand(s): */
259 
260   /* perform the operation: */
261   res = 0;
262 
263   /* store the result: */
264   *((tme_uint8_t *) _op1) = res;
265 
266   /* set the flags: */
267   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
268   if (res == 0) flags |= TME_M68K_FLAG_Z;
269   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
270   ic->tme_m68k_ireg_ccr = flags;
271 
272   TME_M68K_INSN_OK;
273 }
274 
275 /* this does a 8-bit "negx DST": */
TME_M68K_INSN(tme_m68k_negx8)276 TME_M68K_INSN(tme_m68k_negx8)
277 {
278   tme_uint8_t res, op1;
279   tme_uint8_t flags;
280 
281   /* load the operand(s): */
282   op1 = *((tme_uint8_t *) _op1);
283 
284   /* perform the operation: */
285   res = 0 - op1 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1);
286 
287   /* store the result: */
288   *((tme_uint8_t *) _op1) = res;
289 
290   /* set the flags: */
291   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
292   if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);
293   flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V;
294   if (op1 > 0 || (op1 == 0 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
295   ic->tme_m68k_ireg_ccr = flags;
296 
297   TME_M68K_INSN_OK;
298 }
299 
300 /* this does a 8-bit "addx SRC, DST": */
TME_M68K_INSN(tme_m68k_addx8)301 TME_M68K_INSN(tme_m68k_addx8)
302 {
303   tme_uint8_t res, op0, op1;
304   tme_uint8_t flags;
305 
306   /* load the operand(s): */
307   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
308   int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
309   int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
310   tme_uint32_t ireg_src_adjust = sizeof(tme_uint8_t) + ((ireg_src + 1) >> 3);
311   tme_uint32_t ireg_dst_adjust = sizeof(tme_uint8_t) + ((ireg_dst + 1) >> 3);
312   tme_uint16_t memory;
313 
314   memory = (TME_M68K_INSN_OPCODE & TME_BIT(3));
315   if (memory) {
316     TME_M68K_INSN_CANFAULT;
317     if (!TME_M68K_SEQUENCE_RESTARTING) {
318       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust;
319       ic->_tme_m68k_ea_function_code = function_code;
320       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);
321     }
322     tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY8);
323     if (!TME_M68K_SEQUENCE_RESTARTING) {
324       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust;
325       ic->_tme_m68k_ea_function_code = function_code;
326       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
327     }
328     tme_m68k_read_memx8(ic);
329     op1 = ic->tme_m68k_ireg_memx8;
330     op0 = ic->tme_m68k_ireg_memy8;
331   }
332   else {
333     op0 = ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_src) << 2);
334     op1 = ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_dst) << 2);
335   }
336 
337   /* perform the operation: */
338   res = op1 + op0 + ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1);
339 
340   /* store the result: */
341   if (memory) {
342     if (!TME_M68K_SEQUENCE_RESTARTING) {
343       ic->tme_m68k_ireg_memx8 = res;
344       ic->_tme_m68k_ea_function_code = function_code;
345       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
346     }
347     tme_m68k_write_memx8(ic);
348   }
349   else {
350     ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_dst) << 2) = res;
351   }
352 
353   /* set the flags: */
354   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
355   if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);
356   flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xff) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V;
357   if (op0 > (op1 ^ 0xff) || (op0 == (op1 ^ 0xff) && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
358   ic->tme_m68k_ireg_ccr = flags;
359 
360   TME_M68K_INSN_OK;
361 }
362 
363 /* this does a 8-bit "subx SRC, DST": */
TME_M68K_INSN(tme_m68k_subx8)364 TME_M68K_INSN(tme_m68k_subx8)
365 {
366   tme_uint8_t res, op0, op1;
367   tme_uint8_t flags;
368 
369   /* load the operand(s): */
370   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
371   int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
372   int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
373   tme_uint32_t ireg_src_adjust = sizeof(tme_uint8_t) + ((ireg_src + 1) >> 3);
374   tme_uint32_t ireg_dst_adjust = sizeof(tme_uint8_t) + ((ireg_dst + 1) >> 3);
375   tme_uint16_t memory;
376 
377   memory = (TME_M68K_INSN_OPCODE & TME_BIT(3));
378   if (memory) {
379     TME_M68K_INSN_CANFAULT;
380     if (!TME_M68K_SEQUENCE_RESTARTING) {
381       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust;
382       ic->_tme_m68k_ea_function_code = function_code;
383       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);
384     }
385     tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY8);
386     if (!TME_M68K_SEQUENCE_RESTARTING) {
387       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust;
388       ic->_tme_m68k_ea_function_code = function_code;
389       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
390     }
391     tme_m68k_read_memx8(ic);
392     op1 = ic->tme_m68k_ireg_memx8;
393     op0 = ic->tme_m68k_ireg_memy8;
394   }
395   else {
396     op0 = ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_src) << 2);
397     op1 = ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_dst) << 2);
398   }
399 
400   /* perform the operation: */
401   res = op1 - op0 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1);
402 
403   /* store the result: */
404   if (memory) {
405     if (!TME_M68K_SEQUENCE_RESTARTING) {
406       ic->tme_m68k_ireg_memx8 = res;
407       ic->_tme_m68k_ea_function_code = function_code;
408       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
409     }
410     tme_m68k_write_memx8(ic);
411   }
412   else {
413     ic->tme_m68k_ireg_uint8((TME_M68K_IREG_D0 + ireg_dst) << 2) = res;
414   }
415 
416   /* set the flags: */
417   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
418   if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);
419   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V;
420   if (op0 > op1 || (op0 == op1 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
421   ic->tme_m68k_ireg_ccr = flags;
422 
423   TME_M68K_INSN_OK;
424 }
425 
426 /* this does a 8-bit "cmpm SRC, DST": */
TME_M68K_INSN(tme_m68k_cmpm8)427 TME_M68K_INSN(tme_m68k_cmpm8)
428 {
429   tme_uint8_t res, op0, op1;
430   tme_uint8_t flags;
431 
432   /* load the operand(s): */
433   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
434   int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
435   int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
436   tme_uint32_t ireg_src_adjust = sizeof(tme_uint8_t) + ((ireg_src + 1) >> 3);
437   tme_uint32_t ireg_dst_adjust = sizeof(tme_uint8_t) + ((ireg_dst + 1) >> 3);
438 
439   TME_M68K_INSN_CANFAULT;
440 
441   if (!TME_M68K_SEQUENCE_RESTARTING) {
442     ic->_tme_m68k_ea_function_code = function_code;
443     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);
444     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) += ireg_src_adjust;
445   }
446   tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY8);
447   if (!TME_M68K_SEQUENCE_RESTARTING) {
448     ic->_tme_m68k_ea_function_code = function_code;
449     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
450     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust;
451   }
452   tme_m68k_read_memx8(ic);
453   op1 = ic->tme_m68k_ireg_memx8;
454   op0 = ic->tme_m68k_ireg_memy8;
455 
456   /* perform the operation: */
457   res = op1 - op0;
458 
459   /* set the flags: */
460   flags = ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
461   if (res == 0) flags |= TME_M68K_FLAG_Z;
462   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (8 - 1))) * TME_M68K_FLAG_V;
463   if (op0 > op1) flags |= TME_M68K_FLAG_C;
464   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
465   ic->tme_m68k_ireg_ccr = flags;
466 
467   TME_M68K_INSN_OK;
468 }
469 
470 /* the btst function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_btst8)471 TME_M68K_INSN(tme_m68k_btst8)
472 {
473   tme_uint8_t value, bit;
474   bit = _TME_BIT(tme_uint8_t, TME_M68K_INSN_OP0(tme_uint8_t) & (8 - 1));
475   value = TME_M68K_INSN_OP1(tme_uint8_t);
476   if (value & bit) {
477     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;
478   }
479   else {
480     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
481   }
482   TME_M68K_INSN_OK;
483 }
484 
485 /* the bchg function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_bchg8)486 TME_M68K_INSN(tme_m68k_bchg8)
487 {
488   tme_uint8_t value, bit;
489   bit = _TME_BIT(tme_uint8_t, TME_M68K_INSN_OP0(tme_uint8_t) & (8 - 1));
490   value = TME_M68K_INSN_OP1(tme_uint8_t);
491   if (value & bit) {
492     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;
493   }
494   else {
495     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
496   }
497   TME_M68K_INSN_OP1(tme_uint8_t) = value ^ bit;
498   TME_M68K_INSN_OK;
499 }
500 
501 /* the bclr function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_bclr8)502 TME_M68K_INSN(tme_m68k_bclr8)
503 {
504   tme_uint8_t value, bit;
505   bit = _TME_BIT(tme_uint8_t, TME_M68K_INSN_OP0(tme_uint8_t) & (8 - 1));
506   value = TME_M68K_INSN_OP1(tme_uint8_t);
507   if (value & bit) {
508     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;
509   }
510   else {
511     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
512   }
513   TME_M68K_INSN_OP1(tme_uint8_t) = value & ~bit;
514   TME_M68K_INSN_OK;
515 }
516 
517 /* the bset function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_bset8)518 TME_M68K_INSN(tme_m68k_bset8)
519 {
520   tme_uint8_t value, bit;
521   bit = _TME_BIT(tme_uint8_t, TME_M68K_INSN_OP0(tme_uint8_t) & (8 - 1));
522   value = TME_M68K_INSN_OP1(tme_uint8_t);
523   if (value & bit) {
524     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;
525   }
526   else {
527     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
528   }
529   TME_M68K_INSN_OP1(tme_uint8_t) = value | bit;
530   TME_M68K_INSN_OK;
531 }
532 
533 /* the asl function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_asl8)534 TME_M68K_INSN(tme_m68k_asl8)
535 {
536   unsigned int count;
537   tme_uint8_t sign_bits, sign_bits_mask;
538   tme_uint8_t res;
539   tme_uint8_t flags;
540 
541   /* get the count and operand: */
542   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
543   res = TME_M68K_INSN_OP1(tme_uint8_t);
544 
545   /* generate the X, V, and C flags assuming the count is zero: */
546   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
547 
548   /* if the count is nonzero, update the result and
549      generate the X, V, and C flags: */
550   if (count > 0) {
551 
552     /* we need to see how the sign of the result will change during
553        shifting in order to generate V.
554 
555        in general, the idea is to get all of the bits that will ever
556        appear in the sign position into sign_bits, with a mask in
557        sign_bits_mask.  if (sign_bits & sign_bits_mask) is zero or
558        sign_bits_mask, clear V, else set V.
559 
560        start by loading the operand into sign_bits and setting
561        sign_bits_mask to all-bits-one.
562 
563        if the shift count is exactly 8 - 1, then all of the bits
564        of the operand will appear in the sign position.
565 
566        if the shift count is less than 8 - 1, then some of the
567        less significant bits of the operand will never appear in the
568        sign position, so we can shift sign_bits_mask to ignore them.
569 
570        if the shift count is greater than 8 - 1, then all of the
571        bits in the operand, plus at least one zero bit, will appear in
572        the sign position.  the only way that the sign bit will never
573        change during the shift is if the operand was zero to begin with.
574        without any changes to sign_bits or sign_bits_mask, the final
575        test will always work, except when sign_bits is all-bits-one.
576        the magic below clears the least-significant bit of sign_bits
577        iff sign_bits is all-bits-one: */
578     sign_bits = res;
579     if (63 > SHIFTMAX_INT8_T
580         && count > 8) {
581       res = 0;
582     }
583     res <<= (count - 1);
584     flags = (res >> (8 - 1));
585     flags *= TME_M68K_FLAG_C;
586     flags |= (flags * TME_M68K_FLAG_X);
587     res <<= 1;
588     sign_bits_mask = (tme_uint8_t) -1;
589     if (count != 8 - 1) {
590       if (count < 8) {
591         sign_bits_mask <<= ((8 - 1) - count);
592       }
593       else {
594         sign_bits ^= !(sign_bits + 1);
595       }
596     }
597     sign_bits &= sign_bits_mask;
598     if (sign_bits != 0 && sign_bits != sign_bits_mask) {
599       flags |= TME_M68K_FLAG_V;
600     }
601   }
602 
603   /* store the result: */
604   TME_M68K_INSN_OP1(tme_uint8_t) = res;
605 
606   /* generate the N flag.  we cast to tme_uint8_t as soon as we
607      know the bit we want is within the range of the type, to try
608      to affect the generated assembly: */
609   flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
610 
611   /* generate the Z flag: */
612   if (res == 0) flags |= TME_M68K_FLAG_Z;
613 
614   /* store the flags: */
615   ic->tme_m68k_ireg_ccr = flags;
616   TME_M68K_INSN_OK;
617 }
618 
619 /* the asr function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_asr8)620 TME_M68K_INSN(tme_m68k_asr8)
621 {
622   unsigned int count;
623   tme_int8_t res;
624   tme_uint8_t flags;
625 
626   /* get the count and operand: */
627   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
628   res = TME_M68K_INSN_OP1(tme_int8_t);
629 
630   /* generate the X, V, and C flags assuming the count is zero: */
631   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
632 
633   /* if the count is nonzero, update the result and
634      generate the X, V, and C flags: */
635   if (count > 0) {
636     if (63 > SHIFTMAX_INT8_T
637         && count > 8) {
638       res = 0 - (res < 0);
639     }
640 #ifdef SHIFTSIGNED_INT8_T
641     res >>= (count - 1);
642 #else  /* !SHIFTSIGNED_INT8_T */
643     for (; --count > 0; ) {
644       res = (res & ~((tme_int8_t) 1)) / 2;
645     }
646 #endif /* !SHIFTSIGNED_INT8_T */
647     flags = (res & 1);
648     flags *= TME_M68K_FLAG_C;
649     flags |= (flags * TME_M68K_FLAG_X);
650 #ifdef SHIFTSIGNED_INT8_T
651     res >>= 1;
652 #else  /* !SHIFTSIGNED_INT8_T */
653     res = (res & ~((tme_int8_t) 1)) / 2;
654 #endif /* !SHIFTSIGNED_INT8_T */
655   }
656 
657   /* store the result: */
658   TME_M68K_INSN_OP1(tme_int8_t) = res;
659 
660   /* generate the N flag.  we cast to tme_uint8_t as soon as we
661      know the bit we want is within the range of the type, to try
662      to affect the generated assembly: */
663   flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
664 
665   /* generate the Z flag: */
666   if (res == 0) flags |= TME_M68K_FLAG_Z;
667 
668   /* store the flags: */
669   ic->tme_m68k_ireg_ccr = flags;
670   TME_M68K_INSN_OK;
671 }
672 
673 /* the lsl function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_lsl8)674 TME_M68K_INSN(tme_m68k_lsl8)
675 {
676   unsigned int count;
677   tme_uint8_t res;
678   tme_uint8_t flags;
679 
680   /* get the count and operand: */
681   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
682   res = TME_M68K_INSN_OP1(tme_uint8_t);
683 
684   /* generate the X, V, and C flags assuming the count is zero: */
685   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
686 
687   /* if the count is nonzero, update the result and
688      generate the X, V, and C flags: */
689   if (count > 0) {
690     if (63 > SHIFTMAX_INT8_T
691         && count > 8) {
692       res = 0;
693     }
694     res <<= (count - 1);
695     flags = (res >> (8 - 1));
696     flags *= TME_M68K_FLAG_C;
697     flags |= (flags * TME_M68K_FLAG_X);
698     res <<= 1;
699   }
700 
701   /* store the result: */
702   TME_M68K_INSN_OP1(tme_uint8_t) = res;
703 
704   /* generate the N flag.  we cast to tme_uint8_t as soon as we
705      know the bit we want is within the range of the type, to try
706      to affect the generated assembly: */
707   flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
708 
709   /* generate the Z flag: */
710   if (res == 0) flags |= TME_M68K_FLAG_Z;
711 
712   /* store the flags: */
713   ic->tme_m68k_ireg_ccr = flags;
714   TME_M68K_INSN_OK;
715 }
716 
717 /* the lsr function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_lsr8)718 TME_M68K_INSN(tme_m68k_lsr8)
719 {
720   unsigned int count;
721   tme_uint8_t res;
722   tme_uint8_t flags;
723 
724   /* get the count and operand: */
725   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
726   res = TME_M68K_INSN_OP1(tme_uint8_t);
727 
728   /* generate the X, V, and C flags assuming the count is zero: */
729   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
730 
731   /* if the count is nonzero, update the result and
732      generate the X, V, and C flags: */
733   if (count > 0) {
734     if (63 > SHIFTMAX_INT8_T
735         && count > 8) {
736       res = 0;
737     }
738     res >>= (count - 1);
739     flags = (res & 1);
740     flags *= TME_M68K_FLAG_C;
741     flags |= (flags * TME_M68K_FLAG_X);
742     res >>= 1;
743   }
744 
745   /* store the result: */
746   TME_M68K_INSN_OP1(tme_uint8_t) = res;
747 
748   /* generate the N flag.  we cast to tme_uint8_t as soon as we
749      know the bit we want is within the range of the type, to try
750      to affect the generated assembly: */
751   flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
752 
753   /* generate the Z flag: */
754   if (res == 0) flags |= TME_M68K_FLAG_Z;
755 
756   /* store the flags: */
757   ic->tme_m68k_ireg_ccr = flags;
758   TME_M68K_INSN_OK;
759 }
760 
761 /* the rol function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_rol8)762 TME_M68K_INSN(tme_m68k_rol8)
763 {
764   unsigned int count;
765   tme_uint8_t res;
766   tme_uint8_t flags;
767 
768   /* get the count and operand: */
769   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
770   res = TME_M68K_INSN_OP1(tme_uint8_t);
771 
772   /* generate the X, V, and C flags assuming the count is zero: */
773   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
774 
775   /* if the count is nonzero, update the result and
776      generate the X, V, and C flags: */
777   if (count > 0) {
778     count &= (8 - 1);
779     res = (res << count) | (res >> (8 - count));
780     flags |= ((res & 1) * TME_M68K_FLAG_C);
781   }
782 
783   /* store the result: */
784   TME_M68K_INSN_OP1(tme_uint8_t) = res;
785 
786   /* generate the N flag.  we cast to tme_uint8_t as soon as we
787      know the bit we want is within the range of the type, to try
788      to affect the generated assembly: */
789   flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
790 
791   /* generate the Z flag: */
792   if (res == 0) flags |= TME_M68K_FLAG_Z;
793 
794   /* store the flags: */
795   ic->tme_m68k_ireg_ccr = flags;
796   TME_M68K_INSN_OK;
797 }
798 
799 /* the ror function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_ror8)800 TME_M68K_INSN(tme_m68k_ror8)
801 {
802   unsigned int count;
803   tme_uint8_t res;
804   tme_uint8_t flags;
805 
806   /* get the count and operand: */
807   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
808   res = TME_M68K_INSN_OP1(tme_uint8_t);
809 
810   /* generate the X, V, and C flags assuming the count is zero: */
811   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
812 
813   /* if the count is nonzero, update the result and
814      generate the X, V, and C flags: */
815   if (count > 0) {
816     count &= (8 - 1);
817     res = (res << (8 - count)) | (res >> count);
818     flags |= ((res >> (8 - 1)) * TME_M68K_FLAG_C);
819   }
820 
821   /* store the result: */
822   TME_M68K_INSN_OP1(tme_uint8_t) = res;
823 
824   /* generate the N flag.  we cast to tme_uint8_t as soon as we
825      know the bit we want is within the range of the type, to try
826      to affect the generated assembly: */
827   flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
828 
829   /* generate the Z flag: */
830   if (res == 0) flags |= TME_M68K_FLAG_Z;
831 
832   /* store the flags: */
833   ic->tme_m68k_ireg_ccr = flags;
834   TME_M68K_INSN_OK;
835 }
836 
837 /* the roxl function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_roxl8)838 TME_M68K_INSN(tme_m68k_roxl8)
839 {
840   unsigned int count;
841   tme_uint8_t xbit;
842   tme_uint8_t res;
843   tme_uint8_t flags;
844 
845   /* get the count and operand: */
846   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
847   res = TME_M68K_INSN_OP1(tme_uint8_t);
848 
849   /* generate the X, V, and C flags assuming the count is zero: */
850   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
851   xbit = (flags / TME_M68K_FLAG_X);
852   flags |= (xbit * TME_M68K_FLAG_C);
853 
854   /* if the count is nonzero, update the result and
855      generate the X, V, and C flags: */
856   if (count > 0) {
857     count %= (8 + 1);
858     flags = xbit;
859     if (count > 0) {
860       flags = (res >> (8 - count)) & 1;
861       if (8 > SHIFTMAX_INT8_T
862           && count == 8) {
863         res = 0 | (xbit << (8 - 1)) | (res >> ((8 + 1) - 8));
864       }
865       else if (8 > SHIFTMAX_INT8_T
866                && count == 1) {
867         res = (res << 1) | (xbit << (1 - 1)) | 0;
868       }
869       else {
870         res = (res << count) | (xbit << (count - 1)) | (res >> ((8 + 1) - count));
871       }
872     }
873     flags *= TME_M68K_FLAG_C;
874     flags |= (flags * TME_M68K_FLAG_X);
875   }
876 
877   /* store the result: */
878   TME_M68K_INSN_OP1(tme_uint8_t) = res;
879 
880   /* generate the N flag.  we cast to tme_uint8_t as soon as we
881      know the bit we want is within the range of the type, to try
882      to affect the generated assembly: */
883   flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
884 
885   /* generate the Z flag: */
886   if (res == 0) flags |= TME_M68K_FLAG_Z;
887 
888   /* store the flags: */
889   ic->tme_m68k_ireg_ccr = flags;
890   TME_M68K_INSN_OK;
891 }
892 
893 /* the roxr function on a 8-byte EA: */
TME_M68K_INSN(tme_m68k_roxr8)894 TME_M68K_INSN(tme_m68k_roxr8)
895 {
896   unsigned int count;
897   tme_uint8_t xbit;
898   tme_uint8_t res;
899   tme_uint8_t flags;
900 
901   /* get the count and operand: */
902   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
903   res = TME_M68K_INSN_OP1(tme_uint8_t);
904 
905   /* generate the X, V, and C flags assuming the count is zero: */
906   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
907   xbit = (flags / TME_M68K_FLAG_X);
908   flags |= (xbit * TME_M68K_FLAG_C);
909 
910   /* if the count is nonzero, update the result and
911      generate the X, V, and C flags: */
912   if (count > 0) {
913     count %= (8 + 1);
914     flags = xbit;
915     if (count > 0) {
916       flags = (res >> (count - 1)) & 1;
917       if (8 > SHIFTMAX_INT8_T
918           && count == 8) {
919         res = (res << ((8 + 1) - 8)) | (xbit << (8 - 8)) | 0;
920       }
921       else if (8 > SHIFTMAX_INT8_T
922                && count == 1) {
923         res = 0 | (xbit << (8 - 1)) | (res >> 1);
924       }
925       else {
926         res = (res << ((8 + 1) - count)) | (xbit << (8 - count)) | (res >> count);
927       }
928     }
929     flags *= TME_M68K_FLAG_C;
930     flags |= (flags * TME_M68K_FLAG_X);
931   }
932 
933   /* store the result: */
934   TME_M68K_INSN_OP1(tme_uint8_t) = res;
935 
936   /* generate the N flag.  we cast to tme_uint8_t as soon as we
937      know the bit we want is within the range of the type, to try
938      to affect the generated assembly: */
939   flags |= ((tme_uint8_t) (((tme_uint8_t) res) >> (8 - 1))) * TME_M68K_FLAG_N;
940 
941   /* generate the Z flag: */
942   if (res == 0) flags |= TME_M68K_FLAG_Z;
943 
944   /* store the flags: */
945   ic->tme_m68k_ireg_ccr = flags;
946   TME_M68K_INSN_OK;
947 }
948 
949 /* cas8: */
TME_M68K_INSN(tme_m68k_cas8)950 TME_M68K_INSN(tme_m68k_cas8)
951 {
952   struct tme_m68k_rmw rmw;
953   struct tme_m68k_tlb *tlb;
954   int ireg_dc, ireg_du;
955   tme_uint8_t value_dc, value_du, value_mem;
956 
957   /* start the read/modify/write cycle: */
958   rmw.tme_m68k_rmw_addresses[0] = ic->_tme_m68k_ea_address;
959   rmw.tme_m68k_rmw_address_count = 1;
960   rmw.tme_m68k_rmw_size = sizeof(tme_uint8_t);
961   if (tme_m68k_rmw_start(ic,
962                          &rmw)) {
963     TME_M68K_INSN_OK;
964   }
965 
966   /* get the compare and update registers: */
967   ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);
968   ireg_du = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 6, 3);
969 
970   /* if we can do the fast compare-and-exchange: */
971   if (!rmw.tme_m68k_rmw_slow_reads[0]) {
972 
973     /* get the compare and update values in big-endian byte order: */
974     value_dc = ic->tme_m68k_ireg_uint8(ireg_dc << 2);
975     value_du = ic->tme_m68k_ireg_uint8(ireg_du << 2);
976 
977     /* get this TLB entry: */
978     tlb = rmw.tme_m68k_rmw_tlbs[0];
979 
980     /* this TLB entry must allow fast reading and fast writing
981        to the same memory: */
982     assert (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF
983             && tlb->tme_m68k_tlb_emulator_off_write == tlb->tme_m68k_tlb_emulator_off_read);
984 
985     /* do the compare-and-exchange: */
986     value_mem =
987       tme_memory_atomic_cx8(((tme_shared tme_uint8_t *)
988                                    (tlb->tme_m68k_tlb_emulator_off_read
989                                     + ic->_tme_m68k_ea_address)),
990                                   value_dc,
991                                   value_du,
992                                   tlb->tme_m68k_tlb_bus_rwlock,
993                                   sizeof(tme_uint8_t));
994     ic->tme_m68k_ireg_memx8 = (value_mem);
995   }
996 
997   /* compare the compare operand to the effective address operand: */
998   tme_m68k_cmp8(ic, &ic->tme_m68k_ireg_uint8(ireg_dc << 2), &ic->tme_m68k_ireg_memx8);
999 
1000   /* if the comparison succeeded: */
1001   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
1002 
1003     /* write the update operand to the effective address operand: */
1004     ic->tme_m68k_ireg_memx8 = ic->tme_m68k_ireg_uint8(ireg_du << 2);
1005   }
1006 
1007   /* otherwise, the comparison failed: */
1008   else {
1009 
1010     /* write the effective address operand to the compare operand: */
1011     ic->tme_m68k_ireg_uint8(ireg_dc << 2) = ic->tme_m68k_ireg_memx8;
1012   }
1013 
1014   /* finish the read/modify/write cycle: */
1015   tme_m68k_rmw_finish(ic,
1016                       &rmw,
1017                       (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0);
1018   TME_M68K_INSN_OK;
1019 }
1020 
1021 /* moves8: */
TME_M68K_INSN(tme_m68k_moves8)1022 TME_M68K_INSN(tme_m68k_moves8)
1023 {
1024   int ireg;
1025   tme_uint8_t ireg_value;
1026   unsigned int ea_reg;
1027   unsigned int increment;
1028   TME_M68K_INSN_PRIV;
1029   TME_M68K_INSN_CANFAULT;
1030   ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);
1031 
1032   /* in case we're storing the same address register used in a
1033      postincrement or predecrement EA, save the current value
1034      of the register now: */
1035   ireg_value = ic->tme_m68k_ireg_uint8(ireg << 2);
1036 
1037   /* we have to handle postincrement and predecrement ourselves: */
1038   if (!TME_M68K_SEQUENCE_RESTARTING) {
1039     ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
1040     increment = TME_M68K_SIZE_8;
1041     if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) {
1042       increment = TME_M68K_SIZE_16;
1043     }
1044     switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) {
1045     case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break;
1046     case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break;
1047     default: break;
1048     }
1049   }
1050 
1051   if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {
1052     if (!TME_M68K_SEQUENCE_RESTARTING) {
1053       ic->tme_m68k_ireg_memx8 = ireg_value;
1054       ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc;
1055     }
1056     tme_m68k_write_memx8(ic);
1057   }
1058   else {
1059     if (!TME_M68K_SEQUENCE_RESTARTING) {
1060       ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc;
1061     }
1062     tme_m68k_read_memx8(ic);
1063     if (ireg >= TME_M68K_IREG_A0) {
1064       ic->tme_m68k_ireg_uint32(ireg) =
1065         TME_EXT_S8_U32((tme_int8_t) ic->tme_m68k_ireg_memx8);
1066     }
1067     else
1068       ic->tme_m68k_ireg_uint8(ireg << 2) = ic->tme_m68k_ireg_memx8;
1069   }
1070   TME_M68K_INSN_OK;
1071 }
1072 
1073 /* this does a 16-bit "add SRC, DST": */
TME_M68K_INSN(tme_m68k_add16)1074 TME_M68K_INSN(tme_m68k_add16)
1075 {
1076   tme_uint16_t res, op0, op1;
1077   tme_uint8_t flags;
1078 
1079   /* load the operand(s): */
1080   op0 = *((tme_uint16_t *) _op0);
1081   op1 = *((tme_uint16_t *) _op1);
1082 
1083   /* perform the operation: */
1084   res = op1 + op0;
1085 
1086   /* store the result: */
1087   *((tme_uint16_t *) _op1) = res;
1088 
1089   /* set the flags: */
1090   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1091   if (res == 0) flags |= TME_M68K_FLAG_Z;
1092   flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xffff) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V;
1093   if (op0 > (op1 ^ 0xffff)) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
1094   ic->tme_m68k_ireg_ccr = flags;
1095 
1096   TME_M68K_INSN_OK;
1097 }
1098 
1099 /* this does a 16-bit "sub SRC, DST": */
TME_M68K_INSN(tme_m68k_sub16)1100 TME_M68K_INSN(tme_m68k_sub16)
1101 {
1102   tme_uint16_t res, op0, op1;
1103   tme_uint8_t flags;
1104 
1105   /* load the operand(s): */
1106   op0 = *((tme_uint16_t *) _op0);
1107   op1 = *((tme_uint16_t *) _op1);
1108 
1109   /* perform the operation: */
1110   res = op1 - op0;
1111 
1112   /* store the result: */
1113   *((tme_uint16_t *) _op1) = res;
1114 
1115   /* set the flags: */
1116   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1117   if (res == 0) flags |= TME_M68K_FLAG_Z;
1118   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V;
1119   if (op0 > op1) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
1120   ic->tme_m68k_ireg_ccr = flags;
1121 
1122   TME_M68K_INSN_OK;
1123 }
1124 
1125 /* this does a 16-bit "cmp SRC, DST": */
TME_M68K_INSN(tme_m68k_cmp16)1126 TME_M68K_INSN(tme_m68k_cmp16)
1127 {
1128   tme_uint16_t res, op0, op1;
1129   tme_uint8_t flags;
1130 
1131   /* load the operand(s): */
1132   op0 = *((tme_uint16_t *) _op0);
1133   op1 = *((tme_uint16_t *) _op1);
1134 
1135   /* perform the operation: */
1136   res = op1 - op0;
1137 
1138   /* set the flags: */
1139   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1140   if (res == 0) flags |= TME_M68K_FLAG_Z;
1141   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V;
1142   if (op0 > op1) flags |= TME_M68K_FLAG_C;
1143   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1144   ic->tme_m68k_ireg_ccr = flags;
1145 
1146   TME_M68K_INSN_OK;
1147 }
1148 
1149 /* this does a 16-bit "neg DST": */
TME_M68K_INSN(tme_m68k_neg16)1150 TME_M68K_INSN(tme_m68k_neg16)
1151 {
1152   tme_uint16_t res, op1;
1153   tme_uint8_t flags;
1154 
1155   /* load the operand(s): */
1156   op1 = *((tme_uint16_t *) _op1);
1157 
1158   /* perform the operation: */
1159   res = 0 - op1;
1160 
1161   /* store the result: */
1162   *((tme_uint16_t *) _op1) = res;
1163 
1164   /* set the flags: */
1165   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1166   if (res == 0) flags |= TME_M68K_FLAG_Z;
1167   flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V;
1168   if (op1 > 0) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
1169   ic->tme_m68k_ireg_ccr = flags;
1170 
1171   TME_M68K_INSN_OK;
1172 }
1173 
1174 /* this does a 16-bit "or SRC, DST": */
TME_M68K_INSN(tme_m68k_or16)1175 TME_M68K_INSN(tme_m68k_or16)
1176 {
1177   tme_uint16_t res, op0, op1;
1178   tme_uint8_t flags;
1179 
1180   /* load the operand(s): */
1181   op0 = *((tme_uint16_t *) _op0);
1182   op1 = *((tme_uint16_t *) _op1);
1183 
1184   /* perform the operation: */
1185   res = op1 | op0;
1186 
1187   /* store the result: */
1188   *((tme_uint16_t *) _op1) = res;
1189 
1190   /* set the flags: */
1191   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1192   if (res == 0) flags |= TME_M68K_FLAG_Z;
1193   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1194   ic->tme_m68k_ireg_ccr = flags;
1195 
1196   TME_M68K_INSN_OK;
1197 }
1198 
1199 /* this does a 16-bit "and SRC, DST": */
TME_M68K_INSN(tme_m68k_and16)1200 TME_M68K_INSN(tme_m68k_and16)
1201 {
1202   tme_uint16_t res, op0, op1;
1203   tme_uint8_t flags;
1204 
1205   /* load the operand(s): */
1206   op0 = *((tme_uint16_t *) _op0);
1207   op1 = *((tme_uint16_t *) _op1);
1208 
1209   /* perform the operation: */
1210   res = op1 & op0;
1211 
1212   /* store the result: */
1213   *((tme_uint16_t *) _op1) = res;
1214 
1215   /* set the flags: */
1216   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1217   if (res == 0) flags |= TME_M68K_FLAG_Z;
1218   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1219   ic->tme_m68k_ireg_ccr = flags;
1220 
1221   TME_M68K_INSN_OK;
1222 }
1223 
1224 /* this does a 16-bit "eor SRC, DST": */
TME_M68K_INSN(tme_m68k_eor16)1225 TME_M68K_INSN(tme_m68k_eor16)
1226 {
1227   tme_uint16_t res, op0, op1;
1228   tme_uint8_t flags;
1229 
1230   /* load the operand(s): */
1231   op0 = *((tme_uint16_t *) _op0);
1232   op1 = *((tme_uint16_t *) _op1);
1233 
1234   /* perform the operation: */
1235   res = op1 ^ op0;
1236 
1237   /* store the result: */
1238   *((tme_uint16_t *) _op1) = res;
1239 
1240   /* set the flags: */
1241   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1242   if (res == 0) flags |= TME_M68K_FLAG_Z;
1243   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1244   ic->tme_m68k_ireg_ccr = flags;
1245 
1246   TME_M68K_INSN_OK;
1247 }
1248 
1249 /* this does a 16-bit "not DST": */
TME_M68K_INSN(tme_m68k_not16)1250 TME_M68K_INSN(tme_m68k_not16)
1251 {
1252   tme_uint16_t res, op1;
1253   tme_uint8_t flags;
1254 
1255   /* load the operand(s): */
1256   op1 = *((tme_uint16_t *) _op1);
1257 
1258   /* perform the operation: */
1259   res = ~ op1;
1260 
1261   /* store the result: */
1262   *((tme_uint16_t *) _op1) = res;
1263 
1264   /* set the flags: */
1265   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1266   if (res == 0) flags |= TME_M68K_FLAG_Z;
1267   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1268   ic->tme_m68k_ireg_ccr = flags;
1269 
1270   TME_M68K_INSN_OK;
1271 }
1272 
1273 /* this does a 16-bit "tst DST": */
TME_M68K_INSN(tme_m68k_tst16)1274 TME_M68K_INSN(tme_m68k_tst16)
1275 {
1276   tme_uint16_t res, op1;
1277   tme_uint8_t flags;
1278 
1279   /* load the operand(s): */
1280   op1 = *((tme_uint16_t *) _op1);
1281 
1282   /* perform the operation: */
1283   res = op1;
1284 
1285   /* set the flags: */
1286   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1287   if (res == 0) flags |= TME_M68K_FLAG_Z;
1288   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1289   ic->tme_m68k_ireg_ccr = flags;
1290 
1291   TME_M68K_INSN_OK;
1292 }
1293 
1294 /* this does a 16-bit "move DST": */
TME_M68K_INSN(tme_m68k_move16)1295 TME_M68K_INSN(tme_m68k_move16)
1296 {
1297   tme_uint16_t res, op1;
1298   tme_uint8_t flags;
1299 
1300   /* load the operand(s): */
1301   op1 = *((tme_uint16_t *) _op1);
1302 
1303   /* perform the operation: */
1304   res = op1;
1305 
1306   /* store the result: */
1307   *((tme_uint16_t *) _op0) = res;
1308 
1309   /* set the flags: */
1310   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1311   if (res == 0) flags |= TME_M68K_FLAG_Z;
1312   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1313   ic->tme_m68k_ireg_ccr = flags;
1314 
1315   TME_M68K_INSN_OK;
1316 }
1317 
1318 /* this does a 16-bit "clr DST": */
TME_M68K_INSN(tme_m68k_clr16)1319 TME_M68K_INSN(tme_m68k_clr16)
1320 {
1321   tme_uint16_t res;
1322   tme_uint8_t flags;
1323 
1324   /* load the operand(s): */
1325 
1326   /* perform the operation: */
1327   res = 0;
1328 
1329   /* store the result: */
1330   *((tme_uint16_t *) _op1) = res;
1331 
1332   /* set the flags: */
1333   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1334   if (res == 0) flags |= TME_M68K_FLAG_Z;
1335   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1336   ic->tme_m68k_ireg_ccr = flags;
1337 
1338   TME_M68K_INSN_OK;
1339 }
1340 
1341 /* this does a 16-bit "cmpa SRC, DST": */
TME_M68K_INSN(tme_m68k_cmpa16)1342 TME_M68K_INSN(tme_m68k_cmpa16)
1343 {
1344   tme_uint32_t res, op0, op1;
1345   tme_uint8_t flags;
1346 
1347   /* load the operand(s): */
1348   op0 = (tme_uint32_t) ((tme_int32_t) *((tme_int16_t *) _op0));
1349   op1 = *((tme_uint32_t *) _op1);
1350 
1351   /* perform the operation: */
1352   res = op1 - op0;
1353 
1354   /* set the flags: */
1355   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
1356   if (res == 0) flags |= TME_M68K_FLAG_Z;
1357   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V;
1358   if (op0 > op1) flags |= TME_M68K_FLAG_C;
1359   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1360   ic->tme_m68k_ireg_ccr = flags;
1361 
1362   TME_M68K_INSN_OK;
1363 }
1364 
1365 /* this does a 16-bit "negx DST": */
TME_M68K_INSN(tme_m68k_negx16)1366 TME_M68K_INSN(tme_m68k_negx16)
1367 {
1368   tme_uint16_t res, op1;
1369   tme_uint8_t flags;
1370 
1371   /* load the operand(s): */
1372   op1 = *((tme_uint16_t *) _op1);
1373 
1374   /* perform the operation: */
1375   res = 0 - op1 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1);
1376 
1377   /* store the result: */
1378   *((tme_uint16_t *) _op1) = res;
1379 
1380   /* set the flags: */
1381   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1382   if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);
1383   flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V;
1384   if (op1 > 0 || (op1 == 0 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
1385   ic->tme_m68k_ireg_ccr = flags;
1386 
1387   TME_M68K_INSN_OK;
1388 }
1389 
1390 /* this does a 16-bit "addx SRC, DST": */
TME_M68K_INSN(tme_m68k_addx16)1391 TME_M68K_INSN(tme_m68k_addx16)
1392 {
1393   tme_uint16_t res, op0, op1;
1394   tme_uint8_t flags;
1395 
1396   /* load the operand(s): */
1397   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
1398   int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
1399   int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
1400   tme_uint32_t ireg_src_adjust = sizeof(tme_uint16_t);
1401   tme_uint32_t ireg_dst_adjust = sizeof(tme_uint16_t);
1402   tme_uint16_t memory;
1403 
1404   memory = (TME_M68K_INSN_OPCODE & TME_BIT(3));
1405   if (memory) {
1406     TME_M68K_INSN_CANFAULT;
1407     if (!TME_M68K_SEQUENCE_RESTARTING) {
1408       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust;
1409       ic->_tme_m68k_ea_function_code = function_code;
1410       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);
1411     }
1412     tme_m68k_read_mem16(ic, TME_M68K_IREG_MEMY16);
1413     if (!TME_M68K_SEQUENCE_RESTARTING) {
1414       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust;
1415       ic->_tme_m68k_ea_function_code = function_code;
1416       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
1417     }
1418     tme_m68k_read_memx16(ic);
1419     op1 = ic->tme_m68k_ireg_memx16;
1420     op0 = ic->tme_m68k_ireg_memy16;
1421   }
1422   else {
1423     op0 = ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_src) << 1);
1424     op1 = ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_dst) << 1);
1425   }
1426 
1427   /* perform the operation: */
1428   res = op1 + op0 + ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1);
1429 
1430   /* store the result: */
1431   if (memory) {
1432     if (!TME_M68K_SEQUENCE_RESTARTING) {
1433       ic->tme_m68k_ireg_memx16 = res;
1434       ic->_tme_m68k_ea_function_code = function_code;
1435       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
1436     }
1437     tme_m68k_write_memx16(ic);
1438   }
1439   else {
1440     ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_dst) << 1) = res;
1441   }
1442 
1443   /* set the flags: */
1444   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1445   if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);
1446   flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xffff) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V;
1447   if (op0 > (op1 ^ 0xffff) || (op0 == (op1 ^ 0xffff) && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
1448   ic->tme_m68k_ireg_ccr = flags;
1449 
1450   TME_M68K_INSN_OK;
1451 }
1452 
1453 /* this does a 16-bit "subx SRC, DST": */
TME_M68K_INSN(tme_m68k_subx16)1454 TME_M68K_INSN(tme_m68k_subx16)
1455 {
1456   tme_uint16_t res, op0, op1;
1457   tme_uint8_t flags;
1458 
1459   /* load the operand(s): */
1460   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
1461   int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
1462   int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
1463   tme_uint32_t ireg_src_adjust = sizeof(tme_uint16_t);
1464   tme_uint32_t ireg_dst_adjust = sizeof(tme_uint16_t);
1465   tme_uint16_t memory;
1466 
1467   memory = (TME_M68K_INSN_OPCODE & TME_BIT(3));
1468   if (memory) {
1469     TME_M68K_INSN_CANFAULT;
1470     if (!TME_M68K_SEQUENCE_RESTARTING) {
1471       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust;
1472       ic->_tme_m68k_ea_function_code = function_code;
1473       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);
1474     }
1475     tme_m68k_read_mem16(ic, TME_M68K_IREG_MEMY16);
1476     if (!TME_M68K_SEQUENCE_RESTARTING) {
1477       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust;
1478       ic->_tme_m68k_ea_function_code = function_code;
1479       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
1480     }
1481     tme_m68k_read_memx16(ic);
1482     op1 = ic->tme_m68k_ireg_memx16;
1483     op0 = ic->tme_m68k_ireg_memy16;
1484   }
1485   else {
1486     op0 = ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_src) << 1);
1487     op1 = ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_dst) << 1);
1488   }
1489 
1490   /* perform the operation: */
1491   res = op1 - op0 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1);
1492 
1493   /* store the result: */
1494   if (memory) {
1495     if (!TME_M68K_SEQUENCE_RESTARTING) {
1496       ic->tme_m68k_ireg_memx16 = res;
1497       ic->_tme_m68k_ea_function_code = function_code;
1498       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
1499     }
1500     tme_m68k_write_memx16(ic);
1501   }
1502   else {
1503     ic->tme_m68k_ireg_uint16((TME_M68K_IREG_D0 + ireg_dst) << 1) = res;
1504   }
1505 
1506   /* set the flags: */
1507   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1508   if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);
1509   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V;
1510   if (op0 > op1 || (op0 == op1 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
1511   ic->tme_m68k_ireg_ccr = flags;
1512 
1513   TME_M68K_INSN_OK;
1514 }
1515 
1516 /* this does a 16-bit "cmpm SRC, DST": */
TME_M68K_INSN(tme_m68k_cmpm16)1517 TME_M68K_INSN(tme_m68k_cmpm16)
1518 {
1519   tme_uint16_t res, op0, op1;
1520   tme_uint8_t flags;
1521 
1522   /* load the operand(s): */
1523   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
1524   int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
1525   int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
1526   tme_uint32_t ireg_src_adjust = sizeof(tme_uint16_t);
1527   tme_uint32_t ireg_dst_adjust = sizeof(tme_uint16_t);
1528 
1529   TME_M68K_INSN_CANFAULT;
1530 
1531   if (!TME_M68K_SEQUENCE_RESTARTING) {
1532     ic->_tme_m68k_ea_function_code = function_code;
1533     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);
1534     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) += ireg_src_adjust;
1535   }
1536   tme_m68k_read_mem16(ic, TME_M68K_IREG_MEMY16);
1537   if (!TME_M68K_SEQUENCE_RESTARTING) {
1538     ic->_tme_m68k_ea_function_code = function_code;
1539     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
1540     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust;
1541   }
1542   tme_m68k_read_memx16(ic);
1543   op1 = ic->tme_m68k_ireg_memx16;
1544   op0 = ic->tme_m68k_ireg_memy16;
1545 
1546   /* perform the operation: */
1547   res = op1 - op0;
1548 
1549   /* set the flags: */
1550   flags = ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1551   if (res == 0) flags |= TME_M68K_FLAG_Z;
1552   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (16 - 1))) * TME_M68K_FLAG_V;
1553   if (op0 > op1) flags |= TME_M68K_FLAG_C;
1554   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
1555   ic->tme_m68k_ireg_ccr = flags;
1556 
1557   TME_M68K_INSN_OK;
1558 }
1559 
1560 /* a move of an address register to a predecrement or
1561    postincrement EA with that same address register, must
1562    store the original value of the address register.  since the
1563    predecrement and postincrement code in the executer updates
1564    the address register before the move has happened, we wrap
1565    the normal move function in this one, that gives an op1
1566    argument that is the original value of the address register: */
TME_M68K_INSN(tme_m68k_move_srpd16)1567 TME_M68K_INSN(tme_m68k_move_srpd16)
1568 {
1569   /* NB: both this function and tme_m68k_move16()
1570      get the source operand as _op1, and the destination
1571      operand as _op0: */
1572   if (!TME_M68K_SEQUENCE_RESTARTING) {
1573     *((tme_uint16_t *) _op0)
1574       = (*((tme_uint16_t *) _op1)
1575          + sizeof(tme_uint16_t));
1576   }
1577   tme_m68k_move16(ic, _op0, _op0);
1578 }
1579 
1580 /* a move of an address register to a predecrement or
1581    postincrement EA with that same address register, must
1582    store the original value of the address register.  since the
1583    predecrement and postincrement code in the executer updates
1584    the address register before the move has happened, we wrap
1585    the normal move function in this one, that gives an op1
1586    argument that is the original value of the address register: */
TME_M68K_INSN(tme_m68k_move_srpi16)1587 TME_M68K_INSN(tme_m68k_move_srpi16)
1588 {
1589   /* NB: both this function and tme_m68k_move16()
1590      get the source operand as _op1, and the destination
1591      operand as _op0: */
1592   if (!TME_M68K_SEQUENCE_RESTARTING) {
1593     *((tme_uint16_t *) _op0)
1594       = (*((tme_uint16_t *) _op1)
1595          - sizeof(tme_uint16_t));
1596   }
1597   tme_m68k_move16(ic, _op0, _op0);
1598 }
1599 
1600 /* the suba function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_suba16)1601 TME_M68K_INSN(tme_m68k_suba16)
1602 {
1603   *((tme_int32_t *) _op1) -= *((tme_int16_t *) _op0);
1604   TME_M68K_INSN_OK;
1605 }
1606 
1607 /* the adda function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_adda16)1608 TME_M68K_INSN(tme_m68k_adda16)
1609 {
1610   *((tme_int32_t *) _op1) += *((tme_int16_t *) _op0);
1611   TME_M68K_INSN_OK;
1612 }
1613 
1614 /* the movea function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_movea16)1615 TME_M68K_INSN(tme_m68k_movea16)
1616 {
1617   *((tme_int32_t *) _op0) = *((tme_int16_t *) _op1);
1618   TME_M68K_INSN_OK;
1619 }
1620 
1621 /* the asl function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_asl16)1622 TME_M68K_INSN(tme_m68k_asl16)
1623 {
1624   unsigned int count;
1625   tme_uint16_t sign_bits, sign_bits_mask;
1626   tme_uint16_t res;
1627   tme_uint8_t flags;
1628 
1629   /* get the count and operand: */
1630   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
1631   res = TME_M68K_INSN_OP1(tme_uint16_t);
1632 
1633   /* generate the X, V, and C flags assuming the count is zero: */
1634   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
1635 
1636   /* if the count is nonzero, update the result and
1637      generate the X, V, and C flags: */
1638   if (count > 0) {
1639 
1640     /* we need to see how the sign of the result will change during
1641        shifting in order to generate V.
1642 
1643        in general, the idea is to get all of the bits that will ever
1644        appear in the sign position into sign_bits, with a mask in
1645        sign_bits_mask.  if (sign_bits & sign_bits_mask) is zero or
1646        sign_bits_mask, clear V, else set V.
1647 
1648        start by loading the operand into sign_bits and setting
1649        sign_bits_mask to all-bits-one.
1650 
1651        if the shift count is exactly 16 - 1, then all of the bits
1652        of the operand will appear in the sign position.
1653 
1654        if the shift count is less than 16 - 1, then some of the
1655        less significant bits of the operand will never appear in the
1656        sign position, so we can shift sign_bits_mask to ignore them.
1657 
1658        if the shift count is greater than 16 - 1, then all of the
1659        bits in the operand, plus at least one zero bit, will appear in
1660        the sign position.  the only way that the sign bit will never
1661        change during the shift is if the operand was zero to begin with.
1662        without any changes to sign_bits or sign_bits_mask, the final
1663        test will always work, except when sign_bits is all-bits-one.
1664        the magic below clears the least-significant bit of sign_bits
1665        iff sign_bits is all-bits-one: */
1666     sign_bits = res;
1667     if (63 > SHIFTMAX_INT16_T
1668         && count > 16) {
1669       res = 0;
1670     }
1671     res <<= (count - 1);
1672     flags = (res >> (16 - 1));
1673     flags *= TME_M68K_FLAG_C;
1674     flags |= (flags * TME_M68K_FLAG_X);
1675     res <<= 1;
1676     sign_bits_mask = (tme_uint16_t) -1;
1677     if (count != 16 - 1) {
1678       if (count < 16) {
1679         sign_bits_mask <<= ((16 - 1) - count);
1680       }
1681       else {
1682         sign_bits ^= !(sign_bits + 1);
1683       }
1684     }
1685     sign_bits &= sign_bits_mask;
1686     if (sign_bits != 0 && sign_bits != sign_bits_mask) {
1687       flags |= TME_M68K_FLAG_V;
1688     }
1689   }
1690 
1691   /* store the result: */
1692   TME_M68K_INSN_OP1(tme_uint16_t) = res;
1693 
1694   /* generate the N flag.  we cast to tme_uint8_t as soon as we
1695      know the bit we want is within the range of the type, to try
1696      to affect the generated assembly: */
1697   flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1698 
1699   /* generate the Z flag: */
1700   if (res == 0) flags |= TME_M68K_FLAG_Z;
1701 
1702   /* store the flags: */
1703   ic->tme_m68k_ireg_ccr = flags;
1704   TME_M68K_INSN_OK;
1705 }
1706 
1707 /* the asr function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_asr16)1708 TME_M68K_INSN(tme_m68k_asr16)
1709 {
1710   unsigned int count;
1711   tme_int16_t res;
1712   tme_uint8_t flags;
1713 
1714   /* get the count and operand: */
1715   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
1716   res = TME_M68K_INSN_OP1(tme_int16_t);
1717 
1718   /* generate the X, V, and C flags assuming the count is zero: */
1719   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
1720 
1721   /* if the count is nonzero, update the result and
1722      generate the X, V, and C flags: */
1723   if (count > 0) {
1724     if (63 > SHIFTMAX_INT16_T
1725         && count > 16) {
1726       res = 0 - (res < 0);
1727     }
1728 #ifdef SHIFTSIGNED_INT16_T
1729     res >>= (count - 1);
1730 #else  /* !SHIFTSIGNED_INT16_T */
1731     for (; --count > 0; ) {
1732       res = (res & ~((tme_int16_t) 1)) / 2;
1733     }
1734 #endif /* !SHIFTSIGNED_INT16_T */
1735     flags = (res & 1);
1736     flags *= TME_M68K_FLAG_C;
1737     flags |= (flags * TME_M68K_FLAG_X);
1738 #ifdef SHIFTSIGNED_INT16_T
1739     res >>= 1;
1740 #else  /* !SHIFTSIGNED_INT16_T */
1741     res = (res & ~((tme_int16_t) 1)) / 2;
1742 #endif /* !SHIFTSIGNED_INT16_T */
1743   }
1744 
1745   /* store the result: */
1746   TME_M68K_INSN_OP1(tme_int16_t) = res;
1747 
1748   /* generate the N flag.  we cast to tme_uint8_t as soon as we
1749      know the bit we want is within the range of the type, to try
1750      to affect the generated assembly: */
1751   flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1752 
1753   /* generate the Z flag: */
1754   if (res == 0) flags |= TME_M68K_FLAG_Z;
1755 
1756   /* store the flags: */
1757   ic->tme_m68k_ireg_ccr = flags;
1758   TME_M68K_INSN_OK;
1759 }
1760 
1761 /* the lsl function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_lsl16)1762 TME_M68K_INSN(tme_m68k_lsl16)
1763 {
1764   unsigned int count;
1765   tme_uint16_t res;
1766   tme_uint8_t flags;
1767 
1768   /* get the count and operand: */
1769   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
1770   res = TME_M68K_INSN_OP1(tme_uint16_t);
1771 
1772   /* generate the X, V, and C flags assuming the count is zero: */
1773   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
1774 
1775   /* if the count is nonzero, update the result and
1776      generate the X, V, and C flags: */
1777   if (count > 0) {
1778     if (63 > SHIFTMAX_INT16_T
1779         && count > 16) {
1780       res = 0;
1781     }
1782     res <<= (count - 1);
1783     flags = (res >> (16 - 1));
1784     flags *= TME_M68K_FLAG_C;
1785     flags |= (flags * TME_M68K_FLAG_X);
1786     res <<= 1;
1787   }
1788 
1789   /* store the result: */
1790   TME_M68K_INSN_OP1(tme_uint16_t) = res;
1791 
1792   /* generate the N flag.  we cast to tme_uint8_t as soon as we
1793      know the bit we want is within the range of the type, to try
1794      to affect the generated assembly: */
1795   flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1796 
1797   /* generate the Z flag: */
1798   if (res == 0) flags |= TME_M68K_FLAG_Z;
1799 
1800   /* store the flags: */
1801   ic->tme_m68k_ireg_ccr = flags;
1802   TME_M68K_INSN_OK;
1803 }
1804 
1805 /* the lsr function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_lsr16)1806 TME_M68K_INSN(tme_m68k_lsr16)
1807 {
1808   unsigned int count;
1809   tme_uint16_t res;
1810   tme_uint8_t flags;
1811 
1812   /* get the count and operand: */
1813   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
1814   res = TME_M68K_INSN_OP1(tme_uint16_t);
1815 
1816   /* generate the X, V, and C flags assuming the count is zero: */
1817   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
1818 
1819   /* if the count is nonzero, update the result and
1820      generate the X, V, and C flags: */
1821   if (count > 0) {
1822     if (63 > SHIFTMAX_INT16_T
1823         && count > 16) {
1824       res = 0;
1825     }
1826     res >>= (count - 1);
1827     flags = (res & 1);
1828     flags *= TME_M68K_FLAG_C;
1829     flags |= (flags * TME_M68K_FLAG_X);
1830     res >>= 1;
1831   }
1832 
1833   /* store the result: */
1834   TME_M68K_INSN_OP1(tme_uint16_t) = res;
1835 
1836   /* generate the N flag.  we cast to tme_uint8_t as soon as we
1837      know the bit we want is within the range of the type, to try
1838      to affect the generated assembly: */
1839   flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1840 
1841   /* generate the Z flag: */
1842   if (res == 0) flags |= TME_M68K_FLAG_Z;
1843 
1844   /* store the flags: */
1845   ic->tme_m68k_ireg_ccr = flags;
1846   TME_M68K_INSN_OK;
1847 }
1848 
1849 /* the rol function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_rol16)1850 TME_M68K_INSN(tme_m68k_rol16)
1851 {
1852   unsigned int count;
1853   tme_uint16_t res;
1854   tme_uint8_t flags;
1855 
1856   /* get the count and operand: */
1857   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
1858   res = TME_M68K_INSN_OP1(tme_uint16_t);
1859 
1860   /* generate the X, V, and C flags assuming the count is zero: */
1861   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
1862 
1863   /* if the count is nonzero, update the result and
1864      generate the X, V, and C flags: */
1865   if (count > 0) {
1866     count &= (16 - 1);
1867     res = (res << count) | (res >> (16 - count));
1868     flags |= ((res & 1) * TME_M68K_FLAG_C);
1869   }
1870 
1871   /* store the result: */
1872   TME_M68K_INSN_OP1(tme_uint16_t) = res;
1873 
1874   /* generate the N flag.  we cast to tme_uint8_t as soon as we
1875      know the bit we want is within the range of the type, to try
1876      to affect the generated assembly: */
1877   flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1878 
1879   /* generate the Z flag: */
1880   if (res == 0) flags |= TME_M68K_FLAG_Z;
1881 
1882   /* store the flags: */
1883   ic->tme_m68k_ireg_ccr = flags;
1884   TME_M68K_INSN_OK;
1885 }
1886 
1887 /* the ror function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_ror16)1888 TME_M68K_INSN(tme_m68k_ror16)
1889 {
1890   unsigned int count;
1891   tme_uint16_t res;
1892   tme_uint8_t flags;
1893 
1894   /* get the count and operand: */
1895   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
1896   res = TME_M68K_INSN_OP1(tme_uint16_t);
1897 
1898   /* generate the X, V, and C flags assuming the count is zero: */
1899   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
1900 
1901   /* if the count is nonzero, update the result and
1902      generate the X, V, and C flags: */
1903   if (count > 0) {
1904     count &= (16 - 1);
1905     res = (res << (16 - count)) | (res >> count);
1906     flags |= ((res >> (16 - 1)) * TME_M68K_FLAG_C);
1907   }
1908 
1909   /* store the result: */
1910   TME_M68K_INSN_OP1(tme_uint16_t) = res;
1911 
1912   /* generate the N flag.  we cast to tme_uint8_t as soon as we
1913      know the bit we want is within the range of the type, to try
1914      to affect the generated assembly: */
1915   flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1916 
1917   /* generate the Z flag: */
1918   if (res == 0) flags |= TME_M68K_FLAG_Z;
1919 
1920   /* store the flags: */
1921   ic->tme_m68k_ireg_ccr = flags;
1922   TME_M68K_INSN_OK;
1923 }
1924 
1925 /* the roxl function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_roxl16)1926 TME_M68K_INSN(tme_m68k_roxl16)
1927 {
1928   unsigned int count;
1929   tme_uint8_t xbit;
1930   tme_uint16_t res;
1931   tme_uint8_t flags;
1932 
1933   /* get the count and operand: */
1934   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
1935   res = TME_M68K_INSN_OP1(tme_uint16_t);
1936 
1937   /* generate the X, V, and C flags assuming the count is zero: */
1938   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
1939   xbit = (flags / TME_M68K_FLAG_X);
1940   flags |= (xbit * TME_M68K_FLAG_C);
1941 
1942   /* if the count is nonzero, update the result and
1943      generate the X, V, and C flags: */
1944   if (count > 0) {
1945     count %= (16 + 1);
1946     flags = xbit;
1947     if (count > 0) {
1948       flags = (res >> (16 - count)) & 1;
1949       if (16 > SHIFTMAX_INT16_T
1950           && count == 16) {
1951         res = 0 | (xbit << (16 - 1)) | (res >> ((16 + 1) - 16));
1952       }
1953       else if (16 > SHIFTMAX_INT16_T
1954                && count == 1) {
1955         res = (res << 1) | (xbit << (1 - 1)) | 0;
1956       }
1957       else {
1958         res = (res << count) | (xbit << (count - 1)) | (res >> ((16 + 1) - count));
1959       }
1960     }
1961     flags *= TME_M68K_FLAG_C;
1962     flags |= (flags * TME_M68K_FLAG_X);
1963   }
1964 
1965   /* store the result: */
1966   TME_M68K_INSN_OP1(tme_uint16_t) = res;
1967 
1968   /* generate the N flag.  we cast to tme_uint8_t as soon as we
1969      know the bit we want is within the range of the type, to try
1970      to affect the generated assembly: */
1971   flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
1972 
1973   /* generate the Z flag: */
1974   if (res == 0) flags |= TME_M68K_FLAG_Z;
1975 
1976   /* store the flags: */
1977   ic->tme_m68k_ireg_ccr = flags;
1978   TME_M68K_INSN_OK;
1979 }
1980 
1981 /* the roxr function on a 16-byte EA: */
TME_M68K_INSN(tme_m68k_roxr16)1982 TME_M68K_INSN(tme_m68k_roxr16)
1983 {
1984   unsigned int count;
1985   tme_uint8_t xbit;
1986   tme_uint16_t res;
1987   tme_uint8_t flags;
1988 
1989   /* get the count and operand: */
1990   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
1991   res = TME_M68K_INSN_OP1(tme_uint16_t);
1992 
1993   /* generate the X, V, and C flags assuming the count is zero: */
1994   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
1995   xbit = (flags / TME_M68K_FLAG_X);
1996   flags |= (xbit * TME_M68K_FLAG_C);
1997 
1998   /* if the count is nonzero, update the result and
1999      generate the X, V, and C flags: */
2000   if (count > 0) {
2001     count %= (16 + 1);
2002     flags = xbit;
2003     if (count > 0) {
2004       flags = (res >> (count - 1)) & 1;
2005       if (16 > SHIFTMAX_INT16_T
2006           && count == 16) {
2007         res = (res << ((16 + 1) - 16)) | (xbit << (16 - 16)) | 0;
2008       }
2009       else if (16 > SHIFTMAX_INT16_T
2010                && count == 1) {
2011         res = 0 | (xbit << (16 - 1)) | (res >> 1);
2012       }
2013       else {
2014         res = (res << ((16 + 1) - count)) | (xbit << (16 - count)) | (res >> count);
2015       }
2016     }
2017     flags *= TME_M68K_FLAG_C;
2018     flags |= (flags * TME_M68K_FLAG_X);
2019   }
2020 
2021   /* store the result: */
2022   TME_M68K_INSN_OP1(tme_uint16_t) = res;
2023 
2024   /* generate the N flag.  we cast to tme_uint8_t as soon as we
2025      know the bit we want is within the range of the type, to try
2026      to affect the generated assembly: */
2027   flags |= ((tme_uint8_t) (((tme_uint16_t) res) >> (16 - 1))) * TME_M68K_FLAG_N;
2028 
2029   /* generate the Z flag: */
2030   if (res == 0) flags |= TME_M68K_FLAG_Z;
2031 
2032   /* store the flags: */
2033   ic->tme_m68k_ireg_ccr = flags;
2034   TME_M68K_INSN_OK;
2035 }
2036 
2037 /* the movep_rm function on a 16-bit dreg: */
TME_M68K_INSN(tme_m68k_movep_rm16)2038 TME_M68K_INSN(tme_m68k_movep_rm16)
2039 {
2040   unsigned int function_code;
2041   tme_uint32_t linear_address;
2042   tme_uint16_t value;
2043   int dreg;
2044 
2045   TME_M68K_INSN_CANFAULT;
2046 
2047   function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
2048   linear_address = TME_M68K_INSN_OP1(tme_uint32_t);
2049   linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP);
2050   dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
2051   value = ic->tme_m68k_ireg_uint16(dreg << 1);
2052   if (!TME_M68K_SEQUENCE_RESTARTING) {
2053     ic->_tme_m68k_ea_function_code = function_code;
2054     ic->_tme_m68k_ea_address = linear_address;
2055     ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 8, 8);
2056   }
2057   tme_m68k_write_memx8(ic);
2058   linear_address += 2;
2059   if (!TME_M68K_SEQUENCE_RESTARTING) {
2060     ic->_tme_m68k_ea_function_code = function_code;
2061     ic->_tme_m68k_ea_address = linear_address;
2062     ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 0, 8);
2063   }
2064   tme_m68k_write_memx8(ic);
2065   linear_address += 2;
2066   TME_M68K_INSN_OK;
2067 }
2068 
2069 /* the movem_rm function on 16-bit registers: */
TME_M68K_INSN(tme_m68k_movem_rm16)2070 TME_M68K_INSN(tme_m68k_movem_rm16)
2071 {
2072   int ireg, direction;
2073   tme_uint16_t mask, bit;
2074   unsigned int ea_mode;
2075   tme_uint32_t addend;
2076   tme_uint32_t total_size;
2077   /* get the register mask, and figure out the total size
2078      of the transfer: */
2079   mask = TME_M68K_INSN_SPECOP;
2080   total_size = 0;
2081   if (mask != 0) {
2082     TME_M68K_INSN_CANFAULT;
2083     bit = mask;
2084     do {
2085       total_size += sizeof(tme_uint16_t);
2086       bit &= (bit - 1);
2087     } while (bit != 0);
2088   }
2089 
2090   /* figure out what direction to move in, and where to start from: */
2091   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
2092   direction = 1;
2093   ireg = TME_M68K_IREG_D0;
2094   if (ea_mode == 4) {
2095     direction = -1;
2096     ireg = TME_M68K_IREG_A7;
2097     if (!TME_M68K_SEQUENCE_RESTARTING) {
2098 
2099       /* "For the MC68020, MC68030, MC68040, and CPU32, if
2100          the addressing register is also moved to memory, the
2101          value written is the initial register value decremented
2102          by the size of the operation. The MC68000 and MC68010
2103          write the initial register value (not decremented)." */
2104       if (ic->tme_m68k_type >= TME_M68K_M68020) {
2105         ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
2106                                  + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
2107           = (ic->_tme_m68k_ea_address - total_size);
2108       }
2109 
2110       /* predecrement the effective address for the first transfer: */
2111       ic->_tme_m68k_ea_address -= sizeof(tme_uint16_t);
2112     }
2113   }
2114   addend = (tme_uint32_t) (direction * sizeof(tme_uint16_t));
2115 
2116   /* do the transfer: */
2117   for (bit = 1; bit != 0; bit <<= 1) {
2118     if (mask & bit) {
2119       if (!TME_M68K_SEQUENCE_RESTARTING) {
2120         ic->tme_m68k_ireg_memx16 = ic->tme_m68k_ireg_uint16(ireg << 1);
2121       }
2122       tme_m68k_write_memx16(ic);
2123       if (!TME_M68K_SEQUENCE_RESTARTING) {
2124         ic->_tme_m68k_ea_address += addend;
2125       }
2126     }
2127     ireg += direction;
2128   }
2129 
2130   /* if this is the predecrement mode, update the address register: */
2131   /* "For the MC68020, MC68030, MC68040, and CPU32, if
2132      the addressing register is also moved to memory, the
2133      value written is the initial register value decremented
2134      by the size of the operation. The MC68000 and MC68010
2135      write the initial register value (not decremented)." */
2136   if (ea_mode == 4
2137       && ic->tme_m68k_type < TME_M68K_M68020) {
2138     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
2139                               + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
2140       = (ic->_tme_m68k_ea_address + sizeof(tme_uint16_t));
2141   }
2142   TME_M68K_INSN_OK;
2143 }
2144 
2145 /* the movep_mr function on a 16-bit dreg: */
TME_M68K_INSN(tme_m68k_movep_mr16)2146 TME_M68K_INSN(tme_m68k_movep_mr16)
2147 {
2148   unsigned int function_code;
2149   tme_uint32_t linear_address;
2150   int dreg;
2151 
2152   TME_M68K_INSN_CANFAULT;
2153 
2154   function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
2155   linear_address = TME_M68K_INSN_OP1(tme_uint32_t);
2156   linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP);
2157   dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
2158   if (!TME_M68K_SEQUENCE_RESTARTING) {
2159     ic->_tme_m68k_ea_function_code = function_code;
2160     ic->_tme_m68k_ea_address = linear_address;
2161   }
2162   tme_m68k_read_memx8(ic);
2163   if (!TME_M68K_SEQUENCE_RESTARTING) {
2164     TME_FIELD_DEPOSIT16(ic->tme_m68k_ireg_uint16(dreg << 1), 8, 8, ic->tme_m68k_ireg_memx8);
2165   }
2166   linear_address += 2;
2167   if (!TME_M68K_SEQUENCE_RESTARTING) {
2168     ic->_tme_m68k_ea_function_code = function_code;
2169     ic->_tme_m68k_ea_address = linear_address;
2170   }
2171   tme_m68k_read_memx8(ic);
2172   if (!TME_M68K_SEQUENCE_RESTARTING) {
2173     TME_FIELD_DEPOSIT16(ic->tme_m68k_ireg_uint16(dreg << 1), 0, 8, ic->tme_m68k_ireg_memx8);
2174   }
2175   linear_address += 2;
2176   TME_M68K_INSN_OK;
2177 }
2178 
2179 /* the movem_mr function on 16-bit registers: */
TME_M68K_INSN(tme_m68k_movem_mr16)2180 TME_M68K_INSN(tme_m68k_movem_mr16)
2181 {
2182   int ireg, direction;
2183   tme_uint16_t mask, bit;
2184   unsigned int ea_mode;
2185   tme_uint32_t addend;
2186   tme_uint32_t total_size;
2187   /* get the register mask, and figure out the total size
2188      of the transfer: */
2189   mask = TME_M68K_INSN_SPECOP;
2190   total_size = 0;
2191   if (mask != 0) {
2192     TME_M68K_INSN_CANFAULT;
2193     bit = mask;
2194     do {
2195       total_size += sizeof(tme_uint16_t);
2196       bit &= (bit - 1);
2197     } while (bit != 0);
2198   }
2199 
2200   /* figure out what direction to move in, and where to start from: */
2201   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
2202   direction = 1;
2203   ireg = TME_M68K_IREG_D0;
2204   addend = (tme_uint32_t) (direction * sizeof(tme_uint16_t));
2205 
2206   /* do the transfer: */
2207   for (bit = 1; bit != 0; bit <<= 1) {
2208     if (mask & bit) {
2209       tme_m68k_read_memx16(ic);
2210       if (!TME_M68K_SEQUENCE_RESTARTING) {
2211         ic->tme_m68k_ireg_uint32(ireg) = TME_EXT_S16_U32((tme_int16_t) ic->tme_m68k_ireg_memx16);
2212         ic->_tme_m68k_ea_address += addend;
2213       }
2214     }
2215     ireg += direction;
2216   }
2217 
2218   /* if this is the postincrement mode, update the address register: */
2219   if (ea_mode == 3) {
2220     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
2221                               + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
2222       = ic->_tme_m68k_ea_address;
2223   }
2224   TME_M68K_INSN_OK;
2225 }
2226 
2227 /* chk16: */
TME_M68K_INSN(tme_m68k_chk16)2228 TME_M68K_INSN(tme_m68k_chk16)
2229 {
2230   if (*((tme_int16_t *) _op0) < 0) {
2231     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N;
2232     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
2233     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
2234     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));
2235   }
2236   if (*((tme_int16_t *) _op0) > *((tme_int16_t *) _op1)) {
2237     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N;
2238     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
2239     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
2240     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));
2241   }
2242   TME_M68K_INSN_OK;
2243 }
2244 
2245 /* cas16: */
TME_M68K_INSN(tme_m68k_cas16)2246 TME_M68K_INSN(tme_m68k_cas16)
2247 {
2248   struct tme_m68k_rmw rmw;
2249   struct tme_m68k_tlb *tlb;
2250   int ireg_dc, ireg_du;
2251   tme_uint16_t value_dc, value_du, value_mem;
2252 
2253   /* start the read/modify/write cycle: */
2254   rmw.tme_m68k_rmw_addresses[0] = ic->_tme_m68k_ea_address;
2255   rmw.tme_m68k_rmw_address_count = 1;
2256   rmw.tme_m68k_rmw_size = sizeof(tme_uint16_t);
2257   if (tme_m68k_rmw_start(ic,
2258                          &rmw)) {
2259     TME_M68K_INSN_OK;
2260   }
2261 
2262   /* get the compare and update registers: */
2263   ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);
2264   ireg_du = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 6, 3);
2265 
2266   /* if we can do the fast compare-and-exchange: */
2267   if (!rmw.tme_m68k_rmw_slow_reads[0]) {
2268 
2269     /* get the compare and update values in big-endian byte order: */
2270     value_dc = ic->tme_m68k_ireg_uint16(ireg_dc << 1);
2271     value_du = ic->tme_m68k_ireg_uint16(ireg_du << 1);
2272     value_dc = tme_htobe_u16(value_dc);
2273     value_du = tme_htobe_u16(value_du);
2274 
2275     /* get this TLB entry: */
2276     tlb = rmw.tme_m68k_rmw_tlbs[0];
2277 
2278     /* this TLB entry must allow fast reading and fast writing
2279        to the same memory: */
2280     assert (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF
2281             && tlb->tme_m68k_tlb_emulator_off_write == tlb->tme_m68k_tlb_emulator_off_read);
2282 
2283     /* do the compare-and-exchange: */
2284     value_mem =
2285       tme_memory_atomic_cx16(((tme_shared tme_uint16_t *)
2286                                    (tlb->tme_m68k_tlb_emulator_off_read
2287                                     + ic->_tme_m68k_ea_address)),
2288                                   value_dc,
2289                                   value_du,
2290                                   tlb->tme_m68k_tlb_bus_rwlock,
2291                                   sizeof(tme_uint8_t));
2292     ic->tme_m68k_ireg_memx16 = tme_betoh_u16(value_mem);
2293   }
2294 
2295   /* compare the compare operand to the effective address operand: */
2296   tme_m68k_cmp16(ic, &ic->tme_m68k_ireg_uint16(ireg_dc << 1), &ic->tme_m68k_ireg_memx16);
2297 
2298   /* if the comparison succeeded: */
2299   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
2300 
2301     /* write the update operand to the effective address operand: */
2302     ic->tme_m68k_ireg_memx16 = ic->tme_m68k_ireg_uint16(ireg_du << 1);
2303   }
2304 
2305   /* otherwise, the comparison failed: */
2306   else {
2307 
2308     /* write the effective address operand to the compare operand: */
2309     ic->tme_m68k_ireg_uint16(ireg_dc << 1) = ic->tme_m68k_ireg_memx16;
2310   }
2311 
2312   /* finish the read/modify/write cycle: */
2313   tme_m68k_rmw_finish(ic,
2314                       &rmw,
2315                       (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0);
2316   TME_M68K_INSN_OK;
2317 }
2318 
2319 /* cas2_16: */
TME_M68K_INSN(tme_m68k_cas2_16)2320 TME_M68K_INSN(tme_m68k_cas2_16)
2321 {
2322   struct tme_m68k_rmw rmw;
2323   int ireg_dcx, ireg_dux;
2324   int ireg_dcy, ireg_duy;
2325   const tme_uint16_t specopx = TME_M68K_INSN_SPECOP;
2326   const tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t);
2327 
2328   /* start the read/modify/write cycle: */
2329   ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
2330   rmw.tme_m68k_rmw_addresses[0] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0
2331                                                            + TME_FIELD_EXTRACTU(specopx, 12, 4));
2332   rmw.tme_m68k_rmw_addresses[1] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0
2333                                                            + TME_FIELD_EXTRACTU(specopy, 12, 4));
2334   rmw.tme_m68k_rmw_address_count = 2;
2335   rmw.tme_m68k_rmw_size = sizeof(tme_uint16_t);
2336   if (tme_m68k_rmw_start(ic,
2337                          &rmw)) {
2338     TME_M68K_INSN_OK;
2339   }
2340 
2341   /* do the comparisons: */
2342   ireg_dcx = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 0, 3);
2343   ireg_dcy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 0, 3);
2344   tme_m68k_cmp16(ic,
2345                  &ic->tme_m68k_ireg_uint16(ireg_dcx << 1),
2346                  &ic->tme_m68k_ireg_memx16);
2347   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
2348     tme_m68k_cmp16(ic,
2349                    &ic->tme_m68k_ireg_uint16(ireg_dcy << 1),
2350                    &ic->tme_m68k_ireg_memy16);
2351   }
2352 
2353   /* if the comparisons succeeded: */
2354   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
2355 
2356     /* write the update operands to the effective address operands: */
2357     ireg_dux = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 6, 3);
2358     ireg_duy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 6, 3);
2359     ic->tme_m68k_ireg_memx16 = ic->tme_m68k_ireg_uint16(ireg_dux << 1);
2360     ic->tme_m68k_ireg_memy16 = ic->tme_m68k_ireg_uint16(ireg_duy << 1);
2361   }
2362 
2363   /* otherwise, the comparisons failed: */
2364   else {
2365 
2366     /* write the effective address operands to the compare operands.
2367        "If Dc1 and Dc2 specify the same data register and the comparison
2368         fails, memory operand 1 is stored in the data register." */
2369     ic->tme_m68k_ireg_uint16(ireg_dcy << 1) = ic->tme_m68k_ireg_memy16;
2370     ic->tme_m68k_ireg_uint16(ireg_dcx << 1) = ic->tme_m68k_ireg_memx16;
2371   }
2372 
2373   /* finish the read/modify/write cycle: */
2374   tme_m68k_rmw_finish(ic,
2375                       &rmw,
2376                       (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0);
2377   TME_M68K_INSN_OK;
2378 }
2379 
2380 /* moves16: */
TME_M68K_INSN(tme_m68k_moves16)2381 TME_M68K_INSN(tme_m68k_moves16)
2382 {
2383   int ireg;
2384   tme_uint16_t ireg_value;
2385   unsigned int ea_reg;
2386   unsigned int increment;
2387   TME_M68K_INSN_PRIV;
2388   TME_M68K_INSN_CANFAULT;
2389   ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);
2390 
2391   /* in case we're storing the same address register used in a
2392      postincrement or predecrement EA, save the current value
2393      of the register now: */
2394   ireg_value = ic->tme_m68k_ireg_uint16(ireg << 1);
2395 
2396   /* we have to handle postincrement and predecrement ourselves: */
2397   if (!TME_M68K_SEQUENCE_RESTARTING) {
2398     ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
2399     increment = TME_M68K_SIZE_16;
2400     if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) {
2401       increment = TME_M68K_SIZE_16;
2402     }
2403     switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) {
2404     case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break;
2405     case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break;
2406     default: break;
2407     }
2408   }
2409 
2410   if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {
2411     if (!TME_M68K_SEQUENCE_RESTARTING) {
2412       ic->tme_m68k_ireg_memx16 = ireg_value;
2413       ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc;
2414     }
2415     tme_m68k_write_memx16(ic);
2416   }
2417   else {
2418     if (!TME_M68K_SEQUENCE_RESTARTING) {
2419       ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc;
2420     }
2421     tme_m68k_read_memx16(ic);
2422     if (ireg >= TME_M68K_IREG_A0) {
2423       ic->tme_m68k_ireg_uint32(ireg) =
2424         TME_EXT_S16_U32((tme_int16_t) ic->tme_m68k_ireg_memx16);
2425     }
2426     else
2427       ic->tme_m68k_ireg_uint16(ireg << 1) = ic->tme_m68k_ireg_memx16;
2428   }
2429   TME_M68K_INSN_OK;
2430 }
2431 
2432 /* this does a 32-bit "add SRC, DST": */
TME_M68K_INSN(tme_m68k_add32)2433 TME_M68K_INSN(tme_m68k_add32)
2434 {
2435   tme_uint32_t res, op0, op1;
2436   tme_uint8_t flags;
2437 
2438   /* load the operand(s): */
2439   op0 = *((tme_uint32_t *) _op0);
2440   op1 = *((tme_uint32_t *) _op1);
2441 
2442   /* perform the operation: */
2443   res = op1 + op0;
2444 
2445   /* store the result: */
2446   *((tme_uint32_t *) _op1) = res;
2447 
2448   /* set the flags: */
2449   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2450   if (res == 0) flags |= TME_M68K_FLAG_Z;
2451   flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xffffffff) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V;
2452   if (op0 > (op1 ^ 0xffffffff)) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
2453   ic->tme_m68k_ireg_ccr = flags;
2454 
2455   TME_M68K_INSN_OK;
2456 }
2457 
2458 /* this does a 32-bit "sub SRC, DST": */
TME_M68K_INSN(tme_m68k_sub32)2459 TME_M68K_INSN(tme_m68k_sub32)
2460 {
2461   tme_uint32_t res, op0, op1;
2462   tme_uint8_t flags;
2463 
2464   /* load the operand(s): */
2465   op0 = *((tme_uint32_t *) _op0);
2466   op1 = *((tme_uint32_t *) _op1);
2467 
2468   /* perform the operation: */
2469   res = op1 - op0;
2470 
2471   /* store the result: */
2472   *((tme_uint32_t *) _op1) = res;
2473 
2474   /* set the flags: */
2475   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2476   if (res == 0) flags |= TME_M68K_FLAG_Z;
2477   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V;
2478   if (op0 > op1) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
2479   ic->tme_m68k_ireg_ccr = flags;
2480 
2481   TME_M68K_INSN_OK;
2482 }
2483 
2484 /* this does a 32-bit "cmp SRC, DST": */
TME_M68K_INSN(tme_m68k_cmp32)2485 TME_M68K_INSN(tme_m68k_cmp32)
2486 {
2487   tme_uint32_t res, op0, op1;
2488   tme_uint8_t flags;
2489 
2490   /* load the operand(s): */
2491   op0 = *((tme_uint32_t *) _op0);
2492   op1 = *((tme_uint32_t *) _op1);
2493 
2494   /* perform the operation: */
2495   res = op1 - op0;
2496 
2497   /* set the flags: */
2498   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2499   if (res == 0) flags |= TME_M68K_FLAG_Z;
2500   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V;
2501   if (op0 > op1) flags |= TME_M68K_FLAG_C;
2502   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2503   ic->tme_m68k_ireg_ccr = flags;
2504 
2505   TME_M68K_INSN_OK;
2506 }
2507 
2508 /* this does a 32-bit "neg DST": */
TME_M68K_INSN(tme_m68k_neg32)2509 TME_M68K_INSN(tme_m68k_neg32)
2510 {
2511   tme_uint32_t res, op1;
2512   tme_uint8_t flags;
2513 
2514   /* load the operand(s): */
2515   op1 = *((tme_uint32_t *) _op1);
2516 
2517   /* perform the operation: */
2518   res = 0 - op1;
2519 
2520   /* store the result: */
2521   *((tme_uint32_t *) _op1) = res;
2522 
2523   /* set the flags: */
2524   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2525   if (res == 0) flags |= TME_M68K_FLAG_Z;
2526   flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V;
2527   if (op1 > 0) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
2528   ic->tme_m68k_ireg_ccr = flags;
2529 
2530   TME_M68K_INSN_OK;
2531 }
2532 
2533 /* this does a 32-bit "or SRC, DST": */
TME_M68K_INSN(tme_m68k_or32)2534 TME_M68K_INSN(tme_m68k_or32)
2535 {
2536   tme_uint32_t res, op0, op1;
2537   tme_uint8_t flags;
2538 
2539   /* load the operand(s): */
2540   op0 = *((tme_uint32_t *) _op0);
2541   op1 = *((tme_uint32_t *) _op1);
2542 
2543   /* perform the operation: */
2544   res = op1 | op0;
2545 
2546   /* store the result: */
2547   *((tme_uint32_t *) _op1) = res;
2548 
2549   /* set the flags: */
2550   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2551   if (res == 0) flags |= TME_M68K_FLAG_Z;
2552   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2553   ic->tme_m68k_ireg_ccr = flags;
2554 
2555   TME_M68K_INSN_OK;
2556 }
2557 
2558 /* this does a 32-bit "and SRC, DST": */
TME_M68K_INSN(tme_m68k_and32)2559 TME_M68K_INSN(tme_m68k_and32)
2560 {
2561   tme_uint32_t res, op0, op1;
2562   tme_uint8_t flags;
2563 
2564   /* load the operand(s): */
2565   op0 = *((tme_uint32_t *) _op0);
2566   op1 = *((tme_uint32_t *) _op1);
2567 
2568   /* perform the operation: */
2569   res = op1 & op0;
2570 
2571   /* store the result: */
2572   *((tme_uint32_t *) _op1) = res;
2573 
2574   /* set the flags: */
2575   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2576   if (res == 0) flags |= TME_M68K_FLAG_Z;
2577   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2578   ic->tme_m68k_ireg_ccr = flags;
2579 
2580   TME_M68K_INSN_OK;
2581 }
2582 
2583 /* this does a 32-bit "eor SRC, DST": */
TME_M68K_INSN(tme_m68k_eor32)2584 TME_M68K_INSN(tme_m68k_eor32)
2585 {
2586   tme_uint32_t res, op0, op1;
2587   tme_uint8_t flags;
2588 
2589   /* load the operand(s): */
2590   op0 = *((tme_uint32_t *) _op0);
2591   op1 = *((tme_uint32_t *) _op1);
2592 
2593   /* perform the operation: */
2594   res = op1 ^ op0;
2595 
2596   /* store the result: */
2597   *((tme_uint32_t *) _op1) = res;
2598 
2599   /* set the flags: */
2600   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2601   if (res == 0) flags |= TME_M68K_FLAG_Z;
2602   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2603   ic->tme_m68k_ireg_ccr = flags;
2604 
2605   TME_M68K_INSN_OK;
2606 }
2607 
2608 /* this does a 32-bit "not DST": */
TME_M68K_INSN(tme_m68k_not32)2609 TME_M68K_INSN(tme_m68k_not32)
2610 {
2611   tme_uint32_t res, op1;
2612   tme_uint8_t flags;
2613 
2614   /* load the operand(s): */
2615   op1 = *((tme_uint32_t *) _op1);
2616 
2617   /* perform the operation: */
2618   res = ~ op1;
2619 
2620   /* store the result: */
2621   *((tme_uint32_t *) _op1) = res;
2622 
2623   /* set the flags: */
2624   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2625   if (res == 0) flags |= TME_M68K_FLAG_Z;
2626   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2627   ic->tme_m68k_ireg_ccr = flags;
2628 
2629   TME_M68K_INSN_OK;
2630 }
2631 
2632 /* this does a 32-bit "tst DST": */
TME_M68K_INSN(tme_m68k_tst32)2633 TME_M68K_INSN(tme_m68k_tst32)
2634 {
2635   tme_uint32_t res, op1;
2636   tme_uint8_t flags;
2637 
2638   /* load the operand(s): */
2639   op1 = *((tme_uint32_t *) _op1);
2640 
2641   /* perform the operation: */
2642   res = op1;
2643 
2644   /* set the flags: */
2645   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2646   if (res == 0) flags |= TME_M68K_FLAG_Z;
2647   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2648   ic->tme_m68k_ireg_ccr = flags;
2649 
2650   TME_M68K_INSN_OK;
2651 }
2652 
2653 /* this does a 32-bit "move DST": */
TME_M68K_INSN(tme_m68k_move32)2654 TME_M68K_INSN(tme_m68k_move32)
2655 {
2656   tme_uint32_t res, op1;
2657   tme_uint8_t flags;
2658 
2659   /* load the operand(s): */
2660   op1 = *((tme_uint32_t *) _op1);
2661 
2662   /* perform the operation: */
2663   res = op1;
2664 
2665   /* store the result: */
2666   *((tme_uint32_t *) _op0) = res;
2667 
2668   /* set the flags: */
2669   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2670   if (res == 0) flags |= TME_M68K_FLAG_Z;
2671   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2672   ic->tme_m68k_ireg_ccr = flags;
2673 
2674   TME_M68K_INSN_OK;
2675 }
2676 
2677 /* this does a 32-bit "moveq DST": */
TME_M68K_INSN(tme_m68k_moveq32)2678 TME_M68K_INSN(tme_m68k_moveq32)
2679 {
2680   tme_uint32_t res;
2681   tme_uint8_t flags;
2682 
2683   /* load the operand(s): */
2684 
2685   /* perform the operation: */
2686   res = TME_EXT_S8_U32((tme_int8_t) (TME_M68K_INSN_OPCODE & 0xff));
2687 
2688   /* store the result: */
2689   *((tme_uint32_t *) _op1) = res;
2690 
2691   /* set the flags: */
2692   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2693   if (res == 0) flags |= TME_M68K_FLAG_Z;
2694   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2695   ic->tme_m68k_ireg_ccr = flags;
2696 
2697   TME_M68K_INSN_OK;
2698 }
2699 
2700 /* this does a 32-bit "clr DST": */
TME_M68K_INSN(tme_m68k_clr32)2701 TME_M68K_INSN(tme_m68k_clr32)
2702 {
2703   tme_uint32_t res;
2704   tme_uint8_t flags;
2705 
2706   /* load the operand(s): */
2707 
2708   /* perform the operation: */
2709   res = 0;
2710 
2711   /* store the result: */
2712   *((tme_uint32_t *) _op1) = res;
2713 
2714   /* set the flags: */
2715   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2716   if (res == 0) flags |= TME_M68K_FLAG_Z;
2717   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2718   ic->tme_m68k_ireg_ccr = flags;
2719 
2720   TME_M68K_INSN_OK;
2721 }
2722 
2723 /* this does a 32-bit "negx DST": */
TME_M68K_INSN(tme_m68k_negx32)2724 TME_M68K_INSN(tme_m68k_negx32)
2725 {
2726   tme_uint32_t res, op1;
2727   tme_uint8_t flags;
2728 
2729   /* load the operand(s): */
2730   op1 = *((tme_uint32_t *) _op1);
2731 
2732   /* perform the operation: */
2733   res = 0 - op1 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1);
2734 
2735   /* store the result: */
2736   *((tme_uint32_t *) _op1) = res;
2737 
2738   /* set the flags: */
2739   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2740   if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);
2741   flags |= ((tme_uint8_t) (((op1 ^ 0) & (0 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V;
2742   if (op1 > 0 || (op1 == 0 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
2743   ic->tme_m68k_ireg_ccr = flags;
2744 
2745   TME_M68K_INSN_OK;
2746 }
2747 
2748 /* this does a 32-bit "addx SRC, DST": */
TME_M68K_INSN(tme_m68k_addx32)2749 TME_M68K_INSN(tme_m68k_addx32)
2750 {
2751   tme_uint32_t res, op0, op1;
2752   tme_uint8_t flags;
2753 
2754   /* load the operand(s): */
2755   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
2756   int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
2757   int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
2758   tme_uint32_t ireg_src_adjust = sizeof(tme_uint32_t);
2759   tme_uint32_t ireg_dst_adjust = sizeof(tme_uint32_t);
2760   tme_uint16_t memory;
2761 
2762   memory = (TME_M68K_INSN_OPCODE & TME_BIT(3));
2763   if (memory) {
2764     TME_M68K_INSN_CANFAULT;
2765     if (!TME_M68K_SEQUENCE_RESTARTING) {
2766       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust;
2767       ic->_tme_m68k_ea_function_code = function_code;
2768       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);
2769     }
2770     tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32);
2771     if (!TME_M68K_SEQUENCE_RESTARTING) {
2772       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust;
2773       ic->_tme_m68k_ea_function_code = function_code;
2774       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
2775     }
2776     tme_m68k_read_memx32(ic);
2777     op1 = ic->tme_m68k_ireg_memx32;
2778     op0 = ic->tme_m68k_ireg_memy32;
2779   }
2780   else {
2781     op0 = ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_src));
2782     op1 = ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_dst));
2783   }
2784 
2785   /* perform the operation: */
2786   res = op1 + op0 + ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1);
2787 
2788   /* store the result: */
2789   if (memory) {
2790     if (!TME_M68K_SEQUENCE_RESTARTING) {
2791       ic->tme_m68k_ireg_memx32 = res;
2792       ic->_tme_m68k_ea_function_code = function_code;
2793       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
2794     }
2795     tme_m68k_write_memx32(ic);
2796   }
2797   else {
2798     ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_dst)) = res;
2799   }
2800 
2801   /* set the flags: */
2802   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2803   if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);
2804   flags |= ((tme_uint8_t) (((op0 ^ op1 ^ 0xffffffff) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V;
2805   if (op0 > (op1 ^ 0xffffffff) || (op0 == (op1 ^ 0xffffffff) && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
2806   ic->tme_m68k_ireg_ccr = flags;
2807 
2808   TME_M68K_INSN_OK;
2809 }
2810 
2811 /* this does a 32-bit "subx SRC, DST": */
TME_M68K_INSN(tme_m68k_subx32)2812 TME_M68K_INSN(tme_m68k_subx32)
2813 {
2814   tme_uint32_t res, op0, op1;
2815   tme_uint8_t flags;
2816 
2817   /* load the operand(s): */
2818   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
2819   int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
2820   int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
2821   tme_uint32_t ireg_src_adjust = sizeof(tme_uint32_t);
2822   tme_uint32_t ireg_dst_adjust = sizeof(tme_uint32_t);
2823   tme_uint16_t memory;
2824 
2825   memory = (TME_M68K_INSN_OPCODE & TME_BIT(3));
2826   if (memory) {
2827     TME_M68K_INSN_CANFAULT;
2828     if (!TME_M68K_SEQUENCE_RESTARTING) {
2829       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) -= ireg_src_adjust;
2830       ic->_tme_m68k_ea_function_code = function_code;
2831       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);
2832     }
2833     tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32);
2834     if (!TME_M68K_SEQUENCE_RESTARTING) {
2835       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) -= ireg_dst_adjust;
2836       ic->_tme_m68k_ea_function_code = function_code;
2837       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
2838     }
2839     tme_m68k_read_memx32(ic);
2840     op1 = ic->tme_m68k_ireg_memx32;
2841     op0 = ic->tme_m68k_ireg_memy32;
2842   }
2843   else {
2844     op0 = ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_src));
2845     op1 = ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_dst));
2846   }
2847 
2848   /* perform the operation: */
2849   res = op1 - op0 - ((ic->tme_m68k_ireg_ccr / TME_M68K_FLAG_X) & 1);
2850 
2851   /* store the result: */
2852   if (memory) {
2853     if (!TME_M68K_SEQUENCE_RESTARTING) {
2854       ic->tme_m68k_ireg_memx32 = res;
2855       ic->_tme_m68k_ea_function_code = function_code;
2856       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
2857     }
2858     tme_m68k_write_memx32(ic);
2859   }
2860   else {
2861     ic->tme_m68k_ireg_uint32((TME_M68K_IREG_D0 + ireg_dst)) = res;
2862   }
2863 
2864   /* set the flags: */
2865   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2866   if (res == 0) flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z);
2867   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V;
2868   if (op0 > op1 || (op0 == op1 && (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X))) flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
2869   ic->tme_m68k_ireg_ccr = flags;
2870 
2871   TME_M68K_INSN_OK;
2872 }
2873 
2874 /* this does a 32-bit "cmpm SRC, DST": */
TME_M68K_INSN(tme_m68k_cmpm32)2875 TME_M68K_INSN(tme_m68k_cmpm32)
2876 {
2877   tme_uint32_t res, op0, op1;
2878   tme_uint8_t flags;
2879 
2880   /* load the operand(s): */
2881   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
2882   int ireg_src = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
2883   int ireg_dst = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
2884   tme_uint32_t ireg_src_adjust = sizeof(tme_uint32_t);
2885   tme_uint32_t ireg_dst_adjust = sizeof(tme_uint32_t);
2886 
2887   TME_M68K_INSN_CANFAULT;
2888 
2889   if (!TME_M68K_SEQUENCE_RESTARTING) {
2890     ic->_tme_m68k_ea_function_code = function_code;
2891     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src);
2892     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_src) += ireg_src_adjust;
2893   }
2894   tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32);
2895   if (!TME_M68K_SEQUENCE_RESTARTING) {
2896     ic->_tme_m68k_ea_function_code = function_code;
2897     ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst);
2898     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ireg_dst) += ireg_dst_adjust;
2899   }
2900   tme_m68k_read_memx32(ic);
2901   op1 = ic->tme_m68k_ireg_memx32;
2902   op0 = ic->tme_m68k_ireg_memy32;
2903 
2904   /* perform the operation: */
2905   res = op1 - op0;
2906 
2907   /* set the flags: */
2908   flags = ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
2909   if (res == 0) flags |= TME_M68K_FLAG_Z;
2910   flags |= ((tme_uint8_t) (((op0 ^ op1) & (op1 ^ res)) >> (32 - 1))) * TME_M68K_FLAG_V;
2911   if (op0 > op1) flags |= TME_M68K_FLAG_C;
2912   flags |= (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X);
2913   ic->tme_m68k_ireg_ccr = flags;
2914 
2915   TME_M68K_INSN_OK;
2916 }
2917 
2918 /* a move of an address register to a predecrement or
2919    postincrement EA with that same address register, must
2920    store the original value of the address register.  since the
2921    predecrement and postincrement code in the executer updates
2922    the address register before the move has happened, we wrap
2923    the normal move function in this one, that gives an op1
2924    argument that is the original value of the address register: */
TME_M68K_INSN(tme_m68k_move_srpd32)2925 TME_M68K_INSN(tme_m68k_move_srpd32)
2926 {
2927   /* NB: both this function and tme_m68k_move32()
2928      get the source operand as _op1, and the destination
2929      operand as _op0: */
2930   if (!TME_M68K_SEQUENCE_RESTARTING) {
2931     *((tme_uint32_t *) _op0)
2932       = (*((tme_uint32_t *) _op1)
2933          + sizeof(tme_uint32_t));
2934   }
2935   tme_m68k_move32(ic, _op0, _op0);
2936 }
2937 
2938 /* a move of an address register to a predecrement or
2939    postincrement EA with that same address register, must
2940    store the original value of the address register.  since the
2941    predecrement and postincrement code in the executer updates
2942    the address register before the move has happened, we wrap
2943    the normal move function in this one, that gives an op1
2944    argument that is the original value of the address register: */
TME_M68K_INSN(tme_m68k_move_srpi32)2945 TME_M68K_INSN(tme_m68k_move_srpi32)
2946 {
2947   /* NB: both this function and tme_m68k_move32()
2948      get the source operand as _op1, and the destination
2949      operand as _op0: */
2950   if (!TME_M68K_SEQUENCE_RESTARTING) {
2951     *((tme_uint32_t *) _op0)
2952       = (*((tme_uint32_t *) _op1)
2953          - sizeof(tme_uint32_t));
2954   }
2955   tme_m68k_move32(ic, _op0, _op0);
2956 }
2957 
2958 /* the suba function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_suba32)2959 TME_M68K_INSN(tme_m68k_suba32)
2960 {
2961   *((tme_int32_t *) _op1) -= *((tme_int32_t *) _op0);
2962   TME_M68K_INSN_OK;
2963 }
2964 
2965 /* the adda function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_adda32)2966 TME_M68K_INSN(tme_m68k_adda32)
2967 {
2968   *((tme_int32_t *) _op1) += *((tme_int32_t *) _op0);
2969   TME_M68K_INSN_OK;
2970 }
2971 
2972 /* the movea function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_movea32)2973 TME_M68K_INSN(tme_m68k_movea32)
2974 {
2975   *((tme_int32_t *) _op0) = *((tme_int32_t *) _op1);
2976   TME_M68K_INSN_OK;
2977 }
2978 
2979 /* the btst function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_btst32)2980 TME_M68K_INSN(tme_m68k_btst32)
2981 {
2982   tme_uint32_t value, bit;
2983   bit = _TME_BIT(tme_uint32_t, TME_M68K_INSN_OP0(tme_uint8_t) & (32 - 1));
2984   value = TME_M68K_INSN_OP1(tme_uint32_t);
2985   if (value & bit) {
2986     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;
2987   }
2988   else {
2989     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
2990   }
2991   TME_M68K_INSN_OK;
2992 }
2993 
2994 /* the bchg function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_bchg32)2995 TME_M68K_INSN(tme_m68k_bchg32)
2996 {
2997   tme_uint32_t value, bit;
2998   bit = _TME_BIT(tme_uint32_t, TME_M68K_INSN_OP0(tme_uint8_t) & (32 - 1));
2999   value = TME_M68K_INSN_OP1(tme_uint32_t);
3000   if (value & bit) {
3001     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;
3002   }
3003   else {
3004     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
3005   }
3006   TME_M68K_INSN_OP1(tme_uint32_t) = value ^ bit;
3007   TME_M68K_INSN_OK;
3008 }
3009 
3010 /* the bclr function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_bclr32)3011 TME_M68K_INSN(tme_m68k_bclr32)
3012 {
3013   tme_uint32_t value, bit;
3014   bit = _TME_BIT(tme_uint32_t, TME_M68K_INSN_OP0(tme_uint8_t) & (32 - 1));
3015   value = TME_M68K_INSN_OP1(tme_uint32_t);
3016   if (value & bit) {
3017     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;
3018   }
3019   else {
3020     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
3021   }
3022   TME_M68K_INSN_OP1(tme_uint32_t) = value & ~bit;
3023   TME_M68K_INSN_OK;
3024 }
3025 
3026 /* the bset function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_bset32)3027 TME_M68K_INSN(tme_m68k_bset32)
3028 {
3029   tme_uint32_t value, bit;
3030   bit = _TME_BIT(tme_uint32_t, TME_M68K_INSN_OP0(tme_uint8_t) & (32 - 1));
3031   value = TME_M68K_INSN_OP1(tme_uint32_t);
3032   if (value & bit) {
3033     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_Z;
3034   }
3035   else {
3036     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_Z;
3037   }
3038   TME_M68K_INSN_OP1(tme_uint32_t) = value | bit;
3039   TME_M68K_INSN_OK;
3040 }
3041 
3042 /* the asl function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_asl32)3043 TME_M68K_INSN(tme_m68k_asl32)
3044 {
3045   unsigned int count;
3046   tme_uint32_t sign_bits, sign_bits_mask;
3047   tme_uint32_t res;
3048   tme_uint8_t flags;
3049 
3050   /* get the count and operand: */
3051   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
3052   res = TME_M68K_INSN_OP1(tme_uint32_t);
3053 
3054   /* generate the X, V, and C flags assuming the count is zero: */
3055   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
3056 
3057   /* if the count is nonzero, update the result and
3058      generate the X, V, and C flags: */
3059   if (count > 0) {
3060 
3061     /* we need to see how the sign of the result will change during
3062        shifting in order to generate V.
3063 
3064        in general, the idea is to get all of the bits that will ever
3065        appear in the sign position into sign_bits, with a mask in
3066        sign_bits_mask.  if (sign_bits & sign_bits_mask) is zero or
3067        sign_bits_mask, clear V, else set V.
3068 
3069        start by loading the operand into sign_bits and setting
3070        sign_bits_mask to all-bits-one.
3071 
3072        if the shift count is exactly 32 - 1, then all of the bits
3073        of the operand will appear in the sign position.
3074 
3075        if the shift count is less than 32 - 1, then some of the
3076        less significant bits of the operand will never appear in the
3077        sign position, so we can shift sign_bits_mask to ignore them.
3078 
3079        if the shift count is greater than 32 - 1, then all of the
3080        bits in the operand, plus at least one zero bit, will appear in
3081        the sign position.  the only way that the sign bit will never
3082        change during the shift is if the operand was zero to begin with.
3083        without any changes to sign_bits or sign_bits_mask, the final
3084        test will always work, except when sign_bits is all-bits-one.
3085        the magic below clears the least-significant bit of sign_bits
3086        iff sign_bits is all-bits-one: */
3087     sign_bits = res;
3088     if (63 > SHIFTMAX_INT32_T
3089         && count > 32) {
3090       res = 0;
3091     }
3092     res <<= (count - 1);
3093     flags = (res >> (32 - 1));
3094     flags *= TME_M68K_FLAG_C;
3095     flags |= (flags * TME_M68K_FLAG_X);
3096     res <<= 1;
3097     sign_bits_mask = (tme_uint32_t) -1;
3098     if (count != 32 - 1) {
3099       if (count < 32) {
3100         sign_bits_mask <<= ((32 - 1) - count);
3101       }
3102       else {
3103         sign_bits ^= !(sign_bits + 1);
3104       }
3105     }
3106     sign_bits &= sign_bits_mask;
3107     if (sign_bits != 0 && sign_bits != sign_bits_mask) {
3108       flags |= TME_M68K_FLAG_V;
3109     }
3110   }
3111 
3112   /* store the result: */
3113   TME_M68K_INSN_OP1(tme_uint32_t) = res;
3114 
3115   /* generate the N flag.  we cast to tme_uint8_t as soon as we
3116      know the bit we want is within the range of the type, to try
3117      to affect the generated assembly: */
3118   flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
3119 
3120   /* generate the Z flag: */
3121   if (res == 0) flags |= TME_M68K_FLAG_Z;
3122 
3123   /* store the flags: */
3124   ic->tme_m68k_ireg_ccr = flags;
3125   TME_M68K_INSN_OK;
3126 }
3127 
3128 /* the asr function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_asr32)3129 TME_M68K_INSN(tme_m68k_asr32)
3130 {
3131   unsigned int count;
3132   tme_int32_t res;
3133   tme_uint8_t flags;
3134 
3135   /* get the count and operand: */
3136   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
3137   res = TME_M68K_INSN_OP1(tme_int32_t);
3138 
3139   /* generate the X, V, and C flags assuming the count is zero: */
3140   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
3141 
3142   /* if the count is nonzero, update the result and
3143      generate the X, V, and C flags: */
3144   if (count > 0) {
3145     if (63 > SHIFTMAX_INT32_T
3146         && count > 32) {
3147       res = 0 - (res < 0);
3148     }
3149 #ifdef SHIFTSIGNED_INT32_T
3150     res >>= (count - 1);
3151 #else  /* !SHIFTSIGNED_INT32_T */
3152     for (; --count > 0; ) {
3153       res = (res & ~((tme_int32_t) 1)) / 2;
3154     }
3155 #endif /* !SHIFTSIGNED_INT32_T */
3156     flags = (res & 1);
3157     flags *= TME_M68K_FLAG_C;
3158     flags |= (flags * TME_M68K_FLAG_X);
3159 #ifdef SHIFTSIGNED_INT32_T
3160     res >>= 1;
3161 #else  /* !SHIFTSIGNED_INT32_T */
3162     res = (res & ~((tme_int32_t) 1)) / 2;
3163 #endif /* !SHIFTSIGNED_INT32_T */
3164   }
3165 
3166   /* store the result: */
3167   TME_M68K_INSN_OP1(tme_int32_t) = res;
3168 
3169   /* generate the N flag.  we cast to tme_uint8_t as soon as we
3170      know the bit we want is within the range of the type, to try
3171      to affect the generated assembly: */
3172   flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
3173 
3174   /* generate the Z flag: */
3175   if (res == 0) flags |= TME_M68K_FLAG_Z;
3176 
3177   /* store the flags: */
3178   ic->tme_m68k_ireg_ccr = flags;
3179   TME_M68K_INSN_OK;
3180 }
3181 
3182 /* the lsl function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_lsl32)3183 TME_M68K_INSN(tme_m68k_lsl32)
3184 {
3185   unsigned int count;
3186   tme_uint32_t res;
3187   tme_uint8_t flags;
3188 
3189   /* get the count and operand: */
3190   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
3191   res = TME_M68K_INSN_OP1(tme_uint32_t);
3192 
3193   /* generate the X, V, and C flags assuming the count is zero: */
3194   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
3195 
3196   /* if the count is nonzero, update the result and
3197      generate the X, V, and C flags: */
3198   if (count > 0) {
3199     if (63 > SHIFTMAX_INT32_T
3200         && count > 32) {
3201       res = 0;
3202     }
3203     res <<= (count - 1);
3204     flags = (res >> (32 - 1));
3205     flags *= TME_M68K_FLAG_C;
3206     flags |= (flags * TME_M68K_FLAG_X);
3207     res <<= 1;
3208   }
3209 
3210   /* store the result: */
3211   TME_M68K_INSN_OP1(tme_uint32_t) = res;
3212 
3213   /* generate the N flag.  we cast to tme_uint8_t as soon as we
3214      know the bit we want is within the range of the type, to try
3215      to affect the generated assembly: */
3216   flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
3217 
3218   /* generate the Z flag: */
3219   if (res == 0) flags |= TME_M68K_FLAG_Z;
3220 
3221   /* store the flags: */
3222   ic->tme_m68k_ireg_ccr = flags;
3223   TME_M68K_INSN_OK;
3224 }
3225 
3226 /* the lsr function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_lsr32)3227 TME_M68K_INSN(tme_m68k_lsr32)
3228 {
3229   unsigned int count;
3230   tme_uint32_t res;
3231   tme_uint8_t flags;
3232 
3233   /* get the count and operand: */
3234   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
3235   res = TME_M68K_INSN_OP1(tme_uint32_t);
3236 
3237   /* generate the X, V, and C flags assuming the count is zero: */
3238   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
3239 
3240   /* if the count is nonzero, update the result and
3241      generate the X, V, and C flags: */
3242   if (count > 0) {
3243     if (63 > SHIFTMAX_INT32_T
3244         && count > 32) {
3245       res = 0;
3246     }
3247     res >>= (count - 1);
3248     flags = (res & 1);
3249     flags *= TME_M68K_FLAG_C;
3250     flags |= (flags * TME_M68K_FLAG_X);
3251     res >>= 1;
3252   }
3253 
3254   /* store the result: */
3255   TME_M68K_INSN_OP1(tme_uint32_t) = res;
3256 
3257   /* generate the N flag.  we cast to tme_uint8_t as soon as we
3258      know the bit we want is within the range of the type, to try
3259      to affect the generated assembly: */
3260   flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
3261 
3262   /* generate the Z flag: */
3263   if (res == 0) flags |= TME_M68K_FLAG_Z;
3264 
3265   /* store the flags: */
3266   ic->tme_m68k_ireg_ccr = flags;
3267   TME_M68K_INSN_OK;
3268 }
3269 
3270 /* the rol function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_rol32)3271 TME_M68K_INSN(tme_m68k_rol32)
3272 {
3273   unsigned int count;
3274   tme_uint32_t res;
3275   tme_uint8_t flags;
3276 
3277   /* get the count and operand: */
3278   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
3279   res = TME_M68K_INSN_OP1(tme_uint32_t);
3280 
3281   /* generate the X, V, and C flags assuming the count is zero: */
3282   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
3283 
3284   /* if the count is nonzero, update the result and
3285      generate the X, V, and C flags: */
3286   if (count > 0) {
3287     count &= (32 - 1);
3288     res = (res << count) | (res >> (32 - count));
3289     flags |= ((res & 1) * TME_M68K_FLAG_C);
3290   }
3291 
3292   /* store the result: */
3293   TME_M68K_INSN_OP1(tme_uint32_t) = res;
3294 
3295   /* generate the N flag.  we cast to tme_uint8_t as soon as we
3296      know the bit we want is within the range of the type, to try
3297      to affect the generated assembly: */
3298   flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
3299 
3300   /* generate the Z flag: */
3301   if (res == 0) flags |= TME_M68K_FLAG_Z;
3302 
3303   /* store the flags: */
3304   ic->tme_m68k_ireg_ccr = flags;
3305   TME_M68K_INSN_OK;
3306 }
3307 
3308 /* the ror function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_ror32)3309 TME_M68K_INSN(tme_m68k_ror32)
3310 {
3311   unsigned int count;
3312   tme_uint32_t res;
3313   tme_uint8_t flags;
3314 
3315   /* get the count and operand: */
3316   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
3317   res = TME_M68K_INSN_OP1(tme_uint32_t);
3318 
3319   /* generate the X, V, and C flags assuming the count is zero: */
3320   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
3321 
3322   /* if the count is nonzero, update the result and
3323      generate the X, V, and C flags: */
3324   if (count > 0) {
3325     count &= (32 - 1);
3326     res = (res << (32 - count)) | (res >> count);
3327     flags |= ((res >> (32 - 1)) * TME_M68K_FLAG_C);
3328   }
3329 
3330   /* store the result: */
3331   TME_M68K_INSN_OP1(tme_uint32_t) = res;
3332 
3333   /* generate the N flag.  we cast to tme_uint8_t as soon as we
3334      know the bit we want is within the range of the type, to try
3335      to affect the generated assembly: */
3336   flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
3337 
3338   /* generate the Z flag: */
3339   if (res == 0) flags |= TME_M68K_FLAG_Z;
3340 
3341   /* store the flags: */
3342   ic->tme_m68k_ireg_ccr = flags;
3343   TME_M68K_INSN_OK;
3344 }
3345 
3346 /* the roxl function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_roxl32)3347 TME_M68K_INSN(tme_m68k_roxl32)
3348 {
3349   unsigned int count;
3350   tme_uint8_t xbit;
3351   tme_uint32_t res;
3352   tme_uint8_t flags;
3353 
3354   /* get the count and operand: */
3355   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
3356   res = TME_M68K_INSN_OP1(tme_uint32_t);
3357 
3358   /* generate the X, V, and C flags assuming the count is zero: */
3359   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
3360   xbit = (flags / TME_M68K_FLAG_X);
3361   flags |= (xbit * TME_M68K_FLAG_C);
3362 
3363   /* if the count is nonzero, update the result and
3364      generate the X, V, and C flags: */
3365   if (count > 0) {
3366     count %= (32 + 1);
3367     flags = xbit;
3368     if (count > 0) {
3369       flags = (res >> (32 - count)) & 1;
3370       if (32 > SHIFTMAX_INT32_T
3371           && count == 32) {
3372         res = 0 | (xbit << (32 - 1)) | (res >> ((32 + 1) - 32));
3373       }
3374       else if (32 > SHIFTMAX_INT32_T
3375                && count == 1) {
3376         res = (res << 1) | (xbit << (1 - 1)) | 0;
3377       }
3378       else {
3379         res = (res << count) | (xbit << (count - 1)) | (res >> ((32 + 1) - count));
3380       }
3381     }
3382     flags *= TME_M68K_FLAG_C;
3383     flags |= (flags * TME_M68K_FLAG_X);
3384   }
3385 
3386   /* store the result: */
3387   TME_M68K_INSN_OP1(tme_uint32_t) = res;
3388 
3389   /* generate the N flag.  we cast to tme_uint8_t as soon as we
3390      know the bit we want is within the range of the type, to try
3391      to affect the generated assembly: */
3392   flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
3393 
3394   /* generate the Z flag: */
3395   if (res == 0) flags |= TME_M68K_FLAG_Z;
3396 
3397   /* store the flags: */
3398   ic->tme_m68k_ireg_ccr = flags;
3399   TME_M68K_INSN_OK;
3400 }
3401 
3402 /* the roxr function on a 32-byte EA: */
TME_M68K_INSN(tme_m68k_roxr32)3403 TME_M68K_INSN(tme_m68k_roxr32)
3404 {
3405   unsigned int count;
3406   tme_uint8_t xbit;
3407   tme_uint32_t res;
3408   tme_uint8_t flags;
3409 
3410   /* get the count and operand: */
3411   count = TME_M68K_INSN_OP0(tme_uint8_t) & 63;
3412   res = TME_M68K_INSN_OP1(tme_uint32_t);
3413 
3414   /* generate the X, V, and C flags assuming the count is zero: */
3415   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
3416   xbit = (flags / TME_M68K_FLAG_X);
3417   flags |= (xbit * TME_M68K_FLAG_C);
3418 
3419   /* if the count is nonzero, update the result and
3420      generate the X, V, and C flags: */
3421   if (count > 0) {
3422     count %= (32 + 1);
3423     flags = xbit;
3424     if (count > 0) {
3425       flags = (res >> (count - 1)) & 1;
3426       if (32 > SHIFTMAX_INT32_T
3427           && count == 32) {
3428         res = (res << ((32 + 1) - 32)) | (xbit << (32 - 32)) | 0;
3429       }
3430       else if (32 > SHIFTMAX_INT32_T
3431                && count == 1) {
3432         res = 0 | (xbit << (32 - 1)) | (res >> 1);
3433       }
3434       else {
3435         res = (res << ((32 + 1) - count)) | (xbit << (32 - count)) | (res >> count);
3436       }
3437     }
3438     flags *= TME_M68K_FLAG_C;
3439     flags |= (flags * TME_M68K_FLAG_X);
3440   }
3441 
3442   /* store the result: */
3443   TME_M68K_INSN_OP1(tme_uint32_t) = res;
3444 
3445   /* generate the N flag.  we cast to tme_uint8_t as soon as we
3446      know the bit we want is within the range of the type, to try
3447      to affect the generated assembly: */
3448   flags |= ((tme_uint8_t) (((tme_uint32_t) res) >> (32 - 1))) * TME_M68K_FLAG_N;
3449 
3450   /* generate the Z flag: */
3451   if (res == 0) flags |= TME_M68K_FLAG_Z;
3452 
3453   /* store the flags: */
3454   ic->tme_m68k_ireg_ccr = flags;
3455   TME_M68K_INSN_OK;
3456 }
3457 
3458 /* the movep_rm function on a 32-bit dreg: */
TME_M68K_INSN(tme_m68k_movep_rm32)3459 TME_M68K_INSN(tme_m68k_movep_rm32)
3460 {
3461   unsigned int function_code;
3462   tme_uint32_t linear_address;
3463   tme_uint32_t value;
3464   int dreg;
3465 
3466   TME_M68K_INSN_CANFAULT;
3467 
3468   function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
3469   linear_address = TME_M68K_INSN_OP1(tme_uint32_t);
3470   linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP);
3471   dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
3472   value = ic->tme_m68k_ireg_uint32(dreg);
3473   if (!TME_M68K_SEQUENCE_RESTARTING) {
3474     ic->_tme_m68k_ea_function_code = function_code;
3475     ic->_tme_m68k_ea_address = linear_address;
3476     ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 24, 8);
3477   }
3478   tme_m68k_write_memx8(ic);
3479   linear_address += 2;
3480   if (!TME_M68K_SEQUENCE_RESTARTING) {
3481     ic->_tme_m68k_ea_function_code = function_code;
3482     ic->_tme_m68k_ea_address = linear_address;
3483     ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 16, 8);
3484   }
3485   tme_m68k_write_memx8(ic);
3486   linear_address += 2;
3487   if (!TME_M68K_SEQUENCE_RESTARTING) {
3488     ic->_tme_m68k_ea_function_code = function_code;
3489     ic->_tme_m68k_ea_address = linear_address;
3490     ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 8, 8);
3491   }
3492   tme_m68k_write_memx8(ic);
3493   linear_address += 2;
3494   if (!TME_M68K_SEQUENCE_RESTARTING) {
3495     ic->_tme_m68k_ea_function_code = function_code;
3496     ic->_tme_m68k_ea_address = linear_address;
3497     ic->tme_m68k_ireg_memx8 = TME_FIELD_EXTRACTU(value, 0, 8);
3498   }
3499   tme_m68k_write_memx8(ic);
3500   linear_address += 2;
3501   TME_M68K_INSN_OK;
3502 }
3503 
3504 /* the movem_rm function on 32-bit registers: */
TME_M68K_INSN(tme_m68k_movem_rm32)3505 TME_M68K_INSN(tme_m68k_movem_rm32)
3506 {
3507   int ireg, direction;
3508   tme_uint16_t mask, bit;
3509   unsigned int ea_mode;
3510   tme_uint32_t addend;
3511   tme_uint32_t total_size;
3512   /* get the register mask, and figure out the total size
3513      of the transfer: */
3514   mask = TME_M68K_INSN_SPECOP;
3515   total_size = 0;
3516   if (mask != 0) {
3517     TME_M68K_INSN_CANFAULT;
3518     bit = mask;
3519     do {
3520       total_size += sizeof(tme_uint32_t);
3521       bit &= (bit - 1);
3522     } while (bit != 0);
3523   }
3524 
3525   /* figure out what direction to move in, and where to start from: */
3526   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
3527   direction = 1;
3528   ireg = TME_M68K_IREG_D0;
3529   if (ea_mode == 4) {
3530     direction = -1;
3531     ireg = TME_M68K_IREG_A7;
3532     if (!TME_M68K_SEQUENCE_RESTARTING) {
3533 
3534       /* "For the MC68020, MC68030, MC68040, and CPU32, if
3535          the addressing register is also moved to memory, the
3536          value written is the initial register value decremented
3537          by the size of the operation. The MC68000 and MC68010
3538          write the initial register value (not decremented)." */
3539       if (ic->tme_m68k_type >= TME_M68K_M68020) {
3540         ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
3541                                  + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
3542           = (ic->_tme_m68k_ea_address - total_size);
3543       }
3544 
3545       /* predecrement the effective address for the first transfer: */
3546       ic->_tme_m68k_ea_address -= sizeof(tme_uint32_t);
3547     }
3548   }
3549   addend = (tme_uint32_t) (direction * sizeof(tme_uint32_t));
3550 
3551   /* do the transfer: */
3552   for (bit = 1; bit != 0; bit <<= 1) {
3553     if (mask & bit) {
3554       if (!TME_M68K_SEQUENCE_RESTARTING) {
3555         ic->tme_m68k_ireg_memx32 = ic->tme_m68k_ireg_uint32(ireg);
3556       }
3557       tme_m68k_write_memx32(ic);
3558       if (!TME_M68K_SEQUENCE_RESTARTING) {
3559         ic->_tme_m68k_ea_address += addend;
3560       }
3561     }
3562     ireg += direction;
3563   }
3564 
3565   /* if this is the predecrement mode, update the address register: */
3566   /* "For the MC68020, MC68030, MC68040, and CPU32, if
3567      the addressing register is also moved to memory, the
3568      value written is the initial register value decremented
3569      by the size of the operation. The MC68000 and MC68010
3570      write the initial register value (not decremented)." */
3571   if (ea_mode == 4
3572       && ic->tme_m68k_type < TME_M68K_M68020) {
3573     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
3574                               + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
3575       = (ic->_tme_m68k_ea_address + sizeof(tme_uint32_t));
3576   }
3577   TME_M68K_INSN_OK;
3578 }
3579 
3580 /* the movep_mr function on a 32-bit dreg: */
TME_M68K_INSN(tme_m68k_movep_mr32)3581 TME_M68K_INSN(tme_m68k_movep_mr32)
3582 {
3583   unsigned int function_code;
3584   tme_uint32_t linear_address;
3585   int dreg;
3586 
3587   TME_M68K_INSN_CANFAULT;
3588 
3589   function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
3590   linear_address = TME_M68K_INSN_OP1(tme_uint32_t);
3591   linear_address += (tme_int32_t) ((tme_int16_t) TME_M68K_INSN_SPECOP);
3592   dreg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
3593   if (!TME_M68K_SEQUENCE_RESTARTING) {
3594     ic->_tme_m68k_ea_function_code = function_code;
3595     ic->_tme_m68k_ea_address = linear_address;
3596   }
3597   tme_m68k_read_memx8(ic);
3598   if (!TME_M68K_SEQUENCE_RESTARTING) {
3599     TME_FIELD_DEPOSIT32(ic->tme_m68k_ireg_uint32(dreg), 24, 8, ic->tme_m68k_ireg_memx8);
3600   }
3601   linear_address += 2;
3602   if (!TME_M68K_SEQUENCE_RESTARTING) {
3603     ic->_tme_m68k_ea_function_code = function_code;
3604     ic->_tme_m68k_ea_address = linear_address;
3605   }
3606   tme_m68k_read_memx8(ic);
3607   if (!TME_M68K_SEQUENCE_RESTARTING) {
3608     TME_FIELD_DEPOSIT32(ic->tme_m68k_ireg_uint32(dreg), 16, 8, ic->tme_m68k_ireg_memx8);
3609   }
3610   linear_address += 2;
3611   if (!TME_M68K_SEQUENCE_RESTARTING) {
3612     ic->_tme_m68k_ea_function_code = function_code;
3613     ic->_tme_m68k_ea_address = linear_address;
3614   }
3615   tme_m68k_read_memx8(ic);
3616   if (!TME_M68K_SEQUENCE_RESTARTING) {
3617     TME_FIELD_DEPOSIT32(ic->tme_m68k_ireg_uint32(dreg), 8, 8, ic->tme_m68k_ireg_memx8);
3618   }
3619   linear_address += 2;
3620   if (!TME_M68K_SEQUENCE_RESTARTING) {
3621     ic->_tme_m68k_ea_function_code = function_code;
3622     ic->_tme_m68k_ea_address = linear_address;
3623   }
3624   tme_m68k_read_memx8(ic);
3625   if (!TME_M68K_SEQUENCE_RESTARTING) {
3626     TME_FIELD_DEPOSIT32(ic->tme_m68k_ireg_uint32(dreg), 0, 8, ic->tme_m68k_ireg_memx8);
3627   }
3628   linear_address += 2;
3629   TME_M68K_INSN_OK;
3630 }
3631 
3632 /* the movem_mr function on 32-bit registers: */
TME_M68K_INSN(tme_m68k_movem_mr32)3633 TME_M68K_INSN(tme_m68k_movem_mr32)
3634 {
3635   int ireg, direction;
3636   tme_uint16_t mask, bit;
3637   unsigned int ea_mode;
3638   tme_uint32_t addend;
3639   tme_uint32_t total_size;
3640   /* get the register mask, and figure out the total size
3641      of the transfer: */
3642   mask = TME_M68K_INSN_SPECOP;
3643   total_size = 0;
3644   if (mask != 0) {
3645     TME_M68K_INSN_CANFAULT;
3646     bit = mask;
3647     do {
3648       total_size += sizeof(tme_uint32_t);
3649       bit &= (bit - 1);
3650     } while (bit != 0);
3651   }
3652 
3653   /* figure out what direction to move in, and where to start from: */
3654   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
3655   direction = 1;
3656   ireg = TME_M68K_IREG_D0;
3657   addend = (tme_uint32_t) (direction * sizeof(tme_uint32_t));
3658 
3659   /* do the transfer: */
3660   for (bit = 1; bit != 0; bit <<= 1) {
3661     if (mask & bit) {
3662       tme_m68k_read_memx32(ic);
3663       if (!TME_M68K_SEQUENCE_RESTARTING) {
3664         ic->tme_m68k_ireg_uint32(ireg) = ic->tme_m68k_ireg_memx32;
3665         ic->_tme_m68k_ea_address += addend;
3666       }
3667     }
3668     ireg += direction;
3669   }
3670 
3671   /* if this is the postincrement mode, update the address register: */
3672   if (ea_mode == 3) {
3673     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
3674                               + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
3675       = ic->_tme_m68k_ea_address;
3676   }
3677   TME_M68K_INSN_OK;
3678 }
3679 
3680 /* chk32: */
TME_M68K_INSN(tme_m68k_chk32)3681 TME_M68K_INSN(tme_m68k_chk32)
3682 {
3683   if (*((tme_int32_t *) _op0) < 0) {
3684     ic->tme_m68k_ireg_ccr |= TME_M68K_FLAG_N;
3685     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
3686     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
3687     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));
3688   }
3689   if (*((tme_int32_t *) _op0) > *((tme_int32_t *) _op1)) {
3690     ic->tme_m68k_ireg_ccr &= ~TME_M68K_FLAG_N;
3691     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
3692     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
3693     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_CHK));
3694   }
3695   TME_M68K_INSN_OK;
3696 }
3697 
3698 /* cas32: */
TME_M68K_INSN(tme_m68k_cas32)3699 TME_M68K_INSN(tme_m68k_cas32)
3700 {
3701   struct tme_m68k_rmw rmw;
3702   struct tme_m68k_tlb *tlb;
3703   int ireg_dc, ireg_du;
3704   tme_uint32_t value_dc, value_du, value_mem;
3705 
3706   /* start the read/modify/write cycle: */
3707   rmw.tme_m68k_rmw_addresses[0] = ic->_tme_m68k_ea_address;
3708   rmw.tme_m68k_rmw_address_count = 1;
3709   rmw.tme_m68k_rmw_size = sizeof(tme_uint32_t);
3710   if (tme_m68k_rmw_start(ic,
3711                          &rmw)) {
3712     TME_M68K_INSN_OK;
3713   }
3714 
3715   /* get the compare and update registers: */
3716   ireg_dc = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);
3717   ireg_du = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 6, 3);
3718 
3719   /* if we can do the fast compare-and-exchange: */
3720   if (!rmw.tme_m68k_rmw_slow_reads[0]) {
3721 
3722     /* get the compare and update values in big-endian byte order: */
3723     value_dc = ic->tme_m68k_ireg_uint32(ireg_dc);
3724     value_du = ic->tme_m68k_ireg_uint32(ireg_du);
3725     value_dc = tme_htobe_u32(value_dc);
3726     value_du = tme_htobe_u32(value_du);
3727 
3728     /* get this TLB entry: */
3729     tlb = rmw.tme_m68k_rmw_tlbs[0];
3730 
3731     /* this TLB entry must allow fast reading and fast writing
3732        to the same memory: */
3733     assert (tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF
3734             && tlb->tme_m68k_tlb_emulator_off_write == tlb->tme_m68k_tlb_emulator_off_read);
3735 
3736     /* do the compare-and-exchange: */
3737     value_mem =
3738       tme_memory_atomic_cx32(((tme_shared tme_uint32_t *)
3739                                    (tlb->tme_m68k_tlb_emulator_off_read
3740                                     + ic->_tme_m68k_ea_address)),
3741                                   value_dc,
3742                                   value_du,
3743                                   tlb->tme_m68k_tlb_bus_rwlock,
3744                                   sizeof(tme_uint8_t));
3745     ic->tme_m68k_ireg_memx32 = tme_betoh_u32(value_mem);
3746   }
3747 
3748   /* compare the compare operand to the effective address operand: */
3749   tme_m68k_cmp32(ic, &ic->tme_m68k_ireg_uint32(ireg_dc), &ic->tme_m68k_ireg_memx32);
3750 
3751   /* if the comparison succeeded: */
3752   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
3753 
3754     /* write the update operand to the effective address operand: */
3755     ic->tme_m68k_ireg_memx32 = ic->tme_m68k_ireg_uint32(ireg_du);
3756   }
3757 
3758   /* otherwise, the comparison failed: */
3759   else {
3760 
3761     /* write the effective address operand to the compare operand: */
3762     ic->tme_m68k_ireg_uint32(ireg_dc) = ic->tme_m68k_ireg_memx32;
3763   }
3764 
3765   /* finish the read/modify/write cycle: */
3766   tme_m68k_rmw_finish(ic,
3767                       &rmw,
3768                       (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0);
3769   TME_M68K_INSN_OK;
3770 }
3771 
3772 /* cas2_32: */
TME_M68K_INSN(tme_m68k_cas2_32)3773 TME_M68K_INSN(tme_m68k_cas2_32)
3774 {
3775   struct tme_m68k_rmw rmw;
3776   int ireg_dcx, ireg_dux;
3777   int ireg_dcy, ireg_duy;
3778   const tme_uint16_t specopx = TME_M68K_INSN_SPECOP;
3779   const tme_uint16_t specopy = TME_M68K_INSN_OP0(tme_uint16_t);
3780 
3781   /* start the read/modify/write cycle: */
3782   ic->_tme_m68k_ea_function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
3783   rmw.tme_m68k_rmw_addresses[0] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0
3784                                                            + TME_FIELD_EXTRACTU(specopx, 12, 4));
3785   rmw.tme_m68k_rmw_addresses[1] = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0
3786                                                            + TME_FIELD_EXTRACTU(specopy, 12, 4));
3787   rmw.tme_m68k_rmw_address_count = 2;
3788   rmw.tme_m68k_rmw_size = sizeof(tme_uint32_t);
3789   if (tme_m68k_rmw_start(ic,
3790                          &rmw)) {
3791     TME_M68K_INSN_OK;
3792   }
3793 
3794   /* do the comparisons: */
3795   ireg_dcx = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 0, 3);
3796   ireg_dcy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 0, 3);
3797   tme_m68k_cmp32(ic,
3798                  &ic->tme_m68k_ireg_uint32(ireg_dcx),
3799                  &ic->tme_m68k_ireg_memx32);
3800   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
3801     tme_m68k_cmp32(ic,
3802                    &ic->tme_m68k_ireg_uint32(ireg_dcy),
3803                    &ic->tme_m68k_ireg_memy32);
3804   }
3805 
3806   /* if the comparisons succeeded: */
3807   if (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) {
3808 
3809     /* write the update operands to the effective address operands: */
3810     ireg_dux = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopx, 6, 3);
3811     ireg_duy = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(specopy, 6, 3);
3812     ic->tme_m68k_ireg_memx32 = ic->tme_m68k_ireg_uint32(ireg_dux);
3813     ic->tme_m68k_ireg_memy32 = ic->tme_m68k_ireg_uint32(ireg_duy);
3814   }
3815 
3816   /* otherwise, the comparisons failed: */
3817   else {
3818 
3819     /* write the effective address operands to the compare operands.
3820        "If Dc1 and Dc2 specify the same data register and the comparison
3821         fails, memory operand 1 is stored in the data register." */
3822     ic->tme_m68k_ireg_uint32(ireg_dcy) = ic->tme_m68k_ireg_memy32;
3823     ic->tme_m68k_ireg_uint32(ireg_dcx) = ic->tme_m68k_ireg_memx32;
3824   }
3825 
3826   /* finish the read/modify/write cycle: */
3827   tme_m68k_rmw_finish(ic,
3828                       &rmw,
3829                       (ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_Z) != 0);
3830   TME_M68K_INSN_OK;
3831 }
3832 
3833 /* moves32: */
TME_M68K_INSN(tme_m68k_moves32)3834 TME_M68K_INSN(tme_m68k_moves32)
3835 {
3836   int ireg;
3837   tme_uint32_t ireg_value;
3838   unsigned int ea_reg;
3839   unsigned int increment;
3840   TME_M68K_INSN_PRIV;
3841   TME_M68K_INSN_CANFAULT;
3842   ireg = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 4);
3843 
3844   /* in case we're storing the same address register used in a
3845      postincrement or predecrement EA, save the current value
3846      of the register now: */
3847   ireg_value = ic->tme_m68k_ireg_uint32(ireg);
3848 
3849   /* we have to handle postincrement and predecrement ourselves: */
3850   if (!TME_M68K_SEQUENCE_RESTARTING) {
3851     ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
3852     increment = TME_M68K_SIZE_32;
3853     if (increment == TME_M68K_SIZE_8 && ea_reg == TME_M68K_IREG_A7) {
3854       increment = TME_M68K_SIZE_16;
3855     }
3856     switch (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3)) {
3857     case 3: ic->tme_m68k_ireg_uint32(ea_reg) += increment; break;
3858     case 4: ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(ea_reg) -= increment); break;
3859     default: break;
3860     }
3861   }
3862 
3863   if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {
3864     if (!TME_M68K_SEQUENCE_RESTARTING) {
3865       ic->tme_m68k_ireg_memx32 = ireg_value;
3866       ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_dfc;
3867     }
3868     tme_m68k_write_memx32(ic);
3869   }
3870   else {
3871     if (!TME_M68K_SEQUENCE_RESTARTING) {
3872       ic->_tme_m68k_ea_function_code = ic->tme_m68k_ireg_sfc;
3873     }
3874     tme_m68k_read_memx32(ic);
3875     ic->tme_m68k_ireg_uint32(ireg) = ic->tme_m68k_ireg_memx32;
3876   }
3877   TME_M68K_INSN_OK;
3878 }
3879 
3880 /* this reads a 8-bit memx value: */
3881 void
tme_m68k_read_memx8(struct tme_m68k * ic)3882 tme_m68k_read_memx8(struct tme_m68k *ic)
3883 {
3884   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
3885   unsigned int function_code = ic->_tme_m68k_ea_function_code;
3886   tme_uint32_t linear_address = ic->_tme_m68k_ea_address;
3887   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address);
3888   tme_uint8_t mem_value;
3889   const tme_shared tme_uint8_t *mem;
3890 
3891 #ifdef _TME_M68K_STATS
3892   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
3893 #endif /* _TME_M68K_STATS */
3894 
3895   /* busy this TLB entry: */
3896   tme_m68k_tlb_busy(tlb);
3897 
3898   /* if we aren't restarting, and this address is properly aligned,
3899      and this TLB entry covers the operand and allows fast reads: */
3900   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
3901                          && tme_m68k_tlb_is_valid(tlb)
3902                          && tlb->tme_m68k_tlb_bus_context == bus_context
3903                          && (tlb->tme_m68k_tlb_function_codes_mask
3904                              & TME_BIT(function_code))
3905                          && linear_address >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
3906                          && linear_address <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
3907                          && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
3908 
3909     /* make the emulator memory pointer: */
3910     mem = (const tme_shared tme_uint8_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address);
3911 
3912     /* do the 8-bit bus read: */
3913     mem_value = tme_memory_bus_read8(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
3914 
3915     /* put the value read: */
3916     ic->tme_m68k_ireg_memx8 = mem_value;
3917 
3918     /* step the transfer count: */
3919     TME_M68K_SEQUENCE_TRANSFER_STEP;
3920   }
3921 
3922   /* otherwise, do the bus cycles the slow way: */
3923   else {
3924     tme_m68k_read8(ic, tlb,
3925                     &ic->_tme_m68k_ea_function_code,
3926                     &ic->_tme_m68k_ea_address,
3927                     &ic->tme_m68k_ireg_memx8,
3928                     TME_M68K_BUS_CYCLE_NORMAL);
3929   }
3930 
3931   /* unbusy this TLB entry: */
3932   tme_m68k_tlb_unbusy(tlb);
3933 
3934   /* log the value read: */
3935   tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx8, TME_BUS_CYCLE_READ);
3936   tme_m68k_log(ic, 1000, TME_OK,
3937                (TME_M68K_LOG_HANDLE(ic),
3938                 _("read_memx8	%d:0x%08x:	0x%02x"),
3939                 ic->_tme_m68k_ea_function_code,
3940                 ic->_tme_m68k_ea_address,
3941                 ic->tme_m68k_ireg_memx8));
3942 }
3943 
3944 /* this reads a 8-bit mem value: */
3945 void
tme_m68k_read_mem8(struct tme_m68k * ic,int ireg)3946 tme_m68k_read_mem8(struct tme_m68k *ic, int ireg)
3947 {
3948   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
3949   unsigned int function_code = ic->_tme_m68k_ea_function_code;
3950   tme_uint32_t linear_address = ic->_tme_m68k_ea_address;
3951   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address);
3952   tme_uint8_t mem_value;
3953   const tme_shared tme_uint8_t *mem;
3954 
3955 #ifdef _TME_M68K_STATS
3956   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
3957 #endif /* _TME_M68K_STATS */
3958 
3959   /* busy this TLB entry: */
3960   tme_m68k_tlb_busy(tlb);
3961 
3962   /* if we aren't restarting, and this address is properly aligned,
3963      and this TLB entry covers the operand and allows fast reads: */
3964   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
3965                          && tme_m68k_tlb_is_valid(tlb)
3966                          && tlb->tme_m68k_tlb_bus_context == bus_context
3967                          && (tlb->tme_m68k_tlb_function_codes_mask
3968                              & TME_BIT(function_code))
3969                          && linear_address >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
3970                          && linear_address <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
3971                          && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
3972 
3973     /* make the emulator memory pointer: */
3974     mem = (const tme_shared tme_uint8_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address);
3975 
3976     /* do the 8-bit bus read: */
3977     mem_value = tme_memory_bus_read8(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
3978 
3979     /* put the value read: */
3980     ic->tme_m68k_ireg_uint8(ireg) = mem_value;
3981 
3982     /* step the transfer count: */
3983     TME_M68K_SEQUENCE_TRANSFER_STEP;
3984   }
3985 
3986   /* otherwise, do the bus cycles the slow way: */
3987   else {
3988     tme_m68k_read8(ic, tlb,
3989                     &ic->_tme_m68k_ea_function_code,
3990                     &ic->_tme_m68k_ea_address,
3991                     &ic->tme_m68k_ireg_uint8(ireg),
3992                     TME_M68K_BUS_CYCLE_NORMAL);
3993   }
3994 
3995   /* unbusy this TLB entry: */
3996   tme_m68k_tlb_unbusy(tlb);
3997 
3998   /* log the value read: */
3999   tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint8(ireg), TME_BUS_CYCLE_READ);
4000   tme_m68k_log(ic, 1000, TME_OK,
4001                (TME_M68K_LOG_HANDLE(ic),
4002                 _("read_mem8	%d:0x%08x:	0x%02x"),
4003                 ic->_tme_m68k_ea_function_code,
4004                 ic->_tme_m68k_ea_address,
4005                 ic->tme_m68k_ireg_uint8(ireg)));
4006 }
4007 
4008 /* this writes a 8-bit memx value: */
4009 void
tme_m68k_write_memx8(struct tme_m68k * ic)4010 tme_m68k_write_memx8(struct tme_m68k *ic)
4011 {
4012   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4013   unsigned int function_code = ic->_tme_m68k_ea_function_code;
4014   tme_uint32_t linear_address = ic->_tme_m68k_ea_address;
4015   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address);
4016   tme_uint8_t mem_value;
4017   tme_shared tme_uint8_t *mem;
4018 
4019 #ifdef _TME_M68K_STATS
4020   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4021 #endif /* _TME_M68K_STATS */
4022 
4023   /* log the value written: */
4024   tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx8, TME_BUS_CYCLE_WRITE);
4025   tme_m68k_log(ic, 1000, TME_OK,
4026                (TME_M68K_LOG_HANDLE(ic),
4027                 _("write_memx8	%d:0x%08x:	0x%02x"),
4028                 ic->_tme_m68k_ea_function_code,
4029                 ic->_tme_m68k_ea_address,
4030                 ic->tme_m68k_ireg_memx8));
4031 
4032   /* busy this TLB entry: */
4033   tme_m68k_tlb_busy(tlb);
4034 
4035   /* if we aren't restarting, and this address is properly aligned,
4036      and this TLB entry covers the operand and allows fast writes: */
4037   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4038                          && tme_m68k_tlb_is_valid(tlb)
4039                          && tlb->tme_m68k_tlb_bus_context == bus_context
4040                          && (tlb->tme_m68k_tlb_function_codes_mask
4041                              & TME_BIT(function_code))
4042                          && linear_address >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4043                          && linear_address <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4044                          && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) {
4045 
4046     /* make the emulator memory pointer: */
4047     mem = (tme_shared tme_uint8_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address);
4048 
4049     /* get the value to write: */
4050     mem_value = ic->tme_m68k_ireg_memx8;
4051 
4052     /* do the 8-bit bus write: */
4053     tme_memory_bus_write8(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4054 
4055     /* step the transfer count: */
4056     TME_M68K_SEQUENCE_TRANSFER_STEP;
4057   }
4058 
4059   /* otherwise, do the bus cycles the slow way: */
4060   else {
4061     tme_m68k_write8(ic, tlb,
4062                     &ic->_tme_m68k_ea_function_code,
4063                     &ic->_tme_m68k_ea_address,
4064                     &ic->tme_m68k_ireg_memx8,
4065                     TME_M68K_BUS_CYCLE_NORMAL);
4066   }
4067 
4068   /* unbusy this TLB entry: */
4069   tme_m68k_tlb_unbusy(tlb);
4070 }
4071 
4072 /* this writes a 8-bit mem value: */
4073 void
tme_m68k_write_mem8(struct tme_m68k * ic,int ireg)4074 tme_m68k_write_mem8(struct tme_m68k *ic, int ireg)
4075 {
4076   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4077   unsigned int function_code = ic->_tme_m68k_ea_function_code;
4078   tme_uint32_t linear_address = ic->_tme_m68k_ea_address;
4079   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address);
4080   tme_uint8_t mem_value;
4081   tme_shared tme_uint8_t *mem;
4082 
4083 #ifdef _TME_M68K_STATS
4084   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4085 #endif /* _TME_M68K_STATS */
4086 
4087   /* log the value written: */
4088   tme_m68k_verify_mem8(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint8(ireg), TME_BUS_CYCLE_WRITE);
4089   tme_m68k_log(ic, 1000, TME_OK,
4090                (TME_M68K_LOG_HANDLE(ic),
4091                 _("write_mem8	%d:0x%08x:	0x%02x"),
4092                 ic->_tme_m68k_ea_function_code,
4093                 ic->_tme_m68k_ea_address,
4094                 ic->tme_m68k_ireg_uint8(ireg)));
4095 
4096   /* busy this TLB entry: */
4097   tme_m68k_tlb_busy(tlb);
4098 
4099   /* if we aren't restarting, and this address is properly aligned,
4100      and this TLB entry covers the operand and allows fast writes: */
4101   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4102                          && tme_m68k_tlb_is_valid(tlb)
4103                          && tlb->tme_m68k_tlb_bus_context == bus_context
4104                          && (tlb->tme_m68k_tlb_function_codes_mask
4105                              & TME_BIT(function_code))
4106                          && linear_address >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4107                          && linear_address <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4108                          && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) {
4109 
4110     /* make the emulator memory pointer: */
4111     mem = (tme_shared tme_uint8_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address);
4112 
4113     /* get the value to write: */
4114     mem_value = ic->tme_m68k_ireg_uint8(ireg);
4115 
4116     /* do the 8-bit bus write: */
4117     tme_memory_bus_write8(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4118 
4119     /* step the transfer count: */
4120     TME_M68K_SEQUENCE_TRANSFER_STEP;
4121   }
4122 
4123   /* otherwise, do the bus cycles the slow way: */
4124   else {
4125     tme_m68k_write8(ic, tlb,
4126                     &ic->_tme_m68k_ea_function_code,
4127                     &ic->_tme_m68k_ea_address,
4128                     &ic->tme_m68k_ireg_uint8(ireg),
4129                     TME_M68K_BUS_CYCLE_NORMAL);
4130   }
4131 
4132   /* unbusy this TLB entry: */
4133   tme_m68k_tlb_unbusy(tlb);
4134 }
4135 
4136 /* this reads a 16-bit memx value: */
4137 void
tme_m68k_read_memx16(struct tme_m68k * ic)4138 tme_m68k_read_memx16(struct tme_m68k *ic)
4139 {
4140   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4141   unsigned int function_code = ic->_tme_m68k_ea_function_code;
4142   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
4143   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1;
4144   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
4145   tme_uint16_t mem_value;
4146   const tme_shared tme_uint16_t *mem;
4147 
4148 #ifdef _TME_M68K_STATS
4149   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4150 #endif /* _TME_M68K_STATS */
4151 
4152   /* busy this TLB entry: */
4153   tme_m68k_tlb_busy(tlb);
4154 
4155   /* if we aren't restarting, and this address is properly aligned,
4156      and this TLB entry covers the operand and allows fast reads: */
4157   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4158                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
4159                          && tme_m68k_tlb_is_valid(tlb)
4160                          && tlb->tme_m68k_tlb_bus_context == bus_context
4161                          && (tlb->tme_m68k_tlb_function_codes_mask
4162                              & TME_BIT(function_code))
4163                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4164                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4165                          && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
4166 
4167     /* make the emulator memory pointer: */
4168     mem = (const tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first);
4169 
4170     /* do the 16-bit bus read: */
4171     mem_value = tme_memory_bus_read16(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4172 
4173     /* put the value read, in host byte order: */
4174     ic->tme_m68k_ireg_memx16 = tme_betoh_u16(mem_value);
4175 
4176     /* step the transfer count: */
4177     TME_M68K_SEQUENCE_TRANSFER_STEP;
4178   }
4179 
4180   /* otherwise, do the bus cycles the slow way: */
4181   else {
4182     tme_m68k_read16(ic, tlb,
4183                     &ic->_tme_m68k_ea_function_code,
4184                     &ic->_tme_m68k_ea_address,
4185                     &ic->tme_m68k_ireg_memx16,
4186                     TME_M68K_BUS_CYCLE_NORMAL);
4187   }
4188 
4189   /* unbusy this TLB entry: */
4190   tme_m68k_tlb_unbusy(tlb);
4191 
4192   /* log the value read: */
4193   tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx16, TME_BUS_CYCLE_READ);
4194   tme_m68k_log(ic, 1000, TME_OK,
4195                (TME_M68K_LOG_HANDLE(ic),
4196                 _("read_memx16	%d:0x%08x:	0x%04x"),
4197                 ic->_tme_m68k_ea_function_code,
4198                 ic->_tme_m68k_ea_address,
4199                 ic->tme_m68k_ireg_memx16));
4200 }
4201 
4202 /* this reads a 16-bit mem value: */
4203 void
tme_m68k_read_mem16(struct tme_m68k * ic,int ireg)4204 tme_m68k_read_mem16(struct tme_m68k *ic, int ireg)
4205 {
4206   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4207   unsigned int function_code = ic->_tme_m68k_ea_function_code;
4208   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
4209   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1;
4210   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
4211   tme_uint16_t mem_value;
4212   const tme_shared tme_uint16_t *mem;
4213 
4214 #ifdef _TME_M68K_STATS
4215   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4216 #endif /* _TME_M68K_STATS */
4217 
4218   /* busy this TLB entry: */
4219   tme_m68k_tlb_busy(tlb);
4220 
4221   /* if we aren't restarting, and this address is properly aligned,
4222      and this TLB entry covers the operand and allows fast reads: */
4223   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4224                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
4225                          && tme_m68k_tlb_is_valid(tlb)
4226                          && tlb->tme_m68k_tlb_bus_context == bus_context
4227                          && (tlb->tme_m68k_tlb_function_codes_mask
4228                              & TME_BIT(function_code))
4229                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4230                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4231                          && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
4232 
4233     /* make the emulator memory pointer: */
4234     mem = (const tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first);
4235 
4236     /* do the 16-bit bus read: */
4237     mem_value = tme_memory_bus_read16(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4238 
4239     /* put the value read, in host byte order: */
4240     ic->tme_m68k_ireg_uint16(ireg) = tme_betoh_u16(mem_value);
4241 
4242     /* step the transfer count: */
4243     TME_M68K_SEQUENCE_TRANSFER_STEP;
4244   }
4245 
4246   /* otherwise, do the bus cycles the slow way: */
4247   else {
4248     tme_m68k_read16(ic, tlb,
4249                     &ic->_tme_m68k_ea_function_code,
4250                     &ic->_tme_m68k_ea_address,
4251                     &ic->tme_m68k_ireg_uint16(ireg),
4252                     TME_M68K_BUS_CYCLE_NORMAL);
4253   }
4254 
4255   /* unbusy this TLB entry: */
4256   tme_m68k_tlb_unbusy(tlb);
4257 
4258   /* log the value read: */
4259   tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint16(ireg), TME_BUS_CYCLE_READ);
4260   tme_m68k_log(ic, 1000, TME_OK,
4261                (TME_M68K_LOG_HANDLE(ic),
4262                 _("read_mem16	%d:0x%08x:	0x%04x"),
4263                 ic->_tme_m68k_ea_function_code,
4264                 ic->_tme_m68k_ea_address,
4265                 ic->tme_m68k_ireg_uint16(ireg)));
4266 }
4267 
4268 /* this reads a 16-bit inst value: */
4269 tme_uint16_t
tme_m68k_fetch16(struct tme_m68k * ic,tme_uint32_t pc)4270 tme_m68k_fetch16(struct tme_m68k *ic, tme_uint32_t pc)
4271 {
4272   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4273   unsigned int function_code = TME_M68K_FUNCTION_CODE_PROGRAM(ic);
4274   tme_uint32_t linear_address_first = pc;
4275   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1;
4276   struct tme_m68k_tlb *tlb = &ic->_tme_m68k_itlb;
4277   tme_uint16_t mem_value;
4278   const tme_shared tme_uint16_t *mem;
4279   unsigned int fetch_slow_next = ic->_tme_m68k_insn_fetch_slow_next;
4280 
4281 #ifdef _TME_M68K_STATS
4282   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4283 #endif /* _TME_M68K_STATS */
4284 
4285   /* busy this TLB entry: */
4286   tme_m68k_tlb_busy(tlb);
4287 
4288   /* if this fetch was done by the fast executor: */
4289   if (__tme_predict_true(fetch_slow_next < ic->_tme_m68k_insn_fetch_slow_count_fast)) {
4290 
4291     /* the entire fetch must be in the instruction buffer, and
4292        we must be restarting: */
4293     assert ((fetch_slow_next + sizeof(tme_uint16_t))
4294             <= ic->_tme_m68k_insn_fetch_slow_count_fast);
4295     assert (TME_M68K_SEQUENCE_RESTARTING);
4296     mem_value = tme_memory_read16(((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), sizeof(tme_uint16_t));
4297   }
4298 
4299   /* otherwise, this fetch was not done by the fast executor: */
4300   else {
4301 
4302     /* if we're restarting, but the offset in the instruction buffer
4303        to fetch into is at the instruction buffer total, this must be
4304        a fake fault caused by the fast executor.  we confirm this by
4305        checking that this transfer "caused" the fault, and that this
4306        transfer will be the first slow one after any fast fetches.
4307        in this case, we can cancel the restart for now: */
4308     if (TME_M68K_SEQUENCE_RESTARTING
4309         && (fetch_slow_next
4310             == ic->_tme_m68k_insn_fetch_slow_count_total)) {
4311       assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next
4312                == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted)
4313               && (fetch_slow_next
4314                   == ic->_tme_m68k_insn_fetch_slow_count_fast));
4315       ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted--;
4316     }
4317 
4318     /* if we're not restarting: */
4319     if (!TME_M68K_SEQUENCE_RESTARTING) {
4320 
4321       /* we advance the instruction buffer total *before* we do
4322          what may be a slow fetch, because we may transfer a few
4323          bytes and then fault.  without this, those few bytes
4324          would not get saved in the exception stack frame and
4325          restored later before the continuation of the fetch: */
4326       ic->_tme_m68k_insn_fetch_slow_count_total += sizeof(tme_uint16_t);
4327     }
4328 
4329     /* make sure that if this is a new transfer or if this
4330        transfer faulted, that we're fetching for the current
4331        last positions in the instruction buffer: */
4332     assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next
4333              < ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted)
4334             || ((fetch_slow_next + sizeof(tme_uint16_t))
4335                 == ic->_tme_m68k_insn_fetch_slow_count_total));
4336 
4337     /* if we aren't restarting, and this address is properly aligned,
4338        and this TLB entry covers the operand and allows fast reads: */
4339     if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4340                            && ((sizeof(tme_uint16_t) - 1) & linear_address_first) == 0
4341                            && tme_m68k_tlb_is_valid(tlb)
4342                            && tlb->tme_m68k_tlb_bus_context == bus_context
4343                            && (tlb->tme_m68k_tlb_function_codes_mask
4344                                & TME_BIT(function_code))
4345                            && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4346                            && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4347                            && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
4348 
4349       /* make the emulator memory pointer: */
4350       mem = (const tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first);
4351 
4352       /* do the 16-bit bus read: */
4353       mem_value = tme_memory_bus_read16(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint16_t), sizeof(tme_uint32_t));
4354 
4355       /* put the value read, in host byte order: */
4356       mem_value = tme_betoh_u16(mem_value);
4357       tme_memory_write16(((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), mem_value, sizeof(tme_uint16_t));
4358 
4359       /* step the transfer count: */
4360       TME_M68K_SEQUENCE_TRANSFER_STEP;
4361     }
4362 
4363     /* otherwise, do the bus cycles the slow way: */
4364     else {
4365       tme_m68k_read16(ic, tlb,
4366                       &function_code,
4367                       &pc,
4368                       ((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)),
4369                       TME_M68K_BUS_CYCLE_FETCH);
4370       mem_value = tme_memory_read16(((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), sizeof(tme_uint16_t));
4371     }
4372   }
4373 
4374   /* unbusy this TLB entry: */
4375   tme_m68k_tlb_unbusy(tlb);
4376 
4377   /* log the value read: */
4378   tme_m68k_verify_mem16(ic, function_code, pc, *((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), TME_BUS_CYCLE_READ);
4379   tme_m68k_log(ic, 1000, TME_OK,
4380                (TME_M68K_LOG_HANDLE(ic),
4381                 _("fetch16	%d:0x%08x:	0x%04x"),
4382                 function_code,
4383                 pc,
4384                 *((tme_uint16_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next))));
4385 
4386   /* advance the offset in the instruction buffer for the next slow fetch: */
4387   fetch_slow_next += sizeof(tme_uint16_t);
4388   ic->_tme_m68k_insn_fetch_slow_next = fetch_slow_next;
4389 
4390   /* return the fetched value: */
4391   return(mem_value);
4392 }
4393 
4394 /* this reads a 16-bit stack value: */
4395 void
tme_m68k_pop16(struct tme_m68k * ic,tme_uint16_t * _value)4396 tme_m68k_pop16(struct tme_m68k *ic, tme_uint16_t *_value)
4397 {
4398   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4399   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
4400   tme_uint32_t linear_address_first = ic->tme_m68k_ireg_a7;
4401   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1;
4402   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
4403   tme_uint16_t mem_value;
4404   const tme_shared tme_uint16_t *mem;
4405 
4406 #ifdef _TME_M68K_STATS
4407   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4408 #endif /* _TME_M68K_STATS */
4409 
4410   /* busy this TLB entry: */
4411   tme_m68k_tlb_busy(tlb);
4412 
4413   /* if we aren't restarting, and this address is properly aligned,
4414      and this TLB entry covers the operand and allows fast reads: */
4415   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4416                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
4417                          && tme_m68k_tlb_is_valid(tlb)
4418                          && tlb->tme_m68k_tlb_bus_context == bus_context
4419                          && (tlb->tme_m68k_tlb_function_codes_mask
4420                              & TME_BIT(function_code))
4421                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4422                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4423                          && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
4424 
4425     /* make the emulator memory pointer: */
4426     mem = (const tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first);
4427 
4428     /* do the 16-bit bus read: */
4429     mem_value = tme_memory_bus_read16(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4430 
4431     /* put the value read, in host byte order: */
4432     *_value = tme_betoh_u16(mem_value);
4433 
4434     /* step the transfer count: */
4435     TME_M68K_SEQUENCE_TRANSFER_STEP;
4436   }
4437 
4438   /* otherwise, do the bus cycles the slow way: */
4439   else {
4440     tme_m68k_read16(ic, tlb,
4441                     &function_code,
4442                     &ic->tme_m68k_ireg_a7,
4443                     _value,
4444                     TME_M68K_BUS_CYCLE_NORMAL);
4445   }
4446 
4447   /* unbusy this TLB entry: */
4448   tme_m68k_tlb_unbusy(tlb);
4449 
4450   /* log the value read: */
4451   tme_m68k_verify_mem16(ic, function_code, ic->tme_m68k_ireg_a7, *_value, TME_BUS_CYCLE_READ);
4452   tme_m68k_log(ic, 1000, TME_OK,
4453                (TME_M68K_LOG_HANDLE(ic),
4454                 _("pop16	%d:0x%08x:	0x%04x"),
4455                 function_code,
4456                 ic->tme_m68k_ireg_a7,
4457                 *_value));
4458   if (!TME_M68K_SEQUENCE_RESTARTING) {
4459     ic->tme_m68k_ireg_a7 += sizeof(tme_uint16_t);
4460   }
4461 }
4462 
4463 /* this writes a 16-bit memx value: */
4464 void
tme_m68k_write_memx16(struct tme_m68k * ic)4465 tme_m68k_write_memx16(struct tme_m68k *ic)
4466 {
4467   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4468   unsigned int function_code = ic->_tme_m68k_ea_function_code;
4469   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
4470   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1;
4471   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
4472   tme_uint16_t mem_value;
4473   tme_shared tme_uint16_t *mem;
4474 
4475 #ifdef _TME_M68K_STATS
4476   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4477 #endif /* _TME_M68K_STATS */
4478 
4479   /* log the value written: */
4480   tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx16, TME_BUS_CYCLE_WRITE);
4481   tme_m68k_log(ic, 1000, TME_OK,
4482                (TME_M68K_LOG_HANDLE(ic),
4483                 _("write_memx16	%d:0x%08x:	0x%04x"),
4484                 ic->_tme_m68k_ea_function_code,
4485                 ic->_tme_m68k_ea_address,
4486                 ic->tme_m68k_ireg_memx16));
4487 
4488   /* busy this TLB entry: */
4489   tme_m68k_tlb_busy(tlb);
4490 
4491   /* if we aren't restarting, and this address is properly aligned,
4492      and this TLB entry covers the operand and allows fast writes: */
4493   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4494                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
4495                          && tme_m68k_tlb_is_valid(tlb)
4496                          && tlb->tme_m68k_tlb_bus_context == bus_context
4497                          && (tlb->tme_m68k_tlb_function_codes_mask
4498                              & TME_BIT(function_code))
4499                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4500                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4501                          && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) {
4502 
4503     /* make the emulator memory pointer: */
4504     mem = (tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first);
4505 
4506     /* get the value to write, in big-endian byte order: */
4507     mem_value = tme_htobe_u16(ic->tme_m68k_ireg_memx16);
4508 
4509     /* do the 16-bit bus write: */
4510     tme_memory_bus_write16(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4511 
4512     /* step the transfer count: */
4513     TME_M68K_SEQUENCE_TRANSFER_STEP;
4514   }
4515 
4516   /* otherwise, do the bus cycles the slow way: */
4517   else {
4518     tme_m68k_write16(ic, tlb,
4519                     &ic->_tme_m68k_ea_function_code,
4520                     &ic->_tme_m68k_ea_address,
4521                     &ic->tme_m68k_ireg_memx16,
4522                     TME_M68K_BUS_CYCLE_NORMAL);
4523   }
4524 
4525   /* unbusy this TLB entry: */
4526   tme_m68k_tlb_unbusy(tlb);
4527 }
4528 
4529 /* this writes a 16-bit mem value: */
4530 void
tme_m68k_write_mem16(struct tme_m68k * ic,int ireg)4531 tme_m68k_write_mem16(struct tme_m68k *ic, int ireg)
4532 {
4533   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4534   unsigned int function_code = ic->_tme_m68k_ea_function_code;
4535   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
4536   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1;
4537   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
4538   tme_uint16_t mem_value;
4539   tme_shared tme_uint16_t *mem;
4540 
4541 #ifdef _TME_M68K_STATS
4542   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4543 #endif /* _TME_M68K_STATS */
4544 
4545   /* log the value written: */
4546   tme_m68k_verify_mem16(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint16(ireg), TME_BUS_CYCLE_WRITE);
4547   tme_m68k_log(ic, 1000, TME_OK,
4548                (TME_M68K_LOG_HANDLE(ic),
4549                 _("write_mem16	%d:0x%08x:	0x%04x"),
4550                 ic->_tme_m68k_ea_function_code,
4551                 ic->_tme_m68k_ea_address,
4552                 ic->tme_m68k_ireg_uint16(ireg)));
4553 
4554   /* busy this TLB entry: */
4555   tme_m68k_tlb_busy(tlb);
4556 
4557   /* if we aren't restarting, and this address is properly aligned,
4558      and this TLB entry covers the operand and allows fast writes: */
4559   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4560                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
4561                          && tme_m68k_tlb_is_valid(tlb)
4562                          && tlb->tme_m68k_tlb_bus_context == bus_context
4563                          && (tlb->tme_m68k_tlb_function_codes_mask
4564                              & TME_BIT(function_code))
4565                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4566                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4567                          && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) {
4568 
4569     /* make the emulator memory pointer: */
4570     mem = (tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first);
4571 
4572     /* get the value to write, in big-endian byte order: */
4573     mem_value = tme_htobe_u16(ic->tme_m68k_ireg_uint16(ireg));
4574 
4575     /* do the 16-bit bus write: */
4576     tme_memory_bus_write16(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4577 
4578     /* step the transfer count: */
4579     TME_M68K_SEQUENCE_TRANSFER_STEP;
4580   }
4581 
4582   /* otherwise, do the bus cycles the slow way: */
4583   else {
4584     tme_m68k_write16(ic, tlb,
4585                     &ic->_tme_m68k_ea_function_code,
4586                     &ic->_tme_m68k_ea_address,
4587                     &ic->tme_m68k_ireg_uint16(ireg),
4588                     TME_M68K_BUS_CYCLE_NORMAL);
4589   }
4590 
4591   /* unbusy this TLB entry: */
4592   tme_m68k_tlb_unbusy(tlb);
4593 }
4594 
4595 /* this writes a 16-bit stack value: */
4596 void
tme_m68k_push16(struct tme_m68k * ic,tme_uint16_t value)4597 tme_m68k_push16(struct tme_m68k *ic, tme_uint16_t value)
4598 {
4599   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4600   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
4601   tme_uint32_t linear_address_first = ic->tme_m68k_ireg_a7 - sizeof(tme_uint16_t);
4602   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint16_t) - 1;
4603   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
4604   tme_uint16_t mem_value;
4605   tme_shared tme_uint16_t *mem;
4606 
4607 #ifdef _TME_M68K_STATS
4608   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4609 #endif /* _TME_M68K_STATS */
4610 
4611   /* log the value written: */
4612   tme_m68k_verify_mem16(ic, function_code, linear_address_first, value, TME_BUS_CYCLE_WRITE);
4613   tme_m68k_log(ic, 1000, TME_OK,
4614                (TME_M68K_LOG_HANDLE(ic),
4615                 _("push16	%d:0x%08x:	0x%04x"),
4616                 function_code,
4617                 linear_address_first,
4618                 value));
4619 
4620   /* busy this TLB entry: */
4621   tme_m68k_tlb_busy(tlb);
4622 
4623   /* if we aren't restarting, and this address is properly aligned,
4624      and this TLB entry covers the operand and allows fast writes: */
4625   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4626                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
4627                          && tme_m68k_tlb_is_valid(tlb)
4628                          && tlb->tme_m68k_tlb_bus_context == bus_context
4629                          && (tlb->tme_m68k_tlb_function_codes_mask
4630                              & TME_BIT(function_code))
4631                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4632                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4633                          && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) {
4634 
4635     /* make the emulator memory pointer: */
4636     mem = (tme_shared tme_uint16_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first);
4637 
4638     /* get the value to write, in big-endian byte order: */
4639     mem_value = tme_htobe_u16(value);
4640 
4641     /* do the 16-bit bus write: */
4642     tme_memory_bus_write16(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4643 
4644     /* step the transfer count: */
4645     TME_M68K_SEQUENCE_TRANSFER_STEP;
4646   }
4647 
4648   /* otherwise, do the bus cycles the slow way: */
4649   else {
4650     tme_m68k_write16(ic, tlb,
4651                     &function_code,
4652                     &linear_address_first,
4653                     &value,
4654                     TME_M68K_BUS_CYCLE_NORMAL);
4655   }
4656 
4657   /* unbusy this TLB entry: */
4658   tme_m68k_tlb_unbusy(tlb);
4659   if (!TME_M68K_SEQUENCE_RESTARTING) {
4660     ic->tme_m68k_ireg_a7 -= sizeof(tme_uint16_t);
4661   }
4662 }
4663 
4664 /* this reads a 32-bit memx value: */
4665 void
tme_m68k_read_memx32(struct tme_m68k * ic)4666 tme_m68k_read_memx32(struct tme_m68k *ic)
4667 {
4668   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4669   unsigned int function_code = ic->_tme_m68k_ea_function_code;
4670   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
4671   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1;
4672   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
4673   tme_uint32_t mem_value;
4674   const tme_shared tme_uint32_t *mem;
4675 
4676 #ifdef _TME_M68K_STATS
4677   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4678 #endif /* _TME_M68K_STATS */
4679 
4680   /* busy this TLB entry: */
4681   tme_m68k_tlb_busy(tlb);
4682 
4683   /* if we aren't restarting, and this address is properly aligned,
4684      and this TLB entry covers the operand and allows fast reads: */
4685   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4686                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
4687                          && tme_m68k_tlb_is_valid(tlb)
4688                          && tlb->tme_m68k_tlb_bus_context == bus_context
4689                          && (tlb->tme_m68k_tlb_function_codes_mask
4690                              & TME_BIT(function_code))
4691                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4692                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4693                          && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
4694 
4695     /* make the emulator memory pointer: */
4696     mem = (const tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first);
4697 
4698     /* do the 32-bit bus read: */
4699     mem_value = tme_memory_bus_read32(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4700 
4701     /* put the value read, in host byte order: */
4702     ic->tme_m68k_ireg_memx32 = tme_betoh_u32(mem_value);
4703 
4704     /* step the transfer count: */
4705     TME_M68K_SEQUENCE_TRANSFER_STEP;
4706   }
4707 
4708   /* otherwise, do the bus cycles the slow way: */
4709   else {
4710     tme_m68k_read32(ic, tlb,
4711                     &ic->_tme_m68k_ea_function_code,
4712                     &ic->_tme_m68k_ea_address,
4713                     &ic->tme_m68k_ireg_memx32,
4714                     TME_M68K_BUS_CYCLE_NORMAL);
4715   }
4716 
4717   /* unbusy this TLB entry: */
4718   tme_m68k_tlb_unbusy(tlb);
4719 
4720   /* log the value read: */
4721   tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx32, TME_BUS_CYCLE_READ);
4722   tme_m68k_log(ic, 1000, TME_OK,
4723                (TME_M68K_LOG_HANDLE(ic),
4724                 _("read_memx32	%d:0x%08x:	0x%08x"),
4725                 ic->_tme_m68k_ea_function_code,
4726                 ic->_tme_m68k_ea_address,
4727                 ic->tme_m68k_ireg_memx32));
4728 }
4729 
4730 /* this reads a 32-bit mem value: */
4731 void
tme_m68k_read_mem32(struct tme_m68k * ic,int ireg)4732 tme_m68k_read_mem32(struct tme_m68k *ic, int ireg)
4733 {
4734   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4735   unsigned int function_code = ic->_tme_m68k_ea_function_code;
4736   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
4737   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1;
4738   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
4739   tme_uint32_t mem_value;
4740   const tme_shared tme_uint32_t *mem;
4741 
4742 #ifdef _TME_M68K_STATS
4743   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4744 #endif /* _TME_M68K_STATS */
4745 
4746   /* busy this TLB entry: */
4747   tme_m68k_tlb_busy(tlb);
4748 
4749   /* if we aren't restarting, and this address is properly aligned,
4750      and this TLB entry covers the operand and allows fast reads: */
4751   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4752                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
4753                          && tme_m68k_tlb_is_valid(tlb)
4754                          && tlb->tme_m68k_tlb_bus_context == bus_context
4755                          && (tlb->tme_m68k_tlb_function_codes_mask
4756                              & TME_BIT(function_code))
4757                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4758                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4759                          && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
4760 
4761     /* make the emulator memory pointer: */
4762     mem = (const tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first);
4763 
4764     /* do the 32-bit bus read: */
4765     mem_value = tme_memory_bus_read32(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4766 
4767     /* put the value read, in host byte order: */
4768     ic->tme_m68k_ireg_uint32(ireg) = tme_betoh_u32(mem_value);
4769 
4770     /* step the transfer count: */
4771     TME_M68K_SEQUENCE_TRANSFER_STEP;
4772   }
4773 
4774   /* otherwise, do the bus cycles the slow way: */
4775   else {
4776     tme_m68k_read32(ic, tlb,
4777                     &ic->_tme_m68k_ea_function_code,
4778                     &ic->_tme_m68k_ea_address,
4779                     &ic->tme_m68k_ireg_uint32(ireg),
4780                     TME_M68K_BUS_CYCLE_NORMAL);
4781   }
4782 
4783   /* unbusy this TLB entry: */
4784   tme_m68k_tlb_unbusy(tlb);
4785 
4786   /* log the value read: */
4787   tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint32(ireg), TME_BUS_CYCLE_READ);
4788   tme_m68k_log(ic, 1000, TME_OK,
4789                (TME_M68K_LOG_HANDLE(ic),
4790                 _("read_mem32	%d:0x%08x:	0x%08x"),
4791                 ic->_tme_m68k_ea_function_code,
4792                 ic->_tme_m68k_ea_address,
4793                 ic->tme_m68k_ireg_uint32(ireg)));
4794 }
4795 
4796 /* this reads a 32-bit inst value: */
4797 tme_uint32_t
tme_m68k_fetch32(struct tme_m68k * ic,tme_uint32_t pc)4798 tme_m68k_fetch32(struct tme_m68k *ic, tme_uint32_t pc)
4799 {
4800   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4801   unsigned int function_code = TME_M68K_FUNCTION_CODE_PROGRAM(ic);
4802   tme_uint32_t linear_address_first = pc;
4803   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1;
4804   struct tme_m68k_tlb *tlb = &ic->_tme_m68k_itlb;
4805   tme_uint32_t mem_value;
4806   const tme_shared tme_uint32_t *mem;
4807   unsigned int fetch_slow_next = ic->_tme_m68k_insn_fetch_slow_next;
4808 
4809 #ifdef _TME_M68K_STATS
4810   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4811 #endif /* _TME_M68K_STATS */
4812 
4813   /* busy this TLB entry: */
4814   tme_m68k_tlb_busy(tlb);
4815 
4816   /* if this fetch was done by the fast executor: */
4817   if (__tme_predict_true(fetch_slow_next < ic->_tme_m68k_insn_fetch_slow_count_fast)) {
4818 
4819     /* the entire fetch must be in the instruction buffer, and
4820        we must be restarting: */
4821     assert ((fetch_slow_next + sizeof(tme_uint32_t))
4822             <= ic->_tme_m68k_insn_fetch_slow_count_fast);
4823     assert (TME_M68K_SEQUENCE_RESTARTING);
4824     mem_value = tme_memory_read32(((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), sizeof(tme_uint16_t));
4825   }
4826 
4827   /* otherwise, this fetch was not done by the fast executor: */
4828   else {
4829 
4830     /* if we're restarting, but the offset in the instruction buffer
4831        to fetch into is at the instruction buffer total, this must be
4832        a fake fault caused by the fast executor.  we confirm this by
4833        checking that this transfer "caused" the fault, and that this
4834        transfer will be the first slow one after any fast fetches.
4835        in this case, we can cancel the restart for now: */
4836     if (TME_M68K_SEQUENCE_RESTARTING
4837         && (fetch_slow_next
4838             == ic->_tme_m68k_insn_fetch_slow_count_total)) {
4839       assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next
4840                == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted)
4841               && (fetch_slow_next
4842                   == ic->_tme_m68k_insn_fetch_slow_count_fast));
4843       ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted--;
4844     }
4845 
4846     /* if we're not restarting: */
4847     if (!TME_M68K_SEQUENCE_RESTARTING) {
4848 
4849       /* we advance the instruction buffer total *before* we do
4850          what may be a slow fetch, because we may transfer a few
4851          bytes and then fault.  without this, those few bytes
4852          would not get saved in the exception stack frame and
4853          restored later before the continuation of the fetch: */
4854       ic->_tme_m68k_insn_fetch_slow_count_total += sizeof(tme_uint32_t);
4855     }
4856 
4857     /* make sure that if this is a new transfer or if this
4858        transfer faulted, that we're fetching for the current
4859        last positions in the instruction buffer: */
4860     assert ((ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next
4861              < ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted)
4862             || ((fetch_slow_next + sizeof(tme_uint32_t))
4863                 == ic->_tme_m68k_insn_fetch_slow_count_total));
4864 
4865     /* if we aren't restarting, and this address is properly aligned,
4866        and this TLB entry covers the operand and allows fast reads: */
4867     if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4868                            && ((sizeof(tme_uint16_t) - 1) & linear_address_first) == 0
4869                            && tme_m68k_tlb_is_valid(tlb)
4870                            && tlb->tme_m68k_tlb_bus_context == bus_context
4871                            && (tlb->tme_m68k_tlb_function_codes_mask
4872                                & TME_BIT(function_code))
4873                            && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4874                            && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4875                            && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
4876 
4877       /* make the emulator memory pointer: */
4878       mem = (const tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first);
4879 
4880       /* do the 32-bit bus read: */
4881       mem_value = tme_memory_bus_read32(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint16_t), sizeof(tme_uint32_t));
4882 
4883       /* put the value read, in host byte order: */
4884       mem_value = tme_betoh_u32(mem_value);
4885       tme_memory_write32(((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), mem_value, sizeof(tme_uint16_t));
4886 
4887       /* step the transfer count: */
4888       TME_M68K_SEQUENCE_TRANSFER_STEP;
4889     }
4890 
4891     /* otherwise, do the bus cycles the slow way: */
4892     else {
4893       tme_m68k_read32(ic, tlb,
4894                       &function_code,
4895                       &pc,
4896                       ((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)),
4897                       TME_M68K_BUS_CYCLE_FETCH);
4898       mem_value = tme_memory_read32(((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), sizeof(tme_uint16_t));
4899     }
4900   }
4901 
4902   /* unbusy this TLB entry: */
4903   tme_m68k_tlb_unbusy(tlb);
4904 
4905   /* log the value read: */
4906   tme_m68k_verify_mem32(ic, function_code, pc, *((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next)), TME_BUS_CYCLE_READ);
4907   tme_m68k_log(ic, 1000, TME_OK,
4908                (TME_M68K_LOG_HANDLE(ic),
4909                 _("fetch32	%d:0x%08x:	0x%08x"),
4910                 function_code,
4911                 pc,
4912                 *((tme_uint32_t *) (((tme_uint8_t *) &ic->_tme_m68k_insn_fetch_buffer[0]) + fetch_slow_next))));
4913 
4914   /* advance the offset in the instruction buffer for the next slow fetch: */
4915   fetch_slow_next += sizeof(tme_uint32_t);
4916   ic->_tme_m68k_insn_fetch_slow_next = fetch_slow_next;
4917 
4918   /* return the fetched value: */
4919   return(mem_value);
4920 }
4921 
4922 /* this reads a 32-bit stack value: */
4923 void
tme_m68k_pop32(struct tme_m68k * ic,tme_uint32_t * _value)4924 tme_m68k_pop32(struct tme_m68k *ic, tme_uint32_t *_value)
4925 {
4926   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4927   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
4928   tme_uint32_t linear_address_first = ic->tme_m68k_ireg_a7;
4929   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1;
4930   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
4931   tme_uint32_t mem_value;
4932   const tme_shared tme_uint32_t *mem;
4933 
4934 #ifdef _TME_M68K_STATS
4935   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
4936 #endif /* _TME_M68K_STATS */
4937 
4938   /* busy this TLB entry: */
4939   tme_m68k_tlb_busy(tlb);
4940 
4941   /* if we aren't restarting, and this address is properly aligned,
4942      and this TLB entry covers the operand and allows fast reads: */
4943   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
4944                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
4945                          && tme_m68k_tlb_is_valid(tlb)
4946                          && tlb->tme_m68k_tlb_bus_context == bus_context
4947                          && (tlb->tme_m68k_tlb_function_codes_mask
4948                              & TME_BIT(function_code))
4949                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
4950                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
4951                          && tlb->tme_m68k_tlb_emulator_off_read != TME_EMULATOR_OFF_UNDEF)) {
4952 
4953     /* make the emulator memory pointer: */
4954     mem = (const tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_read + linear_address_first);
4955 
4956     /* do the 32-bit bus read: */
4957     mem_value = tme_memory_bus_read32(mem, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
4958 
4959     /* put the value read, in host byte order: */
4960     *_value = tme_betoh_u32(mem_value);
4961 
4962     /* step the transfer count: */
4963     TME_M68K_SEQUENCE_TRANSFER_STEP;
4964   }
4965 
4966   /* otherwise, do the bus cycles the slow way: */
4967   else {
4968     tme_m68k_read32(ic, tlb,
4969                     &function_code,
4970                     &ic->tme_m68k_ireg_a7,
4971                     _value,
4972                     TME_M68K_BUS_CYCLE_NORMAL);
4973   }
4974 
4975   /* unbusy this TLB entry: */
4976   tme_m68k_tlb_unbusy(tlb);
4977 
4978   /* log the value read: */
4979   tme_m68k_verify_mem32(ic, function_code, ic->tme_m68k_ireg_a7, *_value, TME_BUS_CYCLE_READ);
4980   tme_m68k_log(ic, 1000, TME_OK,
4981                (TME_M68K_LOG_HANDLE(ic),
4982                 _("pop32	%d:0x%08x:	0x%08x"),
4983                 function_code,
4984                 ic->tme_m68k_ireg_a7,
4985                 *_value));
4986   if (!TME_M68K_SEQUENCE_RESTARTING) {
4987     ic->tme_m68k_ireg_a7 += sizeof(tme_uint32_t);
4988   }
4989 }
4990 
4991 /* this writes a 32-bit memx value: */
4992 void
tme_m68k_write_memx32(struct tme_m68k * ic)4993 tme_m68k_write_memx32(struct tme_m68k *ic)
4994 {
4995   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
4996   unsigned int function_code = ic->_tme_m68k_ea_function_code;
4997   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
4998   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1;
4999   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
5000   tme_uint32_t mem_value;
5001   tme_shared tme_uint32_t *mem;
5002 
5003 #ifdef _TME_M68K_STATS
5004   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
5005 #endif /* _TME_M68K_STATS */
5006 
5007   /* log the value written: */
5008   tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_memx32, TME_BUS_CYCLE_WRITE);
5009   tme_m68k_log(ic, 1000, TME_OK,
5010                (TME_M68K_LOG_HANDLE(ic),
5011                 _("write_memx32	%d:0x%08x:	0x%08x"),
5012                 ic->_tme_m68k_ea_function_code,
5013                 ic->_tme_m68k_ea_address,
5014                 ic->tme_m68k_ireg_memx32));
5015 
5016   /* busy this TLB entry: */
5017   tme_m68k_tlb_busy(tlb);
5018 
5019   /* if we aren't restarting, and this address is properly aligned,
5020      and this TLB entry covers the operand and allows fast writes: */
5021   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
5022                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
5023                          && tme_m68k_tlb_is_valid(tlb)
5024                          && tlb->tme_m68k_tlb_bus_context == bus_context
5025                          && (tlb->tme_m68k_tlb_function_codes_mask
5026                              & TME_BIT(function_code))
5027                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
5028                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
5029                          && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) {
5030 
5031     /* make the emulator memory pointer: */
5032     mem = (tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first);
5033 
5034     /* get the value to write, in big-endian byte order: */
5035     mem_value = tme_htobe_u32(ic->tme_m68k_ireg_memx32);
5036 
5037     /* do the 32-bit bus write: */
5038     tme_memory_bus_write32(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
5039 
5040     /* step the transfer count: */
5041     TME_M68K_SEQUENCE_TRANSFER_STEP;
5042   }
5043 
5044   /* otherwise, do the bus cycles the slow way: */
5045   else {
5046     tme_m68k_write32(ic, tlb,
5047                     &ic->_tme_m68k_ea_function_code,
5048                     &ic->_tme_m68k_ea_address,
5049                     &ic->tme_m68k_ireg_memx32,
5050                     TME_M68K_BUS_CYCLE_NORMAL);
5051   }
5052 
5053   /* unbusy this TLB entry: */
5054   tme_m68k_tlb_unbusy(tlb);
5055 }
5056 
5057 /* this writes a 32-bit mem value: */
5058 void
tme_m68k_write_mem32(struct tme_m68k * ic,int ireg)5059 tme_m68k_write_mem32(struct tme_m68k *ic, int ireg)
5060 {
5061   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
5062   unsigned int function_code = ic->_tme_m68k_ea_function_code;
5063   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
5064   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1;
5065   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
5066   tme_uint32_t mem_value;
5067   tme_shared tme_uint32_t *mem;
5068 
5069 #ifdef _TME_M68K_STATS
5070   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
5071 #endif /* _TME_M68K_STATS */
5072 
5073   /* log the value written: */
5074   tme_m68k_verify_mem32(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, ic->tme_m68k_ireg_uint32(ireg), TME_BUS_CYCLE_WRITE);
5075   tme_m68k_log(ic, 1000, TME_OK,
5076                (TME_M68K_LOG_HANDLE(ic),
5077                 _("write_mem32	%d:0x%08x:	0x%08x"),
5078                 ic->_tme_m68k_ea_function_code,
5079                 ic->_tme_m68k_ea_address,
5080                 ic->tme_m68k_ireg_uint32(ireg)));
5081 
5082   /* busy this TLB entry: */
5083   tme_m68k_tlb_busy(tlb);
5084 
5085   /* if we aren't restarting, and this address is properly aligned,
5086      and this TLB entry covers the operand and allows fast writes: */
5087   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
5088                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
5089                          && tme_m68k_tlb_is_valid(tlb)
5090                          && tlb->tme_m68k_tlb_bus_context == bus_context
5091                          && (tlb->tme_m68k_tlb_function_codes_mask
5092                              & TME_BIT(function_code))
5093                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
5094                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
5095                          && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) {
5096 
5097     /* make the emulator memory pointer: */
5098     mem = (tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first);
5099 
5100     /* get the value to write, in big-endian byte order: */
5101     mem_value = tme_htobe_u32(ic->tme_m68k_ireg_uint32(ireg));
5102 
5103     /* do the 32-bit bus write: */
5104     tme_memory_bus_write32(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
5105 
5106     /* step the transfer count: */
5107     TME_M68K_SEQUENCE_TRANSFER_STEP;
5108   }
5109 
5110   /* otherwise, do the bus cycles the slow way: */
5111   else {
5112     tme_m68k_write32(ic, tlb,
5113                     &ic->_tme_m68k_ea_function_code,
5114                     &ic->_tme_m68k_ea_address,
5115                     &ic->tme_m68k_ireg_uint32(ireg),
5116                     TME_M68K_BUS_CYCLE_NORMAL);
5117   }
5118 
5119   /* unbusy this TLB entry: */
5120   tme_m68k_tlb_unbusy(tlb);
5121 }
5122 
5123 /* this writes a 32-bit stack value: */
5124 void
tme_m68k_push32(struct tme_m68k * ic,tme_uint32_t value)5125 tme_m68k_push32(struct tme_m68k *ic, tme_uint32_t value)
5126 {
5127   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
5128   unsigned int function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
5129   tme_uint32_t linear_address_first = ic->tme_m68k_ireg_a7 - sizeof(tme_uint32_t);
5130   tme_uint32_t linear_address_last = linear_address_first + sizeof(tme_uint32_t) - 1;
5131   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
5132   tme_uint32_t mem_value;
5133   tme_shared tme_uint32_t *mem;
5134 
5135 #ifdef _TME_M68K_STATS
5136   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
5137 #endif /* _TME_M68K_STATS */
5138 
5139   /* log the value written: */
5140   tme_m68k_verify_mem32(ic, function_code, linear_address_first, value, TME_BUS_CYCLE_WRITE);
5141   tme_m68k_log(ic, 1000, TME_OK,
5142                (TME_M68K_LOG_HANDLE(ic),
5143                 _("push32	%d:0x%08x:	0x%08x"),
5144                 function_code,
5145                 linear_address_first,
5146                 value));
5147 
5148   /* busy this TLB entry: */
5149   tme_m68k_tlb_busy(tlb);
5150 
5151   /* if we aren't restarting, and this address is properly aligned,
5152      and this TLB entry covers the operand and allows fast writes: */
5153   if (__tme_predict_true(!TME_M68K_SEQUENCE_RESTARTING
5154                          && (ic->_tme_m68k_bus_16bit & linear_address_first) == 0
5155                          && tme_m68k_tlb_is_valid(tlb)
5156                          && tlb->tme_m68k_tlb_bus_context == bus_context
5157                          && (tlb->tme_m68k_tlb_function_codes_mask
5158                              & TME_BIT(function_code))
5159                          && linear_address_first >= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
5160                          && linear_address_last <= (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
5161                          && tlb->tme_m68k_tlb_emulator_off_write != TME_EMULATOR_OFF_UNDEF)) {
5162 
5163     /* make the emulator memory pointer: */
5164     mem = (tme_shared tme_uint32_t *) (tlb->tme_m68k_tlb_emulator_off_write + linear_address_first);
5165 
5166     /* get the value to write, in big-endian byte order: */
5167     mem_value = tme_htobe_u32(value);
5168 
5169     /* do the 32-bit bus write: */
5170     tme_memory_bus_write32(mem, mem_value, tlb->tme_m68k_tlb_bus_rwlock, sizeof(tme_uint8_t), sizeof(tme_uint32_t));
5171 
5172     /* step the transfer count: */
5173     TME_M68K_SEQUENCE_TRANSFER_STEP;
5174   }
5175 
5176   /* otherwise, do the bus cycles the slow way: */
5177   else {
5178     tme_m68k_write32(ic, tlb,
5179                     &function_code,
5180                     &linear_address_first,
5181                     &value,
5182                     TME_M68K_BUS_CYCLE_NORMAL);
5183   }
5184 
5185   /* unbusy this TLB entry: */
5186   tme_m68k_tlb_unbusy(tlb);
5187   if (!TME_M68K_SEQUENCE_RESTARTING) {
5188     ic->tme_m68k_ireg_a7 -= sizeof(tme_uint32_t);
5189   }
5190 }
5191 
5192 /* this reads a any-bit mem value: */
5193 void
tme_m68k_read_mem(struct tme_m68k * ic,tme_uint8_t * buffer,unsigned int count)5194 tme_m68k_read_mem(struct tme_m68k *ic, tme_uint8_t *buffer, unsigned int count)
5195 {
5196   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
5197   unsigned int function_code = ic->_tme_m68k_ea_function_code;
5198   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
5199   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
5200 
5201 #ifdef _TME_M68K_STATS
5202   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
5203 #endif /* _TME_M68K_STATS */
5204 
5205   /* busy this TLB entry: */
5206   tme_m68k_tlb_busy(tlb);
5207 
5208   /* call the full read function: */
5209   tme_m68k_read(ic, tlb, &ic->_tme_m68k_ea_function_code, &ic->_tme_m68k_ea_address, buffer, count, TME_M68K_BUS_CYCLE_RAW);
5210 
5211   /* unbusy this TLB entry: */
5212   tme_m68k_tlb_unbusy(tlb);
5213 
5214   /* log the value read: */
5215   tme_m68k_verify_mem_any(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, buffer, count, TME_BUS_CYCLE_READ);
5216   tme_m68k_log_start(ic, 1000, TME_OK) {
5217     unsigned int byte_i;
5218     tme_log_part(TME_M68K_LOG_HANDLE(ic),
5219                  _("read_mem %d:0x%08x count %d:"),
5220                  ic->_tme_m68k_ea_function_code,
5221                  ic->_tme_m68k_ea_address,
5222                  count);
5223     for (byte_i = 0; byte_i < count ; byte_i++) {
5224       tme_log_part(TME_M68K_LOG_HANDLE(ic), " 0x%02x", (buffer)[byte_i]);
5225     }
5226   } tme_m68k_log_finish(ic);
5227 }
5228 
5229 /* this reads a region of address space using actual bus cycles: */
5230 void
tme_m68k_read(struct tme_m68k * ic,struct tme_m68k_tlb * tlb,unsigned int * _function_code,tme_uint32_t * _linear_address,tme_uint8_t * reg,unsigned int reg_size,unsigned int flags)5231 tme_m68k_read(struct tme_m68k *ic,
5232               struct tme_m68k_tlb *tlb,
5233               unsigned int *_function_code,
5234               tme_uint32_t *_linear_address,
5235               tme_uint8_t *reg,
5236               unsigned int reg_size,
5237               unsigned int flags)
5238 {
5239   unsigned int function_code;
5240   tme_uint32_t linear_address;
5241   tme_bus_addr_t physical_address;
5242   int shift;
5243   struct tme_bus_cycle cycle;
5244   unsigned int transferred, resid, cycle_size;
5245   int exception;
5246   int err;
5247   tme_uint8_t *reg_p;
5248   unsigned int buffer_i;
5249   tme_uint8_t reg_buffer[sizeof(tme_uint32_t) * 2];
5250   const tme_shared tme_uint8_t *mem;
5251 
5252   /* if we're not restarting, everything is fresh: */
5253   if (!TME_M68K_SEQUENCE_RESTARTING) {
5254     function_code = *_function_code;
5255     linear_address = *_linear_address;
5256     transferred = 0;
5257   }
5258 
5259   /* otherwise, if this is the transfer that faulted, restore
5260      our state to the cycle that faulted, then take into account
5261      any data provided by a software rerun of the faulted cycle: */
5262   else if (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted
5263            == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next) {
5264     function_code = *_function_code = ic->_tme_m68k_group0_function_code;
5265     linear_address = ic->_tme_m68k_group0_address;
5266     transferred = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted_after;
5267     if (transferred >= reg_size) abort();
5268     *_linear_address = linear_address - transferred;
5269     resid = reg_size - transferred;
5270     if (ic->_tme_m68k_group0_buffer_read_size > resid) abort();
5271     if (ic->_tme_m68k_group0_buffer_read_softrr > resid) abort();
5272     if (ic->_tme_m68k_group0_buffer_read_softrr > 0) {
5273 #ifdef WORDS_BIGENDIAN
5274       memcpy(reg + transferred,
5275              ic->_tme_m68k_group0_buffer_read,
5276              ic->_tme_m68k_group0_buffer_read_size);
5277 #else  /* !WORDS_BIGENDIAN */
5278       reg_p = (reg + reg_size - 1) - transferred;
5279       for (buffer_i = 0;
5280            buffer_i < ic->_tme_m68k_group0_buffer_read_size;
5281            buffer_i++) {
5282         *(reg_p--) = ic->_tme_m68k_group0_buffer_read[buffer_i];
5283       }
5284 #endif /* !WORDS_BIGENDIAN */
5285     }
5286     transferred += ic->_tme_m68k_group0_buffer_read_softrr;
5287   }
5288 
5289   /* otherwise, a later transfer has faulted.  just step the
5290      transfer number and return: */
5291   else {
5292     TME_M68K_SEQUENCE_TRANSFER_STEP;
5293     return;
5294   }
5295 
5296   /* do as many bus cycles as needed to complete the transfer: */
5297   exception = TME_M68K_EXCEPTION_NONE;
5298   cycle_size = 0;
5299   for(; transferred < reg_size; ) {
5300     resid = reg_size - transferred;
5301 
5302     /* start the bus cycle structure: */
5303     cycle.tme_bus_cycle_type = TME_BUS_CYCLE_READ;
5304     if (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG
5305         || (flags & TME_M68K_BUS_CYCLE_RAW)) {
5306       cycle.tme_bus_cycle_buffer = reg + transferred;
5307       cycle.tme_bus_cycle_buffer_increment = 1;
5308     }
5309     else {
5310       cycle.tme_bus_cycle_buffer = reg + reg_size - (1 + transferred);
5311       cycle.tme_bus_cycle_buffer_increment = -1;
5312     }
5313 
5314     /* if we're emulating a CPU with a 16-bit bus interface: */
5315     if (ic->_tme_m68k_bus_16bit) {
5316 
5317       /* if we're trying to transfer a non-power-of-two
5318          number of bytes, either the CPU is broken (no
5319          instructions ever transfer a non-power-of-two
5320          number of bytes), or this function allowed an
5321          unaligned transfer: */
5322       assert((resid & (resid - 1)) == 0
5323              || (flags & TME_M68K_BUS_CYCLE_RAW));
5324 
5325       /* only byte transfers can be unaligned: */
5326       if (resid > sizeof(tme_uint8_t)
5327           && (linear_address & 1)) {
5328           exception = TME_M68K_EXCEPTION_AERR;
5329           break;
5330       }
5331 
5332       /* set the bus-size specific parts of the bus cycle structure: */
5333       cycle_size = TME_MIN(resid, sizeof(tme_uint16_t));
5334       cycle.tme_bus_cycle_size = cycle_size;
5335       cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2);
5336       cycle.tme_bus_cycle_lane_routing =
5337         &tme_m68k_router_16[TME_M68K_BUS_ROUTER_INDEX(TME_BUS16_LOG2, cycle_size, linear_address)];
5338     }
5339 
5340     /* otherwise we're emulating a CPU with a 32-bit bus interface: */
5341     else {
5342 
5343       /* an instruction fetch must be aligned: */
5344       if (flags & TME_M68K_BUS_CYCLE_FETCH) {
5345         if (linear_address & 1) {
5346           exception = TME_M68K_EXCEPTION_AERR;
5347           break;
5348         }
5349         assert(!(resid & 1));
5350       }
5351 
5352       /* set the bus-size specific parts of the bus cycle structure: */
5353       cycle_size = TME_MIN(resid, sizeof(tme_uint32_t) - (linear_address & (sizeof(tme_uint32_t) - 1)));
5354       cycle.tme_bus_cycle_size = cycle_size;
5355       cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2);
5356       cycle.tme_bus_cycle_lane_routing =
5357         &tme_m68k_router_32[TME_M68K_BUS_ROUTER_INDEX(TME_BUS32_LOG2, cycle_size, linear_address)];
5358     }
5359 
5360     /* loop while this TLB entry is invalid or does not apply: */
5361     for (; __tme_predict_false(tme_m68k_tlb_is_invalid(tlb)
5362                                || tlb->tme_m68k_tlb_bus_context != ic->_tme_m68k_bus_context
5363                                || (tlb->tme_m68k_tlb_function_codes_mask & TME_BIT(function_code)) == 0
5364                                || linear_address < (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
5365                                || linear_address > (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
5366                                || (tlb->tme_m68k_tlb_emulator_off_read == TME_EMULATOR_OFF_UNDEF
5367                                    && (tlb->tme_m68k_tlb_cycles_ok & TME_BUS_CYCLE_READ) == 0)); ) {
5368 
5369       /* this must not be part of a read/modify/write cycle: */
5370       assert(!(flags & TME_M68K_BUS_CYCLE_RMW));
5371 
5372       /* fill this TLB entry: */
5373       tme_m68k_tlb_fill(ic, tlb,
5374                         function_code,
5375                         linear_address,
5376                         TME_BUS_CYCLE_READ);
5377     }
5378 
5379     /* if this TLB entry allows for fast reads: */
5380     mem = tlb->tme_m68k_tlb_emulator_off_read;
5381     if (__tme_predict_true(mem != TME_EMULATOR_OFF_UNDEF)) {
5382 
5383       /* make the emulator memory pointer: */
5384       mem += linear_address;
5385 
5386       /* limit the cycle size to addresses covered by the TLB entry: */
5387       if (__tme_predict_false((cycle_size - 1)
5388                               > (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address))) {
5389         cycle_size = (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address) + 1;
5390       }
5391 
5392       /* if this is a little-endian host, and this isn't a raw read: */
5393       if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE
5394           && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) {
5395 
5396         /* use the intermediate buffer for the read: */
5397         cycle.tme_bus_cycle_buffer = &reg_buffer[0];
5398       }
5399 
5400       /* do the bus read: */
5401       tme_memory_bus_read_buffer(mem,
5402                                  cycle.tme_bus_cycle_buffer,
5403                                  cycle_size,
5404                                  tlb->tme_m68k_tlb_bus_rwlock,
5405                                  sizeof(tme_uint8_t),
5406                                  sizeof(tme_uint32_t));
5407 
5408       /* if this is a little-endian host, and this isn't a raw read: */
5409       if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE
5410           && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) {
5411 
5412         /* byteswap the read data in the intermediate buffer: */
5413         reg_p = reg + reg_size - (1 + transferred);
5414         buffer_i = 0;
5415         do {
5416           *(reg_p--) = reg_buffer[buffer_i];
5417         } while (++buffer_i != cycle_size);
5418       }
5419 
5420       /* update: */
5421       linear_address += cycle_size;
5422       transferred += cycle_size;
5423       continue;
5424     }
5425 
5426     /* otherwise, this TLB entry does not allow for fast reads: */
5427 
5428     /* if this is a part of a read/modify/write cycle: */
5429     if (flags & TME_M68K_BUS_CYCLE_RMW) {
5430 
5431       /* if this is the first cycle in this read,
5432          we will establish the new lock, otherwise
5433          we will continue using the existing lock: */
5434       cycle.tme_bus_cycle_type
5435         |= (TME_BUS_CYCLE_LOCK
5436             | (transferred == 0 ? 0 : TME_BUS_CYCLE_UNLOCK));
5437     }
5438 
5439     /* form the physical address for the bus cycle handler: */
5440     physical_address = tlb->tme_m68k_tlb_addr_offset + linear_address;
5441     shift = tlb->tme_m68k_tlb_addr_shift;
5442     if (shift < 0) {
5443       physical_address <<= (0 - shift);
5444     }
5445     else if (shift > 0) {
5446       physical_address >>= shift;
5447     }
5448     cycle.tme_bus_cycle_address = physical_address;
5449 
5450     /* run the bus cycle: */
5451     tme_m68k_tlb_unbusy(tlb);
5452     tme_m68k_callout_unlock(ic);
5453     err = (*tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle)
5454          (tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle);
5455     tme_m68k_callout_relock(ic);
5456     tme_m68k_tlb_busy(tlb);
5457 
5458     /* if the TLB entry was invalidated before the read: */
5459     if (err == EBADF
5460         && tme_m68k_tlb_is_invalid(tlb)) {
5461       cycle.tme_bus_cycle_size = 0;
5462     }
5463 
5464     /* otherwise, if we didn't get a bus error, but some
5465        synchronous event has happened: */
5466     else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {
5467 
5468       /* after the currently executing instruction finishes, check
5469          for external resets, halts, or interrupts: */
5470       ic->_tme_m68k_instruction_burst_remaining = 0;
5471     }
5472 
5473     /* otherwise, any other error might be a bus error: */
5474     else if (err != TME_OK) {
5475       err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err);
5476       if (err != TME_OK) {
5477         exception = TME_M68K_EXCEPTION_BERR;
5478         break;
5479       }
5480     }
5481 
5482     /* update: */
5483     linear_address += cycle.tme_bus_cycle_size;
5484     transferred += cycle.tme_bus_cycle_size;
5485   }
5486 
5487   /* NB: there is no need to explicitly unlock
5488      a device.  if a locked bus cycle to a device
5489      faults, the lock must be automatically unlocked: */
5490 
5491   /* if we faulted, stash the information the fault stacker
5492      will need and start exception processing: */
5493   if (exception != TME_M68K_EXCEPTION_NONE) {
5494     ic->_tme_m68k_group0_flags = flags | TME_M68K_BUS_CYCLE_READ;
5495     ic->_tme_m68k_group0_function_code = function_code;
5496     ic->_tme_m68k_group0_address = linear_address;
5497     ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence;
5498     ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = transferred;
5499     ic->_tme_m68k_group0_buffer_read_size = cycle_size;
5500     if (ic->_tme_m68k_group0_hook != NULL) {
5501       (*ic->_tme_m68k_group0_hook)(ic);
5502     }
5503     ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted =
5504       ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next;
5505     tme_m68k_tlb_unbusy(tlb);
5506     tme_m68k_exception(ic, exception);
5507   }
5508 
5509   /* otherwise, this transfer has now completed: */
5510   TME_M68K_SEQUENCE_TRANSFER_STEP;
5511 }
5512 
5513 /* this writes a any-bit mem value: */
5514 void
tme_m68k_write_mem(struct tme_m68k * ic,tme_uint8_t * buffer,unsigned int count)5515 tme_m68k_write_mem(struct tme_m68k *ic, tme_uint8_t *buffer, unsigned int count)
5516 {
5517   tme_bus_context_t bus_context = ic->_tme_m68k_bus_context;
5518   unsigned int function_code = ic->_tme_m68k_ea_function_code;
5519   tme_uint32_t linear_address_first = ic->_tme_m68k_ea_address;
5520   struct tme_m68k_tlb *tlb = TME_M68K_DTLB_ENTRY(ic, bus_context, function_code, linear_address_first);
5521 
5522 #ifdef _TME_M68K_STATS
5523   ic->tme_m68k_stats.tme_m68k_stats_memory_total++;
5524 #endif /* _TME_M68K_STATS */
5525 
5526   /* log the value written: */
5527   tme_m68k_verify_mem_any(ic, ic->_tme_m68k_ea_function_code, ic->_tme_m68k_ea_address, buffer, count, TME_BUS_CYCLE_WRITE);
5528   tme_m68k_log_start(ic, 1000, TME_OK) {
5529     unsigned int byte_i;
5530     tme_log_part(TME_M68K_LOG_HANDLE(ic),
5531                  _("write_mem %d:0x%08x count %d:"),
5532                  ic->_tme_m68k_ea_function_code,
5533                  ic->_tme_m68k_ea_address,
5534                  count);
5535     for (byte_i = 0; byte_i < count ; byte_i++) {
5536       tme_log_part(TME_M68K_LOG_HANDLE(ic), " 0x%02x", (buffer)[byte_i]);
5537     }
5538   } tme_m68k_log_finish(ic);
5539 
5540   /* busy this TLB entry: */
5541   tme_m68k_tlb_busy(tlb);
5542 
5543   /* call the full write function: */
5544   tme_m68k_write(ic, tlb, &ic->_tme_m68k_ea_function_code, &ic->_tme_m68k_ea_address, buffer, count, TME_M68K_BUS_CYCLE_RAW);
5545 
5546   /* unbusy this TLB entry: */
5547   tme_m68k_tlb_unbusy(tlb);
5548 }
5549 
5550 /* this writes a region of address space using actual bus cycles: */
5551 void
tme_m68k_write(struct tme_m68k * ic,struct tme_m68k_tlb * tlb,unsigned int * _function_code,tme_uint32_t * _linear_address,tme_uint8_t * reg,unsigned int reg_size,unsigned int flags)5552 tme_m68k_write(struct tme_m68k *ic,
5553               struct tme_m68k_tlb *tlb,
5554               unsigned int *_function_code,
5555               tme_uint32_t *_linear_address,
5556               tme_uint8_t *reg,
5557               unsigned int reg_size,
5558               unsigned int flags)
5559 {
5560   unsigned int function_code;
5561   tme_uint32_t linear_address;
5562   tme_bus_addr_t physical_address;
5563   int shift;
5564   struct tme_bus_cycle cycle;
5565   unsigned int transferred, resid, cycle_size;
5566   int exception;
5567   int err;
5568   tme_uint8_t *reg_p;
5569   unsigned int buffer_i;
5570   tme_uint8_t reg_buffer[sizeof(tme_uint32_t) * 2];
5571   tme_shared tme_uint8_t *mem;
5572 
5573   /* if we're not restarting, everything is fresh: */
5574   if (!TME_M68K_SEQUENCE_RESTARTING) {
5575     function_code = *_function_code;
5576     linear_address = *_linear_address;
5577     transferred = 0;
5578   }
5579 
5580   /* otherwise, if this is the transfer that faulted, restore
5581      our state to the cycle that faulted, then take into account
5582      any data provided by a software rerun of the faulted cycle: */
5583   else if (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted
5584            == ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next) {
5585     function_code = *_function_code = ic->_tme_m68k_group0_function_code;
5586     linear_address = ic->_tme_m68k_group0_address;
5587     transferred = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_faulted_after;
5588     if (transferred >= reg_size) abort();
5589     *_linear_address = linear_address - transferred;
5590     resid = reg_size - transferred;
5591     if (ic->_tme_m68k_group0_buffer_write_size > resid) abort();
5592     if (ic->_tme_m68k_group0_buffer_write_softrr > resid) abort();
5593     if (ic->_tme_m68k_group0_buffer_write_softrr == 0) {
5594 #ifdef WORDS_BIGENDIAN
5595       memcpy(reg + transferred,
5596              ic->_tme_m68k_group0_buffer_write,
5597              ic->_tme_m68k_group0_buffer_write_size);
5598 #else  /* !WORDS_BIGENDIAN */
5599       reg_p = (reg + reg_size - 1) - transferred;
5600       for (buffer_i = 0;
5601            buffer_i < ic->_tme_m68k_group0_buffer_write_size;
5602            buffer_i++) {
5603         *(reg_p--) = ic->_tme_m68k_group0_buffer_write[buffer_i];
5604       }
5605 #endif /* !WORDS_BIGENDIAN */
5606     }
5607     transferred += ic->_tme_m68k_group0_buffer_write_softrr;
5608   }
5609 
5610   /* otherwise, a later transfer has faulted.  just step the
5611      transfer number and return: */
5612   else {
5613     TME_M68K_SEQUENCE_TRANSFER_STEP;
5614     return;
5615   }
5616 
5617   /* do as many bus cycles as needed to complete the transfer: */
5618   exception = TME_M68K_EXCEPTION_NONE;
5619   cycle_size = 0;
5620   for(; transferred < reg_size; ) {
5621     resid = reg_size - transferred;
5622 
5623     /* start the bus cycle structure: */
5624     cycle.tme_bus_cycle_type = TME_BUS_CYCLE_WRITE;
5625     if (TME_ENDIAN_NATIVE == TME_ENDIAN_BIG
5626         || (flags & TME_M68K_BUS_CYCLE_RAW)) {
5627       cycle.tme_bus_cycle_buffer = reg + transferred;
5628       cycle.tme_bus_cycle_buffer_increment = 1;
5629     }
5630     else {
5631       cycle.tme_bus_cycle_buffer = reg + reg_size - (1 + transferred);
5632       cycle.tme_bus_cycle_buffer_increment = -1;
5633     }
5634 
5635     /* if we're emulating a CPU with a 16-bit bus interface: */
5636     if (ic->_tme_m68k_bus_16bit) {
5637 
5638       /* if we're trying to transfer a non-power-of-two
5639          number of bytes, either the CPU is broken (no
5640          instructions ever transfer a non-power-of-two
5641          number of bytes), or this function allowed an
5642          unaligned transfer: */
5643       assert((resid & (resid - 1)) == 0
5644              || (flags & TME_M68K_BUS_CYCLE_RAW));
5645 
5646       /* only byte transfers can be unaligned: */
5647       if (resid > sizeof(tme_uint8_t)
5648           && (linear_address & 1)) {
5649           exception = TME_M68K_EXCEPTION_AERR;
5650           break;
5651       }
5652 
5653       /* set the bus-size specific parts of the bus cycle structure: */
5654       cycle_size = TME_MIN(resid, sizeof(tme_uint16_t));
5655       cycle.tme_bus_cycle_size = cycle_size;
5656       cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS16_LOG2);
5657       cycle.tme_bus_cycle_lane_routing =
5658         &tme_m68k_router_16[TME_M68K_BUS_ROUTER_INDEX(TME_BUS16_LOG2, cycle_size, linear_address)];
5659     }
5660 
5661     /* otherwise we're emulating a CPU with a 32-bit bus interface: */
5662     else {
5663 
5664       /* set the bus-size specific parts of the bus cycle structure: */
5665       cycle_size = TME_MIN(resid, sizeof(tme_uint32_t) - (linear_address & (sizeof(tme_uint32_t) - 1)));
5666       cycle.tme_bus_cycle_size = cycle_size;
5667       cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2);
5668       cycle.tme_bus_cycle_lane_routing =
5669         &tme_m68k_router_32[TME_M68K_BUS_ROUTER_INDEX(TME_BUS32_LOG2, cycle_size, linear_address)];
5670     }
5671 
5672     /* loop while this TLB entry is invalid or does not apply: */
5673     for (; __tme_predict_false(tme_m68k_tlb_is_invalid(tlb)
5674                                || tlb->tme_m68k_tlb_bus_context != ic->_tme_m68k_bus_context
5675                                || (tlb->tme_m68k_tlb_function_codes_mask & TME_BIT(function_code)) == 0
5676                                || linear_address < (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_first
5677                                || linear_address > (tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last
5678                                || (tlb->tme_m68k_tlb_emulator_off_write == TME_EMULATOR_OFF_UNDEF
5679                                    && (tlb->tme_m68k_tlb_cycles_ok & TME_BUS_CYCLE_WRITE) == 0)); ) {
5680 
5681       /* this must not be part of a read/modify/write cycle: */
5682       assert(!(flags & TME_M68K_BUS_CYCLE_RMW));
5683 
5684       /* fill this TLB entry: */
5685       tme_m68k_tlb_fill(ic, tlb,
5686                         function_code,
5687                         linear_address,
5688                         TME_BUS_CYCLE_WRITE);
5689     }
5690 
5691     /* if this TLB entry allows for fast writes: */
5692     mem = tlb->tme_m68k_tlb_emulator_off_write;
5693     if (__tme_predict_true(mem != TME_EMULATOR_OFF_UNDEF)) {
5694 
5695       /* make the emulator memory pointer: */
5696       mem += linear_address;
5697 
5698       /* limit the cycle size to addresses covered by the TLB entry: */
5699       if (__tme_predict_false((cycle_size - 1)
5700                               > (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address))) {
5701         cycle_size = (((tme_bus_addr32_t) tlb->tme_m68k_tlb_linear_last) - linear_address) + 1;
5702       }
5703 
5704       /* if this is a little-endian host, and this isn't a raw write: */
5705       if (TME_ENDIAN_NATIVE == TME_ENDIAN_LITTLE
5706           && (flags & TME_M68K_BUS_CYCLE_RAW) == 0) {
5707 
5708         /* byteswap the data to write in the intermediate buffer: */
5709         reg_p = cycle.tme_bus_cycle_buffer;
5710         buffer_i = 0;
5711         do {
5712           reg_buffer[buffer_i] = *(reg_p--);
5713         } while (++buffer_i != cycle_size);
5714 
5715         /* use the intermediate buffer for the write: */
5716         cycle.tme_bus_cycle_buffer = &reg_buffer[0];
5717       }
5718 
5719       /* do the bus write: */
5720       tme_memory_bus_write_buffer(mem,
5721                                  cycle.tme_bus_cycle_buffer,
5722                                  cycle_size,
5723                                  tlb->tme_m68k_tlb_bus_rwlock,
5724                                  sizeof(tme_uint8_t),
5725                                  sizeof(tme_uint32_t));
5726 
5727       /* update: */
5728       linear_address += cycle_size;
5729       transferred += cycle_size;
5730       continue;
5731     }
5732 
5733     /* otherwise, this TLB entry does not allow for fast writes: */
5734 
5735     /* if this is a part of a read/modify/write cycle: */
5736     if (flags & TME_M68K_BUS_CYCLE_RMW) {
5737 
5738       /* we will continue using the existing lock.
5739          the device will automatically unlock after
5740          the last cycle of this write: */
5741       cycle.tme_bus_cycle_type
5742         |= (TME_BUS_CYCLE_LOCK
5743             | (TME_BUS_CYCLE_UNLOCK));
5744     }
5745 
5746     /* form the physical address for the bus cycle handler: */
5747     physical_address = tlb->tme_m68k_tlb_addr_offset + linear_address;
5748     shift = tlb->tme_m68k_tlb_addr_shift;
5749     if (shift < 0) {
5750       physical_address <<= (0 - shift);
5751     }
5752     else if (shift > 0) {
5753       physical_address >>= shift;
5754     }
5755     cycle.tme_bus_cycle_address = physical_address;
5756 
5757     /* run the bus cycle: */
5758     tme_m68k_tlb_unbusy(tlb);
5759     tme_m68k_callout_unlock(ic);
5760     err = (*tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle)
5761          (tlb->tme_m68k_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle);
5762     tme_m68k_callout_relock(ic);
5763     tme_m68k_tlb_busy(tlb);
5764 
5765     /* if the TLB entry was invalidated before the write: */
5766     if (err == EBADF
5767         && tme_m68k_tlb_is_invalid(tlb)) {
5768       cycle.tme_bus_cycle_size = 0;
5769     }
5770 
5771     /* otherwise, if we didn't get a bus error, but some
5772        synchronous event has happened: */
5773     else if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {
5774 
5775       /* after the currently executing instruction finishes, check
5776          for external resets, halts, or interrupts: */
5777       ic->_tme_m68k_instruction_burst_remaining = 0;
5778     }
5779 
5780     /* otherwise, any other error might be a bus error: */
5781     else if (err != TME_OK) {
5782       err = tme_bus_tlb_fault(&tlb->tme_m68k_tlb_bus_tlb, &cycle, err);
5783       if (err != TME_OK) {
5784         exception = TME_M68K_EXCEPTION_BERR;
5785         break;
5786       }
5787     }
5788 
5789     /* update: */
5790     linear_address += cycle.tme_bus_cycle_size;
5791     transferred += cycle.tme_bus_cycle_size;
5792   }
5793 
5794   /* NB: there is no need to explicitly unlock
5795      a device.  if a locked bus cycle to a device
5796      faults, the lock must be automatically unlocked: */
5797 
5798   /* if we faulted, stash the information the fault stacker
5799      will need and start exception processing: */
5800   if (exception != TME_M68K_EXCEPTION_NONE) {
5801     ic->_tme_m68k_group0_flags = flags;
5802     ic->_tme_m68k_group0_function_code = function_code;
5803     ic->_tme_m68k_group0_address = linear_address;
5804     ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence;
5805     ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = transferred;
5806     ic->_tme_m68k_group0_buffer_write_size = cycle_size;
5807 #ifdef WORDS_BIGENDIAN
5808     memcpy(ic->_tme_m68k_group0_buffer_write,
5809            reg + transferred,
5810            ic->_tme_m68k_group0_buffer_write_size);
5811 #else  /* !WORDS_BIGENDIAN */
5812       reg_p = (reg + reg_size - 1) - transferred;
5813       for (buffer_i = 0;
5814            buffer_i < ic->_tme_m68k_group0_buffer_write_size;
5815            buffer_i++) {
5816         ic->_tme_m68k_group0_buffer_write[buffer_i] = *(reg_p--);
5817       }
5818 #endif /* !WORDS_BIGENDIAN */
5819     if (ic->_tme_m68k_group0_hook != NULL) {
5820       (*ic->_tme_m68k_group0_hook)(ic);
5821     }
5822     ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted =
5823       ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next;
5824     tme_m68k_tlb_unbusy(tlb);
5825     tme_m68k_exception(ic, exception);
5826   }
5827 
5828   /* otherwise, this transfer has now completed: */
5829   TME_M68K_SEQUENCE_TRANSFER_STEP;
5830 }
5831 
TME_M68K_INSN(tme_m68k_abcd)5832 TME_M68K_INSN(tme_m68k_abcd)
5833 {
5834   tme_uint8_t dst, dst_msd, dst_lsd;
5835   tme_uint8_t src, src_msd, src_lsd;
5836   tme_uint8_t res, res_msd, res_lsd;
5837   tme_uint8_t flags;
5838   int memory;
5839   int rx, ry, function_code;
5840 
5841   /* load the operands: */
5842   rx = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
5843   ry = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
5844   memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)) != 0;
5845   function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
5846   if (memory) {
5847     TME_M68K_INSN_CANFAULT;
5848     if (!TME_M68K_SEQUENCE_RESTARTING) {
5849       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx) -= sizeof(tme_uint8_t) + ((rx + 1) >> 3);
5850       ic->_tme_m68k_ea_function_code = function_code;
5851       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx);
5852     }
5853     tme_m68k_read_memx8(ic);
5854     if (!TME_M68K_SEQUENCE_RESTARTING) {
5855       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry) -= sizeof(tme_uint8_t) + ((ry + 1) >> 3);
5856       ic->_tme_m68k_ea_function_code = function_code;
5857       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);
5858     }
5859     tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY32);
5860     src = ic->tme_m68k_ireg_memx8;
5861     dst = ic->tme_m68k_ireg_memy8;
5862   }
5863   else {
5864     src = ic->tme_m68k_ireg_uint8(rx << 2);
5865     dst = ic->tme_m68k_ireg_uint8(ry << 2);
5866   }
5867   dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4);
5868   dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4);
5869   src_lsd = TME_FIELD_EXTRACTU(src, 0, 4);
5870   src_msd = TME_FIELD_EXTRACTU(src, 4, 4);
5871 
5872   /* perform the operation: */
5873   res_lsd = dst_lsd + src_lsd + ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0);
5874   res_msd = dst_msd + src_msd;
5875   flags = 0;
5876   if (res_lsd > 9) {
5877     res_lsd -= 10;
5878     res_msd += 1;
5879   }
5880   if (res_msd > 9) {
5881     res_msd -= 10;
5882     flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
5883   }
5884   res = (res_msd << 4) + (res_lsd & 0xf);
5885   if (res == 0) flags |= TME_M68K_FLAG_N;
5886 
5887   /* store the result and set the flags: */
5888   if (memory) {
5889     if (!TME_M68K_SEQUENCE_RESTARTING) {
5890       ic->tme_m68k_ireg_memx8 = res;
5891       ic->_tme_m68k_ea_function_code = function_code;
5892       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);
5893       ic->tme_m68k_ireg_ccr = flags;
5894      }
5895      tme_m68k_write_memx8(ic);
5896   }
5897   else {
5898     ic->tme_m68k_ireg_uint8(ry << 2) = res;
5899     ic->tme_m68k_ireg_ccr = flags;
5900   }
5901 
5902   TME_M68K_INSN_OK;
5903 }
5904 
TME_M68K_INSN(tme_m68k_sbcd)5905 TME_M68K_INSN(tme_m68k_sbcd)
5906 {
5907   tme_uint8_t dst, dst_msd, dst_lsd;
5908   tme_uint8_t src, src_msd, src_lsd;
5909   tme_uint8_t res, res_msd, res_lsd;
5910   tme_uint8_t flags;
5911   int memory;
5912   int rx, ry, function_code;
5913 
5914   /* load the operands: */
5915   rx = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
5916   ry = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 9, 3);
5917   memory = (TME_M68K_INSN_OPCODE & TME_BIT(3)) != 0;
5918   function_code = TME_M68K_FUNCTION_CODE_DATA(ic);
5919   if (memory) {
5920     TME_M68K_INSN_CANFAULT;
5921     if (!TME_M68K_SEQUENCE_RESTARTING) {
5922       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx) -= sizeof(tme_uint8_t) + ((rx + 1) >> 3);
5923       ic->_tme_m68k_ea_function_code = function_code;
5924       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + rx);
5925     }
5926     tme_m68k_read_memx8(ic);
5927     if (!TME_M68K_SEQUENCE_RESTARTING) {
5928       ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry) -= sizeof(tme_uint8_t) + ((ry + 1) >> 3);
5929       ic->_tme_m68k_ea_function_code = function_code;
5930       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);
5931     }
5932     tme_m68k_read_mem8(ic, TME_M68K_IREG_MEMY32);
5933     src = ic->tme_m68k_ireg_memx8;
5934     dst = ic->tme_m68k_ireg_memy8;
5935   }
5936   else {
5937     src = ic->tme_m68k_ireg_uint8(rx << 2);
5938     dst = ic->tme_m68k_ireg_uint8(ry << 2);
5939   }
5940   dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4);
5941   dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4);
5942   src_lsd = TME_FIELD_EXTRACTU(src, 0, 4);
5943   src_msd = TME_FIELD_EXTRACTU(src, 4, 4);
5944 
5945   /* perform the operation: */
5946   res_lsd = dst_lsd - src_lsd - ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0);
5947   res_msd = dst_msd - src_msd;
5948   flags = 0;
5949   if (res_lsd > 9) {
5950     res_lsd += 10;
5951     res_msd -= 1;
5952   }
5953   if (res_msd > 9) {
5954     res_msd += 10;
5955     flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
5956   }
5957   res = (res_msd << 4) + (res_lsd & 0xf);
5958   if (res == 0) flags |= TME_M68K_FLAG_N;
5959 
5960   /* store the result and set the flags: */
5961   if (memory) {
5962     if (!TME_M68K_SEQUENCE_RESTARTING) {
5963       ic->tme_m68k_ireg_memx8 = res;
5964       ic->_tme_m68k_ea_function_code = function_code;
5965       ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ry);
5966       ic->tme_m68k_ireg_ccr = flags;
5967      }
5968      tme_m68k_write_memx8(ic);
5969   }
5970   else {
5971     ic->tme_m68k_ireg_uint8(ry << 2) = res;
5972     ic->tme_m68k_ireg_ccr = flags;
5973   }
5974 
5975   TME_M68K_INSN_OK;
5976 }
5977 
TME_M68K_INSN(tme_m68k_nbcd)5978 TME_M68K_INSN(tme_m68k_nbcd)
5979 {
5980   tme_uint8_t dst, dst_msd, dst_lsd;
5981   tme_uint8_t src, src_msd, src_lsd;
5982   tme_uint8_t res, res_msd, res_lsd;
5983   tme_uint8_t flags;
5984 
5985   dst = 0x00;
5986   src = TME_M68K_INSN_OP1(tme_uint8_t);
5987   dst_lsd = TME_FIELD_EXTRACTU(dst, 0, 4);
5988   dst_msd = TME_FIELD_EXTRACTU(dst, 4, 4);
5989   src_lsd = TME_FIELD_EXTRACTU(src, 0, 4);
5990   src_msd = TME_FIELD_EXTRACTU(src, 4, 4);
5991 
5992   /* perform the operation: */
5993   res_lsd = dst_lsd - src_lsd - ((ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X) != 0);
5994   res_msd = dst_msd - src_msd;
5995   flags = 0;
5996   if (res_lsd > 9) {
5997     res_lsd += 10;
5998     res_msd -= 1;
5999   }
6000   if (res_msd > 9) {
6001     res_msd += 10;
6002     flags |= TME_M68K_FLAG_C | TME_M68K_FLAG_X;
6003   }
6004   res = (res_msd << 4) + (res_lsd & 0xf);
6005   if (res == 0) flags |= TME_M68K_FLAG_N;
6006 
6007   /* store the result and set the flags: */
6008   TME_M68K_INSN_OP1(tme_uint8_t) = res;
6009   ic->tme_m68k_ireg_ccr = flags;
6010 
6011   TME_M68K_INSN_OK;
6012 }
6013 
TME_M68K_INSN(tme_m68k_ori_ccr)6014 TME_M68K_INSN(tme_m68k_ori_ccr)
6015 {
6016   tme_uint8_t reg;
6017   reg = ic->tme_m68k_ireg_ccr | (TME_M68K_INSN_OP0(tme_uint8_t) & TME_M68K_FLAG_CCR);
6018   ic->tme_m68k_ireg_ccr = reg;
6019   TME_M68K_INSN_OK;
6020 }
6021 
TME_M68K_INSN(tme_m68k_andi_ccr)6022 TME_M68K_INSN(tme_m68k_andi_ccr)
6023 {
6024   tme_uint8_t reg;
6025   reg = ic->tme_m68k_ireg_ccr & (TME_M68K_INSN_OP0(tme_uint8_t) & TME_M68K_FLAG_CCR);
6026   ic->tme_m68k_ireg_ccr = reg;
6027   TME_M68K_INSN_OK;
6028 }
6029 
TME_M68K_INSN(tme_m68k_eori_ccr)6030 TME_M68K_INSN(tme_m68k_eori_ccr)
6031 {
6032   tme_uint8_t reg;
6033   reg = ic->tme_m68k_ireg_ccr ^ (TME_M68K_INSN_OP0(tme_uint8_t) & TME_M68K_FLAG_CCR);
6034   ic->tme_m68k_ireg_ccr = reg;
6035   TME_M68K_INSN_OK;
6036 }
6037 
TME_M68K_INSN(tme_m68k_move_to_ccr)6038 TME_M68K_INSN(tme_m68k_move_to_ccr)
6039 {
6040   tme_uint8_t reg;
6041   reg = (TME_M68K_INSN_OP1(tme_uint16_t) & TME_M68K_FLAG_CCR);
6042   ic->tme_m68k_ireg_ccr = reg;
6043   TME_M68K_INSN_OK;
6044 }
6045 
TME_M68K_INSN(tme_m68k_ori_sr)6046 TME_M68K_INSN(tme_m68k_ori_sr)
6047 {
6048   tme_uint16_t reg;
6049   reg = ic->tme_m68k_ireg_sr | (TME_M68K_INSN_OP0(tme_uint16_t) & TME_M68K_FLAG_SR);
6050   TME_M68K_INSN_PRIV;
6051   TME_M68K_INSN_CHANGE_SR(reg);
6052   TME_M68K_INSN_OK;
6053 }
6054 
TME_M68K_INSN(tme_m68k_andi_sr)6055 TME_M68K_INSN(tme_m68k_andi_sr)
6056 {
6057   tme_uint16_t reg;
6058   reg = ic->tme_m68k_ireg_sr & (TME_M68K_INSN_OP0(tme_uint16_t) & TME_M68K_FLAG_SR);
6059   TME_M68K_INSN_PRIV;
6060   TME_M68K_INSN_CHANGE_SR(reg);
6061   TME_M68K_INSN_OK;
6062 }
6063 
TME_M68K_INSN(tme_m68k_eori_sr)6064 TME_M68K_INSN(tme_m68k_eori_sr)
6065 {
6066   tme_uint16_t reg;
6067   reg = ic->tme_m68k_ireg_sr ^ (TME_M68K_INSN_OP0(tme_uint16_t) & TME_M68K_FLAG_SR);
6068   TME_M68K_INSN_PRIV;
6069   TME_M68K_INSN_CHANGE_SR(reg);
6070   TME_M68K_INSN_OK;
6071 }
6072 
TME_M68K_INSN(tme_m68k_move_to_sr)6073 TME_M68K_INSN(tme_m68k_move_to_sr)
6074 {
6075   tme_uint16_t reg;
6076   reg = (TME_M68K_INSN_OP1(tme_uint16_t) & TME_M68K_FLAG_SR);
6077   TME_M68K_INSN_PRIV;
6078   TME_M68K_INSN_CHANGE_SR(reg);
6079   TME_M68K_INSN_OK;
6080 }
6081 
TME_M68K_INSN(tme_m68k_mulu)6082 TME_M68K_INSN(tme_m68k_mulu)
6083 {
6084   int ireg_dl;
6085   tme_uint32_t res;
6086   tme_uint8_t flags;
6087 
6088   /* get the register containing the factor: */
6089   ireg_dl = TME_M68K_IREG_D0 + TME_M68K_INSN_OP0(tme_uint32_t);
6090 
6091   /* perform the multiplication: */
6092   res = (((tme_uint32_t) ic->tme_m68k_ireg_uint16(ireg_dl << 1))
6093          * TME_M68K_INSN_OP1(tme_uint16_t));
6094 
6095   /* store the result: */
6096   ic->tme_m68k_ireg_uint32(ireg_dl) = (tme_uint32_t) res;
6097 
6098   /* set the flags: */
6099   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
6100   if (((tme_int32_t) res) < 0) flags |= TME_M68K_FLAG_N;
6101   if (res == 0) flags |= TME_M68K_FLAG_Z;
6102   ic->tme_m68k_ireg_ccr = flags;
6103 
6104   TME_M68K_INSN_OK;
6105 }
6106 
TME_M68K_INSN(tme_m68k_divu)6107 TME_M68K_INSN(tme_m68k_divu)
6108 {
6109   int ireg_dq;
6110   tme_uint32_t dividend, quotient;
6111   tme_uint16_t divisor, remainder;
6112   tme_uint8_t flags;
6113 
6114   /* get the register(s): */
6115   ireg_dq = TME_M68K_IREG_D0 + TME_M68K_INSN_OP0(tme_uint32_t);
6116 
6117   /* form the dividend and the divisor: */
6118   dividend = (tme_uint32_t) ic->tme_m68k_ireg_uint32(ireg_dq);
6119   divisor = TME_M68K_INSN_OP1(tme_uint16_t);
6120   if (divisor == 0) {
6121     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
6122     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
6123     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0));
6124   }
6125 
6126   /* do the division: */
6127   quotient = dividend / divisor;
6128   remainder = dividend % divisor;
6129 
6130   /* set the flags and return the quotient and remainder: */
6131   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
6132   if (quotient > 0xffff) {
6133     flags |= TME_M68K_FLAG_V;
6134   }
6135   else {
6136     if (((tme_int16_t) quotient) < 0) flags |= TME_M68K_FLAG_N;
6137     if (quotient == 0) flags |= TME_M68K_FLAG_Z;
6138     ic->tme_m68k_ireg_uint16(ireg_dq << 1) = (tme_uint16_t) quotient;
6139     ic->tme_m68k_ireg_uint16((ireg_dq << 1) + 1) = remainder;
6140   }
6141   ic->tme_m68k_ireg_ccr = flags;
6142 
6143   TME_M68K_INSN_OK;
6144 }
6145 
TME_M68K_INSN(tme_m68k_mulul)6146 TME_M68K_INSN(tme_m68k_mulul)
6147 {
6148 #ifndef TME_HAVE_INT64_T
6149   abort();
6150 #else /* TME_HAVE_INT64_T */
6151   unsigned int flag_v;
6152   int ireg_dh;
6153   int ireg_dl;
6154   tme_uint64_t res;
6155   tme_uint8_t flags;
6156 
6157   /* get the register containing the factor: */
6158   ireg_dl = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);
6159 
6160   /* perform the multiplication: */
6161   res = (((tme_uint64_t) ic->tme_m68k_ireg_uint32(ireg_dl))
6162          * TME_M68K_INSN_OP1(tme_uint32_t));
6163 
6164   /* store the result: */
6165   ic->tme_m68k_ireg_uint32(ireg_dl) = (tme_uint32_t) res;
6166   flag_v = TME_M68K_FLAG_V;
6167   if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {
6168     flag_v = 0;
6169     ireg_dh = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);
6170     ic->tme_m68k_ireg_uint32(ireg_dh) = (tme_uint32_t) (res >> 32);
6171   }
6172 
6173   /* set the flags: */
6174   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
6175   if (((tme_int64_t) res) < 0) flags |= TME_M68K_FLAG_N;
6176   if (res == 0) flags |= TME_M68K_FLAG_Z;
6177   if (res > 0xffffffffUL) flags |= flag_v;
6178   ic->tme_m68k_ireg_ccr = flags;
6179 
6180   TME_M68K_INSN_OK;
6181 #endif /* TME_HAVE_INT64_T */
6182 }
6183 
TME_M68K_INSN(tme_m68k_divul)6184 TME_M68K_INSN(tme_m68k_divul)
6185 {
6186 #ifndef TME_HAVE_INT64_T
6187   abort();
6188 #else /* TME_HAVE_INT64_T */
6189   int ireg_dr;
6190   int ireg_dq;
6191   tme_uint64_t dividend, quotient;
6192   tme_uint32_t divisor, remainder;
6193   tme_uint8_t flags;
6194 
6195   /* get the register(s): */
6196   ireg_dq = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);
6197   ireg_dr = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);
6198 
6199   /* form the dividend and the divisor: */
6200   if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {
6201     dividend = (tme_uint64_t)
6202                ((((tme_uint64_t) ic->tme_m68k_ireg_uint32(ireg_dr)) << 32)
6203                 | ic->tme_m68k_ireg_uint32(ireg_dq));
6204   }
6205   else
6206     dividend = (tme_uint64_t) ic->tme_m68k_ireg_uint32(ireg_dq);
6207   divisor = TME_M68K_INSN_OP1(tme_uint32_t);
6208   if (divisor == 0) {
6209     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
6210     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
6211     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0));
6212   }
6213 
6214   /* do the division: */
6215   quotient = dividend / divisor;
6216   remainder = dividend % divisor;
6217 
6218   /* set the flags and return the quotient and remainder: */
6219   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
6220   if (quotient > 0xffffffffUL) {
6221     flags |= TME_M68K_FLAG_V;
6222   }
6223   else {
6224     if (((tme_int32_t) quotient) < 0) flags |= TME_M68K_FLAG_N;
6225     if (quotient == 0) flags |= TME_M68K_FLAG_Z;
6226     ic->tme_m68k_ireg_uint32(ireg_dq) = (tme_uint32_t) quotient;
6227     if (ireg_dr != ireg_dq) {
6228       ic->tme_m68k_ireg_uint32(ireg_dr) = remainder;
6229     }
6230   }
6231   ic->tme_m68k_ireg_ccr = flags;
6232 
6233   TME_M68K_INSN_OK;
6234 #endif /* TME_HAVE_INT64_T */
6235 }
6236 
TME_M68K_INSN(tme_m68k_muls)6237 TME_M68K_INSN(tme_m68k_muls)
6238 {
6239   int ireg_dl;
6240   tme_int32_t res;
6241   tme_uint8_t flags;
6242 
6243   /* get the register containing the factor: */
6244   ireg_dl = TME_M68K_IREG_D0 + TME_M68K_INSN_OP0(tme_uint32_t);
6245 
6246   /* perform the multiplication: */
6247   res = (((tme_int32_t) ic->tme_m68k_ireg_int16(ireg_dl << 1))
6248          * TME_M68K_INSN_OP1(tme_int16_t));
6249 
6250   /* store the result: */
6251   ic->tme_m68k_ireg_int32(ireg_dl) = (tme_int32_t) res;
6252 
6253   /* set the flags: */
6254   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
6255   if (((tme_int32_t) res) < 0) flags |= TME_M68K_FLAG_N;
6256   if (res == 0) flags |= TME_M68K_FLAG_Z;
6257   ic->tme_m68k_ireg_ccr = flags;
6258 
6259   TME_M68K_INSN_OK;
6260 }
6261 
TME_M68K_INSN(tme_m68k_divs)6262 TME_M68K_INSN(tme_m68k_divs)
6263 {
6264   int ireg_dq;
6265   tme_int32_t dividend, quotient;
6266   tme_int16_t divisor, remainder;
6267   tme_uint8_t flags;
6268 
6269   /* get the register(s): */
6270   ireg_dq = TME_M68K_IREG_D0 + TME_M68K_INSN_OP0(tme_uint32_t);
6271 
6272   /* form the dividend and the divisor: */
6273   dividend = (tme_int32_t) ic->tme_m68k_ireg_int32(ireg_dq);
6274   divisor = TME_M68K_INSN_OP1(tme_int16_t);
6275   if (divisor == 0) {
6276     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
6277     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
6278     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0));
6279   }
6280 
6281   /* do the division: */
6282   quotient = dividend / divisor;
6283   remainder = dividend % divisor;
6284 
6285   /* set the flags and return the quotient and remainder: */
6286   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
6287   if (quotient > 0x7fff || quotient < -32768) {
6288     flags |= TME_M68K_FLAG_V;
6289   }
6290   else {
6291     if (((tme_int16_t) quotient) < 0) flags |= TME_M68K_FLAG_N;
6292     if (quotient == 0) flags |= TME_M68K_FLAG_Z;
6293     ic->tme_m68k_ireg_int16(ireg_dq << 1) = (tme_int16_t) quotient;
6294     ic->tme_m68k_ireg_int16((ireg_dq << 1) + 1) = remainder;
6295   }
6296   ic->tme_m68k_ireg_ccr = flags;
6297 
6298   TME_M68K_INSN_OK;
6299 }
6300 
TME_M68K_INSN(tme_m68k_mulsl)6301 TME_M68K_INSN(tme_m68k_mulsl)
6302 {
6303 #ifndef TME_HAVE_INT64_T
6304   abort();
6305 #else /* TME_HAVE_INT64_T */
6306   unsigned int flag_v;
6307   int ireg_dh;
6308   int ireg_dl;
6309   tme_int64_t res;
6310   tme_uint8_t flags;
6311 
6312   /* get the register containing the factor: */
6313   ireg_dl = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);
6314 
6315   /* perform the multiplication: */
6316   res = (((tme_int64_t) ic->tme_m68k_ireg_int32(ireg_dl))
6317          * TME_M68K_INSN_OP1(tme_int32_t));
6318 
6319   /* store the result: */
6320   ic->tme_m68k_ireg_int32(ireg_dl) = (tme_int32_t) res;
6321   flag_v = TME_M68K_FLAG_V;
6322   if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {
6323     flag_v = 0;
6324     ireg_dh = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);
6325     ic->tme_m68k_ireg_int32(ireg_dh) = (tme_int32_t) (res >> 32);
6326   }
6327 
6328   /* set the flags: */
6329   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
6330   if (((tme_int64_t) res) < 0) flags |= TME_M68K_FLAG_N;
6331   if (res == 0) flags |= TME_M68K_FLAG_Z;
6332   if (res > 0x7fffffffL || res < ((0L - 0x7fffffffL) - 1L)) flags |= flag_v;
6333   ic->tme_m68k_ireg_ccr = flags;
6334 
6335   TME_M68K_INSN_OK;
6336 #endif /* TME_HAVE_INT64_T */
6337 }
6338 
TME_M68K_INSN(tme_m68k_divsl)6339 TME_M68K_INSN(tme_m68k_divsl)
6340 {
6341 #ifndef TME_HAVE_INT64_T
6342   abort();
6343 #else /* TME_HAVE_INT64_T */
6344   int ireg_dr;
6345   int ireg_dq;
6346   tme_int64_t dividend, quotient;
6347   tme_int32_t divisor, remainder;
6348   tme_uint8_t flags;
6349 
6350   /* get the register(s): */
6351   ireg_dq = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 12, 3);
6352   ireg_dr = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3);
6353 
6354   /* form the dividend and the divisor: */
6355   if (TME_M68K_INSN_SPECOP & TME_BIT(10)) {
6356     dividend = (tme_int64_t)
6357                ((((tme_uint64_t) ic->tme_m68k_ireg_uint32(ireg_dr)) << 32)
6358                 | ic->tme_m68k_ireg_uint32(ireg_dq));
6359   }
6360   else
6361     dividend = (tme_int64_t) ic->tme_m68k_ireg_int32(ireg_dq);
6362   divisor = TME_M68K_INSN_OP1(tme_int32_t);
6363   if (divisor == 0) {
6364     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
6365     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
6366     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_DIV0));
6367   }
6368 
6369   /* do the division: */
6370   quotient = dividend / divisor;
6371   remainder = dividend % divisor;
6372 
6373   /* set the flags and return the quotient and remainder: */
6374   flags = ic->tme_m68k_ireg_ccr & TME_M68K_FLAG_X;
6375   if (quotient > 0x7fffffffL || quotient < ((0L - 0x7fffffffL) - 1L)) {
6376     flags |= TME_M68K_FLAG_V;
6377   }
6378   else {
6379     if (((tme_int32_t) quotient) < 0) flags |= TME_M68K_FLAG_N;
6380     if (quotient == 0) flags |= TME_M68K_FLAG_Z;
6381     ic->tme_m68k_ireg_int32(ireg_dq) = (tme_int32_t) quotient;
6382     if (ireg_dr != ireg_dq) {
6383       ic->tme_m68k_ireg_int32(ireg_dr) = remainder;
6384     }
6385   }
6386   ic->tme_m68k_ireg_ccr = flags;
6387 
6388   TME_M68K_INSN_OK;
6389 #endif /* TME_HAVE_INT64_T */
6390 }
6391 /* automatically generated by m68k-misc-auto.sh, do not edit! */
6392 
6393 /* the flags->conditions mapping: */
6394 const tme_uint16_t _tme_m68k_conditions[32] = {
6395 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT),
6396 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT),
6397 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6398 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6399 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE),
6400 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE),
6401 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6402 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6403 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6404 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6405 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT),
6406 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT),
6407 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6408 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6409 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE),
6410 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE),
6411 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT),
6412 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT),
6413 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6414 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6415 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE),
6416 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE),
6417 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6418 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_PL) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6419 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6420 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6421 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_HI) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT),
6422 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_NE) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_GT),
6423 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6424 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VC) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_LT) | TME_BIT(TME_M68K_C_LE),
6425 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CC) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE),
6426 TME_BIT(TME_M68K_C_T) | TME_BIT(TME_M68K_C_LS) | TME_BIT(TME_M68K_C_CS) | TME_BIT(TME_M68K_C_EQ) | TME_BIT(TME_M68K_C_VS) | TME_BIT(TME_M68K_C_MI) | TME_BIT(TME_M68K_C_GE) | TME_BIT(TME_M68K_C_LE),
6427 };
6428