diff --git a/Makefile b/Makefile index d4cde18..a443d17 100755 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ RM = rm -f SUBMISSIONZIPFILE = submission.zip ZIP = zip -9 # Add the names of your own files with a .o suffix to link them into the VM -VM_OBJECTS = vm.o machine_main.o machine.o \ +VM_OBJECTS = vm.o \ machine_types.o instruction.o bof.o \ regname.o utilities.o TESTS = vm_test0.bof vm_test1.bof vm_test2.bof vm_test3.bof \ diff --git a/bof.o b/bof.o new file mode 100644 index 0000000..d44853e Binary files /dev/null and b/bof.o differ diff --git a/instruction.c b/instruction.c index 28e1383..eb0f3f4 100755 --- a/instruction.c +++ b/instruction.c @@ -16,33 +16,48 @@ extern char *strdup(const char *s); // space to hold one instruction's assembly language form static char instr_buf[INSTR_BUF_SIZE]; -// Return the instruction type of the given opcode -instr_type instruction_type(bin_instr_t i) { - switch (i.comp.op) { // need to pretend a type to read the op field - case COMP_O: - return comp_instr_type; - break; - case OTHC_O: - if (i.othc.func == SYS_F) { - return syscall_instr_type; - } else { - assert(i.othc.op != COMP_O); - assert(i.othc.func != NOP_F); - return other_comp_instr_type; +// Return the instruction type of the given opcode +instr_type instruction_type(bin_instr_t i) +{ + switch (i.comp.op) + { // need to pretend a type to read the op field + case COMP_O: + return comp_instr_type; + break; + case OTHC_O: + if (i.othc.func == SYS_F) + { + return syscall_instr_type; + } + else + { + assert(i.othc.op != COMP_O); + assert(i.othc.func != NOP_F); + return other_comp_instr_type; + } + break; + case ADDI_O: + case ANDI_O: + case BORI_O: + case NORI_O: + case XORI_O: + case BEQ_O: + case BGEZ_O: + case BGTZ_O: + case BLEZ_O: + case BLTZ_O: + case BNE_O: + return immed_instr_type; + break; + case JMPA_O: + case CALL_O: + case RTN_O: + return jump_instr_type; + break; + default: + return error_instr_type; + break; } - break; - case ADDI_O: case ANDI_O: case BORI_O: case NORI_O: case XORI_O: - case BEQ_O: case BGEZ_O: case BGTZ_O: case BLEZ_O: case BLTZ_O: - case BNE_O: - return immed_instr_type; - break; - case JMPA_O: case CALL_O: case RTN_O: - return jump_instr_type; - break; - default: - return error_instr_type; - break; - } } // Requires: bof is open for reading in binary @@ -50,13 +65,14 @@ instr_type instruction_type(bin_instr_t i) { // but exit with an error if there is a problem. bin_instr_t instruction_read(BOFFILE bf) { - bin_instr_t bi; - size_t rd = fread(&bi, sizeof(bi), 1, bf.fileptr); - if (rd != 1) { - bail_with_error("Cannot read instruction from %s (read %d instrs)", - bf.filename, rd); - } - return bi; + bin_instr_t bi; + size_t rd = fread(&bi, sizeof(bi), 1, bf.fileptr); + if (rd != 1) + { + bail_with_error("Cannot read instruction from %s (read %d instrs)", + bf.filename, rd); + } + return bi; } // Requires: bf is open for writing in binary @@ -64,10 +80,11 @@ bin_instr_t instruction_read(BOFFILE bf) // but exit with an error if there is a problem. static void write_bin_instr(BOFFILE bf, bin_instr_t i) { - size_t wr = fwrite(&i, sizeof(i), 1, bf.fileptr); - if (wr != 1) { - bail_with_error("Cannot write binary instr to %s", bf.filename); - } + size_t wr = fwrite(&i, sizeof(i), 1, bf.fileptr); + if (wr != 1) + { + bail_with_error("Cannot write binary instr to %s", bf.filename); + } } // Requires: bof is open for writing in binary @@ -75,16 +92,16 @@ static void write_bin_instr(BOFFILE bf, bin_instr_t i) // but exit with an error if there is a problem. void instruction_write_compInstr(BOFFILE bf, comp_instr_t ci) { - bin_instr_t bi; - bi.comp = ci; - assert(bi.comp.op == ci.op); - assert(bi.comp.rt == ci.rt); - assert(bi.comp.ot == ci.ot); - assert(bi.comp.rs == ci.rs); - assert(bi.comp.os == ci.os); - assert(bi.comp.func == ci.func); - assert(bi.comp.func != NOP_F || bi.comp.op == COMP_O); - write_bin_instr(bf, bi); + bin_instr_t bi; + bi.comp = ci; + assert(bi.comp.op == ci.op); + assert(bi.comp.rt == ci.rt); + assert(bi.comp.ot == ci.ot); + assert(bi.comp.rs == ci.rs); + assert(bi.comp.os == ci.os); + assert(bi.comp.func == ci.func); + assert(bi.comp.func != NOP_F || bi.comp.op == COMP_O); + write_bin_instr(bf, bi); } // Requires: bof is open for writing in binary @@ -92,16 +109,16 @@ void instruction_write_compInstr(BOFFILE bf, comp_instr_t ci) // but exit with an error if there is a problem. void instruction_write_otherCompInstr(BOFFILE bf, other_comp_instr_t oci) { - bin_instr_t bi; - bi.othc = oci; + bin_instr_t bi; + bi.othc = oci; - assert(bi.othc.op == oci.op); - assert(bi.othc.reg == oci.reg); - assert(bi.othc.offset == oci.offset); - assert(bi.othc.arg == oci.arg); - assert(bi.othc.func == oci.func); + assert(bi.othc.op == oci.op); + assert(bi.othc.reg == oci.reg); + assert(bi.othc.offset == oci.offset); + assert(bi.othc.arg == oci.arg); + assert(bi.othc.func == oci.func); - write_bin_instr(bf, bi); + write_bin_instr(bf, bi); } // Requires: bof is open for writing in binary @@ -109,16 +126,16 @@ void instruction_write_otherCompInstr(BOFFILE bf, other_comp_instr_t oci) // but exit with an error if there is a problem. void instruction_write_syscallInstr(BOFFILE bf, syscall_instr_t si) { - bin_instr_t bi; - bi.syscall = si; - /* - assert(bi.syscall.op == OTHC_O); - assert(bi.syscall.reg == si.reg); - assert(bi.syscall.offset == si.offset); - assert(bi.syscall.code == si.code); - assert(bi.syscall.func == SYS_F); - */ - write_bin_instr(bf, bi); + bin_instr_t bi; + bi.syscall = si; + /* + assert(bi.syscall.op == OTHC_O); + assert(bi.syscall.reg == si.reg); + assert(bi.syscall.offset == si.offset); + assert(bi.syscall.code == si.code); + assert(bi.syscall.func == SYS_F); + */ + write_bin_instr(bf, bi); } // Requires: bof is open for writing in binary @@ -126,15 +143,15 @@ void instruction_write_syscallInstr(BOFFILE bf, syscall_instr_t si) // but exit with an error if there is a problem. void instruction_write_uimmedInstr(BOFFILE bf, uimmed_instr_t ui) { - bin_instr_t bi; - bi.uimmed = ui; - /* - assert(bi.uimmed.op == op); - assert(bi.uimmed.reg == ui.reg); - assert(bi.uimmed.offset == ui.offset); - assert(bi.uimmed.uimmed == ui.uimmed); - */ - write_bin_instr(bf, bi); + bin_instr_t bi; + bi.uimmed = ui; + /* + assert(bi.uimmed.op == op); + assert(bi.uimmed.reg == ui.reg); + assert(bi.uimmed.offset == ui.offset); + assert(bi.uimmed.uimmed == ui.uimmed); + */ + write_bin_instr(bf, bi); } // Requires: bof is open for writing in binary @@ -142,15 +159,15 @@ void instruction_write_uimmedInstr(BOFFILE bf, uimmed_instr_t ui) // but exit with an error if there is a problem. void instruction_write_immedInstr(BOFFILE bf, immed_instr_t ii) { - bin_instr_t bi; - bi.immed = ii; - /* - assert(bi.immed.op == op); - assert(bi.immed.reg == ii.reg); - assert(bi.immed.offset == ii.offset); - assert(bi.immed.immed == ii.immed); - */ - write_bin_instr(bf, bi); + bin_instr_t bi; + bi.immed = ii; + /* + assert(bi.immed.op == op); + assert(bi.immed.reg == ii.reg); + assert(bi.immed.offset == ii.offset); + assert(bi.immed.immed == ii.immed); + */ + write_bin_instr(bf, bi); } // Requires: bof is open for writing in binary @@ -158,72 +175,74 @@ void instruction_write_immedInstr(BOFFILE bf, immed_instr_t ii) // but exit with an error if there is a problem. void instruction_write_jumpInstr(BOFFILE bf, jump_instr_t ji) { - bin_instr_t bi; - bi.jump = ji; - /* - assert(bi.jump.op == op); - assert(bi.jump.addr == ji.addr); - */ - write_bin_instr(bf, bi); + bin_instr_t bi; + bi.jump = ji; + /* + assert(bi.jump.op == op); + assert(bi.jump.addr == ji.addr); + */ + write_bin_instr(bf, bi); } // Return the assembly language name (mnemonic) for bi -const char *instruction_mnemonic(bin_instr_t bi) { - switch (bi.comp.op) { // pretending a type is needed to get the op field - case COMP_O: - return instruction_compFunc2name(bi); - break; - case OTHC_O: - return instruction_otherCompFunc2name(bi); - break; - case ADDI_O: - return "ADDI"; - break; - case ANDI_O: - return "ANDI"; - break; - case BORI_O: - return "BORI"; - break; - case NORI_O: - return "NORI"; - break; - case XORI_O: - return "XORI"; - break; - case BEQ_O: - return "BEQ"; - break; - case BGEZ_O: - return "BGEZ"; - break; - case BGTZ_O: - return "BGTZ"; - break; - case BLEZ_O: - return "BLEZ"; - break; - case BLTZ_O: - return "BLTZ"; - break; - case BNE_O: - return "BNE"; - break; - case JMPA_O: - return "JMPA"; - break; - case CALL_O: - return "CALL"; - break; - case RTN_O: - return "RTN"; - break; - default: - bail_with_error("Unknown op code (%d) in instruction_mnemonic!", - bi.immed.op); - return NULL; // should never happen - } - return NULL; // should never happen +const char *instruction_mnemonic(bin_instr_t bi) +{ + switch (bi.comp.op) + { // pretending a type is needed to get the op field + case COMP_O: + return instruction_compFunc2name(bi); + break; + case OTHC_O: + return instruction_otherCompFunc2name(bi); + break; + case ADDI_O: + return "ADDI"; + break; + case ANDI_O: + return "ANDI"; + break; + case BORI_O: + return "BORI"; + break; + case NORI_O: + return "NORI"; + break; + case XORI_O: + return "XORI"; + break; + case BEQ_O: + return "BEQ"; + break; + case BGEZ_O: + return "BGEZ"; + break; + case BGTZ_O: + return "BGTZ"; + break; + case BLEZ_O: + return "BLEZ"; + break; + case BLTZ_O: + return "BLTZ"; + break; + case BNE_O: + return "BNE"; + break; + case JMPA_O: + return "JMPA"; + break; + case CALL_O: + return "CALL"; + break; + case RTN_O: + return "RTN"; + break; + default: + bail_with_error("Unknown op code (%d) in instruction_mnemonic!", + bi.immed.op); + return NULL; // should never happen + } + return NULL; // should never happen } static char address_comment_buf[512]; @@ -232,335 +251,373 @@ static char address_comment_buf[512]; // "# target is word address %u" // that uses the formAddress function to get the proper address static const char *instruction_formAddress_comment(address_type addr, - address_type a) + address_type a) { - address_type actual = machine_types_formAddress(addr, a); - sprintf(address_comment_buf, "# target is word address %u", - actual); - return strdup(address_comment_buf); + address_type actual = machine_types_formAddress(addr, a); + sprintf(address_comment_buf, "# target is word address %u", + actual); + return strdup(address_comment_buf); } - // Return a string containing the assembly language form of instr, // which is found at address addr const char *instruction_assembly_form(address_type addr, - bin_instr_t instr) + bin_instr_t instr) { - char *buf = instr_buf; + char *buf = instr_buf; - // put in the mnemonic for the instruction - int cwr = sprintf(buf, "%s ", instruction_mnemonic(instr)); - // point buf to the null char that was printed into instr_buf - buf += cwr; + // put in the mnemonic for the instruction + int cwr = sprintf(buf, "%s ", instruction_mnemonic(instr)); + // point buf to the null char that was printed into instr_buf + buf += cwr; - instr_type it = instruction_type(instr); - switch (it) { - case comp_instr_type: - switch (instr.comp.func) { - case NOP_F: - // no arguments for NOP! - break; - case ADD_F: case SUB_F: case CPW_F: - case AND_F: case BOR_F: case NOR_F: case XOR_F: - case SCA_F: case LWI_F: case NEG_F: - sprintf(buf, "%s, %hd, %s, %hd", - regname_get(instr.comp.rt), - instr.comp.ot, - regname_get(instr.comp.rs), - instr.comp.os); - break; - case LWR_F: - sprintf(buf, "%s, %s, %hd", - regname_get(instr.comp.rt), - regname_get(instr.comp.rs), - instr.comp.os); - break; - case SWR_F: - sprintf(buf, "%s, %hd, %s", - regname_get(instr.comp.rt), - instr.comp.ot, - regname_get(instr.comp.rs)); - break; - default: - bail_with_error("Unknown computational instruction function (%d) for mnemonic %s!", - instr.comp.func, buf); - break; - } - break; - case other_comp_instr_type: - assert(instr.othc.op == OTHC_O); - switch (instr.othc.func) { - case LIT_F: - sprintf(buf, "%s, %hd, %hd", regname_get(instr.othc.reg), - instr.othc.offset, instr.othc.arg); - break; - case ARI_F: case SRI_F: - sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), - instr.othc.arg); - break; - case MUL_F: case DIV_F: case CFHI_F: case CFLO_F: case JMP_F: - case CSI_F: - sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), - instr.othc.offset); - break; - case SLL_F: case SRL_F: - sprintf(buf, "%s, %hd, %hu", regname_get(instr.othc.reg), - instr.othc.offset, instr.othc.arg); - break; - case JREL_F: - sprintf(buf, "%hd\t%s", instr.othc.arg, - instruction_formAddress_comment(addr, - addr+instr.othc.arg)); - break; - default: - bail_with_error("Unknown other computational instruction function (%d)!", - instr.comp.func); - break; - } - break; - case immed_instr_type: - switch (instr.immed.op) { - case ADDI_O: - sprintf(buf, "%s, %hd, %hd", regname_get(instr.immed.reg), - instr.immed.offset, instr.immed.immed); - break; - case ANDI_O: case BORI_O: case NORI_O: case XORI_O: - sprintf(buf, "%s, %hd, 0x%hx", regname_get(instr.immed.reg), - instr.immed.offset, instr.immed.immed); - break; - case BEQ_O: case BGEZ_O: case BGTZ_O: - case BLEZ_O: case BLTZ_O: case BNE_O: - sprintf(buf, "%s, %hd, %hd\t%s", regname_get(instr.immed.reg), - instr.immed.offset, instr.immed.immed, - instruction_formAddress_comment(addr, - addr+instr.immed.immed)); - break; - default: - bail_with_error("Unknown immediate type instruction opcode (%d)!", - instr.immed.op); - break; - } - break; - case jump_instr_type: - switch (instr.jump.op) { - case JMPA_O: case CALL_O: - sprintf(buf, "%u\t%s", instr.jump.addr, - instruction_formAddress_comment(addr, instr.jump.addr)); - break; - case RTN_O: - // no arguments in this case - break; + instr_type it = instruction_type(instr); + switch (it) + { + case comp_instr_type: + switch (instr.comp.func) + { + case NOP_F: + // no arguments for NOP! + break; + case ADD_F: + case SUB_F: + case CPW_F: + case AND_F: + case BOR_F: + case NOR_F: + case XOR_F: + case SCA_F: + case LWI_F: + case NEG_F: + sprintf(buf, "%s, %hd, %s, %hd", + regname_get(instr.comp.rt), + instr.comp.ot, + regname_get(instr.comp.rs), + instr.comp.os); + break; + case LWR_F: + sprintf(buf, "%s, %s, %hd", + regname_get(instr.comp.rt), + regname_get(instr.comp.rs), + instr.comp.os); + break; + case SWR_F: + sprintf(buf, "%s, %hd, %s", + regname_get(instr.comp.rt), + instr.comp.ot, + regname_get(instr.comp.rs)); + break; + default: + bail_with_error("Unknown computational instruction function (%d) for mnemonic %s!", + instr.comp.func, buf); + break; + } + break; + case other_comp_instr_type: + assert(instr.othc.op == OTHC_O); + switch (instr.othc.func) + { + case LIT_F: + sprintf(buf, "%s, %hd, %hd", regname_get(instr.othc.reg), + instr.othc.offset, instr.othc.arg); + break; + case ARI_F: + case SRI_F: + sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), + instr.othc.arg); + break; + case MUL_F: + case DIV_F: + case CFHI_F: + case CFLO_F: + case JMP_F: + case CSI_F: + sprintf(buf, "%s, %hd", regname_get(instr.othc.reg), + instr.othc.offset); + break; + case SLL_F: + case SRL_F: + sprintf(buf, "%s, %hd, %hu", regname_get(instr.othc.reg), + instr.othc.offset, instr.othc.arg); + break; + case JREL_F: + sprintf(buf, "%hd\t%s", instr.othc.arg, + instruction_formAddress_comment(addr, + addr + instr.othc.arg)); + break; + default: + bail_with_error("Unknown other computational instruction function (%d)!", + instr.comp.func); + break; + } + break; + case immed_instr_type: + switch (instr.immed.op) + { + case ADDI_O: + sprintf(buf, "%s, %hd, %hd", regname_get(instr.immed.reg), + instr.immed.offset, instr.immed.immed); + break; + case ANDI_O: + case BORI_O: + case NORI_O: + case XORI_O: + sprintf(buf, "%s, %hd, 0x%hx", regname_get(instr.immed.reg), + instr.immed.offset, instr.immed.immed); + break; + case BEQ_O: + case BGEZ_O: + case BGTZ_O: + case BLEZ_O: + case BLTZ_O: + case BNE_O: + sprintf(buf, "%s, %hd, %hd\t%s", regname_get(instr.immed.reg), + instr.immed.offset, instr.immed.immed, + instruction_formAddress_comment(addr, + addr + instr.immed.immed)); + break; + default: + bail_with_error("Unknown immediate type instruction opcode (%d)!", + instr.immed.op); + break; + } + break; + case jump_instr_type: + switch (instr.jump.op) + { + case JMPA_O: + case CALL_O: + sprintf(buf, "%u\t%s", instr.jump.addr, + instruction_formAddress_comment(addr, instr.jump.addr)); + break; + case RTN_O: + // no arguments in this case + break; + default: + bail_with_error("Unknown jump type instruction opcode (%d)!", + instr.jump.op); + break; + } + break; + case syscall_instr_type: + switch (instr.syscall.code) + { + case exit_sc: + sprintf(buf, "%hd", instr.syscall.offset); + break; + case print_str_sc: + case print_char_sc: + case read_char_sc: + sprintf(buf, "%s, %hd", regname_get(instr.syscall.reg), + instr.syscall.offset); + break; + case start_tracing_sc: + case stop_tracing_sc: + // no arguments, so nothing to do! + break; + } + break; default: - bail_with_error("Unknown jump type instruction opcode (%d)!", - instr.jump.op); - break; - } - break; - case syscall_instr_type: - switch (instr.syscall.code) { - case exit_sc: - sprintf(buf, "%hd", instr.syscall.offset); - break; - case print_str_sc: case print_char_sc: case read_char_sc: - sprintf(buf, "%s, %hd", regname_get(instr.syscall.reg), - instr.syscall.offset); - break; - case start_tracing_sc: case stop_tracing_sc: - // no arguments, so nothing to do! - break; + bail_with_error("Unknown instruction type (%d) in instruction_assembly_form!", + it); + break; } - break; - default: - bail_with_error("Unknown instruction type (%d) in instruction_assembly_form!", - it); - break; - } - return instr_buf; + return instr_buf; } // Requires: out is open and writable FILE // print the header of the instruction output table on out -void instruction_print_table_heading(FILE *out) { - fprintf(out, "%s %s\n", "Address", "Instruction"); +void instruction_print_table_heading(FILE *out) +{ + fprintf(out, "%s %s\n", "Address", "Instruction"); } // Requires: out is an open FILE, and instr is found at address addr. // Print addr on out, ": ", then the instruction's symbolic // (assembly language) form, and finally a newline character (all on one line) -void instruction_print(FILE *out, address_type addr, bin_instr_t instr) { - fprintf(out, "%8u: %s\n", addr, instruction_assembly_form(addr, instr)); +void instruction_print(FILE *out, address_type addr, bin_instr_t instr) +{ + fprintf(out, "%8u: %s\n", addr, instruction_assembly_form(addr, instr)); } // Return the mnemonic for the given system call code const char *instruction_syscall_mnemonic(syscall_type code) { - switch (code) { - case exit_sc: - return "EXIT"; - break; - case print_str_sc: - return "PSTR"; - break; - case print_char_sc: - return "PCH"; - break; - case read_char_sc: - return "RCH"; - break; - case start_tracing_sc: - return "STRA"; - break; - case stop_tracing_sc: - return "NOTR"; - break; - default: - bail_with_error("Unknown code (%u) in instruction_syscall_mnemonic", - code); - return "NEVERHAPPENS"; - break; - } + switch (code) + { + case exit_sc: + return "EXIT"; + break; + case print_str_sc: + return "PSTR"; + break; + case print_char_sc: + return "PCH"; + break; + case read_char_sc: + return "RCH"; + break; + case start_tracing_sc: + return "STRA"; + break; + case stop_tracing_sc: + return "NOTR"; + break; + default: + bail_with_error("Unknown code (%u) in instruction_syscall_mnemonic", + code); + return "NEVERHAPPENS"; + break; + } } // Requires: instr is a SYSCALL instruction // (i.e., instr.syscall.op == OTHC_O and instr.syscall.func == SYS_F). // Return the code field that tells what kind of system call is being made -syscall_type instruction_syscall_number(bin_instr_t instr) { - assert(instr.syscall.op == OTHC_O && instr.syscall.func == SYS_F); - return instr.syscall.code; +syscall_type instruction_syscall_number(bin_instr_t instr) +{ + assert(instr.syscall.op == OTHC_O && instr.syscall.func == SYS_F); + return instr.syscall.code; } // Requires: bi is a computational instruction (bi.comp.op == COMP_O). // Return a string giving the assembly language mnemonic for bi's operation -const char *instruction_compFunc2name(bin_instr_t bi) { - assert(bi.comp.op == COMP_O); - switch (bi.comp.func) { - case NOP_F: - return "NOP"; - break; - case ADD_F: - return "ADD"; - break; - case SUB_F: - return "SUB"; - break; - case CPW_F: - return "CPW"; - break; - case AND_F: - return "AND"; - break; - case BOR_F: - return "BOR"; - break; - case NOR_F: - return "NOR"; - break; - case XOR_F: - return "XOR"; - break; - case LWR_F: - return "LWR"; - break; - case SWR_F: - return "SWR"; - break; - case SCA_F: - return "SCA"; - break; - case LWI_F: - return "LWI"; - break; - case NEG_F: - return "NEG"; - break; - default: - bail_with_error("Unknown function code (%d) in instruction_compFunc2name", - bi.comp.func); - break; - } - return NULL; // should never happen +const char *instruction_compFunc2name(bin_instr_t bi) +{ + assert(bi.comp.op == COMP_O); + switch (bi.comp.func) + { + case NOP_F: + return "NOP"; + break; + case ADD_F: + return "ADD"; + break; + case SUB_F: + return "SUB"; + break; + case CPW_F: + return "CPW"; + break; + case AND_F: + return "AND"; + break; + case BOR_F: + return "BOR"; + break; + case NOR_F: + return "NOR"; + break; + case XOR_F: + return "XOR"; + break; + case LWR_F: + return "LWR"; + break; + case SWR_F: + return "SWR"; + break; + case SCA_F: + return "SCA"; + break; + case LWI_F: + return "LWI"; + break; + case NEG_F: + return "NEG"; + break; + default: + bail_with_error("Unknown function code (%d) in instruction_compFunc2name", + bi.comp.func); + break; + } + return NULL; // should never happen } // Requires: bi is an other computational instruction (bi.othc.op == OTHC_O). // Return a string giving the assembly language mnemonic for bi's operation -const char *instruction_otherCompFunc2name(bin_instr_t bi) { - assert(bi.othc.op == OTHC_O); - switch (bi.othc.func) { - case LIT_F: - return "LIT"; - break; - case ARI_F: - return "ARI"; - break; - case SRI_F: - return "SRI"; - break; - case MUL_F: - return "MUL"; - break; - case DIV_F: - return "DIV"; - break; - case CFHI_F: - return "CFHI"; - break; - case CFLO_F: - return "CFLO"; - break; - case SLL_F: - return "SLL"; - break; - case SRL_F: - return "SRL"; - break; - case JMP_F: - return "JMP"; - break; - case CSI_F: - return "CSI"; - break; - case JREL_F: - return "JREL"; - break; - case SYS_F: - return instruction_syscall_mnemonic(instruction_syscall_number(bi)); - break; - default: - bail_with_error("Unknown function code (%d) in instruction_otherCompFunc2name", - bi.comp.func); - break; - } - return NULL; // should never happen +const char *instruction_otherCompFunc2name(bin_instr_t bi) +{ + assert(bi.othc.op == OTHC_O); + switch (bi.othc.func) + { + case LIT_F: + return "LIT"; + break; + case ARI_F: + return "ARI"; + break; + case SRI_F: + return "SRI"; + break; + case MUL_F: + return "MUL"; + break; + case DIV_F: + return "DIV"; + break; + case CFHI_F: + return "CFHI"; + break; + case CFLO_F: + return "CFLO"; + break; + case SLL_F: + return "SLL"; + break; + case SRL_F: + return "SRL"; + break; + case JMP_F: + return "JMP"; + break; + case CSI_F: + return "CSI"; + break; + case JREL_F: + return "JREL"; + break; + case SYS_F: + return instruction_syscall_mnemonic(instruction_syscall_number(bi)); + break; + default: + bail_with_error("Unknown function code (%d) in instruction_otherCompFunc2name", + bi.comp.func); + break; + } + return NULL; // should never happen } // Requires: toknum is the token number of a system call operation // Return the system call type corresponding to the given token number syscall_type instruction_token2SyscallCode(int toknum) { - switch (toknum) { - case exitopsym: - return exit_sc; - break; - case pstropsym: - return print_str_sc; - break; - case pchopsym: - return print_char_sc; - break; - case rchopsym: - return read_char_sc; - break; - case straopsym: - return start_tracing_sc; - break; - case notropsym: - return stop_tracing_sc; - break; - default: - bail_with_error("Unlnown token type in instruction_token2SyscallCode: %d", - toknum); - return 0; // should never happen - break; - } + switch (toknum) + { + case exitopsym: + return exit_sc; + break; + case pstropsym: + return print_str_sc; + break; + case pchopsym: + return print_char_sc; + break; + case rchopsym: + return read_char_sc; + break; + case straopsym: + return start_tracing_sc; + break; + case notropsym: + return stop_tracing_sc; + break; + default: + bail_with_error("Unlnown token type in instruction_token2SyscallCode: %d", + toknum); + return 0; // should never happen + break; + } } diff --git a/instruction.o b/instruction.o new file mode 100644 index 0000000..eae1c28 Binary files /dev/null and b/instruction.o differ diff --git a/machine_types.o b/machine_types.o new file mode 100644 index 0000000..24a68ce Binary files /dev/null and b/machine_types.o differ diff --git a/regname.o b/regname.o new file mode 100644 index 0000000..42dab6e Binary files /dev/null and b/regname.o differ diff --git a/utilities.o b/utilities.o new file mode 100644 index 0000000..5292ca9 Binary files /dev/null and b/utilities.o differ diff --git a/vm b/vm new file mode 100644 index 0000000..40ba1ec Binary files /dev/null and b/vm differ diff --git a/vm.c b/vm.c index 31f369a..9863956 100644 --- a/vm.c +++ b/vm.c @@ -1,12 +1,14 @@ #include #include #include +#include #include "vm.h" #include "utilities.h" #include "instruction.h" #include "bof.h" -void vm_init(VM *vm) { +void vm_init(VM *vm) +{ memset(vm->memory, 0, sizeof(vm->memory)); memset(vm->registers, 0, sizeof(vm->registers)); vm->pc = 0; @@ -14,19 +16,24 @@ void vm_init(VM *vm) { vm->lo = 0; } -void vm_load_program(VM *vm, BOFFILE bf) { +void vm_load_program(VM *vm, BOFFILE bf) +{ BOFHeader header = bof_read_header(bf); - + vm->text_length = header.text_length; + vm->data_length = header.data_length; // Load instructions - for (int i = 0; i < header.text_length; i++) { - vm->memory[header.text_start_address + i] = bof_read_word(bf); + for (int i = 0; i < header.text_length; i++) + { + vm->instructions[i] = instruction_read(bf); + // printf(" \n 1 \n"); } - + // Load data - for (int i = 0; i < header.data_length; i++) { + for (int i = 0; i < header.data_length; i++) + { vm->memory[header.data_start_address + i] = bof_read_word(bf); } - + // Set initial register values vm->pc = header.text_start_address; vm->registers[0] = header.data_start_address; // $gp @@ -34,151 +41,397 @@ void vm_load_program(VM *vm, BOFFILE bf) { vm->registers[2] = header.stack_bottom_addr; // $fp } -void vm_print_state(VM *vm) { - printf("PC: %u\n", vm->pc); - for (int i = 0; i < NUM_REGISTERS; i++) { - printf("GPR[$%s]: %d ", regname_get(i), vm->registers[i]); - if ((i + 1) % 4 == 0) printf("\n"); +void vm_print_words(VM *vm) +{ + word_type address = vm->registers[0]; // Correct access to registers array + int count = 0; // Use a counter for formatting + printf(" "); + + // Loop through memory up to the stack pointer (registers[1] = $sp) + while (address <= vm->registers[2]) + { + // Print memory address and value + printf("%6d: %d ", address, vm->memory[address]); + count++; + + // Print a newline every 4 values for readability + if (count % 5 == 0) + printf("\n"); + + // Detect blocks of zeros and print "..." + if (address < vm->registers[2] - 2 && vm->memory[address] == 0 && vm->memory[address + 1] == 0) + { + printf("\t...\t"); + // Skip over consecutive zeros + while (vm->memory[address] == 0 && vm->memory[address + 1] == 0 && address < vm->registers[2] - 1) + { + address++; + } + } + + // Move to the next memory address + address++; } printf("\n"); - // Print memory contents (you may want to limit this to relevant sections) - // ... } -void vm_run(VM *vm) { - bool tracing = true; - while (1) { - if (tracing) vm_print_state(vm); - - // Fetch instruction - bin_instr_t instr = *(bin_instr_t*)&vm->memory[vm->pc]; - - // Print the current instruction - printf("==> %u: %s\n", vm->pc, instruction_assembly_form(vm->pc, instr)); +void vm_print_state(VM *vm) +{ - // Increment PC - vm->pc++; - - // Decode and execute instruction - switch (instruction_type(instr)) { - case comp_instr_type: - vm_execute_comp_instr(vm, instr.comp); - break; - case other_comp_instr_type: - vm_execute_other_comp_instr(vm, instr.othc); - break; - case immed_instr_type: - vm_execute_immed_instr(vm, instr.immed); - break; - case jump_instr_type: - vm_execute_jump_instr(vm, instr.jump); - break; - case syscall_instr_type: - if (vm_execute_syscall(vm, instr.syscall) == 1) { - return; // Exit the VM - } - break; - default: - bail_with_error("Unknown instruction type"); - } + printf(" PC: %u\n", vm->pc); + for (int i = 0; i < NUM_REGISTERS; i++) + { + printf("GPR[$%s]: %-6d\t", regname_get(i), vm->registers[i]); + if ((i + 1) % 5 == 0) + printf("\n"); } + printf("\n"); + // Print memory contents (you may want to limit this to relevant sections) + // ... + vm_print_words(vm); } -// Helper function to get memory address -static inline word_type* get_memory_address(VM *vm, reg_num_type reg, offset_type offset) { +static inline word_type *get_memory_address(VM *vm, reg_num_type reg, offset_type offset) +{ return &vm->memory[vm->registers[reg] + machine_types_formOffset(offset)]; } -// Implement these functions next -void vm_execute_comp_instr(VM *vm, comp_instr_t instr) { +static inline word_type *get_p(VM *vm, reg_num_type reg) +{ + return &vm->memory[vm->registers[reg]]; +} + +void vm_execute_comp_instr(VM *vm, comp_instr_t instr) +{ + word_type *target = get_memory_address(vm, instr.rt, instr.ot); + word_type *sp = get_p(vm, 1); + word_type *s_os = get_memory_address(vm, instr.rs, instr.os); + word_type *rt = get_p(vm, instr.rt); + word_type *rs = get_p(vm, instr.rs); + + switch (instr.func) + { + case NOP_F: + break; + case ADD_F: + *target = *sp + *s_os; + break; + case SUB_F: + *target = *sp - *s_os; + break; + case CPW_F: + *target = *s_os; + break; + case AND_F: + *target = *sp & *s_os; + break; + + case BOR_F: + *target = *sp | *s_os; + break; + case NOR_F: + *target = ~(*sp | *s_os); + break; + case XOR_F: + *target = *sp ^ *s_os; + break; + case LWR_F: + vm->registers[instr.rt] = *s_os; + break; + + case SWR_F: + *target = vm->registers[instr.rs]; + break; + case SCA_F: + *target = vm->registers[instr.rs] + machine_types_formOffset(instr.os); + break; + case LWI_F: + *target = vm->memory[*s_os]; + break; + + case NEG_F: + *target = -(*s_os); + break; + + default: + bail_with_error("Unknown immediate instruction opcode: %d", instr.op); + } + // TODO: Implement computational instructions } +// Implement these functions next -void vm_execute_other_comp_instr(VM *vm, other_comp_instr_t instr) { - // TODO: Implement other computational instructions +void vm_execute_immed_instr(VM *vm, immed_instr_t instr) +{ + word_type *target = get_memory_address(vm, instr.reg, instr.offset); + + switch (instr.op) + { + case ADDI_O: + *target += machine_types_sgnExt(instr.immed); + break; + case ANDI_O: + *target &= machine_types_zeroExt(instr.immed); + break; + case BORI_O: + *target |= machine_types_zeroExt(instr.immed); + break; + case NORI_O: + *target = ~(*target | machine_types_zeroExt(instr.immed)); + break; + case XORI_O: + *target ^= machine_types_zeroExt(instr.immed); + break; + case BEQ_O: + if (*get_memory_address(vm, SP, 0) == *target) + { + vm->pc += machine_types_formOffset(instr.immed); + } + break; + case BGEZ_O: + if ((int)*target >= 0) + { + vm->pc += machine_types_formOffset(instr.immed); + } + break; + case BGTZ_O: + if ((int)*target > 0) + { + vm->pc += machine_types_formOffset(instr.immed); + } + break; + case BLEZ_O: + if ((int)*target <= 0) + { + vm->pc += machine_types_formOffset(instr.immed); + } + break; + case BLTZ_O: + if ((int)*target < 0) + { + vm->pc += machine_types_formOffset(instr.immed); + } + break; + case BNE_O: + if (*get_memory_address(vm, SP, 0) != *target) + { + vm->pc += machine_types_formOffset(instr.immed); + } + break; + default: + bail_with_error("Unknown immediate instruction opcode: %d", instr.op); + } } -void vm_execute_immed_instr(VM *vm, immed_instr_t instr) { +void vm_execute_other_comp_instr(VM *vm, other_comp_instr_t instr) +{ + // TODO: Implement other computational instructions word_type *target = get_memory_address(vm, instr.reg, instr.offset); - switch (instr.op) { - case ADDI_O: - *target += machine_types_sgnExt(instr.immed); - break; - case ANDI_O: - *target &= machine_types_zeroExt(instr.immed); + word_type *sp = get_p(vm, 1); + word_type *ra = get_p(vm, 7); + // word_type *s_os = get_memory_address(vm, instr.rs, instr.os); + word_type *r = get_p(vm, instr.reg); + int64_t temp; + // printf("\n\n\n\\n\n\n %d \n\n\n\n\n\n", instr.op); + switch (instr.func) + { + case LIT_F: + *target = machine_types_sgnExt(instr.arg); + break; + + case ARI_F: + vm->registers[instr.reg] += machine_types_sgnExt(instr.arg); + break; + + case SRI_F: + // printf(" I am here \n\n\n"); + vm->registers[instr.reg] -= machine_types_sgnExt(instr.arg); + break; + + case MUL_F: + + temp = (int32_t)*sp * (int32_t)*target; + + vm->hi = ((temp >> 32) & 0xFFFFFFFF); + vm->lo = (temp & 0xFFFFFFFF); + + break; + + case DIV_F: + vm->hi = *sp % *target; + vm->lo = *sp / *target; + break; + + case CFHI_F: + *target = vm->hi; + break; + + case CFLO_F: + *target = vm->lo; + break; + + case SLL_F: + *target = *sp << instr.arg; + break; + + case SRL_F: + *target = *sp >> instr.arg; + break; + + case JMP_F: + vm->pc = *target; + break; + + case CSI_F: + vm->registers[7] = vm->pc; + vm->pc = *target; + break; + + case JREL_F: + vm->pc = ((vm->pc - 1) + machine_types_formOffset(instr.arg)); + break; + + default: + bail_with_error("Unknown immediate instruction opcode: %d", instr.op); + } +} + +void vm_execute_jump_instr(VM *vm, jump_instr_t instr) +{ + switch (instr.op) + { + case JMPA_O: + vm->pc = machine_types_formAddress(vm->pc, instr.op); + break; + case CALL_O: + vm->registers[RA] = vm->pc; + vm->pc = machine_types_formAddress(vm->pc, instr.op); + break; + case RTN_O: + vm->pc = vm->registers[RA]; + break; + default: + bail_with_error("Unknown immediate instruction opcode: %d", instr.op); + } + + // TODO: Implement jump instructions +} + +void vm_run(VM *vm) +{ + bool tracing; + bool execute = true; + vm_print_state(vm); + while (execute == true) + { + // Increment PC + vm->pc++; + bin_instr_t instr = *(bin_instr_t *)&vm->instructions[vm->pc]; + + if (tracing) + { + printf("\n==> %u: %s\n", vm->pc, instruction_assembly_form(vm->pc, instr)); + vm_print_state(vm); + } + + if (instruction_type(instr) == syscall_instr_type && instr.syscall.code == 1) + { + // Terminate VM if it's an exit syscall (code == 1) + execute = false; + return; // Exit the VM + } + // Fetch instruction + + // Print the current instruction + + // Decode and execute instruction + switch (instruction_type(instr)) + { + case comp_instr_type: + + vm_execute_comp_instr(vm, instr.comp); break; - case BORI_O: - *target |= machine_types_zeroExt(instr.immed); + case other_comp_instr_type: + vm_execute_other_comp_instr(vm, instr.othc); break; - case NORI_O: - *target = ~(*target | machine_types_zeroExt(instr.immed)); + case immed_instr_type: + + vm_execute_immed_instr(vm, instr.immed); break; - case XORI_O: - *target ^= machine_types_zeroExt(instr.immed); + case jump_instr_type: + vm_execute_jump_instr(vm, instr.jump); break; - case BEQ_O: - if (*get_memory_address(vm, SP, 0) == *target) { - vm->pc += machine_types_formOffset(instr.immed); + case syscall_instr_type: + + // printf("\n\n\n\n %d \n\n\n\n\n", instr.syscall.code); + + if (instr.syscall.code == 1) + { + + execute = false; + return; // Exit the VM } - break; - case BGEZ_O: - if ((int)*target >= 0) { - vm->pc += machine_types_formOffset(instr.immed); + else if (instr.syscall.code == 2) + { + word_type *sp = get_p(vm, 1); + char *str = (char *)get_memory_address(vm, instr.syscall.reg, instr.syscall.offset); + *sp = printf("%s", str); } - break; - case BGTZ_O: - if ((int)*target > 0) { - vm->pc += machine_types_formOffset(instr.immed); + else if (instr.syscall.code == 4) + { + + word_type *sp = get_p(vm, 1); + int ch = *(get_memory_address(vm, instr.syscall.reg, instr.syscall.offset)); + *sp = fputc(ch, stdout); } - break; - case BLEZ_O: - if ((int)*target <= 0) { - vm->pc += machine_types_formOffset(instr.immed); + else if (instr.syscall.code == 5) + { + word_type *target = get_memory_address(vm, instr.syscall.reg, instr.syscall.offset); + *target = getc(stdin); } - break; - case BLTZ_O: - if ((int)*target < 0) { - vm->pc += machine_types_formOffset(instr.immed); + else if (instr.syscall.code == 2046) + { + tracing = true; } - break; - case BNE_O: - if (*get_memory_address(vm, SP, 0) != *target) { - vm->pc += machine_types_formOffset(instr.immed); + else if (instr.syscall.code == 2047) + { + tracing = false; } break; default: - bail_with_error("Unknown immediate instruction opcode: %d", instr.op); + bail_with_error("Unknown instruction type"); + } } } -void vm_execute_jump_instr(VM *vm, jump_instr_t instr) { - // TODO: Implement jump instructions -} - -int vm_execute_syscall(VM *vm, syscall_instr_t instr) { - // TODO: Implement system calls - return 0; -} +// Helper function to get memory address -void vm_print_program(VM *vm) { +void vm_print_program(VM *vm) +{ printf("Address Instruction\n"); - for (unsigned int i = 0; i < MEMORY_SIZE_IN_WORDS; i++) { - bin_instr_t instr = *(bin_instr_t*)&vm->memory[i]; - if (instruction_type(instr) == error_instr_type) break; + for (unsigned int i = 0; i < vm->text_length; i++) + { + bin_instr_t instr = *(bin_instr_t *)&vm->instructions[i]; + + if (instruction_type(instr) == error_instr_type) + break; printf("%u: %s\n", i, instruction_assembly_form(i, instr)); } } -int main(int argc, char *argv[]) { - if (argc < 2) { +int main(int argc, char *argv[]) +{ + if (argc < 2) + { bail_with_error("Usage: %s [-p] ", argv[0]); } bool print_mode = false; char *filename = argv[1]; - if (argc == 3 && strcmp(argv[1], "-p") == 0) { + if (argc == 3 && strcmp(argv[1], "-p") == 0) + { print_mode = true; filename = argv[2]; } @@ -188,9 +441,12 @@ int main(int argc, char *argv[]) { vm_init(&vm); vm_load_program(&vm, bf); - if (print_mode) { + if (print_mode) + { vm_print_program(&vm); - } else { + } + else + { vm_run(&vm); } diff --git a/vm.h b/vm.h index 97df824..4bbf060 100644 --- a/vm.h +++ b/vm.h @@ -3,22 +3,23 @@ #include "machine_types.h" #include "instruction.h" +#include "regname.h" #include "bof.h" #define MEMORY_SIZE_IN_WORDS 32768 #define NUM_REGISTERS 8 -#define GP 0 // Global Pointer -#define SP 1 // Stack Pointer -#define FP 2 // Frame Pointer -#define RA 7 // Return Address - -typedef struct { +typedef struct +{ word_type memory[MEMORY_SIZE_IN_WORDS]; word_type registers[NUM_REGISTERS]; + bin_instr_t instructions[MEMORY_SIZE_IN_WORDS]; word_type pc; word_type hi; word_type lo; + word_type data_length; + word_type text_length; + word_type memory_index; } VM; void vm_init(VM *vm); diff --git a/vm.o b/vm.o new file mode 100644 index 0000000..d6c5d0a Binary files /dev/null and b/vm.o differ diff --git a/vm_test0.myp b/vm_test0.myp new file mode 100644 index 0000000..2ad102c --- /dev/null +++ b/vm_test0.myp @@ -0,0 +1,4 @@ +Address Instruction +0: STRA +1: ADDI $sp, -1, 2 +2: EXIT 0 diff --git a/vm_test1.myp b/vm_test1.myp new file mode 100644 index 0000000..64a6c4c --- /dev/null +++ b/vm_test1.myp @@ -0,0 +1,13 @@ +Address Instruction +0: STRA +1: SRI $sp, 2 +2: ADDI $sp, 1, 1 +3: ADD $gp, 2, $sp, 1 +4: ADD $sp, 0, $gp, 2 +5: SUB $gp, 2, $gp, 2 +6: ADDI $sp, 0, 10 +7: SRI $sp, 1 +8: NOTR +9: PCH $gp, 0 +10: PCH $gp, 3 +11: EXIT 0 diff --git a/vm_test2.myp b/vm_test2.myp new file mode 100644 index 0000000..f0d4071 --- /dev/null +++ b/vm_test2.myp @@ -0,0 +1,10 @@ +Address Instruction +0: ADDI $sp, 0, 1 +1: ADD $sp, 0, $sp, 0 +2: ADDI $sp, 0, 1 +3: ADD $sp, 0, $sp, 0 +4: SLL $sp, 0, 1 +5: SRI $sp, 4 +6: PCH $gp, 1 +7: PCH $gp, 2 +8: EXIT 0 diff --git a/vm_test3.myp b/vm_test3.myp new file mode 100644 index 0000000..a31981c --- /dev/null +++ b/vm_test3.myp @@ -0,0 +1,21 @@ +Address Instruction +0: STRA +1: ADDI $sp, 0, 30 +2: SRI $sp, 1 +3: ADDI $sp, 0, 20 +4: ADDI $sp, 0, 10 +5: BNE $sp, 1, 3 # target is word address 8 +6: CALL 10 # target is word address 10 +7: JMPA 18 # target is word address 18 +8: CALL 13 # target is word address 13 +9: JMPA 18 # target is word address 18 +10: NOTR +11: PSTR $gp, 1 +12: RTN +13: NOTR +14: PSTR $gp, 2 +15: RTN +16: STRA +17: EXIT 1 +18: STRA +19: EXIT 0 diff --git a/vm_test4.myp b/vm_test4.myp new file mode 100644 index 0000000..007180b --- /dev/null +++ b/vm_test4.myp @@ -0,0 +1,41 @@ +Address Instruction +0: NOTR +1: STRA +2: ADDI $sp, 0, 5 +3: ADDI $sp, -1, 2 +4: ARI $sp, -1 +5: ADD $sp, 0, $sp, 1 +6: MUL $sp, 1 +7: SRI $sp, 1 +8: CFLO $sp, 0 +9: SUB $sp, 0, $sp, 1 +10: MUL $sp, 2 +11: SRI $sp, 1 +12: CFLO $sp, 0 +13: SRI $sp, 1 +14: CPW $sp, 0, $sp, 2 +15: DIV $sp, 4 +16: SRI $sp, 2 +17: CFLO $sp, 0 +18: CFHI $sp, 1 +19: SRI $sp, 1 +20: ADDI $sp, 0, 5 +21: BEQ $sp, 1, 2 # target is word address 23 +22: CALL 35 # target is word address 35 +23: CALL 31 # target is word address 31 +24: ARI $sp, 1 +25: SWR $sp, 0, $r4 +26: ADDI $sp, 0, 3 +27: BEQ $sp, 1, 2 # target is word address 29 +28: CALL 35 # target is word address 35 +29: CALL 31 # target is word address 31 +30: EXIT 0 +31: NOTR +32: PSTR $gp, 0 +33: STRA +34: RTN +35: NOTR +36: PSTR $gp, 1 +37: STRA +38: EXIT 1 +39: RTN diff --git a/vm_test5.myp b/vm_test5.myp new file mode 100644 index 0000000..bb9c001 --- /dev/null +++ b/vm_test5.myp @@ -0,0 +1,35 @@ +Address Instruction +0: ADDI $sp, 0, 7 +1: ADDI $sp, -1, 15 +2: ARI $sp, -1 +3: LWR $r4, $gp, 0 +4: AND $sp, 0, $sp, 0 +5: SLL $sp, 0, 5 +6: ADDI $sp, 0, -405 +7: SRI $sp, 1 +8: ADDI $sp, 0, 2 +9: SLL $sp, 0, 7 +10: SRL $sp, 0, 2 +11: ARI $sp, -1 +12: LIT $sp, 0, 11 +13: LWR $r5, $sp, 0 +14: XOR $sp, 0, $sp, 0 +15: SWR $sp, 0, $r5 +16: NEG $sp, 0, $sp, 0 +17: LIT $sp, 1, 75 +18: ARI $sp, 1 +19: BNE $sp, 1, 3 # target is word address 22 +20: CALL 26 # target is word address 26 +21: JMPA 24 # target is word address 24 +22: CALL 30 # target is word address 30 +23: JMPA 25 # target is word address 25 +24: EXIT 0 +25: EXIT 1 +26: NOTR +27: PSTR $gp, 5 +28: STRA +29: RTN +30: NOTR +31: PSTR $gp, 1 +32: STRA +33: RTN diff --git a/vm_test6.myp b/vm_test6.myp new file mode 100644 index 0000000..3178526 --- /dev/null +++ b/vm_test6.myp @@ -0,0 +1,25 @@ +Address Instruction +0: ADDI $sp, -1, 1 +1: CPW $sp, 0, $sp, -1 +2: SLL $sp, -1, 20 +3: SRI $sp, 1 +4: ADD $sp, 0, $gp, 0 +5: SRI $sp, 1 +6: LIT $sp, 0, 4 +7: LWR $r4, $sp, 0 +8: LIT $sp, 0, 14 +9: LWR $r5, $sp, 0 +10: SWR $sp, -1, $r4 +11: ARI $sp, -2 +12: SWR $sp, 0, $r5 +13: DIV $sp, 1 +14: CFLO $gp, 2 +15: CFHI $gp, 1 +16: SRI $sp, 1 +17: LIT $sp, 0, 1 +18: SLL $sp, 0, 10 +19: MUL $sp, 0 +20: CFHI $sp, -2 +21: CFLO $sp, -1 +22: SRI $sp, 2 +23: EXIT 0 diff --git a/vm_test7.myp b/vm_test7.myp new file mode 100644 index 0000000..e2f663b --- /dev/null +++ b/vm_test7.myp @@ -0,0 +1,39 @@ +Address Instruction +0: SRI $sp, 6 +1: LIT $sp, 6, 7 +2: LWR $ra, $sp, 6 +3: LIT $sp, 5, 6 +4: LWR $r6, $sp, 5 +5: LIT $sp, 4, 5 +6: LWR $r5, $sp, 4 +7: LIT $sp, 3, 4 +8: LWR $r4, $sp, 3 +9: LIT $sp, 2, 3 +10: LWR $r3, $sp, 2 +11: LIT $sp, 1, 2 +12: SCA $sp, 0, $sp, 0 +13: CALL 24 # target is word address 24 +14: SRI $sp, 1 +15: LIT $sp, 0, -1 +16: LWR $r6, $sp, 0 +17: LWR $r5, $sp, 0 +18: LWR $r4, $sp, 0 +19: LWR $r3, $sp, 0 +20: ARI $sp, 1 +21: CALL 31 # target is word address 31 +22: EXIT 0 +23: EXIT 1 +24: SRI $sp, 5 +25: SWR $sp, 4, $fp +26: SWR $sp, 3, $r3 +27: SWR $sp, 2, $r4 +28: SWR $sp, 1, $r5 +29: SWR $sp, 0, $r6 +30: RTN +31: LWR $r6, $sp, 0 +32: LWR $r5, $sp, 1 +33: LWR $r4, $sp, 2 +34: LWR $r3, $sp, 3 +35: LWR $fp, $sp, 4 +36: ARI $sp, 5 +37: RTN diff --git a/vm_test8.myp b/vm_test8.myp new file mode 100644 index 0000000..c19a801 --- /dev/null +++ b/vm_test8.myp @@ -0,0 +1,10 @@ +Address Instruction +0: LIT $sp, 0, 17 +1: LWR $r4, $sp, 0 +2: SRI $sp, 2 +3: LIT $sp, 0, 19 +4: LWR $r5, $sp, 0 +5: SCA $sp, -1, $sp, 0 +6: LWI $sp, -2, $sp, -1 +7: SRI $sp, 2 +8: EXIT 0 diff --git a/vm_test9.myp b/vm_test9.myp new file mode 100644 index 0000000..8b84b6b --- /dev/null +++ b/vm_test9.myp @@ -0,0 +1,17 @@ +Address Instruction +0: SRI $sp, 1 +1: XORI $sp, 0, 0x567a +2: LIT $sp, -1, 1658 +3: BORI $sp, -1, 0x5000 +4: BNE $sp, -1, 8 # target is word address 12 +5: ANDI $sp, 0, 0xfff +6: LIT $sp, -2, 1658 +7: BNE $sp, -2, 5 # target is word address 12 +8: NOTR +9: PSTR $gp, 0 +10: STRA +11: EXIT 0 +12: NOTR +13: PSTR $gp, 1 +14: STRA +15: EXIT 1 diff --git a/vm_testA.myp b/vm_testA.myp new file mode 100644 index 0000000..6c2f3ea --- /dev/null +++ b/vm_testA.myp @@ -0,0 +1,14 @@ +Address Instruction +0: SRI $sp, 1 +1: XORI $sp, 0, 0xffff +2: LIT $sp, -1, 255 +3: BORI $sp, -1, 0xff00 +4: BNE $sp, -1, 5 # target is word address 9 +5: NOTR +6: PSTR $gp, 0 +7: STRA +8: EXIT 0 +9: NOTR +10: PSTR $gp, 1 +11: STRA +12: EXIT 1 diff --git a/vm_testB.myp b/vm_testB.myp new file mode 100644 index 0000000..ba727fe --- /dev/null +++ b/vm_testB.myp @@ -0,0 +1,15 @@ +Address Instruction +0: SRI $sp, 1 +1: XORI $sp, 0, 0xffff +2: LIT $sp, -1, 255 +3: LIT $sp, -2, -1 +4: BORI $sp, -1, 0xff00 +5: BNE $sp, -1, 5 # target is word address 10 +6: NOTR +7: PSTR $gp, 0 +8: STRA +9: EXIT 0 +10: NOTR +11: PSTR $gp, 1 +12: STRA +13: EXIT 1