summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xLICENSE21
-rwxr-xr-xREADME.md54
-rwxr-xr-xqdma.go140
-rwxr-xr-xtest.asm10
-rwxr-xr-xtest.binbin0 -> 32 bytes
-rwxr-xr-xtest2.asm21
6 files changed, 246 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100755
index 0000000..10f0753
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 Jacob McDonnell
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100755
index 0000000..fc47712
--- /dev/null
+++ b/README.md
@@ -0,0 +1,54 @@
+# QDMA - Quick and Dirty MIPS Assembler
+
+## Intro
+
+QDMA is a simple MIPS assembler written in Go for
+[QDME](https://github.com/JacobMcDonnell/QDME), which is my simple MIPS
+emulator. Currently this assembler can only handle standard instructions,
+which means no sections and no predefined data outside of an I-Type
+instruction.
+
+## Instructions
+
+Here is a list of supported instructions.
+
+|Instruction|Type|Action|
+|-----------|----|------|
+|add |R |rd = rs + rt|
+|addu |R |rd = rs + rt|
+|and |R |rd = rs & rt|
+|or |R |rd = rs \| rt|
+|slt |R |rd = rs < rt|
+|sltu |R |rd = rs < rt|
+|sub |R |rd = rs - rt|
+|subu |R |rd = rs - rt|
+|xor |R |rd = rs ^ rt|
+|sll |R |rd = rt << shamt|
+|sra |R |rd = rt >> shamt|
+|srl |R |rd = rt >> shamt|
+|div |R |hi = rs % rt lo = rs / rt|
+|divu |R |hi = rs % rt lo = rs / rt|
+|mult |R |hi, lo = rs * rt|
+|multu |R |hi, lo = rs * rt|
+|MFHI |R |rd = hi|
+|MFLO |R |rd = lo|
+|MTHI |R |rs = hi|
+|MTLO |R |rs = lo|
+|jr |R |pc = addr, pc = $ra|
+|jalr |R |rd = pc, pc = addr|
+|syscall |R |System Call|
+|jal |J |$ra = pc, pc = addr|
+|j |J |pc = addr|
+|beq |I | pc = (rs == rt) ? imm + pc + 4 : pc|
+|bne |I | pc = (rs != rt) ? imm + pc + 4 : pc|
+|addi |I |rt = rs + imm|
+|addiu |I |rt = rs + imm|
+|andi |I |rt = rs & imm|
+|ori |I |rt = rs \| imm|
+|xori |I |rt = rs ^ imm|
+|slti |R |rt = rs < imm|
+|sltiu |R |rt = rs < imm|
+|lui |I |rt = rs << 16|
+|lw |I |rs = imm(rt)|
+|sw |I |imm(rt) = rs|
+
diff --git a/qdma.go b/qdma.go
new file mode 100755
index 0000000..37e83a1
--- /dev/null
+++ b/qdma.go
@@ -0,0 +1,140 @@
+package main
+
+import (
+ "bufio"
+ "encoding/binary"
+ "log"
+ "os"
+ "strconv"
+ "strings"
+)
+
+var Instructions = map[string]struct {
+ isRtype bool
+ opcode uint32
+}{
+ "add": {true, 32},
+ "addi": {false, 8},
+ "addiu": {false, 9},
+ "sub": {true, 34},
+ "subu": {true, 35},
+ "mult": {true, 24},
+ "multu": {true, 25},
+ "div": {true, 26},
+ "divu": {true, 27},
+ "and": {true, 36},
+ "andi": {false, 12},
+ "or": {true, 37},
+ "ori": {false, 13},
+ "xor": {true, 38},
+ "xori": {false, 14},
+ "sll": {true, 0},
+ "sra": {true, 3},
+ "srl": {true, 2},
+ "lw": {false, 35},
+ "sw": {false, 43},
+ "slt": {true, 42},
+ "slti": {false, 10},
+ "sltiu": {false, 11},
+ "sltu": {true, 43},
+ "beq": {false, 4},
+ "bne": {false, 5},
+ "j": {false, 2},
+ "jal": {false, 3},
+ "jr": {true, 8},
+ "syscall": {false, 12},
+}
+
+var RegNums = map[string]uint32{
+ "$zero": 0,
+ "$at": 1,
+ "$v0": 2,
+ "$v1": 3,
+ "$a0": 4,
+ "$a1": 5,
+ "$a2": 6,
+ "$a3": 7,
+ "$t0": 8,
+ "$t1": 9,
+ "$t2": 10,
+ "$t3": 11,
+ "$t4": 12,
+ "$t5": 13,
+ "$t6": 14,
+ "$t7": 15,
+ "$s0": 16,
+ "$s1": 17,
+ "$s2": 18,
+ "$s3": 19,
+ "$s4": 20,
+ "$s5": 21,
+ "$s6": 22,
+ "$s7": 23,
+ "$t8": 24,
+ "$t9": 25,
+ "$k0": 26,
+ "$k1": 27,
+ "$gp": 28,
+ "$sp": 29,
+ "$fp": 30,
+ "$ra": 31,
+}
+
+func Encode(instruction string) uint32 {
+ var ret uint32 = 0
+ if instruction == "syscall" {
+ return 12
+ }
+ inst := strings.Fields(strings.ReplaceAll(instruction, ",", ""))
+ if Instructions[inst[0]].isRtype {
+ ret = (RegNums[inst[2]] << 21) | (RegNums[inst[3]] << 16) |
+ (RegNums[inst[1]] << 11) | Instructions[inst[0]].opcode
+ } else {
+ var imm int32
+ i, err := strconv.Atoi(inst[3])
+ if err != nil {
+ log.Fatal(err)
+ }
+ imm = int32(i)
+ ret = (Instructions[inst[0]].opcode << 26) | (RegNums[inst[2]] << 21) |
+ (RegNums[inst[1]] << 16) | uint32(imm)
+ }
+ return ret
+}
+
+func Assemble(path string) {
+ file, err := os.Open(path)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ out, err := os.Create(strings.ReplaceAll(path, ".asm", ".bin"))
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer out.Close()
+
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ var s string = scanner.Text()
+ if s != "" {
+ bs := make([]byte, 4)
+ binary.BigEndian.PutUint32(bs, Encode(s))
+ _, err := out.Write(bs)
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func main() {
+ for _, arg := range os.Args[1:] {
+ Assemble(arg)
+ }
+}
diff --git a/test.asm b/test.asm
new file mode 100755
index 0000000..fbb450b
--- /dev/null
+++ b/test.asm
@@ -0,0 +1,10 @@
+addi $t0, $zero, 10
+addi $t1, $zero, 12
+add $t2, $t1, $t0
+
+add $a0, $t2, $zero
+addi $v0, $zero, 1
+syscall
+
+addi $v0, $zero, 10
+syscall
diff --git a/test.bin b/test.bin
new file mode 100755
index 0000000..2cf7b8d
--- /dev/null
+++ b/test.bin
Binary files differ
diff --git a/test2.asm b/test2.asm
new file mode 100755
index 0000000..e22cd5e
--- /dev/null
+++ b/test2.asm
@@ -0,0 +1,21 @@
+.data
+
+fib: space 40
+
+str: .asciiz "Hello"
+
+.text
+main: addi $t0, $zero, 10
+ addi $t1, $zero, 11
+ loop: add $t2, $t1, $t0
+
+ addi $v0, $zero, 1
+ addi $a0, $t2, 0
+ syscall
+
+ addi $t0, $t0, -1
+ addi $t1, $t1, -1
+ bne $t0, $zero, loop
+ addi $v0, $zero, 10
+ syscall
+