aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm.peg9
-rw-r--r--default.do2
-rw-r--r--main.c31
-rw-r--r--minias.h3
-rw-r--r--test/test.sh7
5 files changed, 32 insertions, 20 deletions
diff --git a/asm.peg b/asm.peg
index 03d5ba0..f163271 100644
--- a/asm.peg
+++ b/asm.peg
@@ -50,6 +50,7 @@ lea =
mod-rm-binop =
"add" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_ADD; }
| "and" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_AND;}
+ | "mov" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_MOV;}
| "or" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_OR;}
| "sub" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_SUB;}
| "xor" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_XOR;}
@@ -119,10 +120,10 @@ r32 =
imm =
-'$' i:ident
- { $$.imm = (Imm){.kind = ASM_IMM, .l = i.ident.name, .c = 0 }; }
- | '$' <'-'?[0-9]+>
- { $$.imm = (Imm){.kind = ASM_IMM, .l = NULL, .c = strtoll(yytext, NULL, 10) }; }
+ '$' i:ident
+ { $$.imm = (Imm){.kind = ASM_IMM, .l = i.ident.name, .c = 0 }; }
+ | '$' <'-'?[0-9]+>
+ { $$.imm = (Imm){.kind = ASM_IMM, .l = NULL, .c = strtoll(yytext, NULL, 10) }; }
ident =
<[_a-zA-Z][_a-zA-Z0-9]*>
diff --git a/default.do b/default.do
index 5e05697..1fe1e16 100644
--- a/default.do
+++ b/default.do
@@ -24,7 +24,7 @@ case "$1" in
clang-format -i main.c util.c >&2
;;
*)
- echo "don't know how to build $1" 2>&1
+ echo "don't know how to do $1" 2>&1
exit 1
;;
esac \ No newline at end of file
diff --git a/main.c b/main.c
index 697d3dc..81e6220 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,6 @@
#include "minias.h"
+static FILE *outf = NULL;
static AsmLine *allasm = NULL;
// Symbols in memory before
@@ -257,10 +258,10 @@ static void assemble() {
case ASM_RET:
sb(0xc3);
break;
-
case ASM_ADD:
case ASM_AND:
case ASM_LEA:
+ case ASM_MOV:
case ASM_OR:
case ASM_SUB:
case ASM_XOR: {
@@ -320,6 +321,8 @@ static void assemble() {
opcode = 0x01;
} else if (op->kind == ASM_AND) {
opcode = 0x21;
+ } else if (op->kind == ASM_MOV) {
+ opcode = 0x89;
} else if (op->kind == ASM_OR) {
opcode = 0x09;
} else if (op->kind == ASM_SUB) {
@@ -331,17 +334,6 @@ static void assemble() {
}
reg = rbits(op->src->kind);
- } else if (op->src->kind == ASM_IMM) {
-
- opcode = 0x81;
- reg = 0x00;
-
- if (memarg) {
- rm = rbits(memarg->reg);
- } else {
- rm = rbits(op->dst->kind);
- }
-
} else if (op->src->kind == ASM_MEMARG) {
if (op->kind == ASM_ADD) {
@@ -350,6 +342,8 @@ static void assemble() {
opcode = 0x23;
} else if (op->kind == ASM_LEA) {
opcode = 0x8d;
+ } else if (op->kind == ASM_MOV) {
+ opcode = 0x8b;
} else if (op->kind == ASM_OR) {
opcode = 0x0b;
} else if (op->kind == ASM_SUB) {
@@ -359,8 +353,17 @@ static void assemble() {
} else {
fatal("unreachable");
}
- /* dst is reg */
reg = rbits(op->dst->kind);
+ } else if (op->src->kind == ASM_IMM) {
+
+ opcode = 0x81;
+ reg = 0x00;
+ if (memarg) {
+ rm = rbits(memarg->reg);
+ } else {
+ rm = rbits(op->dst->kind);
+ }
+
}
rex = REX(op->type == 'q', reg & (1 << 4), 0, rm & (1 << 4));
@@ -462,8 +465,6 @@ static void fillsymtab(void) {
}
}
-FILE *outf = NULL;
-
static void out(uint8_t *buf, size_t n) {
fwrite(buf, 1, n, outf);
if (ferror(outf))
diff --git a/minias.h b/minias.h
index a800e2b..5e456fa 100644
--- a/minias.h
+++ b/minias.h
@@ -50,6 +50,7 @@ typedef enum {
ASM_ADD,
ASM_AND,
ASM_LEA,
+ ASM_MOV,
ASM_OR,
ASM_SUB,
ASM_XOR,
@@ -142,6 +143,7 @@ typedef struct {
typedef ModRMBinop Add;
typedef ModRMBinop And;
typedef ModRMBinop Lea;
+typedef ModRMBinop Mov;
typedef ModRMBinop Or;
typedef ModRMBinop Sub;
typedef ModRMBinop Xor;
@@ -156,6 +158,7 @@ union Parsev {
Add add;
And and;
Lea lea;
+ Mov mov;
Or or;
Xor xor;
Sub sub;
diff --git a/test/test.sh b/test/test.sh
index b261afa..be5a91f 100644
--- a/test/test.sh
+++ b/test/test.sh
@@ -25,6 +25,13 @@ t () {
echo -n "."
}
+# TODO Tidy and be more systematic, we could just loop
+t "movq %rax, %rax"
+t "movq (%rax), %rax"
+t "movq %rax, (%rax)"
+t "movl %eax, %eax"
+t "movl (%rax), %eax"
+t "movl %eax, (%rax)"
t "leaq (%rax), %rax"
t "leal (%rax), %eax"
t "addq (%rax), %rax"