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/z80.src/inst_ed.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/z80.src/inst_ed.cc')
| -rw-r--r-- | sim/ucsim/z80.src/inst_ed.cc | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/sim/ucsim/z80.src/inst_ed.cc b/sim/ucsim/z80.src/inst_ed.cc new file mode 100644 index 0000000..1ff2c34 --- /dev/null +++ b/sim/ucsim/z80.src/inst_ed.cc @@ -0,0 +1,433 @@ +/* + * Simulator of microcontrollers (inst_ed.cc) + * ED escaped multi-byte opcodes for Z80. + * + * 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" + +// local +#include "z80cl.h" +#include "regsz80.h" +#include "z80mac.h" + + +#define tst_A_bytereg(br) { \ + ubtmp = regs.raf.A & (br); \ + regs.raf.F &= ~(BIT_ALL); /* clear these */ \ + regs.raf.F |= BIT_A; \ + if (ubtmp == 0) regs.raf.F |= BIT_Z; \ + if (ubtmp & 0x80) regs.raf.F |= BIT_S; \ + if (parity(ubtmp)) regs.raf.F |= BIT_P; \ +} + + +int cl_z80::inst_ed_(t_mem code) +{ + unsigned short tw; + u8_t ubtmp; + + if (code < 0x40) + { + if (!(type->type & (CPU_Z180 | CPU_EZ80))) + return resINV_INST; + + switch ( code & 0x07 ) + { + case 0: // IN0 + ubtmp = fetch1( ); + reg_g_store( (code >> 3) & 0x07, in_byte( ubtmp ) ); + return resGO; + + case 1: // OUT0 + ubtmp = fetch1( ); + out_byte( ubtmp, reg_g_read( (code >> 3) & 0x07 ) ); + return resGO; + + case 4: // TST + tst_A_bytereg(reg_g_read( (code >> 3) & 0x07 )); + return resGO; + + default: + return resINV_INST; + } + } + + switch(code) + { + +#if 0 + case 0x40: // IN B,(C) + return(resGO); + case 0x41: // OUT (C),B + return(resGO); +#endif + case 0x42: // SBC HL,BC + sbc_HL_wordreg(regs.BC); + return(resGO); + case 0x43: // LD (nnnn),BC + tw = fetch2(); + store2(tw, regs.BC); + vc.wr+= 2; + return(resGO); + case 0x44: // NEG + regs.raf.F &= ~(BIT_ALL); /* clear these */ + if (regs.raf.A != 0) regs.raf.F |= BIT_C; + if (regs.raf.A == 0x80) regs.raf.F |= BIT_P; + if ((regs.raf.A & 0x0F) != 0) regs.raf.F |= BIT_A; + regs.raf.A = 0 - regs.raf.A; + regs.raf.F |= BIT_N; /* not addition */ + if (regs.raf.A == 0) regs.raf.F |= BIT_Z; + if (regs.raf.A & 0x80) regs.raf.F |= BIT_S; + return(resGO); + case 0x45: // RETN (return from non-maskable interrupt) + pop2(PC); + vc.rd+= 2; + return(resGO); +#if 0 + case 0x46: // IM 0 + /* interrupt device puts opcode on data bus */ + return(resGO); +#endif + case 0x47: // LD IV,A + regs.iv = regs.raf.A; + return(resGO); + + case 0x48: // IN C,(C) + vc.rd++; + return(resGO); + case 0x49: // OUT (C),C + vc.wr++; + return(resGO); + + case 0x4A: // ADC HL,BC + adc_HL_wordreg(regs.BC); + return(resGO); + case 0x4B: // LD BC,(nnnn) + tw = fetch2(); + regs.BC = get2(tw); + vc.rd+= 2; + return(resGO); + case 0x4C: // MLT BC + if (!(type->type & (CPU_Z180 | CPU_EZ80))) + return(resINV_INST); + regs.BC = (unsigned long)(regs.bc.h) * (unsigned long)(regs.bc.l); + return(resGO); + case 0x4D: // RETI (return from interrupt) + pop2(PC); + vc.rd+= 2; + return(resGO); + case 0x4F: // LD R,A + /* Load "refresh" register(whats that?) */ + return(resGO); + + case 0x50: // IN D,(C) + vc.rd++; + return(resGO); + case 0x51: // OUT (C),D + vc.wr++; + return(resGO); + + case 0x52: // SBC HL,DE + sbc_HL_wordreg(regs.DE); + return(resGO); + case 0x53: // LD (nnnn),DE + tw = fetch2(); + store2(tw, regs.DE); + vc.wr+= 2; + return(resGO); +#if 0 + case 0x56: // IM 1 + return(resGO); +#endif + case 0x57: // LD A,IV + regs.raf.A = regs.iv; + return(resGO); + + case 0x58: // IN E,(C) + vc.rd++; + return(resGO); + case 0x59: // OUT (C),E + vc.wr++; + return(resGO); + + case 0x5A: // ADC HL,DE + adc_HL_wordreg(regs.DE); + return(resGO); + case 0x5B: // LD DE,(nnnn) + tw = fetch2(); + regs.DE = get2(tw); + vc.rd+= 2; + return(resGO); + case 0x5C: // MLT DE + if (!(type->type & (CPU_Z180 | CPU_EZ80))) + return(resINV_INST); + regs.DE = (unsigned long)(regs.de.h) * (unsigned long)(regs.de.l); + return(resGO); +#if 0 + case 0x5E: // IM 2 + return(resGO); + case 0x5F: // LD A,R + return(resGO); + case 0x60: // IN H,(C) + vc.rd++; + return(resGO); + case 0x61: // OUT (C),H + vc.wr++; + return(resGO); +#endif + case 0x62: // SBC HL,HL + sbc_HL_wordreg(regs.HL); + return(resGO); + case 0x63: // LD (nnnn),HL opcode 22 does the same faster + tw = fetch2(); + store2(tw, regs.HL); + vc.wr+= 2; + return(resGO); + case 0x64: + if (!(type->type & (CPU_Z180 | CPU_EZ80))) + return(resINV_INST); + ubtmp = fetch(); // TST A,n + tst_A_bytereg(ubtmp); + return(resGO); + + case 0x67: // RRD + ubtmp = get1(regs.HL); + store1(regs.HL, (ubtmp >> 4) | (regs.raf.A << 4)); + regs.raf.A = (regs.raf.A & 0xf0) | (ubtmp & 0x0f); + return(resGO); + + case 0x68: // IN L,(C) + vc.rd++; + return(resGO); + case 0x69: // OUT (C),L + vc.wr++; + return(resGO); + + case 0x6A: // ADC HL,HL + adc_HL_wordreg(regs.HL); + return(resGO); + case 0x6B: // LD HL,(nnnn) opcode 2A does the same faster + tw = fetch2(); + regs.HL = get2(tw); + vc.rd+= 2; + return(resGO); + case 0x6C: // MLT HL + if (!(type->type & (CPU_Z180 | CPU_EZ80))) + return(resINV_INST); + regs.HL = (unsigned long)(regs.hl.h) * (unsigned long)(regs.hl.l); + return(resGO); + + case 0x6F: // RLD + ubtmp = get1(regs.HL); + store1(regs.HL, (ubtmp << 4) | (regs.raf.A & 0x0f)); + regs.raf.A = (regs.raf.A & 0xf0) | (ubtmp >> 4); + return(resGO); + + case 0x70: // IN (C) set flags only (TSTI) + vc.rd++; + return(resGO); + case 0x71: // OUT (C),0 + vc.wr++; + return(resGO); + + case 0x72: // SBC HL,SP + sbc_HL_wordreg(regs.SP); + return(resGO); + case 0x73: // LD (nnnn),SP + tw = fetch2(); + store2(tw, regs.SP); + vc.wr+= 2; + return(resGO); + + case 0x78: // IN A,(C) + vc.rd++; + return(resGO); + case 0x79: // OUT (C),A + vc.wr++; + return(resGO); + + case 0x7A: // ADC HL,SP + adc_HL_wordreg(regs.SP); + return(resGO); + case 0x7B: // LD SP,(nnnn) + tw = fetch2(); + regs.SP = get2(tw); + vc.rd+= 2; + return(resGO); + + case 0x7C: // MLT SP + //if(type != CPU_Z180) + return(resINV_INST); + //regs.SP = (unsigned long)(regs.sp.h) * (unsigned long)(regs.sp.l); + return(resGO); + case 0xA0: // LDI + // BC - count, sourc=HL, dest=DE. *DE++ = *HL++, --BC until zero + regs.raf.F &= ~(BIT_P | BIT_N | BIT_A); /* clear these */ + store1(regs.DE, get1(regs.HL)); + ++regs.HL; + ++regs.DE; + --regs.BC; + if (regs.BC != 0) regs.raf.F |= BIT_P; + return(resGO); + case 0xA1: // CPI + // compare acc with mem(HL), if ACC=0 set Z flag. Incr HL, decr BC. + { + unsigned char tmp; + tmp = get1(regs.HL); + cp_bytereg(tmp); + ++regs.HL; + --regs.BC; + if (regs.BC != 0) regs.raf.F |= BIT_P; + } + return(resGO); + + case 0xA2: // INI + return(resGO); + case 0xA3: // OUTI + return(resGO); + + case 0xA8: // LDD + // BC - count, source=HL, dest=DE. *DE-- = *HL--, --BC until zero + regs.raf.F &= ~(BIT_P | BIT_N | BIT_A); /* clear these */ + store1(regs.DE, get1(regs.HL)); + --regs.HL; + --regs.DE; + --regs.BC; + if (regs.BC != 0) regs.raf.F |= BIT_P; + vc.rd++; + vc.wr++; + return(resGO); + case 0xA9: // CPD +/* fixme: checkme, compare to other emul. */ + + regs.raf.F &= ~(BIT_ALL); /* clear these */ + if ((regs.raf.A - get1(regs.HL)) == 0) { + regs.raf.F |= (BIT_Z | BIT_P); + } + ++regs.HL; + --regs.BC; + if (regs.BC != 0) regs.raf.F |= BIT_P; + vc.rd++; + + return(resGO); + + case 0xAA: // IND + return(resGO); + case 0xAB: // OUTD + return(resGO); + + case 0xB0: // LDIR + // BC - count, sourc=HL, dest=DE. *DE++ = *HL++, --BC until zero + regs.raf.F &= ~(BIT_P | BIT_N | BIT_A); /* clear these */ + do { + store1(regs.DE, get1(regs.HL)); + ++regs.HL; + ++regs.DE; + --regs.BC; + vc.rd++; + vc.wr++; + } while (regs.BC != 0); + return(resGO); + + case 0xB1: // CPIR + // compare acc with mem(HL), if ACC=0 set Z flag. Incr HL, decr BC. + regs.raf.F &= ~(BIT_P | BIT_A | BIT_Z | BIT_S); /* clear these */ + regs.raf.F |= BIT_N; + do { + if((regs.raf.A - get1(regs.HL)) == 0) + regs.raf.F |= BIT_Z; + else + regs.raf.F &= ~BIT_Z; + if((regs.raf.A - get1(regs.HL)) & 0x80) + regs.raf.F |= BIT_S; + else + regs.raf.F &= ~BIT_S; +/* fixme: set BIT_A correctly. */ + ++regs.HL; + --regs.BC; + vc.rd++; + } while (regs.BC != 0 && (regs.raf.F & BIT_Z) == 0); + if(regs.BC != 0) + regs.raf.F |= BIT_P; + + return(resGO); +#if 0 + case 0xB2: // INIR + return(resGO); + case 0xB3: // OTIR + return(resGO); +#endif + case 0xB8: // LDDR + // BC - count, source=HL, dest=DE. *DE-- = *HL--, --BC until zero + regs.raf.F &= ~(BIT_P | BIT_N | BIT_A); /* clear these */ + do { + store1(regs.DE, get1(regs.HL)); + --regs.HL; + --regs.DE; + --regs.BC; + vc.rd++; + vc.wr++; + } while (regs.BC != 0); + return(resGO); + case 0xB9: // CPDR + // compare acc with mem(HL), if ACC=0 set Z flag. Incr HL, decr BC. + regs.raf.F &= ~(BIT_ALL); /* clear these */ + do { + if ((regs.raf.A - get1(regs.HL)) == 0) { + regs.raf.F |= (BIT_Z | BIT_P); + break; + } + --regs.HL; + --regs.BC; + vc.rd++; + } while (regs.BC != 0); + return(resGO); +#if 0 + case 0xBA: // INDR + return(resGO); + case 0xBB: // OTDR + return(resGO); +#endif + + default: + return(resINV_INST); + } + + return(resGO); +} + +/******** start ED codes *****************/ +int cl_z80::inst_ed(t_mem prefix) +{ + t_mem code; + + if (fetch(&code)) + return(resBREAKPOINT); + + return inst_ed_(code); +} + +/* End of z80.src/inst_ed.cc */ |
