diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /sim/ucsim/hc08.src/inst.cc | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'sim/ucsim/hc08.src/inst.cc')
| -rw-r--r-- | sim/ucsim/hc08.src/inst.cc | 1353 |
1 files changed, 1353 insertions, 0 deletions
diff --git a/sim/ucsim/hc08.src/inst.cc b/sim/ucsim/hc08.src/inst.cc new file mode 100644 index 0000000..56bf495 --- /dev/null +++ b/sim/ucsim/hc08.src/inst.cc @@ -0,0 +1,1353 @@ +/* + * 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 <stdlib.h> + +// 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 */ |
