diff options
| author | Andrew Chambers <[email protected]> | 2021-10-11 22:58:04 +1300 |
|---|---|---|
| committer | Andrew Chambers <[email protected]> | 2021-10-11 22:58:04 +1300 |
| commit | 7c4eb5d7d3f8f207c34da175d11ad6f359896c64 (patch) | |
| tree | 7a9b23dedff390777e9b479221215a1ab30098dc | |
| parent | 1090ba79a608c8ca37d6067053b000fca57b5014 (diff) | |
Add more xmm instructions.
| -rw-r--r-- | asm.peg | 140 | ||||
| -rw-r--r-- | main.c | 39 | ||||
| -rw-r--r-- | minias.h | 23 | ||||
| -rw-r--r-- | test/test.sh | 34 |
4 files changed, 159 insertions, 77 deletions
@@ -56,42 +56,48 @@ label = instr = # XXX Order the rules by frequency to get better lookup time. - "nop" { $$.kind = ASM_NOP; } - | "leave" { $$.kind = ASM_LEAVE; } - | "ret" { $$.kind = ASM_RET; } - | "cltd" { $$.kind = ASM_CLTD; } - | "cqto" { $$.kind = ASM_CQTO; } - | i:push { $$ = i; } - | i:pop { $$ = i; } - | i:call { $$ = i; } - | i:jmp { $$ = i; } - | i:add { $$ = i; } - | i:and { $$ = i; } - | i:cmp { $$ = i; } - | i:div { $$ = i; } - | i:idiv { $$ = i; } - | i:lea { $$ = i; } - | i:mulsd { $$ = i; } - | i:mulss { $$ = i; } - | i:mul { $$ = i; } - | i:imul { $$ = i; } - | i:neg { $$ = i; } - | i:movsx { $$ = i; } - | i:movzx { $$ = i; } - | i:mov { $$ = i; } - | i:or { $$ = i; } - | i:set { $$ = i; } - | i:sub { $$ = i; } - | i:sal { $$ = i; } - | i:sar { $$ = i; } - | i:shl { $$ = i; } - | i:shr { $$ = i; } - | i:test { $$ = i; } - | i:ucomisd { $$ = i; } - | i:ucomiss { $$ = i; } - | i:test { $$ = i; } - | i:xchg { $$ = i; } - | i:xor { $$ = i; } + "nop" { $$.kind = ASM_NOP; } + | "leave" { $$.kind = ASM_LEAVE; } + | "ret" { $$.kind = ASM_RET; } + | "cltd" { $$.kind = ASM_CLTD; } + | "cqto" { $$.kind = ASM_CQTO; } + | i:push { $$ = i; } + | i:pop { $$ = i; } + | i:call { $$ = i; } + | i:jmp { $$ = i; } + | i:add { $$ = i; } + | i:and { $$ = i; } + | i:cvtss2sd { $$ = i; } + | i:cvtsd2ss { $$ = i; } + | i:cmp { $$ = i; } + | i:div { $$ = i; } + | i:idiv { $$ = i; } + | i:lea { $$ = i; } + | i:mulsd { $$ = i; } + | i:mulss { $$ = i; } + | i:mul { $$ = i; } + | i:imul { $$ = i; } + | i:neg { $$ = i; } + | i:movsd { $$ = i; } + | i:movss { $$ = i; } + | i:movsx { $$ = i; } + | i:movzx { $$ = i; } + | i:mov { $$ = i; } + | i:or { $$ = i; } + | i:set { $$ = i; } + | i:sub { $$ = i; } + | i:sal { $$ = i; } + | i:sar { $$ = i; } + | i:shl { $$ = i; } + | i:shr { $$ = i; } + | i:test { $$ = i; } + | i:ucomisd { $$ = i; } + | i:ucomiss { $$ = i; } + | i:test { $$ = i; } + | i:xchg { $$ = i; } + | i:xorpd { $$ = i; } + | i:xorps { $$ = i; } + | i:xor { $$ = i; } push = "push" ( @@ -165,26 +171,60 @@ idiv = "idiv" ( | args:r-opargs { args.instr.variant += 4 ; $$ = args; } ) { $$.instr.kind = ASM_IDIV; } +# TODO XXX Combine the xmm variants into single instructions?? + +cvtss2sd = "cvtss2sd" ( + 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_CVTSS2SD; } + +cvtsd2ss = "cvtsd2ss" ( + 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_CVTSD2SS; } + mulsd = "mulsd" ( - ws s:r-xmm ws? ',' ws? d:r-xmm { $$ = INSTR2(0, s, d); } - | ws s:m ws? ',' ws? d:r-xmm { $$ = INSTR2(1, s, d); } + 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_MULSD; } mulss = "mulss" ( - ws s:r-xmm ws? ',' ws? d:r-xmm { $$ = INSTR2(0, s, d); } - | ws s:m ws? ',' ws? d:r-xmm { $$ = INSTR2(1, s, d); } + 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_MULSS; } +movss = "movss" ( + 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_MOVSS; } + +movsd = "movsd" ( + 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_MOVSD; } + ucomiss = "ucomiss" ( - ws s:r-xmm ws? ',' ws? d:r-xmm { $$ = INSTR2(0, s, d); } - | ws s:m ws? ',' ws? d:r-xmm { $$ = INSTR2(1, s, d); } + 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_UCOMISS; } ucomisd = "ucomisd" ( - ws s:r-xmm ws? ',' ws? d:r-xmm { $$ = INSTR2(0, s, d); } - | ws s:m ws? ',' ws? d:r-xmm { $$ = INSTR2(1, s, d); } + 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_UCOMISD; } +xorpd = "xorpd" ( + 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_XORPD; } + +xorps = "xorps" ( + 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_XORPS; } + mul = "mul" ( args:m-opargs { $$ = args; } | args:r-opargs { args.instr.variant += 4 ; $$ = args; } @@ -465,17 +505,7 @@ r64 = | "%r14" ![lwb] { $$ = REG(ASM_R14); } | "%r15" ![lwb] { $$ = REG(ASM_R15); } -r-mm = - "%mm0" { $$ = REG(ASM_MM0); } - | "%mm1" { $$ = REG(ASM_MM1); } - | "%mm2" { $$ = REG(ASM_MM2); } - | "%mm3" { $$ = REG(ASM_MM3); } - | "%mm4" { $$ = REG(ASM_MM4); } - | "%mm5" { $$ = REG(ASM_MM5); } - | "%mm6" { $$ = REG(ASM_MM6); } - | "%mm7" { $$ = REG(ASM_MM7); } - -r-xmm = +xmm = # Reverse order due to peg ordering. "%xmm15" { $$ = REG(ASM_XMM15); } | "%xmm14" { $$ = REG(ASM_XMM14); } @@ -679,7 +679,7 @@ static void assembleshift(Instr *instr, uint8_t immreg) { } } -static void assemblemulsucomis(Instr *instr, VarBytes prefix, VarBytes opcode) { +static void assemblexmmbasicop(Instr *instr, VarBytes prefix, VarBytes opcode) { if (instr->arg1->kind == ASM_MEMARG) { assemblemem(&instr->arg1->memarg, 0, prefix, opcode, regbits(instr->arg2->kind)); @@ -689,6 +689,17 @@ static void assemblemulsucomis(Instr *instr, VarBytes prefix, VarBytes opcode) { } } +static void assemblemovsmmx(Instr *instr, VarBytes prefix) { + VarBytes opcode; + if (instr->variant == 2) { + opcode = 0x01000f11; + assemblerrm(instr, prefix, opcode); + } else { + opcode = 0x01000f10; + assemblexmmbasicop(instr, prefix, opcode); + } +} + static void assemble(void) { Symbol *sym; Parsev *v; @@ -833,6 +844,18 @@ static void assemble(void) { 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; + case ASM_MOVSS: + assemblemovsmmx(&v->instr, 0xf3); + break; case ASM_MOVSX: { VarBytes opcode; if (v->instr.variant >= 10) { @@ -890,10 +913,10 @@ static void assemble(void) { assembledivmulneg(&v->instr, 0x04); break; case ASM_MULSD: - assemblemulsucomis(&v->instr, 0xf2, 0x01000f59); + assemblexmmbasicop(&v->instr, 0xf2, 0x01000f59); break; case ASM_MULSS: - assemblemulsucomis(&v->instr, 0xf3, 0x01000f59); + assemblexmmbasicop(&v->instr, 0xf3, 0x01000f59); break; case ASM_IMUL: { VarBytes prefix, opcode; @@ -987,10 +1010,16 @@ static void assemble(void) { break; } case ASM_UCOMISD: - assemblemulsucomis(&v->instr, 0x66, 0x01000f2e); + assemblexmmbasicop(&v->instr, 0x66, 0x01000f2e); break; case ASM_UCOMISS: - assemblemulsucomis(&v->instr, EMPTY_VBYTES, 0x01000f2e); + assemblexmmbasicop(&v->instr, EMPTY_VBYTES, 0x01000f2e); + break; + case ASM_XORPD: + assemblexmmbasicop(&v->instr, 0x66, 0x01000f57); + break; + case ASM_XORPS: + assemblexmmbasicop(&v->instr, EMPTY_VBYTES, 0x01000f57); break; case ASM_XOR: { static uint8_t variant2op[24] = { @@ -70,6 +70,8 @@ typedef enum { ASM_ADD, ASM_AND, ASM_CMP, + ASM_CVTSS2SD, + ASM_CVTSD2SS, ASM_DIV, ASM_IDIV, ASM_LEA, @@ -78,6 +80,8 @@ typedef enum { ASM_MULSS, ASM_IMUL, ASM_MOV, + ASM_MOVSD, + ASM_MOVSS, ASM_MOVSX, ASM_MOVZX, ASM_NEG, @@ -93,6 +97,8 @@ typedef enum { ASM_UCOMISS, ASM_XCHG, ASM_XOR, + ASM_XORPD, + ASM_XORPS, // Registers, order matters. ASM_REG_BEGIN, @@ -164,23 +170,6 @@ typedef enum { ASM_R14, ASM_R15, - ASM_MM0, - ASM_MM1, - ASM_MM2, - ASM_MM3, - ASM_MM4, - ASM_MM5, - ASM_MM6, - ASM_MM7, - ASM_MM_RESRVED_0, /* Reserved to preserve reg group size. */ - ASM_MM_RESRVED_1, - ASM_MM_RESRVED_2, - ASM_MM_RESRVED_3, - ASM_MM_RESRVED_4, - ASM_MM_RESRVED_5, - ASM_MM_RESRVED_6, - ASM_MM_RESRVED_7, - ASM_XMM0, ASM_XMM1, ASM_XMM2, diff --git a/test/test.sh b/test/test.sh index 4da49d3..153821a 100644 --- a/test/test.sh +++ b/test/test.sh @@ -30,6 +30,40 @@ t () { echo -n "." } +t "cvtss2sd %xmm0, %xmm1" +t "cvtss2sd %xmm10, %xmm1" +t "cvtss2sd (%rax), %xmm0" +t "cvtss2sd (%rax), %xmm10" + +t "cvtsd2ss %xmm0, %xmm1" +t "cvtsd2ss %xmm10, %xmm1" +t "cvtsd2ss (%rax), %xmm0" +t "cvtsd2ss (%rax), %xmm10" + +t "xorps %xmm0, %xmm1" +t "xorps %xmm10, %xmm1" +t "xorps (%rax), %xmm0" +t "xorps (%rax), %xmm10" + +t "xorpd %xmm0, %xmm1" +t "xorpd %xmm10, %xmm1" +t "xorpd (%rax), %xmm0" +t "xorpd (%rax), %xmm10" + +t "movsd %xmm0, %xmm1" +t "movsd %xmm0, (%rax)" +t "movsd (%rax), %xmm0" +t "movsd %xmm0, %xmm1" +t "movsd %xmm10, (%rax)" +t "movsd (%rax), %xmm10" + +t "movss %xmm0, %xmm1" +t "movss %xmm0, (%rax)" +t "movss (%rax), %xmm0" +t "movss %xmm0, %xmm1" +t "movss %xmm10, (%rax)" +t "movss (%rax), %xmm10" + t "mulsd %xmm0, %xmm1" t "mulsd (%rax), %xmm1" t "mulsd %xmm10, %xmm1" |
