1
0

sstep.c 55 KB

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