diff options
Diffstat (limited to 'src/devices/cpu/lh5801')
-rw-r--r-- | src/devices/cpu/lh5801/5801dasm.c | 725 | ||||
-rw-r--r-- | src/devices/cpu/lh5801/5801tbl.inc | 689 | ||||
-rw-r--r-- | src/devices/cpu/lh5801/lh5801.c | 254 | ||||
-rw-r--r-- | src/devices/cpu/lh5801/lh5801.h | 188 |
4 files changed, 1856 insertions, 0 deletions
diff --git a/src/devices/cpu/lh5801/5801dasm.c b/src/devices/cpu/lh5801/5801dasm.c new file mode 100644 index 00000000000..b622bda9de6 --- /dev/null +++ b/src/devices/cpu/lh5801/5801dasm.c @@ -0,0 +1,725 @@ +// license:BSD-3-Clause +// copyright-holders:Peter Trauner +/***************************************************************************** + * + * disasm.c + * portable lh5801 emulator interface + * + * + *****************************************************************************/ + +#include "emu.h" +#include "debugger.h" + +#include "lh5801.h" + +enum Adr +{ + Imp, + Reg, + Vec, // imm byte (vector at 0xffxx) + Vej, + Imm, + RegImm, + Imm16, + RegImm16, + ME0, + ME0Imm, + Abs, + AbsImm, + ME1, + ME1Imm, + ME1Abs, + ME1AbsImm, + RelP, + RelM +}; + +enum Regs +{ + RegNone, + A, + XL, XH, X, + YL, YH, Y, + UL, UH, U, + P, S +}; + +static const char *const RegNames[]= { + 0, "A", "XL", "XH", "X", "YL", "YH", "Y", "UL", "UH", "U", "P", "S" +}; + +#if defined(SEC) +#undef SEC +#endif + +enum Ins +{ + ILL, ILL2, PREFD, NOP, + + LDA, STA, LDI, LDX, STX, + LDE, SDE, LIN, SIN, + TIN, // (x++)->(y++) + ADC, ADI, ADR, SBC, SBI, + DCA, DCS, // bcd add and sub + CPA, CPI, CIN, // A compared with (x++) + AND, ANI, ORA, ORI, EOR, EAI, BIT, BII, + INC, DEC, + DRL, DRR, // digit rotates + ROL, ROR, + SHL, SHR, + AEX, // A nibble swap + + BCR, BCS, BHR, BHS, BZR, BZS, BVR, BVS, + BCH, LOP, // loop with ul + JMP, SJP, RTN, RTI, HLT, + VCR, VCS, VHR, VHS, VVS, VZR, VZS, + VMJ, VEJ, + PSH, POP, ATT, TTA, + REC, SEC, RIE, SIE, + + AM0, AM1, // load timer reg + ITA, // reads input port + ATP, // akku send to data bus + CDV, // clears internal divider + OFF, // clears bf flip flop + RDP, SDP,// reset display flip flop + RPU, SPU,// flip flop pu off + RPV, SPV // flip flop pv off +}; + +static const char *const InsNames[]={ + "ILL", "ILL", 0, "NOP", + "LDA", "STA", "LDI", "LDX", "STX", + "LDE", "SDE", "LIN", "SIN", + "TIN", + "ADC", "ADI", "ADR", "SBC", "SBI", + "DCA", "DCS", + "CPA", "CPI", "CIN", + "AND", "ANI", "ORA", "ORI", "EOR", "EAI", "BIT", "BII", + "INC", "DEC", + "DRL", "DRR", + "ROL", "ROR", + "SHL", "SHR", + "AEX", + "BCR", "BCS", "BHR", "BHS", "BZR", "BZS", "BVR", "BVS", + "BCH", "LOP", + "JMP", "SJP", "RTN", "RTI", "HLT", + "VCR", "VCS", "VHR", "VHS", "VVS", "VZR", "VZS", + "VMJ", "VEJ", + "PSH", "POP", "ATT", "TTA", + "REC", "SEC", "RIE", "SIE", + + "AM0", "AM1", + "ITA", + "ATP", + "CDV", + "OFF", + "RDP", "SDP", + "RPU", "SPU", + "RPV", "SPV", +}; + +struct Entry { Ins ins; Adr adr; Regs reg; }; + +static const Entry table[0x100]={ + { SBC, Reg, XL }, // 0 + { SBC, ME0, X }, + { ADC, Reg, XL }, + { ADC, ME0, X }, + { LDA, Reg, XL }, + { LDA, ME0, X }, + { CPA, Reg, XL }, + { CPA, ME0, X }, + { STA, Reg, XH }, + { AND, ME0, X }, + { STA, Reg, XL }, + { ORA, ME0, X }, + { DCS, ME0, X }, + { EOR, ME0, X }, + { STA, ME0, X }, + { BIT, ME0, X }, + { SBC, Reg, YL }, // 0x10 + { SBC, ME0, Y }, + { ADC, Reg, YL }, + { ADC, ME0, Y }, + { LDA, Reg, YL }, + { LDA, ME0, Y }, + { CPA, Reg, YL }, + { CPA, ME0, Y }, + { STA, Reg, YH }, + { AND, ME0, Y }, + { STA, Reg, YL }, + { ORA, ME0, Y }, + { DCS, ME0, Y }, + { EOR, ME0, Y }, + { STA, ME0, Y }, + { BIT, ME0, Y }, + { SBC, Reg, UL }, // 0x20 + { SBC, ME0, U }, + { ADC, Reg, UL }, + { ADC, ME0, U }, + { LDA, Reg, UL }, + { LDA, ME0, U }, + { CPA, Reg, UL }, + { CPA, ME0, U }, + { STA, Reg, UH }, + { AND, ME0, U }, + { STA, Reg, UL }, + { ORA, ME0, U }, + { DCS, ME0, U }, + { EOR, ME0, U }, + { STA, ME0, U }, + { BIT, ME0, U }, + { ILL }, // 0x30 + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { NOP, Imp }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { INC, Reg, XL }, //0x40 + { SIN, Reg, X }, + { DEC, Reg, XL }, + { SDE, Reg, X }, + { INC, Reg, X }, + { LIN, Reg, X }, + { DEC, Reg, X }, + { LDE, Reg, X }, + { LDI, RegImm, XH }, + { ANI, ME0Imm, X }, + { LDI, RegImm, XL }, + { ORI, ME0Imm, X }, + { CPI, RegImm, XH }, + { BII, ME0Imm, X }, + { CPI, RegImm, XL }, + { ADI, ME0Imm, X }, + { INC, Reg, YL }, //0x50 + { SIN, Reg, Y }, + { DEC, Reg, YL }, + { SDE, Reg, Y }, + { INC, Reg, Y }, + { LIN, Reg, Y }, + { DEC, Reg, Y }, + { LDE, Reg, Y }, + { LDI, RegImm, YH }, + { ANI, ME0Imm, Y }, + { LDI, RegImm, YL }, + { ORI, ME0Imm, Y }, + { CPI, RegImm, YH }, + { BII, ME0Imm, Y }, + { CPI, RegImm, YL }, + { ADI, ME0Imm, Y }, + { INC, Reg, UL }, //0x60 + { SIN, Reg, U }, + { DEC, Reg, UL }, + { SDE, Reg, U }, + { INC, Reg, U }, + { LIN, Reg, U }, + { DEC, Reg, U }, + { LDE, Reg, U }, + { LDI, RegImm, UH }, + { ANI, ME0Imm, U }, + { LDI, RegImm, UL }, + { ORI, ME0Imm, U }, + { CPI, RegImm, UH }, + { BII, ME0Imm, U }, + { CPI, RegImm, UL }, + { ADI, ME0Imm, U }, + { ILL }, // 0X70 + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { ILL }, + { SBC, Reg, XH }, // 0x80 + { BCR, RelP }, + { ADC, Reg, XH }, + { BCS, RelP }, + { LDA, Reg, XH }, + { BHR, RelP }, + { CPA, Reg, XH }, + { BHS, RelP }, + { LOP, RelM }, + { BZR, RelP }, + { RTI, Imp }, + { BZS, RelP }, + { DCA, ME0, X }, + { BVR, RelP }, + { BCH, RelP }, + { BVS, RelP }, + { SBC, Reg, YH }, // 0x90 + { BCR, RelM }, + { ADC, Reg, YH }, + { BCS, RelM }, + { LDA, Reg, YH }, + { BHR, RelM }, + { CPA, Reg, YH }, + { BHS, RelM }, + { ILL }, + { BZR, RelM }, + { RTN, Imp }, + { BZS, RelM }, + { DCA, ME0, Y }, + { BVR, RelM }, + { BCH, RelM }, + { BVS, RelM }, + { SBC, Reg, UH }, // 0xa0 + { SBC, Abs }, + { ADC, Reg, UH }, + { ADC, Abs }, + { LDA, Reg, UH }, + { LDA, Abs }, + { CPA, Reg, UH }, + { CPA, Abs }, + { SPV, Imp }, + { AND, Abs }, + { LDI, RegImm16, S }, + { ORA, Abs }, + { DCA, ME0, U }, + { EOR, Abs }, + { STA, Abs }, + { BIT, Abs }, + { ILL }, //0xb0 + { SBI }, + { ILL }, + { ADI, RegImm, A }, + { ILL }, + { LDI, RegImm, A }, + { ILL }, + { CPI, RegImm, A }, + { RPV, Imp }, + { ANI, RegImm, A }, + { JMP, Imm16 }, + { ORI, RegImm, A }, + { ILL }, + { EAI, Imm }, + { SJP, Imm16 }, + { BII, RegImm, A }, + { VEJ, Vej }, // 0xc0 + { VCR, Vec }, + { VEJ, Vej }, + { VCS, Vec }, + { VEJ, Vej }, + { VHR, Vec }, + { VEJ, Vej }, + { VHS, Vec }, + { VEJ, Vej }, + { VZR, Vec }, + { VEJ, Vej }, + { VZS, Vec }, + { VEJ, Vej }, + { VMJ, Vec }, + { VEJ, Vej }, + { VVS, Vec }, + { VEJ, Vej }, // 0xd0 + { ROR, Imp }, + { VEJ, Vej }, + { DRR, Imp }, + { VEJ, Vej }, + { SHR, Imp }, + { VEJ, Vej }, + { DRL, Imp }, + { VEJ, Vej }, + { SHL, Imp }, + { VEJ, Vej }, + { ROL, Imp }, + { VEJ, Vej }, + { INC, Reg, A }, + { VEJ, Vej }, + { DEC, Reg, A }, + { VEJ, Vej }, //0xe0 + { SPU, Imp }, + { VEJ, Vej }, + { RPU, Imp }, + { VEJ, Vej }, + { ILL }, + { VEJ, Vej }, + { ILL }, + { VEJ, Vej }, + { ANI, AbsImm }, + { VEJ, Vej }, + { ORI, AbsImm }, + { VEJ, Vej }, + { BII, AbsImm }, + { VEJ, Vej }, + { ADI, AbsImm }, + { VEJ, Vej }, //0xf0 + { AEX, Imp }, + { VEJ, Vej }, + { ILL }, + { VEJ, Vej }, + { TIN, Imp }, + { VEJ, Vej }, + { CIN, Imp }, + { ILL }, + { REC, Imp }, + { ILL }, + { SEC, Imp }, + { ILL }, + { PREFD }, + { ILL }, + { ILL } +}; +static const Entry table_fd[0x100]={ + { ILL2 }, // 0x00 + { SBC, ME1, X }, + { ILL2 }, + { ADC, ME1, X }, + { ILL2 }, + { LDA, ME1, X }, + { ILL2 }, + { CPA, ME1, X }, + { LDX, Reg, X }, + { AND, ME1, X }, + { POP, Reg, X }, + { ORA, ME1, X }, + { DCS, ME1, X }, + { EOR, ME1, X }, + { STA, ME1, X }, + { BIT, ME1, X }, + { ILL2 }, // 0x10 + { SBC, ME1, Y }, + { ILL2 }, + { ADC, ME1, Y }, + { ILL2 }, + { LDA, ME1, Y }, + { ILL2 }, + { CPA, ME1, Y }, + { LDX, Reg, Y }, + { AND, ME1, Y }, + { POP, Reg, Y }, + { ORA, ME1, Y }, + { DCS, ME1, Y }, + { EOR, ME1, Y }, + { STA, ME1, Y }, + { BIT, ME1, Y }, + { ILL2 }, // 0x20 + { SBC, ME1, U }, + { ILL2 }, + { ADC, ME1, U }, + { ILL2 }, + { LDA, ME1, U }, + { ILL2 }, + { CPA, ME1, U }, + { LDX, Reg, U }, + { AND, ME1, U }, + { POP, Reg, U }, + { ORA, ME1, U }, + { DCS, ME1, U }, + { EOR, ME1, U }, + { STA, ME1, U }, + { BIT, ME1, U }, + { ILL2 }, // 0x30 + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { INC, Reg, XH }, // 0x40 + { ILL2 }, + { DEC, Reg, XH }, //46 in other part of manual + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { LDX, Reg, S }, + { ANI, ME1Imm, X }, + { STX, Reg, X }, + { ORI, ME1Imm, X }, + { OFF, Imp }, + { BII, ME1Imm, X }, + { STX, Reg, S }, + { ADI, ME1Imm, X }, + { INC, Reg, YH }, // 0x50 + { ILL2 }, + { DEC, Reg, YH }, // 56 in other part of manual + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { LDX, Reg, P }, + { ANI, ME1Imm, Y }, + { STX, Reg, Y }, + { ORI, ME1Imm, Y }, + { ILL2 }, + { BII, ME1Imm, Y }, + { STX, Reg, P }, + { ADI, ME1Imm, Y }, + { INC, Reg, UH }, // 0x60 + { ILL2 }, + { DEC, Reg, UH }, // 66 in other part of manual + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ANI, ME1Imm, U }, + { STX, Reg, U }, + { ORI, ME1Imm, U }, + { ILL2 }, + { BII, ME1Imm, U }, + { ILL }, + { ADI, ME1Imm, U }, + { ILL2 }, // 0x70 + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, // 0x80 + { SIE, Imp }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { PSH, Reg, X }, + { ILL2 }, + { POP, Reg, A }, + { ILL2 }, + { DCA, ME1, X }, + { ILL2 }, + { CDV, Imp }, + { ILL2 }, + { ILL2 }, // 0x90 + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { PSH, Reg, Y }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { DCA, ME1, Y }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, // 0xa0 + { SBC, ME1Abs }, + { ILL2 }, + { ADC, ME1Abs }, + { ILL2 }, + { LDA, ME1Abs }, + { ILL2 }, + { CPA, ME1Abs }, + { PSH, Reg, U }, + { AND, ME1Abs }, + { TTA, Imp }, + { ORA, ME1Abs }, + { DCA, ME1, U }, + { EOR, ME1Abs }, + { STA, ME1Abs }, + { BIT, ME1Abs }, + { ILL2 }, // 0xb0 + { HLT, Imp }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ITA, Imp }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { RIE, Imp }, + { ILL2 }, + { RDP, Imp }, // 0xc0 + { SDP, Imp }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { PSH, Reg, A }, + { ILL2 }, + { ADR, Reg, X }, + { ILL2 }, + { ATP, Imp }, + { ILL2 }, + { AM0, Imp }, + { ILL2 }, + { ILL2 }, // 0xd0 + { ILL2 }, + { ILL2 }, + { DRR, ME1, X }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { DRL, ME1, X }, + { ILL2 }, + { ILL2 }, + { ADR, Reg, Y }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { AM1, Imp }, + { ILL2 }, + { ILL2 }, // 0xe0 + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ANI, ME1AbsImm }, + { ADR, Reg, U }, + { ORI, ME1AbsImm }, + { ATT, Imp }, + { BII, ME1AbsImm }, + { ILL2 }, + { ADI, ME1AbsImm }, + { ILL2 }, // 0xf0 + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 }, + { ILL2 } +}; + +CPU_DISASSEMBLE( lh5801 ) +{ + int pos = 0; + int oper; + UINT16 absolut; + const Entry *entry; + int temp; + + oper=oprom[pos++]; + entry=table+oper; + + if (table[oper].ins==PREFD) { + oper=oprom[pos++]; + entry=table_fd+oper; + } + switch (entry->ins) { + case ILL: + sprintf(buffer,"%s %.2x", InsNames[entry->ins], oper);break; + case ILL2: + sprintf(buffer,"%s fd%.2x", InsNames[entry->ins], oper);break; + default: + switch(entry->adr) { + case Imp: + sprintf(buffer,"%s", InsNames[entry->ins]);break; + case Reg: + sprintf(buffer,"%s %s", InsNames[entry->ins],RegNames[entry->reg]);break; + case RegImm: + sprintf(buffer,"%s %s,%.2x", InsNames[entry->ins], + RegNames[entry->reg], oprom[pos++]); + break; + case RegImm16: + absolut=oprom[pos++]<<8; + absolut|=oprom[pos++]; + sprintf(buffer,"%s %s,%.4x", InsNames[entry->ins],RegNames[entry->reg],absolut ); + break; + case Vec: + sprintf(buffer,"%s (ff%.2x)", InsNames[entry->ins],oprom[pos++]);break; + case Vej: + sprintf(buffer,"%s (ff%.2x)", InsNames[entry->ins], oper);break; + case Imm: + sprintf(buffer,"%s %.2x", InsNames[entry->ins],oprom[pos++]);break; + case Imm16: + absolut=oprom[pos++]<<8; + absolut|=oprom[pos++]; + sprintf(buffer,"%s %.4x", InsNames[entry->ins],absolut );break; + case RelP: + temp=oprom[pos++]; + sprintf(buffer,"%s %.4x", InsNames[entry->ins],pc+pos+temp );break; + case RelM: + temp=oprom[pos++]; + sprintf(buffer,"%s %.4x", InsNames[entry->ins],pc+pos-temp );break; + case Abs: + absolut=oprom[pos++]<<8; + absolut|=oprom[pos++]; + sprintf(buffer,"%s (%.4x)", InsNames[entry->ins],absolut );break; + case ME1Abs: + absolut=oprom[pos++]<<8; + absolut|=oprom[pos++]; + sprintf(buffer,"%s #(%.4x)", InsNames[entry->ins],absolut );break; + case AbsImm: + absolut=oprom[pos++]<<8; + absolut|=oprom[pos++]; + sprintf(buffer,"%s (%.4x),%.2x", InsNames[entry->ins],absolut, + oprom[pos++]);break; + case ME1AbsImm: + absolut=oprom[pos++]<<8; + absolut|=oprom[pos++]; + sprintf(buffer,"%s #(%.4x),%.2x", InsNames[entry->ins],absolut, + oprom[pos++]);break; + case ME0: + sprintf(buffer,"%s (%s)", InsNames[entry->ins],RegNames[entry->reg] );break; + case ME0Imm: + sprintf(buffer,"%s (%s),%.2x", InsNames[entry->ins],RegNames[entry->reg],oprom[pos++] ); + break; + case ME1: + sprintf(buffer,"%s #(%s)", InsNames[entry->ins],RegNames[entry->reg] );break; + case ME1Imm: + sprintf(buffer,"%s #(%s),%.2x", InsNames[entry->ins],RegNames[entry->reg],oprom[pos++] ); + break; + } + } + + return pos; +} diff --git a/src/devices/cpu/lh5801/5801tbl.inc b/src/devices/cpu/lh5801/5801tbl.inc new file mode 100644 index 00000000000..98a8d7b1d02 --- /dev/null +++ b/src/devices/cpu/lh5801/5801tbl.inc @@ -0,0 +1,689 @@ +// license:BSD-3-Clause +// copyright-holders:Peter Trauner +/* assumed + res=left+right+c + sbc is like adc with inverted carry and right side + (decrement, compare the same) + (like in the m6502 processors) +*/ +UINT8 lh5801_cpu_device::lh5801_add_generic(int left, int right, int carry) +{ + int res=left+right+carry; + int v,c; + + m_t&=~(H|V|Z|C); + + if (!(res&0xff)) m_t|=Z; + c=res&0x100; + if (c) m_t|=C; + if (((left&0xf)+(right&0xf)+carry)&0x10) m_t|=H; + v=((left&0x7f)+(right&0x7f)+carry)&0x80; + if ( (c&&!v)||(!c&&v) ) m_t|=V; + + return res; +} + +UINT16 lh5801_cpu_device::lh5801_readop_word() +{ + UINT16 r; + r=m_direct->read_byte(P++)<<8; + r|=m_direct->read_byte(P++); + return r; +} + + +void lh5801_cpu_device::lh5801_adc(UINT8 data) +{ + m_a=lh5801_add_generic(m_a,data,m_t&C); +} + +void lh5801_cpu_device::lh5801_add_mem(address_space &space, int addr, UINT8 data) +{ + int v=lh5801_add_generic(space.read_byte(addr),data,0); + space.write_byte(addr,v); +} + +void lh5801_cpu_device::lh5801_adr(PAIR *reg) +{ + reg->b.l=lh5801_add_generic(reg->b.l,m_a,0); + if (m_t&C) { + reg->b.h++; + } +} + +void lh5801_cpu_device::lh5801_sbc(UINT8 data) +{ + m_a=lh5801_add_generic(m_a,data^0xff,m_t&C); +} + +void lh5801_cpu_device::lh5801_cpa(UINT8 a, UINT8 b) +{ + lh5801_add_generic(a, b^0xff, 1); +} + +UINT8 lh5801_cpu_device::lh5801_decimaladd_generic(int left, int right, int carry) +{ + int res=lh5801_add_generic(left, right, carry); + UINT8 da; + + //DA values taken from official documentation + if (!(m_t&C) && !(m_t&H)) + da = 0x9a; + else if (!(m_t&C) && (m_t&H)) + da = 0xa0; + else if ((m_t&C) && !(m_t&H)) + da = 0xfa; + else //if ((m_t&C) && (m_t&H)) + da = 0x00; + + return res + da; +} + +void lh5801_cpu_device::lh5801_dca(UINT8 data) +{ + m_a += 0x66; //taken from official documentation + m_a=lh5801_decimaladd_generic(m_a, data, m_t&C); +} + +void lh5801_cpu_device::lh5801_dcs(UINT8 data) +{ + m_a=lh5801_decimaladd_generic(m_a, data^0xff, m_t&C); +} + +void lh5801_cpu_device::lh5801_and(UINT8 data) +{ + m_a&=data; + m_t&=~Z; + if (!m_a) m_t|=Z; +} + +void lh5801_cpu_device::lh5801_and_mem(address_space &space, int addr, UINT8 data) +{ + data&=space.read_byte(addr); + m_t&=~Z; + if (!data) m_t|=Z; + space.write_byte(addr,data); +} + +void lh5801_cpu_device::lh5801_bit(UINT8 a, UINT8 b) +{ + m_t&=~Z; + if (!(a&b)) m_t|=Z; +} + +void lh5801_cpu_device::lh5801_eor(UINT8 data) +{ + m_a^=data; + m_t&=~Z; + if (!m_a) m_t|=Z; +} + +void lh5801_cpu_device::lh5801_ora(UINT8 data) +{ + m_a|=data; + m_t&=~Z; + if (!m_a) m_t|=Z; +} + +void lh5801_cpu_device::lh5801_ora_mem(address_space &space, int addr, UINT8 data) +{ + data|=space.read_byte(addr); + m_t&=~Z; + if (!data) m_t|=Z; + space.write_byte(addr,data); +} + +void lh5801_cpu_device::lh5801_lda(UINT8 data) +{ + m_a=data; + m_t&=~Z; + if (!m_a) m_t|=Z; +} + +void lh5801_cpu_device::lh5801_lde(PAIR *reg) +{ + // or z flag depends on reg + m_a=m_program->read_byte(reg->w.l--); + m_t&=~Z; + if (!m_a) m_t|=Z; +} + +void lh5801_cpu_device::lh5801_sde(PAIR *reg) +{ + m_program->write_byte(reg->w.l--, m_a); +} + +void lh5801_cpu_device::lh5801_lin(PAIR *reg) +{ + // or z flag depends on reg + m_a=m_program->read_byte(reg->w.l++); + m_t&=~Z; + if (!m_a) m_t|=Z; +} + +void lh5801_cpu_device::lh5801_sin(PAIR *reg) +{ + m_program->write_byte(reg->w.l++, m_a); +} + +void lh5801_cpu_device::lh5801_dec(UINT8 *adr) +{ + *adr=lh5801_add_generic(*adr,0xff,0); +} + +void lh5801_cpu_device::lh5801_inc(UINT8 *adr) +{ + *adr=lh5801_add_generic(*adr,1,0); +} + +void lh5801_cpu_device::lh5801_pop() +{ + m_a=m_program->read_byte(++S); + m_t&=~Z; + if (!m_a) m_t|=Z; +} + +void lh5801_cpu_device::lh5801_pop_word(PAIR *reg) +{ + reg->b.h=m_program->read_byte(++S); + reg->b.l=m_program->read_byte(++S); + // z flag? +} + +void lh5801_cpu_device::lh5801_rtn() +{ + P=m_program->read_byte(++S)<<8; + P|=m_program->read_byte(++S); +} + +void lh5801_cpu_device::lh5801_rti() +{ + P=m_program->read_byte(++S)<<8; + P|=m_program->read_byte(++S); + m_t=m_program->read_byte(++S); +} + +void lh5801_cpu_device::lh5801_push(UINT8 data) +{ + m_program->write_byte(S--, data); +} + +void lh5801_cpu_device::lh5801_push_word(UINT16 data) +{ + m_program->write_byte(S--, data&0xff); + m_program->write_byte(S--, data>>8); +} + +void lh5801_cpu_device::lh5801_jmp(UINT16 adr) +{ + P=adr; +} + +void lh5801_cpu_device::lh5801_branch_plus(int doit) +{ + UINT8 t=m_direct->read_byte(P++); + if (doit) { + m_icount-=3; + P+=t; + } +} + +void lh5801_cpu_device::lh5801_branch_minus(int doit) +{ + UINT8 t=m_direct->read_byte(P++); + if (doit) { + m_icount-=3; + P-=t; + } +} + +void lh5801_cpu_device::lh5801_lop() +{ + UINT8 t=m_direct->read_byte(P++); + m_icount-=8; + if (UL--) { + m_icount-=3; + P-=t; + } +} + +void lh5801_cpu_device::lh5801_sjp() +{ + UINT16 n=lh5801_readop_word(); + lh5801_push_word(P); + P=n; +} + +void lh5801_cpu_device::lh5801_vector(int doit, int nr) +{ + if (doit) { + lh5801_push_word(P); + P=m_program->read_byte(0xff00+nr)<<8; + P|=m_program->read_byte(0xff00+nr+1); + m_icount-=21-8; + } + m_t&=~Z; // after the jump!? +} + +void lh5801_cpu_device::lh5801_aex() +{ + UINT8 t=m_a; + m_a=(t<<4)|(t>>4); + // flags? +} + +void lh5801_cpu_device::lh5801_drl(address_space &space, int adr) +{ + UINT16 t=m_a|(space.read_byte(adr)<<8); + + m_a=t>>8; + space.write_byte(adr,t>>4); +} + +void lh5801_cpu_device::lh5801_drr(address_space &space, int adr) +{ + UINT16 t=space.read_byte(adr)|(m_a<<8); + + m_a=t; + space.write_byte(adr,t>>4); +} + +void lh5801_cpu_device::lh5801_rol() +{ + // maybe use of the adder + int n = m_a; + m_a = (n<<1) | (m_t&C); + // flags cvhz + m_t&=~(H|V|Z|C); + if (n&0x80) m_t|=C; + if (!m_a) m_t|=Z; + if (m_a & 0x10) m_t|=H; + if ((BIT(n,6) && !BIT(n,7)) || (!BIT(n,6) && BIT(n,7))) m_t|=V; +} + +void lh5801_cpu_device::lh5801_ror() +{ + int n = m_a; + m_a=(n | ((m_t&C)<<8))>>1; + // flags cvhz + m_t&=~(H|V|Z|C); + if (n&0x01) m_t|=C; + if (!m_a) m_t|=Z; + if (m_a & 0x08) m_t|=H; + if ((BIT(n,0) && BIT(m_a,1)) || (BIT(m_a,0) && BIT(n,1))) m_t|=V; +} + +void lh5801_cpu_device::lh5801_shl() +{ + int n = m_a; + m_a<<=1; + // flags cvhz + m_t&=~(H|V|Z|C); + if (n&0x80) m_t|=C; + if (!m_a) m_t|=Z; + if (m_a & 0x10) m_t|=H; + if ((BIT(n,6) && !BIT(n,7)) || (!BIT(n,6) && BIT(n,7))) m_t|=V; +} + +void lh5801_cpu_device::lh5801_shr() +{ + int n = m_a; + m_a>>=1; + // flags cvhz + m_t&=~(H|V|Z|C); + if (n & 0x01) m_t|=C; + if (!m_a) m_t|=Z; + if (m_a & 0x08) m_t|=H; + if ((BIT(n,0) && BIT(m_a,1)) || (BIT(m_a,0) && BIT(n,1))) m_t|=V; +} + +void lh5801_cpu_device::lh5801_am(int value) +{ + m_tm=value; + // jfkas?jfkl?jkd? +} + +void lh5801_cpu_device::lh5801_ita() +{ + m_a=m_in_func(); + m_t&=~Z; + if (!m_a) m_t|=Z; +} + +void lh5801_cpu_device::lh5801_instruction_fd() +{ + int oper; + int adr; + + oper=m_direct->read_byte(P++); + switch (oper) { + case 0x01: lh5801_sbc(m_io->read_byte(X)); m_icount-=11;break; + case 0x03: lh5801_adc(m_io->read_byte(X)); m_icount-=11;break; + case 0x05: lh5801_lda(m_io->read_byte(X)); m_icount-=10;break; + case 0x07: lh5801_cpa(m_a, m_io->read_byte(X)); m_icount-=11;break; + case 0x08: X=X;m_icount-=11;break; //!!! + case 0x09: lh5801_and(m_io->read_byte(X)); m_icount-=11;break; + case 0x0a: lh5801_pop_word(&m_x); m_icount-=15;break; + case 0x0b: lh5801_ora(m_io->read_byte(X)); m_icount-=11;break; + case 0x0c: lh5801_dcs(m_io->read_byte(X)); m_icount-=17; break; + case 0x0d: lh5801_eor(m_io->read_byte(X)); m_icount-=11;break; + case 0x0e: m_io->write_byte(X,m_a); m_icount-=10;break; + case 0x0f: lh5801_bit(m_io->read_byte(X),m_a); m_icount-=11;break; + case 0x11: lh5801_sbc(m_io->read_byte(Y)); m_icount-=11;break; + case 0x13: lh5801_adc(m_io->read_byte(Y)); m_icount-=11;break; + case 0x15: lh5801_lda(m_io->read_byte(Y)); m_icount-=10;break; + case 0x17: lh5801_cpa(m_a, m_io->read_byte(Y)); m_icount-=11;break; + case 0x18: X=Y;m_icount-=11;break; + case 0x19: lh5801_and(m_io->read_byte(Y)); m_icount-=11;break; + case 0x1a: lh5801_pop_word(&m_y); m_icount-=15;break; + case 0x1b: lh5801_ora(m_io->read_byte(Y)); m_icount-=11;break; + case 0x1c: lh5801_dcs(m_io->read_byte(Y)); m_icount-=17; break; + case 0x1d: lh5801_eor(m_io->read_byte(Y)); m_icount-=11;break; + case 0x1e: m_io->write_byte(Y,m_a); m_icount-=10;break; + case 0x1f: lh5801_bit(m_io->read_byte(Y),m_a); m_icount-=11;break; + case 0x21: lh5801_sbc(m_io->read_byte(U)); m_icount-=11;break; + case 0x23: lh5801_adc(m_io->read_byte(U)); m_icount-=11;break; + case 0x25: lh5801_lda(m_io->read_byte(U)); m_icount-=10;break; + case 0x27: lh5801_cpa(m_a, m_io->read_byte(U)); m_icount-=11;break; + case 0x28: X=U;m_icount-=11;break; + case 0x29: lh5801_and(m_io->read_byte(U)); m_icount-=11;break; + case 0x2a: lh5801_pop_word(&m_u); m_icount-=15;break; + case 0x2b: lh5801_ora(m_io->read_byte(U)); m_icount-=11;break; + case 0x2c: lh5801_dcs(m_io->read_byte(U)); m_icount-=17; break; + case 0x2d: lh5801_eor(m_io->read_byte(U)); m_icount-=11;break; + case 0x2e: m_io->write_byte(U,m_a); m_icount-=10;break; + case 0x2f: lh5801_bit(m_io->read_byte(U),m_a); m_icount-=11;break; + case 0x40: lh5801_inc(&XH);m_icount-=9;break; + case 0x42: lh5801_dec(&XH);m_icount-=9;break; + case 0x48: X=S;m_icount-=11;break; + case 0x49: lh5801_and_mem(*m_io, X, m_direct->read_byte(P++)); m_icount-=17;break; + case 0x4a: X=X;m_icount-=11;break; //!!! + case 0x4b: lh5801_ora_mem(*m_io, X, m_direct->read_byte(P++)); m_icount-=17;break; + case 0x4c: m_bf=0;/*off !*/ m_icount-=8;break; + case 0x4d: lh5801_bit(m_io->read_byte(X), m_direct->read_byte(P++));m_icount-=14;break; + case 0x4e: S=X;m_icount-=11;break; + case 0x4f: lh5801_add_mem(*m_io, X, m_direct->read_byte(P++)); m_icount-=17;break; + case 0x50: lh5801_inc(&YH);m_icount-=9;break; + case 0x52: lh5801_dec(&YH);m_icount-=9;break; + case 0x58: X=P;m_icount-=11;break; + case 0x59: lh5801_and_mem(*m_io, Y, m_direct->read_byte(P++)); m_icount-=17;break; + case 0x5a: Y=X;m_icount-=11;break; + case 0x5b: lh5801_ora_mem(*m_io, Y, m_direct->read_byte(P++)); m_icount-=17;break; + case 0x5d: lh5801_bit(m_io->read_byte(Y), m_direct->read_byte(P++));m_icount-=14;break; + case 0x5e: lh5801_jmp(X);m_icount-=11;break; // P=X + case 0x5f: lh5801_add_mem(*m_io, Y, m_direct->read_byte(P++)); m_icount-=17;break; + case 0x60: lh5801_inc(&UH);m_icount-=9;break; + case 0x62: lh5801_dec(&UH);m_icount-=9;break; + case 0x69: lh5801_and_mem(*m_io, U, m_direct->read_byte(P++)); m_icount-=17;break; + case 0x6a: U=X;m_icount-=11;break; + case 0x6b: lh5801_ora_mem(*m_io, U, m_direct->read_byte(P++)); m_icount-=17;break; + case 0x6d: lh5801_bit(m_io->read_byte(X), m_direct->read_byte(P++));m_icount-=14;break; + case 0x6f: lh5801_add_mem(*m_io, U, m_direct->read_byte(P++)); m_icount-=17;break; + case 0x81: m_t|=IE; /*sie !*/m_icount-=8;break; + case 0x88: lh5801_push_word(X); m_icount-=14;break; + case 0x8a: lh5801_pop(); m_icount-=12; break; + case 0x8c: lh5801_dca(m_io->read_byte(X)); m_icount-=19; break; + case 0x8e: /*cdv clears internal devider*/m_icount-=8;break; + case 0x98: lh5801_push_word(Y); m_icount-=14;break; + case 0x9c: lh5801_dca(m_io->read_byte(Y)); m_icount-=19; break; + case 0xa1: lh5801_sbc(m_io->read_byte(lh5801_readop_word())); m_icount-=17;break; + case 0xa3: lh5801_adc(m_io->read_byte(lh5801_readop_word())); m_icount-=17;break; + case 0xa5: lh5801_lda(m_io->read_byte(lh5801_readop_word())); m_icount-=16;break; + case 0xa7: lh5801_cpa(m_a, m_io->read_byte(lh5801_readop_word())); m_icount-=17;break; + case 0xa8: lh5801_push_word(U); m_icount-=14;break; + case 0xa9: lh5801_and(m_io->read_byte(lh5801_readop_word())); m_icount-=17;break; + case 0xaa: lh5801_lda(m_t); m_icount-=9;break; + case 0xab: lh5801_ora(m_io->read_byte(lh5801_readop_word())); m_icount-=17;break; + case 0xac: lh5801_dca(m_io->read_byte(U)); m_icount-=19; break; + case 0xad: lh5801_eor(m_io->read_byte(lh5801_readop_word())); m_icount-=17;break; + case 0xae: m_io->write_byte(lh5801_readop_word(),m_a); m_icount-=16;break; + case 0xaf: lh5801_bit(m_io->read_byte(lh5801_readop_word()),m_a); m_icount-=17;break; + case 0xb1: /*hlt*/m_icount-=8;break; + case 0xba: lh5801_ita();m_icount-=9;break; + case 0xbe: m_t&=~IE; /*rie !*/m_icount-=8;break; + case 0xc0: m_dp=0; /*rdp !*/m_icount-=8;break; + case 0xc1: m_dp=1; /*sdp !*/m_icount-=8;break; + case 0xc8: lh5801_push(m_a); m_icount-=11;break; + case 0xca: lh5801_adr(&m_x);m_icount-=11;break; + case 0xcc: /*atp sends a to data bus*/m_icount-=9;break; + case 0xce: lh5801_am(m_a); m_icount-=9; break; + case 0xd3: lh5801_drr(*m_io, X); m_icount-=16; break; + case 0xd7: lh5801_drl(*m_io, X); m_icount-=16; break; + case 0xda: lh5801_adr(&m_y);m_icount-=11;break; + case 0xde: lh5801_am(m_a|0x100); m_icount-=9; break; + case 0xea: lh5801_adr(&m_u);m_icount-=11;break; + case 0xe9: + adr=lh5801_readop_word(); + lh5801_and_mem(*m_io, adr, m_direct->read_byte(P++)); m_icount-=23; + break; + case 0xeb: + adr=lh5801_readop_word(); + lh5801_ora_mem(*m_io, adr, m_direct->read_byte(P++)); m_icount-=23; + break; + case 0xec: m_t=m_a; m_icount-=9;break; + case 0xed: + adr=lh5801_readop_word(); + lh5801_bit(m_io->read_byte(adr), m_direct->read_byte(P++)); + m_icount-=20;break; + case 0xef: + adr=lh5801_readop_word(); + lh5801_add_mem(*m_io, adr, m_direct->read_byte(P++)); m_icount-=23; + break; + + default: + logerror("lh5801 illegal opcode at %.4x fd%.2x\n",P-2, oper); + } +} + +void lh5801_cpu_device::lh5801_instruction() +{ + int oper; + int adr; + + oper=m_direct->read_byte(P++); + switch (oper) { + case 0x00: lh5801_sbc(XL); m_icount-=6;break; + case 0x01: lh5801_sbc(m_program->read_byte(X)); m_icount-=7;break; + case 0x02: lh5801_adc(XL); m_icount-=6;break; + case 0x03: lh5801_adc(m_program->read_byte(X)); m_icount-=7;break; + case 0x04: lh5801_lda(XL); m_icount-=5;break; + case 0x05: lh5801_lda(m_program->read_byte(X)); m_icount-=6;break; + case 0x06: lh5801_cpa(m_a, XL); m_icount-=6;break; + case 0x07: lh5801_cpa(m_a, m_program->read_byte(X)); m_icount-=7;break; + case 0x08: XH=m_a; m_icount-=5; break; + case 0x09: lh5801_and(m_program->read_byte(X)); m_icount-=7;break; + case 0x0a: XL=m_a; m_icount-=5; break; + case 0x0b: lh5801_ora(m_program->read_byte(X)); m_icount-=7;break; + case 0x0c: lh5801_dcs(m_program->read_byte(X)); m_icount-=13; break; + case 0x0d: lh5801_eor(m_program->read_byte(X)); m_icount-=7;break; + case 0x0e: m_program->write_byte(X,m_a); m_icount-=6;break; + case 0x0f: lh5801_bit(m_program->read_byte(X),m_a); m_icount-=7;break; + case 0x10: lh5801_sbc(YL); m_icount-=6;break; + case 0x11: lh5801_sbc(m_program->read_byte(Y)); m_icount-=7;break; + case 0x12: lh5801_adc(YL); m_icount-=6;break; + case 0x13: lh5801_adc(m_program->read_byte(Y)); m_icount-=7;break; + case 0x14: lh5801_lda(YL); m_icount-=5;break; + case 0x15: lh5801_lda(m_program->read_byte(Y)); m_icount-=6;break; + case 0x16: lh5801_cpa(m_a, YL); m_icount-=6;break; + case 0x17: lh5801_cpa(m_a, m_program->read_byte(Y)); m_icount-=7;break; + case 0x18: YH=m_a; m_icount-=5; break; + case 0x19: lh5801_and(m_program->read_byte(Y)); m_icount-=7;break; + case 0x1a: YL=m_a; m_icount-=5; break; + case 0x1b: lh5801_ora(m_program->read_byte(Y)); m_icount-=7;break; + case 0x1c: lh5801_dcs(m_program->read_byte(Y)); m_icount-=13; break; + case 0x1d: lh5801_eor(m_program->read_byte(Y)); m_icount-=7;break; + case 0x1e: m_program->write_byte(Y,m_a); m_icount-=6;break; + case 0x1f: lh5801_bit(m_program->read_byte(Y),m_a); m_icount-=7;break; + case 0x20: lh5801_sbc(UL); m_icount-=6;break; + case 0x21: lh5801_sbc(m_program->read_byte(U)); m_icount-=7;break; + case 0x22: lh5801_adc(UL); m_icount-=6;break; + case 0x23: lh5801_adc(m_program->read_byte(U)); m_icount-=7;break; + case 0x24: lh5801_lda(UL); m_icount-=5;break; + case 0x25: lh5801_lda(m_program->read_byte(U)); m_icount-=6;break; + case 0x26: lh5801_cpa(m_a, UL); m_icount-=6;break; + case 0x27: lh5801_cpa(m_a, m_program->read_byte(U)); m_icount-=7;break; + case 0x28: UH=m_a; m_icount-=5; break; + case 0x29: lh5801_and(m_program->read_byte(U)); m_icount-=7;break; + case 0x2a: UL=m_a; m_icount-=5; break; + case 0x2b: lh5801_ora(m_program->read_byte(U)); m_icount-=7;break; + case 0x2c: lh5801_dcs(m_program->read_byte(U)); m_icount-=13; break; + case 0x2d: lh5801_eor(m_program->read_byte(U)); m_icount-=7;break; + case 0x2e: m_program->write_byte(U,m_a); m_icount-=6;break; + case 0x2f: lh5801_bit(m_program->read_byte(U),m_a); m_icount-=7;break; + case 0x38: /*nop*/m_icount-=5;break; + case 0x40: lh5801_inc(&XL);m_icount-=5;break; + case 0x41: lh5801_sin(&m_x); m_icount-=6;break; + case 0x42: lh5801_dec(&XL);m_icount-=5;break; + case 0x43: lh5801_sde(&m_x); m_icount-=6;break; + case 0x44: X++;m_icount-=5;break; + case 0x45: lh5801_lin(&m_x);m_icount-=6;break; + case 0x46: X--;m_icount-=5;break; + case 0x47: lh5801_lde(&m_x);m_icount-=6;break; + case 0x48: XH=m_direct->read_byte(P++);m_icount-=6;break; + case 0x49: lh5801_and_mem(*m_program, X, m_direct->read_byte(P++)); m_icount-=13;break; + case 0x4a: XL=m_direct->read_byte(P++);m_icount-=6;break; + case 0x4b: lh5801_ora_mem(*m_program, X, m_direct->read_byte(P++)); m_icount-=13;break; + case 0x4c: lh5801_cpa(XH, m_direct->read_byte(P++)); m_icount-=7;break; + case 0x4d: lh5801_bit(m_program->read_byte(X), m_direct->read_byte(P++));m_icount-=10;break; + case 0x4e: lh5801_cpa(XL, m_direct->read_byte(P++)); m_icount-=7;break; + case 0x4f: lh5801_add_mem(*m_program, X, m_direct->read_byte(P++)); m_icount-=13;break; + case 0x50: lh5801_inc(&YL);m_icount-=5;break; + case 0x51: lh5801_sin(&m_y); m_icount-=6;break; + case 0x52: lh5801_dec(&YL);m_icount-=5;break; + case 0x53: lh5801_sde(&m_y); m_icount-=6;break; + case 0x54: Y++;m_icount-=5;break; + case 0x55: lh5801_lin(&m_y);m_icount-=6;break; + case 0x56: Y--;m_icount-=5;break; + case 0x57: lh5801_lde(&m_y);m_icount-=6;break; + case 0x58: YH=m_direct->read_byte(P++);m_icount-=6;break; + case 0x59: lh5801_and_mem(*m_program, Y, m_direct->read_byte(P++)); m_icount-=13;break; + case 0x5a: YL=m_direct->read_byte(P++);m_icount-=6;break; + case 0x5b: lh5801_ora_mem(*m_program, Y, m_direct->read_byte(P++)); m_icount-=13;break; + case 0x5c: lh5801_cpa(YH, m_direct->read_byte(P++)); m_icount-=7;break; + case 0x5d: lh5801_bit(m_program->read_byte(Y), m_direct->read_byte(P++));m_icount-=10;break; + case 0x5e: lh5801_cpa(YL, m_direct->read_byte(P++)); m_icount-=7;break; + case 0x5f: lh5801_add_mem(*m_program, Y, m_direct->read_byte(P++)); m_icount-=13;break; + case 0x60: lh5801_inc(&UL);m_icount-=5;break; + case 0x61: lh5801_sin(&m_u); m_icount-=6;break; + case 0x62: lh5801_dec(&UL);m_icount-=5;break; + case 0x63: lh5801_sde(&m_u); m_icount-=6;break; + case 0x64: U++;m_icount-=5;break; + case 0x65: lh5801_lin(&m_u);m_icount-=6;break; + case 0x66: U--;m_icount-=5;break; + case 0x67: lh5801_lde(&m_u);m_icount-=6;break; + case 0x68: UH=m_direct->read_byte(P++);m_icount-=6;break; + case 0x69: lh5801_and_mem(*m_program, U, m_direct->read_byte(P++)); m_icount-=13;break; + case 0x6a: UL=m_direct->read_byte(P++);m_icount-=6;break; + case 0x6b: lh5801_ora_mem(*m_program, U, m_direct->read_byte(P++)); m_icount-=13;break; + case 0x6c: lh5801_cpa(UH, m_direct->read_byte(P++)); m_icount-=7;break; + case 0x6d: lh5801_bit(m_program->read_byte(U), m_direct->read_byte(P++));m_icount-=10;break; + case 0x6e: lh5801_cpa(UL, m_direct->read_byte(P++)); m_icount-=7;break; + case 0x6f: lh5801_add_mem(*m_program, U, m_direct->read_byte(P++)); m_icount-=13;break; + case 0x80: lh5801_sbc(XH); m_icount-=6;break; + case 0x81: lh5801_branch_plus(!(m_t&C)); m_icount-=8; break; + case 0x82: lh5801_adc(XH); m_icount-=6;break; + case 0x83: lh5801_branch_plus(m_t&C); m_icount-=8; break; + case 0x84: lh5801_lda(XH); m_icount-=5;break; + case 0x85: lh5801_branch_plus(!(m_t&H)); m_icount-=8; break; + case 0x86: lh5801_cpa(m_a, XH); m_icount-=6;break; + case 0x87: lh5801_branch_plus(m_t&H); m_icount-=8; break; + case 0x88: lh5801_lop(); break; + case 0x89: lh5801_branch_plus(!(m_t&Z)); m_icount-=8; break; + case 0x8a: lh5801_rti(); m_icount-=14; break; + case 0x8b: lh5801_branch_plus(m_t&Z); m_icount-=8; break; + case 0x8c: lh5801_dca(m_program->read_byte(X)); m_icount-=15; break; + case 0x8d: lh5801_branch_plus(!(m_t&V)); m_icount-=8; break; + case 0x8e: lh5801_branch_plus(1); m_icount-=5; break; + case 0x8f: lh5801_branch_plus(m_t&V); m_icount-=8; break; + case 0x90: lh5801_sbc(YH); m_icount-=6;break; + case 0x91: lh5801_branch_minus(!(m_t&C)); m_icount-=8; break; + case 0x92: lh5801_adc(YH); m_icount-=6;break; + case 0x93: lh5801_branch_minus(m_t&C); m_icount-=8; break; + case 0x94: lh5801_lda(YH); m_icount-=5;break; + case 0x95: lh5801_branch_minus(!(m_t&H)); m_icount-=8; break; + case 0x96: lh5801_cpa(m_a, YH); m_icount-=6;break; + case 0x97: lh5801_branch_minus(m_t&H); m_icount-=8; break; + case 0x99: lh5801_branch_minus(!(m_t&Z)); m_icount-=8; break; + case 0x9a: lh5801_rtn(); m_icount-=11; break; + case 0x9b: lh5801_branch_minus(m_t&Z); m_icount-=8; break; + case 0x9c: lh5801_dca(m_program->read_byte(Y)); m_icount-=15; break; + case 0x9d: lh5801_branch_minus(!(m_t&V)); m_icount-=8; break; + case 0x9e: lh5801_branch_minus(1); m_icount-=6; break; + case 0x9f: lh5801_branch_minus(m_t&V); m_icount-=8; break; + case 0xa0: lh5801_sbc(UH); m_icount-=6;break; + case 0xa2: lh5801_adc(UH); m_icount-=6;break; + case 0xa1: lh5801_sbc(m_program->read_byte(lh5801_readop_word())); m_icount-=13;break; + case 0xa3: lh5801_adc(m_program->read_byte(lh5801_readop_word())); m_icount-=13;break; + case 0xa4: lh5801_lda(UH); m_icount-=5;break; + case 0xa5: lh5801_lda(m_program->read_byte(lh5801_readop_word())); m_icount-=12;break; + case 0xa6: lh5801_cpa(m_a, UH); m_icount-=6;break; + case 0xa7: lh5801_cpa(m_a, m_program->read_byte(lh5801_readop_word())); m_icount-=13;break; + case 0xa8: m_pv=1;/*spv!*/ m_icount-=4; break; + case 0xa9: lh5801_and(m_program->read_byte(lh5801_readop_word())); m_icount-=13;break; + case 0xaa: S=lh5801_readop_word();m_icount-=6;break; + case 0xab: lh5801_ora(m_program->read_byte(lh5801_readop_word())); m_icount-=13;break; + case 0xac: lh5801_dca(m_program->read_byte(U)); m_icount-=15; break; + case 0xad: lh5801_eor(m_program->read_byte(lh5801_readop_word())); m_icount-=13;break; + case 0xae: m_program->write_byte(lh5801_readop_word(),m_a); m_icount-=12;break; + case 0xaf: lh5801_bit(m_program->read_byte(lh5801_readop_word()),m_a); m_icount-=13;break; + case 0xb1: lh5801_sbc(m_direct->read_byte(P++)); m_icount-=7;break; + case 0xb3: lh5801_adc(m_direct->read_byte(P++)); m_icount-=7;break; + case 0xb5: lh5801_lda(m_direct->read_byte(P++)); m_icount-=6;break; + case 0xb7: lh5801_cpa(m_a, m_direct->read_byte(P++)); m_icount-=7;break; + case 0xb8: m_pv=0;/*rpv!*/ m_icount-=4; break; + case 0xb9: lh5801_and(m_direct->read_byte(P++)); m_icount-=7;break; + case 0xba: lh5801_jmp(lh5801_readop_word()); m_icount-=12;break; + case 0xbb: lh5801_ora(m_direct->read_byte(P++)); m_icount-=7;break; + case 0xbd: lh5801_eor(m_direct->read_byte(P++)); m_icount-=7;break; + case 0xbe: lh5801_sjp(); m_icount-=19; break; + case 0xbf: lh5801_bit(m_a, m_direct->read_byte(P++));m_icount-=7;break; + case 0xc1: lh5801_vector(!(m_t&C), m_direct->read_byte(P++)); m_icount-=8;break; + case 0xc3: lh5801_vector(m_t&C, m_direct->read_byte(P++)); m_icount-=8;break; + case 0xc5: lh5801_vector(!(m_t&H), m_direct->read_byte(P++)); m_icount-=8;break; + case 0xc7: lh5801_vector(m_t&H, m_direct->read_byte(P++)); m_icount-=8;break; + case 0xc9: lh5801_vector(!(m_t&Z), m_direct->read_byte(P++)); m_icount-=8;break; + case 0xcb: lh5801_vector(m_t&Z, m_direct->read_byte(P++)); m_icount-=8;break; + case 0xcd: lh5801_vector(1, m_direct->read_byte(P++)); m_icount-=7;break; + case 0xcf: lh5801_vector(m_t&V, m_direct->read_byte(P++)); m_icount-=8;break; + case 0xd1: lh5801_ror(); m_icount-=6; break; + case 0xd3: lh5801_drr(*m_program, X); m_icount-=12; break; + case 0xd5: lh5801_shr(); m_icount-=6; break; + case 0xd7: lh5801_drl(*m_program, X); m_icount-=12; break; + case 0xd9: lh5801_shl(); m_icount-=6; break; + case 0xdb: lh5801_rol(); m_icount-=6; break; + case 0xdd: lh5801_inc(&m_a);m_icount-=5;break; + case 0xdf: lh5801_dec(&m_a);m_icount-=5;break; + case 0xe1: m_pu=1;/*spu!*/ m_icount-=4; break; + case 0xe3: m_pu=0;/*rpu!*/ m_icount-=4; break; + case 0xe9: + adr=lh5801_readop_word();lh5801_and_mem(*m_program, adr, m_direct->read_byte(P++)); + m_icount-=19;break; + case 0xeb: + adr=lh5801_readop_word();lh5801_ora_mem(*m_program, adr, m_direct->read_byte(P++)); + m_icount-=19;break; + case 0xed: + adr=lh5801_readop_word();lh5801_bit(m_program->read_byte(adr), m_direct->read_byte(P++)); + m_icount-=16;break; + case 0xef: + adr=lh5801_readop_word(); + lh5801_add_mem(*m_program, adr, m_direct->read_byte(P++)); m_icount-=19; + break; + case 0xf1: lh5801_aex(); m_icount-=6; break; + case 0xf5: m_program->write_byte(Y++, m_program->read_byte(X++)); m_icount-=7; break; //tin + case 0xf7: lh5801_cpa(m_a, m_program->read_byte(X++));m_icount-=7; break; //cin + case 0xf9: m_t&=~C;m_icount-=4;break; + case 0xfb: m_t|=C;m_icount-=4;break; + case 0xfd: lh5801_instruction_fd();break; + case 0xc0: case 0xc2: case 0xc4: case 0xc6: + case 0xc8: case 0xca: case 0xcc: case 0xce: + case 0xd0: case 0xd2: case 0xd4: case 0xd6: + case 0xd8: case 0xda: case 0xdc: case 0xde: + case 0xe0: case 0xe2: case 0xe4: case 0xe6: + case 0xe8: case 0xea: case 0xec: case 0xee: + case 0xf0: case 0xf2: case 0xf4: case 0xf6: + lh5801_vector(1, oper);m_icount-=4;break; + default: + logerror("lh5801 illegal opcode at %.4x %.2x\n",P-1, oper); + } + +} diff --git a/src/devices/cpu/lh5801/lh5801.c b/src/devices/cpu/lh5801/lh5801.c new file mode 100644 index 00000000000..0287e0d0859 --- /dev/null +++ b/src/devices/cpu/lh5801/lh5801.c @@ -0,0 +1,254 @@ +// license:BSD-3-Clause +// copyright-holders:Peter Trauner +/***************************************************************************** + * + * + * 02/2011 (Sandro Ronco) + * - Added IO_SPACE and updated all access in ME1 memory for use it. + * - Implemented interrupts. + * - Fixed the flags in the ROL/ROR/SHL/SHR opcodes. + * - Fixed decimal add/sub opcodes. + * + * based on info found on an artikel for the tandy trs80 pc2 + * and on "PC1500 Technical reference manual" + * + *****************************************************************************/ + +#include "emu.h" +#include "debugger.h" + +#include "lh5801.h" + +#define VERBOSE 0 + +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +enum +{ + LH5801_T=1, + LH5801_P, + LH5801_S, + LH5801_U, + LH5801_X, + LH5801_Y, + LH5801_A, + + LH5801_TM, + LH5801_IN, + LH5801_BF, + LH5801_PU, + LH5801_PV, + LH5801_DP, + LH5801_IRQ_STATE +}; + + +#define P m_p.w.l +#define S m_s.w.l +#define U m_u.w.l +#define UL m_u.b.l +#define UH m_u.b.h +#define X m_x.w.l +#define XL m_x.b.l +#define XH m_x.b.h +#define Y m_y.w.l +#define YL m_y.b.l +#define YH m_y.b.h + +#define C 0x01 +#define IE 0x02 +#define Z 0x04 +#define V 0x08 +#define H 0x10 + + +const device_type LH5801 = &device_creator<lh5801_cpu_device>; + + +lh5801_cpu_device::lh5801_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : cpu_device(mconfig, LH5801, "LH5801", tag, owner, clock, "lh5801", __FILE__) + , m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0) + , m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0) + , m_in_func(*this) +{ +} + + +/*************************************************************** + * include the opcode macros, functions and tables + ***************************************************************/ +#include "5801tbl.inc" + +void lh5801_cpu_device::device_start() +{ + m_program = &space(AS_PROGRAM); + m_io = &space(AS_IO); + m_direct = &m_program->direct(); + + m_in_func.resolve_safe(0); + + m_s.w.l = 0; + m_p.w.l = 0; + m_u.w.l = 0; + m_x.w.l = 0; + m_y.w.l = 0; + m_tm = 0; + m_t = 0; + m_a = 0; + m_bf = 0; + m_dp = 0; + m_pu = 0; + m_pv = 0; + m_oldpc = 0; + m_irq_state = 0; + memset(m_ir_flipflop, 0, sizeof(m_ir_flipflop)); + memset(m_lines_status, 0, sizeof(m_lines_status)); + m_idle = 0; + + save_item(NAME(m_s.w.l)); + save_item(NAME(m_p.w.l)); + save_item(NAME(m_u.w.l)); + save_item(NAME(m_x.w.l)); + save_item(NAME(m_y.w.l)); + save_item(NAME(m_tm)); + save_item(NAME(m_t)); + save_item(NAME(m_a)); + save_item(NAME(m_bf)); + save_item(NAME(m_dp)); + save_item(NAME(m_pu)); + save_item(NAME(m_pv)); + save_item(NAME(m_oldpc)); + save_item(NAME(m_irq_state)); + save_item(NAME(m_ir_flipflop)); + save_item(NAME(m_lines_status)); + save_item(NAME(m_idle)); + + state_add( LH5801_P, "P", m_p.w.l ).formatstr("%04X"); + state_add( LH5801_S, "S", m_s.w.l ).formatstr("%04X"); + state_add( LH5801_U, "U", m_u.w.l ).formatstr("%04X"); + state_add( LH5801_X, "X", m_x.w.l ).formatstr("%04X"); + state_add( LH5801_Y, "Y", m_y.w.l ).formatstr("%04X"); + state_add( LH5801_T, "T", m_t ).formatstr("%02X"); + state_add( LH5801_A, "A", m_a ).formatstr("%02X"); + state_add( LH5801_TM, "TM", m_tm ).formatstr("%03X"); + state_add( LH5801_PV, "PV", m_pv ).formatstr("%04X"); + state_add( LH5801_PU, "PU", m_pu ).formatstr("%04X"); + state_add( LH5801_BF, "BF", m_bf ).formatstr("%04X"); + state_add( LH5801_DP, "DP", m_dp ).formatstr("%04X"); + + state_add(STATE_GENPC, "GENPC", m_p.w.l).noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_t).noshow().formatstr("%8s"); + + m_icountptr = &m_icount; +} + +void lh5801_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + strprintf(str, "%c%c%c%c%c%c%c%c", + m_t&0x80?'1':'0', + m_t&0x40?'1':'0', + m_t&0x20?'1':'0', + m_t&0x10?'H':'.', + m_t&0x08?'V':'.', + m_t&0x04?'Z':'.', + m_t&0x02?'I':'.', + m_t&0x01?'C':'.'); + break; + } +} + +void lh5801_cpu_device::device_reset() +{ + P = (m_program->read_byte(0xfffe)<<8) | m_program->read_byte(0xffff); + + m_idle=0; + + memset(m_ir_flipflop, 0, sizeof(m_ir_flipflop)); + memset(m_lines_status, 0, sizeof(m_lines_status)); +} + + +void lh5801_cpu_device::check_irq() +{ + if (m_ir_flipflop[0]) + { + //NMI interrupt + m_ir_flipflop[0] = 0; + lh5801_push(m_t); + m_t&=~IE; + lh5801_push_word(P); + P = (m_program->read_byte(0xfffc)<<8) | m_program->read_byte(0xfffd); + } + else if (m_ir_flipflop[1] && (m_t & IE)) + { + //counter interrupt (counter not yet implemented) + m_ir_flipflop[1] = 0; + lh5801_push(m_t); + m_t&=~IE; + lh5801_push_word(P); + P = (m_program->read_byte(0xfffa)<<8) | m_program->read_byte(0xfffb); + } + else if (m_ir_flipflop[2] && (m_t & IE)) + { + //MI interrupt + m_ir_flipflop[2] = 0; + lh5801_push(m_t); + m_t&=~IE; + lh5801_push_word(P); + P = (m_program->read_byte(0xfff8)<<8) | m_program->read_byte(0xfff9); + } +} + + +void lh5801_cpu_device::execute_run() +{ + do + { + check_irq(); + + if (m_idle) + m_icount = 0; + else + { + m_oldpc = P; + + debugger_instruction_hook(this, P); + lh5801_instruction(); + } + + } while (m_icount > 0); +} + +void lh5801_cpu_device::execute_set_input(int irqline, int state) +{ + switch( irqline) + { + case LH5801_LINE_MI: + if (m_lines_status[0] == CLEAR_LINE && state == ASSERT_LINE) + { + m_idle = 0; + m_ir_flipflop[2] = 1; + } + + m_lines_status[0] = state; + break; + case INPUT_LINE_NMI: + if (m_lines_status[1] == CLEAR_LINE && state == ASSERT_LINE) + { + m_idle = 0; + m_ir_flipflop[0] = 1; + } + + m_lines_status[1] = state; + break; + } +} + +offs_t lh5801_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) +{ + extern CPU_DISASSEMBLE( lh5801 ); + return CPU_DISASSEMBLE_NAME(lh5801)(this, buffer, pc, oprom, opram, options); +} diff --git a/src/devices/cpu/lh5801/lh5801.h b/src/devices/cpu/lh5801/lh5801.h new file mode 100644 index 00000000000..e5c6aa74690 --- /dev/null +++ b/src/devices/cpu/lh5801/lh5801.h @@ -0,0 +1,188 @@ +// license:BSD-3-Clause +// copyright-holders:Peter Trauner +/***************************************************************************** + * + * cpustate->h + * portable lh5801 emulator interface + * + * + *****************************************************************************/ +#pragma once + +#ifndef __LH5801_H__ +#define __LH5801_H__ + +/* +lh5801 + +little endian + +ph, pl p +sh, sl s + +xh, xl x +yh, yl y +uh, ul u + +a A + +0 0 0 H V Z IE C + +TM 9bit polynominal? + +pu pv disp flipflops + +bf flipflop (break key connected) + + me0, me1 chip select for 2 64kb memory blocks + +in0-in7 input pins + + mi maskable interrupt input (fff8/9) + timer fffa/b + nmi non .. (fffc/d) + reset fffe/f +e ? + + + +lh5811 chip +pa 8bit io +pb 8bit io +pc 8bit +*/ + + +// input lines +enum +{ + LH5801_LINE_MI //maskable interrupt +}; + + +#define MCFG_LH5801_IN(_devcb) \ + lh5801_cpu_device::set_in_func(*device, DEVCB_##_devcb); + + +class lh5801_cpu_device : public cpu_device +{ +public: + // construction/destruction + lh5801_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // static configuration helpers + template<class _Object> static devcb_base &set_in_func(device_t &device, _Object object) { return downcast<lh5801_cpu_device &>(device).m_in_func.set_callback(object); } + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_execute_interface overrides + virtual UINT32 execute_min_cycles() const { return 2; } + virtual UINT32 execute_max_cycles() const { return 19; } + virtual UINT32 execute_input_lines() const { return 2; } + virtual UINT32 execute_default_irq_vector() const { return 0; } + virtual void execute_run(); + virtual void execute_set_input(int inputnum, int state); + + // device_memory_interface overrides + virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_IO) ? &m_io_config : NULL ); } + + // device_state_interface overrides + void state_string_export(const device_state_entry &entry, std::string &str); + + // device_disasm_interface overrides + virtual UINT32 disasm_min_opcode_bytes() const { return 1; } + virtual UINT32 disasm_max_opcode_bytes() const { return 5; } + virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); + +private: + address_space_config m_program_config; + address_space_config m_io_config; + + devcb_read8 m_in_func; + + address_space *m_program; //ME0 + address_space *m_io; //ME1 + direct_read_data *m_direct; + + PAIR m_s; + PAIR m_p; + PAIR m_u; + PAIR m_x; + PAIR m_y; + int m_tm; //9 bit + + UINT8 m_t, m_a; + + int m_bf; + int m_dp; + int m_pu; + int m_pv; + + UINT16 m_oldpc; + + int m_irq_state; + + UINT8 m_ir_flipflop[3]; //interrupt request flipflop: IR0, IR1, IR2 + int m_lines_status[2]; //MI and NMI lines status + + int m_idle; + int m_icount; + + void check_irq(); + void lh5801_instruction_fd(); + void lh5801_instruction(); + UINT8 lh5801_add_generic(int left, int right, int carry); + UINT16 lh5801_readop_word(); + void lh5801_adc(UINT8 data); + void lh5801_add_mem(address_space &space, int addr, UINT8 data); + void lh5801_adr(PAIR *reg); + void lh5801_sbc(UINT8 data); + void lh5801_cpa(UINT8 a, UINT8 b); + UINT8 lh5801_decimaladd_generic(int left, int right, int carry); + void lh5801_dca(UINT8 data); + void lh5801_dcs(UINT8 data); + void lh5801_and(UINT8 data); + void lh5801_and_mem(address_space &space, int addr, UINT8 data); + void lh5801_bit(UINT8 a, UINT8 b); + void lh5801_eor(UINT8 data); + void lh5801_ora(UINT8 data); + void lh5801_ora_mem(address_space &space, int addr, UINT8 data); + void lh5801_lda(UINT8 data); + void lh5801_lde(PAIR *reg); + void lh5801_sde(PAIR *reg); + void lh5801_lin(PAIR *reg); + void lh5801_sin(PAIR *reg); + void lh5801_dec(UINT8 *adr); + void lh5801_inc(UINT8 *adr); + void lh5801_pop(); + void lh5801_pop_word(PAIR *reg); + void lh5801_rtn(); + void lh5801_rti(); + void lh5801_push(UINT8 data); + void lh5801_push_word(UINT16 data); + void lh5801_jmp(UINT16 adr); + void lh5801_branch_plus(int doit); + void lh5801_branch_minus(int doit); + void lh5801_lop(); + void lh5801_sjp(); + void lh5801_vector(int doit, int nr); + void lh5801_aex(); + void lh5801_drl(address_space &space, int adr); + void lh5801_drr(address_space &space, int adr); + void lh5801_rol(); + void lh5801_ror(); + void lh5801_shl(); + void lh5801_shr(); + void lh5801_am(int value); + void lh5801_ita(); + +}; + + +extern const device_type LH5801; + + +#endif /* __LH5801_H__ */ |