From 90f93db51a374d865050d3d9075d6d44aa7031dc Mon Sep 17 00:00:00 2001
From: jonathanzetier <207571460+jonathanzetier@users.noreply.github.com>
Date: Mon, 14 Apr 2025 07:10:58 -0700
Subject: [PATCH] Add support for MSR/MRS (banked register)
---
Ghidra/Processors/ARM/data/languages/ARM.sinc | 22 ++-
.../data/languages/ARMTHUMBinstructions.sinc | 144 +++++++++++++++++-
.../ARM/data/languages/ARMinstructions.sinc | 86 +++++++++++
.../Processors/ARM/data/languages/ARMt.pspec | 4 +
.../ARM/data/languages/ARMtTHUMB.pspec | 4 +
5 files changed, 258 insertions(+), 2 deletions(-)
diff --git a/Ghidra/Processors/ARM/data/languages/ARM.sinc b/Ghidra/Processors/ARM/data/languages/ARM.sinc
index 756faecbbbc..5822b8197bd 100644
--- a/Ghidra/Processors/ARM/data/languages/ARM.sinc
+++ b/Ghidra/Processors/ARM/data/languages/ARM.sinc
@@ -11,7 +11,6 @@ define register offset=0x0020 size=4 [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11
define register offset=0x0060 size=1 [ NG ZR CY OV tmpNG tmpZR tmpCY tmpOV shift_carry TB Q GE1 GE2 GE3 GE4 ];
define register offset=0x0070 size=4 [ cpsr spsr ];
define register offset=0x0080 size=4 [ mult_addr ]; # Special internal register for dealing with multiple stores/loads
-define register offset=0x0084 size=4 [ r14_svc r13_svc spsr_svc ];
define register offset=0x0090 size=8 [ mult_dat8 ]; # Special internal register for dealing with multiple stores/loads
define register offset=0x0090 size=16 [ mult_dat16 ]; # Special internal register for dealing with multiple stores/loads
define register offset=0x00A0 size=4 [ fpsr ]; # floating point state register (for FPA10 floating-point accelerator)
@@ -75,6 +74,22 @@ define register offset=0x0200 size=4 [ cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7 cr8 cr9 c
@endif # SIMD
+@if defined(VERSION_7)
+ # 0x400-0x500 is marked as volatile in the .pspec; update it there if this
+ # space is moved or expanded
+ # 33 registers x 4 bytes/register = 0x84 bytes consumed
+ define register offset=0x0400 size=4 [ r8_usr r9_usr r10_usr r11_usr r12_usr sp_usr lr_usr
+ r8_fiq r9_fiq r10_fiq r11_fiq r12_fiq sp_fiq lr_fiq
+ sp_irq lr_irq
+ sp_svc lr_svc
+ sp_mon lr_mon
+ sp_abt lr_abt
+ sp_hyp elr_hyp
+ sp_und lr_und
+ spsr_fiq spsr_irq spsr_svc spsr_mon spsr_abt spsr_hyp spsr_und ];
+
+@endif # defined(VERSION_7)
+
# Define context bits
# WARNING: when adjusting context keep compiler packing in mind
# and make sure fields do not span a 32-bit boundary before or
@@ -189,6 +204,11 @@ define pcodeop ReverseBitOrder;
define pcodeop SendEvent;
define pcodeop setEndianState;
+define pcodeop UnkBankedRegRead;
+define pcodeop UnkBankedSpsrRead;
+define pcodeop UnkBankedRegWrite;
+define pcodeop UnkBankedSpsrWrite;
+
# Copies ISAModeSwitch to TMode
define pcodeop setISAMode;
diff --git a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc
index 8f801357db9..1f323253054 100644
--- a/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc
+++ b/Ghidra/Processors/ARM/data/languages/ARMTHUMBinstructions.sinc
@@ -34,6 +34,7 @@ define token instr2 (16)
define token instrThumb (16)
op4=(4,15)
+ op5=(5,15)
op6=(6,15)
op7=(7,15)
op8=(8,15)
@@ -149,6 +150,12 @@ define token instrThumb (16)
sysm37=(3,7)
sysm02=(0,2)
+ mrs_banked_m1=(0,3)
+ mrs_banked_m=(4,4)
+
+ msr_banked_m1=(8,11)
+ msr_banked_m=(4,4)
+
thc0001=(0,1)
thc0002=(0,2)
@@ -2973,7 +2980,142 @@ define pcodeop setStackMode;
# TODO: should we set sp ?
}
-@endif
+@endif # defined(VERSION_7M)
+
+@if defined(VERSION_7)
+
+BankedSysmThumb: banked_sysm is op5=0x79f & thc0003 ; thc0404
+ [ banked_sysm = (thc0404 << 4) $or thc0003; ]
+{
+ export *[const]:4 banked_sysm;
+}
+
+BankedSysmThumb: banked_sysm is op5=0x79c ; thc0811 & thc0404
+ [ banked_sysm = (thc0404 << 4) $or thc0811; ]
+{
+ export *[const]:4 banked_sysm;
+}
+
+# MRS/MSR (banked register)
+# See https://developer.arm.com/documentation/ddi0597/2024-12/Base-Instructions/MSR--Banked-register---Move-general-purpose-register-to-Banked-or-Special-register-
+
+# MRS, SPSR = 0, M = 0
+BankedRegThumb: r8_usr is r8_usr & op4=0xf3e & mrs_banked_m1=0b0000 ; mrs_banked_m=0 { export r8_usr; }
+BankedRegThumb: r9_usr is r9_usr & op4=0xf3e & mrs_banked_m1=0b0001 ; mrs_banked_m=0 { export r9_usr; }
+BankedRegThumb: r10_usr is r10_usr & op4=0xf3e & mrs_banked_m1=0b0010 ; mrs_banked_m=0 { export r10_usr; }
+BankedRegThumb: r11_usr is r11_usr & op4=0xf3e & mrs_banked_m1=0b0011 ; mrs_banked_m=0 { export r11_usr; }
+BankedRegThumb: r12_usr is r12_usr & op4=0xf3e & mrs_banked_m1=0b0100 ; mrs_banked_m=0 { export r12_usr; }
+BankedRegThumb: sp_usr is sp_usr & op4=0xf3e & mrs_banked_m1=0b0101 ; mrs_banked_m=0 { export sp_usr; }
+BankedRegThumb: lr_usr is lr_usr & op4=0xf3e & mrs_banked_m1=0b0110 ; mrs_banked_m=0 { export lr_usr; }
+
+BankedRegThumb: r8_fiq is r8_fiq & op4=0xf3e & mrs_banked_m1=0b1000 ; mrs_banked_m=0 { export r8_fiq; }
+BankedRegThumb: r9_fiq is r9_fiq & op4=0xf3e & mrs_banked_m1=0b1001 ; mrs_banked_m=0 { export r9_fiq; }
+BankedRegThumb: r10_fiq is r10_fiq & op4=0xf3e & mrs_banked_m1=0b1010 ; mrs_banked_m=0 { export r10_fiq; }
+BankedRegThumb: r11_fiq is r11_fiq & op4=0xf3e & mrs_banked_m1=0b1011 ; mrs_banked_m=0 { export r11_fiq; }
+BankedRegThumb: r12_fiq is r12_fiq & op4=0xf3e & mrs_banked_m1=0b1100 ; mrs_banked_m=0 { export r12_fiq; }
+BankedRegThumb: sp_fiq is sp_fiq & op4=0xf3e & mrs_banked_m1=0b1101 ; mrs_banked_m=0 { export sp_fiq; }
+BankedRegThumb: lr_fiq is lr_fiq & op4=0xf3e & mrs_banked_m1=0b1110 ; mrs_banked_m=0 { export lr_fiq; }
+
+# MSR, SPSR = 0, M = 0
+BankedRegThumb: r8_usr is r8_usr & op4=0xf38 ; msr_banked_m1=0b0000 & msr_banked_m=0 { export r8_usr; }
+BankedRegThumb: r9_usr is r9_usr & op4=0xf38 ; msr_banked_m1=0b0001 & msr_banked_m=0 { export r9_usr; }
+BankedRegThumb: r10_usr is r10_usr & op4=0xf38 ; msr_banked_m1=0b0010 & msr_banked_m=0 { export r10_usr; }
+BankedRegThumb: r11_usr is r11_usr & op4=0xf38 ; msr_banked_m1=0b0011 & msr_banked_m=0 { export r11_usr; }
+BankedRegThumb: r12_usr is r12_usr & op4=0xf38 ; msr_banked_m1=0b0100 & msr_banked_m=0 { export r12_usr; }
+BankedRegThumb: sp_usr is sp_usr & op4=0xf38 ; msr_banked_m1=0b0101 & msr_banked_m=0 { export sp_usr; }
+BankedRegThumb: lr_usr is lr_usr & op4=0xf38 ; msr_banked_m1=0b0110 & msr_banked_m=0 { export lr_usr; }
+
+BankedRegThumb: r8_fiq is r8_fiq & op4=0xf38 ; msr_banked_m1=0b1000 & msr_banked_m=0 { export r8_fiq; }
+BankedRegThumb: r9_fiq is r9_fiq & op4=0xf38 ; msr_banked_m1=0b1001 & msr_banked_m=0 { export r9_fiq; }
+BankedRegThumb: r10_fiq is r10_fiq & op4=0xf38 ; msr_banked_m1=0b1010 & msr_banked_m=0 { export r10_fiq; }
+BankedRegThumb: r11_fiq is r11_fiq & op4=0xf38 ; msr_banked_m1=0b1011 & msr_banked_m=0 { export r11_fiq; }
+BankedRegThumb: r12_fiq is r12_fiq & op4=0xf38 ; msr_banked_m1=0b1100 & msr_banked_m=0 { export r12_fiq; }
+BankedRegThumb: sp_fiq is sp_fiq & op4=0xf38 ; msr_banked_m1=0b1101 & msr_banked_m=0 { export sp_fiq; }
+BankedRegThumb: lr_fiq is lr_fiq & op4=0xf38 ; msr_banked_m1=0b1110 & msr_banked_m=0 { export lr_fiq; }
+
+# MRS, SPSR = 0, M = 1
+BankedRegThumb: lr_irq is lr_irq & op4=0xf3e & mrs_banked_m1=0b0000 ; mrs_banked_m=1 { export lr_irq; }
+BankedRegThumb: sp_irq is sp_irq & op4=0xf3e & mrs_banked_m1=0b0001 ; mrs_banked_m=1 { export sp_irq; }
+BankedRegThumb: lr_svc is lr_svc & op4=0xf3e & mrs_banked_m1=0b0010 ; mrs_banked_m=1 { export lr_svc; }
+BankedRegThumb: sp_svc is sp_svc & op4=0xf3e & mrs_banked_m1=0b0011 ; mrs_banked_m=1 { export sp_svc; }
+BankedRegThumb: lr_abt is lr_abt & op4=0xf3e & mrs_banked_m1=0b0100 ; mrs_banked_m=1 { export lr_abt; }
+BankedRegThumb: sp_abt is sp_abt & op4=0xf3e & mrs_banked_m1=0b0101 ; mrs_banked_m=1 { export sp_abt; }
+BankedRegThumb: lr_und is lr_und & op4=0xf3e & mrs_banked_m1=0b0110 ; mrs_banked_m=1 { export lr_und; }
+BankedRegThumb: sp_und is sp_und & op4=0xf3e & mrs_banked_m1=0b0111 ; mrs_banked_m=1 { export sp_und; }
+
+BankedRegThumb: lr_mon is lr_mon & op4=0xf3e & mrs_banked_m1=0b1100 ; mrs_banked_m=1 { export lr_mon; }
+BankedRegThumb: sp_mon is sp_mon & op4=0xf3e & mrs_banked_m1=0b1101 ; mrs_banked_m=1 { export sp_mon; }
+BankedRegThumb: elr_hyp is elr_hyp & op4=0xf3e & mrs_banked_m1=0b1110 ; mrs_banked_m=1 { export elr_hyp; }
+BankedRegThumb: sp_hyp is sp_hyp & op4=0xf3e & mrs_banked_m1=0b1111 ; mrs_banked_m=1 { export sp_hyp; }
+
+# MSR, SPSR = 0, M = 1
+BankedRegThumb: lr_irq is lr_irq & op4=0xf38 ; msr_banked_m1=0b0000 & msr_banked_m=1 { export lr_irq; }
+BankedRegThumb: sp_irq is sp_irq & op4=0xf38 ; msr_banked_m1=0b0001 & msr_banked_m=1 { export sp_irq; }
+BankedRegThumb: lr_svc is lr_svc & op4=0xf38 ; msr_banked_m1=0b0010 & msr_banked_m=1 { export lr_svc; }
+BankedRegThumb: sp_svc is sp_svc & op4=0xf38 ; msr_banked_m1=0b0011 & msr_banked_m=1 { export sp_svc; }
+BankedRegThumb: lr_abt is lr_abt & op4=0xf38 ; msr_banked_m1=0b0100 & msr_banked_m=1 { export lr_abt; }
+BankedRegThumb: sp_abt is sp_abt & op4=0xf38 ; msr_banked_m1=0b0101 & msr_banked_m=1 { export sp_abt; }
+BankedRegThumb: lr_und is lr_und & op4=0xf38 ; msr_banked_m1=0b0110 & msr_banked_m=1 { export lr_und; }
+BankedRegThumb: sp_und is sp_und & op4=0xf38 ; msr_banked_m1=0b0111 & msr_banked_m=1 { export sp_und; }
+
+BankedRegThumb: lr_mon is lr_mon & op4=0xf38 ; msr_banked_m1=0b1100 & msr_banked_m=1 { export lr_mon; }
+BankedRegThumb: sp_mon is sp_mon & op4=0xf38 ; msr_banked_m1=0b1101 & msr_banked_m=1 { export sp_mon; }
+BankedRegThumb: elr_hyp is elr_hyp & op4=0xf38 ; msr_banked_m1=0b1110 & msr_banked_m=1 { export elr_hyp; }
+BankedRegThumb: sp_hyp is sp_hyp & op4=0xf38 ; msr_banked_m1=0b1111 & msr_banked_m=1 { export sp_hyp; }
+
+# Fallback: unknown registers
+BankedRegThumb: "banked_reg_sysm("^BankedSysmThumb^")" is (op4=0xf3e ; op0) & BankedSysmThumb { tmp:4 = UnkBankedRegRead(BankedSysmThumb:1); export tmp; }
+BankedRegThumb: "banked_reg_sysm("^BankedSysmThumb^")" is (op4=0xf38 & thc0404=0 & Rn0003 ; op0) & BankedSysmThumb { tmp:4 = UnkBankedRegWrite(BankedSysmThumb:1, Rn0003); export tmp; }
+
+# MRS, SPSR = 1
+BankedSpsrThumb: spsr_fiq is spsr_fiq & op4=0xf3f & mrs_banked_m1=0b1110 ; mrs_banked_m=0 { export spsr_fiq; }
+BankedSpsrThumb: spsr_irq is spsr_irq & op4=0xf3f & mrs_banked_m1=0b0000 ; mrs_banked_m=1 { export spsr_irq; }
+BankedSpsrThumb: spsr_svc is spsr_svc & op4=0xf3f & mrs_banked_m1=0b0010 ; mrs_banked_m=1 { export spsr_svc; }
+BankedSpsrThumb: spsr_abt is spsr_abt & op4=0xf3f & mrs_banked_m1=0b0100 ; mrs_banked_m=1 { export spsr_abt; }
+BankedSpsrThumb: spsr_und is spsr_und & op4=0xf3f & mrs_banked_m1=0b0110 ; mrs_banked_m=1 { export spsr_und; }
+BankedSpsrThumb: spsr_mon is spsr_mon & op4=0xf3f & mrs_banked_m1=0b1100 ; mrs_banked_m=1 { export spsr_mon; }
+BankedSpsrThumb: spsr_hyp is spsr_hyp & op4=0xf3f & mrs_banked_m1=0b1110 ; mrs_banked_m=1 { export spsr_hyp; }
+
+# MSR, SPSR = 1
+BankedSpsrThumb: spsr_fiq is spsr_fiq & op4=0xf39 ; msr_banked_m1=0b1110 & msr_banked_m=0 { export spsr_fiq; }
+BankedSpsrThumb: spsr_irq is spsr_irq & op4=0xf39 ; msr_banked_m1=0b0000 & msr_banked_m=1 { export spsr_irq; }
+BankedSpsrThumb: spsr_svc is spsr_svc & op4=0xf39 ; msr_banked_m1=0b0010 & msr_banked_m=1 { export spsr_svc; }
+BankedSpsrThumb: spsr_abt is spsr_abt & op4=0xf39 ; msr_banked_m1=0b0100 & msr_banked_m=1 { export spsr_abt; }
+BankedSpsrThumb: spsr_und is spsr_und & op4=0xf39 ; msr_banked_m1=0b0110 & msr_banked_m=1 { export spsr_und; }
+BankedSpsrThumb: spsr_mon is spsr_mon & op4=0xf39 ; msr_banked_m1=0b1100 & msr_banked_m=1 { export spsr_mon; }
+BankedSpsrThumb: spsr_hyp is spsr_hyp & op4=0xf39 ; msr_banked_m1=0b1110 & msr_banked_m=1 { export spsr_hyp; }
+
+# Fallback: unknown registers
+BankedSpsrThumb: "banked_spsr_sysm("^BankedSysmThumb^")" is (op4=0xf3f ; op0) & BankedSysmThumb { tmp:4 = UnkBankedSpsrRead(BankedSysmThumb:1); export tmp; }
+BankedSpsrThumb: "banked_spsr_sysm("^BankedSysmThumb^")" is (op4=0xf39 & Rn0003 ; op0) & BankedSysmThumb { tmp:4 = UnkBankedSpsrWrite(BankedSysmThumb:1, Rn0003); export tmp; }
+
+
+:mrs^ItCond Rd0811,BankedRegThumb is TMode=1 & ItCond & (op4=0xf3e; op12=0x8 & Rd0811 & thc0507=0x1 & thc0003=0x0) & BankedRegThumb
+{
+ build ItCond;
+ Rd0811 = BankedRegThumb;
+}
+
+:mrs^ItCond Rd0811,BankedSpsrThumb is TMode=1 & ItCond & (op4=0xf3f; op12=0x8 & Rd0811 & thc0507=0x1 & thc0003=0x0) & BankedSpsrThumb
+{
+ build ItCond;
+ Rd0811 = BankedSpsrThumb;
+}
+
+:msr^ItCond BankedRegThumb,Rn0003 is TMode=1 & ItCond & (op4=0xf38 & Rn0003; op12=0x8 & thc0507=0x1 & thc0003=0x0) & BankedRegThumb
+{
+ build ItCond;
+ BankedRegThumb = Rn0003;
+}
+
+:msr^ItCond BankedSpsrThumb,Rn0003 is TMode=1 & ItCond & (op4=0xf39 & Rn0003; op12=0x8 & thc0507=0x1 & thc0003=0x0) & BankedSpsrThumb
+{
+ build ItCond;
+ BankedSpsrThumb = Rn0003;
+}
+
+
+@endif # defined(VERSION_7)
thpsrmask: is th_psrmask=0 { export 0:4; }
thpsrmask: "_c" is th_psrmask=1 { export 0xff:4; }
diff --git a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc
index ddd0fa648d4..b4944552cce 100644
--- a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc
+++ b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc
@@ -88,6 +88,8 @@ define token instrArm (32)
x=(5,5)
r=(5,5)
y=(6,6)
+ banked_m1=(16,19)
+ banked_m=(8,8)
# Advanced SIMD and VFP instruction fields
D22=(22,22)
@@ -4142,6 +4144,66 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
Rd = coprocessor_movefromRt(t_cpn,t_op1,t_opc2,CRn,CRm);
}
+BankedSysmArm: banked_sysm is banked_m & banked_m1
+ [ banked_sysm = (banked_m << 4) $or banked_m1; ]
+{
+ export *[const]:4 banked_sysm;
+}
+
+# MRS/MSR (banked register)
+# See https://developer.arm.com/documentation/ddi0597/2024-12/Base-Instructions/MSR--Banked-register---Move-general-purpose-register-to-Banked-or-Special-register-
+#
+# M1/M are in the same places for MRS/MSR instructions, so no need to
+# distinguish between them
+
+# SPSR = 0, M = 0
+BankedRegArm: r8_usr is r8_usr & banked_m=0 & banked_m1=0b0000 { export r8_usr; }
+BankedRegArm: r9_usr is r9_usr & banked_m=0 & banked_m1=0b0001 { export r9_usr; }
+BankedRegArm: r10_usr is r10_usr & banked_m=0 & banked_m1=0b0010 { export r10_usr; }
+BankedRegArm: r11_usr is r11_usr & banked_m=0 & banked_m1=0b0011 { export r11_usr; }
+BankedRegArm: r12_usr is r12_usr & banked_m=0 & banked_m1=0b0100 { export r12_usr; }
+BankedRegArm: sp_usr is sp_usr & banked_m=0 & banked_m1=0b0101 { export sp_usr; }
+BankedRegArm: lr_usr is lr_usr & banked_m=0 & banked_m1=0b0110 { export lr_usr; }
+
+BankedRegArm: r8_fiq is r8_fiq & banked_m=0 & banked_m1=0b1000 { export r8_fiq; }
+BankedRegArm: r9_fiq is r9_fiq & banked_m=0 & banked_m1=0b1001 { export r9_fiq; }
+BankedRegArm: r10_fiq is r10_fiq & banked_m=0 & banked_m1=0b1010 { export r10_fiq; }
+BankedRegArm: r11_fiq is r11_fiq & banked_m=0 & banked_m1=0b1011 { export r11_fiq; }
+BankedRegArm: r12_fiq is r12_fiq & banked_m=0 & banked_m1=0b1100 { export r12_fiq; }
+BankedRegArm: sp_fiq is sp_fiq & banked_m=0 & banked_m1=0b1101 { export sp_fiq; }
+BankedRegArm: lr_fiq is lr_fiq & banked_m=0 & banked_m1=0b1110 { export lr_fiq; }
+
+# SPSR = 0, M = 0
+BankedRegArm: lr_irq is lr_irq & banked_m=1 & banked_m1=0b0000 { export lr_irq; }
+BankedRegArm: sp_irq is sp_irq & banked_m=1 & banked_m1=0b0001 { export sp_irq; }
+BankedRegArm: lr_svc is lr_svc & banked_m=1 & banked_m1=0b0010 { export lr_svc; }
+BankedRegArm: sp_svc is sp_svc & banked_m=1 & banked_m1=0b0011 { export sp_svc; }
+BankedRegArm: lr_abt is lr_abt & banked_m=1 & banked_m1=0b0100 { export lr_abt; }
+BankedRegArm: sp_abt is sp_abt & banked_m=1 & banked_m1=0b0101 { export sp_abt; }
+BankedRegArm: lr_und is lr_und & banked_m=1 & banked_m1=0b0110 { export lr_und; }
+BankedRegArm: sp_und is sp_und & banked_m=1 & banked_m1=0b0111 { export sp_und; }
+
+BankedRegArm: lr_mon is lr_mon & banked_m=1 & banked_m1=0b1100 { export lr_mon; }
+BankedRegArm: sp_mon is sp_mon & banked_m=1 & banked_m1=0b1101 { export sp_mon; }
+BankedRegArm: elr_hyp is elr_hyp & banked_m=1 & banked_m1=0b1110 { export elr_hyp; }
+BankedRegArm: sp_hyp is sp_hyp & banked_m=1 & banked_m1=0b1111 { export sp_hyp; }
+
+# Fallback: unknown registers
+BankedRegArm: "banked_reg_sysm("^BankedSysmArm^")" is c2027=0x10 & BankedSysmArm { tmp:4 = UnkBankedRegRead(BankedSysmArm:1); export tmp; }
+BankedRegArm: "banked_reg_sysm("^BankedSysmArm^")" is c2027=0x12 & RnLo & BankedSysmArm { tmp:4 = UnkBankedRegWrite(BankedSysmArm:1, RnLo); export tmp; }
+
+# MRS/MSR (banked register), spsr=1
+BankedSpsrArm: spsr_fiq is spsr_fiq & banked_m=0 & banked_m1=0b1110 { export spsr_fiq; }
+BankedSpsrArm: spsr_irq is spsr_irq & banked_m=1 & banked_m1=0b0000 { export spsr_irq; }
+BankedSpsrArm: spsr_svc is spsr_svc & banked_m=1 & banked_m1=0b0010 { export spsr_svc; }
+BankedSpsrArm: spsr_abt is spsr_abt & banked_m=1 & banked_m1=0b0100 { export spsr_abt; }
+BankedSpsrArm: spsr_und is spsr_und & banked_m=1 & banked_m1=0b0110 { export spsr_und; }
+BankedSpsrArm: spsr_mon is spsr_mon & banked_m=1 & banked_m1=0b1100 { export spsr_mon; }
+BankedSpsrArm: spsr_hyp is spsr_hyp & banked_m=1 & banked_m1=0b1110 { export spsr_hyp; }
+
+# Fallback: unknown registers
+BankedSpsrArm: "banked_spsr_sysm("^BankedSysmArm^")" is c2027=0x14 & BankedSysmArm { tmp:4 = UnkBankedSpsrRead(BankedSysmArm:1); export tmp; }
+BankedSpsrArm: "banked_spsr_sysm("^BankedSysmArm^")" is c2027=0x16 & RnLo & BankedSysmArm { tmp:4 = UnkBankedSpsrWrite(BankedSysmArm:1, RnLo); export tmp; }
:mrs^COND Rd,cpsr is $(AMODE) & ARMcond=1 & COND & c2027=16 & c1619=15 & Rd & offset_12=0 & cpsr
{
@@ -4156,6 +4218,18 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
Rd = spsr;
}
+:mrs^COND Rd,BankedRegArm is $(AMODE) & ARMcond=1 & COND & c2027=0x10 & Rd & c0911=1 & c0007=0 & BankedRegArm
+{
+ build COND;
+ Rd = BankedRegArm;
+}
+
+:mrs^COND Rd,BankedSpsrArm is $(AMODE) & ARMcond=1 & COND & c2027=0x14 & Rd & c0911=1 & c0007=0 & BankedSpsrArm
+{
+ build COND;
+ Rd = BankedSpsrArm;
+}
+
:msr^COND cpsrmask,shift1 is $(AMODE) & ARMcond=1 & COND & c2027=50 & cpsrmask & c1215=15 & c2627=0 & shift1
{
build COND;
@@ -4193,6 +4267,18 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
spsr = (spsr& ~spsrmask) | (rm & spsrmask);
}
+:msr^COND BankedRegArm,RnLo is $(AMODE) & ARMcond=1 & COND & c2027=0x12 & c0915=0x79 & c0407=0 & RnLo & BankedRegArm
+{
+ build COND;
+ BankedRegArm = RnLo;
+}
+
+:msr^COND BankedSpsrArm,RnLo is $(AMODE) & ARMcond=1 & COND & c2027=0x16 & c0915=0x79 & c0407=0 & RnLo & BankedSpsrArm
+{
+ build COND;
+ BankedSpsrArm = RnLo;
+}
+
:mul^COND^SBIT_ZN rn,rm,rs is $(AMODE) & ARMcond=1 & COND & c2527=0 & c2124=0 & SBIT_ZN & rn & c1215=0 & rs & c0407=9 & rm
{
build COND;
diff --git a/Ghidra/Processors/ARM/data/languages/ARMt.pspec b/Ghidra/Processors/ARM/data/languages/ARMt.pspec
index ff62a392868..11fb4acf812 100644
--- a/Ghidra/Processors/ARM/data/languages/ARMt.pspec
+++ b/Ghidra/Processors/ARM/data/languages/ARMt.pspec
@@ -41,6 +41,10 @@
+
+
+
+
diff --git a/Ghidra/Processors/ARM/data/languages/ARMtTHUMB.pspec b/Ghidra/Processors/ARM/data/languages/ARMtTHUMB.pspec
index 58b125c9080..663c32f6dd6 100644
--- a/Ghidra/Processors/ARM/data/languages/ARMtTHUMB.pspec
+++ b/Ghidra/Processors/ARM/data/languages/ARMtTHUMB.pspec
@@ -42,6 +42,10 @@
+
+
+
+