diff options
| -rw-r--r-- | asm.peg | 206 | ||||
| -rw-r--r-- | main.c | 6 | ||||
| -rw-r--r-- | test/test.sh | 17 |
3 files changed, 128 insertions, 101 deletions
@@ -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]+ @@ -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" |
