aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm.peg206
-rw-r--r--main.c6
-rw-r--r--test/test.sh17
3 files changed, 128 insertions, 101 deletions
diff --git a/asm.peg b/asm.peg
index 9dbfeb6..c5326e4 100644
--- a/asm.peg
+++ b/asm.peg
@@ -1,106 +1,136 @@
-line = s:stmt (eol | !. ) { yy->v = s; }
- | eol { yy->v.kind = ASM_BLANK; }
- | . { yy->v.kind = ASM_SYNTAX_ERROR; }
-
-stmt = d:directive {$$ = d;}
- | i:instr { $$ = i; }
- | l:label { $$ = l; }
-
-directive = ".glob" "o"? "l" ws i:ident
- { $$.globl = (Globl){.kind = ASM_DIR_GLOBL, .name = i.ident.name }; }
- | ".data" { $$.kind = ASM_DIR_DATA; }
- | ".text" { $$.kind = ASM_DIR_TEXT; }
- | ".balign" ws n:number
- { $$.balign = (Balign){.kind = ASM_DIR_BALIGN, .align = n.number.v }; }
- | ".byte" ws n:number
- { $$.byte = (Byte){.kind = ASM_DIR_BYTE, .b = (uint8_t)n.number.v }; }
-
-label = i:ident ':'
- { $$.label = (Label){.kind = ASM_LABEL, .name = i.ident.name}; }
-
-instr = "nop"{ $$.kind = ASM_NOP; }
- | "leave" { $$.kind = ASM_LEAVE; }
- | "ret" { $$.kind = ASM_RET; }
- | i:jmp { $$ = i; }
- | i:mod-rm-binop { $$ = i; }
+line =
+ s:stmt (eol | !. ) { yy->v = s; }
+ | eol { yy->v.kind = ASM_BLANK; }
+ | . { yy->v.kind = ASM_SYNTAX_ERROR; }
+
+stmt =
+ d:directive {$$ = d;}
+ | i:instr { $$ = i; }
+ | l:label { $$ = l; }
+
+directive =
+ ".glob" "o"? "l" ws i:ident
+ { $$.globl = (Globl){.kind = ASM_DIR_GLOBL, .name = i.ident.name }; }
+ | ".data"
+ { $$.kind = ASM_DIR_DATA; }
+ | ".text"
+ { $$.kind = ASM_DIR_TEXT; }
+ | ".balign" ws n:number
+ { $$.balign = (Balign){.kind = ASM_DIR_BALIGN, .align = n.number.v }; }
+ | ".byte" ws n:number
+ { $$.byte = (Byte){.kind = ASM_DIR_BYTE, .b = (uint8_t)n.number.v }; }
+
+label =
+ i:ident ':'
+ { $$.label = (Label){.kind = ASM_LABEL, .name = i.ident.name}; }
+
+instr =
+ "nop" { $$.kind = ASM_NOP; }
+ | "leave" { $$.kind = ASM_LEAVE; }
+ | "ret" { $$.kind = ASM_RET; }
+ | i:jmp { $$ = i; }
+ | i:lea { $$ = i; }
+ | i:mod-rm-binop { $$ = i; }
jmp = "jmp" ws i:ident
{ $$.jmp = (Jmp){.kind = ASM_JMP, .target = i.ident.name}; }
-mod-rm-binop = "add" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_ADD; }
- | "and" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_AND;}
- | "lea" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_LEA;}
- | "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;}
-
-
+lea =
+ "lea"
+ (
+ "q"? ws s:m ws? ',' ws? d:r64
+ { $$.lea.type = 'q'; }
+ | "l"? ws s:m ws? ',' ws? d:r32
+ { $$.lea.type = 'l'; }
+ ) { $$.lea.kind = ASM_LEA;
+ $$.lea.src = dupv(&s);
+ $$.lea.dst = dupv(&d); }
+
+mod-rm-binop =
+ "add" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_ADD; }
+ | "and" a:mod-rm-binop-args { $$ = a; $$.kind = ASM_AND;}
+ | "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;}
mod-rm-binop-args =
- "q" ws s:r-m64 ws? ',' ws? d:r64
- { $$.modrmbinop = (ModRMBinop){ .type = 'q', .src = dupv(&s), .dst = dupv(&d) } }
+ (
+ "q" ws s:r-m64 ws? ',' ws? d:r64
| "q" ws s:r64 ws? ',' ws? d:r-m64
- { $$.modrmbinop = (ModRMBinop){ .type = 'q', .src = dupv(&s), .dst = dupv(&d) } }
| "q" ws s:imm ws? ',' ws? d:r-m64
- { $$.modrmbinop = (ModRMBinop){ .type = 'q', .src = dupv(&s), .dst = dupv(&d) } }
- | "l" ws s:r-m32 ws? ',' ws? d:r32
- { $$.modrmbinop = (ModRMBinop){ .type = 'l', .src = dupv(&s), .dst = dupv(&d) } }
- | "l" ws s:r32 ws? ',' ws? d:r-m32
- { $$.modrmbinop = (ModRMBinop){ .type = 'l', .src = dupv(&s), .dst = dupv(&d) } }
- | "l" ws s:imm ws? ',' ws? d:r-m32
- { $$.modrmbinop = (ModRMBinop){ .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? ')'
+ | ws s:r64 ws? ',' ws? d:r64
+ | ws s:m ws? ',' ws? d:r64
+ | ws s:imm ws? ',' ws? d:r64
+ ) { $$.modrmbinop = (ModRMBinop){ .type = 'q', .src = dupv(&s), .dst = dupv(&d) } }
+ | (
+ "l" ws s:r-m32 ws? ',' ws? d:r32
+ | "l" ws s:r32 ws? ',' ws? d:r-m32
+ | "l" ws s:imm ws? ',' ws? d:r-m32
+ | ws s:r32 ws? ',' ws? d:r32
+ | ws s:m ws? ',' ws? d:r32
+ | ws s:imm ws? ',' ws? d:r32
+ )
+ { $$.modrmbinop = (ModRMBinop){ .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? ')'
{ $$.memarg = (Memarg){ .kind = ASM_MEMARG, .c = strtoll(yytext, NULL, 10), .l = NULL, .reg = r.kind } }
| i:ident ws? '(' ws? r:r64 ws? ')'
{ $$.memarg = (Memarg){ .kind = ASM_MEMARG, .c = 0, .l = i.ident.name, .reg = r.kind } }
-r64 = "%rax" { $$.kind = ASM_RAX }
- | "%rcx" { $$.kind = ASM_RCX }
- | "%rdx" { $$.kind = ASM_RDX }
- | "%rbx" { $$.kind = ASM_RBX }
- | "%rsp" { $$.kind = ASM_RSP }
- | "%rbp" { $$.kind = ASM_RBP }
- | "%rsi" { $$.kind = ASM_RSI }
- | "%rdi" { $$.kind = ASM_RDI }
- | "%r8" { $$.kind = ASM_R8 }
- | "%r9" { $$.kind = ASM_R9 }
- | "%r10" { $$.kind = ASM_R10 }
- | "%r11" { $$.kind = ASM_R11 }
- | "%r12" { $$.kind = ASM_R12 }
- | "%r13" { $$.kind = ASM_R13 }
- | "%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 }; }
- | '$' <'-'?[0-9]+>
- { $$.imm = (Imm){.kind = ASM_IMM, .l = NULL, .c = strtoll(yytext, NULL, 10) }; }
-
-ident = <[_a-zA-Z][_a-zA-Z0-9]*>
- { $$.ident = (Ident){ .kind = ASM_IDENT, .name = xstrdup(yytext) }; }
-
-number = <'-'?[0-9]+>
- { $$.number = (Number){ .kind = ASM_NUMBER, .v = strtoll(yytext, NULL, 10) }; }
+r64 =
+ "%rax" { $$.kind = ASM_RAX }
+ | "%rcx" { $$.kind = ASM_RCX }
+ | "%rdx" { $$.kind = ASM_RDX }
+ | "%rbx" { $$.kind = ASM_RBX }
+ | "%rsp" { $$.kind = ASM_RSP }
+ | "%rbp" { $$.kind = ASM_RBP }
+ | "%rsi" { $$.kind = ASM_RSI }
+ | "%rdi" { $$.kind = ASM_RDI }
+ | "%r8" { $$.kind = ASM_R8 }
+ | "%r9" { $$.kind = ASM_R9 }
+ | "%r10" { $$.kind = ASM_R10 }
+ | "%r11" { $$.kind = ASM_R11 }
+ | "%r12" { $$.kind = ASM_R12 }
+ | "%r13" { $$.kind = ASM_R13 }
+ | "%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 }; }
+ | '$' <'-'?[0-9]+>
+ { $$.imm = (Imm){.kind = ASM_IMM, .l = NULL, .c = strtoll(yytext, NULL, 10) }; }
+
+ident =
+ <[_a-zA-Z][_a-zA-Z0-9]*>
+ { $$.ident = (Ident){ .kind = ASM_IDENT, .name = xstrdup(yytext) }; }
+
+number =
+ <'-'?[0-9]+>
+ { $$.number = (Number){ .kind = ASM_NUMBER, .v = strtoll(yytext, NULL, 10) }; }
ws = [ \t]+
diff --git a/main.c b/main.c
index fc95414..697d3dc 100644
--- a/main.c
+++ b/main.c
@@ -257,13 +257,13 @@ static void assemble() {
case ASM_RET:
sb(0xc3);
break;
+
case ASM_ADD:
case ASM_AND:
case ASM_LEA:
case ASM_OR:
case ASM_SUB:
case ASM_XOR: {
-
ModRMBinop *op;
Memarg *memarg;
uint8_t opcode;
@@ -320,6 +320,8 @@ static void assemble() {
opcode = 0x01;
} else if (op->kind == ASM_AND) {
opcode = 0x21;
+ } else if (op->kind == ASM_OR) {
+ opcode = 0x09;
} else if (op->kind == ASM_SUB) {
opcode = 0x29;
} else if (op->kind == ASM_XOR) {
@@ -348,6 +350,8 @@ static void assemble() {
opcode = 0x23;
} else if (op->kind == ASM_LEA) {
opcode = 0x8d;
+ } else if (op->kind == ASM_OR) {
+ opcode = 0x0b;
} else if (op->kind == ASM_SUB) {
opcode = 0x2b;
} else if (op->kind == ASM_XOR) {
diff --git a/test/test.sh b/test/test.sh
index 4b747fb..b261afa 100644
--- a/test/test.sh
+++ b/test/test.sh
@@ -26,12 +26,12 @@ t () {
}
t "leaq (%rax), %rax"
-
+t "leal (%rax), %eax"
t "addq (%rax), %rax"
t "andq (%rax), %rax"
+t "orq (%rax), %rax"
t "subq (%rax), %rax"
t "xorq (%rax), %rax"
-
t "nop"
t "ret"
t "leave"
@@ -46,19 +46,12 @@ t "addq %rax, (%rbx)"
t "addl %eax, (%rax)"
t "addl %eax, (%r9)"
t "addl %ebx, (%r9)"
-
+t "orq %rax, %rax"
+t "orq %rax, (%rax)"
+t "orl %eax, %eax"
t "xorq %rax, %rax"
t "xorq %rax, (%rax)"
t "xorl %eax, %eax"
-
t "andq %rax, %rax"
t "andq %rax, (%rax)"
t "andl %eax, %eax"
-
-
-
-#t "addq %rbp, (%rax)"
-
-
-#t "addq %rax, %rbx"
-#t "addl %eax, %ebx"