ref: 2810cc5d0c01b06e678b50995edb724c739b8eed
dir: /sys/src/games/v8e/cpubcd.c/
#include <u.h> #include <libc.h> #include "dat.h" #include "fns.h" static s8int getsign(u16int l, u32int a) { u8int c; if(l == 0) return 1; c = readm(a + l/2, 0); c &= 0xf; if(c == 11 || c == 13) return -1; return 1; } static int getdig(u16int l, u32int a, int i) { u8int c; if(i >= l) return 0; i = l - 1 - i; if((l & 1) == 0) i++; a += i/2; c = readm(a, 0); if((i & 1) == 0) return c >> 4; return c & 0xf; } static void putdig(u16int l, u32int a, int i, int v) { u8int c; if(i >= l){ if(v != 0) ps |= FLAGV; return; } i = l - 1 - i; if((l & 1) == 0) i++; a += i/2; if((l & 1) == 0 && i == 1) c = 0; else c = readm(a, 0); if((i & 1) == 0) c = c & 0x0f | v << 4; else c = c & 0xf0 | v; writem(a, c, 0); } static void putsign(u16int l, u32int a, s8int s) { u8int c; a += l/2; c = readm(a, 0); c = c & 0xf0 | 12 | s < 0; writem(a, c, 0); } static u32int sigdig(u16int l, u32int a) { u32int e; e = a + l/2 + 1; for(; a < e; a++) if(readm(a, 0) != 0) return a; return a; } void cvtlp(void) { s32int x; u16int l; u32int a; u8int v; int i; x = readm(amode(2), 2); l = readm(amode(1), 1); a = addrof(amode(0)); ps = ps & ~15 | FLAGZ; if(x < 0){ x = -x; ps |= FLAGN; } for(i = 0; i < l; i++){ v = x % 10; x /= 10; putdig(l, a, i, v); if(v != 0) ps &= ~FLAGZ; } if(x != 0) ps |= FLAGV; if((ps & (FLAGN|FLAGZ)) == 0) ps &= ~FLAGN; putsign(l, a, -((ps & FLAGN) != 0)); r[0] = 0; r[1] = 0; r[2] = 0; r[3] = sigdig(l, a); } static uchar editread(void) { u8int rc; if((s32int) r[0] <= 0){ if(r[0] == 0) sysfatal("editread"); r[0] += 0x10000; return 0; }else{ rc = readm(r[1], 0); if((r[0] & 1) != 0) rc >>= 4; else rc &= 0xf; r[0]--; if((r[0] & 1) != 0) r[1]++; return rc; } } void editpc(void) { u8int p, c; int i; r[0] = readm(amode(1), 1); r[1] = addrof(amode(0)); r[2] = 0x2020; r[3] = addrof(amode(0)); r[5] = addrof(amode(0)); ps = ps & ~15 | FLAGZ; c = readm(r[1] + r[0]/2, 0) & 0xf; if(c == 11 || c == 13){ ps |= FLAGN; r[2] |= 0xd00; } for(;;){ p = readm(r[3]++, 0); switch(p){ case 0x00: if(r[0] != 0) sysfatal("editpc"); if((ps & FLAGZ) != 0) ps &= ~FLAGN; return; case 0x01: if((ps & FLAGC) == 0){ writem(r[5]++, r[2] >> 8, 0); ps |= FLAGC; } break; case 0x02: ps &= ~FLAGC; break; case 0x03: ps |= FLAGC; break; case 0x04: writem(r[5]++, r[2] >> 8, 0); break; case 0x40: r[2] = r[2] & ~0xff | (u8int)readm(r[3]++, 0); break; case 0x41: r[2] = r[2] & ~0xff00 | (u8int)readm(r[3]++, 0) << 8; break; case 0x42: p = readm(r[3]++, 0); if((ps & FLAGN) == 0) r[2] = r[2] & ~0xff00 | p << 8; break; case 0x43: p = readm(r[3]++, 0); if((ps & FLAGN) != 0) r[2] = r[2] & ~0xff00 | p << 8; break; case 0x44: p = readm(r[3]++, 0); if((ps & FLAGC) != 0) writem(r[5]++, p, 0); else writem(r[5]++, r[2], 0); break; case 0x45: p = readm(r[3]++, 0); if((ps & FLAGZ) != 0){ r[5] -= p; while(p-- != 0) writem(r[5]++, r[2], 0); } break; case 0x46: p = readm(r[3]++, 0); if((ps & (FLAGN|FLAGZ)) == (FLAGN|FLAGZ)) writem(r[5] - p, r[2], 0); break; case 0x47: p = readm(r[3]++, 0); if((u16int)r[0] > p){ r[0] = (u16int) r[0]; i = r[0] - p; while(i-- > 0) if(editread() != 0) ps = ps & ~FLAGZ | FLAGV; }else r[0] = (u16int) r[0] | r[0] - p << 16; case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: for(; p > 0x80; p--) writem(r[5]++, r[2], 0); break; case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: for(; p > 0x90; p--){ c = editread(); if(c != 0) ps = ps & ~FLAGZ | FLAGC; if((ps & FLAGC) == 0) writem(r[5]++, r[2], 0); else writem(r[5]++, '0' + c, 0); } break; case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: for(; p > 0xa0; p--){ c = editread(); if(c != 0){ if((ps & FLAGC) == 0) writem(r[5]++, r[2] >> 8, 0); ps = ps & ~FLAGZ | FLAGC; } if((ps & FLAGC) == 0) writem(r[5]++, r[2], 0); else writem(r[5]++, '0' + c, 0); } break; default: sysfatal("editpc: unknown pattern %.2x (pc=%.8ux)", p, curpc); } } } void movp(void) { u16int l; u32int sa, da; u8int c, d; int i, n; l = readm(amode(1), 1); sa = addrof(amode(0)); da = addrof(amode(1)); n = l/2 + 1; ps = ps & ~(FLAGN|FLAGV) | FLAGZ; for(i = 0; i < n-1; i++){ c = readm(sa++, 0); writem(da++, c, 0); if(c != 0) ps &= ~FLAGZ; } c = readm(sa, 0); if((c & 0xf0) != 0) ps &= ~FLAGZ; d = c & 0xf0; c &= 0xf; if(c == 11 || c == 13) ps |= FLAGN; if((ps & (FLAGN|FLAGZ)) == (FLAGN|FLAGZ)) ps &= ~FLAGN; if((ps & FLAGN) != 0) d |= 13; else d |= 12; writem(da, d, 0); } static int cmpmag(u16int l1, u32int a1, u16int l2, u32int a2) { int i; u8int c1, c2; for(i = l1 > l2 ? l1 : l2; --i >= 0; ){ c1 = getdig(l1, a1, i); c2 = getdig(l2, a2, i); if(c1 > c2) return 1; if(c1 < c2) return -1; } return 0; } void addp(int rn, int sub) { u16int l1, l2, l3; u32int a1, a2, a3; s8int s1, s2; int c, i, l, t; l1 = readm(amode(1), 1); a1 = addrof(amode(0)); l2 = readm(amode(1), 1); a2 = addrof(amode(0)); if(rn == 6){ l3 = readm(amode(1), 1); a3 = addrof(amode(0)); }else{ l3 = l2; a3 = a2; } s1 = getsign(l1, a1); s2 = getsign(l2, a2); r[0] = 0; r[1] = sigdig(l1, a1); r[2] = 0; r[3] = sigdig(l2, a2); r[4] = 0; if(sub) s1 ^= -2; if(s1 == s2){ c = 0; l = l1; if(l2 > l) l = l2; if(l3 > l) l = l3; for(i = 0; i < l; i++){ t = c + getdig(l1, a1, i) + getdig(l2, a2, i); for(c = 0; t >= 10; c++) t -= 10; putdig(l3, a3, i, t); } }else{ if(cmpmag(l1, a1, l2, a2) < 0){ t = l1; l1 = l2; l2 = t; t = a1; a1 = a2; a2 = t; s1 = s2; } c = 0; l = l3 > l1 ? l3 : l1; for(i = 0; i < l; i++){ t = getdig(l1, a1, i) - getdig(l2, a2, i); for(c = 0; t < 0; c++) t += 10; putdig(l3, a3, i, t); } } if(c != 0) ps |= FLAGV; putsign(l3, a3, s1); r[5] = sigdig(l3, a3); } void cmpp(int rn) { u16int l1, l2; u32int a1, a2; s8int s1, s2; int rc; l1 = readm(amode(1), 1); a1 = addrof(amode(0)); if(rn == 4) l2 = readm(amode(1), 1); else l2 = l1; a2 = addrof(amode(0)); s1 = getsign(l1, a1); s2 = getsign(l2, a2); r[0] = 0; r[1] = sigdig(l1, a1); r[2] = 0; r[3] = sigdig(l2, a2); ps &= ~15; if(s1 != s2){ if(s1 < s2) ps |= FLAGN; return; } rc = cmpmag(l1, a1, l2, a2); if(rc == 0) ps |= FLAGZ; else if(rc > 0) ps |= FLAGN; } void ashp(void) { s8int cnt, rnd; s16int sl, dl; u32int sa, da; int i, c, x; cnt = readm(amode(0), 0); sl = readm(amode(1), 1); sa = addrof(amode(2)); rnd = readm(amode(0), 0); dl = readm(amode(1), 1); da = addrof(amode(2)); ps = ps & ~15 | FLAGZ; x = getsign(sl, sa); if(x < 0) ps |= FLAGN; putsign(dl, da, x); for(i = 0; i < cnt; i++) putdig(dl, da, i, 0); c = cnt < 0 && getdig(sl, sa, -1-cnt) >= rnd; for(i = cnt >= 0 ? 0 : -cnt; i < sl; i++){ x = getdig(sl, sa, i) + c; for(c = 0; x >= 10; c++) x -= 10; putdig(dl, da, i + cnt, x); if(x != 0) ps &= ~FLAGZ; } putdig(dl, da, i + cnt, c); r[0] = 0; r[1] = sigdig(sl, sa); r[2] = 0; r[3] = sigdig(dl, da); } void locc(int inv) { u8int chr; u16int len; u32int addr; chr = readm(amode(0), 0); len = readm(amode(1), 1); addr = addrof(amode(0)); ps &= ~15; for(; len != 0; addr++, len--) if(inv ^ (readm(addr, 0) == chr)) break; if(len == 0) ps |= FLAGZ; r[0] = len; r[1] = addr; } void cmpc(int op5) { u16int l1, l2; u32int a1, a2; u8int a, b, f; if(op5){ l1 = readm(amode(1), 1); a1 = addrof(amode(2)); f = readm(amode(0), 0); l2 = readm(amode(1), 1); a2 = addrof(amode(2)); }else{ l1 = l2 = readm(amode(1), 1); a1 = addrof(amode(2)); a2 = addrof(amode(2)); f = 0; } a = b = f; for(; l1 > 0 && l2 > 0; l1--, l2--, a1++, a2++){ a = readm(a1, 0); b = readm(a2, 0); if(a != b) goto ineq; } for(; l1 > 0; l1--, a1++){ a = readm(a1, 0); b = f; if(a != b) goto ineq; } for(; l2 > 0; l2--, a2++){ a = f; b = readm(a2, 0); if(a != b) goto ineq; } ineq: ps = ps & ~15; if((s8int)a < (s8int)b) ps |= FLAGN; if(a == b) ps |= FLAGZ; if(a < b) ps |= FLAGC; r[0] = l1; r[1] = a1; r[2] = l2; r[3] = a2; } void movc(int op5) { u16int sl, dl, l; u32int sa, da; int i; u8int f; sl = readm(amode(1), 1); sa = addrof(amode(0)); if(op5){ f = readm(amode(0), 0); dl = readm(amode(1), 1); }else{ f = 0; dl = sl; } da = addrof(amode(0)); l = sl < dl ? sl : dl; if(sa < da) for(i = l; --i >= 0; ) writem(da + i, readm(sa + i, 0), 0); else for(i = 0; i < l; i++) writem(da + i, readm(sa + i, 0), 0); for(i = l; i < dl; i++) writem(da + i, f, 0); r[0] = sl - l; r[1] = sa + sl; r[2] = 0; r[3] = da + dl; r[4] = 0; r[5] = 0; ps &= ~15; if((s16int) sl < (s16int) dl) ps |= FLAGN; else if(sl == dl) ps |= FLAGZ; if(sl < dl) ps |= FLAGC; }