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 = ®_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 = ®_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