diff options
| author | Andrew Chambers <[email protected]> | 2021-10-12 21:45:45 +1300 |
|---|---|---|
| committer | Andrew Chambers <[email protected]> | 2021-10-12 21:45:45 +1300 |
| commit | 974e600961c849e552433756fe3c2c69f1b3677a (patch) | |
| tree | f6bea6a59b74eb1045d1d7aa634110d76f1d83d6 | |
| parent | 25fa3f8e631f26b09303b1263d9bf5cf4e564c64 (diff) | |
Add instructions needed to assemble sqlite3.
| -rw-r--r-- | asm.peg | 45 | ||||
| -rw-r--r-- | main.c | 40 | ||||
| -rw-r--r-- | minias.h | 11 | ||||
| -rw-r--r-- | test/test.sh | 29 |
4 files changed, 110 insertions, 15 deletions
@@ -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); } @@ -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; @@ -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" |
