|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2017 [email protected]
4: //
5:
6: #pragma once
7:
8: extern void acc_chk2cmp2_32(m68kcpu *cpu, uint32, uint32, uint32);
9: extern bool acc_divu_32_16(m68kcpu *cpu, uint32, uint32, uint32 *, uint32 *);
10: extern bool acc_divu_32_32(m68kcpu *cpu, uint32, uint32, uint32 *, uint32 *);
11: extern bool acc_divu_64_32(m68kcpu *cpu, uint32, uint64, uint32 *, uint32 *);
12: extern bool acc_divs_32_16(m68kcpu *cpu, uint32, uint32, uint32 *, uint32 *);
13: extern bool acc_divs_32_32(m68kcpu *cpu, uint32, uint32, uint32 *, uint32 *);
14: extern bool acc_divs_64_32(m68kcpu *cpu, uint32, uint64, uint32 *, uint32 *);
15: extern uint32 acc_abcd_8(m68kcpu *cpu, uint32 src ,uint32 dst);
16: extern uint32 acc_sbcd_8(m68kcpu *cpu, uint32 src, uint32 dst);
17:
18: // ビットフィールド命令
19: class acc_bf
20: {
21: public:
22: acc_bf(m68kcpu *);
23: // デストラクタは無し。
24:
25: void LoadReg(uint n); // Dn から値を読み込む
26: void LoadMem(uint32 addr); // メモリから値を読み込む
27:
28: // レジスタまたはメモリにストアする
29: void Store(uint n) {
30: if (n < 8) {
31: StoreReg(n);
32: } else {
33: StoreMem();
34: }
35: };
36:
37: uint32 data = 0; // 32bit 左詰めデータ
38: int32 offset = 0; // (第2ワードで指定された) オフセット
39: uint32 width = 0; // 幅
40:
41: private:
42: void StoreReg(uint n); // 値を Dn に書き出す
43: void StoreMem(); // 値をメモリに書き出す
44:
45: // 32ビットの val を count ビット左ローテートした値を返す。
46: // count は 0..31。
47: // 実際には count==0 の時 (val>>32) となりこれは未定義動作なのだが
48: // ぶっちゃけこの形式はローテート命令一発に変換されると知っているので
49: // とりあえず放置しておく。C++20 になったら std::rotl() を検討。
50: NO_SANITIZE("undefined")
51: uint32 ROL32(uint32 val, uint count) {
52: return (val << count) | (val >> (32 - count));
53: }
54:
55: // 32ビットの val を count ビット右ローテートした値を返す。
56: // count は 0..31。
57: // 実際には count==0 の時 (val>>32) となりこれは未定義動作なのだが
58: // ぶっちゃけこの形式はローテート命令一発に変換されると知っているので
59: // とりあえず放置しておく。C++20 になったら std::rotr() を検討。
60: NO_SANITIZE("undefined")
61: uint32 ROR32(uint32 val, uint count) {
62: return (val >> count) | (val << (32 - count));
63: }
64:
65: m68kcpu *cpu = NULL;
66:
67: uint32 mask = 0; // 32ビット左詰めマスク
68: uint32 ea = 0; // オフセット計算後の EA
69: int32 local_offset = 0; // 内部(32bit or 8bit 内)オフセット
70: int bytes = 0; // アクセスバイト数
71: uint64 buf = 0; // 40ビットのメモリバッファ
72: };
73:
74: // res を元に NZVC フラグをセットする。
75: // res の上位ビットは無視される。
76: static inline void
77: acc_move_8(m68kcpu *cpu, uint32 res)
78: {
79: CCR.z = res << 24;
80: CCR.n = CCR.z;
81: CCR.c = 0;
82: CCR.v = 0;
83: }
84:
85: // res を元に NZVC フラグをセットする。
86: // res の上位ビットは無視される。
87: static inline void
88: acc_move_16(m68kcpu *cpu, uint32 res)
89: {
90: CCR.z = res << 16;
91: CCR.n = CCR.z;
92: CCR.c = 0;
93: CCR.v = 0;
94: }
95:
96: // res を元に NZVC フラグをセットする。
97: static inline void
98: acc_move_32(m68kcpu *cpu, uint32 res)
99: {
100: CCR.z = res;
101: CCR.n = res;
102: CCR.c = 0;
103: CCR.v = 0;
104: }
105:
106:
107: #define vflag_add_8(src, dst, res) (vflag_add_32(src, dst, res) << 24)
108: #define vflag_add_16(src, dst, res) (vflag_add_32(src, dst, res) << 16)
109: #define vflag_add_32(src, dst, res) (((src) ^ (res)) & ((dst) ^ (res)))
110:
111: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
112: // src, dst の上位ビットはクリアしておくこと。
113: // 戻り値の上位ビットはクリアされている。
114: static inline uint32
115: acc_add_8(m68kcpu *cpu, uint32 src, uint32 dst)
116: {
117: CCR.z = dst + src;
118: CCR.c = CCR.z >> 8;
119: CCR.x = CCR.c;
120: CCR.n = CCR.z << 24;
121: CCR.z &= 0xff;
122: CCR.v = vflag_add_8(src, dst, CCR.z);
123: return CCR.z;
124: }
125:
126: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
127: // src, dst の上位ビットはクリアしておくこと。
128: // 戻り値の上位ビットはクリアされている。
129: static inline uint32
130: acc_add_16(m68kcpu *cpu, uint32 src, uint32 dst)
131: {
132: CCR.z = dst + src;
133: CCR.c = CCR.z >> 16;
134: CCR.x = CCR.c;
135: CCR.n = CCR.z << 16;
136: CCR.z &= 0xffff;
137: CCR.v = vflag_add_16(src, dst, CCR.z);
138: return CCR.z;
139: }
140:
141: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
142: static inline uint32
143: acc_add_32(m68kcpu *cpu, uint32 src, uint32 dst)
144: {
145: CCR.cz = (uint64)dst + (uint64)src;
146: CCR.x = CCR.c;
147: CCR.v = vflag_add_32(src, dst, CCR.z);
148: CCR.n = CCR.z;
149: return CCR.z;
150: }
151:
152: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
153: // src, dst の上位ビットはクリアしておくこと。
154: // 戻り値の上位ビットはクリアされている。
155: static inline uint32
156: acc_addx_8(m68kcpu *cpu, uint32 src, uint32 dst)
157: {
158: uint32 res = dst + src + (CCR.IsX() ? 1 : 0);
159: CCR.c = res >> 8;
160: CCR.x = CCR.c;
161: CCR.n = res << 24;
162: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
163: if (CCR.n != 0) {
164: CCR.z = CCR.n;
165: }
166: CCR.v = vflag_add_8(src, dst, res);
167: return res & 0xff;
168: }
169:
170: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
171: // src, dst の上位ビットはクリアしておくこと。
172: // 戻り値の上位ビットはクリアされている。
173: static inline uint32
174: acc_addx_16(m68kcpu *cpu, uint32 src, uint32 dst)
175: {
176: uint32 res = dst + src + (CCR.IsX() ? 1 : 0);
177: CCR.c = res >> 16;
178: CCR.x = CCR.c;
179: CCR.n = res << 16;
180: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
181: if (CCR.n != 0) {
182: CCR.z = CCR.n;
183: }
184: CCR.v = vflag_add_16(src, dst, res);
185: return res & 0xffff;
186: }
187:
188: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
189: static inline uint32
190: acc_addx_32(m68kcpu *cpu, uint32 src, uint32 dst)
191: {
192: uint64 res = (uint64)dst + (uint64)src + (CCR.IsX() ? 1 : 0);
193: CCR.c = res >> 32;
194: CCR.x = CCR.c;
195: CCR.n = res;
196: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
197: if (CCR.n != 0) {
198: CCR.z = CCR.n;
199: }
200: CCR.v = vflag_add_32(src, dst, res);
201: return res;
202: }
203:
204:
205: #define vflag_sub_8(src, dst, res) (vflag_sub_32(src, dst, res) << 24)
206: #define vflag_sub_16(src, dst, res) (vflag_sub_32(src, dst, res) << 16)
207: #define vflag_sub_32(src, dst, res) (((src) ^ (dst)) & ((dst) ^ (res)))
208:
209: // dst - src を計算し、NZVC フラグをセットして結果を返す。
210: // src, dst の上位ビットはクリアしておくこと。
211: // 戻り値の上位ビットはクリアされている。
212: static inline uint32
213: acc_cmp_8(m68kcpu *cpu, uint32 src, uint32 dst)
214: {
215: CCR.z = dst - src;
216: CCR.c = CCR.z >> 8;
217: CCR.n = CCR.z << 24;
218: CCR.z &= 0xff;
219: CCR.v = vflag_sub_8(src, dst, CCR.z);
220: return CCR.z;
221: }
222:
223: // dst - src を計算し、NZVC フラグをセットして結果を返す。
224: // src, dst の上位ビットはクリアしておくこと。
225: // 戻り値の上位ビットはクリアされている。
226: static inline uint32
227: acc_cmp_16(m68kcpu *cpu, uint32 src, uint32 dst)
228: {
229: CCR.z = dst - src;
230: CCR.c = CCR.z >> 16;
231: CCR.n = CCR.z << 16;
232: CCR.z &= 0xffff;
233: CCR.v = vflag_sub_16(src, dst, CCR.z);
234: return CCR.z;
235: }
236:
237: // dst - src を計算し、NZVC フラグをセットして結果を返す。
238: static inline uint32
239: acc_cmp_32(m68kcpu *cpu, uint32 src, uint32 dst)
240: {
241: CCR.cz = (uint64)dst - (uint64)src;
242: CCR.n = CCR.z;
243: CCR.v = vflag_sub_32(src, dst, CCR.z);
244: return CCR.z;
245: }
246:
247: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
248: // src, dst の上位ビットはクリアしておくこと。
249: // 戻り値の上位ビットはクリアされている。
250: static inline uint32
251: acc_sub_8(m68kcpu *cpu, uint32 src, uint32 dst)
252: {
253: uint32 res = acc_cmp_8(cpu, src, dst);
254: CCR.x = CCR.c;
255: return res;
256: }
257:
258: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
259: // src, dst の上位ビットはクリアしておくこと。
260: // 戻り値の上位ビットはクリアされている。
261: static inline uint32
262: acc_sub_16(m68kcpu *cpu, uint32 src, uint32 dst)
263: {
264: uint32 res = acc_cmp_16(cpu, src, dst);
265: CCR.x = CCR.c;
266: return res;
267: }
268:
269: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
270: static inline uint32
271: acc_sub_32(m68kcpu *cpu, uint32 src, uint32 dst)
272: {
273: uint32 res = acc_cmp_32(cpu, src, dst);
274: CCR.x = CCR.c;
275: return res;
276: }
277:
278: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
279: // src, dst の上位ビットはクリアしておくこと。
280: // 戻り値 res の上位ビットはクリアされている。
281: static inline uint32
282: acc_subx_8(m68kcpu *cpu, uint32 src, uint32 dst)
283: {
284: uint32 res = dst - src - (CCR.IsX() ? 1 : 0);
285: CCR.c = res >> 8;
286: CCR.x = CCR.c;
287: CCR.n = res << 24;
288: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
289: if (CCR.n != 0) {
290: CCR.z = CCR.n;
291: }
292: CCR.v = vflag_sub_8(src, dst, res);
293: return res & 0xff;
294: }
295:
296: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
297: // src, dst の上位ビットはクリアしておくこと。
298: // 戻り値 res の上位ビットはクリアされている。
299: static inline uint32
300: acc_subx_16(m68kcpu *cpu, uint32 src, uint32 dst)
301: {
302: uint32 res = dst - src - (CCR.IsX() ? 1 : 0);
303: CCR.c = res >> 16;
304: CCR.x = CCR.c;
305: CCR.n = res << 16;
306: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
307: if (CCR.n != 0) {
308: CCR.z = CCR.n;
309: }
310: CCR.v = vflag_sub_16(src, dst, res);
311: return res & 0xffff;
312: }
313:
314: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
315: static inline uint32
316: acc_subx_32(m68kcpu *cpu, uint32 src, uint32 dst)
317: {
318: uint64 res = (uint64)dst - (uint64)src - (CCR.IsX() ? 1 : 0);
319: CCR.c = res >> 32;
320: CCR.x = CCR.c;
321: CCR.n = res;
322: // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
323: if (CCR.n != 0) {
324: CCR.z = CCR.n;
325: }
326: CCR.v = vflag_sub_32(src, dst, res);
327: return res;
328: }
329:
330: // src(u16) * dst(u16) を計算し、NZVC フラグをセットして結果(u32)を返す。
331: // src, dst の上位ビットはクリアしておくこと。
332: static inline uint32
333: acc_mulu_16(m68kcpu *cpu, uint32 src, uint32 dst)
334: {
335: uint32 res = src * dst;
336: // 16x16->32 ではオーバーフローは起きないので acc_move でよい
337: acc_move_32(cpu, res);
338: return res;
339: }
340:
341: // src(s16) * dst(s16) を計算し、NZVC フラグをセットして結果(u32)を返す。
342: // src, dst の上位ビットはクリアしておくこと。
343: static inline uint32
344: acc_muls_16(m68kcpu *cpu, uint32 src, uint32 dst)
345: {
346: int32 res = (int32)(int16)src * (int32)(int16)dst;
347: // 16x16->32 ではオーバーフローは起きないので acc_move でよい
348: acc_move_32(cpu, res);
349: return res;
350: }
351:
352: // src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
353: static inline uint32
354: acc_mulu_32(m68kcpu *cpu, uint32 src, uint32 dst)
355: {
356: uint64 res = (uint64)src * (uint64)dst;
357: CCR.z = res;
358: CCR.n = res;
359: CCR.c = 0;
360: if (res > 0xffffffffUL) {
361: CCR.v = m68030ccr::V_BIT;
362: } else {
363: CCR.v = 0;
364: }
365: return (uint32)res;
366: }
367:
368: // src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
369: static inline uint32
370: acc_muls_32(m68kcpu *cpu, uint32 src, uint32 dst)
371: {
372: int64 res = (int64)(int32)src * (int64)(int32)dst;
373: CCR.z = res;
374: CCR.n = res;
375: CCR.c = 0;
376: // V フラグは64ビット演算結果の上位32ビットが
377: // 下位32ビットの符号拡張になっていなかった場合に立つ。
378: // つまり符号付き整数で 32bit 表現と 64bit 表現が一致していなければ立つ。
379: int32 tmp = res;
380: if (res != tmp) {
381: CCR.v = m68030ccr::V_BIT;
382: } else {
383: CCR.v = 0;
384: }
385: return (uint32)res;
386: }
387:
388: // src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
389: static inline uint64
390: acc_mulu_64(m68kcpu *cpu, uint32 src, uint32 dst)
391: {
392: uint64 res = (uint64)src * (uint64)dst;
393: CCR.n = res >> 32;
394: CCR.z = CCR.n | res;
395: CCR.v = 0;
396: CCR.c = 0;
397: return res;
398: }
399:
400: // src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
401: static inline uint64
402: acc_muls_64(m68kcpu *cpu, uint32 src, uint32 dst)
403: {
404: int64 res = (int64)(int32)src * (int64)(int32)dst;
405: CCR.n = res >> 32;
406: CCR.z = CCR.n | res;
407: CCR.v = 0;
408: CCR.c = 0;
409: return res;
410: }
411:
412: static inline void
413: acc_btst(m68kcpu *cpu, uint32 data, int n)
414: {
415: CCR.z = data & (1 << n);
416: }
417:
418: static inline uint32
419: acc_bchg(m68kcpu *cpu, uint32 data, int n)
420: {
421: CCR.z = data & (1 << n);
422: data ^= (1 << n);
423: return data;
424: }
425:
426: static inline uint32
427: acc_bclr(m68kcpu *cpu, uint32 data, int n)
428: {
429: CCR.z = data & (1 << n);
430: data &= ~(1 << n);
431: return data;
432: }
433:
434: static inline uint32
435: acc_bset(m68kcpu *cpu, uint32 data, int n)
436: {
437: CCR.z = data & (1 << n);
438: data |= (1 << n);
439: return data;
440: }
441:
442:
443: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
444: // count は 0..63。data の上位はクリアしておくこと。
445: static inline uint32
446: acc_asl_8(m68kcpu *cpu, uint32 data, int count)
447: {
448: if (count == 0) {
449: acc_move_8(cpu, data);
450: return data;
451: }
452: int64 tmps = (int64)(int8)data;
453: if (count > 8) count = 9;
454: uint64 tmp = (uint64)tmps << count;
455: CCR.x = CCR.c = tmp >> 8;
456: CCR.n = tmp << 24;
457: CCR.z = CCR.n;
458: // 送り出された全てのビットが元の MSB と一致すれば V=0
459: CCR.PutV(((int64)tmp >> 7) != (tmps >> 8));
460: return tmp & 0xff;
461: }
462:
463: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
464: // count は 0..63。data の上位はクリアしておくこと。
465: static inline uint32
466: acc_asl_16(m68kcpu *cpu, uint32 data, int count)
467: {
468: if (count == 0) {
469: acc_move_16(cpu, data);
470: return data;
471: }
472: int64 tmps = (int64)(int16)data;
473: if (count > 16) count = 17;
474: uint64 tmp = (uint64)tmps << count;
475: CCR.x = CCR.c = tmp >> 16;
476: CCR.n = tmp << 16;
477: CCR.z = CCR.n;
478: // 送り出された全てのビットが元の MSB と一致すれば V=0
479: CCR.PutV(((int64)tmp >> 15) != (tmps >> 16));
480: return tmp & 0xffff;
481: }
482:
483: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
484: // count は 0..63
485: static inline uint32
486: acc_asl_32(m68kcpu *cpu, uint32 data, int count)
487: {
488: if (count == 0) {
489: acc_move_32(cpu, data);
490: return data;
491: }
492: int64 tmps = (int64)(int32)data;
493: if (count > 32) count = 33;
494: uint64 tmp = (uint64)tmps << count;
495: CCR.x = CCR.c = tmp >> 32;
496: CCR.n = CCR.z = tmp;
497: // 送り出された全てのビットが元の MSB と一致すれば V=0
498: CCR.PutV(((int64)tmp >> 31) != (tmps >> 32));
499: return tmp;
500: }
501:
502: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
503: // count は 0..63。data の上位はクリアしておくこと。
504: static inline uint32
505: acc_lsl_8(m68kcpu *cpu, uint32 data, int count)
506: {
507: if (count == 0) {
508: acc_move_8(cpu, data);
509: return data;
510: }
511: uint64 tmp = (uint64)data << count;
512: CCR.x = CCR.c = tmp >> 8;
513: CCR.n = tmp << 24;
514: CCR.z = tmp & 0xff;
515: CCR.v = 0;
516: return CCR.z;
517: }
518:
519: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
520: // count は 0..63。data の上位はクリアしておくこと。
521: static inline uint32
522: acc_lsl_16(m68kcpu *cpu, uint32 data, int count)
523: {
524: if (count == 0) {
525: acc_move_16(cpu, data);
526: return data;
527: }
528: uint64 tmp = (uint64)data << count;
529: CCR.x = CCR.c = tmp >> 16;
530: CCR.n = tmp << 16;
531: CCR.z = tmp & 0xffff;
532: CCR.v = 0;
533: return CCR.z;
534: }
535:
536: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
537: // count は 0..63
538: static inline uint32
539: acc_lsl_32(m68kcpu *cpu, uint32 data, int count)
540: {
541: if (count == 0) {
542: acc_move_32(cpu, data);
543: return data;
544: }
545: uint64 tmp = (uint64)data << count;
546: CCR.x = CCR.c = tmp >> 32;
547: CCR.n = tmp;
548: CCR.z = tmp;
549: CCR.v = 0;
550: return CCR.z;
551: }
552:
553: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
554: // count は 0..63
555: static inline uint32
556: acc_roxl_8(m68kcpu *cpu, uint32 data, int count)
557: {
558: count %= 9;
559: if (count == 0) {
560: CCR.z = data;
561: CCR.n = data << 24;
562: CCR.v = 0;
563: CCR.c = CCR.x;
564: return CCR.z;
565: }
566: uint32 x = CCR.x & 1;
567: CCR.z = (data << count) | (data >> (9 - count)) | (x << (count - 1));
568: CCR.c = CCR.x = CCR.z >> 8;
569: CCR.z &= 0xff;
570: CCR.n = CCR.z << 24;
571: CCR.v = 0;
572: return CCR.z;
573: }
574:
575: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
576: // count は 0..63
577: static inline uint32
578: acc_roxl_16(m68kcpu *cpu, uint32 data, int count)
579: {
580: count %= 17;
581: if (count == 0) {
582: CCR.z = data;
583: CCR.n = data << 16;
584: CCR.v = 0;
585: CCR.c = CCR.x;
586: return CCR.z;
587: }
588: uint32 x = CCR.x & 1;
589: CCR.z = (data << count) | (data >> (17 - count)) | (x << (count - 1));
590: CCR.c = CCR.x = CCR.z >> 16;
591: CCR.z &= 0xffff;
592: CCR.n = CCR.z << 16;
593: CCR.v = 0;
594: return CCR.z;
595: }
596:
597: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
598: // count は 0..63
599: static inline uint32
600: acc_roxl_32(m68kcpu *cpu, uint32 data, int count)
601: {
602: count %= 33;
603: if (count == 0) {
604: CCR.z = data;
605: CCR.n = data;
606: CCR.v = 0;
607: CCR.c = CCR.x;
608: return CCR.z;
609: }
610: // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
611: uint64 data64 = data;
612: uint32 x = CCR.x & 1;
613: CCR.z = (data64 << count) | (data64 >> (33 - count)) | (x << (count - 1));
614: CCR.c = CCR.x = data64 >> (32 - count);
615: CCR.n = CCR.z;
616: CCR.v = 0;
617: return CCR.z;
618: }
619:
620: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
621: // count は 0..63。data の上位はクリアしておくこと
622: static inline uint32
623: acc_rol_8(m68kcpu *cpu, uint32 data, int count)
624: {
625: if (count == 0) {
626: acc_move_8(cpu, data);
627: return data;
628: }
629:
630: count %= 8;
631: int count2 = (8 - count) % 8;
632: uint8 tmp = (data << count) | (data >> count2);
633: CCR.z = tmp;
634: CCR.n = (uint32)tmp << 24;
635: CCR.c = data >> count2;
636: CCR.v = 0;
637: return CCR.z;
638: }
639:
640: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
641: // count は 0..63。data の上位はクリアしておくこと
642: static inline uint32
643: acc_rol_16(m68kcpu *cpu, uint32 data, int count)
644: {
645: if (count == 0) {
646: acc_move_16(cpu, data);
647: return data;
648: }
649:
650: count %= 16;
651: int count2 = (16 - count) % 16;
652: uint16 tmp = (data << count) | (data >> count2);
653: CCR.z = tmp;
654: CCR.n = (uint32)tmp << 16;
655: CCR.c = data >> count2;
656: CCR.v = 0;
657: return CCR.z;
658: }
659:
660: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
661: // count は 0..63
662: static inline uint32
663: acc_rol_32(m68kcpu *cpu, uint32 data, int count)
664: {
665: if (count == 0) {
666: acc_move_32(cpu, data);
667: return data;
668: }
669:
670: count %= 32;
671: int count2 = (32 - count) % 32;
672: uint64 data64 = (uint64)data;
673: uint64 tmp = (data << count) | (data >> count2);
674: CCR.z = tmp;
675: CCR.n = CCR.z;
676: CCR.c = data64 >> count2;
677: CCR.v = 0;
678: return CCR.z;
679: }
680:
681: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
682: // count は 0..64。data の上位はクリアしておくこと。
683: static inline uint32
684: acc_asr_8(m68kcpu *cpu, uint32 data, int count)
685: {
686: if (count == 0) {
687: acc_move_8(cpu, data);
688: return data;
689: }
690: if (count > 8) {
691: if ((int8)data < 0) {
692: data = 0xff;
693: } else {
694: data = 0;
695: }
696: CCR.x = CCR.c = CCR.z = data;
697: CCR.n = data << 24;
698: CCR.v = 0;
699: return data;
700: }
701: // data >>> count の結果が tmp の上位32ビット中の下位8ビットに入る
702: uint64 tmp = (uint64)(int64)(int8)data << (32 - count);
703: CCR.x = CCR.c = tmp >> 31;
704: CCR.n = tmp >> 8;
705: CCR.z = (tmp >> 32) & 0xff;
706: CCR.v = 0;
707: return CCR.z;
708: }
709:
710: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
711: // count は 0..64。data の上位はクリアしておくこと。
712: static inline uint32
713: acc_asr_16(m68kcpu *cpu, uint32 data, int count)
714: {
715: if (count == 0) {
716: acc_move_16(cpu, data);
717: return data;
718: }
719: if (count > 16) {
720: if ((int16)data < 0) {
721: data = 0xffff;
722: } else {
723: data = 0;
724: }
725: CCR.x = CCR.c = CCR.z = data;
726: CCR.n = data << 16;
727: CCR.v = 0;
728: return data;
729: }
730: // data >>> count の結果が tmp の上位32ビット中の下位16ビットに入る
731: uint64 tmp = (uint64)(int64)(int16)data << (32 - count);
732: CCR.x = CCR.c = tmp >> 31;
733: CCR.n = tmp >> 16;
734: CCR.z = (tmp >> 32) & 0xffff;
735: CCR.v = 0;
736: return CCR.z;
737: }
738:
739: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
740: // count は 0..64
741: static inline uint32
742: acc_asr_32(m68kcpu *cpu, uint32 data, int count)
743: {
744: if (count == 0) {
745: acc_move_32(cpu, data);
746: return data;
747: }
748: if (count > 32) {
749: if ((int32)data < 0) {
750: data = 0xffffffff;
751: } else {
752: data = 0;
753: }
754: CCR.x = CCR.c = CCR.z = data;
755: CCR.n = data;
756: CCR.v = 0;
757: return data;
758: }
759: // data >>> count の結果が tmp の上位32ビットに入る
760: uint64 tmp = (uint64)(int64)(int32)data << (32 - count);
761: CCR.x = CCR.c = tmp >> 31;
762: CCR.z = CCR.n = tmp >> 32;
763: CCR.v = 0;
764: return CCR.z;
765: }
766:
767: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
768: // count は 0..63
769: static inline uint32
770: acc_lsr_8(m68kcpu *cpu, uint32 data, int count)
771: {
772: if (count == 0) {
773: acc_move_8(cpu, data);
774: return data;
775: }
776: if (count > 8) {
777: CCR.x = CCR.c = 0;
778: acc_move_8(cpu, 0);
779: return 0;
780: }
781: // data >> count の結果が tmp の上位32ビットに入る
782: uint64 tmp = (uint64)data << (32 - count);
783: CCR.x = CCR.c = tmp >> 31;
784: CCR.n = tmp >> 8;
785: CCR.z = (tmp >> 32) & 0xff;
786: CCR.v = 0;
787: return CCR.z;
788: }
789:
790: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
791: // count は 0..63
792: static inline uint32
793: acc_lsr_16(m68kcpu *cpu, uint32 data, int count)
794: {
795: if (count == 0) {
796: acc_move_16(cpu, data);
797: return data;
798: }
799: if (count > 16) {
800: CCR.x = CCR.c = 0;
801: acc_move_16(cpu, 0);
802: return 0;
803: }
804: // data >> count の結果が tmp の上位32ビットに入る
805: uint64 tmp = (uint64)data << (32 - count);
806: CCR.x = CCR.c = tmp >> 31;
807: CCR.n = tmp >> 16;
808: CCR.z = (tmp >> 32) & 0xffff;
809: CCR.v = 0;
810: return CCR.z;
811: }
812:
813: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
814: // count は 0..63
815: static inline uint32
816: acc_lsr_32(m68kcpu *cpu, uint32 data, int count)
817: {
818: if (count == 0) {
819: acc_move_32(cpu, data);
820: return data;
821: }
822: if (count > 32) {
823: CCR.x = CCR.c = 0;
824: acc_move_32(cpu, 0);
825: return 0;
826: }
827: // data >> count の結果が tmp の上位32ビットに入る
828: uint64 tmp = (uint64)data << (32 - count);
829: CCR.x = CCR.c = tmp >> 31;
830: CCR.z = CCR.n = tmp >> 32;
831: CCR.v = 0;
832: return CCR.z;
833: }
834:
835: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
836: // count は 0..63
837: static inline uint32
838: acc_roxr_8(m68kcpu *cpu, uint32 data, int count)
839: {
840: count %= 9;
841: if (count == 0) {
842: CCR.z = data;
843: CCR.n = data << 24;
844: CCR.v = 0;
845: CCR.c = CCR.x;
846: return CCR.z;
847: }
848: uint32 rot = data & ((1 << (count - 1)) - 1);
849: uint32 x = CCR.x & 1;
850: CCR.z = (data >> count) | (rot << (9 - count)) | (x << (8 - count));
851: CCR.c = CCR.x = data >> (count - 1);
852: CCR.n = CCR.z << 24;
853: CCR.v = 0;
854: return CCR.z;
855: }
856:
857: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
858: // count は 0..63
859: static inline uint32
860: acc_roxr_16(m68kcpu *cpu, uint32 data, int count)
861: {
862: count %= 17;
863: if (count == 0) {
864: CCR.z = data;
865: CCR.n = data << 16;
866: CCR.v = 0;
867: CCR.c = CCR.x;
868: return CCR.z;
869: }
870: uint32 rot = data & ((1 << (count - 1)) - 1);
871: uint32 x = CCR.x & 1;
872: CCR.z = (data >> count) | (rot << (17 - count)) | (x << (16 - count));
873: CCR.c = CCR.x = data >> (count - 1);
874: CCR.n = CCR.z << 16;
875: CCR.v = 0;
876: return CCR.z;
877: }
878:
879: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
880: // count は 0..63
881: static inline uint32
882: acc_roxr_32(m68kcpu *cpu, uint32 data, int count)
883: {
884: count %= 33;
885: if (count == 0) {
886: CCR.z = data;
887: CCR.n = data;
888: CCR.v = 0;
889: CCR.c = CCR.x;
890: return CCR.z;
891: }
892: // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
893: uint64 data64 = data;
894: uint64 rot = data64 & ((1 << (count - 1)) - 1);
895: uint32 x = CCR.x & 1;
896: CCR.z = (data64 >> count) | (rot << (33 - count)) | (x << (32 - count));
897: CCR.c = CCR.x = data64 >> (count - 1);
898: CCR.n = CCR.z;
899: CCR.v = 0;
900: return CCR.z;
901: }
902:
903: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
904: // count は 0..63
905: static inline uint32
906: acc_ror_8(m68kcpu *cpu, uint32 data, int count)
907: {
908: if (count == 0) {
909: acc_move_8(cpu, data);
910: return data;
911: }
912:
913: count %= 8;
914: uint8 tmp = (data >> count) | (data << (8 - count));
915: CCR.z = tmp;
916: CCR.n = (uint32)tmp << 24;
917: // 7 0 1 2 3 4 5 6
918: CCR.c = data >> ((count + 7) % 8);
919: CCR.v = 0;
920: return tmp;
921: }
922:
923: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
924: // count は 0..63
925: static inline uint32
926: acc_ror_16(m68kcpu *cpu, uint32 data, int count)
927: {
928: if (count == 0) {
929: acc_move_16(cpu, data);
930: return data;
931: }
932:
933: count %= 16;
934: uint16 tmp = (data >> count) | (data << (16 - count));
935: CCR.z = tmp;
936: CCR.n = (uint32)tmp << 16;
937: CCR.c = data >> ((count + 15) % 16);
938: CCR.v = 0;
939: return tmp;
940: }
941:
942: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
943: // count は 0..63
944: static inline uint32
945: acc_ror_32(m68kcpu *cpu, uint32 data, int count)
946: {
947: if (count == 0) {
948: acc_move_32(cpu, data);
949: return data;
950: }
951:
952: count %= 32;
953: uint64 data64 = (uint64)data;
954: uint64 tmp = (data >> count) | (data << (32 - count));
955: CCR.z = tmp;
956: CCR.n = tmp;
957: CCR.c = data64 >> ((count + 31) % 32);
958: CCR.v = 0;
959: return tmp;
960: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.