From 62003a2d89772175a96b15cd358362a88a85b41a Mon Sep 17 00:00:00 2001
From: MerryMage <MerryMage@users.noreply.github.com>
Date: Sun, 7 Feb 2021 20:30:49 +0000
Subject: [PATCH] A32/ir_emitter: Implement UpdateUpperLocationDescriptor

---
 src/backend/x64/a32_emit_x64.cpp     | 9 +++++++++
 src/frontend/A32/ir_emitter.cpp      | 4 ++++
 src/frontend/A32/ir_emitter.h        | 1 +
 src/frontend/ir/microinstruction.cpp | 2 ++
 src/frontend/ir/opcodes.inc          | 1 +
 5 files changed, 17 insertions(+)

diff --git a/src/backend/x64/a32_emit_x64.cpp b/src/backend/x64/a32_emit_x64.cpp
index 887ad583..55c75bbb 100644
--- a/src/backend/x64/a32_emit_x64.cpp
+++ b/src/backend/x64/a32_emit_x64.cpp
@@ -770,6 +770,15 @@ void A32EmitX64::EmitA32BXWritePC(A32EmitContext& ctx, IR::Inst* inst) {
     }
 }
 
+void A32EmitX64::EmitA32UpdateUpperLocationDescriptor(A32EmitContext& ctx, IR::Inst*) {
+    for (auto& inst : ctx.block) {
+        if (inst.GetOpcode() == IR::Opcode::A32BXWritePC) {
+            return;
+        }
+    }
+    EmitSetUpperLocationDescriptor(ctx.EndLocation(), ctx.Location());
+}
+
 void A32EmitX64::EmitA32CallSupervisor(A32EmitContext& ctx, IR::Inst* inst) {
     ctx.reg_alloc.HostCall(nullptr);
 
diff --git a/src/frontend/A32/ir_emitter.cpp b/src/frontend/A32/ir_emitter.cpp
index ca1e91fe..024d9e0d 100644
--- a/src/frontend/A32/ir_emitter.cpp
+++ b/src/frontend/A32/ir_emitter.cpp
@@ -121,6 +121,10 @@ void IREmitter::LoadWritePC(const IR::U32& value) {
     }
 }
 
+void IREmitter::UpdateUpperLocationDescriptor() {
+    Inst(Opcode::A32UpdateUpperLocationDescriptor);
+}
+
 void IREmitter::CallSupervisor(const IR::U32& value) {
     Inst(Opcode::A32CallSupervisor, value);
 }
diff --git a/src/frontend/A32/ir_emitter.h b/src/frontend/A32/ir_emitter.h
index 57aa40d2..8d3d8df3 100644
--- a/src/frontend/A32/ir_emitter.h
+++ b/src/frontend/A32/ir_emitter.h
@@ -47,6 +47,7 @@ public:
     void BranchWritePC(const IR::U32& value);
     void BXWritePC(const IR::U32& value);
     void LoadWritePC(const IR::U32& value);
+    void UpdateUpperLocationDescriptor();
 
     void CallSupervisor(const IR::U32& value);
     void ExceptionRaised(Exception exception);
diff --git a/src/frontend/ir/microinstruction.cpp b/src/frontend/ir/microinstruction.cpp
index ac6d8152..3658aa74 100644
--- a/src/frontend/ir/microinstruction.cpp
+++ b/src/frontend/ir/microinstruction.cpp
@@ -155,6 +155,7 @@ bool Inst::ReadsFromCPSR() const {
     case Opcode::A32GetCFlag:
     case Opcode::A32GetVFlag:
     case Opcode::A32GetGEFlags:
+    case Opcode::A32UpdateUpperLocationDescriptor:
     case Opcode::A64GetCFlag:
     case Opcode::A64GetNZCVRaw:
     case Opcode::ConditionalSelect32:
@@ -179,6 +180,7 @@ bool Inst::WritesToCPSR() const {
     case Opcode::A32OrQFlag:
     case Opcode::A32SetGEFlags:
     case Opcode::A32SetGEFlagsCompressed:
+    case Opcode::A32UpdateUpperLocationDescriptor:
     case Opcode::A64SetNZCVRaw:
     case Opcode::A64SetNZCV:
         return true;
diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc
index a81a792f..d68a5f5c 100644
--- a/src/frontend/ir/opcodes.inc
+++ b/src/frontend/ir/opcodes.inc
@@ -31,6 +31,7 @@ A32OPC(GetGEFlags,                                          U32,
 A32OPC(SetGEFlags,                                          Void,           U32                                                             )
 A32OPC(SetGEFlagsCompressed,                                Void,           U32                                                             )
 A32OPC(BXWritePC,                                           Void,           U32                                                             )
+A32OPC(UpdateUpperLocationDescriptor,                       Void,                                                                           )
 A32OPC(CallSupervisor,                                      Void,           U32                                                             )
 A32OPC(ExceptionRaised,                                     Void,           U32,            U64                                             )
 A32OPC(DataSynchronizationBarrier,                          Void,                                                                           )