aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-11 16:57:19 +1300
committerAndrew Chambers <[email protected]>2021-10-11 16:57:19 +1300
commit79f7dab1793f38773bb7570322488a887a9693dc (patch)
tree9ca81f94b05157e3da5ec781e4be9ea7ccb8471e
parent9e3472e4899c83a6a078db0b8881eead671fb7da (diff)
Work on floating point support.
-rw-r--r--README.md2
-rw-r--r--asm.peg116
-rw-r--r--main.c57
-rw-r--r--minias.h38
-rw-r--r--test/test.sh27
5 files changed, 207 insertions, 33 deletions
diff --git a/README.md b/README.md
index 1505a4d..bc9cbe2 100644
--- a/README.md
+++ b/README.md
@@ -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)
diff --git a/asm.peg b/asm.peg
index 742da11..8923b08 100644
--- a/asm.peg
+++ b/asm.peg
@@ -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); }
diff --git a/main.c b/main.c
index a169a42..0d58350 100644
--- a/main.c
+++ b/main.c
@@ -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,
diff --git a/minias.h b/minias.h
index 750f481..fdcbc09 100644
--- a/minias.h
+++ b/minias.h
@@ -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"