// // Created by imanol on 12/26/16. // #include #include #include "debug.h" //uint32_t cycle_count = 0; uint8_t breakpoint = 1; uint16_t breakpoints[0xFF]; uint16_t nbpoints = 0; char lastchoice = 0; void load_state(char *filename) { FILE *state = fopen(filename,"r"); uint16_t regsdump[NUM_REGISTERS+1]; uint16_t memdump[MEMSIZE]; uint16_t *stackdump; uint32_t stacksize, stackpos; fread(regsdump,sizeof(uint16_t),NUM_REGISTERS+1,state); fread(memdump,sizeof(uint16_t),MEMSIZE,state); stackpos = ftell(state); fseek(state,0,SEEK_END); stacksize = (ftell(state) - stackpos)/sizeof(uint16_t); stackdump = calloc(stacksize,sizeof(uint16_t)); fseek(state,stackpos,SEEK_SET); fread(stackdump,sizeof(uint16_t),stacksize,state); fclose(state); load_regs(regsdump); load_memory(memdump); stack_load(stackdump,stacksize); free(stackdump); } void save_state(char *filename) { FILE *state = fopen(filename,"w"); uint16_t regsdump[NUM_REGISTERS+1]; uint16_t memdump[MEMSIZE]; uint16_t *stackdump; uint32_t stacksize; dump_regs(regsdump); dump_memory(memdump); stacksize = stack_dump(&stackdump); fwrite(regsdump,sizeof(uint16_t),NUM_REGISTERS+1,state); fwrite(memdump,sizeof(uint16_t),MEMSIZE,state); fwrite(stackdump,sizeof(uint16_t),stacksize,state); fclose(state); free(stackdump); } void query() { //TODO discard stdin uint8_t end = 0; uint16_t bpoint; uint16_t mempos; char input[100] = {0}; char filename[32]; uint8_t reg; uint8_t value; while(!end) { printf("\n> "); char command = 0; fgets(input,100,stdin); command = input[0]; if (command != '\n') { lastchoice = command; } else { command = lastchoice; } switch (command) { case 'b': sscanf(input,"b %d\n",&bpoint); fprintf(stderr,"Set breakpoint %d to %d",nbpoints,bpoint); breakpoints[nbpoints] = bpoint; nbpoints = nbpoints + 1 % 0xFF; break; case 'd': sscanf(input,"d %d\n",&bpoint); fprintf(stderr,"Deleted breakpoint %d",bpoint); breakpoints[bpoint] = 0; break; case 'c': breakpoint = 0; end = 1; break; case 'n': end = 1; break; case 'r': print_regs(); break; case 'm': sscanf(input,"m %d\n",&mempos); fprintf(stderr,"%d: %02x\n",mempos,mem[mempos]); break; case 's': sscanf(input,"s %s\n",filename); save_state(filename); fprintf(stderr,"Saved state as %s",filename); break; case 'l': sscanf(input,"l %s\n",filename); load_state(filename); fprintf(stderr,"Loaded state as %s",filename); break; case 'w': //FIXME ALREADY sscanf(input,"w %d %d\n",®,&value); fprintf(stderr,"Setting register %d to %d",reg,value); regs[reg] = value; break; default: break; } } } uint8_t in_breakpoint(uint16_t pc) { uint8_t i; for(i = 0; i < nbpoints; i++) { if(breakpoints[i] == pc) { return 1; } } return 0; } uint16_t fetch_debug() { uint16_t value = mem[pc++]; /*if(breakpoint) { fprintf(stderr,"0x%2x (0x%2x): %d", pc, pc * sizeof(uint16_t),value); fprintf(stderr," cycle: %d\n", cycle_count++); }*/ return value; } void translate_args(uint16_t a1, uint16_t a2, uint16_t a3, char *arg1, char *arg2, char *arg3) { if(a1 > MAX_INT) { sprintf(arg1,"r%d",a1-(MAX_INT+1)); } else { sprintf(arg1,"%d",a1); } if(a2 > MAX_INT) { sprintf(arg2,"r%d",a2-(MAX_INT+1)); } else { sprintf(arg2,"%d",a2); } if(a3 > MAX_INT) { sprintf(arg3,"r%d",a3-(MAX_INT+1)); } else { sprintf(arg3,"%d",a3); } } void print_instruction(uint16_t opcode, uint16_t a1, uint16_t a2, uint16_t a3) { char arg1[10]; char arg2[10]; char arg3[10]; translate_args(a1,a2,a3,arg1,arg2,arg3); switch(opcode) { case HALT: fprintf(stderr,"HALT\n"); break; case MOV: fprintf(stderr,"MOV %s %s\n",arg1,arg2); break; case PUSH: fprintf(stderr,"PUSH %s\n",arg1); break; case POP: fprintf(stderr,"POP %s\n",arg1); break; case TEQ: fprintf(stderr,"TEQ %s %s %s\n",arg1,arg2,arg3); break; case TGT: fprintf(stderr,"TGT %s %s %s\n",arg1,arg2,arg3); break; case JMP: fprintf(stderr,"JMP %s\n",arg1); break; case JNZ: fprintf(stderr,"JNZ %s %s\n",arg1,arg2); break; case JZ: fprintf(stderr,"JZ %s %s\n",arg1,arg2); break; case ADD: fprintf(stderr,"ADD %s %s %s\n",arg1,arg2,arg3); break; case MUL: fprintf(stderr,"MUL %s %s %s\n",arg1,arg2,arg3); break; case MOD: fprintf(stderr,"MOD %s %s %s\n",arg1,arg2,arg3); break; case AND: fprintf(stderr,"AND %s %s %s\n",arg1,arg2,arg3); break; case OR: fprintf(stderr,"OR %s %s %s\n",arg1,arg2,arg3); break; case NOT: fprintf(stderr,"NOT %s %s\n",arg1,arg2); break; case LOAD: fprintf(stderr,"LOAD %s %s\n",arg1,arg2); break; case STOR: fprintf(stderr,"STOR %s %s\n",arg1,arg2); break; case CALL: fprintf(stderr,"CALL %s\n",arg1); break; case RET: fprintf(stderr,"RET\n"); break; case OUT: fprintf(stderr,"OUT %s\n",arg1); break; case IN: fprintf(stderr,"IN %s\n",arg1); break; case NOP: fprintf(stderr,"NOP\n"); break; default: fprintf(stderr,"UNK %d\n", opcode); break; } } void debug_program() { memset(breakpoints,0x00,0xFF); uint16_t arg1; uint16_t arg2; uint16_t arg3; for(;;) { if(in_breakpoint(pc) || breakpoint) { breakpoint = 1; fprintf(stderr, "%d: ", pc); print_instruction(mem[pc], mem[pc+1], mem[pc+2], mem[pc+3]); query(); } uint16_t opcode = fetch_debug(); decode_instruction(opcode, &arg1, &arg2, &arg3); if (execute_instruction(opcode, arg1, arg2, arg3)) { return; } } }