kervinck / gigatron-rom

System, apps and tooling for the Gigatron TTL microcomputer
BSD 2-Clause "Simplified" License
231 stars 80 forks source link

v8080 #108

Open kervinck opened 5 years ago

kervinck commented 5 years ago

In a similar manner as vCPU and v6502, add an interpreter for the 8080 instruction set as suggested by AlanC.

Justification: together with a block device (SDC/MMC), this opens the road to run CP/M on the Gigatron. 8080 is much simpler than Z80, and sufficient to get CP/M and applications running. We probably need to interface with CP/M over a SPI interface, instead of having the Gigatron act as a video terminal like we're used to now. (But we can still use the VGA output as a "god view" of the memory in the CP/M system. Thanks to OscarV for this idea.)

Points of attention:

  1. Take care that the address space is CP/M compatible. For example, the zero-page now isn't. Perhaps solve this by mapping it to a different physical page in the emulation. Otherwise by entering a completely new video loop for this mode.
  2. The parity flag is hard. For proper emulation it needs a lookup from RAM or ROM. But not all applications use this flag. Perhaps we can get very far by ignoring it, or by only looking at bit 0. (This is speculation).
  3. It's probably needed (and ok) to use zero-page variables in the userVars section (that is ≥$30). There's no need to preserve v6502 state when entering v8080 mode. We only need vCPU for the hardware layer, for example to do SYS calls into EPROM.

Some links, courtesy KenB for sending these:

From Propeller Forum

http://forums.parallax.com/discussion/110804/zicog-a-zilog-z80-emulator-in-1-cog

8080 Instruction Set - in octal with colour added

https://nanode0000.wordpress.com/2017/08/22/a-minimum-interactive-language-toolkit/

kervinck commented 5 years ago
8080 instruction encoding:

Conventions in instruction source:
    D   = Destination register (8 bit)
    S   = Source register (8 bit)
    RP  = Register pair (16 bit)
    #   = 8 or 16 bit immediate operand
    a   = 16 bit Memory address
    p   = 8 bit port address
    ccc = Conditional

Conventions in instruction encoding:
    db  = Data byte (8 bit)
    lb  = Low byte of 16 bit value
    hb  = High byte of 16 bit value
    pa  = Port address (8 bit)

Dest and Source reg fields:
    111=A   (Accumulator)
    000=B
    001=C
    010=D
    011=E
    100=H
    101=L
    110=M   (Memory reference through address in H:L)

Register pair 'RP' fields:
    00=BC   (B:C as 16 bit register)
    01=DE   (D:E as 16 bit register)
    10=HL   (H:L as 16 bit register)
    11=SP   (Stack pointer, refers to PSW (FLAGS:A) for PUSH/POP)

Condition code 'CCC' fields: (FLAGS: S Z x A x P x C)
    000=NZ  ('Z'ero flag not set)
    001=Z   ('Z'ero flag set)
    010=NC  ('C'arry flag not set)
    011=C   ('C'arry flag set)
    100=PO  ('P'arity flag not set - ODD)
    101=PE  ('P'arity flag set - EVEN)
    110=P   ('S'ign flag not set - POSITIVE)
    111=M   ('S'ign flag set - MINUS)

Inst      Encoding          Flags   Description
----------------------------------------------------------------------
MOV D,S   01DDDSSS          -       Move register to register
MVI D,#   00DDD110 db       -       Move immediate to register
LXI RP,#  00RP0001 lb hb    -       Load register pair immediate
LDA a     00111010 lb hb    -       Load A from memory
STA a     00110010 lb hb    -       Store A to memory
LHLD a    00101010 lb hb    -       Load H:L from memory
SHLD a    00100010 lb hb    -       Store H:L to memory
LDAX RP   00RP1010 *1       -       Load indirect through BC or DE
STAX RP   00RP0010 *1       -       Store indirect through BC or DE
XCHG      11101011          -       Exchange DE and HL content
ADD S     10000SSS          ZSPCA   Add register to A
ADI #     11000110 db       ZSCPA   Add immediate to A
ADC S     10001SSS          ZSCPA   Add register to A with carry
ACI #     11001110 db       ZSCPA   Add immediate to A with carry
SUB S     10010SSS          ZSCPA   Subtract register from A
SUI #     11010110 db       ZSCPA   Subtract immediate from A
SBB S     10011SSS          ZSCPA   Subtract register from A with borrow
SBI #     11011110 db       ZSCPA   Subtract immediate from A with borrow
INR D     00DDD100          ZSPA    Increment register
DCR D     00DDD101          ZSPA    Decrement register
INX RP    00RP0011          -       Increment register pair
DCX RP    00RP1011          -       Decrement register pair
DAD RP    00RP1001          C       Add register pair to HL (16 bit add)
DAA       00100111          ZSPCA   Decimal Adjust accumulator
ANA S     10100SSS          ZSCPA   AND register with A
ANI #     11100110 db       ZSPCA   AND immediate with A
ORA S     10110SSS          ZSPCA   OR  register with A
ORI #     11110110          ZSPCA   OR  immediate with A
XRA S     10101SSS          ZSPCA   ExclusiveOR register with A
XRI #     11101110 db       ZSPCA   ExclusiveOR immediate with A
CMP S     10111SSS          ZSPCA   Compare register with A
CPI #     11111110          ZSPCA   Compare immediate with A
RLC       00000111          C       Rotate A left
RRC       00001111          C       Rotate A right
RAL       00010111          C       Rotate A left through carry
RAR       00011111          C       Rotate A right through carry
CMA       00101111          -       Compliment A
CMC       00111111          C       Compliment Carry flag
STC       00110111          C       Set Carry flag
JMP a     11000011 lb hb    -       Unconditional jump
Jccc a    11CCC010 lb hb    -       Conditional jump
CALL a    11001101 lb hb    -       Unconditional subroutine call
Cccc a    11CCC100 lb hb    -       Conditional subroutine call
RET       11001001          -       Unconditional return from subroutine
Rccc      11CCC000          -       Conditional return from subroutine
RST n     11NNN111          -       Restart (Call n*8)
PCHL      11101001          -       Jump to address in H:L
PUSH RP   11RP0101 *2       -       Push register pair on the stack
POP RP    11RP0001 *2       *2      Pop  register pair from the stack
XTHL      11100011          -       Swap H:L with top word on stack
SPHL      11111001          -       Set SP to content of H:L
IN p      11011011 pa       -       Read input port into A
OUT p     11010011 pa       -       Write A to output port
EI        11111011          -       Enable interrupts
DI        11110011          -       Disable interrupts
HLT       01110110          -       Halt processor
NOP       00000000          -       No operation

*1 = Only RP=00(BC) and 01(DE) are allowed for LDAX/STAX

*2 = RP=11 refers to PSW for PUSH/POP (cannot push/pop SP).
     When PSW is POP'd, ALL flags are affected.
EtchedPixels commented 4 years ago

CP/M will happily run with a video terminal as well. It has no idea whether the BIOS call it made went out of a serial port, wrote to a textmode display, drew bitmaps or trapped out of emulation into something. It does need some simple terminal emulation logic but that's not hard and lots of old CP/M systems had that. Just don't pick horrors like VT100. ADM3A emulation was popular as being an early terminal it was simple and only had clear screen, home, up, down, left, right, set cursor position.

https://vt100.net/lsi/adm3a-mm.pdf

EtchedPixels commented 4 years ago

As an aside parity checking is indeed fairly rare and the only time you need to evaluate parity is on PUSH PSW and conditional jump using that flag. You need to store the byte whose parity is supposedly in the flag somewhere but you don't actually need to calculate the parity unless someone asks or it becomes observable by other means (PUSH PSW)...

For an early hack you may well still have to deal with Z80 aware code using

SUB A JP PE

to check Z80 v 8080.

kervinck commented 4 years ago

Thanks! The worry about including the video terminal is more about the ~30K effective RAM pressure it creates than about anything else. 1 pixel = 1 byte, no tiling, while each line of 160 pixels leaves a gap of 96 bytes in that memory page. We can perhaps reduce it to ~20K by further reducing the number of text rows, and by sharing the black lines between them. [I'm planning something like that to make MS BASIC and Apple 1 BASIC work on the stock 32K system BTW.]. For SDC/MMC enabled systems we can safely assume 64K/128K is available, but still...

kervinck commented 4 years ago

The other issue is if a 40x20 character video terminal is in any sense "workable" for applications other than Zork. We just have 160 pixels after all. (Or 256 if we allow scrolling, giving 64 chars)

EtchedPixels commented 4 years ago

My Epson PX-4 has a 40x8 display. In software it has an 80x25/40x43 display of which you see a window that tracks the cursor and can be scrolled around. It's quite usable for most things. Trek would suck I suspect though 8)