Shop OBEX P1 Docs P2 Docs Learn Events
P2 Z80 Emulator - Page 2 — Parallax Forums

P2 Z80 Emulator

2»

Comments

  • '***************************************************************************************************************
    '               OPCODES CB xx
    '***************************************************************************************************************
    cb_rlc_b      {cb 00}   mov     alu, B
                            call    #alu_rlc
                            jmp     #alu_to_B
    ' ----------------------------------------------------------------------------------------------
    alu_to_b                mov     B, alu                          ' B   <-- alu
                            jmp     #fetch
    
    '***************************************************************************************************************
    alu_rlc                 shl     alu, #1                         '                               (rotate left)
                            test    alu, #$100      WC              ' get bit #7 into zero flag
                            muxc    alu, #$01                       ' get carry in bit #0
                            jmp     #szp_flags_ff
    ' ----------------------------------------------------------------------------------------------
    ' Compute sign, zero and parity flags after logic/shift/rotate instruction
    szp_flags_ff            mov     F, #0                           ' clear all flags
                            muxc    F, #CF                          ' set C flag on carry
                            and     alu, #$ff       WCZ          ' get zero and parity flags
    szp_flags               muxz    F, #ZF                          ' if zero set Z flag
                            muxnc   F, #PF                          ' if even parity set the P flag
                            test    alu, #$80       WC              ' get sign in prop's carry flag
                  _RET_     muxc    F, #SF                          ' set S flag
    

    ?? RET ist doch nicht mit CALL aufgerufen??

  • Cluso99Cluso99 Posts: 18,069

    I use the jmp #fetch as a quick way to get back in sync without needing to pop the stack and decide if there is another routine to run to complete the instruction. So it's faster.

  • I ran the source code through flexprop to get a lst file.
    I hope someone here sees the error. I've been looking for it for 2 days. :(

  • Cluso99Cluso99 Posts: 18,069
    edited 2021-11-26 12:22

    I am fairly sure that’s not the latest code :(

    What is the date of the last comment ‘ RRyyyymmdd and the rest of the line?

    MMBASIC runs successfully on the latest code :)

    I will look tomorrow.

  • Is that what you mean?

    '' RR20190819      029  fix rdxxxx/wrxxxx with Z80_MEM offset
    ''                      add ea,ram_base -> or ea,ram_base
    ''                      insert OR xx,ram_base before rd/wrbyte/word in various places
    ''                 030-031  debug with zexdoc
    ''                 032  tweek
    
    
    ''============================[ CON 
    
  • Okay, I'll wait a little longer.
    Thank you.

  • Cluso99Cluso99 Posts: 18,069
    edited 2021-11-27 02:14

    I have created a new thread for my P2 Z80 Emulation and posted my latest code here

    https://forums.parallax.com/discussion/174087/clusos-z80-emulation-for-retroblade2-p2#latest

    Enjoy :sunglasses:

  • Thanks Cluso99.
    Let's see how I can get the propeller tool to work.

    Next I have to deal a bit with the memory management of the COG.

    hram $xxxxx --[ copy ]--> COG RAM $00000..$001FF (the hram can be overwritten after loading)
    hram $xxxxx --[ ???? ]--> COG LUT $00200..$003FF ( ? )
    hram $xxxxx --[ ???? ]--> COG HUBEXEC $00400..$FFFFF ( ? )

  • Cluso99Cluso99 Posts: 18,069

    IMHO PropTool and pnut are just not going to work. I gave up that option for this code a long time back. Just use Eric’s Fastspin compiler.

  • Ok, I'll give it a try.
    Github.com is having some problems right now.
    I'll try to access it again tomorrow.
    Is Fastspin available for Windows and Linux(Debian)?

  • Hello,
    I just tested your last Z80 emulator and I must say that the problem does not occur here.
    I have adapted it for the time being so that it runs on the Propellertool. :)
    Later it will be converted to an OBJ. But as I said ... later.

  • Cluso99Cluso99 Posts: 18,069

    Congratulations :)

  • pic18f2550pic18f2550 Posts: 400
    edited 2021-11-30 15:19

    Hello Cluso99,
    There are a few things that need to be added to your emulator.

    1. the refresh register should increase by 1 with each run.
      There are computers that use the refresh register in the software, e.g. ZX81.
      " add R, #1 "
      " and R, #$7F " 7 Bit refresh

    2. the Halt command should not stop the execution.
      In Halt mode, the refresh signals are still delivered.
      " sub PC, #1 "

    3. simulate the NMI and INT input.
      These are needed for the emulation of hardware.

    Otherwise, the Emmulator is very good.
    The average cycle time is between 34 and 132 ckls.
    This could easily emulate a 10 MHz CPU.

  • Cluso99Cluso99 Posts: 18,069

    @pic18f2550
    1. I didn't know any code was using the R register
    2. The halt mode is used to stop the emulation and return to the OS in my P1 zicog version. The same will be true when my P2 OS works properly.
    3. Currently I have not intended to simulate NMI and INT.

    There is a lot I can do to speed this up but for now it is what it is.

    BTW I have my RetroBlade2 connected to a bare Z80 (Z84C0020) and working. It's not fast as the interface is currently in spin2. Last night I I was able to run the zexall adc verification so I am on my way to being able to run it on my Z80 emulation too. :)

  • Hello,
    I wanted to move the memory for the Z80 today.
    But this is not possible.

                  orgh      Z80_MEM
    {0000}        byte      $C3, $00, $F0, $00
                  orgh      Z80_MEM + $F000
                  file      "z1013_a2.bin"
                  orgh      Z80_MEM + $1_0000               '' fill to end of Z80 64KB
    
    PC   B C  D E  H L  A  F  R  R2 IF SP     alu  ea    OpCode(s)    Vector3   V-1 V-2 V-3  M1-STEP  CLK/CYCL
    ----------------------------------------------------------------------------------------------------------
    0000 0000 0000 0000 00 40 00 00 03 0000 = 130C 0000: C3 00 F0 00  000C2057: 057 0C2 000  00000001 00000041
    F000 0000 0000 0000 00 40 01 00 03 0000 = 1060 F000: 18 0D 21 4D  000000CC: 0CC 000 000  00000002 00000035
    F00F 0000 0000 0000 00 40 02 00 03 0000 = 10C4 F00F: 31 B0 00 3E  000BE057: 057 0BE 000  00000003 0000003D
    F012 0000 0000 0000 00 40 03 00 03 00B0 = 10F8 F012: 3E C3 32 20  000B4055: 055 0B4 000  00000004 0000003D
    F014 0000 0000 0000 C3 40 04 00 03 00B0 = 10C8 F014: 32 20 00 21  3206407F: 07F 064 0C8  00000005 00000053
    F017 0000 0000 0000 C3 40 05 00 03 00B0 = 1084 F017: 21 D5 F0 22  000A7057: 057 0A7 000  00000006 00000045
    F01A 0000 0000 F0D5 C3 40 06 00 03 00B0 = 1088 F01A: 22 21 00 3E  3286B07F: 07F 06B 0CA  00000007 0000005B
    F01D 0000 0000 F0D5 C3 40 07 00 03 00B0 = 10F8 F01D: 3E CF D3 03  000B4055: 055 0B4 000  00000008 00000040
    F01F 0000 0000 F0D5 CF 40 08 00 03 00B0 = 134C F01F: D3 03 3E 6F  2F06407D: 07D 064 0BC  00000009 00000049
    F021 0000 0000 F0D5 CF 40 09 00 03 00B0 = 10F8 F021: 3E 6F D3 03  000B4055: 055 0B4 000  0000000A 00000039
    
    

    So make from Z80_MEM = $1_0000 --> $1_1000.

    PC   B C  D E  H L  A  F  R  R2 IF SP     alu  ea    OpCode(s)    Vector3   V-1 V-2 V-3  M1-STEP  CLK/CYCL
    ----------------------------------------------------------------------------------------------------------
    0000 0000 0000 0000 00 40 00 00 03 0000 = 130C 1000: C3 00 F0 00  000C2057: 057 0C2 000  00000001 00000041
    F000 0000 0000 0000 00 40 01 00 03 0000 = 1000 F000: 00 00 00 00  00000004: 004 000 000  00000002 0000000E <---- OpCode read error
    F001 0000 0000 0000 00 40 02 00 03 0000 = 1000 F001: 00 00 00 00  00000004: 004 000 000  00000003 0000000E
    F002 0000 0000 0000 00 40 03 00 03 0000 = 1000 F002: 00 00 00 00  00000004: 004 000 000  00000004 0000000E
    F003 0000 0000 0000 00 40 04 00 03 0000 = 1000 F003: 00 00 00 00  00000004: 004 000 000  00000005 0000000E
    F004 0000 0000 0000 00 40 05 00 03 0000 = 1000 F004: 00 00 00 00  00000004: 004 000 000  00000006 0000000E
    F005 0000 0000 0000 00 40 06 00 03 0000 = 1000 F005: 00 00 00 00  00000004: 004 000 000  00000007 0000000E
    F006 0000 0000 0000 00 40 07 00 03 0000 = 1000 F006: 00 00 00 00  00000004: 004 000 000  00000008 0000000E
    F007 0000 0000 0000 00 40 08 00 03 0000 = 1000 F007: 00 00 00 00  00000004: 004 000 000  00000009 0000000E
    F008 0000 0000 0000 00 40 09 00 03 0000 = 1000 F008: 00 00 00 00  00000004: 004 000 000  0000000A 0000000E
    F009 0000 0000 0000 00 40 0A 00 03 0000 = 1000 F009: 00 00 00 00  00000004: 004 000 000  0000000B 0000000E
    

    Where could the problem lie?
    My guess is the wdread commands.

  • Cluso99Cluso99 Posts: 18,069

    @pic18f2550 said:
    Hello,
    I wanted to move the memory for the Z80 today.
    But this is not possible.

                  orgh      Z80_MEM
    {0000}        byte      $C3, $00, $F0, $00
                  orgh      Z80_MEM + $F000
                  file      "z1013_a2.bin"
                  orgh      Z80_MEM + $1_0000               '' fill to end of Z80 64KB
    
    PC   B C  D E  H L  A  F  R  R2 IF SP     alu  ea    OpCode(s)    Vector3   V-1 V-2 V-3  M1-STEP  CLK/CYCL
    ----------------------------------------------------------------------------------------------------------
    0000 0000 0000 0000 00 40 00 00 03 0000 = 130C 0000: C3 00 F0 00  000C2057: 057 0C2 000  00000001 00000041
    F000 0000 0000 0000 00 40 01 00 03 0000 = 1060 F000: 18 0D 21 4D  000000CC: 0CC 000 000  00000002 00000035
    F00F 0000 0000 0000 00 40 02 00 03 0000 = 10C4 F00F: 31 B0 00 3E  000BE057: 057 0BE 000  00000003 0000003D
    F012 0000 0000 0000 00 40 03 00 03 00B0 = 10F8 F012: 3E C3 32 20  000B4055: 055 0B4 000  00000004 0000003D
    F014 0000 0000 0000 C3 40 04 00 03 00B0 = 10C8 F014: 32 20 00 21  3206407F: 07F 064 0C8  00000005 00000053
    F017 0000 0000 0000 C3 40 05 00 03 00B0 = 1084 F017: 21 D5 F0 22  000A7057: 057 0A7 000  00000006 00000045
    F01A 0000 0000 F0D5 C3 40 06 00 03 00B0 = 1088 F01A: 22 21 00 3E  3286B07F: 07F 06B 0CA  00000007 0000005B
    F01D 0000 0000 F0D5 C3 40 07 00 03 00B0 = 10F8 F01D: 3E CF D3 03  000B4055: 055 0B4 000  00000008 00000040
    F01F 0000 0000 F0D5 CF 40 08 00 03 00B0 = 134C F01F: D3 03 3E 6F  2F06407D: 07D 064 0BC  00000009 00000049
    F021 0000 0000 F0D5 CF 40 09 00 03 00B0 = 10F8 F021: 3E 6F D3 03  000B4055: 055 0B4 000  0000000A 00000039
    
    

    So make from Z80_MEM = $1_0000 --> $1_1000.

    PC   B C  D E  H L  A  F  R  R2 IF SP     alu  ea    OpCode(s)    Vector3   V-1 V-2 V-3  M1-STEP  CLK/CYCL
    ----------------------------------------------------------------------------------------------------------
    0000 0000 0000 0000 00 40 00 00 03 0000 = 130C 1000: C3 00 F0 00  000C2057: 057 0C2 000  00000001 00000041
    F000 0000 0000 0000 00 40 01 00 03 0000 = 1000 F000: 00 00 00 00  00000004: 004 000 000  00000002 0000000E <---- OpCode read error
    F001 0000 0000 0000 00 40 02 00 03 0000 = 1000 F001: 00 00 00 00  00000004: 004 000 000  00000003 0000000E
    F002 0000 0000 0000 00 40 03 00 03 0000 = 1000 F002: 00 00 00 00  00000004: 004 000 000  00000004 0000000E
    F003 0000 0000 0000 00 40 04 00 03 0000 = 1000 F003: 00 00 00 00  00000004: 004 000 000  00000005 0000000E
    F004 0000 0000 0000 00 40 05 00 03 0000 = 1000 F004: 00 00 00 00  00000004: 004 000 000  00000006 0000000E
    F005 0000 0000 0000 00 40 06 00 03 0000 = 1000 F005: 00 00 00 00  00000004: 004 000 000  00000007 0000000E
    F006 0000 0000 0000 00 40 07 00 03 0000 = 1000 F006: 00 00 00 00  00000004: 004 000 000  00000008 0000000E
    F007 0000 0000 0000 00 40 08 00 03 0000 = 1000 F007: 00 00 00 00  00000004: 004 000 000  00000009 0000000E
    F008 0000 0000 0000 00 40 09 00 03 0000 = 1000 F008: 00 00 00 00  00000004: 004 000 000  0000000A 0000000E
    F009 0000 0000 0000 00 40 0A 00 03 0000 = 1000 F009: 00 00 00 00  00000004: 004 000 000  0000000B 0000000E
    

    Where could the problem lie?
    My guess is the wdread commands.

    I targeted Z80_MEM to be on a 64KB boundary. I suggest if you want to move it you will need to go to $2_0000.

  • Is there a reason for this?
    I wanted to move the range into a variable because spin ignores the instructions orgh.

  • That should be all areas.
    Only functions that write to or read from the Z80_MEM are affected.

    '***************************************************************************************************************
    rd_opcode               mov     ea, PC                          ' alu <-- mem[PC++]  (read byte)
                            add     PC, #1
                            and     PC, low_word
    ' ----------------------------------------------------------------------------------------------
    '---------> OR ---> ADD ######################################################################################################################################
    'rd_byte                 or      ea, ram_base                    '                    (add Z80_MEM hub base addr)
    rd_byte                 add     ea, ram_base                    '                    (add Z80_MEM hub base addr)
                  _RET_     rdbyte  alu, ea                         ' alu <-- mem[ea]    (read byte)
    '***************************************************************************************************************
    rd_opword               mov     ea, PC                          ' alu <-- mem[PC++]  (read word)
                            add     PC, #2
                            and     PC, low_word                    ' mask any overflow
                            jmp     #rd_word
    '***************************************************************************************************************
    pop_alu                 mov     ea, SP                          ' alu <-- mem[SP++]  (pop word)
                            add     SP, #2
                            and     SP, low_word                    ' mask any overflow
    ' ----------------------------------------------------------------------------------------------
    '---------> OR ---> ADD ######################################################################################################################################
    'rd_word                 or       ea, ram_base                    '                    (add Z80_MEM hub base addr)
    rd_word                 add      ea, ram_base                    '                    (add Z80_MEM hub base addr)
                  _RET_     rdword  alu, ea                         ' alu <-- mem[ea]    (read word)
    '***************************************************************************************************************
    '---------> OR ---> ADD ######################################################################################################################################
    'wr_byte                 or      ea, ram_base                    '                    (add Z80-mem hub base addr)
    wr_byte                 add     ea, ram_base                    '                    (add Z80-mem hub base addr)
                  _RET_     wrbyte  alu, ea                         ' mem[ea] <-- alu    (write byte)
    '***************************************************************************************************************
    '***************************************************************************************************************
    push_alu                sub     SP, #2                          ' mem[SP++] <-- alu  (push word onto stack)
                            and     SP, low_word                    ' mask any overflow
                            mov     ea, SP
    ' ----------------------------------------------------------------------------------------------
    '---------> OR ---> ADD ######################################################################################################################################
    'wr_word                 or      ea, ram_base                    '                    (add Z80_MEM hub base addr)
    wr_word                 add     ea, ram_base                    '                    (add Z80_MEM hub base addr)
                  _RET_     wrword  alu, ea                         ' mem[ea] <-- alu    (write word)
    ''#####################################################################################################################################
    
    
  • I don't know what that means but it definitely doesn't look OK.
    File p2asm. created by Flexprop.

    '-' '***************************************************************************************************************
    '-' opcodes_ed                                           {ed xx}
    '-' {ed 40}    word    ed_in_b_bc                           ' IN   B,(C)
        byte    $99, $03
    '-' {ed 41}    word    ed_out_bc_b                          ' OUT  (C),B
        byte    $b1, $03
    '-' {ed 42}    word    ed_sbc_hl_bc                         ' SBC  HL,BC
        byte    $d1, $03
    '-' {ed 43}    word    zed_ld_abs16_bc                      ' LD   (abs16),BC
        long    @@@_dat_ + 324  <---------------------------------------- ???? ----------------------------
        byte    $08
        byte    $02
        byte    $20
        byte    $02
        byte    $40
        byte    $02
        byte    $9c
        byte    $03
        byte    $b5
        byte    $03
        byte    $5c
        byte    $00
        byte    $ac
        byte    $01
        byte    $ec
        byte    $01
        byte    $14
        byte    $02
    
  • Cluso99Cluso99 Posts: 18,069

    I just realised that some of the issues you are finding are because you are trying to add spin2.

    IMHO spin2 has a major flaw that you cannot compile pasm code/data to go into a specific location in hub which is why your orgh xxxx does not work.

    I use a specific hub location for the Z80_MEM to gain speed. Every instruction will need to perform these extra cycles to allow the Z80_MEM to be located anywhere in hub. So while I've not tried to extract every bit of speed currently, I did make some fundamental decisions.

  • pic18f2550pic18f2550 Posts: 400
    edited 2021-12-02 10:55

    Yes I want to use Spin to create a simple management layer to make the system easier to handle.

    I replaced the orgh xxxx with orgh.
    For Z80_MEM I now use a 64k spoke image.

    The current speed is more than sufficient to simulate a 10Mhz CPU.

    The current memory consumption without SPIN and Z80_MEM is 10.312 bytes.

    The problems are manageable. :)
    To enable the integration of SPIN the jump distributor has to be rebuilt 11 bit as well as 16 bit are not sufficient to cover the whole address range from $0 to $7FFFF.

            orgh
            alignl
    {00}    jmp   #fetch            ' NOP
            nop
            nop
    
    {01}    call  #imm16_to_alu     ' LD   BC,nnnn
            jmp   #alu_to_bc
            nop
    
    {02}    call  #bc_to_ea         ' LD   (BC),A
            call  #a_to_alu
            jmp   #wr_byte_ea
    ...
    
  • pic18f2550pic18f2550 Posts: 400
    edited 2021-12-02 12:06

    Small debug bug when reloading the Vector3.

    execute
              cmp     debug_flag, #0          WZ
      if_ne   call    #_debug_regs
                  add     instr_count, #1
                  call    #rd_opcode                      ' fetch opcode and dispatch through table_00
                  mov     opcode, alu
                  shl     alu, #2
                  add     alu, table_00
                  rdlong  vector3, alu
              cmp     debug_flag, #0          WZ   <---- move
      if_ne   call    #_debug_opc                  <---- move
    
    fetch_11      getct   clkza
                  mov     vector, vector3                 '\ extract first vector (12-bits)
                  and     vector, maskFFF                 '/   and mask to 12-bits
                  call    vector                          ' dispatch
    ' ----------------------------------------------------------------------------------------------
                  mov     vector, vector3                 '
                  shr     vector, #12                     '\ shift to 2nd vector (10-bits)
                  and     vector, mask3FF                 '/   and mask to 10-bits
                  call    vector                          ' dispatch
    ' ----------------------------------------------------------------------------------------------
                  shr     vector3, #22                    ' shift to 3rd vector (10-bits)
                  call    vector3                         ' dispatch
    ' ----------------------------------------------------------------------------------------------
                  mov     lmm_p,      ##@str_oops
                  call    #\_hubTxStr
    .here         call    #_HubMonitor                    ' should never return here!!!
                  jmp     #.here
    
    fetch_1       rdlong  vector3, alu   <---- new
                  jmp     #fetch_11      <---- new
    
  • @pic18f2550 said:

    '***************************************************************************************************************
    '               OPCODES CB xx
    '***************************************************************************************************************
    cb_rlc_b      {cb 00}   mov     alu, B
                            call    #alu_rlc
                            jmp     #alu_to_B
    ' ----------------------------------------------------------------------------------------------
    alu_to_b                mov     B, alu                          ' B   <-- alu
                            jmp     #fetch
    
    '***************************************************************************************************************
    alu_rlc                 shl     alu, #1                         '                               (rotate left)
                            test    alu, #$100      WC              ' get bit #7 into zero flag
                            muxc    alu, #$01                       ' get carry in bit #0
                            jmp     #szp_flags_ff
    ' ----------------------------------------------------------------------------------------------
    ' Compute sign, zero and parity flags after logic/shift/rotate instruction
    szp_flags_ff            mov     F, #0                           ' clear all flags
                            muxc    F, #CF                          ' set C flag on carry
                            and     alu, #$ff       WCZ          ' get zero and parity flags
    szp_flags               muxz    F, #ZF                          ' if zero set Z flag
                            muxnc   F, #PF                          ' if even parity set the P flag
                            test    alu, #$80       WC              ' get sign in prop's carry flag
                  _RET_     muxc    F, #SF                          ' set S flag
    

    ?? RET ist doch nicht mit CALL aufgerufen??

    02e28 033 DA B3 C3 0A |               _RET_     rdbyte  alu, ea                         ' alu <-- mem[ea]    (read byte)
    02e2c 034 DA B3 C3 FA |                         rdbyte  alu, ea                         ' alu <-- mem[ea]    (read byte)
    02e30 035 2D 00 64 FD |                         ret                                     ' alu <-- mem[ea]    (read byte)
    

    Apparently you can save a long in the COG Ran with RET and speed up the processing.

  • pic18f2550pic18f2550 Posts: 400
    edited 2021-12-12 21:23

    From The:

    {dd/fd c0}    long    test_flag_0     | ret_cond        << 12  | ZF             << 22  ' RET  NZ
    

    Will That:

    0275c     04 00 00 10 | {dd/fd c0}      long  4 | ZF << 22
    02760     92 00 A0 FD |                 call  #test_flag_0    ' RET  NZ
    02764     C2 00 80 FD |                 jmp   #ret_cond
    02768     00 00 00 00 |                 nop
    
  • Cluso99Cluso99 Posts: 18,069

    @pic18f2550 said:
    From The:

    {dd/fd c0}    long    test_flag_0     | ret_cond        << 12  | ZF             << 22  ' RET  NZ
    

    Will That:

    0275c     04 00 00 10 | {dd/fd c0}      long  4 | ZF << 22
    02760     92 00 A0 FD |                 call  #test_flag_0    ' RET  NZ
    02764     C2 00 80 FD |                 jmp   #ret_cond
    02768     00 00 00 00 |                 nop
    

    Yes except there will not be a NOP executed.

    There will be some parts where you can save bytes and speed up the code. Be careful when using RET as in some places you may need to restore the P2 flags.

    I had planned to use the exec/skip mechanism once all tests pass and that will negate a lot of the speed up sections anyway.
    I am in the middle of updating the zexall z80 instruction tester so I can run this successfully.

  • Yes, but no NOP is executed.

    The NOPS are just placeholders code I could have taken long 0 only binn I a bit lazy to write. :)
    A block always consists of 4 longs.
    The 1st one contains the current clock count of the Z80 for the command and the flag mask for conditional commands.
    The rest are jumps to the routines.

    There are some places where you can save bytes and speed up the code. Be careful when using RET, as you will need to restore P2 flags in some places.

    can you show me an example in the code so i understand the issue. I binn until now assumed that Z and C are unaffected by ret.

    I had planned to use the exec/skip mechanism once all tests passed, and that will negate a lot of the accelerated sections anyway.

    The priority should be a flexible use of the code.
    For me it would already be enough if a 4Mhz Z80 would be simulated at 256Mhz.

    I am in the process of updating the zexall z80 command tester so that I can run it successfully.

    :)

Sign In or Register to comment.