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