diff options
| -rw-r--r-- | asm.peg | 19 | ||||
| -rw-r--r-- | main.c | 18 | ||||
| -rw-r--r-- | minias.h | 1 | ||||
| -rw-r--r-- | test/test.sh | 31 |
4 files changed, 56 insertions, 13 deletions
@@ -71,6 +71,7 @@ instr = | i:sar { $$ = i; } | i:shl { $$ = i; } | i:shr { $$ = i; } + | i:test { $$ = i; } | i:xchg { $$ = i; } | i:xor { $$ = i; } @@ -153,7 +154,6 @@ imul = "imul" ( | 'w'? ws s:r16 ws? ',' ws? d:r16 { $$ = INSTR2(11, s, d); } | 'l'? ws s:r32 ws? ',' ws? d:r32 { $$ = INSTR2(12, s, d); } | 'q'? ws s:r64 ws? ',' ws? d:r64 { $$ = INSTR2(13, s, d); } - | 'w'? ws i:imm16 ',' ws? s:m ws? ',' ws? d:r16 { $$ = INSTR3(14, s, d, i); } | 'l'? ws i:imm32 ',' ws? s:m ws? ',' ws? d:r32 { $$ = INSTR3(15, s, d, i); } | 'q'? ws i:imm32 ',' ws? s:m ws? ',' ws? d:r64 { $$ = INSTR3(16, s, d, i); } @@ -239,6 +239,7 @@ shr = 'shr' args:shift-args {$$ = args; $$.instr.kind = ASM_SHR} shift-args = + # There are some more specific variants we could add. 'w' ws c:cl ws? ',' ws? d:m { $$ = INSTR2(0, c, d); } | 'l' ws c:cl ws? ',' ws? d:m { $$ = INSTR2(1, c, d); } | 'q' ws c:cl ws? ',' ws? d:m { $$ = INSTR2(2, c, d); } @@ -252,6 +253,22 @@ shift-args = | 'l'? ws i:imm8 ws? ',' ws? d:r32 { $$ = INSTR2(10, i, d); } | 'q'? ws i:imm8 ws? ',' ws? d:r64 { $$ = INSTR2(11, i, d); } +test = "test" ( + # There are some more specific variants we could add. + 'b'? ws s:imm8 ws? ',' ws? d:al { $$ = INSTR2(0, s, d); } + | 'w'? ws s:imm16 ws? ',' ws? d:ax { $$ = INSTR2(1, s, d); } + | 'l'? ws s:imm32 ws? ',' ws? d:eax { $$ = INSTR2(2, s, d); } + | 'q'? ws s:imm32 ws? ',' ws? d:rax { $$ = INSTR2(3, s, d); } + | args:imm-rm-opargs { args.instr.variant += 4; $$ = args; } + | 'b'? ws s:r8 ws? ',' ws? d:m { $$ = INSTR2(12, s, d); } + | 'w'? ws s:r16 ws? ',' ws? d:m { $$ = INSTR2(13, s, d); } + | 'l'? ws s:r32 ws? ',' ws? d:m { $$ = INSTR2(14, s, d); } + | 'q'? ws s:r64 ws? ',' ws? d:m { $$ = INSTR2(15, s, d); } + | 'b'? ws s:r8 ws? ',' ws? d:r8 { $$ = INSTR2(16, s, d); } + | 'w'? ws s:r16 ws? ',' ws? d:r16 { $$ = INSTR2(17, s, d); } + | 'l'? ws s:r32 ws? ',' ws? d:r32 { $$ = INSTR2(18, s, d); } + | 'q'? ws s:r64 ws? ',' ws? d:r64 { $$ = INSTR2(19, s, d); } +) { $$.instr.kind = ASM_TEST; } r64-or-rip = ( r:r64 @@ -800,6 +800,24 @@ static void assemble(void) { assemblebasicop(&v->instr, variant2op[v->instr.variant], 0x05); break; } + case ASM_TEST: { + uint8_t opsz = 1 << (v->instr.variant % 4); + if (v->instr.variant < 4) { + Imm *imm; + if (opsz == 2) + sb(0x66); + if (v->instr.arg2->kind == ASM_RAX) + sb(rexbyte(1, 0, 0, 0)); + assembleopcode((opsz == 1) ? 0xa8 : 0xa9); + imm = &v->instr.arg1->imm; + assemblereloc(imm->l, imm->c, imm->nbytes, R_X86_64_32); + } else if (v->instr.variant < 12) { + assembleimmrm(&v->instr, (opsz == 1) ? 0xf6 : 0xf7, 0, opsz); + } else { + assemblerrm(&v->instr, (opsz == 1) ? 0x84 : 0x85, opsz); + } + break; + } case ASM_XOR: { static uint8_t variant2op[24] = { 0x34, 0x35, 0x35, 0x35, 0x80, 0x81, 0x81, 0x81, @@ -79,6 +79,7 @@ typedef enum { ASM_SHL, ASM_SHR, ASM_SUB, + ASM_TEST, ASM_XCHG, ASM_XOR, // Registers, order matters. diff --git a/test/test.sh b/test/test.sh index 6126d1c..271f815 100644 --- a/test/test.sh +++ b/test/test.sh @@ -114,7 +114,7 @@ for r in a b t "leaw (%r${r}x), %${r}x" done -for op in mov add and cmp or sub xor +for op in mov add and cmp or sub xor test do # rip relative t "${op}b \$127, (%rip)" @@ -126,7 +126,7 @@ do for r in a b do - # immediate variants. + # immediate variants t "${op}b \$127, (%r${r}x)" t "${op}w \$32767, (%r${r}x)" t "${op}l \$2147483647, (%r${r}x)" @@ -136,16 +136,7 @@ do t "${op}l \$2147483647, %e${r}x" t "${op}q \$2147483647, %r${r}x" - # r rm variants - t "${op}b (%rip), %${r}l" - t "${op}b (%rax), %${r}l" - t "${op}b (%rax), %${r}l" - t "${op}w (%rax), %${r}x" - t "${op}l (%rax), %e${r}x" - t "${op}q (%rax), %r${r}x" - t "${op}q (%rbp), %r${r}x" - t "${op}q (%r8), %r${r}x" - t "${op}q (%r13), %r${r}x" + # r -> m variants t "${op}b %${r}l, (%rip)" t "${op}b %${r}l, (%rax)" t "${op}w %${r}x, (%rax)" @@ -158,6 +149,22 @@ do t "${op}w %${r}x, %ax" t "${op}l %e${r}x, %eax" t "${op}q %r${r}x, %rax" + + if test "$op" = "test" # m -> variants are not supported by test + then + continue + fi + + # m -> r variants + t "${op}b (%rip), %${r}l" + t "${op}b (%rax), %${r}l" + t "${op}b (%rax), %${r}l" + t "${op}w (%rax), %${r}x" + t "${op}l (%rax), %e${r}x" + t "${op}q (%rax), %r${r}x" + t "${op}q (%rbp), %r${r}x" + t "${op}q (%r8), %r${r}x" + t "${op}q (%r13), %r${r}x" done done |
