He realizado una conversión rápida del core del Z80 de José Luis Sánchez a C (no POSIX) en normativa STD(C89).
El proyecto original en C++ es de Jose Luis Sánchez. Yo tan sólo he realizado una conversión a C, para que
sirva de plantilla en otras plataformas y compiladores de recursos más reducidos.
Esta versión modificada sólo permite usar un único core de Z80, en lugar de múltiples, característica que si tenía el proyecto original:
- Windows (mingw32)
- ESP32 (Arduino IDE)
- ANDROID (C4droid y CppDroid)
- RP2040, W801, W806
- z80.h
- z80.c
- sim.c (para simulación)
- zxallbin.h (el binario de test zxall)
- gbGlobal (variables globales de Z80 y de simulación)
unsigned char fetchOpcode(unsigned short int address) { } unsigned char peek8(unsigned short int address) { } void poke8(unsigned short int address, unsigned char value) { } unsigned short int peek16(unsigned short int address) { } void poke16(unsigned short int address, RegisterPair word) { } void addressOnBus(unsigned short int address, int wstates) { } unsigned char inPort(unsigned short int port) { } void outPort(unsigned short int port, unsigned char value) { } void interruptHandlingTime(int wstates) { } unsigned char isActiveINT(void) { }
Debemos tener en cuenta la sección de Inicio simulador del fichero gbGlobal.h, porque ahi es donde definimos los recursos del Z80 a emular, es decir, RAM y puertos.
- cfg_use_big_endian: Soporte de Big endian
- WITH_BREAKPOINT_SUPPORT: Permite depuración
- cfg_use_time_show: Muestra los tiempos
- cfg_use_time_per_line: Muestra el tiempo en cada linea de ejecución.
- cfg_use_tstates_64bits: Declara la variable de temporización de 64 bits.
- cfg_use_direct_RegA: Modo de acceso rápido a un registro del Z80.
- --
- cfg_use_direct_PendingEI: Modo de acceso rápido a PendingEI.
- cfg_use_finish_fast: Variable de ejecución declarada en modo rápido (ESP32).
- cfg_use_z80RAM_fast: El array de RAM en modo rápido (ESP32)
- cfg_use_z80Ports_fast: El array de puertos en modo rápido (ESP32)
- cfg_use_time_fast: El acceso al timer en modo rápido (ESP32)
La memoria de puertos se ha dejado en 8192 bytes, que nos vale para los tests.
La salida se realiza por el puerto serie, por donde podemos monitorizar.
15:50:13.123 -> BEGIN Test 15:50:13.123 -> (00:00:00) Z80all instruction exerciser 15:50:13.123 -> hl,.... OK 15:54:23.087 -> add hl,.......... OK 15:56:27.501 -> add ix,.......... OK 15:58:31.963 -> add iy,.......... OK 16:00:36.416 -> aluop a,nn.................... OK 16:01:39.342 -> aluop a,.. OK 16:38:21.948 -> aluop a,..... OK 16:57:04.702 -> aluop a,(+1)........... OK 17:06:31.325 -> bit n,(+1)............. OK 17:06:35.739 -> bit n,.... OK 17:08:57.614 -> cpd........................ OK 17:09:25.270 -> cpi........................ OK 17:09:52.965 -> ............. OK 17:11:54.128 -> a................... OK 17:12:00.667 -> b................... OK 17:12:07.207 -> bc.................. OK 17:12:10.582 -> c................... OK 17:12:17.121 -> d................... OK 17:12:23.682 -> de.................. OK 17:12:27.041 -> e................... OK 17:12:33.574 -> h................... OK 17:12:40.136 -> hl.................. OK 17:12:43.496 -> ix.................. OK 17:12:46.894 -> iy.................. OK 17:12:50.253 -> l................... OK 17:12:56.777 -> (hl)................ OK 17:13:03.339 -> sp.................. OK 17:13:06.699 -> (+1)......... OK 17:13:20.410 -> ixh................. OK 17:13:26.972 -> ixl................. OK 17:13:33.496 -> iyh................. OK 17:13:40.058 -> iyl................. OK 17:13:46.621 -> ld ,(nnnn)............. OK 17:13:46.660 -> ld hl,(nnnn).................. OK 17:13:46.699 -> ld sp,(nnnn).................. OK 17:13:46.738 -> ld ,(nnnn)............. OK 17:13:46.816 -> ld (nnnn),............. OK 17:13:46.933 -> ld (nnnn),hl.................. OK 17:13:46.972 -> ld (nnnn),sp.................. OK 17:13:47.011 -> ld (nnnn),............. OK 17:13:47.167 -> ld ,nnnn......... OK 17:13:47.285 -> ld ,nnnn............... OK 17:13:47.363 -> ld a,<(bc),(de)>.............. OK 17:13:47.441 -> ld ,nn.... OK 17:13:47.558 -> ld (+1),nn............. OK 17:13:47.636 -> ld ,(+1)...... OK 17:13:48.808 -> ld ,(+1).......... OK 17:13:49.394 -> ld a,(+1).............. OK 17:13:49.667 -> ld ,nn....... OK 17:13:49.707 -> ld ,........ OK 17:13:59.707 -> ld ,........ OK 17:14:20.292 -> ld a,(nnnn) / ld (nnnn),a..... OK 17:14:20.371 -> ldd (1).................... OK 17:14:20.488 -> ldd (2).................... OK 17:14:20.566 -> ldi (1).................... OK 17:14:20.683 -> ldi (2).................... OK 17:14:20.761 -> neg........................... OK 17:14:49.316 -> ..................... OK 17:15:04.824 -> ........... OK 17:15:17.988 -> shf/rot (+1)........... OK 17:15:18.886 -> shf/rot .. OK 17:15:39.121 -> n,..... OK 17:15:59.277 -> n,(+1)....... OK 17:16:00.214 -> ld (+1),...... OK 17:16:02.871 -> ld (+1),.......... OK 17:16:03.457 -> ld (+1),a.............. OK 17:16:03.574 -> ld (),a................ OK 17:16:03.808 -> Tests completeZ80 reset after 3785304271 t-states 17:16:03.808 -> (01:25:46) END TestSe puede ver la velocidad en un ESP32, de 1 hora y 25 minutos de ejecución con las opciones por defecto.
Si se seleccionan varias opciones de optimización, nos queda en (01:24:58).
16:35:48.682 -> fps(135) - ms cur(7) min(7) max(7) 16:35:49.698 -> fps(135) - ms cur(7) min(7) max(7) 16:35:50.713 -> fps(135) - ms cur(7) min(7) max(7) 16:35:51.690 -> fps(135) - ms cur(8) min(8) max(8) 16:35:52.706 -> fps(135) - ms cur(8) min(8) max(8) 16:35:53.721 -> fps(135) - ms cur(8) min(8) max(8) 16:35:54.698 -> fps(135) - ms cur(8) min(8) max(8) 16:35:55.713 -> fps(135) - ms cur(7) min(7) max(7)
fps(64) - ms cur(15) min(15) max(15) fps(64) - ms cur(15) min(15) max(15) fps(64) - ms cur(16) min(16) max(16) fps(64) - ms cur(16) min(16) max(16) fps(64) - ms cur(16) min(16) max(16) fps(64) - ms cur(16) min(16) max(16) fps(64) - ms cur(16) min(16) max(16) fps(64) - ms cur(16) min(16) max(16) fps(64) - ms cur(16) min(16) max(16) fps(64) - ms cur(16) min(16) max(16) fps(64) - ms cur(15) min(15) max(15) fps(64) - ms cur(15) min(15) max(15)
Dependiendo de la versión de framework, es posible que se tengan que sustituir los printf por print.
fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(17) min(17) max(17) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(17) min(17) max(17) fps(62) - ms cur(16) min(16) max(16)
fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(17) min(17) max(17) fps(62) - ms cur(17) min(17) max(17) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(17) min(17) max(17) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(17) min(17) max(17) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(16) min(16) max(16) fps(62) - ms cur(17) min(17) max(17)