'***************************************************************************************************************
' 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
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.
'' RR20190819 029 fix rdxxxx/wrxxxx with Z80_MEM offset''add ea,ram_base ->or ea,ram_base
''insertOR xx,ram_base before rd/wrbyte/word in various places
''030-031 debug with zexdoc
''032 tweek
''============================[ CON
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 ( ? )
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.
Hello Cluso99,
There are a few things that need to be added to your emulator.
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
the Halt command should not stop the execution.
In Halt mode, the refresh signals are still delivered.
" sub PC, #1 "
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.
@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.
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.
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.
'***************************************************************************************************************
' 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 0064 FD | ret' alu <-- mem[ea] (read byte)
Apparently you can save a long in the COG Ran with RET and speed up the processing.
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.
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.
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??
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.
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.
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
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 ( ? )
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.
Congratulations
Hello Cluso99,
There are a few things that need to be added to your emulator.
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
the Halt command should not stop the execution.
In Halt mode, the refresh signals are still delivered.
" sub PC, #1 "
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.
@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.
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
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.
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 ...
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
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.
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.
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.
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.
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.