From 2a378692fa768d4c138b622ae4ee7a7277c65c02 Mon Sep 17 00:00:00 2001
From: SachinVin <sachinvinayak2000@gmail.com>
Date: Sat, 27 Jul 2019 10:03:06 +0530
Subject: [PATCH] a64 emitter: Vector Halving and Saturation instructions

---
 src/backend/A64/emitter/a64_emitter.cpp | 40 +++++++++++++++++++++++++
 src/backend/A64/emitter/a64_emitter.h   | 10 +++++++
 2 files changed, 50 insertions(+)

diff --git a/src/backend/A64/emitter/a64_emitter.cpp b/src/backend/A64/emitter/a64_emitter.cpp
index 4e16b6a4..942a6ea0 100644
--- a/src/backend/A64/emitter/a64_emitter.cpp
+++ b/src/backend/A64/emitter/a64_emitter.cpp
@@ -2851,6 +2851,14 @@ void ARM64FloatEmitter::AND(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
 void ARM64FloatEmitter::BSL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
     EmitThreeSame(1, 1, 3, Rd, Rn, Rm);
 }
+void ARM64FloatEmitter::CMGE(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    EmitThreeSame(0, static_cast<u32>(esize), 0b00111, Rd, Rn, Rm);
+}
+void ARM64FloatEmitter::CMGE_zero(ESize esize, ARM64Reg Rd, ARM64Reg Rn) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    Emit2RegMisc(IsQuad(Rd), 1, static_cast<u32>(esize), 0b1000, Rd, Rn);
+}
 void ARM64FloatEmitter::CMGT(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
     ASSERT(!(IsDouble(Rd) && esize == D));
     EmitThreeSame(0, static_cast<u32>(esize), 0b00110, Rd, Rn, Rm);
@@ -2948,6 +2956,22 @@ void ARM64FloatEmitter::REV32(u8 size, ARM64Reg Rd, ARM64Reg Rn) {
 void ARM64FloatEmitter::REV64(u8 size, ARM64Reg Rd, ARM64Reg Rn) {
     Emit2RegMisc(IsQuad(Rd), 0, size >> 4, 0, Rd, Rn);
 }
+void ARM64FloatEmitter::SHADD(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    EmitThreeSame(0, static_cast<u32>(esize), 0b0, Rd, Rn, Rm);
+}
+void ARM64FloatEmitter::UHADD(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    EmitThreeSame(1, static_cast<u32>(esize), 0b0, Rd, Rn, Rm);
+}
+void ARM64FloatEmitter::SHSUB(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    EmitThreeSame(0, static_cast<u32>(esize), 0b00100, Rd, Rn, Rm);
+}
+void ARM64FloatEmitter::UHSUB(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    EmitThreeSame(1, static_cast<u32>(esize), 0b00100, Rd, Rn, Rm);
+}
 void ARM64FloatEmitter::SMIN(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
     ASSERT(!(IsDouble(Rd) && esize == D));
     EmitThreeSame(0, static_cast<u32>(esize), 0b01101, Rd, Rn, Rm);
@@ -2956,6 +2980,22 @@ void ARM64FloatEmitter::UMIN(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
     ASSERT(!(IsDouble(Rd) && esize == D));
     EmitThreeSame(1, static_cast<u32>(esize), 0b01101, Rd, Rn, Rm);
 }
+void ARM64FloatEmitter::SQADD(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    EmitThreeSame(0, static_cast<u32>(esize), 0b00001, Rd, Rn, Rm);
+}
+void ARM64FloatEmitter::SQSUB(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    EmitThreeSame(0, static_cast<u32>(esize), 0b00101, Rd, Rn, Rm);
+}
+void ARM64FloatEmitter::UQADD(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    EmitThreeSame(1, static_cast<u32>(esize), 0b00001, Rd, Rn, Rm);
+}
+void ARM64FloatEmitter::UQSUB(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm) {
+    ASSERT(!(IsDouble(Rd) && esize == D));
+    EmitThreeSame(1, static_cast<u32>(esize), 0b00101, Rd, Rn, Rm);
+}
 void ARM64FloatEmitter::SCVTF(u8 size, ARM64Reg Rd, ARM64Reg Rn) {
     Emit2RegMisc(IsQuad(Rd), 0, size >> 6, 0x1D, Rd, Rn);
 }
diff --git a/src/backend/A64/emitter/a64_emitter.h b/src/backend/A64/emitter/a64_emitter.h
index c89b0424..14d7e45a 100644
--- a/src/backend/A64/emitter/a64_emitter.h
+++ b/src/backend/A64/emitter/a64_emitter.h
@@ -967,6 +967,8 @@ public:
     void SUB(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
     void AND(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
     void BSL(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
+    void CMGE(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
+    void CMGE_zero(ESize esize, ARM64Reg Rd, ARM64Reg Rn);
     void CMGT(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
     void CMHI(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
     void CMHS(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
@@ -997,8 +999,16 @@ public:
     void REV16(u8 size, ARM64Reg Rd, ARM64Reg Rn);
     void REV32(u8 size, ARM64Reg Rd, ARM64Reg Rn);
     void REV64(u8 size, ARM64Reg Rd, ARM64Reg Rn);
+    void SHADD(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
+    void UHADD(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
+    void SHSUB(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
+    void UHSUB(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
     void SMIN(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
     void UMIN(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
+    void SQADD(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
+    void SQSUB(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
+    void UQADD(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
+    void UQSUB(ESize esize, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm);
     void SCVTF(u8 size, ARM64Reg Rd, ARM64Reg Rn);
     void UCVTF(u8 size, ARM64Reg Rd, ARM64Reg Rn);
     void SCVTF(u8 size, ARM64Reg Rd, ARM64Reg Rn, int scale);