// Processes the instruction, calls printReg with correct params void processInstr() { if (icode != 0) { numConsecutiveHalts = 0; } switch (icode) { case 0: instr = "halt"; // if invalid ifun, exit assertZeroiFunCode(ifun, icode_ifun); // set params setParams1ByteInstr(); // increment number of consecutive halts numConsecutiveHalts++; break; case 1: instr = "nop"; assertZeroiFunCode(ifun, icode_ifun); setParams1ByteInstr(); break; case 2: // get instr based on ifun switch (ifun) { case 0: instr = "rrmovq"; break; case 1: instr = "cmovle"; break; case 2: instr = "cmovl"; break; case 3: instr = "cmove"; break; case 4: instr = "cmovne"; break; case 5: instr = "cmovge"; break; case 6: instr = "cmovg"; break; default: // Invalid function code printf("Invalid function code %.2x at 0x%016llX\n",icode_ifun,PC); exit(0); } setParams2ByteInstr(); break; case 3: instr = "irmovq"; assertZeroiFunCode(ifun, icode_ifun); setParams10ByteInstr(); break; case 4: instr = "rmmovq"; assertZeroiFunCode(ifun, icode_ifun); setParams10ByteInstr(); break; case 5: instr = "mrmovq"; assertZeroiFunCode(ifun, icode_ifun); setParams10ByteInstr(); break; case 6: // get instr based on ifun switch (ifun) { case 0: instr = "addq"; break; case 1: instr = "subq"; break; case 2: instr = "andq"; break; case 3: instr = "xorq"; break; case 4: instr = "mulq"; break; case 5: instr = "divq"; break; case 6: instr = "modq"; break; default: // Invalid function code printf("Invalid function code %.2x at 0x%016llX\n",icode_ifun,PC); exit(0); } setParams2ByteInstr(); break; case 7: switch (ifun) { case 0: instr = "jmp"; break; case 1: instr = "jle"; break; case 2: instr = "jl"; break; case 3: instr = "je"; break; case 4: instr = "jne"; break; case 5: instr = "jge"; break; case 6: instr = "jg"; break; default: // Invalid function code printf("Invalid function code %.2x at 0x%016llX\n",icode_ifun,PC); exit(0); } setParams9ByteInstr(); break; case 8: instr = "call"; assertZeroiFunCode(ifun, icode_ifun); setParams9ByteInstr(); break; case 9: instr = "ret"; assertZeroiFunCode(ifun, icode_ifun); setParams1ByteInstr(); break; case 0xA: instr = "pushq"; assertZeroiFunCode(ifun, icode_ifun); setParams2ByteInstr(); break; case 0xB: instr = "popq"; assertZeroiFunCode(ifun, icode_ifun); setParams2ByteInstr(); break; default: // icode not recognized. Print message and exit. printf("Invalid opcode %.2x at 0x%016llX", icode_ifun, PC); exit(0); break; } // handling case where insufficient bytes to complete instruction fetch if (notEnoughBytes) { printf("Memory access error at %.X, required %d bytes, read %d bytes.\n", PC, bytesToRead, numBytesCanRead); exit(0); } // for halt instructions, do not print out more than 5 consecutive. if (icode != 0 || numConsecutiveHalts <= 5) { printReg(PC,icode,ifun,regsValid,rA,rB,valCValid,valC,b0,b1,b2,b3,b4,b5,b6,b7,valP,instr); } // set new PC PC = valP; }
// NOTE: loc points to 1st or 2nd opcode byte (if any) void Ez80::disasmAddrMode(ULONG loc,unsigned int mode) { //unsigned int dig=w->getHexDigits(); //w->setHexDigits(4); switch(mode) { // case Ez80_NONE: DEBUG_OUT<<" ;Ez80_NONE"; break; // case Ez80_SPECIAL: DEBUG_OUT<<" ;Ez80_SPECIAL"; break; // case Ez80_ILLEGAL: DEBUG_OUT<<" ;Ez80_ILLEGAL"; break; // case Ez80_CONST: DEBUG_OUT<<"$?const?"; DEBUG_OUT<<" ;Ez80_CONST"; break; // case Ez80_REGB: reg=map->read8(loc)&0x7; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<" ;Ez80_REGB"; break; // case Ez80_REGB2: reg=(map->read8(loc)>>3)&0x7; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<" ;Ez80_REGB2"; break; // case Ez80_REGW: reg=(map->read8(loc)>>4)&0x3; printReg(reg,Ez80_SIZE_WORD); DEBUG_OUT<<" ;Ez80_REGW"; break; // case Ez80_A_REGB: DEBUG_OUT<<"a,"; reg=map->read8(loc)&0x7; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<" ;Ez80_REGB"; break; // case Ez80_REGB_REGB: reg2=(map->read8(loc)>>3)&0x7; printReg(reg2,Ez80_SIZE_BYTE); DEBUG_OUT<<","; reg=map->read8(loc)&0x7; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<" ;Ez80_REGB_REGB"; break; // case Ez80_REGW_REGW: reg2=(map->read8(loc)>>3)&0x7; printReg(reg2,Ez80_SIZE_WORD); DEBUG_OUT<<","; reg=(map->read8(loc)>>4)&0x3; printReg(reg,Ez80_SIZE_WORD); DEBUG_OUT<<" ;Ez80_REGW_REGW"; break; // case Ez80_REGB_BYTE: reg=(map->read8(loc)>>3)&0x7; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<",#$"<<(BYTE)map->read8(loc+1); DEBUG_OUT<<" ;Ez80_REGB_BYTE"; break; // case Ez80_REGW_WORD: reg=(map->read8(loc)>>4)&0x3; printReg(reg,Ez80_SIZE_WORD); DEBUG_OUT<<",#$"<<(UINT16)map->read16l(loc+1); DEBUG_OUT<<" ;Ez80_REGW_WORD"; break; // case Ez80_INDREGW: reg=(map->read8(loc)>>4)&0x3; DEBUG_OUT<<"("; printReg(reg,Ez80_SIZE_WORD); DEBUG_OUT<<")"; DEBUG_OUT<<" ;Ez80_INDREGW"; break; // case Ez80_INDREGW_BYTE: reg=map->read8(loc)&0x3; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<",#$"<<(short)map->read8(loc+1); DEBUG_OUT<<" ;Ez80_INDREGW_BYTE"; break; // case Ez80_INDBYTE_REGB: reg=(map->read8(loc)>>4)&0x3; DEBUG_OUT<<"($"<<(short)map->read8(loc+1)<<"),"; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<" ;Ez80_INDBYTE_REGB"; break; // case Ez80_REGW_INDABS: reg=(map->read8(loc)>>4)&0x3; printReg(reg,Ez80_SIZE_WORD); DEBUG_OUT<<",($"<<map->read16l(loc+1)<<")"; DEBUG_OUT<<" ;Ez80_REGW_INDABS"; break; // case Ez80_REGW_ABS: reg=(map->read8(loc)>>4)&0x3; printReg(reg,Ez80_SIZE_WORD); DEBUG_OUT<<",$"<<map->read16l(loc+1); DEBUG_OUT<<" ;Ez80_REGW_ABS"; break; // case Ez80_INDABS_REGW: DEBUG_OUT<<"($"<<map->read16l(loc+1)<<"),"; reg=(map->read8(loc)>>4)&0x3; printReg(reg,Ez80_SIZE_WORD); DEBUG_OUT<<" ;Ez80_INDABS_REGW"; break; // case Ez80_INDABS_REGB: DEBUG_OUT<<"($"<<map->read16l(loc+1)<<"),"; reg=(map->read8(loc)>>3)&0x7; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<" ;Ez80_INDABS_REGB"; break; // case Ez80_REGB_INDABS: reg=(map->read8(loc)>>3)&0x7; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<",($"<<map->read16l(loc+1)<<")"; DEBUG_OUT<<" ;Ez80_REGB_INDABS"; break; // case Ez80_REGB_INDREGW: reg=(map->read8(loc)>>3)&0x7; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<",(hl)"; DEBUG_OUT<<" ;Ez80_REGB_INDREGW"; break; // case Ez80_INDREGW_REGB: reg=map->read8(loc)&0x7; DEBUG_OUT<<"(hl),"; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<" ;Ez80_INDREGW_REGB"; break; // case Ez80_INDREGW_REGW: reg=(map->read8(loc)>>3)&0x7; DEBUG_OUT<<"(hl),"; printReg(reg,Ez80_SIZE_WORD); DEBUG_OUT<<" ;Ez80_INDREGW_REGW"; break; // case Ez80_BYTE: DEBUG_OUT<<"#$"<<(short)map->read8(loc+1); DEBUG_OUT<<" ;Ez80_BYTE"; break; // case Ez80_REGB_INDBYTE: reg=(map->read8(loc)>>3)&0x7; printReg(reg,Ez80_SIZE_BYTE); DEBUG_OUT<<",($"<<(short)map->read8(loc+1)<<")"; DEBUG_OUT<<" ;Ez80_INDBYTE"; break; // case Ez80_DJ_REL: case Ez80_J_REL: DEBUG_OUT<<"$"<<(short)map->read8(loc+1)<<" ;"<<(UINT16)((SBYTE)map->read8(loc+1)+loc+2); DEBUG_OUT<<" ;Ez80_J_REL"; break; // case Ez80_ABS: case Ez80_JABS: DEBUG_OUT<<"$"<<map->read16l(loc+1); DEBUG_OUT<<" ;Ez80_ABS"; break; // case Ez80_JCC_REL: reg=(map->read8(loc)>>3)&0x3; printCondCode(reg); DEBUG_OUT<<",$"<<(short)map->read8(loc+1)<<" ;"; DEBUG_OUT<<(UINT16)((SBYTE)map->read8(loc+1)+loc+2); DEBUG_OUT<<" ;Ez80_JCC_REL"; break; // case Ez80_JCC_ABS: reg=(map->read8(loc)>>3)&0x7; printCondCode(reg); DEBUG_OUT<<",$"<<map->read16l(loc+1); DEBUG_OUT<<" ;Ez80_JCC_ABS"; break; // default: DEBUG_OUT<<"???"; DEBUG_OUT<<" ;Ez80_???"; debugger("bad address mode in disasmAddrMode!"); break; }; //w->setHexDigits(dig); }
/* * Main loop used to continuously ask for user input */ int mainloop(){ //Local variables int mode = 0; char op_code[100]; uint16_t instAddr; uint16_t topAddr; uint16_t baseAddr; char fileName[100]; char run = 1; char in[100]; regA.data = 0; regSTAT.data = 0; nibble currentInst; int tempAddress = 0; int instrRun = 0; struct timespec gettime_now; struct timespec newTime = {0, 0}; long totalFirstTime; long totalSecondTime; long firstTime; long secondTime; long period = 200000; char step = 0; while(run){ if(mode == USERMODE) printf("Input: "); fgets(in, 99, stdin); sscanf(in, "%s %hu %hu", op_code, &instAddr, &topAddr); //Process input if(!strcmp(op_code, "~q")){ printf("Halting\n"); run = 0; } else if(!strcmp(op_code, "~pm")){ printMem(instAddr, topAddr); } else if(!strcmp(op_code, "~pr")){ printReg(); } else if(!strcmp(op_code, "~in")){ printf("Enter file name, followed by an address to load at: "); scanf("%s %hu", fileName, &baseAddr); puts("WARNING, make sure the base address is set correctly when assembling file"); while(getchar()!= '\n'); if(readBin(fileName, baseAddr) == -1){ printf("Entering User Input Mode"); mode = USERMODE; } } else if(!strcmp(op_code, "~run")){ regPC = instAddr; instrRun = 0; regSTAT.data &= 0xD; mode = FILEMODE; step = 0; } else if(!strcmp(op_code, "~step")){ if(instAddr != NULL) { regPC = instAddr; regSTAT.data &= 0xD; } instrRun = 0; mode = FILEMODE; step = 1; } else if(!strcmp(op_code, "~cp")){ printf("Enter period: "); scanf("%li", &period); while(getchar()!= '\n'); } else if(!strcmp(op_code, "~rm")){ freeMem(); initMem(); } else { if(mode == USERMODE) decode(op_code, instAddr); } if(mode == FILEMODE){ if(step == 0) { puts("Program started..."); } else if (step == 1) { puts("Stepping forward..."); } //Runs while HLT is off while(!(regSTAT.data & 0x2)){ //Start of file code //EXECUTE FIRST 4 BITS currentInst = readMem(regPC); clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_CLR = 1<<CLKPIN; #endif clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_SET = 1<<CLKPIN; #endif //EXECUTE SECOND 4 BITS instAddr = 0; tempAddress = 0; tempAddress = readMem(++regPC).data; instAddr |= (tempAddress << 12); clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2); #ifdef RPI GPIO_CLR = 1 <<CLKPIN; #endif clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_SET = 1<<CLKPIN; #endif //EXECUTE THIRD 4 BITS tempAddress = readMem(++regPC).data; instAddr |= (tempAddress << 8); clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_CLR = 1<<CLKPIN; #endif clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_SET = 1<<CLKPIN; #endif //EXECUTE FOURTH 4 BITS tempAddress = readMem(++regPC).data; instAddr |= (tempAddress << 4); clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_CLR = 1 <<CLKPIN; #endif clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_SET = 1<<CLKPIN; #endif //EXECUTE FIFTH 4 BITS tempAddress = readMem(++regPC).data; instAddr |= (tempAddress); regPC++; clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_CLR = 1<<CLKPIN; #endif clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_SET = 1<<CLKPIN; #endif if(currentInst.data == HLT) decode("HLT", instAddr); else if(currentInst.data == LOD) decode("LOD", instAddr); else if(currentInst.data == STR) decode("STR", instAddr); else if(currentInst.data == ADD) decode("ADD", instAddr); else if(currentInst.data == NOP) decode("NOP", instAddr); else if(currentInst.data == NND) decode("NND", instAddr); else if(currentInst.data == CXA) decode("CXA", instAddr); else if(currentInst.data == JMP) decode("JMP", instAddr); else #ifndef __MINGW32__ shutdown(UNKNOWNINSTRUCTIONERROR); #endif #ifdef __MINGW32__ shutdown_vm4(UNKNOWNINSTRUCTIONERROR); #endif clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_CLR = 1 <<CLKPIN; #endif clock_gettime(CLOCK_REALTIME, &gettime_now); firstTime = gettime_now.tv_nsec; waitForPeriod(firstTime,gettime_now,period/2 ); #ifdef RPI GPIO_SET = 1<<CLKPIN; #endif if(step == 1) { break; } } if((regSTAT.data & 0x2) && step) { puts("Computer halted"); } mode = USERMODE; if(step == 0) { puts("Program finished"); printf("Instructions run %d\n", instrRun); #ifdef RPI GPIO_CLR = 1 << CLKPIN; #endif } } } return 1; }