aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-12 21:45:45 +1300
committerAndrew Chambers <[email protected]>2021-10-12 21:45:45 +1300
commit974e600961c849e552433756fe3c2c69f1b3677a (patch)
treef6bea6a59b74eb1045d1d7aa634110d76f1d83d6
parent25fa3f8e631f26b09303b1263d9bf5cf4e564c64 (diff)
Add instructions needed to assemble sqlite3.
-rw-r--r--asm.peg45
-rw-r--r--main.c40
-rw-r--r--minias.h11
-rw-r--r--test/test.sh29
4 files changed, 110 insertions, 15 deletions
diff --git a/asm.peg b/asm.peg
index c00abec..0a80d3a 100644
--- a/asm.peg
+++ b/asm.peg
@@ -1,19 +1,19 @@
line =
- ws? s:stmt eol { yy->v = s; }
+ ws? s:stmt { yy->v = s; }
| eol { yy->v.kind = ASM_BLANK; }
| . { yy->v.kind = ASM_SYNTAX_ERROR; }
-ws =
- [ \t]+
- | "/*" (! "*/" . )* "*/" # XXX multiline comments break our line numbers.
+ws = ([ \t] | comment)+
+
+comment = "/*" (! "*/" . )* "*/" # XXX multiline comments break our line numbers.
eol = ws? "\n"
stmt =
- '.' d:directive {$$ = d;}
- | i:instr { $$ = i; }
- | l:label { $$ = l; }
+ '.' d:directive eol {$$ = d;}
+ | l:label eol { $$ = l; }
+ | i:instr eol { $$ = i; }
directive =
"glob" 'o'? 'l' ws i:ident
@@ -28,6 +28,8 @@ directive =
{ $$.balign = (Balign){.kind = ASM_DIR_BALIGN, .align = n.i64 }; }
| "byte" ws v:value
{ $$.dirbyte = (Byte){.kind = ASM_DIR_BYTE, .value = v.value }; }
+ | "short" ws v:value
+ { $$.dirshort = (Short){.kind = ASM_DIR_BYTE, .value = v.value }; }
| "int" ws v:value
{ $$.dirint = (Int){.kind = ASM_DIR_INT, .value = v.value }; }
| "quad" ws v:value
@@ -74,6 +76,8 @@ instr =
| i:jmp { $$ = i; }
| i:add { $$ = i; }
| i:and { $$ = i; }
+ | i:cvtsi2sd { $$ = i; }
+ | i:cvtsi2ss { $$ = i; }
| i:cvtss2sd { $$ = i; }
| i:cvtsd2ss { $$ = i; }
| i:cmp { $$ = i; }
@@ -85,12 +89,14 @@ instr =
| i:mul { $$ = i; }
| i:imul { $$ = i; }
| i:neg { $$ = i; }
+ | i:movaps { $$ = i; }
| i:movsd { $$ = i; }
| i:movss { $$ = i; }
| i:movsx { $$ = i; }
| i:movzx { $$ = i; }
| i:mov { $$ = i; }
| i:or { $$ = i; }
+ | i:pxor { $$ = i; }
| i:set { $$ = i; }
| i:sub { $$ = i; }
| i:sal { $$ = i; }
@@ -185,6 +191,20 @@ idiv = "idiv" (
# TODO XXX Combine the xmm variants into single instructions??
+cvtsi2sd = "cvtsi2sd" (
+ ws s:r32 ws? ',' ws? d:xmm { $$ = INSTR2(0, s, d); }
+ | ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); }
+ | ws s:r64 ws? ',' ws? d:xmm { $$ = INSTR2(2, s, d); }
+ | ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(3, s, d); }
+) { $$.instr.kind = ASM_CVTSI2SD; }
+
+cvtsi2ss = "cvtsi2ss" (
+ ws s:r32 ws? ',' ws? d:xmm { $$ = INSTR2(0, s, d); }
+ | ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); }
+ | ws s:r64 ws? ',' ws? d:xmm { $$ = INSTR2(2, s, d); }
+ | ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(3, s, d); }
+) { $$.instr.kind = ASM_CVTSI2SS; }
+
cvtss2sd = "cvtss2sd" (
ws s:xmm ws? ',' ws? d:xmm { $$ = INSTR2(0, s, d); }
| ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); }
@@ -195,6 +215,12 @@ cvtsd2ss = "cvtsd2ss" (
| ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); }
) { $$.instr.kind = ASM_CVTSD2SS; }
+movaps = "movaps" (
+ ws s:xmm ws? ',' ws? d:xmm { $$ = INSTR2(0, s, d); }
+ | ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); }
+ | ws s:xmm ws? ',' ws? d:m { $$ = INSTR2(2, s, d); }
+) { $$.instr.kind = ASM_MOVAPS; }
+
mulsd = "mulsd" (
ws s:xmm ws? ',' ws? d:xmm { $$ = INSTR2(0, s, d); }
| ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); }
@@ -227,6 +253,11 @@ ucomisd = "ucomisd" (
| ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); }
) { $$.instr.kind = ASM_UCOMISD; }
+pxor = "pxor" (
+ ws s:xmm ws? ',' ws? d:xmm { $$ = INSTR2(0, s, d); }
+ | ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); }
+) { $$.instr.kind = ASM_PXOR; }
+
xorpd = "xorpd" (
ws s:xmm ws? ',' ws? d:xmm { $$ = INSTR2(0, s, d); }
| ws s:m ws? ',' ws? d:xmm { $$ = INSTR2(1, s, d); }
diff --git a/main.c b/main.c
index 8ba72e2..a36250a 100644
--- a/main.c
+++ b/main.c
@@ -689,15 +689,19 @@ static void assembleshift(Instr *instr, uint8_t immreg) {
}
static void assemblexmmbasicop(Instr *instr, VarBytes prefix, VarBytes opcode) {
- uint8_t rex, reg, rm;
+ uint8_t rexw, rex, reg, rm;
if (instr->arg1->kind == ASM_MEMARG) {
assemblemem(&instr->arg1->memarg, 0, prefix, opcode,
regbits(instr->arg2->kind));
+ } else if (instr->arg2->kind == ASM_MEMARG) {
+ assemblemem(&instr->arg2->memarg, 0, prefix, opcode,
+ regbits(instr->arg1->kind));
} else {
+ rexw = isreg64(instr->arg1->kind);
reg = regbits(instr->arg2->kind);
rm = regbits(instr->arg1->kind);
- rex = rexbyte(0, reg & (1 << 3), 0, rm & (1 << 3));
+ rex = rexbyte(rexw, reg & (1 << 3), 0, rm & (1 << 3));
assemblemodregrm(rex, prefix, opcode, 0x03, reg, rm);
}
}
@@ -821,6 +825,9 @@ static void assemble(void) {
case ASM_DIR_BYTE:
assemblereloc(v->dirbyte.value.l, v->dirbyte.value.c, 1, R_X86_64_32);
break;
+ case ASM_DIR_SHORT:
+ assemblereloc(v->dirshort.value.l, v->dirshort.value.c, 2, R_X86_64_32);
+ break;
case ASM_DIR_INT:
assemblereloc(v->dirint.value.l, v->dirint.value.c, 4, R_X86_64_32);
break;
@@ -896,6 +903,18 @@ static void assemble(void) {
case ASM_CQTO:
sb2(0x48, 0x99);
break;
+ case ASM_CVTSI2SD:
+ assemblexmmbasicop(&v->instr, 0xf2, 0x01000f2A);
+ break;
+ case ASM_CVTSI2SS:
+ assemblexmmbasicop(&v->instr, 0xf3, 0x01000f2A);
+ break;
+ case ASM_CVTSS2SD:
+ assemblexmmbasicop(&v->instr, 0xf3, 0x01000f5A);
+ break;
+ case ASM_CVTSD2SS:
+ assemblexmmbasicop(&v->instr, 0xf2, 0x01000f5A);
+ break;
case ASM_RET:
sb(0xc3);
break;
@@ -905,15 +924,16 @@ static void assemble(void) {
assemblerrm(&v->instr, prefix, 0x8d);
break;
}
+ case ASM_MOVAPS: {
+ VarBytes prefix, opcode;
+ prefix = EMPTY_VBYTES;
+ opcode = v->instr.variant == 2 ? 0x01000f29 : 0x01000f28;
+ assemblexmmbasicop(&v->instr, prefix, opcode);
+ break;
+ }
case ASM_MOV:
assemblemov(&v->instr);
break;
- case ASM_CVTSS2SD:
- assemblexmmbasicop(&v->instr, 0xf3, 0x01000f5A);
- break;
- case ASM_CVTSD2SS:
- assemblexmmbasicop(&v->instr, 0xf2, 0x01000f5A);
- break;
case ASM_MOVSD:
assemblemovsmmx(&v->instr, 0xf2);
break;
@@ -1013,6 +1033,10 @@ static void assemble(void) {
assemblebasicop(&v->instr, variant2op[v->instr.variant], 0x01);
break;
}
+ case ASM_PXOR: {
+ assemblexmmbasicop(&v->instr, 0x66, 0x01000fef);
+ break;
+ }
case ASM_SET: {
VarBytes prefix, opcode;
uint8_t rex, reg, rm;
diff --git a/minias.h b/minias.h
index b5eb779..cbaae9b 100644
--- a/minias.h
+++ b/minias.h
@@ -55,6 +55,7 @@ typedef enum {
ASM_DIR_TEXT,
ASM_DIR_FILL,
ASM_DIR_BYTE,
+ ASM_DIR_SHORT,
ASM_DIR_INT,
ASM_DIR_QUAD,
ASM_DIR_BALIGN,
@@ -73,6 +74,8 @@ typedef enum {
ASM_CMP,
ASM_CVTSS2SD,
ASM_CVTSD2SS,
+ ASM_CVTSI2SD,
+ ASM_CVTSI2SS,
ASM_DIV,
ASM_IDIV,
ASM_LEA,
@@ -81,12 +84,14 @@ typedef enum {
ASM_MULSS,
ASM_IMUL,
ASM_MOV,
+ ASM_MOVAPS,
ASM_MOVSD,
ASM_MOVSS,
ASM_MOVSX,
ASM_MOVZX,
ASM_NEG,
ASM_OR,
+ ASM_PXOR,
ASM_SAL,
ASM_SAR,
ASM_SET,
@@ -227,6 +232,11 @@ typedef struct {
typedef struct {
AsmKind kind;
Value value;
+} Short;
+
+typedef struct {
+ AsmKind kind;
+ Value value;
} Int;
typedef struct {
@@ -305,6 +315,7 @@ union Parsev {
Jmp jmp;
Fill fill;
Byte dirbyte;
+ Short dirshort;
Int dirint;
Quad dirquad;
Imm imm;
diff --git a/test/test.sh b/test/test.sh
index 115be24..a916740 100644
--- a/test/test.sh
+++ b/test/test.sh
@@ -33,6 +33,32 @@ t () {
t "callq *%rax"
t "callq *%r10"
+t "cvtsi2sd %rax, %xmm1"
+t "cvtsi2sd %rax, %xmm10"
+t "cvtsi2sd (%rax), %xmm1"
+t "cvtsi2sd (%rax), %xmm10"
+t "cvtsi2sd %eax, %xmm1"
+t "cvtsi2sd %eax, %xmm10"
+
+t "cvtsi2ss %rax, %xmm1"
+t "cvtsi2ss %rax, %xmm10"
+t "cvtsi2ss (%rax), %xmm1"
+t "cvtsi2ss (%rax), %xmm10"
+t "cvtsi2ss %eax, %xmm1"
+t "cvtsi2ss %eax, %xmm10"
+
+t "pxor %xmm0, %xmm1"
+t "pxor %xmm10, %xmm1"
+t "pxor (%rax), %xmm0"
+t "pxor (%rax), %xmm10"
+
+t "movaps %xmm0, %xmm1"
+t "movaps %xmm0, (%rax)"
+t "movaps (%rax), %xmm0"
+t "movaps %xmm0, %xmm1"
+t "movaps %xmm10, (%rax)"
+t "movaps (%rax), %xmm10"
+
t "cvtss2sd %xmm0, %xmm1"
t "cvtss2sd %xmm10, %xmm1"
t "cvtss2sd (%rax), %xmm0"
@@ -43,6 +69,9 @@ t "cvtsd2ss %xmm10, %xmm1"
t "cvtsd2ss (%rax), %xmm0"
t "cvtsd2ss (%rax), %xmm10"
+t "pxor %xmm0, %xmm1"
+t "pxor (%rax), %xmm1"
+
t "xorps %xmm0, %xmm1"
t "xorps %xmm10, %xmm1"
t "xorps (%rax), %xmm0"