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); + } +}