diff --git a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py
index dd5dc2db57..10f2658e68 100644
--- a/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py
+++ b/Ghidra/Extensions/SleighDevTools/pcodetest/pcode_defs.py
@@ -129,6 +129,16 @@ PCodeTest({
'proc_test': 'arm',
})
+PCodeTest({
+ 'name': 'ARM_v8m',
+ 'build_all': 1,
+ 'build_exe': 1,
+ 'qemu_command': 'qemu-arm -cpu cortex-m33',
+ 'toolchain': 'ARM/arm-eabi',
+ 'ccflags': '-mthumb -march=armv8-m.main -mfloat-abi=softfp -L %(toolchain_dir)s/lib/gcc/arm-eabi/%(gcc_version)s/thumb -lgcc',
+ 'language_id': 'ARM:LE:32:Cortexv8m',
+})
+
PCodeTest({
'name': 'AARCH64',
'build_all': 1,
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc
index 9dfd874934..adfb835e98 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.cc
@@ -2162,6 +2162,26 @@ int4 ActionLikelyTrash::apply(Funcdata &data)
return 0;
}
+/// Return \b true if either the Varnode is a constant or if it is the not yet simplified
+/// INT_ADD of constants.
+/// \param vn is the given Varnode to test
+/// \return \b true if the Varnode will be a constant
+bool ActionRestructureVarnode::isDelayedConstant(Varnode *vn)
+
+{
+ if (vn->isConstant()) return true;
+ if (!vn->isWritten()) return false;
+ PcodeOp *op = vn->getDef();
+ if (op->code() != CPUI_INT_ADD) return false;
+ if (!op->getIn(1)->isConstant()) return false;
+ Varnode *cvn = op->getIn(0);
+ if (cvn->isConstant()) return true;
+ if (!cvn->isWritten()) return false;
+ PcodeOp *copy = cvn->getDef();
+ if (copy->code() != CPUI_COPY) return false;
+ return copy->getIn(0)->isConstant();
+}
+
/// Test if the path to the given BRANCHIND originates from a constant but passes through INDIRECT operations.
/// This indicates that the switch value is produced indirectly, so we mark these INDIRECT
/// operations as \e not \e collapsible, to guarantee that the indirect value is not lost during analysis.
@@ -2176,9 +2196,16 @@ void ActionRestructureVarnode::protectSwitchPathIndirects(PcodeOp *op)
uint4 evalType = curOp->getEvalType();
if ((evalType & (PcodeOp::binary | PcodeOp::ternary)) != 0) {
if (curOp->numInput() > 1) {
- if (!curOp->getIn(1)->isConstant()) return; // Multiple paths
+ if (isDelayedConstant(curOp->getIn(1)))
+ curVn = curOp->getIn(0);
+ else if (isDelayedConstant(curOp->getIn(0)))
+ curVn = curOp->getIn(1);
+ else
+ return; // Multiple paths
+ }
+ else {
+ curVn = curOp->getIn(0);
}
- curVn = curOp->getIn(0);
}
else if ((evalType & PcodeOp::unary) != 0)
curVn = curOp->getIn(0);
diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh
index eefa3a8176..71a281c6b8 100644
--- a/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh
+++ b/Ghidra/Features/Decompiler/src/decompile/cpp/coreaction.hh
@@ -832,6 +832,7 @@ public:
/// This produces on intermediate view of symbols on the stack.
class ActionRestructureVarnode : public Action {
int4 numpass; ///< Number of passes performed for this function
+ static bool isDelayedConstant(Varnode *vn); ///< Determine if given Varnode is or will be a constant
static void protectSwitchPathIndirects(PcodeOp *op); ///< Protect path to the given switch from INDIRECT collapse
static void protectSwitchPaths(Funcdata &data); ///< Look for switches and protect path of switch variable
public:
diff --git a/Ghidra/Processors/ARM/certification.manifest b/Ghidra/Processors/ARM/certification.manifest
index af7c971381..07837a53b0 100644
--- a/Ghidra/Processors/ARM/certification.manifest
+++ b/Ghidra/Processors/ARM/certification.manifest
@@ -20,8 +20,11 @@ data/languages/ARM7_be.slaspec||GHIDRA||||END|
data/languages/ARM7_le.slaspec||GHIDRA||||END|
data/languages/ARM8_be.slaspec||GHIDRA||||END|
data/languages/ARM8_le.slaspec||GHIDRA||||END|
+data/languages/ARM8m_be.slaspec||GHIDRA||||END|
+data/languages/ARM8m_le.slaspec||GHIDRA||||END|
data/languages/ARMCortex.pspec||GHIDRA||||END|
data/languages/ARMTHUMBinstructions.sinc||GHIDRA||||END|
+data/languages/ARM_CDE.sinc||GHIDRA||||END|
data/languages/ARM_v45.cspec||GHIDRA||||END|
data/languages/ARM_v45.pspec||GHIDRA||||END|
data/languages/ARM_win.cspec||GHIDRA||||END|
diff --git a/Ghidra/Processors/ARM/data/languages/ARM.ldefs b/Ghidra/Processors/ARM/data/languages/ARM.ldefs
index 972573ac56..c541c73afc 100644
--- a/Ghidra/Processors/ARM/data/languages/ARM.ldefs
+++ b/Ghidra/Processors/ARM/data/languages/ARM.ldefs
@@ -16,9 +16,6 @@
-
-
-
@@ -76,9 +73,6 @@
-
-
-
@@ -175,6 +169,7 @@
+
@@ -195,11 +190,47 @@
+
+
+ ARM Cortex v8-m little endian
+
+
+
+
+
+
+
+
+ ARM Cortex v8-m big endian
+
+
+
+
+
+
+
+
> 27 & 0x1f;
+ Q = ((tmp ) & 0x1) != 0;
+ OV = ((tmp >> 1) & 0x1) != 0;
+ CY = ((tmp >> 2) & 0x1) != 0;
+ ZR = ((tmp >> 3) & 0x1) != 0;
+ NG = ((tmp >> 4) & 0x1) != 0;
+}
+
+macro readAPSR_nzcv(r) {
+ r = zext( (NG<<3) | (ZR<<2) | (CY<<1) | (OV) ) << 28;
+}
+
+macro writeAPSR_nzcv(r) {
+ local tmp = r >> 28 & 0xf;
+ OV = ((tmp) & 0x1) != 0;
+ CY = ((tmp >> 1) & 0x1) != 0;
+ ZR = ((tmp >> 2) & 0x1) != 0;
+ NG = ((tmp >> 3) & 0x1) != 0;
+}
+
###############################################################################
# conditionals for the branch instruction
@@ -1589,6 +1627,7 @@ bxns: "ns" is thc0002=0b100 { }
@if defined(VERSION_6T2) || defined(VERSION_7)
+@ifndef CDE
:cdp^ItCond thcpn,thopcode1,thCRd,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thopcode1 & thCRn; thCRd & thcpn & thopcode2 & thc0404=0 & thCRm
{
build ItCond;
@@ -1606,6 +1645,7 @@ bxns: "ns" is thc0002=0b100 { }
t_op2:4 = thopcode2;
coprocessor_function2(t_cpn,t_op1,t_op2,thCRd,thCRn,thCRm);
}
+@endif #CDE
define pcodeop IndexCheck;
@@ -1902,6 +1942,7 @@ XYZ: X^Y^Z is TMode=1 & X & Y & Z { }
# just sets up the condition and If Then/Else mask
}
+@ifndef CDE
:ldc^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=0 & thL4=1; thCRd & thcpn) & taddrmode5
{
build ItCond;
@@ -1933,7 +1974,7 @@ XYZ: X^Y^Z is TMode=1 & X & Y & Z { }
t_cpn:4 = thcpn;
coprocessor_loadlong(t_cpn,thCRd,taddrmode5);
}
-
+@endif # CDE
@endif # VERSION_6T2 || VERSION_7
:ldmia^ItCond Rn_exclaim,ldbrace is TMode=1 & ItCond & op11=0x19 & Rn_exclaim & ldbrace & Rn_exclaim_WB
@@ -2541,7 +2582,7 @@ macro th_set_carry_for_lsr(op1,shift_count) {
@endif # VERSION_6T2 || VERSION_7
-
+@ifndef CDE
:mcr^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thc0507 & thc0404=0 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm
{
build ItCond;
@@ -2575,7 +2616,7 @@ macro th_set_carry_for_lsr(op1,shift_count) {
t_op:4 = thopcode1;
coprocessor_moveto2(t_cpn,t_op,Rt1215,Rn0003,thCRm);
}
-
+@endif # CDE
:mov^CheckInIT_ZN^ItCond Rd0810,Immed8 is TMode=1 & ItCond & op11=4 & Rd0810 & Immed8 & CheckInIT_ZN
{
@@ -2652,7 +2693,7 @@ macro th_set_carry_for_lsr(op1,shift_count) {
Rd0811 = (zext(Immed16) << 16) | (Rd0811 & 0xffff);
}
-
+@ifndef CDE
:mrc^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thc0507 & thc0404=1 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm
{
build ItCond;
@@ -2661,6 +2702,15 @@ macro th_set_carry_for_lsr(op1,shift_count) {
t_op2:4 = thopcode2;
Rt1215 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm);
}
+:mrc^ItCond thcpn,thc0507,"APSR_nzcv",thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thc0507 & thc0404=1 & thCRn; Rt1215=15 & thcpn & thopcode2 & thc0404=1 & thCRm
+{
+ build ItCond;
+ t_cpn:4 = thcpn;
+ t_op1:4 = thc0507;
+ t_op2:4 = thopcode2;
+ local tmp:4 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm);
+ writeAPSR_nzcv(tmp);
+}
:mrc2^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xfe & thc0507 & thc0404=1 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm
{
@@ -2670,6 +2720,15 @@ macro th_set_carry_for_lsr(op1,shift_count) {
t_op2:4 = thopcode2;
Rt1215 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm);
}
+:mrc2^ItCond thcpn,thc0507,"APSR_nzcv",thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xfe & thc0507 & thc0404=1 & thCRn; Rt1215=15 & thcpn & thopcode2 & thc0404=1 & thCRm
+{
+ build ItCond;
+ t_cpn:4 = thcpn;
+ t_op1:4 = thc0507;
+ t_op2:4 = thopcode2;
+ local tmp:4 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm);
+ writeAPSR_nzcv(tmp);
+}
:mrrc^ItCond thcpn,thopcode1,Rt1215,Rn0003,thCRm is TMode=1 & ItCond & op4=0xec5 & Rn0003; Rt1215 & thcpn & thopcode1 & thCRm
{
@@ -2688,22 +2747,7 @@ macro th_set_carry_for_lsr(op1,shift_count) {
Rt1215 = coprocessor_movefromRt(t_cpn,t_op,thCRm);
Rn0003 = coprocessor_movefromRt2(t_cpn,t_op,thCRm);
}
-
-macro readAPSR(r) {
-# TODO: GE bits have not been included
- r = r | zext( (NG<<4) | (ZR<<3) | (CY<<2) | (OV<<1) | (Q) ) << 27;
-}
-
-macro writeAPSR(r) {
-# TODO: GE bits have not been included
- local tmp = r >> 27 & 0x1f;
- Q = ((tmp ) & 0x1) != 0;
- OV = ((tmp >> 1) & 0x1) != 0;
- CY = ((tmp >> 2) & 0x1) != 0;
- ZR = ((tmp >> 3) & 0x1) != 0;
- NG = ((tmp >> 4) & 0x1) != 0;
-}
-
+@endif #CDE
@if defined(VERSION_7M)
define pcodeop getMainStackPointer;
@@ -2722,7 +2766,7 @@ mrsipsr: is thc0000=0 { }
mrsepsr: "e" is thc0101=1 { }
mrsepsr: is thc0101=0 { }
mrsapsr: is thc0202=1 { }
-mrsapsr: "a" is thc0202=0 & Rd0811 { readAPSR(Rd0811); }
+mrsapsr: "a" is thc0202=0 & Rd0811 { readAPSR_nzcvq(Rd0811); }
mrspsr: mrsipsr^mrsepsr^mrsapsr^"psr" is mrsipsr & mrsepsr & mrsapsr & Rd0811 {
Rd0811 = 0;
@@ -2820,7 +2864,7 @@ control: "control" is epsilon {}
{
build ItCond;
tmp:4 = 0;
- readAPSR(tmp);
+ readAPSR_nzcvq(tmp);
Rd0811 = tmp;
}
@@ -2840,7 +2884,7 @@ msrepsr: is thc0101=0 { }
msrapsr: is thc0202=1 { }
msrapsr: "a" is thc0202=0 & Rn0003 {
cpsr = cpsr | (Rn0003 & 0xf8000000);
- writeAPSR(cpsr);
+ writeAPSR_nzcvq(cpsr);
}
msrpsr: msripsr^msrepsr^msrapsr^"psr" is msripsr & msrepsr & msrapsr {
@@ -2955,7 +2999,7 @@ thcpsrmask: cpsr^thpsrmask is thpsrmask & cpsr { export thpsrmask; }
build ItCond;
build thcpsrmask;
cpsr = (cpsr& ~thcpsrmask) | (Rn0003 & thcpsrmask);
- writeAPSR(cpsr);
+ writeAPSR_nzcvq(cpsr);
}
thspsrmask: spsr^thpsrmask is thpsrmask & spsr { export thpsrmask; }
@@ -3773,7 +3817,7 @@ macro th_set_carry_for_ror(result, count) {
:sdiv^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb9 & Rn0003; op12=0xf & Rd0811 & thc0407=0xf & Rm0003
{
build ItCond;
- local result = Rn0003 / Rm0003;
+ local result = Rn0003 s/ Rm0003;
Rd0811 = result;
}
@@ -4259,7 +4303,7 @@ thumbEndianNess: "BE" is op0=0xb658 { export 1:1; }
@endif # VERSION_6
@if defined(VERSION_6T2) || defined(VERSION_7)
-
+@ifndef CDE
:stc^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=0 & thL4=0; thCRd & thcpn) & taddrmode5
{
build ItCond;
@@ -4291,6 +4335,7 @@ thumbEndianNess: "BE" is op0=0xb658 { export 1:1; }
t_cpn:4 = thcpn;
coprocessor_storelong(t_cpn,thCRd,taddrmode5);
}
+@endif # CDE
:stm^ItCond Rn0003,thstrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=0 & thc0404=0 & Rn0003; thc1515=0 & thc1313=0 & thstrlist_inc
{
@@ -5330,4 +5375,4 @@ Pcrel: [pc,Rm0003] is Rm0003 & thc0404=1 & pc
}
@endif #VERSION_6T2 || VERSION_7
-} # End with : ARMcondCk=1
\ No newline at end of file
+} # End with : ARMcondCk=1
diff --git a/Ghidra/Processors/ARM/data/languages/ARM_CDE.sinc b/Ghidra/Processors/ARM/data/languages/ARM_CDE.sinc
new file mode 100644
index 0000000000..da6bbacf97
--- /dev/null
+++ b/Ghidra/Processors/ARM/data/languages/ARM_CDE.sinc
@@ -0,0 +1,223 @@
+@if defined(CDE)
+# ARMv8-M Custom Datapath Extension
+
+acc: "a" is thc1212=1 { local tmp:1 = 1; export *[const]:1 tmp; }
+acc: "" is thc1212=0 { local tmp:1 = 0; export *[const]:1 tmp; }
+vacc: "a" is thv_c2828=1 { local tmp:1 = 1; export *[const]:1 tmp; }
+vacc: "" is thv_c2828=0 { local tmp:1 = 0; export *[const]:1 tmp; }
+
+cx1_imm: val is thc0005; thop2 & thopcode3 [val=(thc0005 << 7) | (thop2 << 6) | thopcode3;] {export *[const]:4 val; }
+cx2_imm: val is thc0405; thop2 & thopcode3 [val=(thc0405 << 7) | (thop2 << 6) | thopcode3;] {export *[const]:4 val; }
+cx3_imm: val is thop1; thop2 & thop3 [val=(thop1 << 3) | (thop2 << 2) | thop3;] {export *[const]:4 val; }
+
+vcx1_imm: val is thv_c2424 & thv_c1619 & thv_c0707 & thv_c0005 [val = (thv_c2424 << 11) |(thv_c1619 << 7) | (thv_c0707 << 6) | thv_c0005;] {export *[const]:4 val; }
+vcx2_imm: val is thv_c2424 & thv_c1619 & thv_c0707 & thv_c0404 [val = (thv_c2424 << 6 ) |(thv_c1619 << 2) | (thv_c0707 << 1) | thv_c0404;] {export *[const]:4 val; }
+vcx3_imm: val is thv_c2424 & thv_c2021 & thv_c0404 [val = (thv_c2424 << 3 ) |(thv_c2021 << 1) | thv_c0404;] {export *[const]:4 val; }
+
+fvcx1_imm: val is thv_c1619 & thv_c0707 & thv_c0005 [val = (thv_c1619 << 7) | (thv_c0707 << 6) | thv_c0005;] {export *[const]:4 val; }
+fvcx2_imm: val is thv_c1619 & thv_c0707 & thv_c0404 [val = (thv_c1619 << 2) | (thv_c0707 << 1) | thv_c0404;] {export *[const]:4 val; }
+fvcx3_imm: val is thv_c2021 & thv_c0404 [val = (thv_c2021 << 1) | thv_c0404;] {export *[const]:4 val; }
+
+
+cx_coRd: Ra1215 is Ra1215 { export Ra1215; }
+cx_coRd:"APSR_nzcv" is Ra1215=15 { tmp:4 = 0; readAPSR_nzcv(tmp); export tmp; }
+cx_coRn: Rn0003 is Rn0003 { export Rn0003; }
+cx_coRn:"APSR_nzcv" is Rn0003=15 { tmp:4 = 0; readAPSR_nzcv(tmp); export tmp; }
+cx_coRm: Ra1215 is Ra1215 { export Ra1215; }
+cx_coRm:"APSR_nzcv" is Ra1215=15 { tmp:4 = 0; readAPSR_nzcv(tmp); export tmp; }
+cx_coRd0: Rd0003 is Rd0003 { export Rd0003; }
+cx_coRd0:"APSR_nzcv" is Rd0003=15 { tmp:4 = 0; readAPSR_nzcv(tmp); export tmp; }
+
+# Pseudo-ops
+define pcodeop cx1; # Rd = cx1(Coprocessor #, operation, Rd, accumulator, size)
+define pcodeop cx2; # Rd = cx2(Coprocessor #, operation, Rd, Rn, accumulator, size)
+define pcodeop cx3; # Rd = cx3(Coprocessor #, operation, Rd, Rn, Rm, accumulator, size)
+define pcodeop vcx1; # Rd = vcx1(Coprocessor #, operation, Rd, accumulator, size, vectored)
+define pcodeop vcx2; # Rd = vcx2(Coprocessor #, operation, Rd, Rn, accumulator, size, vectored)
+define pcodeop vcx3; # Rd = vcx3(Coprocessor #, operation, Rd, Rn, Rm, accumulator, size, vectored)
+
+:cx1^acc^ItCond thcop, cx_coRd, cx1_imm is TMode=1 & ItCond & (op13=7 & acc & thc0811=0xe & thc0607=0; cx_coRd & thc1111=0 & thcop & thc0606=0) & cx1_imm
+{
+ build ItCond;
+ t_cpn:4 = thcop;
+ t_op1:4 = cx1_imm;
+ t_acc:1 = acc;
+ cx_coRd = cx1(t_cpn, t_op1, cx_coRd, t_acc, 32:1);
+}
+
+:cx1^acc^ItCond thcop, cx_coRd, cx1_imm is TMode=1 & ItCond & (op13=7 & acc & thc0811=0xe & thc0607=0; (cx_coRd & Ra1215=15) & thc1111=0 & thcop & thc0606=0) & cx1_imm
+{
+ build ItCond;
+ t_cpn:4 = thcop;
+ t_op1:4 = cx1_imm;
+ t_acc:1 = acc;
+ cx_coRd = cx1(t_cpn, t_op1, cx_coRd, t_acc, 32:1);
+ writeAPSR_nzcv(cx_coRd);
+}
+
+:cx1d^acc^ItCond thcop, Ra1215, Rd1215hi, cx1_imm is TMode=1 & ItCond & (op13=7 & acc & thc0811=0xe & thc0607=0; Ra1215 & Rd1215hi & thc1111=0 & thcop & thc0606=1) & cx1_imm
+{
+ build ItCond;
+ t_cpn:4 = thcop;
+ t_op1:4 = cx1_imm;
+ t_acc:1 = acc;
+ result:8 = cx1(t_cpn, t_op1, Ra1215, Rd1215hi, t_acc, 64:1);
+ Ra1215 = result(0);
+ Rd1215hi = result(4);
+}
+
+:cx2^acc^ItCond thcop, cx_coRd, cx_coRn, cx2_imm is TMode=1 & ItCond & (op13=7 & acc & thc0811=0xe & thc0607=1 & cx_coRn; cx_coRd & thc1111=0 & thcop & thc0606=0) & cx2_imm
+{
+ build ItCond;
+ t_cpn:4 = thcop;
+ t_op1:4 = cx2_imm;
+ t_acc:1 = acc;
+ cx_coRd = cx2(t_cpn, t_op1, cx_coRd, cx_coRn, t_acc, 32:1);
+}
+:cx2^acc^ItCond thcop, cx_coRd, cx_coRn, cx2_imm is TMode=1 & ItCond & (op13=7 & acc & thc0811=0xe & thc0607=1 & cx_coRn; (cx_coRd & Ra1215=15) & thc1111=0 & thcop & thc0606=0) & cx2_imm
+{
+ build ItCond;
+ t_cpn:4 = thcop;
+ t_op1:4 = cx2_imm;
+ t_acc:1 = acc;
+ cx_coRd = cx2(t_cpn, t_op1, cx_coRd, cx_coRn, t_acc, 32:1);
+ writeAPSR_nzcv(cx_coRd);
+}
+
+:cx2d^acc^ItCond thcop, Ra1215, Rd1215hi, cx_coRn, cx2_imm is TMode=1 & ItCond & (op13=7 & acc & thc0811=0xe & thc0607=1 & cx_coRn; Ra1215 & Rd1215hi & thc1111=0 & thcop & thc0606=1) & cx2_imm
+{
+ build ItCond;
+ t_cpn:4 = thcop;
+ t_op1:4 = cx2_imm;
+ t_acc:1 = acc;
+ result:8 = cx2(t_cpn, t_op1, Ra1215, Rd1215hi, cx_coRn, t_acc, 64:1);
+ Ra1215 = result(0);
+ Rd1215hi = result(4);
+}
+
+:cx3^acc^ItCond thcop, cx_coRd0, cx_coRn, cx_coRm, cx3_imm is TMode=1 & ItCond & (op13=7 & acc & thc0811=0xe & thc0707=1 & cx_coRn; cx_coRm & thc1111=0 & thcop & thc0606=0 & cx_coRd0) & cx3_imm
+{
+ build ItCond;
+ t_cpn:4 = thcop;
+ t_op1:4 = cx3_imm;
+ t_acc:1 = acc;
+ cx_coRd0 = cx3(t_cpn, t_op1, cx_coRd0, cx_coRn, cx_coRm, t_acc, 32:1);
+}
+:cx3^acc^ItCond thcop, cx_coRd0, cx_coRn, cx_coRm, cx3_imm is TMode=1 & ItCond & (op13=7 & acc & thc0811=0xe & thc0707=1 & cx_coRn; cx_coRm & thc1111=0 & thcop & thc0606=0 & (cx_coRd0 & Rd0003=15)) & cx3_imm
+{
+ build ItCond;
+ t_cpn:4 = thcop;
+ t_op1:4 = cx3_imm;
+ t_acc:1 = acc;
+ cx_coRd0 = cx3(t_cpn, t_op1, cx_coRd0, cx_coRn, cx_coRm, t_acc, 32:1);
+ writeAPSR_nzcv(cx_coRd0);
+}
+
+:cx3d^acc^ItCond thcop, Rd0003, Rd0003hi, cx_coRn, cx_coRm, cx3_imm is TMode=1 & ItCond & (op13=7 & acc & thc0811=0xe & thc0707=1 & cx_coRn; cx_coRm & thc1111=0 & thcop & thc0606=1 & Rd0003 & Rd0003hi) & cx3_imm
+{
+ build ItCond;
+ t_cpn:4 = thcop;
+ t_op1:4 = cx3_imm;
+ t_acc:1 = acc;
+ result:8 = cx3(t_cpn, t_op1, Rd0003, Rd0003hi, cx_coRn, cx_coRm, t_acc, 64:1);
+ Rd0003 = result(0);
+ Rd0003hi = result(4);
+}
+
+# Vector CDE instructions - Requires Armv8.1-M MVE
+:vcx1^vacc^ItCond thv_cpn, Qd, vcx1_imm is TMode=1 & ItCond & thv_c2931=7 & vacc & thv_c2527=6 & thv_c2323=0 & thv_c2021=2 & thv_c1111=0 & thv_cpn & thv_c0606=1 & Qd & vcx1_imm
+{
+ build ItCond;
+ t_cpn:4 = thv_cpn;
+ t_op1:4 = vcx1_imm;
+ t_acc:1 = vacc;
+ t_vec:1 = 1;
+ Qd = vcx1(t_cpn, t_op1, Qd, t_acc, 32:1, t_vec);
+}
+
+:vcx2^vacc^ItCond thv_cpn, Qd, Qm, vcx2_imm is TMode=1 & ItCond & thv_c2931=7 & vacc & thv_c2527=6 & thv_c2323=0 & thv_c2021=3 & thv_c1111=0 & thv_cpn & thv_c0606=1 & Qm & Qd & vcx2_imm
+{
+ build ItCond;
+ t_cpn:4 = thv_cpn;
+ t_op1:4 = vcx2_imm;
+ t_acc:1 = vacc;
+ t_vec:1 = 1;
+ Qd = vcx2(t_cpn, t_op1, Qd, Qm, t_acc, 32:1, t_vec);
+}
+
+
+:vcx3^vacc^ItCond thv_cpn, Qd, Qn, Qm, vcx3_imm is TMode=1 & ItCond & thv_c2931=7 & vacc & thv_c2527=6 & thv_c2323=1 & thv_c1111=0 & thv_cpn & thv_c0606=1 & Qm & Qn & Qd & vcx3_imm
+{
+ build ItCond;
+ t_cpn:4 = thv_cpn;
+ t_op1:4 = vcx3_imm;
+ t_acc:1 = vacc;
+ t_vec:1 = 1;
+ Qd = vcx3(t_cpn, t_op1, Qd, Qn, Qm, t_acc, 32:1, t_vec);
+}
+
+
+# Floating-point CDE instructions - Requires Armv8.1-M MVE
+:vcx1^vacc^ItCond thv_cpn, Sd, fvcx1_imm is TMode=1 & ItCond & thv_c2931=7 & vacc & thv_c2527=6 & thv_c2424=0 & thv_c2323=0 & thv_c2021=2 & thv_c1111=0 & thv_cpn & thv_c0606=0 & Sd & fvcx1_imm
+{
+ build ItCond;
+ t_cpn:4 = thv_cpn;
+ t_op1:4 = fvcx1_imm;
+ t_acc:1 = vacc;
+ t_vec:1 = 0;
+ Sd = vcx1(t_cpn, t_op1, Sd, t_acc, 32:1, t_vec);
+}
+
+:vcx1^vacc^ItCond thv_cpn, Dd, fvcx1_imm is TMode=1 & ItCond & thv_c2931=7 & vacc & thv_c2527=6 & thv_c2424=1 & thv_c2323=0 & thv_c2021=2 & thv_c1111=0 & thv_cpn & thv_c0606=0 & Dd & fvcx1_imm
+{
+ build ItCond;
+ t_cpn:4 = thv_cpn;
+ t_op1:4 = fvcx1_imm;
+ t_acc:1 = vacc;
+ t_vec:1 = 0;
+ Dd = vcx1(t_cpn, t_op1, Dd, t_acc, 64:1, t_vec);
+}
+
+
+
+:vcx2^vacc^ItCond thv_cpn, Sd, Sm, fvcx2_imm is TMode=1 & ItCond & thv_c2931=7 & vacc & thv_c2527=6 & thv_c2424=0 & thv_c2323=0 & thv_c2021=3 & thv_c1111=0 & thv_cpn & thv_c0606=0 & Sm & Sd & fvcx2_imm
+{
+ build ItCond;
+ t_cpn:4 = thv_cpn;
+ t_op1:4 = fvcx2_imm;
+ t_acc:1 = vacc;
+ t_vec:1 = 0;
+ Sd = vcx2(t_cpn, t_op1, Sd, Sm, t_acc, 32:1, t_vec);
+}
+
+:vcx2^vacc^ItCond thv_cpn, Dd, Dm, fvcx2_imm is TMode=1 & ItCond & thv_c2931=7 & vacc & thv_c2527=6 & thv_c2424=1 & thv_c2323=0 & thv_c2021=3 & thv_c1111=0 & thv_cpn & thv_c0606=0 & Dm & Dd & fvcx2_imm
+{
+ build ItCond;
+ t_cpn:4 = thv_cpn;
+ t_op1:4 = fvcx2_imm;
+ t_acc:1 = vacc;
+ t_vec:1 = 0;
+ Dd = vcx2(t_cpn, t_op1, Dd, Dm, t_acc, 64:1, t_vec);
+}
+
+
+:vcx3^vacc^ItCond thv_cpn, Sd, Sn, Sm, fvcx3_imm is TMode=1 & ItCond & thv_c2931=7 & vacc & thv_c2527=6 & thv_c2424=0 & thv_c2323=1 & thv_c1111=0 & thv_cpn & thv_c0606=0 & Sm & Sn & Sd & fvcx3_imm
+{
+ build ItCond;
+ t_cpn:4 = thv_cpn;
+ t_op1:4 = fvcx3_imm;
+ t_acc:1 = vacc;
+ t_vec:1 = 0;
+ Sd = vcx3(t_cpn, t_op1, Sd, Sn, Sm, t_acc, 32:1, t_vec);
+}
+
+:vcx3^vacc^ItCond thv_cpn, Dd, Dn, Dm, fvcx3_imm is TMode=1 & ItCond & thv_c2931=7 & vacc & thv_c2527=6 & thv_c2424=1 & thv_c2323=1 & thv_c1111=0 & thv_cpn & thv_c0606=0 & Dm & Dn & Dd & fvcx3_imm
+{
+ build ItCond;
+ t_cpn:4 = thv_cpn;
+ t_op1:4 = fvcx3_imm;
+ t_acc:1 = vacc;
+ t_vec:1 = 0;
+ Dd = vcx3(t_cpn, t_op1, Dd, Dn, Dm, t_acc, 64:1, t_vec);
+}
+@endif # CDE
\ No newline at end of file
diff --git a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc
index 16d8208c8d..d26172a9e8 100644
--- a/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc
+++ b/Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc
@@ -313,6 +313,7 @@ define token instrArm (32)
thv_Rm=(16,19)
thv_Rt2=(24,27)
thv_immed=(16,23)
+ thv_cpn=(8,10)
# Arbitrary bit fields for 32-bit Little Endian Thumb
@@ -330,15 +331,16 @@ define token instrArm (32)
thv_c2831=(12,15)
thv_c2828=(12,12)
thv_c2627=(10,11)
- thv_c2531=(9,15)
thv_c2527=(9,11)
thv_c2525=(9,9)
+ thv_c2431=(8,15)
thv_c2427=(8,11)
thv_c2424=(8,8)
thv_c2331=(7,15)
thv_c2327=(7,11)
thv_c2324=(7,8)
thv_c2323=(7,7)
+ thv_c2223=(6,7)
thv_c2222=(6,6)
thv_c2131=(5,15)
thv_c2127=(5,11)
@@ -415,6 +417,7 @@ define token instrArm (32)
thv_c0008=(16,24)
thv_c0007=(16,23)
thv_c0006=(16,22)
+ thv_c0005=(16,21)
thv_c0004=(16,20)
thv_c0003=(16,19)
thv_c0001=(16,17)
@@ -477,6 +480,7 @@ define token instrArm (32)
thv_Rm=(0,3)
thv_Rt2=(8,11)
thv_immed=(0,7)
+ thv_cpn=(24,26)
# Arbitrary bit fields for 32-bit Big Endian Thumb
thv_bit31=(31,31)
@@ -493,15 +497,16 @@ define token instrArm (32)
thv_c2831=(28,31)
thv_c2828=(28,28)
thv_c2627=(26,27)
- thv_c2531=(25,31)
thv_c2527=(25,27)
thv_c2525=(25,25)
+ thv_c2431=(24,31)
thv_c2427=(24,27)
thv_c2424=(24,24)
thv_c2331=(23,31)
thv_c2327=(23,27)
thv_c2324=(23,24)
thv_c2323=(23,23)
+ thv_c2223=(22,23)
thv_c2222=(22,22)
thv_c2131=(21,31)
thv_c2127=(21,27)
@@ -578,6 +583,7 @@ define token instrArm (32)
thv_c0008=(0,8)
thv_c0007=(0,7)
thv_c0006=(0,6)
+ thv_c0005=(0,5)
thv_c0004=(0,4)
thv_c0003=(0,3)
thv_c0001=(0,1)
@@ -594,6 +600,7 @@ attach variables [ CRd CRn CRm ] [ cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7 cr8 cr9 cr10
attach variables [ thv_Rd thv_Rn thv_Rt thv_Rt2 ] [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ];
attach names [ cpn ] [ p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 ];
+attach names [ thv_cpn ] [ p0 p1 p2 p3 p4 p5 p6 p7 ];
attach names [ ibOption ] [ opt0 opt1 opt2 opt3 opt4 opt5 opt6 opt7 opt8 opt9 opt10 opt11 opt12 opt13 opt14 SY ];
attach names [ dbOption ] [ opt0 opt1 OSHST OSH opt4 opt5 NSHST NSH opt8 opt9 ISHST ISH opt12 opt13 ST SY ];
@@ -4907,7 +4914,7 @@ macro BitReverse_arm(val) {
:sdiv^COND RdHi,RnLo,RmHi is $(AMODE) & ARMcond=1 & COND & c2027=0x71 & RdHi & c1215=0xf & RmHi & c0407=0x1 & RnLo
{
build COND;
- local result = RnLo / RmHi;
+ local result = RnLo s/ RmHi;
RdHi = result;
}
diff --git a/Ghidra/Processors/ARM/src/test.processors/java/ghidra/test/processors/ARM_v8m_O0_EmulatorTest.java b/Ghidra/Processors/ARM/src/test.processors/java/ghidra/test/processors/ARM_v8m_O0_EmulatorTest.java
new file mode 100644
index 0000000000..9238902270
--- /dev/null
+++ b/Ghidra/Processors/ARM/src/test.processors/java/ghidra/test/processors/ARM_v8m_O0_EmulatorTest.java
@@ -0,0 +1,40 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.test.processors;
+
+import ghidra.test.processors.support.ProcessorEmulatorTestAdapter;
+import junit.framework.Test;
+
+public class ARM_v8m_O0_EmulatorTest extends ProcessorEmulatorTestAdapter {
+
+ private static final String LANGUAGE_ID = "ARM:LE:32:Cortex8m";
+ private static final String COMPILER_SPEC_ID = "default";
+
+ private static final String[] REG_DUMP_SET = new String[] {};
+
+ public ARM_v8m_O0_EmulatorTest(String name) throws Exception {
+ super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET);
+ }
+
+ @Override
+ protected String getProcessorDesignator() {
+ return "ARM_v8m_GCC_O0";
+ }
+
+ public static Test suite() {
+ return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(ARM_v8m_O0_EmulatorTest.class);
+ }
+}
diff --git a/Ghidra/Processors/ARM/src/test.processors/java/ghidra/test/processors/ARM_v8m_O3_EmulatorTest.java b/Ghidra/Processors/ARM/src/test.processors/java/ghidra/test/processors/ARM_v8m_O3_EmulatorTest.java
new file mode 100644
index 0000000000..7f9c77e8ae
--- /dev/null
+++ b/Ghidra/Processors/ARM/src/test.processors/java/ghidra/test/processors/ARM_v8m_O3_EmulatorTest.java
@@ -0,0 +1,40 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package ghidra.test.processors;
+
+import ghidra.test.processors.support.ProcessorEmulatorTestAdapter;
+import junit.framework.Test;
+
+public class ARM_v8m_O3_EmulatorTest extends ProcessorEmulatorTestAdapter {
+
+ private static final String LANGUAGE_ID = "ARM:LE:32:Cortex8m";
+ private static final String COMPILER_SPEC_ID = "default";
+
+ private static final String[] REG_DUMP_SET = new String[] {};
+
+ public ARM_v8m_O3_EmulatorTest(String name) throws Exception {
+ super(name, LANGUAGE_ID, COMPILER_SPEC_ID, REG_DUMP_SET);
+ }
+
+ @Override
+ protected String getProcessorDesignator() {
+ return "ARM_v8m_GCC_O3";
+ }
+
+ public static Test suite() {
+ return ProcessorEmulatorTestAdapter.buildEmulatorTestSuite(ARM_v8m_O3_EmulatorTest.class);
+ }
+}