aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-13 22:46:17 +1300
committerAndrew Chambers <[email protected]>2021-10-13 22:46:17 +1300
commitdfe49d06a417f4cb6a9ee0c67f7c1234c2315a7a (patch)
tree3efcf1ffc9df78f76026f6304e7d7ba1ea4410de
parent174fc3291257e96a81a8757ae22dd0e14d3b259f (diff)
Fix broken test.
-rw-r--r--asm.peg20
-rw-r--r--main.c47
-rw-r--r--minias.h11
-rw-r--r--test/test.sh10
4 files changed, 59 insertions, 29 deletions
diff --git a/asm.peg b/asm.peg
index bcc7935..bc1ed72 100644
--- a/asm.peg
+++ b/asm.peg
@@ -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; }
diff --git a/main.c b/main.c
index 69a73b7..6858d70 100644
--- a/main.c
+++ b/main.c
@@ -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);
diff --git a/minias.h b/minias.h
index 5c9452c..d46a8b5 100644
--- a/minias.h
+++ b/minias.h
@@ -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"