#include #include #include #include #include #include "defines.h" #include "structs.h" #include "externs.h" #include "asm.h" #include "load.ext" #include "execute.pro" #include "dump.ext" #include "main.ext" UWORD execute_program() { WORD opcode, operand1, operand2; // initialize simulated CPU memset(&Cpu, 0, sizeof(Cpu) ); // varaible initializations Cpu.pc = ModuleStart + OrgLoc; // set program counter to first instruction Halt = FALSE; opcode = 0; clrscr(); gotoxy(0,16); // main loop while( ! Halt) { fetch_instruction(&opcode,&operand1,&operand2); dispatch_instruction(opcode, operand1, operand2); } return(OK); } //////////////////////////////////////////////////////////////////////////// void fetch_instruction(WORD * opcode, WORD * op1, WORD * op2) { // fetches opcode and operands *opcode = (AssocMem[Cpu.pc] & OPCODE_MASK); *op1 = ( AssocMem[Cpu.pc] & REG_MASK); *op2 = 0; *op2 = (AssocMem[Cpu.pc+1] << 8); *op2 |= AssocMem[Cpu.pc+2]; } //////////////////////////////////////////////////////////////////////////// void dispatch_instruction(WORD opcode, WORD operand1, WORD operand2) { // dispatches instructions based on opcode switch( opcode ) { case LOD: execute_lod( operand1,operand2); break; case STO: execute_sto( operand1, operand2); break; case OUT: execute_out( operand1, operand2); break; case CALL: execute_call(operand2); break; case ADD: execute_add( operand1, operand2); break; case RET: execute_ret(); break; case JZE: execute_jze(operand2); break; case JMP: execute_jmp(operand2); break; case HLT: execute_hlt(); break; default : // catches illegal opcode, and halts clrscr(); printf("\nError. Illegal Opcode"); pause(); Halt = TRUE; Error = TRUE; break; } } //////////////////////////////////////////////////////////////////////////// void execute_lod(WORD reg, WORD eff_add) { WORD * ptr; // executes LOD instr Cpu.pc += MODE0_LENGTH; // point to next instruction ptr = &Cpu.r0; // point to base of structure ptr += reg; // offset to correct register number (*ptr) = ( AssocMem[eff_add++] >> 8); // load register with contents of effective address (*ptr) |= AssocMem[eff_add]; set_cpu_flags(*ptr); } //////////////////////////////////////////////////////////////////////////// void execute_sto(WORD reg, WORD eff_add) { WORD * ptr; // executes STO instr Cpu.pc += MODE0_LENGTH; // point to next instruction ptr = &Cpu.r0; // point to base of structure ptr += reg; // offset to correct register number AssocMem[eff_add++] = ( (*ptr) >> 8); // write contents of register to memory AssocMem[eff_add] = ( (*ptr) & 0xFF); // write contents of register to memory set_cpu_flags(*ptr); // check for negative and zero result } //////////////////////////////////////////////////////////////////////////// void execute_out(WORD count, WORD eff_add) { // executes OUT instr Cpu.pc += MODE0_LENGTH; // point to next instruction Swap.b[1] = AssocMem[eff_add]; Swap.b[0] = AssocMem[eff_add+1]; printf("Program Output %2.2X\n", Swap.w); } //////////////////////////////////////////////////////////////////////////// void execute_call(WORD subroutine_address) { // executes CALL instr Cpu.sp = (Cpu.pc + MODE0_LENGTH); // save return address Cpu.pc = subroutine_address; // point to address of subroutine } //////////////////////////////////////////////////////////////////////////// void execute_add(WORD reg, WORD address) { WORD * ptr; // executes ADD instr Cpu.pc += MODE0_LENGTH; // point to next instruction ptr = &Cpu.r0; // point to base of structure ptr += reg; // offset to correct register number Swap.b[1] = AssocMem[address]; Swap.b[0] = AssocMem[address+1]; *ptr += Swap.w; // add memory contents to register set_cpu_flags( *ptr ); } //////////////////////////////////////////////////////////////////////////// void execute_ret() { // executes RET instr Cpu.pc = Cpu.sp; // reset pc to return address // effectively does same as popping stack. Our stak is only 1 entry deep } //////////////////////////////////////////////////////////////////////////// void execute_hlt() { // executes HLT instr Halt = TRUE; gotoxy(28,23); printf("Program Halted. "); if(!Error); printf("No Errors."); pause(); } //////////////////////////////////////////////////////////////////////////// void execute_jze(WORD eff_add) { // executes JZE instr if( check_zero_flag() ) Cpu.pc = eff_add; else { Cpu.pc += MODE0_LENGTH; } } //////////////////////////////////////////////////////////////////////////// void execute_jmp(WORD eff_add) { //executes JMP instr Cpu.pc = eff_add; } //////////////////////////////////////////////////////////////////////////// void set_cpu_flags(WORD data) { // sets cpu zero and neg flags // set zero flag is zero if(data) Cpu.zero = FALSE; else Cpu.zero = TRUE; // set negative flag if negative if(data < 0) Cpu.neg = TRUE; else Cpu.neg = FALSE; } //////////////////////////////////////////////////////////////////////////// WORD check_zero_flag() { // gets status of cpu zero flag return( Cpu.zero); } //////////////////////////////////////////////////////////////////////////// WORD check_neg_flag() { // gets staus of cpu neg flag return( Cpu.neg ); } ////////////////////////////////////////////////////////////////////////////