aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm.peg18
-rw-r--r--default.do4
-rw-r--r--main.c72
3 files changed, 78 insertions, 16 deletions
diff --git a/asm.peg b/asm.peg
index 946f6e6..5bcd972 100644
--- a/asm.peg
+++ b/asm.peg
@@ -34,10 +34,19 @@ add = "addq" ws s:r-m64 ws? ',' ws? d:r64
{ $$.add = (Add){ .kind = ASM_ADD, .type = 'q', .src = dupv(&s), .dst = dupv(&d) } }
| "addq" ws s:imm ws? ',' ws? d:r-m64
{ $$.add = (Add){ .kind = ASM_ADD, .type = 'q', .src = dupv(&s), .dst = dupv(&d) } }
+ | "addl" ws s:r-m32 ws? ',' ws? d:r32
+ { $$.add = (Add){ .kind = ASM_ADD, .type = 'l', .src = dupv(&s), .dst = dupv(&d) } }
+ | "addl" ws s:r32 ws? ',' ws? d:r-m32
+ { $$.add = (Add){ .kind = ASM_ADD, .type = 'l', .src = dupv(&s), .dst = dupv(&d) } }
+ | "addl" ws s:imm ws? ',' ws? d:r-m32
+ { $$.add = (Add){ .kind = ASM_ADD, .type = 'l', .src = dupv(&s), .dst = dupv(&d) } }
r-m64 = r:r64 { $$ = r; }
| m:m { $$ = m; }
+r-m32 = r:r32 { $$ = r; }
+ | m:m { $$ = m; }
+
m = '(' ws? r:r64 ws? ')'
{ $$.memarg = (Memarg){ .kind = ASM_MEMARG, .c = 0, .l = NULL, .reg = r.kind } }
| <'-'?[0-9]+> ws? '(' ws? r:r64 ws? ')'
@@ -62,6 +71,15 @@ r64 = "%rax" { $$.kind = ASM_RAX }
| "%r14" { $$.kind = ASM_R14 }
| "%r15" { $$.kind = ASM_R15 }
+r32 = "%eax" { $$.kind = ASM_EAX }
+ | "%ecx" { $$.kind = ASM_ECX }
+ | "%edx" { $$.kind = ASM_EDX }
+ | "%ebx" { $$.kind = ASM_EBX }
+ | "%esp" { $$.kind = ASM_ESP }
+ | "%ebp" { $$.kind = ASM_EBP }
+ | "%esi" { $$.kind = ASM_ESI }
+ | "%edi" { $$.kind = ASM_EDI }
+
imm = '$' i:ident
{ $$.imm = (Imm){.kind = ASM_IMM, .l = i.ident.name, .c = 0 }; }
diff --git a/default.do b/default.do
index 6787b8d..5e05697 100644
--- a/default.do
+++ b/default.do
@@ -6,7 +6,7 @@ case "$1" in
test "$1" = "main.o" && redo-ifchange asm.peg.inc
redo-ifchange "${1%.o}.c" minias.h
set -x
- ${CC:- cc} ${CFLAGS:- -O -Og} -c -o "$3" "${1%.o}.c"
+ ${CC:- cc} ${CFLAGS:- -g -Og} -c -o "$3" "${1%.o}.c"
;;
asm.peg.inc)
redo-ifchange asm.peg
@@ -16,9 +16,11 @@ case "$1" in
minias)
obj="main.o util.o "
redo-ifchange $obj
+ set -x
${CC:- cc} ${LDFLAGS:-} -o "$3" $obj
;;
fmt)
+ set -x
clang-format -i main.c util.c >&2
;;
*)
diff --git a/main.c b/main.c
index 69de674..0aa059a 100644
--- a/main.c
+++ b/main.c
@@ -113,7 +113,7 @@ static void initsections(void) {
text->hdr.sh_addralign = 4;
}
-static Parsev *dupv(Parsev *p) {
+static Parsev *dupv(Parsev *p) {
Parsev *r = xmalloc(sizeof(Parsev));
*r = *p;
return r;
@@ -179,20 +179,18 @@ static void sw(uint32_t w) {
/* Compose a ModR/M byte. */
static uint8_t modrm(uint8_t mod, uint8_t regop, uint8_t rm) {
- return ((mod&3) << 6) | ((regop&7) << 3) | (rm&7);
+ return ((mod & 3) << 6) | ((regop & 7) << 3) | (rm & 7);
}
/* Is one of the r$n style registers. */
-static uint8_t isextr64(AsmKind k) {
- return k >= ASM_R8 && k <= ASM_R15;
-}
+static uint8_t isextr64(AsmKind k) { return k >= ASM_R8 && k <= ASM_R15; }
/* Convert an ASM_KIND to register bits */
static uint8_t r64bits(AsmKind k) {
if (isextr64(k)) {
- return (1<<4) | ((k - ASM_R8) & 0xff);
+ return (1 << 4) | ((k - ASM_R8) & 0xff);
} else {
- return (k - ASM_RAX) & 0xff;
+ return (k - ASM_RAX) & 0xff;
}
}
@@ -254,19 +252,63 @@ static void assemble() {
break;
case ASM_ADD: {
Add *add = &v->add;
-
switch (add->type) {
+ case 'l':
+ switch (add->src->kind) {
+ case ASM_IMM:
+ if (add->dst->kind == ASM_MEMARG) {
+ uint8_t rbits = r64bits(add->dst->memarg.reg);
+ if (rbits & (1 << 4)) {
+ // 64 bit register, need rex.
+ sb(REX(0, 0, 0, rbits & (1 << 4)));
+ }
+ if ((rbits & 7) == 4) {
+ fatal("%d: cannot address destination", l->lineno);
+ }
+ if (add->dst->memarg.c == 0 && add->dst->memarg.l == NULL) {
+ if ((rbits & 7) == 5) { /* BP style registers need displacement */
+ sb3(0x81, modrm(0x01, 0x00, rbits), 0x00);
+ } else {
+ sb2(0x81, modrm(0x00, 0x00, rbits));
+ }
+ } else {
+ fatal("TODO mem arg with disp");
+ }
+ } else { // imm, r32
+ sb2(0x81, modrm(0x03, 0x00, r32bits(add->dst->kind)));
+ }
+ sw(0);
+ break;
+ break;
+ case ASM_MEMARG:
+ fatal("TODO");
+ break;
+ default:
+ switch (add->src->kind) {
+ case ASM_MEMARG:
+ fatal("TODO");
+ break;
+ default: { // r32, r32
+ uint8_t srcbits = r32bits(add->src->kind);
+ uint8_t dstbits = r32bits(add->dst->kind);
+ sb2(0x03, modrm(0x03, dstbits, srcbits));
+ break;
+ }
+ }
+ break;
+ }
+ break;
case 'q':
switch (add->src->kind) {
case ASM_IMM:
if (add->dst->kind == ASM_MEMARG) {
uint8_t rbits = r64bits(add->dst->memarg.reg);
- uint8_t rex = REX(1,0,0,rbits&(1<<4));
- if ((rbits&7) == 4) {
- fatal("%d: cannot address destination register", l->lineno);
+ uint8_t rex = REX(1, 0, 0, rbits & (1 << 4));
+ if ((rbits & 7) == 4) {
+ fatal("%d: cannot address destination", l->lineno);
}
if (add->dst->memarg.c == 0 && add->dst->memarg.l == NULL) {
- if ((rbits&7) == 5) { /* BP style registers need displacement */
+ if ((rbits & 7) == 5) { /* BP style registers need displacement */
sb4(rex, 0x81, modrm(0x01, 0x00, rbits), 0x00);
} else {
sb3(rex, 0x81, modrm(0x00, 0x00, rbits));
@@ -276,7 +318,7 @@ static void assemble() {
}
} else { // imm, r64
uint8_t rbits = r64bits(add->dst->kind);
- uint8_t rex = REX(1,0,0,rbits&(1<<4));
+ uint8_t rex = REX(1, 0, 0, rbits & (1 << 4));
sb3(rex, 0x81, modrm(0x03, 0x00, rbits));
}
sw(0);
@@ -289,10 +331,10 @@ static void assemble() {
case ASM_MEMARG:
fatal("TODO");
break;
- default: { // r64, r64
+ default: { // r64, r64
uint8_t srcbits = r64bits(add->src->kind);
uint8_t dstbits = r64bits(add->dst->kind);
- uint8_t rex = REX(1,dstbits&(1<<4),0,srcbits&(1<<4));
+ uint8_t rex = REX(1, dstbits & (1 << 4), 0, srcbits & (1 << 4));
sb3(rex, 0x03, modrm(0x03, dstbits, srcbits));
break;
}