aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-11 22:58:04 +1300
committerAndrew Chambers <[email protected]>2021-10-11 22:58:04 +1300
commit7c4eb5d7d3f8f207c34da175d11ad6f359896c64 (patch)
tree7a9b23dedff390777e9b479221215a1ab30098dc
parent1090ba79a608c8ca37d6067053b000fca57b5014 (diff)
Add more xmm instructions.
-rw-r--r--asm.peg140
-rw-r--r--main.c39
-rw-r--r--minias.h23
-rw-r--r--test/test.sh34
4 files changed, 159 insertions, 77 deletions
diff --git a/asm.peg b/asm.peg
index 8923b08..aaad38f 100644
--- a/asm.peg
+++ b/asm.peg
@@ -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); }
diff --git a/main.c b/main.c
index a298fc6..302e16c 100644
--- a/main.c
+++ b/main.c
@@ -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] = {
diff --git a/minias.h b/minias.h
index fdcbc09..46a9779 100644
--- a/minias.h
+++ b/minias.h
@@ -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"