summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2020-06-18 07:37:44 +0200
committerPierre Bourdon <delroth@gmail.com>2020-06-18 07:37:44 +0200
commitdd1fc711c727bf34ecf1caa4ba4c8f14fafdff1e (patch)
treeb70b7653716fad300ce025e9e2eb11fe6d893eba
parentd6341c4117d59565b3bc42264d6fa5ba7e796526 (diff)
PowerPC: partially implement thermal related SPRs
Doesn't support triggering interrupts when the thermal threshold is exceeded, but allows polling for temperature information. The THRM[123] registers are documented in most PPC datasheets, see e.g. this PPC750CX one: http://datasheets.chipdb.org/IBM/PowerPC/750/750cx_um3-17-05.pdf
-rw-r--r--Source/Core/Core/PowerPC/Gekko.h36
-rw-r--r--Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp31
-rw-r--r--Source/Core/Core/PowerPC/PowerPC.h3
3 files changed, 70 insertions, 0 deletions
diff --git a/Source/Core/Core/PowerPC/Gekko.h b/Source/Core/Core/PowerPC/Gekko.h
index b11a7565f0..590bd5c3ea 100644
--- a/Source/Core/Core/PowerPC/Gekko.h
+++ b/Source/Core/Core/PowerPC/Gekko.h
@@ -744,6 +744,38 @@ union UReg_BAT_Lo
explicit UReg_BAT_Lo(u32 hex_) : Hex{hex_} {}
};
+union UReg_THRM12
+{
+ struct
+ {
+ u32 V : 1; // Valid
+ u32 TIE : 1; // Thermal Interrupt Enable
+ u32 TID : 1; // Thermal Interrupt Direction
+ u32 : 20;
+ u32 THRESHOLD : 7; // Temperature Threshold, 0-127°C
+ u32 TIV : 1; // Thermal Interrupt Valid
+ u32 TIN : 1; // Thermal Interrupt
+ };
+ u32 Hex = 0;
+
+ UReg_THRM12() = default;
+ explicit UReg_THRM12(u32 hex_) : Hex{hex_} {}
+};
+
+union UReg_THRM3
+{
+ struct
+ {
+ u32 E : 1; // Enable
+ u32 SITV : 13; // Sample Interval Timer Value
+ u32 : 18;
+ };
+ u32 Hex = 0;
+
+ UReg_THRM3() = default;
+ explicit UReg_THRM3(u32 hex_) : Hex{hex_} {}
+};
+
union UReg_PTE
{
struct
@@ -854,6 +886,10 @@ enum
SPR_MMCR1 = 956,
SPR_PMC3 = 957,
SPR_PMC4 = 958,
+
+ SPR_THRM1 = 1020,
+ SPR_THRM2 = 1021,
+ SPR_THRM3 = 1022,
};
// Exceptions
diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
index d40462c7b5..7a5c0455b5 100644
--- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
+++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
@@ -459,6 +459,37 @@ void Interpreter::mtspr(UGeckoInstruction inst)
PowerPC::IBATUpdated();
}
break;
+
+ case SPR_THRM1:
+ case SPR_THRM2:
+ case SPR_THRM3:
+ {
+ // We update both THRM1 and THRM2 when either of the 3 thermal control
+ // registers are updated. THRM1 and THRM2 are independent, but THRM3 has
+ // settings that impact both.
+ //
+ // TODO: Support thermal interrupts when enabled.
+ constexpr u32 SIMULATED_TEMP = 42; // °C
+
+ auto UpdateThermalReg = [](UReg_THRM12* reg) {
+ if (!THRM3.E || !reg->V)
+ {
+ reg->TIV = 0;
+ }
+ else
+ {
+ reg->TIV = 1;
+ if (reg->TID)
+ reg->TIN = SIMULATED_TEMP < reg->THRESHOLD;
+ else
+ reg->TIN = SIMULATED_TEMP > reg->THRESHOLD;
+ }
+ };
+
+ UpdateThermalReg(&THRM1);
+ UpdateThermalReg(&THRM2);
+ break;
+ }
}
}
diff --git a/Source/Core/Core/PowerPC/PowerPC.h b/Source/Core/Core/PowerPC/PowerPC.h
index fe1e11ef03..9d551de056 100644
--- a/Source/Core/Core/PowerPC/PowerPC.h
+++ b/Source/Core/Core/PowerPC/PowerPC.h
@@ -220,6 +220,9 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst);
#define DMAL (*(UReg_DMAL*)&PowerPC::ppcState.spr[SPR_DMAL])
#define MMCR0 ((UReg_MMCR0&)PowerPC::ppcState.spr[SPR_MMCR0])
#define MMCR1 ((UReg_MMCR1&)PowerPC::ppcState.spr[SPR_MMCR1])
+#define THRM1 ((UReg_THRM12&)PowerPC::ppcState.spr[SPR_THRM1])
+#define THRM2 ((UReg_THRM12&)PowerPC::ppcState.spr[SPR_THRM2])
+#define THRM3 ((UReg_THRM3&)PowerPC::ppcState.spr[SPR_THRM3])
#define PC PowerPC::ppcState.pc
#define NPC PowerPC::ppcState.npc
#define FPSCR PowerPC::ppcState.fpscr