From 3cfd8e1da5dedecf9c306770acbc7125ec874d35 Mon Sep 17 00:00:00 2001 From: Jacob McDonnell Date: Thu, 9 May 2024 18:54:46 -0400 Subject: Move to Big Endian Binaries --- LICENSE | 0 README.md | 2 +- binwrite.c | 21 ----- makefile | 10 +- mips | Bin 17624 -> 0 bytes mips.c | 315 ------------------------------------------------------------- mips.o | Bin 11504 -> 0 bytes qdme.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++++ qdme.h | 50 ++++++++++ test.bin | Bin 32 -> 32 bytes 10 files changed, 330 insertions(+), 341 deletions(-) mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md delete mode 100644 binwrite.c mode change 100644 => 100755 makefile delete mode 100755 mips delete mode 100644 mips.c delete mode 100644 mips.o create mode 100755 qdme.c create mode 100644 qdme.h mode change 100644 => 100755 test.bin diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 370e3e6..d7b8757 --- a/README.md +++ b/README.md @@ -66,5 +66,5 @@ manually created, eventually this will change. |14 |Not Implemented Yet| |15 |Not Implemented Yet| |16 |Not Implemented Yet| -|17 |Exit with Status Code in $0| +|17 |Exit with Status Code in $a0| diff --git a/binwrite.c b/binwrite.c deleted file mode 100644 index e70edbc..0000000 --- a/binwrite.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include - -int main(void) { - uint32_t insts[] = { - 0x2008000a, // addi $t0, $zero, 10 - 0x2009000b, // addi $t1, $zero, 11 - 0x01285020, // add $t2, $t1, $t0 - 0x20020001, // addi $v0, $zero, 1 - 0x000a2020, // add $a0, $zero, $t2 - 0x0000000C, // syscall - 0x2002000a, // addi $v0, $zero, 10 - 0x0000000C, // syscall - }; - FILE *fp = fopen("test.bin", "w"); - for (size_t i = 0; i < sizeof(insts) / sizeof(insts[0]); i++) { - fwrite(insts + i, 1, 4, fp); - } - fclose(fp); - return 0; -} diff --git a/makefile b/makefile old mode 100644 new mode 100755 index e5c8228..d8e53c5 --- a/makefile +++ b/makefile @@ -1,13 +1,15 @@ CC=gcc CFLAGS=-Wall -Werror -pedantic --std=c17 -OBJS=mips.o -TARGET=mips +OBJS=qdme.o +TARGET=qdme -%.o: %.c - $(CC) $(CFLAGS) -c $@ $^ +%.o: %.c %.h + $(CC) $(CFLAGS) -c $@ $< all: $(TARGET) mips: $(OBJS) $(CC) $(CFLAGS) -o $@ $^ +clean: + rm -rf $(TARGET) diff --git a/mips b/mips deleted file mode 100755 index 3a7a0a9..0000000 Binary files a/mips and /dev/null differ diff --git a/mips.c b/mips.c deleted file mode 100644 index dcda5f7..0000000 --- a/mips.c +++ /dev/null @@ -1,315 +0,0 @@ -#include -#include -#include -#include -#include - -#define MEM_SIZE 36 -#define RA 31 -#define V0 2 -#define V1 3 -#define A0 4 -#define A1 5 -#define A2 6 -#define A3 7 -#define WORD_SIZE 4 - -typedef struct { - unsigned int op: 6; - unsigned int rs: 5; - unsigned int rt: 5; - unsigned int rd: 5; - unsigned int shamt: 5; - unsigned int func: 6; -} rtype_t; - -typedef struct { - unsigned int op: 6; - unsigned int rs: 5; - unsigned int rt: 5; - unsigned int imm: 16; -} itype_t; - -typedef struct { - unsigned int op: 6; - unsigned int addr: 26; -} jtype_t; - -typedef enum { NOP, RTYPE, ITYPE, JTYPE } type_t; - -typedef struct { - type_t type; - union { - uint32_t value; - rtype_t r; - jtype_t j; - itype_t i; - }; -} inst_t; - -uint8_t memory[MEM_SIZE] = {0}; -uint32_t pc = 0, hi = 0, lo = 0; -uint32_t regFile[32] = {0}; - -/* InstFetch: Fetch the next instruction from memory into the given - * instruction */ -void InstFetch(inst_t *inst) { - uint32_t value = 0; - memcpy(&value, memory + pc, WORD_SIZE); - switch ((value & 0xFC000000) >> 24) { - case 0: - inst->type = RTYPE; - inst->r.op = (value & 0xFC000000) >> 26; - inst->r.rs = (value & 0x03E00000) >> 21; - inst->r.rt = (value & 0x001F0000) >> 16; - inst->r.rd = (value & 0x0000F800) >> 11; - inst->r.shamt = (value & 0x000007C0) >> 6; - inst->r.func = value & 0x0000002F; - break; - case 2: - case 3: - inst->type = JTYPE; - inst->j.op = (value & 0xFC000000) >> 26; - inst->j.addr = value & 0X03FFFFFF; - break; - default: - inst->type = ITYPE; - inst->i.op = (value & 0xFC000000) >> 26; - inst->i.rs = (value & 0x03E00000) >> 21; - inst->i.rt = (value & 0x001F0000) >> 16; - inst->i.imm = value & 0x0000FFFF; - break; - } - if (inst->value == 0) { - inst->type = NOP; - } - pc += WORD_SIZE; -} - -void Syscall(void) { - char c, *s; - switch (regFile[V0]) { - case 1: // print integer - printf("%d", regFile[A0]); - break; - case 2: // print float - break; - case 3: // print double - break; - case 4: // print string - printf("%s", memory + regFile[A0]); - break; - case 5: // read integer - scanf("%d", (int *)regFile + V0); - break; - case 6: // read float - break; - case 7: // read double - break; - case 8: // read string - s = (char *)calloc(regFile[A0], sizeof(char)); - fgets(s, regFile[A0], stdin); - memcpy(memory + regFile[A1], s, regFile[A0]); - free(s); - break; - case 9: // sbrk - break; - case 10: //exit - exit(0); - case 11: // print char - printf("%c", regFile[A0]); - break; - case 12: // read char - c = 0; - scanf("%c", &c); - regFile[V0] = c; - break; - case 13: // open file - break; - case 14: // read from file - break; - case 15: // write to file - break; - case 16: // close file - break; - case 17: // exit2 - exit(regFile[A0]); - } -} - -/* ExecRtype: Execute a given R-Type instruction */ -void ExecRtype(const inst_t inst) { - rtype_t r = inst.r; - uint32_t a = regFile[r.rs], b = regFile[r.rt]; - uint64_t mult = 0; - switch (r.func) { - case 32: // add - regFile[r.rd] = (signed)a + (signed)b; - break; - case 33: // addu - regFile[r.rd] = a + b; - break; - case 36: // and - regFile[r.rd] = a & b; - break; - case 37: // or - regFile[r.rd] = a | b; - break; - case 42: // slt - regFile[r.rd] = (signed)a < (signed)b; - break; - case 43: // sltu - regFile[r.rd] = a < b; - break; - case 34: // sub - regFile[r.rd] = (signed)a - (signed)b; - break; - case 35: // subu - regFile[r.rd] = a - b; - break; - case 38: // xor - regFile[r.rd] = a ^ b; - break; - case 0: // sll - regFile[r.rd] = b << r.shamt; - break; - case 3: // sra - regFile[r.rd] = (signed)b >> r.shamt; - break; - case 2: // srl - regFile[r.rd] = b >> r.shamt; - break; - case 26: // div - hi = (signed)a % (signed)b; - lo = (signed)a / (signed)b; - break; - case 27: // divu - hi = a % b; - lo = a / b; - break; - case 24: // mult - mult = (signed)a * (signed)b; - hi = (0xFFFFFFFF00000000 & mult) >> 32; - lo = 0x00000000FFFFFFFF & mult; - break; - case 25: // multu - mult = a * b; - hi = (0xFFFFFFFF00000000 & mult) >> 32; - lo = 0x00000000FFFFFFFF & mult; - break; - case 16: // MFHI - regFile[r.rd] = hi; - break; - case 18: // MFLO - regFile[r.rd] = lo; - break; - case 17: // MTHI - hi = regFile[r.rs]; - break; - case 19: // MTLO - lo = regFile[r.rs]; - break; - case 8: // jr - pc = a; - break; - case 9: // jalr - regFile[r.rd] = pc + 4; - pc = a; - break; - case 12: // syscall - Syscall(); - break; - } -} - -/* InstExec: Execute a given instruction */ -void InstExec(const inst_t inst) { - if (inst.type == NOP) { - return; - } - switch (inst.j.op) { - case 0: // R-type instruction - ExecRtype(inst); - break; - case 3: // jal - regFile[RA] = pc + 4; - /* intentional fall through */ - case 2: // j - pc = (0xF0000000 & pc ) | inst.j.addr; - break; - case 4: // beq - pc = (regFile[inst.i.rs] == regFile[inst.i.rt]) ? pc + 4 + - inst.i.imm : pc; - break; - case 5: // bne - pc = (regFile[inst.i.rs] != regFile[inst.i.rt]) ? pc + 4 + - inst.i.imm : pc; - break; - case 8: // addi - regFile[inst.i.rt] = (signed)inst.i.rs + (signed)inst.i.imm; - break; - case 9: // addiu - regFile[inst.i.rt] = inst.i.rs + inst.i.imm; - break; - case 12: // andi - regFile[inst.i.rt] = inst.i.rs & inst.i.imm; - break; - case 13: // ori - regFile[inst.i.rt] = inst.i.rs | inst.i.imm; - break; - case 14: // xori - regFile[inst.i.rt] = inst.i.rs ^ inst.i.imm; - break; - case 10: // slti - regFile[inst.i.rt] = (signed)inst.i.rs < (signed)inst.i.imm; - break; - case 11: // sltiu - regFile[inst.i.rt] = inst.i.rs < inst.i.imm; - break; - case 15: // lui - regFile[inst.i.rt] = inst.i.imm << 16; - break; - case 35: // lw - memcpy(regFile + inst.i.rs, memory + inst.i.rt + inst.i.imm, - WORD_SIZE); - break; - case 43: // sw - memcpy(memory + inst.i.rt + inst.i.imm, regFile + inst.i.rs, - WORD_SIZE); - break; - } -} - -void CycleCpu(void) { - inst_t instFetch, instExec; - memset(&instFetch, 0, sizeof(inst_t)); - memset(&instExec, 0, sizeof(inst_t)); - while (pc < MEM_SIZE) { - InstFetch(&instFetch); - InstExec(instExec); - instExec = instFetch; - } -} - -int LoadBinary(const char * const path) { - FILE *fp = fopen(path, "r"); - if (fp == NULL) { - perror("LoadBinary"); - return -1; - } - int8_t byte = 0; - size_t i = 0; - while ((byte = fgetc(fp)) != EOF && i < MEM_SIZE) { - memory[i++] = byte; - } - fclose(fp); - return 0; -} - -int main(int argc, char *argv[]) { - if (LoadBinary(*++argv) == -1) { - return -1; - } - CycleCpu(); -} - diff --git a/mips.o b/mips.o deleted file mode 100644 index 1a23fe9..0000000 Binary files a/mips.o and /dev/null differ diff --git a/qdme.c b/qdme.c new file mode 100755 index 0000000..c957609 --- /dev/null +++ b/qdme.c @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include "qdme.h" + +uint8_t memory[MEM_SIZE] = {0}; +uint32_t pc = 0, hi = 0, lo = 0; +uint32_t regFile[32] = {0}; + +/* InstFetch: Fetch the next instruction from memory into the given + * instruction */ +void InstFetch(inst_t *inst) { + uint32_t value = 0; + memcpy(&value, memory + pc, WORD_SIZE); + value = ntohl(value); + switch ((value & 0xFC000000) >> 24) { + case 0: + inst->type = RTYPE; + inst->r.op = (value & 0xFC000000) >> 26; + inst->r.rs = (value & 0x03E00000) >> 21; + inst->r.rt = (value & 0x001F0000) >> 16; + inst->r.rd = (value & 0x0000F800) >> 11; + inst->r.shamt = (value & 0x000007C0) >> 6; + inst->r.func = value & 0x0000002F; + break; + case 2: + case 3: + inst->type = JTYPE; + inst->j.op = (value & 0xFC000000) >> 26; + inst->j.addr = value & 0X03FFFFFF; + break; + default: + inst->type = ITYPE; + inst->i.op = (value & 0xFC000000) >> 26; + inst->i.rs = (value & 0x03E00000) >> 21; + inst->i.rt = (value & 0x001F0000) >> 16; + inst->i.imm = value & 0x0000FFFF; + break; + } + if (inst->value == 0) { + inst->type = NOP; + } + pc += WORD_SIZE; +} + +void Syscall(void) { + char c, *s; + switch (regFile[V0]) { + case 1: // print integer + printf("%d", regFile[A0]); + break; + case 2: // print float + break; + case 3: // print double + break; + case 4: // print string + printf("%s", memory + regFile[A0]); + break; + case 5: // read integer + scanf("%d", (int *)regFile + V0); + break; + case 6: // read float + break; + case 7: // read double + break; + case 8: // read string + s = (char *)calloc(regFile[A0], sizeof(char)); + fgets(s, regFile[A0], stdin); + memcpy(memory + regFile[A1], s, regFile[A0]); + free(s); + break; + case 9: // sbrk + break; + case 10: //exit + exit(0); + case 11: // print char + printf("%c", regFile[A0]); + break; + case 12: // read char + c = 0; + scanf("%c", &c); + regFile[V0] = c; + break; + case 13: // open file + break; + case 14: // read from file + break; + case 15: // write to file + break; + case 16: // close file + break; + case 17: // exit2 + exit(regFile[A0]); + } +} + +/* ExecRtype: Execute a given R-Type instruction */ +void ExecRtype(const inst_t inst) { + rtype_t r = inst.r; + uint32_t a = regFile[r.rs], b = regFile[r.rt]; + uint64_t mult = 0; + switch (r.func) { + case 32: // add + regFile[r.rd] = (signed)a + (signed)b; + break; + case 33: // addu + regFile[r.rd] = a + b; + break; + case 36: // and + regFile[r.rd] = a & b; + break; + case 37: // or + regFile[r.rd] = a | b; + break; + case 42: // slt + regFile[r.rd] = (signed)a < (signed)b; + break; + case 43: // sltu + regFile[r.rd] = a < b; + break; + case 34: // sub + regFile[r.rd] = (signed)a - (signed)b; + break; + case 35: // subu + regFile[r.rd] = a - b; + break; + case 38: // xor + regFile[r.rd] = a ^ b; + break; + case 0: // sll + regFile[r.rd] = b << r.shamt; + break; + case 3: // sra + regFile[r.rd] = (signed)b >> r.shamt; + break; + case 2: // srl + regFile[r.rd] = b >> r.shamt; + break; + case 26: // div + hi = (signed)a % (signed)b; + lo = (signed)a / (signed)b; + break; + case 27: // divu + hi = a % b; + lo = a / b; + break; + case 24: // mult + mult = (signed)a * (signed)b; + hi = (0xFFFFFFFF00000000 & mult) >> 32; + lo = 0x00000000FFFFFFFF & mult; + break; + case 25: // multu + mult = a * b; + hi = (0xFFFFFFFF00000000 & mult) >> 32; + lo = 0x00000000FFFFFFFF & mult; + break; + case 16: // MFHI + regFile[r.rd] = hi; + break; + case 18: // MFLO + regFile[r.rd] = lo; + break; + case 17: // MTHI + hi = regFile[r.rs]; + break; + case 19: // MTLO + lo = regFile[r.rs]; + break; + case 8: // jr + pc = a; + break; + case 9: // jalr + regFile[r.rd] = pc + 4; + pc = a; + break; + case 12: // syscall + Syscall(); + break; + } +} + +/* InstExec: Execute a given instruction */ +void InstExec(const inst_t inst) { + if (inst.type == NOP) { + return; + } + switch (inst.j.op) { + case 0: // R-type instruction + ExecRtype(inst); + break; + case 3: // jal + regFile[RA] = pc + 4; + /* intentional fall through */ + case 2: // j + pc = (0xF0000000 & pc ) | inst.j.addr; + break; + case 4: // beq + pc = (regFile[inst.i.rs] == regFile[inst.i.rt]) ? pc + 4 + + inst.i.imm : pc; + break; + case 5: // bne + pc = (regFile[inst.i.rs] != regFile[inst.i.rt]) ? pc + 4 + + inst.i.imm : pc; + break; + case 8: // addi + regFile[inst.i.rt] = (signed)inst.i.rs + (signed)inst.i.imm; + break; + case 9: // addiu + regFile[inst.i.rt] = inst.i.rs + inst.i.imm; + break; + case 12: // andi + regFile[inst.i.rt] = inst.i.rs & inst.i.imm; + break; + case 13: // ori + regFile[inst.i.rt] = inst.i.rs | inst.i.imm; + break; + case 14: // xori + regFile[inst.i.rt] = inst.i.rs ^ inst.i.imm; + break; + case 10: // slti + regFile[inst.i.rt] = (signed)inst.i.rs < (signed)inst.i.imm; + break; + case 11: // sltiu + regFile[inst.i.rt] = inst.i.rs < inst.i.imm; + break; + case 15: // lui + regFile[inst.i.rt] = inst.i.imm << 16; + break; + case 35: // lw + memcpy(regFile + inst.i.rs, memory + inst.i.rt + inst.i.imm, + WORD_SIZE); + break; + case 43: // sw + memcpy(memory + inst.i.rt + inst.i.imm, regFile + inst.i.rs, + WORD_SIZE); + break; + } +} + +void CycleCpu(void) { + inst_t instFetch, instExec; + memset(&instFetch, 0, sizeof(inst_t)); + memset(&instExec, 0, sizeof(inst_t)); + while (pc < MEM_SIZE) { + InstFetch(&instFetch); + InstExec(instExec); + instExec = instFetch; + } +} + +int LoadBinary(const char * const path) { + FILE *fp = fopen(path, "r"); + if (fp == NULL) { + perror("LoadBinary"); + return -1; + } + int8_t byte = 0; + size_t i = 0; + while ((byte = fgetc(fp)) != EOF && i < MEM_SIZE) { + memory[i++] = byte; + } + fclose(fp); + return 0; +} + +int main(int argc, char *argv[]) { + if (LoadBinary(*++argv) == -1) { + return -1; + } + CycleCpu(); +} + diff --git a/qdme.h b/qdme.h new file mode 100644 index 0000000..50652f0 --- /dev/null +++ b/qdme.h @@ -0,0 +1,50 @@ +#ifndef _QDME_H +#define _QDME_H + +#include + +#define MEM_SIZE 36 +#define RA 31 +#define V0 2 +#define V1 3 +#define A0 4 +#define A1 5 +#define A2 6 +#define A3 7 +#define WORD_SIZE 4 + +typedef struct { + unsigned int op: 6; + unsigned int rs: 5; + unsigned int rt: 5; + unsigned int rd: 5; + unsigned int shamt: 5; + unsigned int func: 6; +} rtype_t; + +typedef struct { + unsigned int op: 6; + unsigned int rs: 5; + unsigned int rt: 5; + unsigned int imm: 16; +} itype_t; + +typedef struct { + unsigned int op: 6; + unsigned int addr: 26; +} jtype_t; + +typedef enum { NOP, RTYPE, ITYPE, JTYPE } type_t; + +typedef struct { + type_t type; + union { + rtype_t r; + jtype_t j; + itype_t i; + uint32_t value; + }; +} inst_t; + +#endif + diff --git a/test.bin b/test.bin old mode 100644 new mode 100755 index cb24090..2cf7b8d Binary files a/test.bin and b/test.bin differ -- cgit v1.2.3