diff options
| author | Andrew Chambers <[email protected]> | 2021-10-11 16:57:19 +1300 |
|---|---|---|
| committer | Andrew Chambers <[email protected]> | 2021-10-11 16:57:19 +1300 |
| commit | 79f7dab1793f38773bb7570322488a887a9693dc (patch) | |
| tree | 9ca81f94b05157e3da5ec781e4be9ea7ccb8471e | |
| parent | 9e3472e4899c83a6a078db0b8881eead671fb7da (diff) | |
Work on floating point support.
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | asm.peg | 116 | ||||
| -rw-r--r-- | main.c | 57 | ||||
| -rw-r--r-- | minias.h | 38 | ||||
| -rw-r--r-- | test/test.sh | 27 |
5 files changed, 207 insertions, 33 deletions
@@ -29,7 +29,7 @@ cc -O2 *.c -o minias # Resources -- [intel reference](https://software.intel.com/content/dam/develop/external/us/en/documents-tps/325383-sdm-vol-2abcd.pdf) - Especially chapter 2 section 1. +- [intel reference](https://software.intel.com/content/dam/develop/external/us/en/documents-tps/325383-sdm-vol-2abcd.pdf) - Specifically chapter 2.1 and chapter 3.1. - [elf spec](https://refspecs.linuxfoundation.org/elf/elf.pdf) - [goas](https://github.com/DQNEO/goas) - [neatas](https://repo.or.cz/neatas.git) @@ -56,37 +56,42 @@ 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: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: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: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; } push = "push" ( @@ -160,6 +165,26 @@ idiv = "idiv" ( | args:r-opargs { args.instr.variant += 4 ; $$ = args; } ) { $$.instr.kind = ASM_IDIV; } +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); } +) { $$.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); } +) { $$.instr.kind = ASM_MULSS; } + +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); } +) { $$.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); } +) { $$.instr.kind = ASM_UCOMISD; } + mul = "mul" ( args:m-opargs { $$ = args; } | args:r-opargs { args.instr.variant += 4 ; $$ = args; } @@ -440,6 +465,35 @@ 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 = + # Reverse order due to peg ordering. + "%xmm15" { $$ = REG(ASM_XMM15); } + | "%xmm14" { $$ = REG(ASM_XMM14); } + | "%xmm13" { $$ = REG(ASM_XMM13); } + | "%xmm12" { $$ = REG(ASM_XMM12); } + | "%xmm11" { $$ = REG(ASM_XMM11); } + | "%xmm10" { $$ = REG(ASM_XMM10); } + | "%xmm9" { $$ = REG(ASM_XMM7); } + | "%xmm8" { $$ = REG(ASM_XMM7); } + | "%xmm7" { $$ = REG(ASM_XMM7); } + | "%xmm6" { $$ = REG(ASM_XMM6); } + | "%xmm5" { $$ = REG(ASM_XMM5); } + | "%xmm4" { $$ = REG(ASM_XMM4); } + | "%xmm3" { $$ = REG(ASM_XMM3); } + | "%xmm2" { $$ = REG(ASM_XMM2); } + | "%xmm1" { $$ = REG(ASM_XMM1); } + | "%xmm0" { $$ = REG(ASM_XMM0); } + # We disallow newlines in our strings, it is simpler for lineno tracking. string = '"' <(string-escape | ( ! '\n' ! '\\' !'"' .))*> '"' { $$.string = decodestring(yytext); } @@ -667,6 +667,29 @@ static void assembleshift(Instr *instr, uint8_t immreg) { } } +static void assemblemuls(Instr *instr, uint8_t prefix) { + Opcode opcode; + + opcode = 0x01000f59; + sb(prefix); + + if (instr->arg1->kind == ASM_MEMARG) { + assemblemem(&instr->arg1->memarg, 0, opcode, regbits(instr->arg2->kind), 8); + } else { + assemblemodregrm(0, opcode, 3, regbits(instr->arg2->kind), + regbits(instr->arg1->kind), 8); + } +} + +static void assembleucomis(Instr *instr, Opcode opcode) { + if (instr->arg1->kind == ASM_MEMARG) { + assemblemem(&instr->arg1->memarg, 0, opcode, regbits(instr->arg2->kind), 8); + } else { + assemblemodregrm(0, opcode, 3, regbits(instr->arg2->kind), + regbits(instr->arg1->kind), 8); + } +} + static void assemble(void) { Symbol *sym; Parsev *v; @@ -866,6 +889,12 @@ static void assemble(void) { case ASM_MUL: assembledivmulneg(&v->instr, 0x04); break; + case ASM_MULSD: + assemblemuls(&v->instr, 0xf2); + break; + case ASM_MULSS: + assemblemuls(&v->instr, 0xf3); + break; case ASM_IMUL: { Opcode opcode; uint8_t opsz; @@ -951,6 +980,34 @@ static void assemble(void) { } break; } + case ASM_UCOMISD: { + Opcode opcode = 0x01000f2e; + + sb(0x66); + + if (v->instr.arg1->kind == ASM_MEMARG) { + assemblemem(&v->instr.arg1->memarg, 0, opcode, + regbits(v->instr.arg2->kind), 8); + } else { + assemblemodregrm(0, opcode, 3, regbits(v->instr.arg2->kind), + regbits(v->instr.arg1->kind), 8); + } + + break; + } + case ASM_UCOMISS: { + Opcode opcode = 0x01000f2e; + + if (v->instr.arg1->kind == ASM_MEMARG) { + assemblemem(&v->instr.arg1->memarg, 0, opcode, + regbits(v->instr.arg2->kind), 8); + } else { + assemblemodregrm(0, opcode, 3, regbits(v->instr.arg2->kind), + regbits(v->instr.arg1->kind), 8); + } + + break; + } case ASM_XOR: { static uint8_t variant2op[24] = { 0x34, 0x35, 0x35, 0x35, 0x80, 0x81, 0x81, 0x81, @@ -74,6 +74,8 @@ typedef enum { ASM_IDIV, ASM_LEA, ASM_MUL, + ASM_MULSD, + ASM_MULSS, ASM_IMUL, ASM_MOV, ASM_MOVSX, @@ -87,6 +89,8 @@ typedef enum { ASM_SHR, ASM_SUB, ASM_TEST, + ASM_UCOMISD, + ASM_UCOMISS, ASM_XCHG, ASM_XOR, // Registers, order matters. @@ -159,6 +163,40 @@ typedef enum { ASM_R13, 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, + ASM_XMM3, + ASM_XMM4, + ASM_XMM5, + ASM_XMM6, + ASM_XMM7, + ASM_XMM8, + ASM_XMM9, + ASM_XMM10, + ASM_XMM11, + ASM_XMM12, + ASM_XMM13, + ASM_XMM14, + ASM_XMM15, /* RIP is in a special class of its own. */ ASM_RIP, diff --git a/test/test.sh b/test/test.sh index 9946f7f..8658e5f 100644 --- a/test/test.sh +++ b/test/test.sh @@ -30,6 +30,32 @@ t () { echo -n "." } +t "mulsd %xmm0, %xmm1" +t "mulsd (%rax), %xmm1" +t "mulsd %xmm10, %xmm1" +t "mulsd %xmm1, %xmm10" +t "mulsd %xmm10, %xmm11" +t "mulsd (%rax), %xmm11" +t "mulss %xmm0, %xmm1" +t "mulss (%rax), %xmm1" +t "mulss %xmm10, %xmm1" +t "mulss %xmm1, %xmm10" +t "mulss %xmm10, %xmm11" +t "mulss (%rax), %xmm11" + + +t "ucomisd %xmm0, %xmm1" +t "ucomisd (%rax), %xmm1" +t "ucomisd %xmm10, %xmm1" +t "ucomisd %xmm1, %xmm10" +t "ucomisd %xmm10, %xmm11" +t "ucomisd (%rax), %xmm11" +t "ucomiss %xmm0, %xmm1" +t "ucomiss (%rax), %xmm1" +t "ucomiss %xmm10, %xmm1" +t "ucomiss %xmm1, %xmm10" +t "ucomiss %xmm10, %xmm11" +t "ucomiss (%rax), %xmm11" for r in a b @@ -57,7 +83,6 @@ do t "lea 2147483647(%r${r}x, %r${r}x, 4), %r${r}x" done - t "ret" t "cltd" t "cqto" |
