|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: #include "mpu680x0.h"
8: #include "m680x0acc.h"
9:
10: /*static*/ inline uint32
11: m680x0ACC::vflag_add_8(uint32 src, uint32 dst, uint32 res)
12: {
13: return vflag_add_32(src, dst, res) << 24;
14: }
15:
16: /*static*/ inline uint32
17: m680x0ACC::vflag_add_16(uint32 src, uint32 dst, uint32 res)
18: {
19: return vflag_add_32(src, dst, res) << 16;
20: }
21:
22: /*static*/ inline uint32
23: m680x0ACC::vflag_add_32(uint32 src, uint32 dst, uint32 res)
24: {
25: return (src ^ res) & (dst ^ res);
26: }
27:
28: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
29: // src, dst の上位ビットはクリアしておくこと。
30: // 戻り値の上位ビットはクリアされている。
31: uint32
32: m680x0ACC::add_8(uint32 src, uint32 dst)
33: {
34: Z = dst + src;
35: C = Z >> 8;
36: X = C;
37: N = Z << 24;
38: Z &= 0xff;
39: V = vflag_add_8(src, dst, Z);
40: return Z;
41: }
42:
43: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
44: // src, dst の上位ビットはクリアしておくこと。
45: // 戻り値の上位ビットはクリアされている。
46: uint32
47: m680x0ACC::add_16(uint32 src, uint32 dst)
48: {
49: Z = dst + src;
50: C = Z >> 16;
51: X = C;
52: N = Z << 16;
53: Z &= 0xffff;
54: V = vflag_add_16(src, dst, Z);
55: return Z;
56: }
57:
58: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
59: uint32
60: m680x0ACC::add_32(uint32 src, uint32 dst)
61: {
62: CZ = (uint64)dst + (uint64)src;
63: X = C;
64: V = vflag_add_32(src, dst, Z);
65: N = Z;
66: return Z;
67: }
68:
69: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
70: // src, dst の上位ビットはクリアしておくこと。
71: // 戻り値の上位ビットはクリアされている。
72: uint32
73: m680x0ACC::addx_8(uint32 src, uint32 dst)
74: {
75: uint32 res = dst + src + (IsX() ? 1 : 0);
76: C = res >> 8;
77: X = C;
78: N = res << 24;
79: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
80: if (N != 0) {
81: Z = N;
82: }
83: V = vflag_add_8(src, dst, res);
84: return res & 0xff;
85: }
86:
87: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
88: // src, dst の上位ビットはクリアしておくこと。
89: // 戻り値の上位ビットはクリアされている。
90: uint32
91: m680x0ACC::addx_16(uint32 src, uint32 dst)
92: {
93: uint32 res = dst + src + (IsX() ? 1 : 0);
94: C = res >> 16;
95: X = C;
96: N = res << 16;
97: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
98: if (N != 0) {
99: Z = N;
100: }
101: V = vflag_add_16(src, dst, res);
102: return res & 0xffff;
103: }
104:
105: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
106: uint32
107: m680x0ACC::addx_32(uint32 src, uint32 dst)
108: {
109: uint64 res = (uint64)dst + (uint64)src + (IsX() ? 1 : 0);
110: C = res >> 32;
111: X = C;
112: N = res;
113: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
114: if (N != 0) {
115: Z = N;
116: }
117: V = vflag_add_32(src, dst, res);
118: return res;
119: }
120:
121:
122: /*static*/ inline uint32
123: m680x0ACC::vflag_sub_8(uint32 src, uint32 dst, uint32 res)
124: {
125: return vflag_sub_32(src, dst, res) << 24;
126: }
127:
128: /*static*/ inline uint32
129: m680x0ACC::vflag_sub_16(uint32 src, uint32 dst, uint32 res)
130: {
131: return vflag_sub_32(src, dst, res) << 16;
132: }
133:
134: /*static*/ inline uint32
135: m680x0ACC::vflag_sub_32(uint32 src, uint32 dst, uint32 res)
136: {
137: return (src ^ dst) & (dst ^ res);
138: }
139:
140: // dst - src を計算し、NZVC フラグをセットして結果を返す。
141: // src, dst の上位ビットはクリアしておくこと。
142: // 戻り値の上位ビットはクリアされている。
143: uint32
144: m680x0ACC::cmp_8(uint32 src, uint32 dst)
145: {
146: Z = dst - src;
147: C = Z >> 8;
148: N = Z << 24;
149: Z &= 0xff;
150: V = vflag_sub_8(src, dst, Z);
151: return Z;
152: }
153:
154: // dst - src を計算し、NZVC フラグをセットして結果を返す。
155: // src, dst の上位ビットはクリアしておくこと。
156: // 戻り値の上位ビットはクリアされている。
157: uint32
158: m680x0ACC::cmp_16(uint32 src, uint32 dst)
159: {
160: Z = dst - src;
161: C = Z >> 16;
162: N = Z << 16;
163: Z &= 0xffff;
164: V = vflag_sub_16(src, dst, Z);
165: return Z;
166: }
167:
168: // dst - src を計算し、NZVC フラグをセットして結果を返す。
169: uint32
170: m680x0ACC::cmp_32(uint32 src, uint32 dst)
171: {
172: CZ = (uint64)dst - (uint64)src;
173: N = Z;
174: V = vflag_sub_32(src, dst, Z);
175: return Z;
176: }
177:
178: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
179: // src, dst の上位ビットはクリアしておくこと。
180: // 戻り値の上位ビットはクリアされている。
181: uint32
182: m680x0ACC::sub_8(uint32 src, uint32 dst)
183: {
184: uint32 res = cmp_8(src, dst);
185: X = C;
186: return res;
187: }
188:
189: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
190: // src, dst の上位ビットはクリアしておくこと。
191: // 戻り値の上位ビットはクリアされている。
192: uint32
193: m680x0ACC::sub_16(uint32 src, uint32 dst)
194: {
195: uint32 res = cmp_16(src, dst);
196: X = C;
197: return res;
198: }
199:
200: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
201: uint32
202: m680x0ACC::sub_32(uint32 src, uint32 dst)
203: {
204: uint32 res = cmp_32(src, dst);
205: X = C;
206: return res;
207: }
208:
209: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
210: // src, dst の上位ビットはクリアしておくこと。
211: // 戻り値 res の上位ビットはクリアされている。
212: uint32
213: m680x0ACC::subx_8(uint32 src, uint32 dst)
214: {
215: uint32 res = dst - src - (IsX() ? 1 : 0);
216: C = res >> 8;
217: X = C;
218: N = res << 24;
219: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
220: if (N != 0) {
221: Z = N;
222: }
223: V = vflag_sub_8(src, dst, res);
224: return res & 0xff;
225: }
226:
227: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
228: // src, dst の上位ビットはクリアしておくこと。
229: // 戻り値 res の上位ビットはクリアされている。
230: uint32
231: m680x0ACC::subx_16(uint32 src, uint32 dst)
232: {
233: uint32 res = dst - src - (IsX() ? 1 : 0);
234: C = res >> 16;
235: X = C;
236: N = res << 16;
237: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
238: if (N != 0) {
239: Z = N;
240: }
241: V = vflag_sub_16(src, dst, res);
242: return res & 0xffff;
243: }
244:
245: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
246: uint32
247: m680x0ACC::subx_32(uint32 src, uint32 dst)
248: {
249: uint64 res = (uint64)dst - (uint64)src - (IsX() ? 1 : 0);
250: C = res >> 32;
251: X = C;
252: N = res;
253: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
254: if (N != 0) {
255: Z = N;
256: }
257: V = vflag_sub_32(src, dst, res);
258: return res;
259: }
260:
261: // src(u16) * dst(u16) を計算し、NZVC フラグをセットして結果(u32)を返す。
262: // src, dst の上位ビットはクリアしておくこと。
263: uint32
264: m680x0ACC::mulu_16(uint32 src, uint32 dst)
265: {
266: uint32 res = src * dst;
267: // 16x16->32 ではオーバーフローは起きないので move でよい
268: move_32(res);
269: return res;
270: }
271:
272: // src(s16) * dst(s16) を計算し、NZVC フラグをセットして結果(u32)を返す。
273: // src, dst の上位ビットはクリアしておくこと。
274: uint32
275: m680x0ACC::muls_16(uint32 src, uint32 dst)
276: {
277: int32 res = (int32)(int16)src * (int32)(int16)dst;
278: // 16x16->32 ではオーバーフローは起きないので move でよい
279: move_32(res);
280: return res;
281: }
282:
283: // src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
284: uint32
285: m680x0ACC::mulu_32(uint32 src, uint32 dst)
286: {
287: uint64 res = (uint64)src * (uint64)dst;
288: Z = res;
289: N = res;
290: C = 0;
291: if (res > 0xffffffffUL) {
292: V = V_BIT;
293: } else {
294: V = 0;
295: }
296: return (uint32)res;
297: }
298:
299: // src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
300: uint32
301: m680x0ACC::muls_32(uint32 src, uint32 dst)
302: {
303: int64 res = (int64)(int32)src * (int64)(int32)dst;
304: Z = res;
305: N = res;
306: C = 0;
307: // V フラグは64ビット演算結果の上位32ビットが
308: // 下位32ビットの符号拡張になっていなかった場合に立つ。
309: // つまり符号付き整数で 32bit 表現と 64bit 表現が一致していなければ立つ。
310: int32 tmp = res;
311: if (res != tmp) {
312: V = V_BIT;
313: } else {
314: V = 0;
315: }
316: return (uint32)res;
317: }
318:
319: // src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
320: uint64
321: m680x0ACC::mulu_64(uint32 src, uint32 dst)
322: {
323: uint64 res = (uint64)src * (uint64)dst;
324: N = res >> 32;
325: Z = N | res;
326: V = 0;
327: C = 0;
328: return res;
329: }
330:
331: // src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
332: uint64
333: m680x0ACC::muls_64(uint32 src, uint32 dst)
334: {
335: int64 res = (int64)(int32)src * (int64)(int32)dst;
336: N = res >> 32;
337: Z = N | res;
338: V = 0;
339: C = 0;
340: return res;
341: }
342:
343: void
344: m680x0ACC::btst(uint32 data, int n)
345: {
1.1.1.2 ! root 346: Z = data & (1U << n);
1.1 root 347: }
348:
349: uint32
350: m680x0ACC::bchg(uint32 data, int n)
351: {
1.1.1.2 ! root 352: Z = data & (1U << n);
! 353: data ^= (1U << n);
1.1 root 354: return data;
355: }
356:
357: uint32
358: m680x0ACC::bclr(uint32 data, int n)
359: {
1.1.1.2 ! root 360: Z = data & (1U << n);
! 361: data &= ~(1U << n);
1.1 root 362: return data;
363: }
364:
365: uint32
366: m680x0ACC::bset(uint32 data, int n)
367: {
1.1.1.2 ! root 368: Z = data & (1U << n);
! 369: data |= (1U << n);
1.1 root 370: return data;
371: }
372:
373:
374: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
375: // count は 0..63。data の上位はクリアしておくこと。
376: uint32
377: m680x0ACC::asl_8(uint32 data, int count)
378: {
379: if (count == 0) {
380: move_8(data);
381: return data;
382: }
383: int64 tmps = (int64)(int8)data;
384: if (count > 8) count = 9;
385: uint64 tmp = (uint64)tmps << count;
386: X = C = tmp >> 8;
387: N = tmp << 24;
388: Z = N;
389: // 送り出された全てのビットが元の MSB と一致すれば V=0
390: SetV(((int64)tmp >> 7) != (tmps >> 8));
391: return tmp & 0xff;
392: }
393:
394: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
395: // count は 0..63。data の上位はクリアしておくこと。
396: uint32
397: m680x0ACC::asl_16(uint32 data, int count)
398: {
399: if (count == 0) {
400: move_16(data);
401: return data;
402: }
403: int64 tmps = (int64)(int16)data;
404: if (count > 16) count = 17;
405: uint64 tmp = (uint64)tmps << count;
406: X = C = tmp >> 16;
407: N = tmp << 16;
408: Z = N;
409: // 送り出された全てのビットが元の MSB と一致すれば V=0
410: SetV(((int64)tmp >> 15) != (tmps >> 16));
411: return tmp & 0xffff;
412: }
413:
414: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
415: // count は 0..63
416: uint32
417: m680x0ACC::asl_32(uint32 data, int count)
418: {
419: if (count == 0) {
420: move_32(data);
421: return data;
422: }
423: int64 tmps = (int64)(int32)data;
424: if (count > 32) count = 33;
425: uint64 tmp = (uint64)tmps << count;
426: X = C = tmp >> 32;
427: N = Z = tmp;
428: // 送り出された全てのビットが元の MSB と一致すれば V=0
429: SetV(((int64)tmp >> 31) != (tmps >> 32));
430: return tmp;
431: }
432:
433: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
434: // count は 0..63。data の上位はクリアしておくこと。
435: uint32
436: m680x0ACC::lsl_8(uint32 data, int count)
437: {
438: if (count == 0) {
439: move_8(data);
440: return data;
441: }
442: uint64 tmp = (uint64)data << count;
443: X = C = tmp >> 8;
444: N = tmp << 24;
445: Z = tmp & 0xff;
446: V = 0;
447: return Z;
448: }
449:
450: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
451: // count は 0..63。data の上位はクリアしておくこと。
452: uint32
453: m680x0ACC::lsl_16(uint32 data, int count)
454: {
455: if (count == 0) {
456: move_16(data);
457: return data;
458: }
459: uint64 tmp = (uint64)data << count;
460: X = C = tmp >> 16;
461: N = tmp << 16;
462: Z = tmp & 0xffff;
463: V = 0;
464: return Z;
465: }
466:
467: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
468: // count は 0..63
469: uint32
470: m680x0ACC::lsl_32(uint32 data, int count)
471: {
472: if (count == 0) {
473: move_32(data);
474: return data;
475: }
476: uint64 tmp = (uint64)data << count;
477: X = C = tmp >> 32;
478: N = tmp;
479: Z = tmp;
480: V = 0;
481: return Z;
482: }
483:
484: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
485: // count は 0..63
486: uint32
487: m680x0ACC::roxl_8(uint32 data, int count)
488: {
489: count %= 9;
490: if (count == 0) {
491: Z = data;
492: N = data << 24;
493: V = 0;
494: C = X;
495: return Z;
496: }
497: uint32 xbit = X & 1;
498: Z = (data << count) | (data >> (9 - count)) | (xbit << (count - 1));
499: C = X = Z >> 8;
500: Z &= 0xff;
501: N = Z << 24;
502: V = 0;
503: return Z;
504: }
505:
506: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
507: // count は 0..63
508: uint32
509: m680x0ACC::roxl_16(uint32 data, int count)
510: {
511: count %= 17;
512: if (count == 0) {
513: Z = data;
514: N = data << 16;
515: V = 0;
516: C = X;
517: return Z;
518: }
519: uint32 xbit = X & 1;
520: Z = (data << count) | (data >> (17 - count)) | (xbit << (count - 1));
521: C = X = Z >> 16;
522: Z &= 0xffff;
523: N = Z << 16;
524: V = 0;
525: return Z;
526: }
527:
528: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
529: // count は 0..63
530: uint32
531: m680x0ACC::roxl_32(uint32 data, int count)
532: {
533: count %= 33;
534: if (count == 0) {
535: Z = data;
536: N = data;
537: V = 0;
538: C = X;
539: return Z;
540: }
541: // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
542: uint64 data64 = data;
543: uint32 xbit = X & 1;
544: Z = (data64 << count) | (data64 >> (33 - count)) | (xbit << (count - 1));
545: C = X = data64 >> (32 - count);
546: N = Z;
547: V = 0;
548: return Z;
549: }
550:
551: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
552: // count は 0..63。data の上位はクリアしておくこと
553: uint32
554: m680x0ACC::rol_8(uint32 data, int count)
555: {
556: if (count == 0) {
557: move_8(data);
558: return data;
559: }
560:
561: count %= 8;
562: int count2 = (8 - count) % 8;
563: uint8 tmp = (data << count) | (data >> count2);
564: Z = tmp;
565: N = (uint32)tmp << 24;
566: C = data >> count2;
567: V = 0;
568: return Z;
569: }
570:
571: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
572: // count は 0..63。data の上位はクリアしておくこと
573: uint32
574: m680x0ACC::rol_16(uint32 data, int count)
575: {
576: if (count == 0) {
577: move_16(data);
578: return data;
579: }
580:
581: count %= 16;
582: int count2 = (16 - count) % 16;
583: uint16 tmp = (data << count) | (data >> count2);
584: Z = tmp;
585: N = (uint32)tmp << 16;
586: C = data >> count2;
587: V = 0;
588: return Z;
589: }
590:
591: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
592: // count は 0..63
593: uint32
594: m680x0ACC::rol_32(uint32 data, int count)
595: {
596: if (count == 0) {
597: move_32(data);
598: return data;
599: }
600:
601: count %= 32;
602: int count2 = (32 - count) % 32;
603: uint64 data64 = (uint64)data;
604: uint64 tmp = (data << count) | (data >> count2);
605: Z = tmp;
606: N = Z;
607: C = data64 >> count2;
608: V = 0;
609: return Z;
610: }
611:
612: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
613: // count は 0..64。data の上位はクリアしておくこと。
614: uint32
615: m680x0ACC::asr_8(uint32 data, int count)
616: {
617: if (count == 0) {
618: move_8(data);
619: return data;
620: }
621: if (count > 8) {
622: if ((int8)data < 0) {
623: data = 0xff;
624: } else {
625: data = 0;
626: }
627: X = C = Z = data;
628: N = data << 24;
629: V = 0;
630: return data;
631: }
632: // data >>> count の結果が tmp の上位32ビット中の下位8ビットに入る
633: uint64 tmp = (uint64)(int64)(int8)data << (32 - count);
634: X = C = tmp >> 31;
635: N = tmp >> 8;
636: Z = (tmp >> 32) & 0xff;
637: V = 0;
638: return Z;
639: }
640:
641: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
642: // count は 0..64。data の上位はクリアしておくこと。
643: uint32
644: m680x0ACC::asr_16(uint32 data, int count)
645: {
646: if (count == 0) {
647: move_16(data);
648: return data;
649: }
650: if (count > 16) {
651: if ((int16)data < 0) {
652: data = 0xffff;
653: } else {
654: data = 0;
655: }
656: X = C = Z = data;
657: N = data << 16;
658: V = 0;
659: return data;
660: }
661: // data >>> count の結果が tmp の上位32ビット中の下位16ビットに入る
662: uint64 tmp = (uint64)(int64)(int16)data << (32 - count);
663: X = C = tmp >> 31;
664: N = tmp >> 16;
665: Z = (tmp >> 32) & 0xffff;
666: V = 0;
667: return Z;
668: }
669:
670: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
671: // count は 0..64
672: uint32
673: m680x0ACC::asr_32(uint32 data, int count)
674: {
675: if (count == 0) {
676: move_32(data);
677: return data;
678: }
679: if (count > 32) {
680: if ((int32)data < 0) {
681: data = 0xffffffff;
682: } else {
683: data = 0;
684: }
685: X = C = Z = data;
686: N = data;
687: V = 0;
688: return data;
689: }
690: // data >>> count の結果が tmp の上位32ビットに入る
691: uint64 tmp = (uint64)(int64)(int32)data << (32 - count);
692: X = C = tmp >> 31;
693: Z = N = tmp >> 32;
694: V = 0;
695: return Z;
696: }
697:
698: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
699: // count は 0..63
700: uint32
701: m680x0ACC::lsr_8(uint32 data, int count)
702: {
703: if (count == 0) {
704: move_8(data);
705: return data;
706: }
707: if (count > 8) {
708: X = C = 0;
709: move_8(0);
710: return 0;
711: }
712: // data >> count の結果が tmp の上位32ビットに入る
713: uint64 tmp = (uint64)data << (32 - count);
714: X = C = tmp >> 31;
715: N = tmp >> 8;
716: Z = (tmp >> 32) & 0xff;
717: V = 0;
718: return Z;
719: }
720:
721: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
722: // count は 0..63
723: uint32
724: m680x0ACC::lsr_16(uint32 data, int count)
725: {
726: if (count == 0) {
727: move_16(data);
728: return data;
729: }
730: if (count > 16) {
731: X = C = 0;
732: move_16(0);
733: return 0;
734: }
735: // data >> count の結果が tmp の上位32ビットに入る
736: uint64 tmp = (uint64)data << (32 - count);
737: X = C = tmp >> 31;
738: N = tmp >> 16;
739: Z = (tmp >> 32) & 0xffff;
740: V = 0;
741: return Z;
742: }
743:
744: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
745: // count は 0..63
746: uint32
747: m680x0ACC::lsr_32(uint32 data, int count)
748: {
749: if (count == 0) {
750: move_32(data);
751: return data;
752: }
753: if (count > 32) {
754: X = C = 0;
755: move_32(0);
756: return 0;
757: }
758: // data >> count の結果が tmp の上位32ビットに入る
759: uint64 tmp = (uint64)data << (32 - count);
760: X = C = tmp >> 31;
761: Z = N = tmp >> 32;
762: V = 0;
763: return Z;
764: }
765:
766: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
767: // count は 0..63
768: uint32
769: m680x0ACC::roxr_8(uint32 data, int count)
770: {
771: count %= 9;
772: if (count == 0) {
773: Z = data;
774: N = data << 24;
775: V = 0;
776: C = X;
777: return Z;
778: }
1.1.1.2 ! root 779: uint32 rot = data & ((1U << (count - 1)) - 1);
1.1 root 780: uint32 xbit = X & 1;
781: Z = (data >> count) | (rot << (9 - count)) | (xbit << (8 - count));
782: C = X = data >> (count - 1);
783: N = Z << 24;
784: V = 0;
785: return Z;
786: }
787:
788: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
789: // count は 0..63
790: uint32
791: m680x0ACC::roxr_16(uint32 data, int count)
792: {
793: count %= 17;
794: if (count == 0) {
795: Z = data;
796: N = data << 16;
797: V = 0;
798: C = X;
799: return Z;
800: }
1.1.1.2 ! root 801: uint32 rot = data & ((1U << (count - 1)) - 1);
1.1 root 802: uint32 xbit = X & 1;
803: Z = (data >> count) | (rot << (17 - count)) | (xbit << (16 - count));
804: C = X = data >> (count - 1);
805: N = Z << 16;
806: V = 0;
807: return Z;
808: }
809:
810: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
811: // count は 0..63
812: uint32
813: m680x0ACC::roxr_32(uint32 data, int count)
814: {
815: count %= 33;
816: if (count == 0) {
817: Z = data;
818: N = data;
819: V = 0;
820: C = X;
821: return Z;
822: }
823: // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
824: uint64 data64 = data;
1.1.1.2 ! root 825: uint64 rot = data64 & ((1U << (count - 1)) - 1);
1.1 root 826: uint32 xbit = X & 1;
827: Z = (data64 >> count) | (rot << (33 - count)) | (xbit << (32 - count));
828: C = X = data64 >> (count - 1);
829: N = Z;
830: V = 0;
831: return Z;
832: }
833:
834: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
835: // count は 0..63
836: uint32
837: m680x0ACC::ror_8(uint32 data, int count)
838: {
839: if (count == 0) {
840: move_8(data);
841: return data;
842: }
843:
844: count %= 8;
845: uint8 tmp = (data >> count) | (data << (8 - count));
846: Z = tmp;
847: N = (uint32)tmp << 24;
848: // 7 0 1 2 3 4 5 6
849: C = data >> ((count + 7) % 8);
850: V = 0;
851: return tmp;
852: }
853:
854: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
855: // count は 0..63
856: uint32
857: m680x0ACC::ror_16(uint32 data, int count)
858: {
859: if (count == 0) {
860: move_16(data);
861: return data;
862: }
863:
864: count %= 16;
865: uint16 tmp = (data >> count) | (data << (16 - count));
866: Z = tmp;
867: N = (uint32)tmp << 16;
868: C = data >> ((count + 15) % 16);
869: V = 0;
870: return tmp;
871: }
872:
873: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
874: // count は 0..63
875: uint32
876: m680x0ACC::ror_32(uint32 data, int count)
877: {
878: if (count == 0) {
879: move_32(data);
880: return data;
881: }
882:
883: count %= 32;
884: uint64 data64 = (uint64)data;
885: uint64 tmp = (data >> count) | (data << (32 - count));
886: Z = tmp;
887: N = tmp;
888: C = data64 >> ((count + 31) % 32);
889: V = 0;
890: return tmp;
891: }
892:
893: void
894: m680x0ACC::chk2cmp2_32(uint32 compare, uint32 lower, uint32 upper)
895: {
896: // 実機の実行結果をじっと睨んだ結果、このロジックで
897: // cmp2 は実行していると考えられる。
898: // オペランド順はフラグに影響する。
899: // なぜ 68k のデザイナが順序を入れ替えたのかは不明。
900: // なんかの都合があったんだろうな...
901:
902: // この cmp は通常の if で代替できるけど、
903: // あえて MPU 内部の動作をエミュレート。
904: cmp_32(lower, upper);
905:
906: if (CondCS()) {
907: cmp_32(compare, upper);
908: if (CondEQ()) {
909: // break
910: } else if (CondCS()) {
911: cmp_32(lower, compare);
912: } else {
913: cmp_32(compare, lower);
914: }
915: } else {
916: cmp_32(lower, compare);
917: if (CondEQ()) {
918: // break
919: } else if (CondCS()) {
920: // break
921: } else {
922: cmp_32(compare, upper);
923: }
924: }
925: }
926:
927: // src_10 + dst_10 + X を計算し、XNZVC フラグをセットして結果を返す。
928: // src, dst の上位ビットはクリアしておくこと。
929: // 戻り値の上位ビットはクリアされている。
930: uint32
931: m680x0ACC::abcd_8(uint32 src, uint32 dst)
932: {
933: uint32 res;
934: uint32 tmp;
935: uint32 adj;
936: uint32 low;
937: uint32 cbit;
938:
939: adj = 0;
940: cbit = 0;
941:
942: // X フラグは LSB なので直接足してよい
943: tmp = src + dst + (X & X_BIT);
944:
945: low = (src & 0x0f) + (dst & 0x0f) + (X & X_BIT);
946: if (low > 0x09) {
947: adj = 0x06;
948: }
949:
950: if (tmp > 0x99) {
951: adj += 0x60;
952: cbit = C_BIT;
953: }
954:
955: res = tmp + adj;
956: cbit |= res >> 8;
957: X = C = cbit;
958:
959: res &= 0xff;
960: Z |= res;
961:
962: // V フラグは不定だが 68030 では常にクリア
963: V = 0;
964: // N フラグは不定だが 68030 実機合わせ
965: N = res << 24;
966:
967: return res;
968: }
969:
970: // src_10 - dst_10 - X を計算し、XNZVC フラグをセットして結果を返す。
971: // src, dst の上位ビットはクリアしておくこと。
972: // 戻り値の上位ビットはクリアされている。
973: uint32
974: m680x0ACC::sbcd_8(uint32 src, uint32 dst)
975: {
976: uint32 res;
977: int32 tmp;
978: int32 adj;
979: int32 low;
980: uint32 cbit;
981:
982: adj = 0;
983: cbit = 0;
984:
985: // X フラグは LSB なので直接引いてよい
986: tmp = dst - src - (X & X_BIT);
987:
988: low = (dst & 0x0f) - (src & 0x0f) - (X & X_BIT);
989: if (low < 0) {
990: adj = 0x06;
991: }
992:
993: if (tmp < 0) {
994: adj += 0x60;
995: cbit = C_BIT;
996: }
997:
998: res = tmp - adj;
999: cbit |= res >> 8;
1000: X = C = cbit;
1001:
1002: res &= 0xff;
1003: Z |= res;
1004:
1005: // V フラグは不定だが 68030 では常にクリア
1006: V = 0;
1007: // N フラグは不定だが 68030 実機合わせ
1008: N = res << 24;
1009:
1010: return res;
1011: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.