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