sstep.c 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. sstep.c
  9. Abstract:
  10. This module implements support for getting the next PC instruction on ARM.
  11. This is most commonly used to implement single stepping support.
  12. Author:
  13. Evan Green 11-Aug-2012
  14. Environment:
  15. Kernel
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/kernel.h>
  21. #include <minoca/kernel/arm.h>
  22. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. //
  26. // Definitions that relate to the condition code of an ARM instruction. The
  27. // values here are shifted down by one, as the low bit just negates the
  28. // condition.
  29. //
  30. #define ARM_CONDITION_CODE_MASK 0xF0000000
  31. #define ARM_CONDITION_CODE_SHIFT 28
  32. #define ARM_CONDITION_CODE_UNCONDITIONAL 0xF
  33. #define ARM_CONDITION_EQUAL 0x0
  34. #define ARM_CONDITION_CARRY 0x1
  35. #define ARM_CONDITION_NEGATIVE 0x2
  36. #define ARM_CONDITION_OVERFLOW 0x3
  37. #define ARM_CONDITION_UNSIGNED_GREATER 0x4
  38. #define ARM_CONDITION_SIGNED_GREATER_OR_EQUAL 0x5
  39. #define ARM_CONDITION_SIGNED_GREATER 0x6
  40. #define ARM_CONDITION_ALWAYS 0x7
  41. //
  42. // Branch and exchange instruction (BX).
  43. //
  44. #define BRANCH_EXCHANGE_MASK 0x0FFFFFF0
  45. #define BRANCH_EXCHANGE_VALUE 0x012FFF10
  46. #define BRANCH_EXCHANGE_LINK_REGISTER 14
  47. #define BRANCH_EXCHANGE_X_MASK 0x0FFFFFF0
  48. #define BRANCH_EXCHANGE_X_VALUE 0x012FFF30
  49. //
  50. // Branch instruction.
  51. //
  52. #define BRANCH_MASK 0x0E000000
  53. #define BRANCH_VALUE 0x0A000000
  54. #define BRANCH_H_BIT 0x01000000
  55. //
  56. // Media instructions.
  57. //
  58. #define MEDIA_MASK 0x0E000010
  59. #define MEDIA_VALUE 0x06000010
  60. //
  61. // Load/Store instructions (LDR/STR).
  62. //
  63. #define LOAD_STORE_SINGLE_MASK 0x0C000000
  64. #define LOAD_STORE_SINGLE_VALUE 0x04000000
  65. #define LOAD_STORE_BYTE_BIT 0x00400000
  66. #define DESTINATION_REGISTER_MASK 0x0000F000
  67. #define DESTINATION_REGISTER_SHIFT 12
  68. #define LOAD_BIT 0x00100000
  69. #define PREINDEX_BIT 0x01000000
  70. #define IMMEDIATE_BIT 0x02000000
  71. #define SET_FLAGS_BIT 0x00100000
  72. #define ADD_SUBTRACT_BIT 0x00800000
  73. #define SHIFT_TYPE 0x00000060
  74. #define SHIFT_LSL 0x00000000
  75. #define SHIFT_LSR 0x00000020
  76. #define SHIFT_ASR 0x00000040
  77. #define SHIFT_ROR 0x00000060
  78. #define LOAD_STORE_BYTE_BIT 0x00400000
  79. #define LOAD_STORE_BASE_MASK 0x000F0000
  80. #define LOAD_STORE_BASE_SHIFT 16
  81. #define REGISTER_REGISTER_SHIFT_BIT 0x00000010
  82. #define REGISTER_PC 0xF
  83. //
  84. // Load/Store Multiple (LDM/STM).
  85. //
  86. #define LOAD_STORE_MULTIPLE_MASK 0x0E000000
  87. #define LOAD_STORE_MULTIPLE_VALUE 0x08000000
  88. #define PUSH_POP_TYPE_MASK 0x01800000
  89. #define PUSH_POP_INCREMENT_AFTER 0x00800000
  90. #define PUSH_POP_INCREMENT_BEFORE 0x01800000
  91. #define PUSH_POP_DECREMENT_AFTER 0x00000000
  92. #define PUSH_POP_DECREMENT_BEFORE 0x01000000
  93. #define LOAD_STORE_MULTIPLE_PC_BIT 0x00008000
  94. #define REGISTER_LIST_MASK 0x0000FFFF
  95. //
  96. // Data processing instructions.
  97. //
  98. #define DATA_PROCESSING_MASK 0x0C000000
  99. #define DATA_PROCESSING_VALUE 0x00000000
  100. #define DATA_PROCESSING_OPCODE_MASK 0x01E00000
  101. #define DATA_PROCESSING_OPCODE_SHIFT 21
  102. #define DATA_PROCESSING_OPERAND1_MASK 0x000F0000
  103. #define DATA_PROCESSING_OPERAND1_SHIFT 16
  104. #define DATA_PROCESSING_NOT_IMMEDIATE_MASK 0x01900000
  105. #define DATA_PROCESSING_NOT_IMMEDIATE_VALUE 0x01000000
  106. #define SHIFT_REGISTER_MASK 0x00000F00
  107. #define SHIFT_REGISTER_SHIFT 8
  108. #define SHIFT_REGISTER_EMPTY_BIT 0x00000080
  109. #define SHIFT_IMMEDIATE_MASK 0x00000F80
  110. #define SHIFT_IMMEDIATE_SHIFT 7
  111. #define OPERAND2_REGISTER_MASK 0x0000000F
  112. #define IMMEDIATE8_MASK 0x000000FF
  113. #define IMMEDIATE_ROTATE_MASK 0x00000F00
  114. #define IMMEDIATE_ROTATE_SHIFT 8
  115. #define OPCODE_AND 0
  116. #define OPCODE_EOR 1
  117. #define OPCODE_SUB 2
  118. #define OPCODE_RSB 3
  119. #define OPCODE_ADD 4
  120. #define OPCODE_ADC 5
  121. #define OPCODE_SBC 6
  122. #define OPCODE_RSC 7
  123. #define OPCODE_TST 8
  124. #define OPCODE_TEQ 9
  125. #define OPCODE_CMP 10
  126. #define OPCODE_CMN 11
  127. #define OPCODE_ORR 12
  128. #define OPCODE_MOV 13
  129. #define OPCODE_BIC 14
  130. #define OPCODE_MVN 15
  131. //
  132. // Define RFE instruction bits.
  133. //
  134. #define ARM_RFE_MASK 0xFE50FFFF
  135. #define ARM_RFE_VALUE 0xF8100A00
  136. #define ARM_RFE_PREINDEX (1 << 24)
  137. #define ARM_RFE_INCREMENT (1 << 23)
  138. #define ARM_RFE_REGISTER_MASK 0x000F0000
  139. #define ARM_RFE_REGISTER_SHIFT 16
  140. //
  141. // Define Thumb decoding constants.
  142. //
  143. //
  144. // Common Thumb definitions
  145. //
  146. #define THUMB_REGISTER8_MASK 0x7
  147. #define THUMB_REGISTER16_MASK 0xF
  148. #define THUMB_CONDITION_MASK 0xF
  149. #define THUMB_IMMEDIATE5_MASK 0x1F
  150. #define THUMB_IMMEDIATE6_MASK 0x3F
  151. #define THUMB_IMMEDIATE8_MASK 0xFF
  152. #define THUMB_IMMEDIATE10_MASK 0x3FF
  153. #define THUMB_IMMEDIATE11_MASK 0x7FF
  154. //
  155. // 16-bit Thumb decoding constants
  156. //
  157. #define THUMB16_IT_MASK 0xFF00
  158. #define THUMB16_IT_VALUE 0xBF00
  159. #define THUMB16_IT_STATE_MASK 0x00FF
  160. #define THUMB16_BX_MASK 0xFF07
  161. #define THUMB16_BX_VALUE 0x4700
  162. #define THUMB16_BX_RM_SHIFT 3
  163. #define THUMB16_B_CONDITIONAL_MASK 0xF000
  164. #define THUMB16_B_CONDITIONAL_VALUE 0xD000
  165. #define THUMB16_B_CONDITIONAL_CONDITION_SHIFT 8
  166. #define THUMB16_B_UNCONDITIONAL_MASK 0xF800
  167. #define THUMB16_B_UNCONDITIONAL_VALUE 0xE000
  168. #define THUMB16_CBZ_MASK 0xF500
  169. #define THUMB16_CBZ_VALUE 0xB100
  170. #define THUMB16_CBZ_IMMEDIATE5_SHIFT 3
  171. #define THUMB16_CBZ_IMMEDIATE5 (1 << 9)
  172. #define THUMB16_CBZ_NOT (1 << 11)
  173. #define THUMB16_POP_MASK 0xFE00
  174. #define THUMB16_POP_VALUE 0xBC00
  175. #define THUMB16_POP_PC (1 << 8)
  176. #define THUMB16_POP_REGISTER_LIST 0xFF
  177. //
  178. // 32-BIT Thumb decoding constants
  179. //
  180. #define THUMB32_RFE_MASK 0xFFD0FFFF
  181. #define THUMB32_RFEIA_VALUE 0xF810C000
  182. #define THUMB32_RFEDB_VALUE 0xF990C000
  183. #define THUMB32_RFE_REGISTER_MASK 0x000F0000
  184. #define THUMB32_RFE_REGISTER_SHIFT 16
  185. #define THUMB32_LDM_MASK 0xFE500000
  186. #define THUMB32_LDM_VALUE 0xE8100000
  187. #define THUMB32_LDM_RN_SHIFT 16
  188. #define THUMB32_LDM_INCREMENT (1 << 23)
  189. #define THUMB32_TB_MASK 0xFFF0FFE0
  190. #define THUMB32_TB_VALUE 0xE8D0F000
  191. #define THUMB32_TB_RN_SHIFT 16
  192. #define THUMB32_TB_RM_SHIFT 0
  193. #define THUMB32_TB_HALF_WORD (1 << 4)
  194. #define THUMB32_SUBS_PC_LR_MASK 0xFFFFFF00
  195. #define THUMB32_SUBS_PC_LR_VALUE 0xF3DE8F00
  196. #define THUMB32_B_CONDITIONAL_MASK 0xF800D000
  197. #define THUMB32_B_CONDITIONAL_VALUE 0xF0008000
  198. #define THUMB32_B_IMMEDIATE11_SHIFT 0
  199. #define THUMB32_B_IMMEDIATE11_MASK 0x7FF
  200. #define THUMB32_B_J2_BIT (1 << 11)
  201. #define THUMB32_B_J1_BIT (1 << 13)
  202. #define THUMB32_B_S_BIT (1 << 26)
  203. #define THUMB32_B_CONDITIONAL_IMMEDIATE6_SHIFT 16
  204. #define THUMB32_B_CONDITIONAL_CONDITION_SHIFT 22
  205. #define THUMB32_B_CONDITIONAL_CONDITION_MASK 0xF
  206. #define THUMB32_B_UNCONDITIONAL_MASK 0xF800D000
  207. #define THUMB32_B_UNCONDITIONAL_VALUE 0xF0009000
  208. #define THUMB32_B_UNCONDITIONAL_IMMEDIATE10_SHIFT 16
  209. #define THUMB32_BL_MASK 0xF800C000
  210. #define THUMB32_BL_VALUE 0xF000C000
  211. #define THUMB32_BL_IMMEDIATE11_SHIFT 0
  212. #define THUMB32_BL_IMMEDIATE10_SHIFT 16
  213. #define THUMB32_BL_X_BIT (1 << 12)
  214. //
  215. // ----------------------------------------------- Internal Function Prototypes
  216. //
  217. KSTATUS
  218. ArpGetNextPcThumb (
  219. PTRAP_FRAME TrapFrame,
  220. ULONG Instruction,
  221. PGET_NEXT_PC_READ_MEMORY_FUNCTION ReadMemoryFunction,
  222. PBOOL IsFunctionReturning,
  223. PVOID *NextPcValue
  224. );
  225. KSTATUS
  226. ArpGetNextPcThumb16 (
  227. PTRAP_FRAME TrapFrame,
  228. ULONG Instruction,
  229. PGET_NEXT_PC_READ_MEMORY_FUNCTION ReadMemoryFunction,
  230. PBOOL IsFunctionReturning,
  231. PVOID *NextPcValue
  232. );
  233. KSTATUS
  234. ArpGetNextPcThumb32 (
  235. PTRAP_FRAME TrapFrame,
  236. ULONG Instruction,
  237. PGET_NEXT_PC_READ_MEMORY_FUNCTION ReadMemoryFunction,
  238. PBOOL IsFunctionReturning,
  239. PVOID *NextPcValue
  240. );
  241. BOOL
  242. ArpIsMaskedByThumbItState (
  243. ULONG Instruction,
  244. ULONG Cpsr,
  245. PGET_NEXT_PC_READ_MEMORY_FUNCTION ReadMemoryFunction,
  246. PVOID *NextPc
  247. );
  248. ULONG
  249. ArpGetArmRegister (
  250. PTRAP_FRAME TrapFrame,
  251. ULONG RegisterNumber
  252. );
  253. ULONG
  254. ArpDecodeShiftedOperand (
  255. PTRAP_FRAME TrapFrame,
  256. ULONG Instruction
  257. );
  258. ULONG
  259. ArpThumbGetInstructionSize (
  260. ULONG Instruction
  261. );
  262. BOOL
  263. ArpArmCheckConditionCode (
  264. ULONG Cpsr,
  265. UCHAR Condition
  266. );
  267. //
  268. // ------------------------------------------------------ Data Type Definitions
  269. //
  270. //
  271. // -------------------------------------------------------------------- Globals
  272. //
  273. //
  274. // ------------------------------------------------------------------ Functions
  275. //
  276. KSTATUS
  277. ArGetNextPc (
  278. PTRAP_FRAME TrapFrame,
  279. PGET_NEXT_PC_READ_MEMORY_FUNCTION ReadMemoryFunction,
  280. PBOOL IsFunctionReturning,
  281. PVOID *NextPcValue
  282. )
  283. /*++
  284. Routine Description:
  285. This routine attempts to predict the next instruction to be executed. It
  286. will decode the current instruction, check if the condition matches, and
  287. attempt to follow any branches.
  288. Arguments:
  289. TrapFrame - Supplies a pointer to the current machine state.
  290. ReadMemoryFunction - Supplies a pointer to a function this routine can
  291. call when it needs to read target memory.
  292. IsFunctionReturning - Supplies an optional pointer where a boolean will be
  293. stored indicating if the current instruction is a return of some kind.
  294. NextPcValue - Supplies a pointer of the next executing address.
  295. Return Value:
  296. Status code. This routine will attempt to make a guess at the next PC even
  297. if the status code is failing, but chances it's right go way down if a
  298. failing status is returned.
  299. --*/
  300. {
  301. ULONG Address;
  302. ULONG BaseRegister;
  303. BOOL Condition;
  304. UCHAR ConditionCode;
  305. ULONG DestinationRegister;
  306. BOOL FunctionReturning;
  307. ULONG Instruction;
  308. ULONG NextPc;
  309. BOOL NotDataProcessing;
  310. ULONG Offset;
  311. ULONG Operand1;
  312. ULONG Operand1Register;
  313. ULONG Operand2;
  314. ULONG RegisterCount;
  315. ULONG Registers;
  316. ULONG Result;
  317. ULONG ShiftImmediate;
  318. KSTATUS Status;
  319. FunctionReturning = FALSE;
  320. Result = 0;
  321. //
  322. // Get the current instruction.
  323. //
  324. Address = REMOVE_THUMB_BIT((UINTN)(TrapFrame->Pc));
  325. Status = ReadMemoryFunction((PVOID)Address,
  326. ARM_INSTRUCTION_LENGTH,
  327. &Instruction);
  328. if (!KSUCCESS(Status)) {
  329. goto GetNextPcEnd;
  330. }
  331. //
  332. // If executing in Thumb mode, use that encoding and skip all this ARM
  333. // mode stuff.
  334. //
  335. if ((TrapFrame->Cpsr & PSR_FLAG_THUMB) != 0) {
  336. Status = ArpGetNextPcThumb(TrapFrame,
  337. Instruction,
  338. ReadMemoryFunction,
  339. &FunctionReturning,
  340. (PVOID *)&NextPc);
  341. goto GetNextPcEnd;
  342. }
  343. //
  344. // The default guess is just PC + 4 in ARM mode.
  345. //
  346. NextPc = TrapFrame->Pc + 4;
  347. //
  348. // Determine whether the condition code is satisfied. If the condition is
  349. // not satisfied, there's no need to decode the instruction.
  350. //
  351. ConditionCode = (Instruction & ARM_CONDITION_CODE_MASK) >>
  352. ARM_CONDITION_CODE_SHIFT;
  353. if (ConditionCode != ARM_CONDITION_CODE_UNCONDITIONAL) {
  354. Condition = ArpArmCheckConditionCode(TrapFrame->Cpsr, ConditionCode);
  355. if (Condition == FALSE) {
  356. goto GetNextPcEnd;
  357. }
  358. }
  359. //
  360. // Attempt to decode a return from exception (RFE).
  361. //
  362. if ((Instruction & ARM_RFE_MASK) == ARM_RFE_VALUE) {
  363. BaseRegister = (Instruction & ARM_RFE_REGISTER_MASK) >>
  364. ARM_RFE_REGISTER_SHIFT;
  365. Address = ArpGetArmRegister(TrapFrame, BaseRegister);
  366. //
  367. // The RFE instruction pops the PC and CPSR. Determine the location of
  368. // the PC based on the mode.
  369. //
  370. if ((Instruction & ARM_RFE_INCREMENT) == 0) {
  371. Address -= (sizeof(PVOID) * 2);
  372. if ((Instruction & ARM_RFE_PREINDEX) == 0) {
  373. Address += sizeof(PVOID);
  374. }
  375. } else if ((Instruction & ARM_RFE_PREINDEX) != 0) {
  376. Address += sizeof(PVOID);
  377. }
  378. Status = ReadMemoryFunction((PVOID)Address, sizeof(PVOID), &NextPc);
  379. goto GetNextPcEnd;
  380. }
  381. //
  382. // Attempt to decode a branch and exchange instruction. It branches to the
  383. // contents of a register indexed by the last 4 bits of the instruction.
  384. //
  385. if ((ConditionCode != ARM_CONDITION_CODE_UNCONDITIONAL) &&
  386. (((Instruction & BRANCH_EXCHANGE_MASK) == BRANCH_EXCHANGE_VALUE) ||
  387. ((Instruction & BRANCH_EXCHANGE_X_MASK) == BRANCH_EXCHANGE_X_VALUE))) {
  388. if ((Instruction & 0xF) == BRANCH_EXCHANGE_LINK_REGISTER) {
  389. FunctionReturning = TRUE;
  390. }
  391. NextPc = ArpGetArmRegister(TrapFrame, Instruction & 0xF);
  392. goto GetNextPcEnd;
  393. }
  394. //
  395. // Attempt to decode a branch instruction. These instructions branch to
  396. // PC + immediate24, where the PC is 8 bytes ahead of the ARM instruction
  397. // being decoded. Recall that the guess of NextPc is already 4 ahead of the
  398. // current instruction. This mask works for both conditional and
  399. // unconditional branches.
  400. //
  401. if ((Instruction & BRANCH_MASK) == BRANCH_VALUE) {
  402. //
  403. // If this is an unconditional BLX instruction, the immediate value is
  404. // formed differently and the destination is Thumb, so the low bit
  405. // should be set in the address.
  406. //
  407. if (ConditionCode == ARM_CONDITION_CODE_UNCONDITIONAL) {
  408. Offset = (Instruction & 0x00FFFFFF) << 2;
  409. if ((Instruction & BRANCH_H_BIT) != 0) {
  410. Offset |= 0x2;
  411. }
  412. Offset |= ARM_THUMB_BIT;
  413. //
  414. // Otherwise The offset is formed by taking the lower 24 bits from the
  415. // instruction, right shifting by 2, and then sign extending.
  416. //
  417. } else {
  418. Offset = (Instruction & 0x00FFFFFF) << 2;
  419. }
  420. if ((Offset & 0x02000000) != 0) {
  421. Offset |= 0xFC000000;
  422. }
  423. NextPc += Offset + 4;
  424. goto GetNextPcEnd;
  425. }
  426. //
  427. // Attempt to decode a load register (LDR) instruction.
  428. //
  429. if ((ConditionCode != ARM_CONDITION_CODE_UNCONDITIONAL) &&
  430. ((Instruction & LOAD_STORE_SINGLE_MASK) == LOAD_STORE_SINGLE_VALUE) &&
  431. ((Instruction & MEDIA_MASK) != MEDIA_VALUE)) {
  432. DestinationRegister = (Instruction & DESTINATION_REGISTER_MASK) >>
  433. DESTINATION_REGISTER_SHIFT;
  434. //
  435. // This instruction only affects the PC if it's a load instruction and
  436. // the PC is the destination. Technically writebacks could affect the
  437. // PC too, but it's unlikely anyone would ever use that side effect
  438. // to manipulate the PC.
  439. //
  440. if (((Instruction & LOAD_BIT) != 0) &&
  441. (DestinationRegister == REGISTER_PC)) {
  442. BaseRegister = (Instruction & LOAD_STORE_BASE_MASK) >>
  443. LOAD_STORE_BASE_SHIFT;
  444. //
  445. // In the immediate addressing form, the address is [Rn +/- #imm12],
  446. // where the immediate is in the lower 12 bits of the instruction.
  447. //
  448. if ((Instruction & IMMEDIATE_BIT) == 0) {
  449. Offset = 0;
  450. if ((Instruction & PREINDEX_BIT) != 0) {
  451. Offset = Instruction & 0x00000FFF;
  452. }
  453. //
  454. // In the pre-indexed register addressing form, the address is
  455. // [Rn +/- Rm <shift> #<shift_imm>].
  456. //
  457. } else if ((Instruction & PREINDEX_BIT) != 0) {
  458. Offset = ArpDecodeShiftedOperand(TrapFrame, Instruction);
  459. //
  460. // Post-indexing uses only the base register as the address.
  461. //
  462. } else {
  463. Offset = 0;
  464. }
  465. //
  466. // Now form the actual address.
  467. //
  468. if ((Instruction & ADD_SUBTRACT_BIT) != 0) {
  469. Address = ArpGetArmRegister(TrapFrame, BaseRegister) +
  470. Offset;
  471. } else {
  472. Address = ArpGetArmRegister(TrapFrame, BaseRegister) -
  473. Offset;
  474. }
  475. //
  476. // Get that byte or word.
  477. //
  478. if ((Instruction & LOAD_STORE_BYTE_BIT) != 0) {
  479. Status = ReadMemoryFunction((PVOID)Address, 1, &NextPc);
  480. if (!KSUCCESS(Status)) {
  481. goto GetNextPcEnd;
  482. }
  483. if ((NextPc & 0x00000080) != 0) {
  484. NextPc |= 0xFFFFFF00;
  485. }
  486. } else {
  487. Status = ReadMemoryFunction((PVOID)Address, 4, &NextPc);
  488. if (!KSUCCESS(Status)) {
  489. goto GetNextPcEnd;
  490. }
  491. }
  492. }
  493. goto GetNextPcEnd;
  494. }
  495. //
  496. // Attempt to decode a load/store multiple instruction.
  497. //
  498. if ((ConditionCode != ARM_CONDITION_CODE_UNCONDITIONAL) &&
  499. ((Instruction & LOAD_STORE_MULTIPLE_MASK) ==
  500. LOAD_STORE_MULTIPLE_VALUE)) {
  501. //
  502. // Only care about load instructions that affect the PC register.
  503. //
  504. if (((Instruction & LOAD_BIT) != 0) &&
  505. ((Instruction & LOAD_STORE_MULTIPLE_PC_BIT) != 0)) {
  506. FunctionReturning = TRUE;
  507. BaseRegister = (Instruction & LOAD_STORE_BASE_MASK) >>
  508. LOAD_STORE_BASE_SHIFT;
  509. //
  510. // Count the number of registers being popped.
  511. //
  512. Registers = Instruction & REGISTER_LIST_MASK;
  513. RegisterCount = 0;
  514. while (Registers != 0) {
  515. if ((Registers & 0x1) != 0) {
  516. RegisterCount += 1;
  517. }
  518. Registers = Registers >> 1;
  519. }
  520. switch (Instruction & PUSH_POP_TYPE_MASK) {
  521. case PUSH_POP_INCREMENT_AFTER:
  522. Offset = RegisterCount - 1;
  523. break;
  524. case PUSH_POP_DECREMENT_AFTER:
  525. Offset = -(RegisterCount - 1);
  526. break;
  527. case PUSH_POP_INCREMENT_BEFORE:
  528. Offset = RegisterCount;
  529. break;
  530. case PUSH_POP_DECREMENT_BEFORE:
  531. Offset = -RegisterCount;
  532. break;
  533. default:
  534. goto GetNextPcEnd;
  535. }
  536. Address = ArpGetArmRegister(TrapFrame, BaseRegister) +
  537. (Offset * sizeof(ULONG));
  538. Status = ReadMemoryFunction((PVOID)Address, 4, &NextPc);
  539. if (!KSUCCESS(Status)) {
  540. goto GetNextPcEnd;
  541. }
  542. }
  543. goto GetNextPcEnd;
  544. }
  545. //
  546. // Decode data processing instructions.
  547. //
  548. if ((ConditionCode != ARM_CONDITION_CODE_UNCONDITIONAL) &&
  549. ((Instruction & DATA_PROCESSING_MASK) == DATA_PROCESSING_VALUE)) {
  550. NotDataProcessing = FALSE;
  551. //
  552. // The immediate form is an 8 bit value rotated right by 2 times the
  553. // shift amount.
  554. //
  555. if ((Instruction & IMMEDIATE_BIT) != 0) {
  556. //
  557. // The 16-bit immediate load and MSR instructions do not follow the
  558. // same pattern as the data processing instructions.
  559. //
  560. if ((Instruction & DATA_PROCESSING_NOT_IMMEDIATE_MASK) ==
  561. DATA_PROCESSING_NOT_IMMEDIATE_VALUE) {
  562. NotDataProcessing = TRUE;
  563. }
  564. ShiftImmediate = 2 * ((Instruction & IMMEDIATE_ROTATE_MASK) >>
  565. IMMEDIATE_ROTATE_SHIFT);
  566. Operand2 = Instruction & IMMEDIATE8_MASK;
  567. while (ShiftImmediate > 0) {
  568. if ((Operand2 & 0x1) != 0) {
  569. Operand2 = (Operand2 >> 1) | 0x80000000;
  570. } else {
  571. Operand2 = (Operand2 >> 1) & 0x7FFFFFFF;
  572. }
  573. ShiftImmediate -= 1;
  574. }
  575. //
  576. // The register form is either an immediate shift or a register shift.
  577. //
  578. } else {
  579. //
  580. // If the immediate bit is not set and it's a register shift, then
  581. // check the bit that must be zero. If it's not zero, then this
  582. // isn't actually a data processing instruction (it's a multiply).
  583. //
  584. if (((Instruction & REGISTER_REGISTER_SHIFT_BIT) != 0) &&
  585. ((Instruction & SHIFT_REGISTER_EMPTY_BIT) != 0)) {
  586. NotDataProcessing = TRUE;
  587. }
  588. Operand2 = ArpDecodeShiftedOperand(TrapFrame, Instruction);
  589. }
  590. Operand1Register = (Instruction & DATA_PROCESSING_OPERAND1_MASK) >>
  591. DATA_PROCESSING_OPERAND1_SHIFT;
  592. Operand1 = ArpGetArmRegister(TrapFrame, Operand1Register);
  593. //
  594. // Determine what to do based on the opcode.
  595. //
  596. switch ((Instruction & DATA_PROCESSING_OPCODE_MASK) >>
  597. DATA_PROCESSING_OPCODE_SHIFT) {
  598. case OPCODE_AND:
  599. Result = Operand1 & Operand2;
  600. break;
  601. case OPCODE_EOR:
  602. Result = Operand1 ^ Operand2;
  603. break;
  604. case OPCODE_SUB:
  605. Result = Operand1 - Operand2;
  606. break;
  607. case OPCODE_RSB:
  608. Result = Operand2 - Operand1;
  609. break;
  610. case OPCODE_ADD:
  611. Result = Operand1 + Operand2;
  612. break;
  613. case OPCODE_ADC:
  614. Result = Operand1 + Operand2;
  615. if ((TrapFrame->Cpsr & PSR_FLAG_CARRY) != 0) {
  616. Result += 1;
  617. }
  618. break;
  619. case OPCODE_SBC:
  620. Result = Operand1 - Operand2;
  621. if ((TrapFrame->Cpsr & PSR_FLAG_CARRY) == 0) {
  622. Result -= 1;
  623. }
  624. break;
  625. case OPCODE_RSC:
  626. Result = Operand2 - Operand1;
  627. if ((TrapFrame->Cpsr & PSR_FLAG_CARRY) == 0) {
  628. Result -= 1;
  629. }
  630. break;
  631. case OPCODE_ORR:
  632. Result = Operand1 | Operand2;
  633. break;
  634. case OPCODE_BIC:
  635. Result = Operand1 & (~Operand2);
  636. break;
  637. case OPCODE_MOV:
  638. Result = Operand2;
  639. if (Operand1 != 0) {
  640. NotDataProcessing = TRUE;
  641. }
  642. break;
  643. case OPCODE_MVN:
  644. Result = ~Operand2;
  645. if (Operand1 != 0) {
  646. NotDataProcessing = TRUE;
  647. }
  648. break;
  649. //
  650. // Compare instructions can't update the PC. If this is in fact a
  651. // data processing instruction, then there's nothing left to do.
  652. //
  653. case OPCODE_TST:
  654. case OPCODE_TEQ:
  655. case OPCODE_CMP:
  656. case OPCODE_CMN:
  657. if ((Instruction & SET_FLAGS_BIT) == 0) {
  658. NotDataProcessing = TRUE;
  659. }
  660. if (NotDataProcessing == FALSE) {
  661. goto GetNextPcEnd;
  662. }
  663. }
  664. //
  665. // If the destination register is the PC, then the next PC is the
  666. // result of the operation.
  667. //
  668. DestinationRegister = (Instruction & DESTINATION_REGISTER_MASK) >>
  669. DESTINATION_REGISTER_SHIFT;
  670. if (NotDataProcessing == FALSE) {
  671. if (DestinationRegister == REGISTER_PC) {
  672. NextPc = Result;
  673. }
  674. goto GetNextPcEnd;
  675. }
  676. }
  677. GetNextPcEnd:
  678. if (IsFunctionReturning != NULL) {
  679. *IsFunctionReturning = FunctionReturning;
  680. }
  681. *NextPcValue = (PVOID)NextPc;
  682. return Status;
  683. }
  684. VOID
  685. ArBackUpIfThenState (
  686. PTRAP_FRAME TrapFrame
  687. )
  688. /*++
  689. Routine Description:
  690. This routine backs up the Thumb if-then state in the CPSR by one
  691. instruction, assuming that the previous instruction tested positively for
  692. being executed.
  693. Arguments:
  694. TrapFrame - Supplies a pointer to the current machine state.
  695. Return Value:
  696. Status code. This routine will attempt to make a guess at the next PC even
  697. if the status code is failing, but chances it's right go way down if a
  698. failing status is returned.
  699. --*/
  700. {
  701. ULONG Condition;
  702. ULONG ItState;
  703. //
  704. // If the if-then state is no longer active, then it doesn't need to be
  705. // backed up (even if it was just previously active, as this instruction
  706. // is going to get executed).
  707. //
  708. if (!PSR_IS_IT_ACTIVE(TrapFrame->Cpsr)) {
  709. return;
  710. }
  711. ItState = PSR_GET_IT_STATE(TrapFrame->Cpsr);
  712. Condition = THUMB_CONDITION_FROM_IT_STATE(ItState);
  713. if (ArpArmCheckConditionCode(TrapFrame->Cpsr, Condition) != FALSE) {
  714. ItState = THUMB_RETREAT_IT_STATE(ItState, Condition & 0x1);
  715. } else {
  716. ItState = THUMB_RETREAT_IT_STATE(ItState, ((~Condition) & 0x1));
  717. }
  718. TrapFrame->Cpsr = PSR_SET_IT_STATE(TrapFrame->Cpsr, ItState);
  719. return;
  720. }
  721. //
  722. // --------------------------------------------------------- Internal Functions
  723. //
  724. KSTATUS
  725. ArpGetNextPcThumb (
  726. PTRAP_FRAME TrapFrame,
  727. ULONG Instruction,
  728. PGET_NEXT_PC_READ_MEMORY_FUNCTION ReadMemoryFunction,
  729. PBOOL IsFunctionReturning,
  730. PVOID *NextPcValue
  731. )
  732. /*++
  733. Routine Description:
  734. This routine attempts to predict the next instruction to be executed for
  735. Thumb-2 execution.
  736. Arguments:
  737. TrapFrame - Supplies a pointer to the current machine state.
  738. Instruction - Supplies the instruction itself.
  739. ReadMemoryFunction - Supplies a pointer to a function this routine can
  740. call when it needs to read target memory.
  741. IsFunctionReturning - Supplies an optional pointer where a boolean will be
  742. stored indicating if the current instruction is a return of some kind.
  743. NextPcValue - Supplies a pointer of the next executing address.
  744. Return Value:
  745. Status code. This routine will attempt to make a guess at the next PC even
  746. if the status code is failing, but chances it's right go way down if a
  747. failing status is returned.
  748. --*/
  749. {
  750. ULONG InstructionSize;
  751. BOOL IsMasked;
  752. KSTATUS Status;
  753. InstructionSize = ArpThumbGetInstructionSize(Instruction);
  754. *NextPcValue = (PVOID)((TrapFrame->Pc + InstructionSize) | ARM_THUMB_BIT);
  755. //
  756. // Determine if the if-then state dictates the next instruction. The
  757. // if-then instruction itself is also decoded in this routine.
  758. //
  759. IsMasked = ArpIsMaskedByThumbItState(Instruction,
  760. TrapFrame->Cpsr,
  761. ReadMemoryFunction,
  762. NextPcValue);
  763. if (IsMasked != FALSE) {
  764. return STATUS_SUCCESS;
  765. }
  766. //
  767. // Determine whether this is a 16 or 32-bit thumb instruction.
  768. //
  769. if (InstructionSize == THUMB32_INSTRUCTION_LENGTH) {
  770. //
  771. // Reverse the words of the 32-bit instruction.
  772. //
  773. Instruction = ((Instruction >> 16) & 0x0000FFFF) |
  774. ((Instruction << 16) & 0xFFFF0000);
  775. Status = ArpGetNextPcThumb32(TrapFrame,
  776. Instruction,
  777. ReadMemoryFunction,
  778. IsFunctionReturning,
  779. NextPcValue);
  780. return Status;
  781. }
  782. //
  783. // It's a 16-bit instruction.
  784. //
  785. Status = ArpGetNextPcThumb16(TrapFrame,
  786. Instruction,
  787. ReadMemoryFunction,
  788. IsFunctionReturning,
  789. NextPcValue);
  790. return Status;
  791. }
  792. KSTATUS
  793. ArpGetNextPcThumb16 (
  794. PTRAP_FRAME TrapFrame,
  795. ULONG Instruction,
  796. PGET_NEXT_PC_READ_MEMORY_FUNCTION ReadMemoryFunction,
  797. PBOOL IsFunctionReturning,
  798. PVOID *NextPcValue
  799. )
  800. /*++
  801. Routine Description:
  802. This routine attempts to predict the next instruction to be executed for
  803. 32-bit Thumb instructions.
  804. Arguments:
  805. TrapFrame - Supplies a pointer to the current machine state.
  806. Instruction - Supplies the instruction itself.
  807. ReadMemoryFunction - Supplies a pointer to a function this routine can
  808. call when it needs to read target memory.
  809. IsFunctionReturning - Supplies an optional pointer where a boolean will be
  810. stored indicating if the current instruction is a return of some kind.
  811. NextPcValue - Supplies a pointer of the next executing address.
  812. Return Value:
  813. Status code.
  814. --*/
  815. {
  816. PVOID Address;
  817. UCHAR Condition;
  818. UINTN NextPc;
  819. ULONG RegisterCount;
  820. ULONG RegisterList;
  821. UINTN Rm;
  822. UINTN Rn;
  823. LONG SignedImmediate;
  824. KSTATUS Status;
  825. ULONG UnsignedImmediate;
  826. ULONG Value;
  827. NextPc = (UINTN)*NextPcValue;
  828. //
  829. // Handle bx and blx. Not adding the thumb bit is intentional, as blx may
  830. // change modes.
  831. //
  832. if ((Instruction & THUMB16_BX_MASK) == THUMB16_BX_VALUE) {
  833. Rm = (Instruction >> THUMB16_BX_RM_SHIFT) & THUMB_REGISTER16_MASK;
  834. if (Rm == 14) {
  835. *IsFunctionReturning = TRUE;
  836. }
  837. NextPc = ArpGetArmRegister(TrapFrame, Rm);
  838. //
  839. // Handle conditional branches.
  840. //
  841. } else if ((Instruction & THUMB16_B_CONDITIONAL_MASK) ==
  842. THUMB16_B_CONDITIONAL_VALUE) {
  843. Condition = (Instruction >> THUMB16_B_CONDITIONAL_CONDITION_SHIFT) &
  844. THUMB_CONDITION_MASK;
  845. if (((Condition >> 1) != ARM_CONDITION_ALWAYS) &&
  846. (ArpArmCheckConditionCode(TrapFrame->Cpsr, Condition) != FALSE)) {
  847. SignedImmediate = (CHAR)(Instruction & THUMB_IMMEDIATE8_MASK);
  848. if ((SignedImmediate & 0x80) != 0) {
  849. SignedImmediate |= 0xFFFFFF00;
  850. }
  851. SignedImmediate <<= 1;
  852. //
  853. // The signed offset is PC-relative, but the Next PC guess is only
  854. // 2 bytes ahead of the instruction pointer, when the real PC is
  855. // always 4 bytes ahead on Thumb.
  856. //
  857. NextPc += SignedImmediate + THUMB16_INSTRUCTION_LENGTH;
  858. }
  859. //
  860. // Handle unconditional branches. Sign extend the immediate.
  861. //
  862. } else if ((Instruction & THUMB16_B_UNCONDITIONAL_MASK) ==
  863. THUMB16_B_UNCONDITIONAL_VALUE) {
  864. SignedImmediate = Instruction & THUMB_IMMEDIATE11_MASK;
  865. if ((SignedImmediate & (1 << 10)) != 0) {
  866. SignedImmediate |= 0xFFFFF800;
  867. }
  868. SignedImmediate <<= 1;
  869. //
  870. // The signed offset is PC-relative, but the Next PC guess is only
  871. // 2 bytes ahead of the instruction pointer, when the real PC is
  872. // always 4 bytes ahead on Thumb.
  873. //
  874. NextPc += SignedImmediate + THUMB16_INSTRUCTION_LENGTH;
  875. //
  876. // Handle compare and branch if zero (or not zero), cbz and cbnz. This
  877. // compares the encoded register value with zero (or not zero), and
  878. // branches if the comparison succeeded.
  879. //
  880. } else if ((Instruction & THUMB16_CBZ_MASK) == THUMB16_CBZ_VALUE) {
  881. Rn = Instruction & THUMB_REGISTER8_MASK;
  882. Value = ArpGetArmRegister(TrapFrame, Rn);
  883. UnsignedImmediate = (Instruction >> THUMB16_CBZ_IMMEDIATE5_SHIFT) &
  884. THUMB_IMMEDIATE5_MASK;
  885. if ((Instruction & THUMB16_CBZ_IMMEDIATE5) != 0) {
  886. UnsignedImmediate |= 1 << 5;
  887. }
  888. UnsignedImmediate <<= 1;
  889. Condition = (Value == 0);
  890. if ((Instruction & THUMB16_CBZ_NOT) != 0) {
  891. Condition = !Condition;
  892. }
  893. //
  894. // The offset is PC-relative, but the Next PC guess is only 2 bytes
  895. // ahead of the instruction pointer, when the real PC is always 4 bytes
  896. // ahead on Thumb.
  897. //
  898. if (Condition != 0) {
  899. NextPc += THUMB16_INSTRUCTION_LENGTH + UnsignedImmediate;
  900. }
  901. //
  902. // Handle a pop instruction.
  903. //
  904. } else if ((Instruction & THUMB16_POP_MASK) == THUMB16_POP_VALUE) {
  905. if ((Instruction & THUMB16_POP_PC) != 0) {
  906. *IsFunctionReturning = TRUE;
  907. RegisterList = Instruction & THUMB16_POP_REGISTER_LIST;
  908. //
  909. // Count the number of registers being popped.
  910. //
  911. RegisterCount = 0;
  912. while (RegisterList != 0) {
  913. if ((RegisterList & 0x1) != 0) {
  914. RegisterCount += 1;
  915. }
  916. RegisterList = RegisterList >> 1;
  917. }
  918. Address = (PVOID)ArpGetArmRegister(TrapFrame, 13);
  919. //
  920. // The pop action is always increment after.
  921. //
  922. Address += RegisterCount * sizeof(PVOID);
  923. Status = ReadMemoryFunction((PVOID)Address,
  924. sizeof(PVOID),
  925. &NextPc);
  926. if (!KSUCCESS(Status)) {
  927. return Status;
  928. }
  929. }
  930. }
  931. *NextPcValue = (PVOID)NextPc;
  932. return STATUS_SUCCESS;
  933. }
  934. KSTATUS
  935. ArpGetNextPcThumb32 (
  936. PTRAP_FRAME TrapFrame,
  937. ULONG Instruction,
  938. PGET_NEXT_PC_READ_MEMORY_FUNCTION ReadMemoryFunction,
  939. PBOOL IsFunctionReturning,
  940. PVOID *NextPcValue
  941. )
  942. /*++
  943. Routine Description:
  944. This routine attempts to predict the next instruction to be executed for
  945. 32-bit Thumb instructions.
  946. Arguments:
  947. TrapFrame - Supplies a pointer to the current machine state.
  948. Instruction - Supplies the instruction itself.
  949. ReadMemoryFunction - Supplies a pointer to a function this routine can
  950. call when it needs to read target memory.
  951. IsFunctionReturning - Supplies an optional pointer where a boolean will be
  952. stored indicating if the current instruction is a return of some kind.
  953. NextPcValue - Supplies a pointer of the next executing address.
  954. Return Value:
  955. Status code.
  956. --*/
  957. {
  958. UINTN Address;
  959. ULONG Bit;
  960. ULONG Condition;
  961. LONG Immediate;
  962. UINTN Offset;
  963. ULONG Register;
  964. ULONG RegisterCount;
  965. ULONG RegisterList;
  966. ULONG Rm;
  967. ULONG Rn;
  968. ULONG SBit;
  969. KSTATUS Status;
  970. Status = STATUS_SUCCESS;
  971. //
  972. // Handle the rfe (return from exception) instruction.
  973. //
  974. if (((Instruction & THUMB32_RFE_MASK) == THUMB32_RFEIA_VALUE) ||
  975. ((Instruction & THUMB32_RFE_MASK) == THUMB32_RFEDB_VALUE)) {
  976. *IsFunctionReturning = TRUE;
  977. Register = (Instruction & THUMB32_RFE_REGISTER_MASK) >>
  978. THUMB32_RFE_REGISTER_SHIFT;
  979. Address = ArpGetArmRegister(TrapFrame, Register);
  980. //
  981. // RFE pops the PC and CPSR from the register. For Thumb, there is only
  982. // IA and DB. For increment after, PC is located at the address stored
  983. // in the register. For decrement before, the register value minus 8 is
  984. // the location of the PC.
  985. //
  986. if ((Instruction & THUMB32_RFE_MASK) == THUMB32_RFEDB_VALUE) {
  987. Address -= 8;
  988. }
  989. Status = ReadMemoryFunction((PVOID)Address, sizeof(PVOID), NextPcValue);
  990. //
  991. // Handle ldm (load multiple) registers. They only matter if they pop the
  992. // PC.
  993. //
  994. } else if ((Instruction & THUMB32_LDM_MASK) == THUMB32_LDM_VALUE) {
  995. RegisterList = Instruction & REGISTER_LIST_MASK;
  996. if ((RegisterList & LOAD_STORE_MULTIPLE_PC_BIT) != 0) {
  997. *IsFunctionReturning = TRUE;
  998. //
  999. // Count the number of registers being popped.
  1000. //
  1001. RegisterCount = 0;
  1002. while (RegisterList != 0) {
  1003. if ((RegisterList & 0x1) != 0) {
  1004. RegisterCount += 1;
  1005. }
  1006. RegisterList = RegisterList >> 1;
  1007. }
  1008. Rn = (Instruction >> THUMB32_LDM_RN_SHIFT) & THUMB_REGISTER16_MASK;
  1009. Address = ArpGetArmRegister(TrapFrame, Rn);
  1010. //
  1011. // The pop action is either increment after or decrement before.
  1012. //
  1013. if ((Instruction & THUMB32_LDM_INCREMENT) != 0) {
  1014. Address += (RegisterCount - 1) * sizeof(PVOID);
  1015. } else {
  1016. Address -= (RegisterCount + 1) * sizeof(PVOID);
  1017. }
  1018. Status = ReadMemoryFunction((PVOID)Address,
  1019. sizeof(PVOID),
  1020. NextPcValue);
  1021. }
  1022. //
  1023. // Handle the tbb and tbh, which are table branch instructions. Rn
  1024. // specifies a base of a table, and Rm specifies an index into the table.
  1025. // Table branch causes a forward PC jump by the value in the table entry.
  1026. //
  1027. } else if ((Instruction & THUMB32_TB_MASK) == THUMB32_TB_VALUE) {
  1028. Rm = (Instruction >> THUMB32_TB_RM_SHIFT) & THUMB_REGISTER16_MASK;
  1029. Rn = (Instruction >> THUMB32_TB_RN_SHIFT) & THUMB_REGISTER16_MASK;
  1030. Rm = ArpGetArmRegister(TrapFrame, Rm);
  1031. Rn = ArpGetArmRegister(TrapFrame, Rn);
  1032. Offset = 0;
  1033. if ((Instruction & THUMB32_TB_HALF_WORD) != 0) {
  1034. Address = Rn + (Rm << 1);
  1035. Status = ReadMemoryFunction((PVOID)Address, 2, &Offset);
  1036. } else {
  1037. Address = Rn + Rm;
  1038. Status = ReadMemoryFunction((PVOID)Address, 1, &Offset);
  1039. }
  1040. if (!KSUCCESS(Status)) {
  1041. return Status;
  1042. }
  1043. //
  1044. // The next PC value was already guessed to be 4 bytes ahead of the
  1045. // instruction being decoded. Conveniently, that is the location of the
  1046. // actually PC (from the instruction's perspective) and the offset is
  1047. // PC-relative.
  1048. //
  1049. *NextPcValue += (Offset << 1);
  1050. //
  1051. // Handle the subs pc, lr, #imm8 instruction, which performs an exception
  1052. // return without the stack. It copies SPSR into CPSR, and moves the link
  1053. // register (offset by an unsigned immediate) to the PC. The ERET
  1054. // instruction is the same as subs pc, lr, #0.
  1055. //
  1056. } else if ((Instruction & THUMB32_SUBS_PC_LR_MASK) ==
  1057. THUMB32_SUBS_PC_LR_VALUE) {
  1058. *IsFunctionReturning = TRUE;
  1059. Offset = Instruction & THUMB_IMMEDIATE8_MASK;
  1060. *NextPcValue = (PVOID)(TrapFrame->SvcLink + Offset);
  1061. //
  1062. // Handle a conditional branch, which contains a signed however-many-bit
  1063. // immediate and a condition code.
  1064. //
  1065. } else if ((Instruction & THUMB32_B_CONDITIONAL_MASK) ==
  1066. THUMB32_B_CONDITIONAL_VALUE) {
  1067. Condition = (Instruction >> THUMB32_B_CONDITIONAL_CONDITION_SHIFT) &
  1068. THUMB32_B_CONDITIONAL_CONDITION_MASK;
  1069. if (((Condition >> 1) < ARM_CONDITION_ALWAYS) &&
  1070. (ArpArmCheckConditionCode(TrapFrame->Cpsr, Condition) != FALSE)) {
  1071. Immediate = (Instruction >> THUMB32_B_IMMEDIATE11_SHIFT) &
  1072. THUMB32_B_IMMEDIATE11_MASK;
  1073. Immediate |= ((Instruction >>
  1074. THUMB32_B_CONDITIONAL_IMMEDIATE6_SHIFT) &
  1075. THUMB_IMMEDIATE6_MASK) << 11;
  1076. if ((Instruction & THUMB32_B_J1_BIT) != 0) {
  1077. Immediate |= (1 << 17);
  1078. }
  1079. if ((Instruction & THUMB32_B_J2_BIT) != 0) {
  1080. Immediate |= (1 << 18);
  1081. }
  1082. if ((Instruction & THUMB32_B_S_BIT) != 0) {
  1083. Immediate |= (1 << 19);
  1084. }
  1085. Immediate <<= 1;
  1086. //
  1087. // Sign extend.
  1088. //
  1089. if ((Immediate & 0x00100000) != 0) {
  1090. Immediate |= 0xFFE00000;
  1091. }
  1092. //
  1093. // This immediate offset is PC relative. On Thumb, the PC is 4
  1094. // bytes ahead of the current instruction. The original guess for
  1095. // the next PC was four bytes ahead, so just add the immediate.
  1096. //
  1097. *NextPcValue += Immediate;
  1098. }
  1099. //
  1100. // Handle an unconditional branch instruction.
  1101. //
  1102. } else if ((Instruction & THUMB32_B_UNCONDITIONAL_MASK) ==
  1103. THUMB32_B_UNCONDITIONAL_VALUE) {
  1104. Immediate = (Instruction >> THUMB32_B_IMMEDIATE11_SHIFT) &
  1105. THUMB32_B_IMMEDIATE11_MASK;
  1106. Immediate |= ((Instruction >>
  1107. THUMB32_B_UNCONDITIONAL_IMMEDIATE10_SHIFT) &
  1108. THUMB_IMMEDIATE10_MASK) << 11;
  1109. //
  1110. // The next two bits are NOT(J2 EOR S) and NOT(J1 EOR S).
  1111. //
  1112. SBit = 0;
  1113. if ((Instruction & THUMB32_B_S_BIT) != 0) {
  1114. SBit = 1;
  1115. }
  1116. Bit = 0;
  1117. if ((Instruction & THUMB32_B_J1_BIT) != 0) {
  1118. Bit = 1;
  1119. }
  1120. Bit = !(Bit ^ SBit);
  1121. if (Bit != 0) {
  1122. Immediate |= 1 << 21;
  1123. }
  1124. Bit = 0;
  1125. if ((Instruction & THUMB32_B_J2_BIT) != 0) {
  1126. Bit = 1;
  1127. }
  1128. Bit = !(Bit ^ SBit);
  1129. if (Bit != 0) {
  1130. Immediate |= 1 << 22;
  1131. }
  1132. if (SBit != 0) {
  1133. Immediate |= 1 << 23;
  1134. }
  1135. Immediate <<= 1;
  1136. //
  1137. // Sign extend.
  1138. //
  1139. if ((Immediate & 0x01000000) != 0) {
  1140. Immediate |= 0xFE000000;
  1141. }
  1142. //
  1143. // This immediate offset is PC relative. On Thumb, the PC is 4 bytes
  1144. // ahead of the current instruction. The original guess for the next PC
  1145. // was four bytes ahead, so just add the immediate.
  1146. //
  1147. *NextPcValue += Immediate;
  1148. //
  1149. // Handle the bl and blx (immediate) instructions.
  1150. //
  1151. } else if ((Instruction & THUMB32_BL_MASK) == THUMB32_BL_VALUE) {
  1152. Immediate = ((Instruction >> THUMB32_BL_IMMEDIATE11_SHIFT) &
  1153. THUMB_IMMEDIATE11_MASK) |
  1154. (((Instruction >> THUMB32_BL_IMMEDIATE10_SHIFT) &
  1155. THUMB_IMMEDIATE10_MASK) << 11);
  1156. if ((Instruction & THUMB32_BL_X_BIT) == 0) {
  1157. Immediate &= ~ARM_THUMB_BIT;
  1158. }
  1159. //
  1160. // The next two bits are NOT(J1 EOR S) and NOT(J2 EOR S).
  1161. //
  1162. SBit = 0;
  1163. if ((Instruction & THUMB32_B_S_BIT) != 0) {
  1164. SBit = 1;
  1165. }
  1166. Bit = 0;
  1167. if ((Instruction & THUMB32_B_J2_BIT) != 0) {
  1168. Bit = 1;
  1169. }
  1170. Bit = !(Bit ^ SBit);
  1171. if (Bit != 0) {
  1172. Immediate |= 1 << 21;
  1173. }
  1174. Bit = 0;
  1175. if ((Instruction & THUMB32_B_J1_BIT) != 0) {
  1176. Bit = 1;
  1177. }
  1178. Bit = !(Bit ^ SBit);
  1179. if (Bit != 0) {
  1180. Immediate |= 1 << 22;
  1181. }
  1182. if (SBit != 0) {
  1183. Immediate |= 1 << 23;
  1184. }
  1185. Immediate <<= 1;
  1186. //
  1187. // Sign extend.
  1188. //
  1189. if ((Immediate & 0x00200000) != 0) {
  1190. Immediate |= 0xFFC00000;
  1191. }
  1192. //
  1193. // BLX instructions transfer from Thumb to ARM. The low bit of the
  1194. // address will be removed when aligning the PC down to a 4-byte
  1195. // boundary.
  1196. //
  1197. Address = (UINTN)(*NextPcValue);
  1198. if (((Instruction & THUMB32_BL_X_BIT) == 0) &&
  1199. ((Instruction & ARM_THUMB_BIT) == 0)) {
  1200. Address = ALIGN_RANGE_DOWN(Address, ARM_INSTRUCTION_LENGTH);
  1201. }
  1202. Address += Immediate;
  1203. *NextPcValue = (PVOID)Address;
  1204. }
  1205. return Status;
  1206. }
  1207. BOOL
  1208. ArpIsMaskedByThumbItState (
  1209. ULONG Instruction,
  1210. ULONG Cpsr,
  1211. PGET_NEXT_PC_READ_MEMORY_FUNCTION ReadMemoryFunction,
  1212. PVOID *NextPc
  1213. )
  1214. /*++
  1215. Routine Description:
  1216. This routine determines if the current instruction is disabled due to
  1217. Thumb if/then state masking it.
  1218. Arguments:
  1219. Instruction - Supplies the next instruction itself to be executed.
  1220. Cpsr - Supplies the current Program Status Register value.
  1221. ReadMemoryFunction - Supplies a pointer to a function this routine can
  1222. call when it needs to read target memory.
  1223. NextPc - Supplies a pointer where the next PC value will be returned if it
  1224. turns out that the If-Then state masks the normal next PC instruction.
  1225. Return Value:
  1226. TRUE if the instruction is not actually executed because the if/then state
  1227. is disabling it.
  1228. FALSE if the if/then state does not affect the next instruction's execution
  1229. (or the if-then state dictates that the next instruction will be executed).
  1230. --*/
  1231. {
  1232. UCHAR Condition;
  1233. ULONG InstructionSize;
  1234. ULONG ItState;
  1235. PVOID NextPcAddress;
  1236. BOOL Result;
  1237. KSTATUS Status;
  1238. Result = FALSE;
  1239. //
  1240. // Figure out the current if-then state. If the next instruction is an
  1241. // if-then instruction, use the mask set up by that.
  1242. //
  1243. if ((Instruction & THUMB16_IT_MASK) == THUMB16_IT_VALUE) {
  1244. ItState = Instruction & THUMB16_IT_STATE_MASK;
  1245. } else {
  1246. ItState = PSR_GET_IT_STATE(Cpsr);
  1247. //
  1248. // Assume that the next instruction to execute is the one that the
  1249. // breakpoint that got in here is sitting on, and advance beyond it.
  1250. //
  1251. ItState = THUMB_ADVANCE_IT_STATE(ItState);
  1252. }
  1253. //
  1254. // Loop skipping instructions that are going to be masked by the if-then
  1255. // state.
  1256. //
  1257. while (TRUE) {
  1258. //
  1259. // If all the if-then business is not on, return now.
  1260. //
  1261. if (!IS_THUMB_IT_STATE_ACTIVE(ItState)) {
  1262. break;
  1263. }
  1264. //
  1265. // If the if-then state works for the next instruction, return now.
  1266. //
  1267. Condition = THUMB_CONDITION_FROM_IT_STATE(ItState);
  1268. if (ArpArmCheckConditionCode(Cpsr, Condition) != FALSE) {
  1269. break;
  1270. }
  1271. //
  1272. // The if-then state is going to mask the next instruction, so advance
  1273. // the next PC and if-then state to the following instruction, maybe
  1274. // it will get executed. The architecture specifies that branching out
  1275. // in the middle of an if-then block is not allowed unless it's the
  1276. // last instruction. It also specifies that instructions in an if-then
  1277. // block are allowed to modify the flags. This loop doesn't handle
  1278. // that case.
  1279. //
  1280. NextPcAddress = (PVOID)REMOVE_THUMB_BIT((UINTN)*NextPc);
  1281. Status = ReadMemoryFunction(NextPcAddress,
  1282. THUMB32_INSTRUCTION_LENGTH,
  1283. &Instruction);
  1284. if (!KSUCCESS(Status)) {
  1285. break;
  1286. }
  1287. //
  1288. // Skip over this instruction that won't get executed.
  1289. //
  1290. InstructionSize = ArpThumbGetInstructionSize(Instruction);
  1291. *NextPc += InstructionSize;
  1292. ItState = THUMB_ADVANCE_IT_STATE(ItState);
  1293. Result = TRUE;
  1294. }
  1295. return Result;
  1296. }
  1297. ULONG
  1298. ArpGetArmRegister (
  1299. PTRAP_FRAME TrapFrame,
  1300. ULONG RegisterNumber
  1301. )
  1302. /*++
  1303. Routine Description:
  1304. This routine returns the register corresponding to one encoded in an ARM
  1305. instruction. 0 returns the contents of r0, 1 returns the contents of r1,
  1306. etc.
  1307. Arguments:
  1308. TrapFrame - Supplies a pointer to the current machine state. This is where
  1309. the register contents come from.
  1310. RegisterNumber - Supplies the register number to return.
  1311. Return Value:
  1312. Returns the contents of the desired register, or MAX_ULONG if the parameter
  1313. was invalid.
  1314. --*/
  1315. {
  1316. BOOL UserMode;
  1317. UserMode = FALSE;
  1318. if ((TrapFrame->Cpsr & ARM_MODE_MASK) == ARM_MODE_USER) {
  1319. UserMode = TRUE;
  1320. }
  1321. switch (RegisterNumber) {
  1322. case 0:
  1323. return TrapFrame->R0;
  1324. case 1:
  1325. return TrapFrame->R1;
  1326. case 2:
  1327. return TrapFrame->R2;
  1328. case 3:
  1329. return TrapFrame->R3;
  1330. case 4:
  1331. return TrapFrame->R4;
  1332. case 5:
  1333. return TrapFrame->R5;
  1334. case 6:
  1335. return TrapFrame->R6;
  1336. case 7:
  1337. return TrapFrame->R7;
  1338. case 8:
  1339. return TrapFrame->R8;
  1340. case 9:
  1341. return TrapFrame->R9;
  1342. case 10:
  1343. return TrapFrame->R10;
  1344. case 11:
  1345. return TrapFrame->R11;
  1346. case 12:
  1347. return TrapFrame->R12;
  1348. case 13:
  1349. if (UserMode != FALSE) {
  1350. return TrapFrame->UserSp;
  1351. } else {
  1352. return TrapFrame->SvcSp;
  1353. }
  1354. case 14:
  1355. if (UserMode != FALSE) {
  1356. return TrapFrame->UserLink;
  1357. } else {
  1358. return TrapFrame->SvcLink;
  1359. }
  1360. //
  1361. // When PC is used as an operand for a Thumb instruction, it is 4 ahead of
  1362. // the current instruction (i.e. the PC stored in the trap frame). When PC
  1363. // is used by an ARM instruction, it is 8 ahead of the current instruction.
  1364. //
  1365. case 15:
  1366. if ((TrapFrame->Cpsr & PSR_FLAG_THUMB) != 0) {
  1367. return TrapFrame->Pc + ARM_INSTRUCTION_LENGTH;
  1368. } else {
  1369. return TrapFrame->Pc + (ARM_INSTRUCTION_LENGTH * 2);
  1370. }
  1371. default:
  1372. return MAX_ULONG;
  1373. }
  1374. return MAX_ULONG;
  1375. }
  1376. ULONG
  1377. ArpDecodeShiftedOperand (
  1378. PTRAP_FRAME TrapFrame,
  1379. ULONG Instruction
  1380. )
  1381. /*++
  1382. Routine Description:
  1383. This routine decodes the operand offset for instructions that have
  1384. addressing modes of immediate shifts and register shifts.
  1385. Arguments:
  1386. TrapFrame - Supplies a pointer to the current machine state. This is where
  1387. the register contents come from.
  1388. Instruction - Supplies the instruction being decoded. It is assumed that
  1389. the instruction has been decoded sufficiently to know that this is the
  1390. correct addressing form.
  1391. Return Value:
  1392. Returns the contents of the shifted operand, which is usually added to the
  1393. base register operand.
  1394. --*/
  1395. {
  1396. ULONG Offset;
  1397. ULONG OffsetRegister;
  1398. ULONG ShiftAmount;
  1399. BOOL ShiftByImmediate;
  1400. ULONG ShiftRegister;
  1401. Offset = 0;
  1402. //
  1403. // Determine whether or not to shift by an immediate value or register
  1404. // value.
  1405. //
  1406. if ((Instruction & REGISTER_REGISTER_SHIFT_BIT) != 0) {
  1407. ShiftByImmediate = FALSE;
  1408. ShiftRegister = (Instruction & SHIFT_REGISTER_MASK) >>
  1409. SHIFT_REGISTER_SHIFT;
  1410. ShiftAmount = ArpGetArmRegister(TrapFrame, ShiftRegister);
  1411. if (ShiftAmount > 32) {
  1412. ShiftAmount = 0;
  1413. }
  1414. } else {
  1415. ShiftByImmediate = TRUE;
  1416. ShiftAmount = (Instruction & SHIFT_IMMEDIATE_MASK) >>
  1417. SHIFT_IMMEDIATE_SHIFT;
  1418. }
  1419. OffsetRegister = ArpGetArmRegister(TrapFrame,
  1420. Instruction & OPERAND2_REGISTER_MASK);
  1421. //
  1422. // Determine the offset.
  1423. //
  1424. switch (Instruction & SHIFT_TYPE) {
  1425. case SHIFT_LSL:
  1426. Offset = OffsetRegister << ShiftAmount;
  1427. break;
  1428. //
  1429. // Logical shift right fills the leftmost bits with zeroes.
  1430. // Since in C this behavior is technically not
  1431. // defined, enforce the zero fill by doing the shift manually.
  1432. //
  1433. case SHIFT_LSR:
  1434. if ((ShiftByImmediate != FALSE) && (ShiftAmount == 0)) {
  1435. ShiftAmount = 32;
  1436. }
  1437. Offset = OffsetRegister;
  1438. while (ShiftAmount > 0) {
  1439. Offset = (Offset >> 1) & 0x7FFFFFFF;
  1440. ShiftAmount -= 1;
  1441. }
  1442. break;
  1443. //
  1444. // Arithmetic shift right fills the leftmost bits with zeroes
  1445. // or ones depending on whether or not the previous bit was 0.
  1446. // Again, since C is not well defined, enforce this manually.
  1447. //
  1448. case SHIFT_ASR:
  1449. if ((ShiftByImmediate != FALSE) && (ShiftAmount == 0)) {
  1450. ShiftAmount = 32;
  1451. }
  1452. Offset = OffsetRegister;
  1453. while (ShiftAmount > 0) {
  1454. if ((Offset & 0x80000000) != 0) {
  1455. Offset = (Offset >> 1) | 0x80000000;
  1456. } else {
  1457. Offset = (Offset >> 1) & 0x7FFFFFFF;
  1458. }
  1459. ShiftAmount -= 1;
  1460. }
  1461. break;
  1462. //
  1463. // Rotate right is what it sounds like. Rotate right with
  1464. // extend uses the carry bit as a 33rd bit. The extend is
  1465. // specified with a shift immediate of 0.
  1466. //
  1467. case SHIFT_ROR:
  1468. Offset = OffsetRegister;
  1469. if ((ShiftByImmediate != FALSE) && (ShiftAmount == 0)) {
  1470. if ((TrapFrame->Cpsr & PSR_FLAG_CARRY) != 0) {
  1471. Offset = (Offset >> 1) | 0x80000000;
  1472. } else {
  1473. Offset = (Offset >> 1) & 0x7FFFFFFF;
  1474. }
  1475. //
  1476. // Normal rotate right.
  1477. //
  1478. } else {
  1479. while (ShiftAmount > 0) {
  1480. if ((Offset & 0x00000001) != 0) {
  1481. Offset = (Offset >> 1) | 0x80000000;
  1482. } else {
  1483. Offset = (Offset >> 1) & 0x7FFFFFFF;
  1484. }
  1485. ShiftAmount -= 1;
  1486. }
  1487. }
  1488. break;
  1489. }
  1490. return Offset;
  1491. }
  1492. ULONG
  1493. ArpThumbGetInstructionSize (
  1494. ULONG Instruction
  1495. )
  1496. /*++
  1497. Routine Description:
  1498. This routine determines the size of the given Thumb instruction.
  1499. Arguments:
  1500. Instruction - Supplies the instruction itself.
  1501. Return Value:
  1502. 2 or 4, depending on whether this is a 16-bit Thumb instruction or a 32-bit
  1503. instruction.
  1504. --*/
  1505. {
  1506. ULONG Op;
  1507. Op = (Instruction >> THUMB32_OP_SHIFT) & THUMB32_OP_MASK;
  1508. //
  1509. // Determine whether this is a 16 or 32-bit thumb instruction.
  1510. //
  1511. if (Op >= THUMB32_OP_MIN) {
  1512. return THUMB32_INSTRUCTION_LENGTH;
  1513. }
  1514. return THUMB16_INSTRUCTION_LENGTH;
  1515. }
  1516. BOOL
  1517. ArpArmCheckConditionCode (
  1518. ULONG Cpsr,
  1519. UCHAR Condition
  1520. )
  1521. /*++
  1522. Routine Description:
  1523. This routine determines whether or not the condition code matches the
  1524. current execution flags.
  1525. Arguments:
  1526. Cpsr - Supplies the current program status register flags.
  1527. Condition - Supplies the condition code.
  1528. Return Value:
  1529. TRUE if the current condition applies.
  1530. FALSE if the condition does not apply.
  1531. --*/
  1532. {
  1533. BOOL Result;
  1534. Result = FALSE;
  1535. //
  1536. // Handle the upper three bits.
  1537. //
  1538. switch (Condition >> 1) {
  1539. case ARM_CONDITION_EQUAL:
  1540. if ((Cpsr & PSR_FLAG_ZERO) != 0) {
  1541. Result = TRUE;
  1542. }
  1543. break;
  1544. case ARM_CONDITION_CARRY:
  1545. if ((Cpsr & PSR_FLAG_CARRY) != 0) {
  1546. Result = TRUE;
  1547. }
  1548. break;
  1549. case ARM_CONDITION_NEGATIVE:
  1550. if ((Cpsr & PSR_FLAG_NEGATIVE) != 0) {
  1551. Result = TRUE;
  1552. }
  1553. break;
  1554. case ARM_CONDITION_OVERFLOW:
  1555. if ((Cpsr & PSR_FLAG_OVERFLOW) != 0) {
  1556. Result = TRUE;
  1557. }
  1558. break;
  1559. case ARM_CONDITION_UNSIGNED_GREATER:
  1560. if (((Cpsr & PSR_FLAG_CARRY) != 0) &&
  1561. ((Cpsr & PSR_FLAG_ZERO) == 0)) {
  1562. Result = TRUE;
  1563. }
  1564. break;
  1565. case ARM_CONDITION_SIGNED_GREATER_OR_EQUAL:
  1566. //
  1567. // Signed greater than or equal to is true when N == V. The XOR reports
  1568. // when bits are different, so if it's zero, then N == V. The
  1569. // comparisons against zero are necessary, otherwise different bits
  1570. // are XORed.
  1571. //
  1572. if ((((Cpsr & PSR_FLAG_NEGATIVE) != 0) ^
  1573. ((Cpsr & PSR_FLAG_OVERFLOW) != 0)) == 0) {
  1574. Result = TRUE;
  1575. }
  1576. break;
  1577. case ARM_CONDITION_SIGNED_GREATER:
  1578. //
  1579. // Signed greater than is true when N == V and Z == 0. See above for
  1580. // how N == V is computed if the XOR is throwing you.
  1581. //
  1582. if (((Cpsr & PSR_FLAG_ZERO) == 0) &&
  1583. ((((Cpsr & PSR_FLAG_NEGATIVE) != 0) ^
  1584. ((Cpsr & PSR_FLAG_OVERFLOW) != 0)) == 0)) {
  1585. Result = TRUE;
  1586. }
  1587. break;
  1588. case ARM_CONDITION_ALWAYS:
  1589. default:
  1590. Result = TRUE;
  1591. break;
  1592. }
  1593. //
  1594. // The lowest bit, if set, simply negates the result.
  1595. //
  1596. if ((Condition & 0x1) != 0) {
  1597. Result = !Result;
  1598. }
  1599. return Result;
  1600. }