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