diff options
| author | Andrew Chambers <[email protected]> | 2021-10-05 18:58:52 +1300 |
|---|---|---|
| committer | Andrew Chambers <[email protected]> | 2021-10-05 18:58:52 +1300 |
| commit | e0b52ff23ca304d581f80f0d9bd2de76fb042d03 (patch) | |
| tree | 6ab1cef175157cbab62f9b379dbdb5f573b7cdbc | |
| parent | 5c0af4055474834542e2813f36f4dd9a16479e53 (diff) | |
Add more add variants.
| -rw-r--r-- | asm.peg | 18 | ||||
| -rw-r--r-- | default.do | 4 | ||||
| -rw-r--r-- | main.c | 72 |
3 files changed, 78 insertions, 16 deletions
@@ -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 }; } @@ -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 ;; *) @@ -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; } |
