/* * Simulator of microcontrollers (inst.cc) * * hc08 code base from Erik Petrich epetrich@users.sourceforge.net * * Copyright (C) 1999,99 Drotos Daniel, Talker Bt. * * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu * */ /* This file is part of microcontroller simulator: ucsim. UCSIM is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. UCSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with UCSIM; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*@1@*/ #include "ddconfig.h" #include "stdio.h" #include // local #include "hc08cl.h" #include "regshc08.h" #include "hc08mac.h" void cl_hc08::incx(void) { int hx = (regs.H << 8) | (regs.X); hx++; regs.H = (hx >> 8) & 0xff; regs.X = hx & 0xff; } int cl_hc08::fetch2(void) { int result; result = fetch() << 8; result |= fetch(); tick(2); return result; } int cl_hc08::fetchea(t_mem code, bool prefix) { switch ((code >> 4) & 0x0f) { case 0x0: case 0x1: case 0x3: case 0xb: tick(1); return fetch(); // Direct case 0x7: case 0xf: tick(1); // extra cycle needed, even without fetch return (regs.H << 8) | regs.X; // IX case 0x6: case 0xe: tick(1); if (!prefix) return ((unsigned char)fetch())+((regs.H << 8) | regs.X); // IX1 else return ((unsigned char)fetch())+regs.SP; // SP1 case 0xd: if (!prefix) return fetch2()+((regs.H << 8) | regs.X); // IX2 else return fetch2()+regs.SP; // SP2 case 0xc: return fetch2(); default: return(resHALT); } } int cl_hc08::inst_nop(t_mem code, bool prefix) { return(resGO); } int cl_hc08::inst_transfer(t_mem code, bool prefix) { int hx; switch (code) { case 0x84: // TAP regs.P = regs.A | 0x60; break; case 0x85: // TPA regs.A = regs.P | 0x60; break; case 0x97: // TAX regs.X = regs.A; break; case 0x9f: // TXA regs.A = regs.X; break; case 0x94: // TXS hx = (regs.H << 8) | regs.X; regs.SP = (hx - 1) & 0xffff; break; case 0x95: // TSX hx = regs.SP +1; regs.H = (hx >> 8) & 0xff; regs.X = hx & 0xff; break; default: return(resHALT); } return(resGO); } int cl_hc08::inst_setclearflags(t_mem code, bool prefix) { switch (code) { case 0x98: regs.P &= ~BIT_C; break; case 0x99: regs.P |= BIT_C; break; case 0x9a: regs.P &= ~BIT_I; break; case 0x9b: regs.P |= BIT_I; break; default: return(resHALT); } return(resGO); } int cl_hc08::inst_rsp(t_mem code, bool prefix) { regs.SP = 0x00ff; return(resGO); } int cl_hc08::inst_nsa(t_mem code, bool prefix) { regs.A = ((regs.A & 0xf0)>>4) | ((regs.A & 0x0f)<<4); return(resGO); } int cl_hc08::inst_lda(t_mem code, bool prefix) { regs.A = OPERAND(code, prefix); tick(1); FLAG_CLEAR(BIT_V); FLAG_NZ(regs.A); return(resGO); } int cl_hc08::inst_ldx(t_mem code, bool prefix) { regs.X = OPERAND(code, prefix); tick(1); FLAG_CLEAR(BIT_V); FLAG_NZ(regs.X); return(resGO); } int cl_hc08::inst_sta(t_mem code, bool prefix) { int ea = fetchea(code, prefix); FLAG_CLEAR(BIT_V); FLAG_NZ(regs.A); store1(ea, regs.A); tick(1); return(resGO); } int cl_hc08::inst_stx(t_mem code, bool prefix) { int ea = fetchea(code, prefix); FLAG_CLEAR(BIT_V); FLAG_NZ(regs.X); store1(ea, regs.X); tick(1); return(resGO); } int cl_hc08::inst_add(t_mem code, bool prefix) { int result, operand1, operand2; operand1 = regs.A; operand2 = OPERAND(code, prefix); tick(1); result = operand1 + operand2; FLAG_NZ (result); FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); FLAG_ASSIGN (BIT_C, 0x100 & result); FLAG_ASSIGN (BIT_H, 0x10 & (operand1 ^ operand2 ^ result)); regs.A = result & 0xff; return(resGO); } int cl_hc08::inst_adc(t_mem code, bool prefix) { int result, operand1, operand2; int carryin = (regs.P & BIT_C)!=0; operand1 = regs.A; operand2 = OPERAND(code, prefix); tick(1); result = operand1 + operand2 + carryin; FLAG_NZ (result); FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); FLAG_ASSIGN (BIT_C, 0x100 & result); FLAG_ASSIGN (BIT_H, 0x10 & (operand1 ^ operand2 ^ result)); regs.A = result & 0xff; return(resGO); } int cl_hc08::inst_sub(t_mem code, bool prefix) { int result, operand1, operand2; operand1 = regs.A; operand2 = OPERAND(code, prefix); tick(1); result = operand1 - operand2; FLAG_NZ (result); FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); FLAG_ASSIGN (BIT_C, 0x100 & result); regs.A = result & 0xff; return(resGO); } int cl_hc08::inst_sbc(t_mem code, bool prefix) { int result, operand1, operand2; int carryin = (regs.P & BIT_C)!=0; operand1 = regs.A; operand2 = OPERAND(code, prefix); tick(1); result = operand1 - operand2 - carryin; FLAG_NZ (result); FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); FLAG_ASSIGN (BIT_C, 0x100 & result); regs.A = result & 0xff; return(resGO); } int cl_hc08::inst_cmp(t_mem code, bool prefix) { int result, operand1, operand2; operand1 = regs.A; operand2 = OPERAND(code, prefix); tick(1); result = operand1 - operand2; FLAG_NZ (result); FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); FLAG_ASSIGN (BIT_C, 0x100 & result); return(resGO); } int cl_hc08::inst_cpx(t_mem code, bool prefix) { int result, operand1, operand2; operand1 = regs.X; operand2 = OPERAND(code, prefix); tick(1); result = operand1 - operand2; FLAG_NZ (result); FLAG_ASSIGN (BIT_V, 0x80 & (operand1 ^ operand2 ^ result ^ (result >>1))); FLAG_ASSIGN (BIT_C, 0x100 & result); return(resGO); } int cl_hc08::inst_jmp(t_mem code, bool prefix) { PC = fetchea(code, prefix); tick(1); // extra cycle to reload pipeline return(resGO); } int cl_hc08::inst_jsr(t_mem code, bool prefix) { int newPC = fetchea(code, prefix); push2(PC); tick(2); PC = newPC; tick(1); // extra cycle to reload pipeline return(resGO); } int cl_hc08::inst_bsr(t_mem code, bool prefix) { signed char ofs = fetch(); push2(PC); tick(2); PC += ofs; tick(1); // extra cycle to reload pipeline return(resGO); } int cl_hc08::inst_ais(t_mem code, bool prefix) { regs.SP = regs.SP + (signed char)fetch(); return(resGO); } int cl_hc08::inst_aix(t_mem code, bool prefix) { int hx = (regs.H << 8) | (regs.X); hx += (signed char)fetch(); tick(1); regs.H = (hx >> 8) & 0xff; regs.X = hx & 0xff; return(resGO); } int cl_hc08::inst_and(t_mem code, bool prefix) { regs.A = regs.A & OPERAND(code, prefix); tick(1); FLAG_CLEAR(BIT_V); FLAG_NZ(regs.A); return(resGO); } int cl_hc08::inst_bit(t_mem code, bool prefix) { uchar operand = regs.A & OPERAND(code, prefix); tick(1); FLAG_CLEAR(BIT_V); FLAG_NZ(operand); return(resGO); } int cl_hc08::inst_ora(t_mem code, bool prefix) { regs.A = regs.A | OPERAND(code, prefix); tick(1); FLAG_CLEAR(BIT_V); FLAG_NZ(regs.A); return(resGO); } int cl_hc08::inst_eor(t_mem code, bool prefix) { regs.A = regs.A ^ OPERAND(code, prefix); tick(1); FLAG_CLEAR(BIT_V); FLAG_NZ(regs.A); return(resGO); } int cl_hc08::inst_asr(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } FLAG_ASSIGN (BIT_C, operand & 1); operand = (operand >> 1) | (operand & 0x80); FLAG_NZ (operand); FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0)); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); tick(1); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_lsr(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } FLAG_ASSIGN (BIT_C, operand & 1); operand = (operand >> 1) & 0x7f; FLAG_NZ (operand); FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0)); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); tick(1); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_lsl(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } FLAG_ASSIGN (BIT_C, operand & 0x80); operand = (operand << 1); FLAG_NZ (operand); FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0)); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); tick(1); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_rol(t_mem code, bool prefix) { uchar c = (regs.P & BIT_C)!=0; int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } FLAG_ASSIGN (BIT_C, operand & 0x80); operand = (operand << 1) | c; FLAG_NZ (operand); FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0)); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); tick(1); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_ror(t_mem code, bool prefix) { uchar c = (regs.P & BIT_C)!=0; int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } FLAG_ASSIGN (BIT_C, operand & 1); operand = (operand >> 1) | (c << 7); FLAG_NZ (operand); FLAG_ASSIGN (BIT_V, ((regs.P & BIT_C)!=0) ^ ((regs.P & BIT_N)!=0)); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); tick(1); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_inc(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } operand++; FLAG_NZ (operand); FLAG_ASSIGN (BIT_V, operand == 0x80); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); tick(1); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_dec(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } operand--; FLAG_NZ (operand); FLAG_ASSIGN (BIT_V, operand == 0x7f); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); tick(1); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_dbnz(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; signed char ofs; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } operand--; FLAG_NZ (operand); FLAG_ASSIGN (BIT_V, operand == 0x7f); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); tick(1); if ((code & 0x70) != 0x70) tick(1); } ofs = fetch(); tick(1); if (operand) PC += ofs; tick(1); // extra cycle to reload pipeline return(resGO); } int cl_hc08::inst_tst(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } FLAG_NZ (operand); FLAG_CLEAR (BIT_V); if ((code & 0xf0) == 0x30 || (code & 0xf0) == 0x60) tick(1); return(resGO); } int cl_hc08::inst_clr(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; // clr uses read-modify-write cycles, so simulate the read even if the data isn't used if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } operand = 0; FLAG_CLEAR (BIT_V); FLAG_CLEAR (BIT_N); FLAG_SET (BIT_Z); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_clrh(t_mem code, bool prefix) { FLAG_CLEAR (BIT_V); FLAG_CLEAR (BIT_N); FLAG_SET (BIT_Z); regs.H = 0; return(resGO); } int cl_hc08::inst_com(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } operand = ~operand; FLAG_SET (BIT_C); FLAG_NZ (operand); FLAG_CLEAR (BIT_V); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_neg(t_mem code, bool prefix) { int ea = 0xffff; uchar operand; if ((code & 0xf0) == 0x40) operand = regs.A; else if ((code & 0xf0) == 0x50) operand = regs.X; else { ea = fetchea(code,prefix); operand = get1(ea); tick(1); } FLAG_ASSIGN (BIT_V, operand==0x80); FLAG_ASSIGN (BIT_C, operand!=0x00); operand = -operand; FLAG_NZ (operand); if ((code & 0xf0) == 0x40) regs.A = operand; else if ((code & 0xf0) == 0x50) regs.X = operand; else { store1(ea, operand); if ((code & 0x70) != 0x70) tick(1); } return(resGO); } int cl_hc08::inst_pushpull(t_mem code, bool prefix) { switch (code) { case 0x86: pop1(regs.A); tick(2); break; case 0x87: push1(regs.A); tick(1); break; case 0x88: pop1(regs.X); tick(2); break; case 0x89: push1(regs.X); tick(1); break; case 0x8a: pop1(regs.H); tick(2); break; case 0x8b: push1(regs.H); tick(1); break; default: return(resHALT); } return(resGO); } int cl_hc08::inst_stop(t_mem code, bool prefix) { FLAG_CLEAR (BIT_I); return(resGO); } int cl_hc08::inst_wait(t_mem code, bool prefix) { FLAG_CLEAR (BIT_I); return(resGO); } int cl_hc08::inst_daa(t_mem code, bool prefix) { uchar lsn, msn; lsn = regs.A & 0xf; msn = (regs.A >> 4) & 0xf; if (regs.P & BIT_H) { lsn += 16; msn = (msn-1) & 0xf; } if (regs.P & BIT_C) msn += 16; FLAG_CLEAR (BIT_C); while (lsn>9) { lsn -= 10; msn++; } if (msn>9) { msn = msn % 10; FLAG_SET (BIT_C); } return(resGO); } int cl_hc08::inst_mul(t_mem code, bool prefix) { int result = regs.A * regs.X; regs.A = result & 0xff; regs.X = (result >> 8) & 0xff; FLAG_CLEAR (BIT_C); FLAG_CLEAR (BIT_H); tick(4); return(resGO); } int cl_hc08::inst_div(t_mem code, bool prefix) { unsigned int dividend = (regs.H << 8) | regs.A; unsigned int quotient; if (regs.X) { quotient = dividend / (unsigned int)regs.X; if (quotient<=0xff) { regs.A = quotient; regs.H = dividend % regs.X; FLAG_CLEAR (BIT_C); FLAG_ASSIGN (BIT_Z, quotient==0); } else FLAG_SET (BIT_C); // overflow } else FLAG_SET (BIT_C); // division by zero tick(5); return(resGO); } int cl_hc08::inst_condbranch(t_mem code, bool prefix) { bool taken; signed char ofs; unsigned char maskedP; if ((code & 0xf0)==0x20) { switch ((code>>1) & 7) { case 0: // BRA taken = 1; break; case 1: // BHI taken = !(regs.P & (BIT_C | BIT_Z)); break; case 2: // BCC taken = !(regs.P & BIT_C); break; case 3: // BNE taken = !(regs.P & BIT_Z); break; case 4: // BHCC taken = !(regs.P & BIT_H); break; case 5: // BPL taken = !(regs.P & BIT_N); break; case 6: // BMC taken = !(regs.P & BIT_I); break; case 7: // BIL taken = 0; // TODO: should read simulated IRQ# pin default: return(resHALT); } } else if ((code & 0xf0)==0x90) { switch ((code>>1) & 7) { case 0: // BGE maskedP = regs.P & (BIT_N | BIT_V); taken = !maskedP || (maskedP == (BIT_N | BIT_V)); break; case 1: // BGT maskedP = regs.P & (BIT_N | BIT_V | BIT_Z); taken = !maskedP || (maskedP == (BIT_N | BIT_V)); break; default: return(resHALT); } } else return(resHALT); if (code & 1) taken = ! taken; ofs = fetch(); tick(1); if (taken) PC += ofs; tick(1); // extra cycle to reload pipeline return(resGO); } int cl_hc08::inst_bitsetclear(t_mem code, bool prefix) { uchar bit = (code >> 1) & 7; int ea = fetchea(code, prefix); uchar operand = get1(ea); tick(1); if (code & 1) operand &= ~(1 << bit); else operand |= (1 << bit); tick(1); store1(ea, operand); tick(1); return(resGO); } int cl_hc08::inst_bittestsetclear(t_mem code, bool prefix) { uchar bit = (code >> 1) & 7; int ea = fetchea(code, prefix); uchar operand = get1(ea); signed char ofs; bool taken; tick(1); if (code & 1) taken = !(operand & (1 << bit)); // brclr else taken = (operand & (1 << bit)); // brset ofs = fetch(); tick(1); if (taken) PC += ofs; tick(1); // extra cycle to reload pipeline FLAG_ASSIGN (BIT_C, operand & (1 << bit)); return(resGO); } int cl_hc08::inst_cbeq(t_mem code, bool prefix) { int ea; uchar operand1, operand2; signed char ofs; if ((code & 0xf0) == 0x40) { operand1 = regs.A; operand2 = fetch(); tick(1); } else if ((code & 0xf0) == 0x50) { operand1 = regs.X; operand2 = fetch(); tick(1); } else { ea = fetchea(code,prefix); operand1 = get1(ea); tick(1); operand2 = regs.A; } ofs = fetch(); tick(1); if (operand1==operand2) PC += ofs; if (code == 0x71 || (!prefix && code == 0x61)) incx(); tick(1); // extra cycle to reload pipeline return(resGO); } int cl_hc08::inst_rti(t_mem code, bool prefix) { pop1(regs.P); tick(1); regs.P |= 0x60; pop1(regs.A); tick(1); pop1(regs.X); tick(1); pop2(PC); tick(2); tick(3); // pipeline reload and some extra overhead? return(resGO); } int cl_hc08::inst_rts(t_mem code, bool prefix) { pop2(PC); tick(2); tick(3); // pipeline reload and some extra overhead? return(resGO); } int cl_hc08::inst_mov(t_mem code, bool prefix) { int ea; uchar operand; bool aix; int hx = (regs.H << 8) | (regs.X); switch (code) { case 0x4e: //mov opr8a,opr8a operand = get1(fetch()); tick(2); ea = fetch(); tick(1); aix = 0; break; case 0x5e: //mov opr8a,x+ operand = get1(fetch()); tick(2); tick(1); ea = hx; aix = 1; break; case 0x6e: //mov #opr8i,opr8a operand = fetch(); tick(1); ea = fetch(); tick(1); aix = 0; break; case 0x7e: //mov x+,opr8a operand = get1(hx); tick(1); ea = fetch(); tick(1); tick(1); aix = 1; break; default: return(resHALT); } store1(ea, operand); tick(1); if (aix) incx(); FLAG_NZ(operand); FLAG_CLEAR(BIT_V); return(resGO); } int cl_hc08::inst_sthx(t_mem code, bool prefix) { int ea; if (code == 0x35) { ea = fetch(); tick(1); } else if ((code == 0x96) && (type->type == CPU_HCS08)) { ea = fetch2(); tick(2); } else if (prefix && (code == 0xff) && (type->type == CPU_HCS08)) { ea = regs.SP + fetch(); tick(1); } else return(resINV_INST); store1(ea, regs.H); tick(1); store1((ea+1) & 0xffff, regs.X); tick(1); FLAG_CLEAR(BIT_V); FLAG_ASSIGN(BIT_N, regs.H & 0x80); FLAG_ASSIGN(BIT_Z, !regs.X && !regs.H); return(resGO); } int cl_hc08::inst_ldhx(t_mem code, bool prefix) { int ea; if (code == 0x45) { regs.H = fetch(); tick(1); regs.X = fetch(); tick(1); } else if (code == 0x55) { ea = fetch(); tick(1); regs.H = get1(ea); tick(1); regs.X = get1(ea+1); tick(1); } else if ((code == 0x32) && (type->type == CPU_HCS08)) { ea = fetch2(); tick(2); regs.H = get1(ea); tick(1); regs.X = get1(ea+1); tick(1); } else if (prefix && (code == 0xae) && (type->type == CPU_HCS08)) { ea = (regs.H << 8) | regs.X; tick(1); regs.H = get1(ea); tick(1); regs.X = get1(ea+1); tick(1); } else if (prefix && (code == 0xbe) && (type->type == CPU_HCS08)) { ea = ((regs.H << 8) | regs.X) + fetch2(); tick(2); regs.H = get1(ea); tick(1); regs.X = get1(ea+1); tick(1); } else if (prefix && (code == 0xce) && (type->type == CPU_HCS08)) { ea = ((regs.H << 8) | regs.X) + fetch(); tick(1); regs.H = get1(ea); tick(1); regs.X = get1(ea+1); tick(1); } else if (prefix && (code == 0xfe) && (type->type == CPU_HCS08)) { ea = regs.SP + fetch(); tick(1); regs.H = get1(ea); tick(1); regs.X = get1(ea+1); tick(1); } else return(resINV_INST); FLAG_CLEAR(BIT_V); FLAG_ASSIGN(BIT_N, regs.H & 0x80); FLAG_ASSIGN(BIT_Z, !regs.X && !regs.H); return(resGO); } int cl_hc08::inst_cphx(t_mem code, bool prefix) { int ea; int hx; int operand; int result; if (code == 0x65) { operand = fetch2(); tick(2); } else if (code == 0x75) { ea = fetch(); tick(1); operand = (get1(ea) << 8) | get1(ea+1); tick(2); tick(1); } else if ((code == 0x3e) && (type->type == CPU_HCS08)) { ea = fetch2(); tick(2); operand = (get1(ea) << 8) | get1(ea+1); tick(2); tick(1); } else if (prefix && (code == 0xf3) && (type->type == CPU_HCS08)) { ea = ((unsigned char)fetch())+regs.SP; tick(1); operand = (get1(ea) << 8) | get1(ea+1); tick(2); tick(1); } else return(resINV_INST); hx = (regs.H << 8) | regs.X; result = hx-operand; FLAG_ASSIGN (BIT_V, 0x8000 & (hx ^ operand ^ result ^ (result>>1))); FLAG_ASSIGN (BIT_C, 0x10000 & result); FLAG_ASSIGN(BIT_N, result & 0x8000); FLAG_ASSIGN(BIT_Z, !(result & 0xffff)); return(resGO); } int cl_hc08::inst_swi(t_mem code, bool prefix) { push2(PC); tick(2); push1(regs.X); tick(1); push1(regs.A); tick(1); push1(regs.P); tick(1); FLAG_CLEAR(BIT_I); PC = get2(0xfffc); tick(2); tick(3); return(resGO); } /* End of hc08.src/inst.cc */