aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm.peg19
-rw-r--r--main.c18
-rw-r--r--minias.h1
-rw-r--r--test/test.sh31
4 files changed, 56 insertions, 13 deletions
diff --git a/asm.peg b/asm.peg
index 6ff6b20..4be25cb 100644
--- a/asm.peg
+++ b/asm.peg
@@ -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
diff --git a/main.c b/main.c
index 8c08f9c..7086165 100644
--- a/main.c
+++ b/main.c
@@ -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,
diff --git a/minias.h b/minias.h
index ac861da..1444b46 100644
--- a/minias.h
+++ b/minias.h
@@ -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