diff options
| author | Andrew Chambers <[email protected]> | 2021-10-13 22:46:17 +1300 |
|---|---|---|
| committer | Andrew Chambers <[email protected]> | 2021-10-13 22:46:17 +1300 |
| commit | dfe49d06a417f4cb6a9ee0c67f7c1234c2315a7a (patch) | |
| tree | 3efcf1ffc9df78f76026f6304e7d7ba1ea4410de | |
| parent | 174fc3291257e96a81a8757ae22dd0e14d3b259f (diff) | |
Fix broken test.
| -rw-r--r-- | asm.peg | 20 | ||||
| -rw-r--r-- | main.c | 47 | ||||
| -rw-r--r-- | minias.h | 11 | ||||
| -rw-r--r-- | test/test.sh | 10 |
4 files changed, 59 insertions, 29 deletions
@@ -80,6 +80,8 @@ instr = | i:cvtsi2ss { $$ = i; } | i:cvtss2sd { $$ = i; } | i:cvtsd2ss { $$ = i; } + | i:cvtsd2si { $$ = i; } + | i:cvtss2si { $$ = i; } | i:cmp { $$ = i; } | i:div { $$ = i; } | i:idiv { $$ = i; } @@ -225,6 +227,20 @@ cvtsd2ss = "cvtsd2ss" ( | ws s:mem ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); } ) { $$.instr.kind = ASM_CVTSD2SS; } +cvtss2si = "cvtss2si" ( + 'l'? ws s:xmm ws? ',' ws? d:r32 { $$ = INSTR2(0, s, d); } + | 'q'? ws s:xmm ws? ',' ws? d:r64 { $$ = INSTR2(1, s, d); } + | 'l' ws s:mem ws? ',' ws? d:r32 { $$ = INSTR2(2, s, d); } + | 'q' ws s:mem ws? ',' ws? d:r64 { $$ = INSTR2(3, s, d); } +) { $$.instr.kind = ASM_CVTSS2SI; } + +cvtsd2si = "cvtsd2si" ( + 'l'? ws s:xmm ws? ',' ws? d:r32 { $$ = INSTR2(0, s, d); } + | 'q'? ws s:xmm ws? ',' ws? d:r64 { $$ = INSTR2(1, s, d); } + | 'l' ws s:mem ws? ',' ws? d:r32 { $$ = INSTR2(2, s, d); } + | 'q' ws s:mem ws? ',' ws? d:r64 { $$ = INSTR2(3, s, d); } +) { $$.instr.kind = ASM_CVTSD2SI; } + movaps = "movaps" ( ws s:xmm ws? ',' ws? d:xmm { $$ = INSTR2(0, s, d); } | ws s:mem ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); } @@ -397,8 +413,8 @@ xchg = | 'q'? ws s:r64 ws? ',' ws? d:r64 { $$ = INSTR2(17, s, d); } ) { $$.instr.kind = ASM_XCHG; } -add = "add" a:basic-op-args { a.instr.kind = ASM_CMP; $$ = a; } -cmp = "cmp" a:basic-op-args { a.instr.kind = ASM_ADD; $$ = a; } +add = "add" a:basic-op-args { a.instr.kind = ASM_ADD; $$ = a; } +cmp = "cmp" a:basic-op-args { a.instr.kind = ASM_CMP; $$ = a; } and = "and" a:basic-op-args { a.instr.kind = ASM_AND; $$ = a; } or = "or" a:basic-op-args { a.instr.kind = ASM_OR; $$ = a; } sub = "sub" a:basic-op-args { a.instr.kind = ASM_SUB; $$ = a; } @@ -210,9 +210,6 @@ static uint8_t regbits(AsmKind k) { return (k - (ASM_REG_BEGIN + 1)) % 16; } static uint8_t isreg(AsmKind k) { return k > ASM_REG_BEGIN && k < ASM_REG_END; } static uint8_t isreg64(AsmKind k) { return k >= ASM_RAX && k <= ASM_R15; } -/* Is an r$n style register variant. */ -static uint8_t isregr(AsmKind k) { return !!(regbits(k) & (1 << 3)); } - /* Compose a rex prefix - See intel manual. */ static uint8_t rexbyte(uint8_t w, uint8_t r, uint8_t x, uint8_t b) { return ((1 << 6) | ((!!w) << 3) | ((!!r) << 2) | ((!!x) << 1) | (!!b)); @@ -251,7 +248,7 @@ void assembleconstant(int64_t c, int nbytes) { The top byte is how many bytes we encode less 1. examples: - <nothing> encodes as -1 + <nothing> encodes as -1 0c encodes as 0x0000000c 02 03 encodes as 0x01000203 */ @@ -271,16 +268,14 @@ static void assemblevbytes(VarBytes bytes) { /* Assemble op +rw | op + rd. */ static void assembleplusr(uint8_t rexw, VarBytes prefix, VarBytes opcode, - AsmKind reg) { - uint8_t bits; + uint8_t reg) { uint8_t rex; assemblevbytes(prefix); - bits = regbits(reg); - rex = rexbyte(rexw, 0, 0, bits & (1 << 3)); + rex = rexbyte(rexw, 0, 0, reg & (1 << 3)); if (rex != rexbyte(0, 0, 0, 0)) sb(rex); - assemblevbytes(opcode | (bits & 7)); + assemblevbytes(opcode | (reg & 7)); } static void assemblemodregrm(uint8_t rex, VarBytes prefix, VarBytes opcode, @@ -467,7 +462,8 @@ static void assemblerrm(const Instr *instr, VarBytes prefix, VarBytes opcode) { } /* Assemble a 'basic op' which is just a repeated op pattern we have named. */ -static void assemblebasicop(const Instr *instr, VarBytes opcode, uint8_t immreg) { +static void assemblebasicop(const Instr *instr, VarBytes opcode, + uint8_t immreg) { VarBytes prefix; const Imm *imm; uint8_t rexw; @@ -498,7 +494,7 @@ static void assemblexchg(const Instr *xchg) { if (xchg->variant < 6) { AsmKind reg = (xchg->variant % 2) ? xchg->arg1->kind : xchg->arg2->kind; prefix = (xchg->variant < 2) ? 0x66 : -1; - assembleplusr(isreg64(reg), prefix, opcode, reg); + assembleplusr(isreg64(reg), prefix, opcode, regbits(reg)); } else { prefix = (((xchg->variant - 6) % 4) == 1) ? 0x66 : -1; assemblerrm(xchg, prefix, opcode); @@ -520,7 +516,8 @@ static void assemblemov(const Instr *mov) { if (mov->variant >= 4 && mov->variant <= 6) { imm = &mov->arg1->imm; - assembleplusr(isreg64(mov->arg2->kind), prefix, opcode, mov->arg2->kind); + assembleplusr(isreg64(mov->arg2->kind), prefix, opcode, + regbits(mov->arg2->kind)); assemblereloc(imm->v.l, imm->v.c, imm->nbytes, R_X86_64_32); } else if (mov->variant == 7 || mov->variant < 4) { rexw = ((mov->variant % 4) == 3); @@ -578,7 +575,8 @@ static void assembleshift(const Instr *instr, uint8_t immreg) { } } -static void assemblexmmbasicop(const Instr *instr, VarBytes prefix, VarBytes opcode) { +static void assemblexmmbasicop(const Instr *instr, VarBytes prefix, + VarBytes opcode) { uint8_t rexw, rex, reg, rm; if (instr->arg1->kind == ASM_MEMARG) { @@ -588,7 +586,7 @@ static void assemblexmmbasicop(const Instr *instr, VarBytes prefix, VarBytes opc assemblemem(&instr->arg2->memarg, 0, prefix, opcode, regbits(instr->arg1->kind)); } else { - rexw = isreg64(instr->arg1->kind); + rexw = isreg64(instr->arg1->kind) || isreg64(instr->arg2->kind); reg = regbits(instr->arg2->kind); rm = regbits(instr->arg1->kind); rex = rexbyte(rexw, reg & (1 << 3), 0, rm & (1 << 3)); @@ -739,8 +737,7 @@ static void assemble(void) { if (v->call.indirect) { if (v->call.target.indirect->kind == ASM_MEMARG) { - assemblemem(&v->call.target.indirect->memarg, 0, -1, 0xff, - 0x02); + assemblemem(&v->call.target.indirect->memarg, 0, -1, 0xff, 0x02); } else { rm = regbits(v->call.target.indirect->kind); rex = rexbyte(0, 0, 0, rm & (1 << 3)); @@ -773,14 +770,14 @@ static void assemble(void) { if (v->instr.arg1->kind == ASM_MEMARG) { assemblemem(&v->instr.arg1->memarg, 0, -1, 0xff, 0x06); } else { - assembleplusr(0, -1, 0x50, v->instr.arg1->kind); + assembleplusr(0, -1, 0x50, regbits(v->instr.arg1->kind)); } break; case ASM_POP: if (v->instr.arg1->kind == ASM_MEMARG) { assemblemem(&v->instr.arg1->memarg, 0, -1, 0x8f, 0x00); } else { - assembleplusr(0, -1, 0x58, v->instr.arg1->kind); + assembleplusr(0, -1, 0x58, regbits(v->instr.arg1->kind)); } break; case ASM_NOP: @@ -796,16 +793,22 @@ static void assemble(void) { sb2(0x48, 0x99); break; case ASM_CVTSI2SD: - assemblexmmbasicop(&v->instr, 0xf2, 0x01000f2A); + assemblexmmbasicop(&v->instr, 0xf2, 0x01000f2a); break; case ASM_CVTSI2SS: - assemblexmmbasicop(&v->instr, 0xf3, 0x01000f2A); + assemblexmmbasicop(&v->instr, 0xf3, 0x01000f2a); break; case ASM_CVTSS2SD: - assemblexmmbasicop(&v->instr, 0xf3, 0x01000f5A); + assemblexmmbasicop(&v->instr, 0xf3, 0x01000f5a); break; case ASM_CVTSD2SS: - assemblexmmbasicop(&v->instr, 0xf2, 0x01000f5A); + assemblexmmbasicop(&v->instr, 0xf2, 0x01000f5a); + break; + case ASM_CVTSD2SI: + assemblexmmbasicop(&v->instr, 0xf2, 0x01000f2d); + break; + case ASM_CVTSS2SI: + assemblexmmbasicop(&v->instr, 0xf3, 0x01000f2d); break; case ASM_RET: sb(0xc3); @@ -1,11 +1,11 @@ #include <assert.h> +#include <ctype.h> #include <elf.h> #include <errno.h> #include <stdarg.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> -#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -76,6 +76,8 @@ typedef enum { ASM_CVTSD2SS, ASM_CVTSI2SD, ASM_CVTSI2SS, + ASM_CVTSD2SI, + ASM_CVTSS2SI, ASM_DIV, ASM_IDIV, ASM_LEA, @@ -107,7 +109,7 @@ typedef enum { ASM_XORPS, // Registers, order matters. ASM_REG_BEGIN, - + ASM_AL, ASM_CL, ASM_DL, @@ -192,7 +194,7 @@ typedef enum { ASM_XMM13, ASM_XMM14, ASM_XMM15, - + /* RIP is in a special class of its own. */ ASM_RIP, ASM_NO_REG, @@ -200,7 +202,6 @@ typedef enum { ASM_REG_END, } AsmKind; - typedef union Parsev Parsev; typedef struct Label { @@ -284,7 +285,7 @@ typedef struct Call { uint32_t indirect; union { const Parsev *indirect; - Value direct; + Value direct; } target; } Call; diff --git a/test/test.sh b/test/test.sh index e81b051..bd512e8 100644 --- a/test/test.sh +++ b/test/test.sh @@ -35,6 +35,16 @@ t "callq *%r10" t "movb %r11b, (%rsi, %r12, 1)" +t "cvtsd2si %xmm1, %rax" +t "cvtsd2si %xmm10, %rax" +t "cvtsd2si %xmm1, %eax" +t "cvtsd2si %xmm10, %eax" + +t "cvtss2si %xmm1, %rax" +t "cvtss2si %xmm10, %rax" +t "cvtss2si %xmm1, %eax" +t "cvtss2si %xmm10, %eax" + t "cvtsi2sd %rax, %xmm1" t "cvtsi2sd %rax, %xmm10" t "cvtsi2sd (%rax), %xmm1" |
