diff options
Diffstat (limited to 'gemma.c')
-rw-r--r-- | gemma.c | 1018 |
1 files changed, 0 insertions, 1018 deletions
diff --git a/gemma.c b/gemma.c deleted file mode 100644 index ec05b5d..0000000 --- a/gemma.c +++ /dev/null @@ -1,1018 +0,0 @@ -/* - - GEMMA - Z80 testbed - - Copyright (C) 2006 Ian Cowburn (ianc@noddybox.demon.co.uk) - - This program 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 2 of the License, or - (at your option) any later version. - - This program 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - ------------------------------------------------------------------------- - -*/ -static const char id[]="$Id$"; - -#include <stdlib.h> -#include <stdio.h> -#include <signal.h> -#include <string.h> -#include <ctype.h> - -#include "gemma.h" -#include "expr.h" -#include "gtkutil.h" -#include "support.h" - -#define HI(w) (((w)&0xff00)>>8) -#define LO(w) ((w)&0xff) -#define MK(h,l) (((Z80Word)(h)<<8)|(l)) - -/* ---------------------------------------- GLOBALS -*/ -static Z80 *z80; -Z80Byte Z80_MEMORY[0x10000]; - -static sig_atomic_t stop=FALSE; - -static Z80Label *label=NULL; - -static GtkWidget *run_button; -static GtkWidget *step_button; -static GtkWidget *step_over_button; -static GtkWidget *stop_button; -static GtkWidget *run_until_button; - -static GtkWidget *breakpoint_text; - -static GtkWidget *top_window; -static GtkWidget *regview; -static GtkWidget *memview; -static GtkWidget *viewreg; -static GtkWidget *logview; -static GtkWidget *assemview; - -static GtkWidget *memview_combo; -static GtkWidget *memview_check; - -#define RUNNING(t) gtk_widget_set_sensitive(run_button,!t); \ - gtk_widget_set_sensitive(step_button,!t); \ - gtk_widget_set_sensitive(step_over_button,!t); \ - gtk_widget_set_sensitive(run_until_button,!t); \ - gtk_widget_set_sensitive(stop_button,t); - - -/* ---------------------------------------- PROTOS -*/ -static void Log(const char *format, ...); -static Z80Word Address(const char *p); -static void *Malloc(size_t len); -static void *Realloc(void *p, size_t len); - - -/* ---------------------------------------- PC BUFFER -*/ -#define PC_BUFFER 100 -static Z80Word pc_buffer[PC_BUFFER]={0}; -static int pc_head=0; - -static Z80Word Get_PC(int back) -{ - return pc_buffer[(pc_head+back+1)%PC_BUFFER]; -} - -static void Step(void) -{ - pc_buffer[pc_head]=z80->PC; - - if (pc_head) - pc_head--; - else - pc_head=PC_BUFFER-1; - - Z80SingleStep(z80); -} - -/* ---------------------------------------- DYNAMIC STRINGS -*/ - -typedef struct -{ - size_t len; - char *text; -} *DString; - - -#define BLOCKSIZE 512 - - -DString DSInit(void) -{ - DString ds; - - ds=Malloc(sizeof *ds); - - ds->len=0; - ds->text=Malloc(BLOCKSIZE); - ds->text[0]=0; - - return ds; -} - - -void DSFree(DString ds) -{ - if (ds) - { - free(ds->text); - free(ds); - } -} - - -DString DSAddChar(DString to, char c) -{ - if (((to->len+2)%BLOCKSIZE)==0) - { - to->text=Realloc(to->text,(((to->len+2)/BLOCKSIZE)+1)*BLOCKSIZE); - } - - to->text[to->len++]=c; - to->text[to->len]=0; - - return to; -} - - -DString DSAdd(DString to, const char *from) -{ - to->len+=strlen(from); - to->text=Realloc(to->text,(((to->len+1)/BLOCKSIZE)+1)*BLOCKSIZE); - - strcat(to->text,from); - - return to; -} - - -/* ---------------------------------------- PRIVATE FUNCTIONS -*/ -static void Log(const char *format, ...) -{ - static char buff[4096]; - va_list va; - - va_start(va,format); - vsprintf(buff,format,va); - va_end(va); - - AppendText(logview,buff); -} - - -static int StrEq(const char *a, const char *b) -{ - while(*a && *b && tolower(*a)==tolower(*b)) - { - a++; - b++; - } - - if (*a || *b) - return FALSE; - else - return TRUE; -} - - -static int Expand(void *client, const char *p, long *res) -{ - int ok=TRUE; - - if (StrEq(p,"AF")) - *res=z80->AF.w; - else if (StrEq(p,"BC")) - *res=z80->BC.w; - else if (StrEq(p,"DE")) - *res=z80->DE.w; - else if (StrEq(p,"HL")) - *res=z80->HL.w; - else if (StrEq(p,"IX")) - *res=z80->IX.w; - else if (StrEq(p,"IY")) - *res=z80->IY.w; - else if (StrEq(p,"SP")) - *res=z80->SP; - else if (StrEq(p,"PC")) - *res=z80->PC; - else if (StrEq(p,"A")) - *res=HI(z80->AF.w); - else if (StrEq(p,"F")) - *res=LO(z80->AF.w); - else if (StrEq(p,"B")) - *res=HI(z80->BC.w); - else if (StrEq(p,"C")) - *res=LO(z80->BC.w); - else if (StrEq(p,"D")) - *res=HI(z80->DE.w); - else if (StrEq(p,"E")) - *res=LO(z80->DE.w); - else if (StrEq(p,"H")) - *res=HI(z80->HL.w); - else if (StrEq(p,"L")) - *res=LO(z80->HL.w); - else if (StrEq(p,"AF_")) - *res=z80->AF_; - else if (StrEq(p,"BC_")) - *res=z80->BC_; - else if (StrEq(p,"DE_")) - *res=z80->DE_; - else if (StrEq(p,"HL_")) - *res=z80->HL_; - else if (StrEq(p,"A_")) - *res=HI(z80->AF_); - else if (StrEq(p,"F_")) - *res=LO(z80->AF_); - else if (StrEq(p,"B_")) - *res=HI(z80->BC_); - else if (StrEq(p,"C_")) - *res=LO(z80->BC_); - else if (StrEq(p,"D_")) - *res=HI(z80->DE_); - else if (StrEq(p,"E_")) - *res=LO(z80->DE_); - else if (StrEq(p,"H_")) - *res=HI(z80->HL_); - else if (StrEq(p,"L_")) - *res=LO(z80->HL_); - else if (StrEq(p,"IM")) - *res=z80->IM; - else if (StrEq(p,"R")) - *res=z80->R; - else if (StrEq(p,"IFF1")) - *res=z80->IFF1; - else if (StrEq(p,"IFF2")) - *res=z80->IFF2; - else if (p[0]=='@') - { - Z80Word n; - - n=Address(p+1); - *res=Z80_MEMORY[n]; - } - else if (p[0]=='#') - { - Z80Word n; - - n=Address(p+1); - *res=MK(Z80_MEMORY[n+1],Z80_MEMORY[n]); - } - else /* Check for labels */ - { - int f; - - ok=FALSE; - - for(f=0;label && label[f].label;f++) - { - if (StrEq(p,label[f].label)) - { - *res=label[f].address; - ok=TRUE; - break; - } - } - } - - return ok; -} - - -static Z80Word Address(const char *p) -{ - long e=0; - - if (!ExprEval(p,&e,Expand,z80)) - Log("%s\n",ExprError()); - - return (Z80Word)e; -} - - -static void *Malloc(size_t len) -{ - void *n; - - n=malloc(len); - - if (!n) - { - fprintf(stderr,"malloc failed\n"); - exit(EXIT_FAILURE); - } - - return n; -} - -static void *Realloc(void *p, size_t len) -{ - void *n; - - n=realloc(p,len); - - if (!n) - { - fprintf(stderr,"realloc failed\n"); - exit(EXIT_FAILURE); - } - - return n; -} - -static char *StrCopy(const char *p) -{ - return strcpy(Malloc(strlen(p)+1),p); -} - -static const int ToHex(char c) -{ - c=toupper(c); - - if (c>='0' && c<='9') - return c-'0'; - - if (c>='A' && c<='F') - return c-'A'+10; - - return 0; -} - -static void FlagString(DString s, Z80Byte flag, Z80Byte last) -{ - static char *c[]={"S","Z","5","H","3","P","N","C"}; - int f; - - DSAdd(s,"Flags: "); - - for(f=0;f<8;f++) - { - int b=1<<(7-f); - - if ((last&b)!=(flag&b)) - { - DSAdd(s,"<span foreground=\"white\" background=\"black\">"); - } - - if (flag&b) - { - DSAdd(s,c[f]); - } - else - { - DSAdd(s,"-"); - } - - if ((last&b)!=(flag&b)) - { - DSAdd(s,"</span>"); - } - } -} - - -static void DisplayState(DString s, const char *label, - int width, Z80Val val, Z80Val last) -{ - static char buff[128]; - - sprintf(buff,"%s: %s%*.*lX</span>", - label, - (last==val) ? - "<span>" : - "<span foreground=\"white\" background=\"black\">", - width,width, - val); - - DSAdd(s,buff); -} - - -/* ---------------------------------------- MEMORY -*/ -#ifndef ENABLE_ARRAY_MEMORY -static Z80Byte Peek(Z80 *z80, Z80Word addr) -{ - return Z80_MEMORY[addr]; -} - -static void Poke(Z80 *z80, Z80Word addr, Z80Byte b) -{ - Z80_MEMORY[addr]=b; -} -#endif - -static Z80Byte ReadPort(Z80 *z80, Z80Word addr) -{ - Z80Byte b=0xff; - Z80Word ptr; - char expr[1024]; - char *p; - - switch(addr&0xff) - { - case 0x80: - ptr=MK(Z80_MEMORY[1],Z80_MEMORY[0]); - - p=expr; - - while(Z80_MEMORY[ptr]) - *p++=Z80_MEMORY[ptr++]; - - *p=0; - - b=(Z80Byte)Address(expr); - - /* Log("%s -> %u\n",expr,b); */ - - break; - - case 0x81: - ptr=z80->DE.w; - - p=expr; - - while(Z80_MEMORY[ptr]) - *p++=Z80_MEMORY[ptr++]; - - *p=0; - - b=(Z80Byte)Address(expr); - - break; - - default: - Log("Read from port 0x%4.4x\n",(int)addr); - break; - } - - return b; -} - - -static void WritePort(Z80 *z80, Z80Word addr, Z80Byte val) -{ - Z80Word de; - - de=z80->DE.w; - - switch(addr&0xff) - { - case 0x80: - Log("%c",val); - fflush(stdout); - break; - - case 0x81: - Log("Stop requested\n"); - stop=TRUE; - break; - - case 0x82: - while(Z80_MEMORY[de]!='$') - { - if (isspace(Z80_MEMORY[de]) || - isprint(Z80_MEMORY[de])) - Log("%c",Z80_MEMORY[de]); - - de++; - } - fflush(stdout); - break; - - case 0x83: - while(Z80_MEMORY[de]) - { - Log("%c",Z80_MEMORY[de]); - de++; - } - fflush(stdout); - break; - - default: - Log("Wrote 0x%2.2x to port 0x%4.4x\n",(int)val,(int)addr); - break; - } -} - - -static int Halt(Z80 *z80, Z80Val v) -{ - - Log("**** Processor halted\n"); - DialogOK("Processor halted\n"); - stop=TRUE; - return FALSE; -} - - -/* ---------------------------------------- EXPORTED FUNCTIONS -*/ -void GEMMA_UpdateDisplay(GEMMA_View view) -{ - if (view&UPDATE_ASSEM_VIEW) - { - Z80Word pc; - DString ds; - char buff[10]; - int f; - - ds=DSInit(); - DSAdd(ds,"<tt><small>"); - - for(f=10;f>=0;f--) - { - pc=Get_PC(f); - - sprintf(buff,"%4.4X: ",pc); - DSAdd(ds,buff); - DSAdd(ds,Z80Disassemble(z80,&pc)); - DSAddChar(ds,'\n'); - } - - pc=z80->PC; - - for(f=0;f<12;f++) - { - if (f==0) - { - DSAdd(ds,"<span foreground=\"white\" background=\"black\">"); - } - - sprintf(buff,"%4.4X: ",pc); - DSAdd(ds,buff); - - DSAdd(ds,Z80Disassemble(z80,&pc)); - - if (f==0) - { - DSAdd(ds,"</span>"); - } - - DSAddChar(ds,'\n'); - } - - DSAdd(ds,"</small></tt>"); - gtk_label_set_markup(GTK_LABEL(assemview),ds->text); - - DSFree(ds); - } - - if (view&UPDATE_REG_VIEW) - { - static int reg_once=FALSE; - static Z80 last_reg; - DString ds; - - ds=DSInit(); - - if (!reg_once) - { - last_reg=*z80; - reg_once=TRUE; - } - - DSAdd(ds,"<tt>"); - - DisplayState(ds,"A ",2,HI(z80->AF.w),HI(last_reg.AF.w)); - DSAdd(ds," "); - FlagString(ds,LO(z80->AF.w),LO(last_reg.AF.w)); - DSAdd(ds,"\n"); - - DisplayState(ds,"BC ",4,z80->BC.w,last_reg.BC.w); - DSAdd(ds," "); - DisplayState(ds,"DE ",4,z80->DE.w,last_reg.DE.w); - DSAdd(ds," "); - DisplayState(ds,"HL ",4,z80->HL.w,last_reg.HL.w); - DSAdd(ds,"\n"); - - DisplayState(ds,"SP ",4,z80->SP,last_reg.SP); - DSAdd(ds," "); - DisplayState(ds,"IX ",4,z80->IX.w,last_reg.IX.w); - DSAdd(ds," "); - DisplayState(ds,"IY ",4,z80->IY.w,last_reg.IY.w); - DSAdd(ds,"\n\n"); - - DisplayState(ds,"A' ",2,HI(z80->AF_),HI(last_reg.AF_)); - DSAdd(ds," "); - FlagString(ds,LO(z80->AF_),LO(last_reg.AF_)); - DSAdd(ds,"\n"); - - DisplayState(ds,"BC'",4,z80->BC_,last_reg.BC_); - DSAdd(ds," "); - DisplayState(ds,"DE'",4,z80->DE_,last_reg.DE_); - DSAdd(ds," "); - DisplayState(ds,"HL'",4,z80->HL_,last_reg.HL_); - DSAdd(ds,"\n\n"); - - DisplayState(ds,"PC ",4,z80->PC,last_reg.PC); - DSAdd(ds," "); - DisplayState(ds,"CYCLE",8,Z80Cycles(z80),0); - DSAdd(ds,"\n\n"); - - DisplayState(ds,"R ",2,z80->R,last_reg.R); - DSAdd(ds," "); - DisplayState(ds,"IFF1",1,z80->IFF1,last_reg.IFF1); - DSAdd(ds," "); - DisplayState(ds,"IFF2",1,z80->IFF2,last_reg.IFF2); - DSAdd(ds,"\n"); - - DisplayState(ds,"IM ",1,z80->IM,last_reg.IM); - DSAdd(ds," "); - DisplayState(ds,"I",1,z80->I,last_reg.I); - DSAdd(ds,"\n"); - - DSAdd(ds,"</tt>"); - - gtk_label_set_markup(GTK_LABEL(regview),ds->text); - - DSFree(ds); - - last_reg=*z80; - } - - if (view&UPDATE_MEM_VIEW) - { - Z80Word addr; - Z80Word orig; - DString ds; - int f; - gboolean as_words; - - ds=DSInit(); - - as_words=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(memview_check)); - - switch(gtk_combo_box_get_active(GTK_COMBO_BOX(memview_combo))) - { - case 0: - addr=z80->HL.w; - break; - case 1: - addr=z80->SP; - as_words=TRUE; - break; - case 2: - addr=z80->IX.w; - break; - case 3: - addr=z80->IY.w; - break; - case 4: - addr=z80->BC.w; - break; - case 5: - addr=z80->DE.w; - break; - default: - addr=z80->PC; - break; - } - - DSAdd(ds,"<tt><small>"); - - orig=addr; - addr-=6*8; - - for(f=0;f<13;f++) - { - DString asc; - char buff[10]; - Z80Word off; - - asc=DSInit(); - - sprintf(buff,"%4.4X: ",addr); - DSAdd(ds,buff); - - for(off=0;off<8;off++) - { - gchar *p; - p=g_markup_printf_escaped - ("%c",isprint(Z80_MEMORY[addr+off]) ? Z80_MEMORY[addr+off] : '.'); - DSAdd(asc,p); - g_free(p); - } - - for(off=0;off<8;off+=(as_words ? 2:1)) - { - Z80Word a; - - a=addr+off; - - if (a==orig) - { - DSAdd(ds,"<span foreground=\"white\" " - "background=\"black\">"); - } - - if (as_words) - { - sprintf(buff,"%4.4X ",MK(Z80_MEMORY[a+1],Z80_MEMORY[a])); - } - else - { - sprintf(buff,"%2.2X ",Z80_MEMORY[a]); - } - - DSAdd(ds,buff); - - if (a==orig) - { - DSAdd(ds,"</span>"); - } - } - - DSAdd(ds," "); - DSAdd(ds,asc->text); - DSAdd(ds,"\n"); - - DSFree(asc); - - addr+=8; - } - - DSAdd(ds,"</small></tt>"); - - gtk_label_set_markup(GTK_LABEL(memview),ds->text); - - DSFree(ds); - } -} - - -void GEMMA_LoadHEX(const char *path) -{ - FILE *fp; - char buff[1024]; - int done=FALSE; - - if (!(fp=fopen(path,"r"))) - { - Log("Failed to open %s\n",path); - return; - } - - while(!done) - { - if (!fgets(buff,sizeof buff,fp)) - { - Log("Missing EOF record\n"); - done=TRUE; - } - - if (!done && buff[0]!=':') - { - Log("Invalid Intel HEX file\n"); - done=TRUE; - } - - if (!done && buff[8]=='1') - { - Log("<EOF>\n"); - done=TRUE; - } - - if (!done) - { - Z80Word addr; - int len; - int f; - - len=ToHex(buff[1])<<4|ToHex(buff[2]); - - addr=ToHex(buff[3])<<12|ToHex(buff[4])<<8| - ToHex(buff[5])<<4|ToHex(buff[6]); - - Log("Segment of 0x%2.2x bytes at address 0x%4.4x\n",len,addr); - - for(f=0;f<len;f++) - { - Z80Byte b; - - b=ToHex(buff[f*2+9])<<4|ToHex(buff[f*2+10]); - Z80_MEMORY[addr++]=b; - } - } - } - - fclose(fp); - - GEMMA_UpdateDisplay(UPDATE_ALL_VIEWS); -} - - -void GEMMA_LoadLabels(const char *path) -{ - FILE *fp; - int f; - char buff[512]; - - if (!(fp=fopen(path,"r"))) - { - Log("Failed to open %s\n",path); - return; - } - - for(f=0;label && label[f].label;f++) - free((void *)label[f].label); - - free(label); - label=NULL; - f=0; - - while(fgets(buff,sizeof buff,fp)) - { - char *name=NULL; - char *addr=NULL; - - if (strlen(buff) && buff[strlen(buff)-1]=='\n') - buff[strlen(buff)-1]=0; - - name=strtok(buff," \t"); - - if (name) - addr=strtok(NULL," \t"); - - if (name && addr) - { - label=Realloc(label,sizeof(*label)*(f+2)); - - label[f].label=StrCopy(name); - label[f].address=Address(addr); - - f++; - } - } - - if (label) - label[f].label=NULL; - - Z80SetLabels(label); - - fclose(fp); -} - - -void GEMMA_Step(void) -{ - Step(); - GEMMA_UpdateDisplay(UPDATE_ALL_VIEWS); -} - - -void GEMMA_StepOver(void) -{ - Z80Word next; - - stop=FALSE; - - next=z80->PC; - Z80Disassemble(z80,&next); - - RUNNING(TRUE); - - while(z80->PC!=next && !stop) - { - Step(); - gtk_main_iteration_do(FALSE); - } - - GEMMA_UpdateDisplay(UPDATE_ALL_VIEWS); - - RUNNING(FALSE); -} - - -void GEMMA_Run(void) -{ - stop=FALSE; - - RUNNING(TRUE); - - while(!stop) - { - GEMMA_Step(); - gtk_main_iteration_do(FALSE); - } - - RUNNING(FALSE); -} - - -void GEMMA_RunUntil(void) -{ - char *expr; - - expr=StrCopy(gtk_entry_get_text(GTK_ENTRY(breakpoint_text))); - - stop=FALSE; - - RUNNING(TRUE); - - while(!stop) - { - long e; - - if (!ExprEval(expr,&e,Expand,z80)) - { - DialogOK("Error evaluating express:\n%s",ExprError()); - stop=TRUE; - continue; - } - - if (e) - { - DialogOK("%s TRUE",expr); - stop=TRUE; - continue; - } - - GEMMA_Step(); - gtk_main_iteration_do(FALSE); - } - - free(expr); - - RUNNING(FALSE); -} - - -void GEMMA_Stop(void) -{ - stop=TRUE; -} - - -void GEMMA_Init(GtkWidget *top) -{ -#ifdef ENABLE_ARRAY_MEMORY - z80=Z80Init(ReadPort,WritePort); -#else - z80=Z80Init(Peek,Poke,ReadPort,WritePort,Peek); -#endif - z80->PC=0x100; - - if (!z80) - { - fprintf(stderr,"Failed to initialise Z80\n"); - exit(EXIT_FAILURE); - } - - Z80LodgeCallback(z80,eZ80_Halt,Halt); - - top_window=top; - regview=lookup_widget(top_window,"register_view"); - memview=lookup_widget(top_window,"memory_view"); - viewreg=lookup_widget(top_window,"memory_view_choice"); - logview=lookup_widget(top_window,"log_view"); - assemview=lookup_widget(top_window,"assem_view"); - - memview_combo=lookup_widget(top_window,"memory_view_choice"); - memview_check=lookup_widget(top_window,"viewmode_check"); - - breakpoint_text=lookup_widget(top_window,"breakpoint_text"); - - run_button=lookup_widget(top_window,"run_button"); - step_button=lookup_widget(top_window,"step_button"); - step_over_button=lookup_widget(top_window,"step_over_button"); - stop_button=lookup_widget(top_window,"stop_button"); - run_until_button=lookup_widget(top_window,"run_until_button"); - - gtk_combo_box_set_active(GTK_COMBO_BOX(memview_combo),0); -} - - -void GEMMA_Interrupt(int nmi) -{ - if (nmi) - { - Z80NMI(z80); - } - else - { - Z80Interrupt(z80,0); - } -} - - -/* END OF FILE */ |