#define BUF_SIZE 100 \ #define rQ 16 \ /*2:*/ #line 35 "mmmix.w" #include #include "mmix-pipe.h" char*config_file_name,*prog_file_name; /*5:*/ #line 101 "mmmix.w" octa cur_loc; octa cur_dat; bool new_chunk; char buffer[BUF_SIZE]; FILE*prog_file; /*:5*//*16:*/ #line 406 "mmmix.w" int n,m; octa bp= {-1,-1}; octa tmp; static unsigned char d[BUF_SIZE]; /*:16*//*25:*/ #line 532 "mmmix.w" bool bad_address; extern bool page_bad; extern octa page_mask; extern int page_r,page_s,page_b[5]; extern octa zero_octa; extern octa neg_one; octa seven_octa= {0,7}; extern octa incr ARGS((octa y,int delta)); extern void mmix_io_init ARGS((void)); extern void MMIX_config ARGS((char*)); /*:25*/ #line 40 "mmmix.w" /*10:*/ #line 205 "mmmix.w" static bool undump_octa ARGS((void)); static bool undump_octa() { register int t0,t1,t2,t3; t0= fgetc(prog_file);if(t0==EOF)return false; t1= fgetc(prog_file);if(t1==EOF)goto oops; t2= fgetc(prog_file);if(t2==EOF)goto oops; t3= fgetc(prog_file);if(t3==EOF)goto oops; cur_dat.h= (t0<<24)+(t1<<16)+(t2<<8)+t3; t0= fgetc(prog_file);if(t0==EOF)goto oops; t1= fgetc(prog_file);if(t1==EOF)goto oops; t2= fgetc(prog_file);if(t2==EOF)goto oops; t3= fgetc(prog_file);if(t3==EOF)goto oops; cur_dat.l= (t0<<24)+(t1<<16)+(t2<<8)+t3; return true; oops:fprintf(stderr,"Premature end of file on %s!\n",prog_file_name); return false; } /*:10*//*17:*/ #line 417 "mmmix.w" octa read_hex ARGS((char*)); octa read_hex(p) char*p; { register int j,k; octa val; val.h= val.l= 0; for(j= 0;;j++){ if(p[j]>='0'&&p[j]<='9')d[j]= p[j]-'0'; else if(p[j]>='a'&&p[j]<='f')d[j]= p[j]-'a'+10; else if(p[j]>='A'&&p[j]<='F')d[j]= p[j]-'A'+10; else break; } p[j]= '\0'; for(j--,k= 0;k<=j;k++){ if(k>=8)val.h+= d[j-k]<<(4*k-32); else val.l+= d[j-k]<<(4*k); } return val; } /*:17*//*20:*/ #line 465 "mmmix.w" static octa sl3 ARGS((octa)); static octa sl3(y) octa y; { register tetra yhl= y.h<<3,ylh= y.l>>29; y.h= yhl+ylh;y.l<<= 3; return y; } /*:20*/ #line 41 "mmmix.w" int main(argc,argv) int argc; char*argv[]; { /*3:*/ #line 62 "mmmix.w" if(argc!=3){ fprintf(stderr,"Usage: %s configfile progfile\n",argv[0]); exit(-3); } config_file_name= argv[1]; prog_file_name= argv[2]; /*:3*/ #line 47 "mmmix.w" ; MMIX_config(config_file_name); MMIX_init(); mmix_io_init(); /*4:*/ #line 71 "mmmix.w" if(strcmp(prog_file_name+strlen(prog_file_name)-4,".mmb")==0) /*9:*/ #line 179 "mmmix.w" { prog_file= fopen(prog_file_name,"rb"); if(!prog_file){ fprintf(stderr,"Panic: Can't open MMIX binary file %s!\n",prog_file_name); exit(-3); } while(1){ if(!undump_octa())break; new_chunk= true; cur_loc= cur_dat; if(cur_loc.h&0x9fffffff)bad_address= true; else bad_address= false,cur_loc.h>>= 29; /*11:*/ #line 226 "mmmix.w" while(1){ if(!undump_octa()){ fprintf(stderr,"Unexpected end of file on %s!\n",prog_file_name); break; } if(!(cur_dat.h||cur_dat.l))break; if(bad_address){ fprintf(stderr,"Panic: Unsupported virtual address %08x%08x!\n", cur_loc.h,cur_loc.l); exit(-5); } if(new_chunk)mem_write(cur_loc,cur_dat); else mem_hash[last_h].chunk[(cur_loc.l&0xffff)>>3]= cur_dat; cur_loc.l+= 8; if((cur_loc.l&0xfff8)!=0)new_chunk= false; else{ new_chunk= true; if((cur_loc.l&0xffff0000)==0){ bad_address= true;cur_loc.h= (cur_loc.h<<29)+1; } } } /*:11*/ #line 194 "mmmix.w" ; } /*12:*/ #line 260 "mmmix.w" if(cur_loc.h!=3){ fprintf(stderr,"Panic: MMIX binary file didn't set up the stack!\n"); exit(-6); } inst_ptr.o= mem_read(incr(cur_loc,-8*14)); inst_ptr.p= NULL; cur_loc.h= 0x60000000; g[255].o= incr(cur_loc,-8); cur_dat.l= 0x90; if(mem_read(cur_dat).h)inst_ptr.o= cur_dat; head->inst= (UNSAVE<<24)+255,tail--; head->loc= incr(inst_ptr.o,-4); g[rT].o.h= 0x80000005,g[rTT].o.h= 0x80000006; cur_dat.h= (RESUME<<24)+1,cur_dat.l= 0,cur_loc.h= 5,cur_loc.l= 0; mem_write(cur_loc,cur_dat); cur_dat.l= cur_dat.h,cur_dat.h= (NEGI<<24)+(255<<16)+1; cur_loc.h= 6,cur_loc.l= 8; mem_write(cur_loc,cur_dat); cur_dat.h= (GET<<24)+rQ,cur_dat.l= (PUTI<<24)+(rQ<<16),cur_loc.l= 0; mem_write(cur_loc,cur_dat); cur_dat.h= 0,cur_dat.l= 7; cur_loc.h= 4; mem_write(cur_loc,cur_dat); ITcache->set[0][0].tag= zero_octa; ITcache->set[0][0].data[0]= cur_dat; cur_dat.l= 6; cur_dat.h= 1,cur_loc.l= 3<<13; mem_write(cur_loc,cur_dat); cur_dat.h= 2,cur_loc.l= 6<<13; mem_write(cur_loc,cur_dat); cur_dat.h= 3,cur_loc.l= 9<<13; mem_write(cur_loc,cur_dat); g[rK].o= neg_one; g[rV].o.h= 0x3692004; page_bad= false,page_r= 4<<(32-13),page_s= 32,page_mask.l= 0xffffffff; page_b[1]= 3,page_b[2]= 6,page_b[3]= 9,page_b[4]= 12; /*:12*/ #line 196 "mmmix.w" ; } /*:9*/ #line 73 "mmmix.w" else/*6:*/ #line 108 "mmmix.w" { prog_file= fopen(prog_file_name,"r"); if(!prog_file){ fprintf(stderr,"Panic: Can't open MMIX hexadecimal file %s!\n",prog_file_name); exit(-3); } new_chunk= true; while(1){ if(!fgets(buffer,BUF_SIZE,prog_file))break; if(buffer[strlen(buffer)-1]!='\n'){ fprintf(stderr,"Panic: Hexadecimal file line too long: `%s...'!\n",buffer); exit(-3); } if(buffer[12]==':')/*7:*/ #line 134 "mmmix.w" { if(sscanf(buffer,"%4x%8x",&cur_loc.h,&cur_loc.l)!=2){ fprintf(stderr,"Panic: Improper hexadecimal file location: `%s'!\n",buffer); exit(-3); } new_chunk= true; } /*:7*/ #line 124 "mmmix.w" else if(buffer[0]==' ')/*8:*/ #line 144 "mmmix.w" { if(sscanf(buffer+1,"%8x%8x",&cur_dat.h,&cur_dat.l)!=2){ fprintf(stderr,"Panic: Improper hexadecimal file data: `%s'!\n",buffer); exit(-3); } if(new_chunk)mem_write(cur_loc,cur_dat); else mem_hash[last_h].chunk[(cur_loc.l&0xffff)>>3]= cur_dat; cur_loc.l+= 8; if((cur_loc.l&0xfff8)!=0)new_chunk= false; else{ new_chunk= true; if((cur_loc.l&0xffff0000)==0)cur_loc.h++; } } /*:8*/ #line 125 "mmmix.w" else{ fprintf(stderr,"Panic: Improper hexadecimal file line: `%s'!\n",buffer); exit(-3); } } } /*:6*/ #line 74 "mmmix.w" ; fclose(prog_file); /*:4*/ #line 51 "mmmix.w" ; /*13:*/ #line 353 "mmmix.w" while(1){ printf("mmmix> "); fgets(buffer,BUF_SIZE,stdin); switch(buffer[0]){ default:what_say: printf("Eh? Sorry, I don't understand. (Type h for help)\n"); continue; case'q':case'x':goto done; /*14:*/ #line 368 "mmmix.w" case'h':case'?':printf("The interactive commands are as follows:\n"); printf(" to run for n cycles\n"); printf(" @ to take next instruction from location x\n"); printf(" b to pause when location x is fetched\n"); printf(" v to print specified diagnostics when running;\n"); printf(" x=1[insts enter/leave pipe]+2[whole pipeline each cycle]+\n"); printf(" 4[coroutine activations]+8[coroutine scheduling]+\n"); printf(" 10[uninitialized read]+20[online I/O read]+\n"); printf(" 40[I/O read/write]+80[branch prediction details]+\n"); printf(" 100[invalid cache blocks displayed too]\n"); printf(" - to deissue n instructions\n"); printf(" l to print current value of local register n\n"); printf(" g to print current value of global register n\n"); printf(" m to print current value of memory address x\n"); printf(" f to insert instruction x into the fetch buffer\n"); printf(" i to initiate a timer interrupt after n cycles\n"); printf(" IT, DT, I, D, or S to print current cache contents\n"); printf(" D* or S* to print dirty blocks of a cache\n"); printf(" p to print current pipeline contents\n"); printf(" s to print current stats\n"); printf(" h to print this message\n"); printf(" q to exit\n"); printf("(Here is a decimal integer, is hexadecimal.)\n"); continue; /*:14*//*15:*/ #line 394 "mmmix.w" case'0':case'1':case'2':case'3':case'4': case'5':case'6':case'7':case'8':case'9': if(sscanf(buffer,"%d",&n)!=1)goto what_say; printf("Running %d at time %d",n,ticks.l); if(bp.h==(tetra)-1&&bp.l==(tetra)-1)printf("\n"); else printf(" with breakpoint %08x%08x\n",bp.h,bp.l); MMIX_run(n,bp);continue; case'@':inst_ptr.o= read_hex(buffer+1);inst_ptr.p= NULL;continue; case'b':bp= read_hex(buffer+1);continue; case'v':verbose= read_hex(buffer+1).l;continue; /*:15*//*18:*/ #line 439 "mmmix.w" case'-':if(sscanf(buffer+1,"%d",&n)!=1||n<0)goto what_say; if(cool<=hot)m= hot-cool;else m= (hot-reorder_bot)+1+(reorder_top-cool); if(n> m)deissues= m;else deissues= n; continue; case'l':if(sscanf(buffer+1,"%d",&n)!=1||n<0)goto what_say; if(n>=lring_size)goto what_say; printf(" l[%d]=%08x%08x\n",n,l[n].o.h,l[n].o.l);continue; case'm':tmp= mem_read(read_hex(buffer+1)); printf(" m[%s]=%08x%08x\n",buffer+1,tmp.h,tmp.l);continue; /*:18*//*19:*/ #line 454 "mmmix.w" case'g':if(sscanf(buffer+1,"%d",&n)!=1||n<0)goto what_say; if(n>=256)goto what_say; if(n==rO||n==rS){ if(hot==cool) g[rO].o= sl3(cool_O),g[rS].o= sl3(cool_S); else g[rO].o= sl3(hot->cur_O),g[rS].o= sl3(hot->cur_S); } printf(" g[%d]=%08x%08x\n",n,g[n].o.h,g[n].o.l); continue; /*:19*//*21:*/ #line 475 "mmmix.w" case'I':print_cache(buffer[1]=='T'?ITcache:Icache,false);continue; case'D':print_cache(buffer[1]=='T'?DTcache:Dcache, buffer[1]=='*');continue; case'S':print_cache(Scache,buffer[1]=='*');continue; case'p':print_pipe();print_locks();continue; case's':print_stats();continue; case'i':if(sscanf(buffer+1,"%d",&n)==1)g[rI].o= incr(zero_octa,n); continue; /*:21*//*22:*/ #line 485 "mmmix.w" case'f':tmp= read_hex(buffer+1); { register fetch*new_tail; if(tail==fetch_bot)new_tail= fetch_top; else new_tail= tail-1; if(new_tail==head)printf("Sorry, the fetch buffer is full!\n"); else{ tail->loc= inst_ptr.o; tail->inst= tmp.l; tail->interrupt= 0; tail->noted= false; tail= new_tail; } continue; } /*:22*//*23:*/ #line 506 "mmmix.w" case'd':if(ticks.l) printf("Sorry: I disable ITcache and DTcache only at the beginning!\n"); else{ ITcache->set[0][0].tag= zero_octa; ITcache->set[0][0].data[0]= seven_octa; DTcache->set[0][0].tag= zero_octa; DTcache->set[0][0].data[0]= seven_octa; g[rK].o= neg_one; page_bad= false; page_mask= neg_one; inst_ptr.p= (specnode*)1; }continue; /*:23*//*24:*/ #line 525 "mmmix.w" case'k':{register int j; for(j= 0;j