2012-04-07 12:33:47 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2009 (C) Raster Software Vigo (Sergio Costas)
|
|
|
|
* This file is part of Z80Free, with some bits extracted
|
|
|
|
* and fixed from libZ80 (from Gabriel Gambetta)
|
|
|
|
*
|
|
|
|
* Z80Free is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Z80Free is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Z80free.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#ifdef GEKKO
|
|
|
|
#include <gccore.h>
|
|
|
|
#include <fat.h>
|
|
|
|
|
|
|
|
FILE *fdebug;
|
|
|
|
#define printf(...) fprintf(fdebug,__VA_ARGS__)
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Z80FREE emulator,emulator2;
|
|
|
|
unsigned char memory[65536];
|
|
|
|
FILE *infile;
|
|
|
|
char test_name[20];
|
|
|
|
byte ports[256];
|
|
|
|
word portdirs[256];
|
|
|
|
int portpos=0,elements=0;
|
|
|
|
|
Fixed Flag emulation for some opcodes:
RRD, RLD, DAA, CCF (bit 3,5)
BIT n, (IX/IY + d) (bit 3,5)
IN BC, r (bit 3,5)
INI, OUTI, IND, OUTD (all flag bits)
CPIR, CPDR (bit 3,5)
INIR, OTIR, INDR, OTDR (all flag bits)
2012-06-09 08:37:22 +02:00
|
|
|
//#define NO35
|
2012-04-07 12:33:47 +02:00
|
|
|
|
|
|
|
int compare_processors() {
|
|
|
|
|
|
|
|
if (emulator.Rm.br.A!=emulator2.Rm.br.A) {
|
|
|
|
printf("A should be %X but is %X\n",emulator2.Rm.br.A,emulator.Rm.br.A);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef NO35
|
|
|
|
if ((emulator.Rm.br.F|0x28)!=(emulator2.Rm.br.F|0x28)) {
|
|
|
|
printf("F should be %X but is %X\n",emulator2.Rm.br.F,emulator.Rm.br.F);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (emulator.Rm.br.F!=emulator2.Rm.br.F) {
|
|
|
|
printf("F should be %X but is %X\n",emulator2.Rm.br.F,emulator.Rm.br.F);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (emulator.Rm.wr.BC!=emulator2.Rm.wr.BC) {
|
|
|
|
printf("BC should be %X but is %X\n",emulator2.Rm.wr.BC,emulator.Rm.wr.BC);
|
|
|
|
}
|
|
|
|
if (emulator.Rm.wr.DE!=emulator2.Rm.wr.DE) {
|
|
|
|
printf("DE should be %X but is %X\n",emulator2.Rm.wr.DE,emulator.Rm.wr.DE);
|
|
|
|
}
|
|
|
|
if (emulator.Rm.wr.HL!=emulator2.Rm.wr.HL) {
|
|
|
|
printf("HL should be %X but is %X\n",emulator2.Rm.wr.HL,emulator.Rm.wr.HL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (emulator.Ra.br.A!=emulator2.Ra.br.A) {
|
|
|
|
printf("A' should be %X but is %X\n",emulator2.Ra.br.A,emulator.Ra.br.A);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef NO35
|
|
|
|
if ((emulator.Ra.br.F|0x28)!=(emulator2.Ra.br.F|0x28)) {
|
|
|
|
printf("F' should be %X but is %X\n",emulator2.Ra.br.F,emulator.Ra.br.F);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (emulator.Ra.br.F!=emulator2.Ra.br.F) {
|
|
|
|
printf("F' should be %X but is %X\n",emulator2.Ra.br.F,emulator.Ra.br.F);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (emulator.Ra.wr.BC!=emulator2.Ra.wr.BC) {
|
|
|
|
printf("BC' should be %X but is %X\n",emulator2.Ra.wr.BC,emulator.Ra.wr.BC);
|
|
|
|
}
|
|
|
|
if (emulator.Ra.wr.DE!=emulator2.Ra.wr.DE) {
|
|
|
|
printf("DE' should be %X but is %X\n",emulator2.Ra.wr.DE,emulator.Ra.wr.DE);
|
|
|
|
}
|
|
|
|
if (emulator.Ra.wr.HL!=emulator2.Ra.wr.HL) {
|
|
|
|
printf("HL' should be %X but is %X\n",emulator2.Ra.wr.HL,emulator.Ra.wr.HL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (emulator.Rm.wr.IX!=emulator2.Rm.wr.IX) {
|
|
|
|
printf("IX should be %X but is %X\n",emulator2.Rm.wr.IX,emulator.Rm.wr.IX);
|
|
|
|
}
|
|
|
|
if (emulator.Rm.wr.IY!=emulator2.Rm.wr.IY) {
|
|
|
|
printf("IY should be %X but is %X\n",emulator2.Rm.wr.IY,emulator.Rm.wr.IY);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (emulator.PC!=emulator2.PC) {
|
|
|
|
printf("PC should be %X but is %X\n",emulator2.PC,emulator.PC);
|
|
|
|
}
|
|
|
|
if (emulator.Rm.wr.SP!=emulator2.Rm.wr.SP) {
|
|
|
|
printf("SP should be %X but is %X\n",emulator2.Rm.wr.SP,emulator.Rm.wr.SP);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (emulator.HALT!=emulator2.HALT) {
|
|
|
|
printf("HALT should be %X but is %X\n",emulator2.HALT,emulator.HALT);
|
|
|
|
}
|
|
|
|
if (emulator.I!=emulator2.I) {
|
|
|
|
printf("I should be %X but is %X\n",emulator2.I,emulator.I);
|
|
|
|
}
|
|
|
|
if ((emulator.R&0x7F)!=(emulator2.R&0x7F)) {
|
|
|
|
printf("R should be %X but is %X\n",(emulator2.R&0x7F),(emulator.R&0x7F));
|
|
|
|
}
|
|
|
|
if (emulator.IM!=emulator2.IM) {
|
|
|
|
printf("IM should be %X but is %X\n",emulator2.IM,emulator.IM);
|
|
|
|
}
|
|
|
|
if (emulator.IFF1!=emulator2.IFF1) {
|
|
|
|
printf("IFF1 should be %X but is %X\n",emulator2.IFF1,emulator.IFF1);
|
|
|
|
}
|
|
|
|
if (emulator.IFF2!=emulator2.IFF2) {
|
|
|
|
printf("IFF2 should be %X but is %X\n",emulator2.IFF2,emulator.IFF2);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int read_elements(Z80FREE *emulador) {
|
|
|
|
|
|
|
|
int tstates,retval;
|
|
|
|
unsigned short int v1,v2,v3,v4,v5,v6,v7,v8,v9,v10;
|
|
|
|
|
|
|
|
|
|
|
|
Z80free_reset(emulador);
|
|
|
|
|
|
|
|
retval=fscanf(infile,"%hx %hx %hx %hx",(unsigned short int *)&emulador->Rm.wr.AF,(unsigned short int *)&emulador->Rm.wr.BC,(unsigned short int *)&emulador->Rm.wr.DE,(unsigned short int *)&emulador->Rm.wr.HL);
|
|
|
|
retval=fscanf(infile,"%hx %hx %hx %hx",&v7,&v8,&v9,&v10);
|
|
|
|
emulador->Ra.wr.AF=v7;
|
|
|
|
emulador->Ra.wr.BC=v8;
|
|
|
|
emulador->Ra.wr.DE=v9;
|
|
|
|
emulador->Ra.wr.HL=v10;
|
|
|
|
retval=fscanf(infile,"%hx %hx %hx %hx",(unsigned short int *)&emulador->Rm.wr.IX,(unsigned short int *)&emulador->Rm.wr.IY,(unsigned short int *)&emulador->Rm.wr.SP,(unsigned short int *)&emulador->PC);
|
|
|
|
retval=fscanf(infile,"%hx %hx %hx %hx %hx %hx %d",&v1,&v2,&v3,&v4,&v5,&v6,&tstates);
|
|
|
|
|
|
|
|
emulador->I=v1;
|
|
|
|
emulador->R=v2;
|
|
|
|
emulador->R2=v2;
|
|
|
|
emulador->IFF1=v3;
|
|
|
|
emulador->IFF2=v4;
|
|
|
|
emulador->IM=v5;
|
|
|
|
emulador->HALT=v6;
|
|
|
|
|
|
|
|
return (tstates);
|
|
|
|
}
|
|
|
|
|
|
|
|
int read_memory(char mode) {
|
|
|
|
// mode=0 : store value in memory
|
|
|
|
// mode=1 : compare value with memory
|
|
|
|
|
|
|
|
int position,retval,value;
|
|
|
|
|
|
|
|
|
|
|
|
retval=fscanf(infile,"%x",&position);
|
|
|
|
if (position==-1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
retval=fscanf(infile,"%x",&value);
|
|
|
|
|
|
|
|
if (value!=-1) {
|
|
|
|
if (mode) {
|
|
|
|
if (memory[position]!=value) {
|
|
|
|
printf("Error in memory, address %X. Expected value: %X, current value: %X\n",position,value,memory[position]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
memory[position]= (byte) value;
|
|
|
|
}
|
|
|
|
position++;
|
|
|
|
}
|
|
|
|
} while(value!=-1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int read_inports() {
|
|
|
|
|
|
|
|
int retval, value, addr;
|
|
|
|
|
|
|
|
|
|
|
|
portpos=0;
|
|
|
|
elements=0;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
retval=fscanf(infile,"%x",&addr);
|
|
|
|
if (addr==-1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
retval=fscanf(infile,"%x",&value);
|
|
|
|
portdirs[elements]=(word) addr;
|
|
|
|
ports[elements]=(byte) value;
|
|
|
|
elements++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int read_test() {
|
|
|
|
|
|
|
|
int retval,tstates,tst2,totaltst;
|
|
|
|
|
|
|
|
retval=fscanf(infile,"%s",test_name);
|
|
|
|
if (retval<=0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
printf("Test %s\n",test_name);
|
|
|
|
tstates=read_elements(&emulator);
|
|
|
|
while(0==read_memory(0)) {
|
|
|
|
}
|
|
|
|
read_inports();
|
|
|
|
totaltst=0;
|
|
|
|
while(totaltst<tstates) {
|
|
|
|
totaltst+=Z80free_step(&emulator);
|
|
|
|
}
|
|
|
|
tst2=read_elements(&emulator2);
|
|
|
|
compare_processors();
|
|
|
|
if (totaltst!=tst2) {
|
|
|
|
printf("Test needed %d tstates, but should needed %d\n",totaltst,tst2);
|
|
|
|
}
|
|
|
|
while(0==read_memory(1)) {
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
byte Z80free_Rd (register word Addr) {
|
|
|
|
|
|
|
|
return ((byte)memory[Addr]);
|
|
|
|
|
|
|
|
}
|
|
|
|
void Z80free_Wr (register word Addr, register byte Value) {
|
|
|
|
|
|
|
|
memory[Addr]=(unsigned char) Value;
|
|
|
|
|
|
|
|
}
|
|
|
|
byte Z80free_In (register word Port) {
|
|
|
|
|
|
|
|
byte value;
|
|
|
|
|
|
|
|
if (portpos>=elements) {
|
|
|
|
printf("IN beyond values\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Port!=portdirs[portpos])
|
|
|
|
printf("IN to port %X (should be %X)\n",Port,portdirs[portpos]);
|
|
|
|
value=ports[portpos];
|
|
|
|
portpos++;
|
|
|
|
return (value);
|
|
|
|
|
|
|
|
}
|
|
|
|
void Z80free_Out (register word Port, register byte Value) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
|
|
|
#ifdef GEKKO
|
|
|
|
|
|
|
|
//initialize libfat library
|
|
|
|
fatInitDefault();
|
|
|
|
|
|
|
|
fdebug = fopen("/logfile_big.txt","w");
|
|
|
|
|
|
|
|
infile=fopen("/apps/z80_test/tests.z80free","r");
|
|
|
|
|
|
|
|
#else
|
|
|
|
infile=fopen("tests.z80free","r");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
while(0==read_test()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|