|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // HD64180 演算部分
9: //
10:
11: #include "hd64180acc.h"
12:
13: /*static*/ inline uint32
14: hd64180acc::vflag_add(uint32 dst, uint32 src, uint32 res)
15: {
16: return (src ^ res) & (dst ^ res);
17: }
18:
19: /*static*/ inline uint32
20: hd64180acc::vflag_sub(uint32 dst, uint32 src, uint32 res)
21: {
22: return (src ^ dst) & (dst ^ res);
23: }
24:
25: /*static*/ inline uint32
26: hd64180acc::hflag_add(uint32 dst, uint32 src)
27: {
28: return (dst & 0x0f) + (src & 0x0f);
29: }
30:
31: /*static*/ inline uint32
32: hd64180acc::hflag_sub(uint32 dst, uint32 src)
33: {
34: return (dst & 0x0f) - (src & 0x0f);
35: }
36:
37: // LD A,I、LD A,R 命令のフラグ変化。
38: // S:* Z:* H:0 P/V:IEF2 N:0 C:-
39: uint32
40: hd64180acc::ld_ir8(uint32 src)
41: {
42: // P/V (IEF2) は呼び出し側で行う。
43:
44: S = Z = src;
45: SetH(false);
46: SetN(false);
47: return Z;
48: }
49:
50: // save_c が true なら C を変更しない。
51: // S:* Z:* H:* V:* N:0 C:*/-
52: uint32
53: hd64180acc::add_8(uint32 dst, uint32 src, bool save_c)
54: {
55: if (save_c) {
56: Z = dst + src;
57: } else {
58: CZ = dst + src;
59: }
60: S = Z;
61: H = hflag_add(dst, src);
62: LetV(vflag_add(dst, src, Z));
63: SetN(false);
64:
65: return (uint8)Z;
66: }
67:
68: // save_c が true なら C を変更しない。
69: // S:* Z:* H:* V:* N:0 C:*/-
70: uint32
71: hd64180acc::sub_8(uint32 dst, uint32 src, bool save_c)
72: {
73: if (save_c) {
74: Z = dst - src;
75: } else {
76: CZ = dst - src;
77: }
78: S = Z;
79: H = hflag_sub(dst, src);
80: LetV(vflag_sub(dst, src, Z));
81: SetN(true);
82:
83: return (uint8)Z;
84: }
85:
86: // S:* Z:* H:* V:* N:0 C:*
87: uint32
88: hd64180acc::adc_8(uint32 dst, uint32 src)
89: {
90: uint32 cin = IsC() ? 1 : 0;
91: uint32 res = dst + src + cin;
92:
93: CZ = res;
94: S = res;
95: LetV(vflag_add(dst, src, res));
96: H = hflag_add(dst, src);
97: H |= hflag_add(H, cin);
98: SetN(false);
99:
100: return Z;
101: }
102:
103: // S:* Z:* H:* V:* N:0 C:*
104: uint32
105: hd64180acc::sbc_8(uint32 dst, uint32 src)
106: {
107: uint32 cin = IsC() ? 1 : 0;
108: uint32 res = dst - src - cin;
109:
110: CZ = res;
111: S = res;
112: LetV(vflag_sub(dst, src, res));
113: H = hflag_sub(dst, src);
114: H |= hflag_sub(H, cin);
115: SetN(true);
116:
117: return Z;
118: }
119:
120: // S:- Z:- H:X PV:- N:0 C:*
121: uint32
122: hd64180acc::add_16(uint32 dst, uint32 src)
123: {
124: uint32 res = dst + src;
125: C = res >> 16;
126: SetN(false);
127: // XXX H は不定
128:
129: return res;
130: }
131:
132: // S:* Z:* H:X V:* N:0 C:*
133: uint32
134: hd64180acc::adc_16(uint32 dst, uint32 src)
135: {
136: // V のために2回に分けて計算しないといけない?
137: uint32 res = dst + src;
138: uint32 v = vflag_add(dst, src, res);
139:
140: dst = res;
141: src = IsC() ? 1 : 0;
142: res = dst + src;
143: v |= vflag_add(dst, src, res);
144:
145: LetV((uint32)(v >> 8));
146:
147: // C, S, Z は 16bit が対象でいい?
148: C = res >> 16;
149: S = res >> 8;
150: Z = res | S;
151:
152: SetN(false);
153:
154: // XXX H は本当は不定
155:
156: return res;
157: }
158:
159: // S:* Z:* H:X V:* N:1 C:*
160: uint32
161: hd64180acc::sbc_16(uint32 dst, uint32 src)
162: {
163: // V のために2回に分けて計算しないといけない?
164: uint32 res = dst - src;
165: uint32 v = vflag_sub(dst, src, res);
166:
167: dst = res;
168: src = IsC() ? 1 : 0;
169: res = dst - src;
170: v |= vflag_sub(dst, src, res);
171:
172: LetV((uint32)(v >> 8));
173:
174: // C, S, Z は 16bit が対象でいい?
175: C = res >> 16;
176: S = res >> 8;
177: Z = res | S;
178:
179: SetN(true);
180:
181: // XXX H は本当は不定
182:
183: return res;
184: }
185:
186: // BIT 命令
187: // S:X Z:* H:1 PV:X N:0 C:-
188: void
189: hd64180acc::bit_8(uint b, uint32 src)
190: {
191: Z = src & (1U << b);
192: SetH(true);
193: SetN(false);
194: // XXX S, P(V) は本当は不定
195: }
196:
197: // IN A,(n) 命令のフラグ変化。他からも色々呼ばれる。
198: // S:* Z:* H:0 P:* N:0 C:-
199: uint32
200: hd64180acc::in_8(uint32 src)
201: {
202: S = Z = src;
203: SetN(false);
204: SetH(false);
205: LetP(Z);
206: return Z;
207: }
208:
209: // OTIM/OTDM 命令のフラグ変化。
210: // 戻り値は演算後の B レジスタの値。
211: // HD64180.pdf p.110
212: // S:* Z:* H:* P:* N:* C:*
213: uint32
214: hd64180acc::outm_8(uint32 src, uint32 breg)
215: {
216: CZ = breg - 1;
217: S = Z;
218: H = hflag_sub(breg, 1);
219: LetP(Z); // 減算後の B のパリティ
220: N = (src & 0x80); // (HL) の MSB
221:
222: return Z;
223: }
224:
225: // S:* Z:* H:1 P:* N:0 C:0
226: uint32
227: hd64180acc::and_8(uint32 dst, uint32 src)
228: {
229: uint32 res;
230: SetC(false);
231: res = in_8(dst & src);
232: SetH(true); // これだけ H はセット
233: return res;
234: }
235:
236: // S:* Z:* H:0 P:* N:0 C:0
237: uint32
238: hd64180acc::or_8(uint32 dst, uint32 src)
239: {
240: SetC(false);
241: return in_8(dst | src);
242: }
243:
244: // S:* Z:* H:0 P:* N:0 C:0
245: uint32
246: hd64180acc::xor_8(uint32 dst, uint32 src)
247: {
248: SetC(false);
249: return in_8(dst ^ src);
250: }
251:
252: // S:* Z:* H:1 P:* N:0 C:0
253: void
254: hd64180acc::tst_8(uint32 dst, uint32 src)
255: {
256: in_8(dst & src);
257: SetH(true);
258: SetC(false);
259: }
260:
261: // S:* Z:* H:0 P:* N:0 C:*
262: uint32
263: hd64180acc::sla_8(uint32 src)
264: {
265: CZ = src << 1;
266: return in_8(Z);
267: }
268:
269: // S:* Z:* H:0 P:* N:0 C:*
270: uint32
271: hd64180acc::sra_8(uint32 src)
272: {
273: C = src;
274: Z = (src >> 1);
275: Z |= src & 0x80;
276: return in_8(Z);
277: }
278:
279: // S:* Z:* H:0 P:* N:0 C:*
280: uint32
281: hd64180acc::srl_8(uint32 src)
282: {
283: C = src;
284: Z = src >> 1;
285: return in_8(Z);
286: }
287:
288: // S Z H P N C
289: // RLA - - 0 - 0 * : rl_8()
290: // RL r * * 0 P 0 * : in_8(rl_8())
291: // RLD * * 0 P 0 - : in_8()
292:
293: uint32
294: hd64180acc::rl_8(uint32 src)
295: {
296: src <<= 1;
297: if (IsC()) {
298: src |= 0x01;
299: }
300: C = src >> 8;
301:
302: SetN(false);
303: SetH(false);
304:
305: return (uint8)src;
306: }
307:
308: uint32
309: hd64180acc::rlc_8(uint32 src)
310: {
311: src <<= 1;
312: if ((src & 0x100)) {
313: src |= 0x01;
314: }
315: C = src >> 8;
316:
317: SetN(false);
318: SetH(false);
319:
320: return (uint8)src;
321: }
322:
323: uint32
324: hd64180acc::rr_8(uint32 src)
325: {
326: src = (uint8)src;
327: if (IsC()) {
328: src |= 0x100;
329: }
330: C = src;
331: src >>= 1;
332:
333: SetN(false);
334: SetH(false);
335:
336: return (uint8)src;
337: }
338:
339: uint32
340: hd64180acc::rrc_8(uint32 src)
341: {
342: C = src;
343: src = (uint8)src;
344: src |= (C << 8);
345: src >>= 1;
346:
347: SetN(false);
348: SetH(false);
349:
350: return (uint8)src;
351: }
1.1.1.2 ! root 352:
! 353: uint32
! 354: hd64180acc::daa_8(uint32 src)
! 355: {
! 356: uint32 ah;
! 357: uint32 al;
! 358: uint32 b;
! 359: uint32 res;
! 360:
! 361: if (IsN() == false) {
! 362: bool tmpC = IsC(); // 入力時の状態
! 363: bool tmpH = IsH();
! 364:
! 365: bool resC = IsC(); // 出力用。C は入力と内部演算の和
! 366: bool resH; // 出力用。H は内部演算のみの和
! 367:
! 368: // 下位桁
! 369: ah = src >> 4;
! 370: al = src & 0xf;
! 371: if (al >= 0x0a || IsH()) {
! 372: b = 0x06;
! 373: } else {
! 374: b = 0;
! 375: }
! 376: src = add_8(src, b);
! 377: resC |= IsC();
! 378: resH = IsH();
! 379:
! 380: // 上位桁
! 381: ah = src >> 4;
! 382: al = src & 0xf;
! 383: if (ah >= 0x0a || tmpC) {
! 384: b = 0x60;
! 385:
! 386: // XXX 入力が 9A-9F で H=1 C=0 の時、
! 387: // 下位桁を補正して(6を足して) 上位桁が A になるのに、
! 388: // HD64180 ではこれを補正してないようだ。
! 389: if (0xa0 <= src && src < 0xa6 && tmpH && tmpC == false) {
! 390: b = 0;
! 391: }
! 392: } else {
! 393: b = 0;
! 394:
! 395: // XXX 入力が FA-FF で C=0 の時、
! 396: // 下位桁を補正して(6 を足して) C=1 00-05 に繰り上がるだけの
! 397: // はずが、HD64180 では 60 も足してしまうようだ。
! 398: if (IsC() && ah == 0x00 && tmpC == false) {
! 399: b = 0x60;
! 400: }
! 401: }
! 402: res = add_8(src, b);
! 403: resC |= IsC();
! 404: resH |= IsH();
! 405:
! 406: SetH(resH);
! 407: SetC(resC);
! 408: } else {
! 409: // N==1 (減算) 側は跡形なく動作が違う。
! 410: // 意味はさっぱり分からんけどとりあえず実機と同じ動作。
! 411:
! 412: bool resC = IsC();
! 413: b = 0;
! 414: if (IsH()) {
! 415: b += 0x06;
! 416: if (src < 0x06) {
! 417: resC = true;
! 418: }
! 419: }
! 420: if (IsC()) {
! 421: b += 0x60;
! 422: }
! 423: res = sub_8(src, b);
! 424:
! 425: SetC(resC);
! 426: }
! 427:
! 428: // P/V フラグは P
! 429: LetP(res);
! 430:
! 431: return res;
! 432: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.