/* * sc61860.js -- SHARP SC61860 (ESR-H) for Pocket/Portable Computer * Emulator JavaScript version * * Original C Language version: Copyright (C) 1994-2016 by Dai ISHIJIMA * 0.1: Oct. 3, 1995 by Dai ISHIJIMA * 0.2: May 1, 2014 (ina/keyscan/termios improvement) * 0.3: Jan. 4, 2016 (FreeBSD/Linux/MacOSX) * * JavaScript version: * 0.0: Jan. 24, 2016 * 0.1: Jan. 30, 2016 * 0.2: Feb. 16, 2024 (hankaku kana I/O) */ /* SC61860 registers */ var pc = 0x0000; var opcode = 0; var dp = 0x0000; var preg = 0; var qreg = 0; var rreg = 0; var dreg = 0; var alu = 0; var cflag = 0; var zflag = 0; var xin = 0; var opcode = 0; var ticks = 0; var ticks2 = 0; var div500 = 0; var div2 = 0; var XTICKS = 500; var XTICK2 = 200; var power_on = 0; var disp_on = 0; var kon = 1; var iaval = 0; var ibval = 0; var foval = 0; var ctrlval = 0; var iacnt = 0; var keychar = ''; var IRAMSIZ = (0x005f + 1); var iram = new Array(); /* registers on IRAM */ var IREG = 0; var JREG = 1; var AREG = 2; var BREG = 3; var XLREG = 4; var XHREG = 5; var YLREG = 6; var YHREG = 7; var KREG = 8; var LREG = 9; var MREG = 10; var NREG = 11; var IAPORT = 0x5c; var IBPORT = 0x5d; var FOPORT = 0x5e; var CTRLPORT = 0x5f; /* */ var keyque = -1; /* length of keyboard input buffer */ var nloops = 0; /* loops */ var oloops = 0; var kloops = 0; var MAXNLOOP = 2048; // 1000, 10, 30 -> 5min var SWAIT = 5; var LWAIT = 100; var msecwait = 10; var mainid; var statid; //var step = 1; var step = 0; var stepdebug = 0; var ndsteps = 0; //var MAXNDS = 4096; var MAXNDS = 8192; var traceiramdump = 1; /* load/save */ var iopos = -1; var OP_ESCAPE = 0x3f; var OP_RTN = 0x37; var BYTEOUT = 1; var BYTEIN = 2; var PCEOF = 032; var iochar = 0; var iomode = '#'; var opfreq = new Array(); /* 8bit, 16bit */ function hibyte(x) { return((parseInt(x, 10) & 0xff00) >> 8); } function lobyte(x) { return(parseInt(x, 10) & 0x00ff); } function hilo(hi, lo) { return( ((parseInt(hi, 10) & 0x00ff) << 8) | (parseInt(lo, 10) & 0x00ff) ); } function hex4(x) { var xx; var s; xx = parseInt(x, 10); if (isNaN(xx)) { scstatus(); return('NaN4'); } s = '' + "0000" + xx.toString(16); if (s.substr(s.length - 5, 1) != '0') { scstatus(); return('X' + s.substr(s.length - 3 , 3)); } return(s.substr(s.length - 4, 4)); } function hex2(x) { var xx; var s; xx = parseInt(x, 10); if (isNaN(xx)) { scstatus(); return('N2'); } s = '' + "00" + xx.toString(16); if (s.substr(s.length - 3, 1) != '0') { scstatus(); return('X' + s.substr(s.length - 1 , 1)); } return(s.substr(s.length - 2, 2)); } function iramr(adr) { var dat = 0; if ((adr < 0) || (0x5f < adr)) { scstatus(); alert('Invalid iram address to read: ' + hex4(adr)); } dat = iram[adr]; if ((dat < 0) || (0x00ff < dat)) { scstatus(); alert('Invalid iram value read: ' + hex4(dat) + ' at ' + hex4(adr)); } return(dat); } function iramw(adr, dat) { if ((adr < 0) || (0x5f < adr)) { scstatus(); alert('Invalid iram address to write:' + hex4(adr)); } if ((dat < 0) || (0x00ff < dat)) { scstatus(); alert('Invalid iram value written:' + hex4(dat) + ' at ' + hex4(adr)); } iram[adr] = dat; } /* read memory */ function memr(adr) { var dat = 0; if ((adr < 0) || (0xffff < adr)) { scstatus(); alert('Invalid mainram address to read:' + adr.toString(16)); } dat = mainram[adr]; if ((dat < 0) || (0x00ff < dat)) { scstatus(); alert('Invalid mainram value read:' + hex4(dat) + ' at ' + hex4(adr)); } return(dat); } /* write memory, check ROM address */ function memw(adr, dat) { if ((adr < 0) || (0xffff < adr)) { scstatus(); alert('Invalid mainram address to write: ' + adr.toString(16)); } if ((dat < 0) || (0x00ff < dat)) { scstatus(); alert('Invalid mainram value written: ' + hex4(dat) + ' at ' + hex4(adr)); } if ((0x2000 <= adr) && (adr <= 0x7fff)) { mainram[adr] = lobyte(dat); } else { scstatus(); alert('Wrote to ROM: ' + hex2(dat) + ' at ' + hex4(adr) + ', pc = ' + hex4(pc)); } } /* * short/unsigned char add/sub */ function add16(a, b) { var c = a + b; return(0xffff & c); } function sub16(a, b) { var c = a - b; return(0xffff & c); } function decr16(dat) { return(sub16(dat, 1)); } function incr16(dat) { return(add16(dat, 1)); } function add8(a, b) { var c = a + b; return(0x00ff & c); } function sub8(a, b) { var c = a - b; return(0x00ff & c); } function incr8(dat) { return(add8(dat, 1)); } function decr8(dat) { return(sub8(dat, 1)); } /* * operations */ /* secret */ function op35_mvwp() { pc = decr16(pc); dreg = incr8(iramr(IREG)); rreg = decr8(rreg); iramw(rreg, hibyte(pc)); rreg = decr8(rreg); iramw(rreg, lobyte(pc)); pc = hilo(iramr(BREG), iramr(AREG)); do { iramw(preg, memr(pc)); preg = incr8(preg); pc = incr16(pc); dreg = decr8(dreg); } while (dreg != 0); pc = incr16(hilo(iramr(rreg + 1), iramr(rreg))); rreg = add8(rreg, 2); } function opc6_tsma() { if ((iramr(preg) & iramr(AREG)) == 0) { zflag = 1; } else { zflag = 0; } } function op23_clra() { iramw(AREG, 0); } function op54_mvmp() { iramw(preg, memr(pc)); } function op56_ldpc() { iramw(AREG, memr(pc)); } function opd7_sz() { iramw(rreg - 1, memr(dp)); pc = incr16(pc); zflag = 1; } function op72_rz() { pc = incr16(pc); zflag = 0; } /* 8bits load */ function op20_ldp() { iramw(AREG, preg); } function op21_ldq() { iramw(AREG, qreg); } function op22_ldr() { iramw(AREG, rreg); } function op59_ldm() { iramw(AREG, iramr(preg)); } function op57_ldd() { iramw(AREG, memr(dp)); } function op02_lia() { iramw(AREG, memr(pc)); pc = incr16(pc); } function op03_lib() { iramw(BREG, memr(pc)); pc = incr16(pc); } function op01_lij() { iramw(JREG, memr(pc)); pc = incr16(pc); } function op00_lii() { iramw(IREG, memr(pc)); pc = incr16(pc); } function op12_lip() { preg = memr(pc); pc = incr16(pc); } function op80_lp() { preg = opcode & 0x3f; } function op30_stp() { preg = iramr(AREG); } function op31_stq() { qreg = iramr(AREG); } function op13_liq() { qreg = memr(pc); pc = incr16(pc); } function op32_str() { rreg = iramr(AREG); } function op11_lidl() { dp = hilo(hibyte(dp), memr(pc)); pc = incr16(pc); } function op52_std() { memw(dp, iramr(AREG)); } function op53_mvdm() { memw(dp, iramr(preg)); } function op55_mvmd() { iramw(preg, memr(dp)); } function opd8_leave() { iramw(rreg, 0); } function op5b_pop() { iramw(AREG, iramr(rreg)); rreg = incr8(rreg); } function op34_push() { rreg = decr8(rreg); iramw(rreg, iramr(AREG)); } /* 16bits load */ function op10_lidp() { dp = hilo(memr(pc), memr(pc + 1)); pc = add16(pc, 2); } /* block load, exchange */ function op0a_mvb() { dreg = incr8(iramr(JREG)); do { iramw(preg, iramr(qreg)); preg = incr8(preg); qreg = incr8(qreg); dreg = decr8(dreg); } while (dreg != 0); } function op08_mvw() { dreg = incr8(iramr(IREG)); do { iramw(preg, iramr(qreg)); preg = incr8(preg); qreg = incr8(qreg); dreg = decr8(dreg); } while (dreg != 0); } function op1a_mvbd() { dreg = incr8(iramr(JREG)); do { iramw(preg, memr(dp)); preg = incr8(preg); dp = incr16(dp); dreg = decr8(dreg); } while (dreg != 0); } function op18_mvwd() { dreg = incr8(iramr(IREG)); do { iramw(preg, memr(dp)); preg = incr8(preg); dp = incr16(dp); dreg = decr8(dreg); } while (dreg != 0); } function op1e_film() { dreg = incr8(iramr(IREG)); do { iramw(preg, iramr(AREG)); preg = incr8(preg); dreg = decr8(dreg); } while (dreg != 0); } function op1f_fild() { dreg = incr8(iramr(IREG)); do { memw(dp, iramr(AREG)); dp = incr16(dp); dreg = decr8(dreg); } while (dreg != 0); } function opda_exab() { var tempval = iramr(AREG); iramw(AREG, iramr(BREG)); iramw(BREG, tempval); } function opdb_exam() { var tempval = iramr(AREG); iramw(AREG, iramr(preg)); iramw(preg, tempval); } function op0b_exb() { var tempval = 0; dreg = incr8(iramr(JREG)); do { tempval = iramr(preg); iramw(preg, iramr(qreg)); iramw(qreg, tempval); preg = incr8(preg); qreg = incr8(qreg); dreg = decr8(dreg); } while (dreg != 0); } function op09_exw() { var tempval = 0; dreg = incr8(iramr(IREG)); do { tempval = iramr(preg); iramw(preg, iramr(qreg)); iramw(qreg, tempval); preg = incr8(preg); qreg = incr8(qreg); dreg = decr8(dreg); } while (dreg != 0); } function op19_exwd() { var tempval = 0; dreg = incr8(iramr(IREG)); do { tempval = memr(dp); memw(dp, iramr(preg)); iramw(preg, tempval); preg = incr8(preg); dp = incr16(dp); dreg = decr8(dreg); } while (dreg != 0); } function op1b_exbd() { var tempval = 0; dreg = incr8(iramr(JREG)); do { tempval = memr(dp); memw(dp, iramr(preg)); iramw(preg, tempval); preg = incr8(preg); dp = incr16(dp); dreg = decr8(dreg); } while (dreg!= 0); } function op58_swp() { var tempval = 0; /* shift lo nibble << 4 */ tempval = ((iramr(AREG) & 0x000f) << 4) /* shift hi nibble >> 4 */ | ((iramr(AREG) & 0x00f0) >> 4); iramw(AREG, tempval); } /* check condition, set flag */ function chkcz() { alu = alu & 0x0000ffff; if ((alu & 0x00ff) == 0) { zflag = 1; } else { zflag = 0; } if ((alu & 0xff00) != 0) { cflag = 1; } else { cflag = 0; } } /* 8bits operation */ function op74_adia() { alu = iramr(AREG) + memr(pc); pc = incr16(pc); iramw(AREG, lobyte(alu)); chkcz(); } function op70_adim() { alu = iramr(preg) + memr(pc); pc = incr16(pc); iramw(preg, lobyte(alu)); chkcz(); } function op44_adm() { alu = iramr(preg) + iramr(AREG); iramw(preg, lobyte(alu)); chkcz(); } function opc4_adcm() { alu = iramr(preg) + iramr(AREG) + cflag; iramw(preg, lobyte(alu)); chkcz(); } function op75_sbia() { alu = iramr(AREG) - memr(pc); pc = incr16(pc); iramw(AREG, lobyte(alu)); chkcz(); } function op71_sbim() { alu = iramr(preg) - memr(pc); pc = incr16(pc); iramw(preg, lobyte(alu)); chkcz(); } function op45_sbm() { alu = iramr(preg) - iramr(AREG); iramw(preg, lobyte(alu)); chkcz(); } function opc5_sbcm() { alu = iramr(preg) - iramr(AREG) - cflag; iramw(preg, lobyte(alu)); chkcz(); } function op42_inca() { qreg = 2; alu = iramr(AREG) + 1; iramw(AREG, lobyte(alu)); chkcz(); } function opc2_incb() { qreg = 3; alu = iramr(BREG) + 1; iramw(BREG, lobyte(alu)); chkcz(); } function op40_inci() { qreg = 0; alu = iramr(IREG) + 1; iramw(IREG, lobyte(alu)); chkcz(); } function opc0_incj() { qreg = 1; alu = iramr(JREG) + 1; iramw(JREG, lobyte(alu)); chkcz(); } function op48_inck() { qreg = 8; alu = iramr(KREG) + 1; iramw(KREG, lobyte(alu)); chkcz(); } function opc8_incl() { qreg = 9; alu = iramr(LREG) + 1; iramw(LREG, lobyte(alu)); chkcz(); } function op4a_incm() { qreg = 10; alu = iramr(MREG) + 1; iramw(MREG, lobyte(alu)); chkcz(); } function opca_incn() { qreg = 11; alu = iramr(NREG) + 1; iramw(NREG, lobyte(alu)); chkcz(); } function op50_incp() { preg = incr8(preg); } function op43_deca() { qreg = 2; alu = iramr(AREG) - 1; iramw(AREG, lobyte(alu)); chkcz(); } function opc3_decb() { qreg = 3; alu = iramr(BREG) - 1; iramw(BREG, lobyte(alu)); chkcz(); } function op41_deci() { qreg = 0; alu = iramr(IREG) - 1; iramw(IREG, lobyte(alu)); chkcz(); } function opc1_decj() { qreg = 1; alu = iramr(JREG) - 1; iramw(JREG, lobyte(alu)); chkcz(); } function op49_deck() { qreg = 8; alu = iramr(KREG) - 1; iramw(KREG, lobyte(alu)); chkcz(); } function opc9_decl() { qreg = 9; alu = iramr(LREG) - 1; iramw(LREG, lobyte(alu)); chkcz(); } function op4b_decm() { qreg = 10; alu = iramr(MREG) - 1; iramw(MREG, lobyte(alu)); chkcz(); } function opcb_decn() { qreg = 11; alu = iramr(NREG) - 1; iramw(NREG, lobyte(alu)); chkcz(); } function op51_decp() { preg = decr8(preg); } function op64_ania() { alu = iramr(AREG) & memr(pc); pc = incr16(pc); iramw(AREG, lobyte(alu)); if (alu == 0) { zflag = 1; } else { zflag = 0; } } function op46_anma() { alu = iramr(preg) & iramr(AREG); iramw(preg, lobyte(alu)); if (alu == 0) { zflag = 1; } else { zflag = 0; } } function op60_anim() { alu = iramr(preg) & memr(pc); pc = incr16(pc); iramw(preg, lobyte(alu)); if (alu == 0) { zflag = 1; } else { zflag = 0; } } function opd4_anid() { iramw(rreg - 1, memr(dp)); memw(dp, memr(dp) & memr(pc)); pc = incr16(pc); if (memr(dp) == 0) { zflag = 1; } else { zflag = 0; } } function op65_oria() { alu = iramr(AREG) | memr(pc); pc = incr16(pc); iramw(AREG, lobyte(alu)); if (alu == 0) { zflag = 1; } else { zflag = 0; } } function op47_orma() { alu = iramr(preg) | iramr(AREG); iramw(preg, lobyte(alu)); if (alu == 0) { zflag = 1; } else { zflag = 0; } } function op61_orim() { alu = iramr(preg) | memr(pc); pc = incr16(pc); iramw(preg, lobyte(alu)); if (alu == 0) { zflag = 1; } else { zflag = 0; } } function opd5_orid() { iramw(rreg - 1, memr(dp)); memw(dp, memr(dp) | memr(pc)); pc = incr16(pc); if (memr(dp) == 0) { zflag = 1; } else { zflag = 0; } } function op67_cpia() { alu = iramr(AREG) - memr(pc); pc = incr16(pc); chkcz(); } function opc7_cpma() { alu = iramr(preg) - iramr(AREG); chkcz(); } function op63_cpim() { alu = iramr(preg) - memr(pc); pc = incr16(pc); chkcz(); } /* 16bits operation */ function op14_adb() { var xx; var pp; xx = hilo(iramr(preg + 1), iramr(preg)); xx += hilo(iramr(BREG), iramr(AREG)); iramw(preg, lobyte(xx)); pp = incr8(preg); iramw(pp, hibyte(xx)); preg = pp; if ((xx & 0x0000ffff) == 0) { zflag = 1; } else { zflag = 0; } if ((xx & 0xffff0000) != 0) { cflag = 1; } else { cflag = 0; } } function op15_sbb() { var xx; var pp; xx = hilo(iramr(preg + 1), iramr(preg)); xx -= hilo(iramr(BREG), iramr(AREG)); iramw(preg, lobyte(xx)); pp = incr8(preg); iramw(pp, hibyte(xx)); preg = pp; if ((xx & 0x0000ffff) == 0) { zflag = 1; } else { zflag = 0; } if ((xx & 0xffff0000) != 0) { cflag = 1; } else { cflag = 0; } } /* inc/dec load/store */ function op04_ix() { qreg = 5; dp = incr16(hilo(iramr(XHREG), iramr(XLREG))); iramw(XHREG, hibyte(dp)); iramw(XLREG, lobyte(dp)); } function op06_iy() { qreg = 7; dp = incr16(hilo(iramr(YHREG), iramr(YLREG))); iramw(YHREG, hibyte(dp)); iramw(YLREG, lobyte(dp)); } function op05_dx() { qreg = 5; dp = decr16(hilo(iramr(XHREG), iramr(XLREG))); iramw(XHREG, hibyte(dp)); iramw(XLREG, lobyte(dp)); } function op07_dy() { qreg = 7; dp = decr16(hilo(iramr(YHREG), iramr(YLREG))); iramw(YHREG, hibyte(dp)); iramw(YLREG, lobyte(dp)); } function op24_ixl() { qreg = 5; dp = incr16(hilo(iramr(XHREG), iramr(XLREG))); iramw(AREG, memr(dp)); iramw(XHREG, hibyte(dp)); iramw(XLREG, lobyte(dp)); } function op26_iys() { qreg = 7; dp = incr16(hilo(iramr(YHREG), iramr(YLREG))); memw(dp, iramr(AREG)); iramw(YHREG, hibyte(dp)); iramw(YLREG, lobyte(dp)); } function op25_dxl() { qreg = 5; dp = decr16(hilo(iramr(XHREG), iramr(XLREG))); iramw(AREG, memr(dp)); iramw(XHREG, hibyte(dp)); iramw(XLREG, lobyte(dp)); } function op27_dys() { qreg = 7; dp = decr16(hilo(iramr(YHREG), iramr(YLREG))); memw(dp, iramr(AREG)); iramw(YHREG, hibyte(dp)); iramw(YLREG, lobyte(dp)); } /* rotate / shift */ function opd2_sr() { alu = (cflag << 8) | iramr(AREG); iramw(AREG, lobyte(alu >> 1)); if ((alu & 1) != 0) { cflag = 1; } else { cflag = 0; } } function op5a_sl() { alu = (iramr(AREG) << 1) | cflag; iramw(AREG, lobyte(alu)); if ((alu & 0xff00) != 0) { cflag = 1; } else { cflag = 0; } } function op1c_srw() { dreg = incr8(iramr(IREG)); alu = 0; do { alu = (alu << 8) | iramr(preg); iramw(preg, lobyte(alu >> 4)); preg = incr8(preg); dreg = decr8(dreg); } while (dreg != 0); } function op1d_slw() { dreg = incr8(iramr(IREG)); alu = 0; do { alu = (iramr(preg) << 8) | (alu >> 8); iramw(preg, lobyte(alu >> 4)); preg = decr8(preg); dreg = decr8(dreg); } while (dreg != 0); } /* bit test */ function op66_tsia() { if ((iramr(AREG) & memr(pc)) == 0) { zflag = 1; } else { zflag = 0; } pc = incr16(pc); } function op62_tsim() { if ((iramr(preg) & memr(pc)) == 0) { zflag = 1; } else { zflag = 0; } pc = incr16(pc); } function opd6_tsid() { iramw(rreg - 1, memr(dp)); if ((memr(dp) & memr(pc)) == 0) { zflag = 1; } else { zflag = 0; } pc = incr16(pc); } function op4f_cup() { dreg = incr8(iramr(IREG)); zflag = 0; if (xin == 0) { do { preg = incr8(preg); dreg = decr8(dreg); } while ((!xin) && (dreg != 0x00ff)); if (xin == 0) { zflag = 1; } } } function op6f_cdn() { dreg = incr8(iramr(IREG)); zflag = 0; if (xin) { do { preg = incr8(preg); dreg = decr8(dreg); } while (xin && (dreg != 0xff)); if (xin) { zflag = 1; } } } /* BCD operation */ function deciadd(p, q) { var ans = 0; ans = (p & 0x000f) + (q & 0x000f); if (ans > 0x0009) { ans += 6; } ans += (p & 0x00f0) + (q & 0x00f0); if ((ans & 0xfff0) > 0x0090) { ans += 0x60; } return(ans & 0x01ff); } function decisub(p, q) { var ans = 0; ans = ((p & 0x000f) - (q & 0x000f)) & 0xffff; if (ans > 0x0009) { ans -= 0x06; } ans = (ans + ((p & 0x00f0) - (q & 0x00f0))) & 0xffff; if ((ans & 0xfff0) > 0x0090) { ans -= 0x60; } return(ans & 0x1ff); } function op0c_adn() { dreg = incr8(iramr(IREG)); alu = iramr(AREG); zflag = 1; do { alu = deciadd(iramr(preg), alu); iramw(preg, lobyte(alu)); if ((zflag != 0) && (iramr(preg) == 0)) { zflag = 1; } else { zflag = 0; } preg = decr8(preg); dreg = decr8(dreg); alu >>= 8; } while (dreg != 0); if (alu != 0) { cflag = 1; } else { cflag = 0; } } function op0d_sbn() { dreg = incr8(iramr(IREG)); alu = iramr(AREG); zflag = 1; do { alu = decisub(iramr(preg), alu); iramw(preg, lobyte(alu)); if ((zflag != 0) && (iramr(preg) == 0)) { zflag = 1; } else { zflag = 0; } preg = decr8(preg); dreg = decr8(dreg); alu >>= 8; } while (dreg != 0); if (alu != 0) { cflag = 1; } else { cflag = 0; } } function op0e_adw() { dreg = incr8(iramr(IREG)); alu = 0; zflag = 1; do { alu = deciadd(iramr(preg), alu); alu = (alu & 0x0100) | deciadd(lobyte(alu), iramr(qreg)); iramw(preg, lobyte(alu)); if ((zflag != 0) && (iramr(preg) == 0)) { zflag = 1; } else { zflag = 0; } preg = decr8(preg); qreg = decr8(qreg); dreg = decr8(dreg); alu >>= 8; } while (dreg != 0); if (alu != 0) { cflag = 1; } else { cflag = 0; } } function op0f_sbw() { dreg = incr8(iramr(IREG)); alu = 0; zflag = 1; do { alu = decisub(iramr(preg), alu); alu = (alu & 0x0100) | decisub(lobyte(alu), iramr(qreg)); iramw(preg, lobyte(alu)); if ((zflag != 0) && (iramr(preg) == 0)) { zflag = 1; } else { zflag = 0; } preg = decr8(preg); qreg = decr8(qreg); dreg = decr8(dreg); alu >>= 8; } while (dreg != 0); if (alu != 0) { cflag = 1; } else { cflag = 0; } } /* jumps */ function op2c_jrp() { pc = add16(pc, memr(pc)); } function op2d_jrm() { pc = sub16(pc, memr(pc)); } function op38_jrzp() { if (zflag != 0) { pc = add16(pc, memr(pc)); } else { pc = incr16(pc); } } function op39_jrzm() { if (zflag != 0) { pc = sub16(pc, memr(pc)); } else { pc = incr16(pc); } } function op28_jrnzp() { if (zflag == 0) { pc = add16(pc, memr(pc)); } else { pc = incr16(pc); } } function op29_jrnzm() { if (zflag == 0) { pc = sub16(pc, memr(pc)); } else { pc = incr16(pc); } } function op3a_jrcp() { if (cflag != 0) { pc = add16(pc, memr(pc)); } else { pc = incr16(pc); } } function op3b_jrcm() { if (cflag != 0) { pc = sub16(pc, memr(pc)); } else { pc = incr16(pc); } } function op2a_jrncp() { if (cflag == 0) { pc = add16(pc, memr(pc)); } else { pc = incr16(pc); } } function op2b_jrncm() { if (cflag == 0) { pc = sub16(pc, memr(pc)); } else { pc = incr16(pc); } } function op79_jp() { pc = hilo(memr(pc), memr(pc + 1)); } function op7e_jpz() { if (zflag != 0) { pc = hilo(memr(pc), memr(pc + 1)); } else { pc = add16(pc, 2); } } function op7c_jpnz() { if (zflag == 0) { pc = hilo(memr(pc), memr(pc + 1)); } else { pc = add16(pc, 2); } } function op7f_jpc() { if (cflag != 0) { pc = hilo(memr(pc), memr(pc + 1)); } else { pc = add16(pc, 2); } } function op7d_jpnc() { if (cflag == 0) { pc = hilo(memr(pc), memr(pc + 1)); } else { pc = add16(pc, 2); } } function op2f_loop() { alu = iramr(rreg); --alu; iramw(rreg, lobyte(alu)); chkcz(); if (cflag != 0) { pc = incr16(pc); } else { pc = sub16(pc, memr(pc)); } } function op7a_case1() { dreg = memr(pc); pc = incr16(pc); rreg = decr8(rreg); iramw(rreg, memr(pc)); pc = incr16(pc); rreg = decr8(rreg); iramw(rreg, memr(pc)); pc = incr16(pc); } function op69_case2() { do { pc = incr16(pc); if (iramr(AREG) == memr(pc - 1)) { pc = hilo(memr(pc), memr(pc + 1)); break; } else { pc = add16(pc, 2); } dreg = decr8(dreg); } while (dreg != 0); if (dreg == 0) { pc = hilo(memr(pc), memr(pc + 1)); } } function opex_cal() { pc = incr16(pc); rreg = decr8(rreg); iramw(rreg, hibyte(pc)); rreg = decr8(rreg); iramw(rreg, lobyte(pc)); pc = hilo(opcode & 0x001f, memr(pc - 1)); } function op78_call() { pc = add16(pc, 2); rreg = decr8(rreg); iramw(rreg, hibyte(pc)); rreg = decr8(rreg); iramw(rreg, lobyte(pc)); pc = hilo(memr(pc - 2), memr(pc - 1)); } function op37_rtn() { pc = hilo(iramr(rreg + 1), iramr(rreg)); rreg = add8(rreg, 2); } function op5d_outa() { var newia; // newia = iramr[IAPORT]; newia = iramr(IAPORT); if ((newia != 0) && (newia != iaval)) { iacnt = incr16(iacnt); if ((keychar.length <= 0) && (kbdcheck() > 0)) { keychar = ttyin(); keyscan(keychar); iacnt = 0; } if (32 < iacnt) { keyclear(); } if (64 < iacnt) { keychar = ''; } if (96 < iacnt) { iacnt = 0; } } qreg = IAPORT; iaval = iramr(IAPORT); } function opdd_outb() { qreg= IBPORT; ibval = iramr(IBPORT); } function op5f_outf() { qreg= FOPORT foval = iramr(FOPORT); } function opdf_outc() { qreg = CTRLPORT; ctrlval = iramr(CTRLPORT); disp_on = ctrlval & 1; if (disp_on != 0) { // busy(); ; } if ((ctrlval & 2) != 0) { ticks = 0; ticks2 = 0; div500 = 0; div2 = 0; } if ((ctrlval & 8) != 0) { power_on = 1; } else { //power_on = 0; power_on = 1; } } function bit(ii) { var jj; for (jj = 0; jj < 8; jj++) { if (ii & 1) { break; } ii >>= 1; } return(jj); } function op4c_ina() { var ii; var jj; iramw(AREG, 0); if ((iaval == 0) && (memr(0x7e00) != 0)) { jj = bit(memr(0x7e00)); if (jj < 7) { iramw(AREG, keym[jj]); } } else { jj = bit(iaval); if (jj < 7) { iramw(AREG, keym[jj + 7]); } } if (iramr(AREG) == 0) { zflag = 1; } else { zflag = 0; } } function opcc_inb() { iramw(AREG, 0x38); if (iramr(AREG) == 0) { zflag = 1; } else { zflag = 0; } } function opd0_sc() { cflag = 1; zflag = 1; } function opd1_rc() { cflag = 0; zflag = 1; } function opxx_nop() { /* no operation */ } function op4e_wait() { pc = incr16(pc); } function op6b_test() { testport = 0; if (div2 != 0) { testport |= 1; } if (div500 != 0) { testport |= 2; } if (kon != 0) { testport |= 8; } if ((testport & memr(pc)) == 0) { zflag = 1; } else { zflag = 0; } pc = incr16(pc); } /* undefined code */ function opxx_undef() { scstatus(); alert("Undefined code: " + hex2(opcode) + " at " + hex4(pc)); } /* escape load/save */ function op3f_escape() { var inout; var ch; var f = iowin.document.forms[0]; inout = memr(pc); pc = incr16(pc); if (iopos < 0) { return; } if (inout == BYTEOUT) { ch = iramr(AREG); if (ch == 015) { ch = 012; } iochar = ch; iomode = 'O'; if (ch == PCEOF) { iowin.focus(); } else { if ((0xa0 <= ch) && (ch <= 0xdf)) { f.loadsave.value += String.fromCharCode(0xff00 + ch - 0x40); } else { f.loadsave.value += String.fromCharCode(ch); } } } if (inout == BYTEIN) { if (iopos >= f.loadsave.value.length) { iramw(AREG, PCEOF); iramw(0x0e, iramr(0x0e) | 0x80); } else { ch = f.loadsave.value.charCodeAt(iopos); if (ch > 0xff00) { ch = (ch & 0xff) + 0x40; } ++iopos; //alert("" + iopos + " " + hex2(ch)); iochar = ch; iomode = 'I'; if (ch == 012) { iramw(AREG, 015); iramw(0x0e, iramr(0x0e) | 0x40); } else { iramw(AREG, lobyte(ch)); iramw(0x0e, iramr(0x0e) & 0x3f); } } cflag = 0; zflag = 0; preg = 0x0e; } return; } /* break point */ function opcf_break() { scstatus(); alert('breakpoint'); } /* */ var opfunc = new Array( op00_lii, op01_lij, op02_lia, op03_lib, op04_ix, op05_dx, op06_iy, op07_dy, op08_mvw, op09_exw, op0a_mvb, op0b_exb, op0c_adn, op0d_sbn, op0e_adw, op0f_sbw, /* 1x */ op10_lidp, op11_lidl, op12_lip, op13_liq, op14_adb, op15_sbb, opxx_undef, opxx_undef, op18_mvwd, op19_exwd, op1a_mvbd, op1b_exbd, op1c_srw, op1d_slw, op1e_film, op1f_fild, /* 2x */ op20_ldp, op21_ldq, op22_ldr, op23_clra, op24_ixl, op25_dxl, op26_iys, op27_dys, op28_jrnzp, op29_jrnzm, op2a_jrncp, op2b_jrncm, op2c_jrp, op2d_jrm, opxx_undef, op2f_loop, /* 3x */ op30_stp, op31_stq, op32_str, opxx_nop, op34_push, op35_mvwp, opxx_undef, op37_rtn, op38_jrzp, op39_jrzm, op3a_jrcp, op3b_jrcm, opxx_undef, opxx_undef, opxx_undef, op3f_escape, /* 4x */ op40_inci, op41_deci, op42_inca, op43_deca, op44_adm, op45_sbm, op46_anma, op47_orma, op48_inck, op49_deck, op4a_incm, op4b_decm, op4c_ina, opxx_nop, op4e_wait, op4f_cup, /* 5x */ op50_incp, op51_decp, op52_std, op53_mvdm, op54_mvmp, op55_mvmd, op56_ldpc, op57_ldd, op58_swp, op59_ldm, op5a_sl, op5b_pop, opxx_undef, op5d_outa, opxx_undef, op5f_outf, /* 6x */ op60_anim, op61_orim, op62_tsim, op63_cpim, op64_ania, op65_oria, op66_tsia, op67_cpia, opxx_nop, op69_case2, opxx_nop, op6b_test, opxx_undef, opxx_undef, opxx_undef, op6f_cdn, /* 7x */ op70_adim, op71_sbim, op72_rz, op72_rz, op74_adia, op75_sbia, op72_rz, op72_rz, op78_call, op79_jp, op7a_case1, opxx_undef, op7c_jpnz, op7d_jpnc, op7e_jpz, op7f_jpc, /* 8x */ op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, /* 9x */ op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, /* Ax */ op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, /* Bx */ op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, op80_lp, /* Cx */ opc0_incj, opc1_decj, opc2_incb, opc3_decb, opc4_adcm, opc5_sbcm, opc6_tsma, opc7_cpma, opc8_incl, opc9_decl, opca_incn, opcb_decn, opcc_inb, opxx_nop, opxx_nop, opcf_break, /* Dx */ opd0_sc, opd1_rc, opd2_sr, opxx_nop, opd4_anid, opd5_orid, opd6_tsid, opd7_sz, opd8_leave, opxx_nop, opda_exab, opdb_exam, opxx_undef, opdd_outb, opxx_undef, opdf_outc, /* Ex */ opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, /* Fx */ opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal, opex_cal ); function tictac() { if (++ticks >= XTICKS) { if (div500 == 0) { div500 = 1; } else { div500 = 0; } if (++ticks2 >= XTICK2) { if (div2 == 0) { div2 = 1; } else { div2 = 0; } ticks2 = 0; } ticks = 0; } } function interpret() { var dname; var i; tictac(); // if (pc == 0x924e) { // sin 30 がエラー // stepdebug = 1; // } // if (pc == 0x921f) { // 1/3 がエラー // stepdebug = 1; // } opcode = memr(pc); if (step != 0) { scstatus(); alert( '' + opfunc[opcode].name + '(' + hex2(opcode) + ') at ' + hex4(pc) ); } if ((ndsteps < MAXNDS) && (stepdebug != 0)) { dname = opfunc[opcode].name + ' '; if ((ndsteps % 256) == 0) { debugwin.document.forms[0].debuginfo.value += 'addr +0 +1 +2 opcode ' + ' p q r ' + ' i j a b ' + ' xl xh yl yh' + ' c z ' + ' dp' + "\n" + 'K..N:' + ' ' + hex2(KREG) + ' ' + hex2(LREG) + ' ' + hex2(MREG) + ' ' + hex2(NREG) + ' ABFC:' + ' ' + hex2(iramr(IAPORT)) + ' ' + hex2(iramr(IBPORT)) + ' ' + hex2(iramr(FOPORT)) + ' ' + hex2(iramr(CTRLPORT)) + ' abfct:' + ' ' + hex2(iaval) + ' ' + hex2(ibval) + ' ' + hex2(foval) + ' ' + hex2(ctrlval) + ' ' + hex2(testport) + "\n" ; } if ((ndsteps % 32) == 0) { debugwin.document.forms[0].debuginfo.value += 'addr +0 +1 +2 opcode ' + ' p q r ' + ' i j a b ' + ' xl xh yl yh' + ' c z ' + ' dp' + "\n" ; } if ((opcode == 0x00c7) || (opcode == 0x000c)) { // cpma || adn traceiramdump = -2; } if (traceiramdump < 0) { debugwin.document.forms[0].debuginfo.value += "irams[00] =" ; for (i = 0; i < 16; i++) { debugwin.document.forms[0].debuginfo.value += ' ' + hex2(iramr(i)); } debugwin.document.forms[0].debuginfo.value += "\n" ; debugwin.document.forms[0].debuginfo.value += "irams[10] =" ; for (i = 16; i < 32; i++) { debugwin.document.forms[0].debuginfo.value += ' ' + hex2(iramr(i)); } debugwin.document.forms[0].debuginfo.value += "\n" ; } debugwin.document.forms[0].debuginfo.value += hex4(pc) + ' ' + hex2(memr(pc)) + ' ' + hex2(memr(pc + 1)) + ' ' + hex2(memr(pc + 2)) + ' ' + dname.substr(5, 8) + '' + hex2(preg) + ' ' + hex2(qreg) + ' ' + hex2(rreg) + ' ' + hex2(iramr(IREG)) + ' ' + hex2(iramr(JREG)) + ' ' + hex2(iramr(AREG)) + ' ' + hex2(iramr(BREG)) + ' ' + hex2(iramr(XLREG)) + ' ' + hex2(iramr(XHREG)) + ' ' + hex2(iramr(YLREG)) + ' ' + hex2(iramr(YHREG)) + ' ' + cflag + ' ' + zflag + ' ' + hex4(dp) + "\n" ; ++ndsteps; ++traceiramdump; } pc = incr16(pc); opfunc[opcode](); ++opfreq[opcode]; if (preg >= 0x60) { scstatus(); alert('invalid preg value: ' + hex2(preg) + ' at ' + hex4(pc)); } return(pc); } /* main loop */ function mainloop() { ++oloops; power_on = 1; nloops = 0; msecwait = parseInt(document.forms[0].sc_throttling.value, 10); do { interpret(); /* OPコード解釈 */ ++nloops; if (nloops > MAXNLOOP) { nloops = 0; } } while (nloops > 0); //if (keychar.length <= 0) { /* キー入力がなければ長く待つ */ if ((disp_on != 0) && (document.forms[0].more_delay.checked)) { msecwait *= 20; if (msecwait > 200) { msecwait = 200; } } mainid = setTimeout("mainloop()", msecwait); } function clearsc() { for (dp = 0x2000; dp < 0x7fff; dp++) { memw(dp, 0); } for (preg = 0; preg < 0x5f; preg++) { iramw(preg, 0); } } function initsc() { var i; pc = 0x0000; dp = 0x0000; preg = 0; qreg = 0; rreg = IRAMSIZ; cflag = 0; zflag = 0; ticks = 0; power_on = 1; kon = 0; iaval = 0; ibval = 0; foval = 0; for (i = 0; i < IRAMSIZ; i++) { iram[i] = 0; } for (i = 0; i < 256; i++) { opfreq[i] = 0; } for (i = 0x2000; i < 0x8000; i++) { // 2016-02-21 memw(i, 0); } mainram[0xed34] = OP_ESCAPE; mainram[0xed35] = BYTEOUT; mainram[0xed36] = OP_RTN; mainram[0xec2e] = OP_ESCAPE; mainram[0xec2f] = BYTEIN; mainram[0xec30] = OP_RTN; mainram[0xeaa8] = 0xd0; mainram[0xeaa9] = OP_RTN; } function scstatus() { var kbchar; var chario; var code; document.getElementById("showpc").innerHTML = hex4(pc); document.getElementById("showpreg").innerHTML = hex2(preg); document.getElementById("showqreg").innerHTML = hex2(qreg); document.getElementById("showrreg").innerHTML = hex2(rreg); document.getElementById("showdp").innerHTML = hex4(dp); document.getElementById("showireg").innerHTML = hex2(iramr(IREG)); document.getElementById("showjreg").innerHTML = hex2(iramr(JREG)); document.getElementById("showareg").innerHTML = hex2(iramr(AREG)); document.getElementById("showbreg").innerHTML = hex2(iramr(BREG)); document.getElementById("showxlreg").innerHTML = hex2(iramr(XLREG)); document.getElementById("showxhreg").innerHTML = hex2(iramr(XHREG)); document.getElementById("showylreg").innerHTML = hex2(iramr(YLREG)); document.getElementById("showyhreg").innerHTML = hex2(iramr(YHREG)); document.getElementById("showkreg").innerHTML = hex2(iramr(KREG)); document.getElementById("showlreg").innerHTML = hex2(iramr(LREG)); document.getElementById("showmreg").innerHTML = hex2(iramr(MREG)); document.getElementById("shownreg").innerHTML = hex2(iramr(NREG)); document.getElementById("showcflag").innerHTML = hex2(cflag); document.getElementById("showzflag").innerHTML = hex2(zflag); if (disp_on != 0) { document.getElementById("showdisp").innerHTML = 'on'; document.getElementById("busymark").style.color = "#f0f0f0"; } else { document.getElementById("showdisp").innerHTML = 'off'; document.getElementById("busymark").style.color = "#101010"; } document.getElementById("showpower").innerHTML = hex2(power_on); if (keychar.length <= 0) { kbchar = '00(.)'; } else { code = keychar.charCodeAt(0); kbchar = hex2(code); if ((' ' <= keychar) && (keychar <= '~')) { kbchar = kbchar + '(' + keychar + ')'; } else { kbchar = kbchar + '(.)'; } } // if (kon != 0) { //kbchar = kbchar + kon; kbchar = kbchar + '!'; } document.getElementById("showkb").innerHTML = kbchar; chario = iomode; chario += hex2(iochar); if ((0x20 <= iochar) && (iochar <= 0x7f)) { chario += '(' + String.fromCharCode(iochar) + ')'; } else { chario += '(.)'; } document.getElementById("showio").innerHTML = chario; // document.getElementById("nowop").innerHTML = opfunc[opcode].name; document.getElementById("show7e00").innerHTML = hex2(memr(0x7e00)); document.getElementById("showaport").innerHTML = hex2(iaval); document.getElementById("showbport").innerHTML = hex2(ibval); document.getElementById("showcport").innerHTML = hex2(ctrlval); document.getElementById("showfoport").innerHTML = hex2(foval); document.getElementById("showk0").innerHTML = hex2(keym[0]); document.getElementById("showk1").innerHTML = hex2(keym[1]); document.getElementById("showk2").innerHTML = hex2(keym[2]); document.getElementById("showk3").innerHTML = hex2(keym[3]); document.getElementById("showk4").innerHTML = hex2(keym[4]); document.getElementById("showk5").innerHTML = hex2(keym[5]); document.getElementById("showk6").innerHTML = hex2(keym[6]); document.getElementById("showmsecwait").innerHTML = '' + msecwait; } function statusloop() { scstatus(); statid = setTimeout("statusloop()", 150); } /* EOF */