thmdis.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. thmdis.c
  5. Abstract:
  6. This module implements support for disassembling the Thumb-2 instruction
  7. set on ARM processors.
  8. Author:
  9. Evan Green 26-Apr-2014
  10. Environment:
  11. Debug
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include "dbgrtl.h"
  17. #include "disasm.h"
  18. #include "armdis.h"
  19. #include "thmdis.h"
  20. #include <assert.h>
  21. #include <string.h>
  22. #include <stdio.h>
  23. //
  24. // ---------------------------------------------------------------- Definitions
  25. //
  26. //
  27. // ------------------------------------------------------ Data Type Definitions
  28. //
  29. //
  30. // ----------------------------------------------- Internal Function Prototypes
  31. //
  32. VOID
  33. DbgpThumb16DecodeShiftMoveCompare (
  34. PARM_DISASSEMBLY Context
  35. );
  36. VOID
  37. DbgpThumb16DecodeShiftImmediate (
  38. PARM_DISASSEMBLY Context
  39. );
  40. VOID
  41. DbgpThumb16DecodeAddSubtractRegister (
  42. PARM_DISASSEMBLY Context
  43. );
  44. VOID
  45. DbgpThumb16DecodeAddSubtractImmediate3 (
  46. PARM_DISASSEMBLY Context
  47. );
  48. VOID
  49. DbgpThumb16DecodeMoveCompareAddSubtractImmediate (
  50. PARM_DISASSEMBLY Context
  51. );
  52. VOID
  53. DbgpThumb16DecodeDataProcessing (
  54. PARM_DISASSEMBLY Context
  55. );
  56. VOID
  57. DbgpThumb16DecodeSpecialDataAndBx (
  58. PARM_DISASSEMBLY Context
  59. );
  60. VOID
  61. DbgpThumb16DecodeLdrLiteral (
  62. PARM_DISASSEMBLY Context
  63. );
  64. VOID
  65. DbgpThumb16DecodeLoadStoreSingle (
  66. PARM_DISASSEMBLY Context
  67. );
  68. VOID
  69. DbgpThumb16DecodeLoadStoreSingleRegister (
  70. PARM_DISASSEMBLY Context
  71. );
  72. VOID
  73. DbgpThumb16DecodeLoadStoreSingleImmediate (
  74. PARM_DISASSEMBLY Context
  75. );
  76. VOID
  77. DbgpThumb16DecodeLoadStoreSingleSpRelative (
  78. PARM_DISASSEMBLY Context
  79. );
  80. VOID
  81. DbgpThumb16DecodeAdrAddSp (
  82. PARM_DISASSEMBLY Context
  83. );
  84. VOID
  85. DbgpThumb16DecodeMiscellaneous (
  86. PARM_DISASSEMBLY Context
  87. );
  88. VOID
  89. DbgpThumb16DecodeLoadStoreMultiple (
  90. PARM_DISASSEMBLY Context
  91. );
  92. VOID
  93. DbgpThumb16DecodeConditionalBranchAndSvc (
  94. PARM_DISASSEMBLY Context
  95. );
  96. VOID
  97. DbgpThumb16DecodeUnconditionalBranch (
  98. PARM_DISASSEMBLY Context
  99. );
  100. VOID
  101. DbgpThumb16DecodeAdjustStackPointer (
  102. PARM_DISASSEMBLY Context
  103. );
  104. VOID
  105. DbgpThumb16DecodeCompareBranchIfZero (
  106. PARM_DISASSEMBLY Context
  107. );
  108. VOID
  109. DbgpThumb16DecodeSignZeroExtend (
  110. PARM_DISASSEMBLY Context
  111. );
  112. VOID
  113. DbgpThumb16DecodePushPop (
  114. PARM_DISASSEMBLY Context
  115. );
  116. VOID
  117. DbgpThumb16DecodeSetEndianness (
  118. PARM_DISASSEMBLY Context
  119. );
  120. VOID
  121. DbgpThumb16DecodeChangeState (
  122. PARM_DISASSEMBLY Context
  123. );
  124. VOID
  125. DbgpThumb16DecodeReverseBytes (
  126. PARM_DISASSEMBLY Context
  127. );
  128. VOID
  129. DbgpThumb16DecodeBreakpoint (
  130. PARM_DISASSEMBLY Context
  131. );
  132. VOID
  133. DbgpThumb16DecodeIfThenAndHints (
  134. PARM_DISASSEMBLY Context
  135. );
  136. //
  137. // -------------------------------------------------------------------- Globals
  138. //
  139. //
  140. // Define mnemonic tables.
  141. //
  142. PSTR DbgThumb16ShiftImmediateMnemonics[] = {
  143. "lsls",
  144. "lsrs",
  145. "asrs"
  146. };
  147. PSTR DbgThumb16MoveCompareImmediateOpcodes[] = {
  148. THUMB_MOVS_MNEMONIC,
  149. THUMB_CMP_MNEMONIC,
  150. THUMB_ADDS_MNEMONIC,
  151. THUMB_SUBS_MNEMONIC
  152. };
  153. PSTR DbgThumb16DataProcessingMnemonics[] = {
  154. "ands",
  155. "eors",
  156. "lsls",
  157. "lsrs",
  158. "asrs",
  159. "adcs",
  160. "sbcs",
  161. "rors",
  162. "tst",
  163. "rsbs",
  164. "cmp",
  165. "cmns",
  166. "orrs",
  167. "muls",
  168. "bics",
  169. "mvns",
  170. };
  171. PSTR DbgThumb16SpecialDataProcessingMnemonics[] = {
  172. "add",
  173. "cmp",
  174. "mov"
  175. };
  176. PSTR DbgThumb16LoadStoreSingleRegisterMnemonics[] = {
  177. "str",
  178. "strh",
  179. "strb",
  180. "ldrsb",
  181. "ldr",
  182. "ldrh",
  183. "ldrb",
  184. "ldrsh"
  185. };
  186. PSTR DbgThumb16SignZeroExtendMnemonics[] = {
  187. "sxth",
  188. "sxtb",
  189. "uxth",
  190. "uxtb"
  191. };
  192. PSTR DbgThumb16ReverseBytesMnemonics[] = {
  193. "rev",
  194. "rev16",
  195. "rev??",
  196. "revsh"
  197. };
  198. //
  199. // Define the two if then suffix arrays, one for when the least significant bit
  200. // of the first condition is clear, and the other for when it's set.
  201. //
  202. PSTR DbgThumb16IfThenSuffixes[2][16] = {
  203. {
  204. "",
  205. "ttt",
  206. "tt",
  207. "tte",
  208. "t",
  209. "tet",
  210. "te",
  211. "tee",
  212. "",
  213. "ett",
  214. "et",
  215. "ete",
  216. "e",
  217. "eet",
  218. "ee",
  219. "eee",
  220. },
  221. {
  222. "",
  223. "eee",
  224. "ee",
  225. "eet",
  226. "e",
  227. "ete",
  228. "et",
  229. "ett",
  230. "",
  231. "tee",
  232. "te",
  233. "tet",
  234. "t",
  235. "tte",
  236. "tt",
  237. "ttt",
  238. }
  239. };
  240. PSTR DbgThumb16HintsMnemonics[16] = {
  241. "nop",
  242. "yield",
  243. "wfe",
  244. "wfi",
  245. "srv",
  246. "hints???",
  247. "hints???",
  248. "hints???",
  249. "hints???",
  250. "hints???",
  251. "hints???",
  252. "hints???",
  253. "hints???",
  254. "hints???",
  255. "hints???",
  256. "hints???"
  257. };
  258. //
  259. // Define decode tables.
  260. //
  261. THUMB_DECODE_BRANCH DbgThumb32Table[] = {
  262. {0x1F, 0x1D, 11, DbgpThumb32Decode},
  263. {0x1F, 0x1E, 11, DbgpThumb32Decode},
  264. {0x1F, 0x1F, 11, DbgpThumb32Decode}
  265. };
  266. THUMB_DECODE_BRANCH DbgThumb16TopLevelTable[] = {
  267. {0x30, 0x00, 10, DbgpThumb16DecodeShiftMoveCompare},
  268. {0x3F, 0x10, 10, DbgpThumb16DecodeDataProcessing},
  269. {0x3F, 0x11, 10, DbgpThumb16DecodeSpecialDataAndBx},
  270. {0x3E, 0x12, 10, DbgpThumb16DecodeLdrLiteral},
  271. {0x3C, 0x14, 10, DbgpThumb16DecodeLoadStoreSingle},
  272. {0x38, 0x18, 10, DbgpThumb16DecodeLoadStoreSingle},
  273. {0x38, 0x20, 10, DbgpThumb16DecodeLoadStoreSingle},
  274. {0x3E, 0x28, 10, DbgpThumb16DecodeAdrAddSp},
  275. {0x3E, 0x2A, 10, DbgpThumb16DecodeAdrAddSp},
  276. {0x3C, 0x2C, 10, DbgpThumb16DecodeMiscellaneous},
  277. {0x3E, 0x30, 10, DbgpThumb16DecodeLoadStoreMultiple},
  278. {0x3E, 0x30, 10, DbgpThumb16DecodeLoadStoreMultiple},
  279. {0x3C, 0x34, 10, DbgpThumb16DecodeConditionalBranchAndSvc},
  280. {0x3E, 0x38, 10, DbgpThumb16DecodeUnconditionalBranch}
  281. };
  282. THUMB_DECODE_BRANCH DbgThumb16ShiftAddSubMovCmpTable[] = {
  283. {0x1C, 0x00, 9, DbgpThumb16DecodeShiftImmediate},
  284. {0x1C, 0x04, 9, DbgpThumb16DecodeShiftImmediate},
  285. {0x1C, 0x08, 9, DbgpThumb16DecodeShiftImmediate},
  286. {0x1F, 0x0C, 9, DbgpThumb16DecodeAddSubtractRegister},
  287. {0x1F, 0x0D, 9, DbgpThumb16DecodeAddSubtractRegister},
  288. {0x1F, 0x0E, 9, DbgpThumb16DecodeAddSubtractImmediate3},
  289. {0x1F, 0x0F, 9, DbgpThumb16DecodeAddSubtractImmediate3},
  290. {0x1C, 0x10, 9, DbgpThumb16DecodeMoveCompareAddSubtractImmediate},
  291. {0x1C, 0x14, 9, DbgpThumb16DecodeMoveCompareAddSubtractImmediate},
  292. {0x1C, 0x18, 9, DbgpThumb16DecodeMoveCompareAddSubtractImmediate},
  293. {0x1C, 0x1C, 9, DbgpThumb16DecodeMoveCompareAddSubtractImmediate},
  294. };
  295. THUMB_DECODE_BRANCH DbgThumb16LoadStoreSingleTable[] = {
  296. {0xF, 0x5, 12, DbgpThumb16DecodeLoadStoreSingleRegister},
  297. {0xF, 0x6, 12, DbgpThumb16DecodeLoadStoreSingleImmediate},
  298. {0xF, 0x7, 12, DbgpThumb16DecodeLoadStoreSingleImmediate},
  299. {0xF, 0x8, 12, DbgpThumb16DecodeLoadStoreSingleImmediate},
  300. {0xF, 0x9, 12, DbgpThumb16DecodeLoadStoreSingleSpRelative},
  301. };
  302. THUMB_DECODE_BRANCH DbgThumb16MiscellaneousTable[] = {
  303. {0xF, 0x0, 8, DbgpThumb16DecodeAdjustStackPointer},
  304. {0x5, 0x1, 8, DbgpThumb16DecodeCompareBranchIfZero},
  305. {0xF, 0x2, 8, DbgpThumb16DecodeSignZeroExtend},
  306. {0x6, 0x4, 8, DbgpThumb16DecodePushPop},
  307. {0xFF, 0x65, 4, DbgpThumb16DecodeSetEndianness},
  308. {0xFE, 0x66, 4, DbgpThumb16DecodeChangeState},
  309. {0xF, 0xA, 8, DbgpThumb16DecodeReverseBytes},
  310. {0xF, 0xE, 8, DbgpThumb16DecodeBreakpoint},
  311. {0xF, 0xF, 8, DbgpThumb16DecodeIfThenAndHints},
  312. };
  313. //
  314. // ------------------------------------------------------------------ Functions
  315. //
  316. VOID
  317. DbgpThumbDecode (
  318. PARM_DISASSEMBLY Context
  319. )
  320. /*++
  321. Routine Description:
  322. This routine decodes the Thumb-2 instruction set.
  323. Arguments:
  324. Context - Supplies a pointer to the disassembly context.
  325. Return Value:
  326. None.
  327. --*/
  328. {
  329. BOOL Decoded;
  330. //
  331. // It's a 32-bit instruction if it matches one of the table values,
  332. // otherwise it's a 16-bit instruction.
  333. //
  334. strcpy(Context->Mnemonic, "Unknown thumb");
  335. Decoded = THUMB_DECODE_WITH_TABLE(Context, DbgThumb32Table);
  336. if (Decoded != FALSE) {
  337. Context->Result->BinaryLength = THUMB32_INSTRUCTION_LENGTH;
  338. } else {
  339. Context->Result->BinaryLength = THUMB16_INSTRUCTION_LENGTH;
  340. //
  341. // Use the 16 bit table.
  342. //
  343. THUMB_DECODE_WITH_TABLE(Context, DbgThumb16TopLevelTable);
  344. }
  345. return;
  346. }
  347. BOOL
  348. DbgpThumbDecodeWithTable (
  349. PARM_DISASSEMBLY Context,
  350. PTHUMB_DECODE_BRANCH Table,
  351. ULONG TableSize
  352. )
  353. /*++
  354. Routine Description:
  355. This routine checks the masks and values specified by the given table, and
  356. calls the appropriate disassembly routine.
  357. Arguments:
  358. Context - Supplies a pointer to the disassembly context.
  359. Table - Supplies a pointer to the decode branch table.
  360. TableSize - Supplies the number of elements in the table.
  361. Return Value:
  362. TRUE if a match was found.
  363. --*/
  364. {
  365. ULONG Instruction;
  366. ULONG Mask;
  367. ULONG Shift;
  368. ULONG TableIndex;
  369. ULONG Value;
  370. Instruction = Context->Instruction;
  371. for (TableIndex = 0; TableIndex < TableSize; TableIndex += 1) {
  372. Shift = Table[TableIndex].Shift;
  373. Mask = Table[TableIndex].Mask << Shift;
  374. Value = Table[TableIndex].Value << Shift;
  375. if ((Instruction & Mask) == Value) {
  376. //
  377. // Call the disassembly routine, this table entry matched.
  378. //
  379. Table[TableIndex].Disassemble(Context);
  380. return TRUE;
  381. }
  382. }
  383. //
  384. // Nothing matched.
  385. //
  386. return FALSE;
  387. }
  388. //
  389. // --------------------------------------------------------- Internal Functions
  390. //
  391. VOID
  392. DbgpThumb16DecodeShiftMoveCompare (
  393. PARM_DISASSEMBLY Context
  394. )
  395. /*++
  396. Routine Description:
  397. This routine decodes shift (immediate), add, subtract, move, and compare
  398. instructions.
  399. Arguments:
  400. Context - Supplies a pointer to the disassembly context.
  401. Return Value:
  402. None.
  403. --*/
  404. {
  405. BOOL Decoded;
  406. Decoded = THUMB_DECODE_WITH_TABLE(Context,
  407. DbgThumb16ShiftAddSubMovCmpTable);
  408. assert(Decoded != FALSE);
  409. return;
  410. }
  411. VOID
  412. DbgpThumb16DecodeShiftImmediate (
  413. PARM_DISASSEMBLY Context
  414. )
  415. /*++
  416. Routine Description:
  417. This routine decodes shift (immediate) instructions.
  418. Arguments:
  419. Context - Supplies a pointer to the disassembly context.
  420. Return Value:
  421. None.
  422. --*/
  423. {
  424. ULONG Immediate5;
  425. ULONG Instruction;
  426. ULONG Op;
  427. ULONG Rd;
  428. ULONG Rm;
  429. Instruction = Context->Instruction;
  430. //
  431. // Watch out for the special case of all zero, it's a MOV.
  432. //
  433. if ((Instruction & THUMB16_MOVS_MASK) == THUMB16_MOVS_VALUE) {
  434. Rm = (Instruction >> THUMB16_MOVS_RM_SHIFT) & THUMB_REGISTER8_MASK;
  435. Rd = (Instruction >> THUMB16_MOVS_RD_SHIFT) & THUMB_REGISTER8_MASK;
  436. strcpy(Context->Mnemonic, THUMB_MOVS_MNEMONIC);
  437. strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
  438. strcpy(Context->Operand2, DbgArmRegisterNames[Rm]);
  439. return;
  440. }
  441. Op = (Instruction >> THUMB16_SHIFT_IMMEDIATE_OP_SHIFT) &
  442. THUMB16_SHIFT_IMMEDIATE_OP_MASK;
  443. assert(Op != 0x3);
  444. Rm = (Instruction >> THUMB16_SHIFT_IMMEDIATE_RM_SHIFT) &
  445. THUMB_REGISTER8_MASK;
  446. Rd = (Instruction >> THUMB16_SHIFT_IMMEDIATE_RD_SHIFT) &
  447. THUMB_REGISTER8_MASK;
  448. Immediate5 = (Instruction >> THUMB16_SHIFT_IMMEDIATE5_SHIFT) &
  449. THUMB_IMMEDIATE5_MASK;
  450. if (Immediate5 == 0) {
  451. Immediate5 = 32;
  452. }
  453. strcpy(Context->Mnemonic, DbgThumb16ShiftImmediateMnemonics[Op]);
  454. strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
  455. strcpy(Context->Operand2, DbgArmRegisterNames[Rm]);
  456. snprintf(Context->Operand3, sizeof(Context->Operand3), "#%d", Immediate5);
  457. return;
  458. }
  459. VOID
  460. DbgpThumb16DecodeAddSubtractRegister (
  461. PARM_DISASSEMBLY Context
  462. )
  463. /*++
  464. Routine Description:
  465. This routine decodes Thumb 16-bit add/subtract (register) instructions.
  466. Arguments:
  467. Context - Supplies a pointer to the disassembly context.
  468. Return Value:
  469. None.
  470. --*/
  471. {
  472. ULONG Instruction;
  473. ULONG Rd;
  474. ULONG Rm;
  475. ULONG Rn;
  476. Instruction = Context->Instruction;
  477. Rd = (Instruction >> THUMB16_ADD_SUBTRACT_REGISTER_RD_SHIFT) &
  478. THUMB_REGISTER8_MASK;
  479. Rm = (Instruction >> THUMB16_ADD_SUBTRACT_REGISTER_RM_SHIFT) &
  480. THUMB_REGISTER8_MASK;
  481. Rn = (Instruction >> THUMB16_ADD_SUBTRACT_REGISTER_RN_SHIFT) &
  482. THUMB_REGISTER8_MASK;
  483. if ((Instruction & THUMB16_SUBTRACT) != 0) {
  484. strcpy(Context->Mnemonic, THUMB_SUBS_MNEMONIC);
  485. } else {
  486. strcpy(Context->Mnemonic, THUMB_ADDS_MNEMONIC);
  487. }
  488. strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
  489. strcpy(Context->Operand2, DbgArmRegisterNames[Rn]);
  490. strcpy(Context->Operand3, DbgArmRegisterNames[Rm]);
  491. return;
  492. }
  493. VOID
  494. DbgpThumb16DecodeAddSubtractImmediate3 (
  495. PARM_DISASSEMBLY Context
  496. )
  497. /*++
  498. Routine Description:
  499. This routine decodes Thumb 16-bit add/subtract (3 bit immediate)
  500. instructions.
  501. Arguments:
  502. Context - Supplies a pointer to the disassembly context.
  503. Return Value:
  504. None.
  505. --*/
  506. {
  507. ULONG Immediate3;
  508. ULONG Instruction;
  509. ULONG Rd;
  510. ULONG Rn;
  511. Instruction = Context->Instruction;
  512. Rd = (Instruction >> THUMB16_ADD_SUBTRACT_IMMEDIATE3_RD_SHIFT) &
  513. THUMB_REGISTER8_MASK;
  514. Rn = (Instruction >> THUMB16_ADD_SUBTRACT_IMMEDIATE3_RN_SHIFT) &
  515. THUMB_REGISTER8_MASK;
  516. Immediate3 = (Instruction >> THUMB16_ADD_SUBTRACT_IMMEDIATE3_SHIFT) &
  517. THUMB_IMMEDIATE3_MASK;
  518. if ((Instruction & THUMB16_SUBTRACT) != 0) {
  519. strcpy(Context->Mnemonic, THUMB_SUBS_MNEMONIC);
  520. } else {
  521. strcpy(Context->Mnemonic, THUMB_ADDS_MNEMONIC);
  522. }
  523. strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
  524. strcpy(Context->Operand2, DbgArmRegisterNames[Rn]);
  525. snprintf(Context->Operand3, sizeof(Context->Operand3), "#%d", Immediate3);
  526. return;
  527. }
  528. VOID
  529. DbgpThumb16DecodeMoveCompareAddSubtractImmediate (
  530. PARM_DISASSEMBLY Context
  531. )
  532. /*++
  533. Routine Description:
  534. This routine decodes Thumb 16-bit move and compare (immediate) instructions,
  535. as well as the add/subtract (8-bit immediate) instructions.
  536. Arguments:
  537. Context - Supplies a pointer to the disassembly context.
  538. Return Value:
  539. None.
  540. --*/
  541. {
  542. ULONG Immediate8;
  543. ULONG Instruction;
  544. ULONG Op;
  545. ULONG Register;
  546. Instruction = Context->Instruction;
  547. Op = (Instruction >> THUMB16_MOVE_COMPARE_IMMEDIATE_OP_SHIFT) &
  548. THUMB16_MOVE_COMPARE_IMMEDIATE_OP_MASK;
  549. Register = (Instruction >> THUMB16_MOVE_COMPARE_IMMEDIATE_REGISTER_SHIFT) &
  550. THUMB_REGISTER8_MASK;
  551. Immediate8 = (Instruction >> THUMB16_MOVE_COMPARE_IMMEDIATE_SHIFT) &
  552. THUMB_IMMEDIATE8_MASK;
  553. strcpy(Context->Mnemonic, DbgThumb16MoveCompareImmediateOpcodes[Op]);
  554. strcpy(Context->Operand1, DbgArmRegisterNames[Register]);
  555. snprintf(Context->Operand2, sizeof(Context->Operand2), "#%d", Immediate8);
  556. return;
  557. }
  558. VOID
  559. DbgpThumb16DecodeDataProcessing (
  560. PARM_DISASSEMBLY Context
  561. )
  562. /*++
  563. Routine Description:
  564. This routine decodes Thumb 16-bit data processing instruction.
  565. Arguments:
  566. Context - Supplies a pointer to the disassembly context.
  567. Return Value:
  568. None.
  569. --*/
  570. {
  571. ULONG Instruction;
  572. ULONG Op;
  573. ULONG Rd;
  574. ULONG Rm;
  575. Instruction = Context->Instruction;
  576. Op = (Instruction >> THUMB16_DATA_PROCESSING_OP_SHIFT) &
  577. THUMB16_DATA_PROCESSING_OP_MASK;
  578. Rd = (Instruction >> THUMB16_DATA_PROCESSING_RD_SHIFT) &
  579. THUMB_REGISTER8_MASK;
  580. Rm = (Instruction >> THUMB16_DATA_PROCESSING_RM_SHIFT) &
  581. THUMB_REGISTER8_MASK;
  582. strcpy(Context->Mnemonic, DbgThumb16DataProcessingMnemonics[Op]);
  583. strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
  584. strcpy(Context->Operand2, DbgArmRegisterNames[Rm]);
  585. if (Op == THUMB16_DATA_PROCESSING_RSB) {
  586. strcpy(Context->Operand3, "#0");
  587. } else if (Op == THUMB16_DATA_PROCESSING_MUL) {
  588. strcpy(Context->Operand3, Context->Operand1);
  589. }
  590. return;
  591. }
  592. VOID
  593. DbgpThumb16DecodeSpecialDataAndBx (
  594. PARM_DISASSEMBLY Context
  595. )
  596. /*++
  597. Routine Description:
  598. This routine decodes Thumb 16-bit special data processing
  599. (accessing R8-R14) and branch with exchange (bl and blx) instructions.
  600. Arguments:
  601. Context - Supplies a pointer to the disassembly context.
  602. Return Value:
  603. None.
  604. --*/
  605. {
  606. ULONG Instruction;
  607. ULONG Op;
  608. ULONG Rd;
  609. ULONG Rm;
  610. Instruction = Context->Instruction;
  611. //
  612. // These registers can access the full R0-R15. The Rd register's high bit
  613. // is not stored sequentially though.
  614. //
  615. Rm = (Instruction >> THUMB16_SPECIAL_DATA_RM_SHIFT) & THUMB_REGISTER16_MASK;
  616. Rd = (Instruction >> THUMB16_SPECIAL_DATA_RD_SHIFT) & THUMB_REGISTER8_MASK;
  617. if ((Instruction & THUMB16_SPECIAL_DATA_RD_HIGH) != 0) {
  618. Rd |= 0x8;
  619. }
  620. Op = (Instruction >> THUMB16_SPECIAL_DATA_OP_SHIFT) &
  621. THUMB16_SPECIAL_DATA_OP_MASK;
  622. //
  623. // Handle bl and blx, which are also nestled in this branch (get it) of
  624. // the instruction set.
  625. //
  626. if (Op == THUMB16_SPECIAL_DATA_OP_BRANCH) {
  627. if ((Instruction & THUMB16_SPECIAL_DATA_BRANCH_LINK) != 0) {
  628. strcpy(Context->Mnemonic, THUMB_BLX_MNEMONIC);
  629. } else {
  630. strcpy(Context->Mnemonic, THUMB_BX_MNEMONIC);
  631. }
  632. strcpy(Context->Operand1, DbgArmRegisterNames[Rm]);
  633. return;
  634. }
  635. strcpy(Context->Mnemonic, DbgThumb16SpecialDataProcessingMnemonics[Op]);
  636. strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
  637. strcpy(Context->Operand2, DbgArmRegisterNames[Rm]);
  638. return;
  639. }
  640. VOID
  641. DbgpThumb16DecodeLdrLiteral (
  642. PARM_DISASSEMBLY Context
  643. )
  644. /*++
  645. Routine Description:
  646. This routine decodes the Thumb 16-bit LDR (load literal from PC-relative
  647. address).
  648. Arguments:
  649. Context - Supplies a pointer to the disassembly context.
  650. Return Value:
  651. None.
  652. --*/
  653. {
  654. ULONG Immediate8;
  655. ULONG Instruction;
  656. ULONGLONG OperandAddress;
  657. ULONG Rt;
  658. Instruction = Context->Instruction;
  659. Immediate8 = (Instruction >> THUMB16_LDR_IMMEDIATE8_SHIFT) &
  660. THUMB_IMMEDIATE8_MASK;
  661. Immediate8 <<= 2;
  662. Rt = (Instruction >> THUMB16_LDR_RT_SHIFT) & THUMB_REGISTER8_MASK;
  663. strcpy(Context->Mnemonic, THUMB_LDR_MNEMONIC);
  664. strcpy(Context->Operand1, DbgArmRegisterNames[Rt]);
  665. //
  666. // The immediate value is relative to the PC aligned down to a 4-byte
  667. // boundary. On Thumb, the PC is always 4 bytes ahead of the instruction
  668. // pointer.
  669. //
  670. OperandAddress = Context->InstructionPointer + 4;
  671. OperandAddress = THUMB_ALIGN_4(OperandAddress);
  672. OperandAddress += Immediate8;
  673. Context->Result->OperandAddress = OperandAddress;
  674. Context->Result->AddressIsDestination = FALSE;
  675. Context->Result->AddressIsValid = TRUE;
  676. snprintf(Context->Operand2,
  677. sizeof(Context->Operand2),
  678. "[0x%08llx]",
  679. OperandAddress);
  680. return;
  681. }
  682. VOID
  683. DbgpThumb16DecodeLoadStoreSingle (
  684. PARM_DISASSEMBLY Context
  685. )
  686. /*++
  687. Routine Description:
  688. This routine decodes the Thumb 16-bit LDR and STR single item instructions.
  689. Arguments:
  690. Context - Supplies a pointer to the disassembly context.
  691. Return Value:
  692. None.
  693. --*/
  694. {
  695. THUMB_DECODE_WITH_TABLE(Context, DbgThumb16LoadStoreSingleTable);
  696. return;
  697. }
  698. VOID
  699. DbgpThumb16DecodeLoadStoreSingleRegister (
  700. PARM_DISASSEMBLY Context
  701. )
  702. /*++
  703. Routine Description:
  704. This routine decodes the Thumb 16-bit load and store (LDR and STR) single
  705. items from registers.
  706. Arguments:
  707. Context - Supplies a pointer to the disassembly context.
  708. Return Value:
  709. None.
  710. --*/
  711. {
  712. ULONG Instruction;
  713. ULONG Op;
  714. ULONG Rm;
  715. ULONG Rn;
  716. ULONG Rt;
  717. Instruction = Context->Instruction;
  718. Op = (Instruction >> THUMB16_LOAD_STORE_REGISTER_OP_SHIFT) &
  719. THUMB16_LOAD_STORE_REGISTER_OP_MASK;
  720. Rm = (Instruction >> THUMB16_LOAD_STORE_REGISTER_RM_SHIFT) &
  721. THUMB_REGISTER8_MASK;
  722. Rn = (Instruction >> THUMB16_LOAD_STORE_REGISTER_RN_SHIFT) &
  723. THUMB_REGISTER8_MASK;
  724. Rt = (Instruction >> THUMB16_LOAD_STORE_REGISTER_RT_SHIFT) &
  725. THUMB_REGISTER8_MASK;
  726. strcpy(Context->Mnemonic, DbgThumb16LoadStoreSingleRegisterMnemonics[Op]);
  727. strcpy(Context->Operand1, DbgArmRegisterNames[Rt]);
  728. snprintf(Context->Operand2,
  729. sizeof(Context->Operand2),
  730. "[%s, %s]",
  731. DbgArmRegisterNames[Rn],
  732. DbgArmRegisterNames[Rm]);
  733. return;
  734. }
  735. VOID
  736. DbgpThumb16DecodeLoadStoreSingleImmediate (
  737. PARM_DISASSEMBLY Context
  738. )
  739. /*++
  740. Routine Description:
  741. This routine decodes the Thumb 16-bit load and store (LDR and STR) single
  742. items from immediates.
  743. Arguments:
  744. Context - Supplies a pointer to the disassembly context.
  745. Return Value:
  746. None.
  747. --*/
  748. {
  749. ULONG Immediate5;
  750. ULONG Instruction;
  751. PSTR Mnemonic;
  752. ULONG Op;
  753. ULONG Rn;
  754. ULONG Rt;
  755. Instruction = Context->Instruction;
  756. Immediate5 = (Instruction >> THUMB16_LOAD_STORE_IMMEDIATE5_SHIFT) &
  757. THUMB_IMMEDIATE5_MASK;
  758. Immediate5 <<= 2;
  759. Rn = (Instruction >> THUMB16_LOAD_STORE_IMMEDIATE_RN_SHIFT) &
  760. THUMB_REGISTER8_MASK;
  761. Rt = (Instruction >> THUMB16_LOAD_STORE_IMMEDIATE_RT_SHIFT) &
  762. THUMB_REGISTER8_MASK;
  763. Op = (Instruction >> THUMB16_LOAD_STORE_IMMEDIATE_OP_SHIFT) &
  764. THUMB16_LOAD_STORE_IMMEDIATE_OP_MASK;
  765. //
  766. // Figure out the mnemonic. Check the higher level opcode mask to figure
  767. // out if it's a half-word load/store. If not, then it's a 32-bit or 8-bit
  768. // load or store.
  769. //
  770. if (Op == THUMB16_LOAD_STORE_IMMEDIATE_OP_HALF_WORD) {
  771. if ((Instruction & THUMB16_LOAD_BIT) != 0) {
  772. Mnemonic = THUMB_LDRH_MNEMONIC;
  773. } else {
  774. Mnemonic = THUMB_STRH_MNEMONIC;
  775. }
  776. } else {
  777. if ((Instruction & THUMB16_LOAD_BIT) != 0) {
  778. if ((Instruction & THUMB16_LOAD_STORE_BYTE) != 0) {
  779. Mnemonic = THUMB_LDRB_MNEMONIC;
  780. } else {
  781. Mnemonic = THUMB_LDR_MNEMONIC;
  782. }
  783. } else {
  784. if ((Instruction & THUMB16_LOAD_STORE_BYTE) != 0) {
  785. Mnemonic = THUMB_STRB_MNEMONIC;
  786. } else {
  787. Mnemonic = THUMB_STR_MNEMONIC;
  788. }
  789. }
  790. }
  791. strcpy(Context->Mnemonic, Mnemonic);
  792. strcpy(Context->Operand1, DbgArmRegisterNames[Rt]);
  793. if (Immediate5 != 0) {
  794. snprintf(Context->Operand2,
  795. sizeof(Context->Operand2),
  796. "[%s, #%d]",
  797. DbgArmRegisterNames[Rn],
  798. Immediate5);
  799. } else {
  800. snprintf(Context->Operand2,
  801. sizeof(Context->Operand2),
  802. "[%s]",
  803. DbgArmRegisterNames[Rn]);
  804. }
  805. return;
  806. }
  807. VOID
  808. DbgpThumb16DecodeLoadStoreSingleSpRelative (
  809. PARM_DISASSEMBLY Context
  810. )
  811. /*++
  812. Routine Description:
  813. This routine decodes the Thumb 16-bit load and store (LDR and STR) from a
  814. stack pointer relative address.
  815. Arguments:
  816. Context - Supplies a pointer to the disassembly context.
  817. Return Value:
  818. None.
  819. --*/
  820. {
  821. ULONG Immediate8;
  822. ULONG Instruction;
  823. ULONG Rt;
  824. Instruction = Context->Instruction;
  825. Immediate8 = (Instruction >>
  826. THUMB16_LOAD_STORE_SP_RELATIVE_IMMEDIATE8_SHIFT) &
  827. THUMB_IMMEDIATE8_MASK;
  828. Immediate8 <<= 2;
  829. Rt = (Instruction >> THUMB16_LOAD_STORE_SP_RELATIVE_IMMEDIATE8_SHIFT) &
  830. THUMB_REGISTER8_MASK;
  831. if ((Instruction & THUMB16_LOAD_BIT) != 0) {
  832. strcpy(Context->Mnemonic, THUMB_LDR_MNEMONIC);
  833. } else {
  834. strcpy(Context->Mnemonic, THUMB_STR_MNEMONIC);
  835. }
  836. strcpy(Context->Operand1, DbgArmRegisterNames[Rt]);
  837. if (Immediate8 != 0) {
  838. snprintf(Context->Operand2,
  839. sizeof(Context->Operand2),
  840. "[sp, #%d]",
  841. Immediate8);
  842. } else {
  843. strcpy(Context->Operand2, "[sp]");
  844. }
  845. return;
  846. }
  847. VOID
  848. DbgpThumb16DecodeAdrAddSp (
  849. PARM_DISASSEMBLY Context
  850. )
  851. /*++
  852. Routine Description:
  853. This routine decodes the Thumb 16-bit ADR instruction, which loads a
  854. PC-relative address. It also decodes the ADD (sp relative) instruction.
  855. Arguments:
  856. Context - Supplies a pointer to the disassembly context.
  857. Return Value:
  858. None.
  859. --*/
  860. {
  861. PSTR BaseMnemonic;
  862. ULONG Immediate8;
  863. ULONG Instruction;
  864. ULONGLONG OperandAddress;
  865. ULONG Rd;
  866. Instruction = Context->Instruction;
  867. Immediate8 = (Instruction >> THUMB16_ADR_IMMEDIATE8_SHIFT) &
  868. THUMB_IMMEDIATE8_MASK;
  869. Immediate8 <<= 2;
  870. Rd = (Instruction >> THUMB16_ADR_RD_SHIFT) & THUMB_REGISTER8_MASK;
  871. //
  872. // The second operand is either SP with an immediate or an absolute address
  873. // calculated from the PC aligned down to a 4-byte boundary.
  874. //
  875. if ((Instruction & THUMB16_ADR_SP) != 0) {
  876. BaseMnemonic = THUMB_ADD_MNEMONIC;
  877. snprintf(Context->Operand2,
  878. sizeof(Context->Operand2),
  879. "%s, #%d",
  880. DbgArmRegisterNames[13],
  881. Immediate8);
  882. } else {
  883. BaseMnemonic = THUMB_ADR_MNEMONIC;
  884. //
  885. // The label here is relative to the PC aligned down to 4-byte boundary.
  886. // On Thumb, the PC is always 4 bytes ahead of the instruction pointer.
  887. //
  888. OperandAddress = Context->InstructionPointer + 4;
  889. OperandAddress = THUMB_ALIGN_4(OperandAddress);
  890. OperandAddress += Immediate8;
  891. Context->Result->OperandAddress = OperandAddress;
  892. Context->Result->AddressIsDestination = FALSE;
  893. Context->Result->AddressIsValid = TRUE;
  894. snprintf(Context->Operand2,
  895. sizeof(Context->Operand2),
  896. "[0x%08llx]",
  897. OperandAddress);
  898. }
  899. strcpy(Context->Mnemonic, BaseMnemonic);
  900. strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
  901. return;
  902. }
  903. VOID
  904. DbgpThumb16DecodeMiscellaneous (
  905. PARM_DISASSEMBLY Context
  906. )
  907. /*++
  908. Routine Description:
  909. This routine decodes the Thumb 16-bit miscellaneous instructions.
  910. Arguments:
  911. Context - Supplies a pointer to the disassembly context.
  912. Return Value:
  913. None.
  914. --*/
  915. {
  916. THUMB_DECODE_WITH_TABLE(Context, DbgThumb16MiscellaneousTable);
  917. return;
  918. }
  919. VOID
  920. DbgpThumb16DecodeLoadStoreMultiple (
  921. PARM_DISASSEMBLY Context
  922. )
  923. /*++
  924. Routine Description:
  925. This routine decodes the Thumb 16-bit load and store multiple (LDM and STM)
  926. instructions.
  927. Arguments:
  928. Context - Supplies a pointer to the disassembly context.
  929. Return Value:
  930. None.
  931. --*/
  932. {
  933. ULONG Instruction;
  934. ULONG RegisterList;
  935. ULONG Rn;
  936. Instruction = Context->Instruction;
  937. Rn = (Instruction >> THUMB16_LOAD_STORE_MULTIPLE_RN_SHIFT) &
  938. THUMB_REGISTER8_MASK;
  939. if ((Instruction & THUMB16_LOAD_BIT) != 0) {
  940. strcpy(Context->Mnemonic, THUMB_LDM_MNEMONIC);
  941. } else {
  942. strcpy(Context->Mnemonic, THUMB_STM_MNEMONIC);
  943. }
  944. snprintf(Context->Operand1,
  945. sizeof(Context->Operand1),
  946. "%s!",
  947. DbgArmRegisterNames[Rn]);
  948. RegisterList = Instruction & THUMB_REGISTER8_LIST;
  949. DbgpArmDecodeRegisterList(Context->Operand2,
  950. sizeof(Context->Operand2),
  951. RegisterList);
  952. return;
  953. }
  954. VOID
  955. DbgpThumb16DecodeConditionalBranchAndSvc (
  956. PARM_DISASSEMBLY Context
  957. )
  958. /*++
  959. Routine Description:
  960. This routine decodes the Thumb 16-bit conditional branch, undefined
  961. instruction (UDF), and supervisor call (SVC, previously SWI).
  962. Arguments:
  963. Context - Supplies a pointer to the disassembly context.
  964. Return Value:
  965. None.
  966. --*/
  967. {
  968. UCHAR Immediate8;
  969. ULONG Instruction;
  970. ULONG Op;
  971. ULONGLONG OperandAddress;
  972. LONG SignedImmediate8;
  973. Instruction = Context->Instruction;
  974. Op = (Instruction >> THUMB16_BRANCH_SVC_OP_SHIFT) &
  975. THUMB16_BRANCH_SVC_OP_MASK;
  976. Immediate8 = Instruction & THUMB_IMMEDIATE8_MASK;
  977. SignedImmediate8 = (CHAR)Immediate8;
  978. SignedImmediate8 <<= 1;
  979. if (Op == THUMB16_BRANCH_SVC_OP_UDF) {
  980. strcpy(Context->Mnemonic, THUMB_UDF_MNEMONIC);
  981. snprintf(Context->Operand1,
  982. sizeof(Context->Operand1),
  983. "#%d",
  984. Immediate8);
  985. } else if (Op == THUMB16_BRANCH_SVC_OP_SVC) {
  986. strcpy(Context->Mnemonic, THUMB_SVC_MNEMONIC);
  987. snprintf(Context->Operand1,
  988. sizeof(Context->Operand1),
  989. "#%d",
  990. Immediate8);
  991. } else {
  992. snprintf(Context->Mnemonic,
  993. sizeof(Context->Mnemonic),
  994. "%s%s",
  995. THUMB_B_MNEMONIC,
  996. DbgArmConditionCodes[Op]);
  997. //
  998. // The destination address is relative to the PC value, which is always
  999. // 4 bytes ahead of the instruction pointer when in Thumb mode.
  1000. //
  1001. OperandAddress = Context->InstructionPointer + 4;
  1002. OperandAddress += (LONGLONG)SignedImmediate8;
  1003. Context->Result->OperandAddress = OperandAddress;
  1004. Context->Result->AddressIsDestination = TRUE;
  1005. Context->Result->AddressIsValid = TRUE;
  1006. snprintf(Context->Operand1,
  1007. sizeof(Context->Operand1),
  1008. "[0x%08llx]",
  1009. OperandAddress);
  1010. }
  1011. return;
  1012. }
  1013. VOID
  1014. DbgpThumb16DecodeUnconditionalBranch (
  1015. PARM_DISASSEMBLY Context
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. This routine decodes the Thumb 16-bit unconditional branch.
  1020. Arguments:
  1021. Context - Supplies a pointer to the disassembly context.
  1022. Return Value:
  1023. None.
  1024. --*/
  1025. {
  1026. ULONG Instruction;
  1027. ULONGLONG OperandAddress;
  1028. LONG SignedImmediate12;
  1029. Instruction = Context->Instruction;
  1030. SignedImmediate12 = Instruction & THUMB_IMMEDIATE11_MASK;
  1031. SignedImmediate12 <<= 1;
  1032. //
  1033. // Sign extend the 12-bit immediate.
  1034. //
  1035. if ((SignedImmediate12 & (1 << 11)) != 0) {
  1036. SignedImmediate12 |= 0xFFFFF000;
  1037. }
  1038. strcpy(Context->Mnemonic, THUMB_B_MNEMONIC);
  1039. //
  1040. // The destination address is relative to the PC value, which is always 4
  1041. // bytes ahead of the instruction pointer on Thumb.
  1042. //
  1043. OperandAddress = Context->InstructionPointer + 4;
  1044. OperandAddress += (LONGLONG)SignedImmediate12;
  1045. Context->Result->OperandAddress = OperandAddress;
  1046. Context->Result->AddressIsDestination = TRUE;
  1047. Context->Result->AddressIsValid = TRUE;
  1048. snprintf(Context->Operand1,
  1049. sizeof(Context->Operand1),
  1050. "[0x%08llx]",
  1051. OperandAddress);
  1052. return;
  1053. }
  1054. VOID
  1055. DbgpThumb16DecodeAdjustStackPointer (
  1056. PARM_DISASSEMBLY Context
  1057. )
  1058. /*++
  1059. Routine Description:
  1060. This routine decodes the Thumb 16-bit add immediate to and subtract
  1061. immediate from the stack pointer instructions.
  1062. Arguments:
  1063. Context - Supplies a pointer to the disassembly context.
  1064. Return Value:
  1065. None.
  1066. --*/
  1067. {
  1068. ULONG Immediate7;
  1069. ULONG Instruction;
  1070. Instruction = Context->Instruction;
  1071. if ((Instruction & THUMB16_ADJUST_STACK_POINTER_SUBTRACT) != 0) {
  1072. strcpy(Context->Mnemonic, THUMB_SUB_MNEMONIC);
  1073. } else {
  1074. strcpy(Context->Mnemonic, THUMB_ADD_MNEMONIC);
  1075. }
  1076. Immediate7 = Instruction & THUMB_IMMEDIATE7_MASK;
  1077. Immediate7 <<= 2;
  1078. strcpy(Context->Operand1, "sp");
  1079. snprintf(Context->Operand2,
  1080. sizeof(Context->Operand2),
  1081. "#%d",
  1082. Immediate7);
  1083. return;
  1084. }
  1085. VOID
  1086. DbgpThumb16DecodeCompareBranchIfZero (
  1087. PARM_DISASSEMBLY Context
  1088. )
  1089. /*++
  1090. Routine Description:
  1091. This routine decodes the Thumb 16-bit compare and branch if (or if not)
  1092. zero (CBZ and CBNZ) instructions.
  1093. Arguments:
  1094. Context - Supplies a pointer to the disassembly context.
  1095. Return Value:
  1096. None.
  1097. --*/
  1098. {
  1099. ULONG Immediate6;
  1100. ULONG Instruction;
  1101. ULONGLONG OperandAddress;
  1102. ULONG Rn;
  1103. Instruction = Context->Instruction;
  1104. if ((Instruction & THUMB16_COMPARE_BRANCH_NOT_ZERO) != 0) {
  1105. strcpy(Context->Mnemonic, THUMB_CBNZ_MNEMONIC);
  1106. } else {
  1107. strcpy(Context->Mnemonic, THUMB_CBZ_MNEMONIC);
  1108. }
  1109. Immediate6 = (Instruction >> THUMB16_COMPARE_BRANCH_ZERO_IMMEDIATE5_SHIFT) &
  1110. THUMB_IMMEDIATE5_MASK;
  1111. if ((Instruction & THUMB16_COMPARE_BRANCH_ZERO_IMMEDIATE6) != 0) {
  1112. Immediate6 |= 1 << 5;
  1113. }
  1114. Immediate6 <<= 1;
  1115. Rn = (Instruction >> THUMB16_COMPARE_BRANCH_ZERO_RN_SHIFT) &
  1116. THUMB_REGISTER8_MASK;
  1117. strcpy(Context->Operand1, DbgArmRegisterNames[Rn]);
  1118. //
  1119. // The branch address is the immediate value added to the PC value of the
  1120. // instruction. For Thumb, the PC is always 4 bytes ahead of the
  1121. // instruction pointer.
  1122. //
  1123. OperandAddress = Context->InstructionPointer + 4;
  1124. OperandAddress += Immediate6;
  1125. Context->Result->OperandAddress = OperandAddress;
  1126. Context->Result->AddressIsDestination = FALSE;
  1127. Context->Result->AddressIsValid = TRUE;
  1128. snprintf(Context->Operand2,
  1129. sizeof(Context->Operand2),
  1130. "[0x%08llx]",
  1131. OperandAddress);
  1132. return;
  1133. }
  1134. VOID
  1135. DbgpThumb16DecodeSignZeroExtend (
  1136. PARM_DISASSEMBLY Context
  1137. )
  1138. /*++
  1139. Routine Description:
  1140. This routine decodes the Thumb 16-bit sign extend and zero extend
  1141. instructions.
  1142. Arguments:
  1143. Context - Supplies a pointer to the disassembly context.
  1144. Return Value:
  1145. None.
  1146. --*/
  1147. {
  1148. ULONG Instruction;
  1149. ULONG Op;
  1150. ULONG Rd;
  1151. ULONG Rm;
  1152. Instruction = Context->Instruction;
  1153. Op = (Instruction >> THUMB16_SIGN_ZERO_EXTEND_OP_SHIFT) &
  1154. THUMB16_SIGN_ZERO_EXTEND_OP_MASK;
  1155. Rd = (Instruction >> THUMB16_SIGN_ZERO_EXTEND_RD_SHIFT) &
  1156. THUMB_REGISTER8_MASK;
  1157. Rm = (Instruction >> THUMB16_SIGN_ZERO_EXTEND_RM_SHIFT) &
  1158. THUMB_REGISTER8_MASK;
  1159. strcpy(Context->Mnemonic, DbgThumb16SignZeroExtendMnemonics[Op]);
  1160. strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
  1161. strcpy(Context->Operand2, DbgArmRegisterNames[Rm]);
  1162. return;
  1163. }
  1164. VOID
  1165. DbgpThumb16DecodePushPop (
  1166. PARM_DISASSEMBLY Context
  1167. )
  1168. /*++
  1169. Routine Description:
  1170. This routine decodes the Thumb 16-bit load and store multiple registers
  1171. (PUSH and POP) instructions.
  1172. Arguments:
  1173. Context - Supplies a pointer to the disassembly context.
  1174. Return Value:
  1175. None.
  1176. --*/
  1177. {
  1178. ULONG Instruction;
  1179. ULONG RegisterList;
  1180. Instruction = Context->Instruction;
  1181. RegisterList = Instruction & THUMB_REGISTER8_LIST;
  1182. if ((Instruction & THUMB16_LOAD_BIT) != 0) {
  1183. strcpy(Context->Mnemonic, THUMB_POP_MNEMONIC);
  1184. if ((Instruction & THUMB16_PUSH_POP_LINK_OR_PC) != 0) {
  1185. RegisterList |= 1 << 15;
  1186. }
  1187. } else {
  1188. strcpy(Context->Mnemonic, THUMB_PUSH_MNEMONIC);
  1189. if ((Instruction & THUMB16_PUSH_POP_LINK_OR_PC) != 0) {
  1190. RegisterList |= 1 << 14;
  1191. }
  1192. }
  1193. DbgpArmDecodeRegisterList(Context->Operand1,
  1194. sizeof(Context->Operand1),
  1195. RegisterList);
  1196. return;
  1197. }
  1198. VOID
  1199. DbgpThumb16DecodeSetEndianness (
  1200. PARM_DISASSEMBLY Context
  1201. )
  1202. /*++
  1203. Routine Description:
  1204. This routine decodes the Thumb 16-bit SETEND instruction.
  1205. Arguments:
  1206. Context - Supplies a pointer to the disassembly context.
  1207. Return Value:
  1208. None.
  1209. --*/
  1210. {
  1211. strcpy(Context->Mnemonic, THUMB_SETEND_MNEMONIC);
  1212. if ((Context->Instruction & THUMB16_SET_ENDIAN_BIG) != 0) {
  1213. strcpy(Context->Operand1, THUMB16_BIG_ENDIAN_MNEMONIC);
  1214. } else {
  1215. strcpy(Context->Operand1, THUMB16_LITTLE_ENDIAN_MNEMONIC);
  1216. }
  1217. return;
  1218. }
  1219. VOID
  1220. DbgpThumb16DecodeChangeState (
  1221. PARM_DISASSEMBLY Context
  1222. )
  1223. /*++
  1224. Routine Description:
  1225. This routine decodes the Thumb 16-bit change processor state (CPS)
  1226. instruction.
  1227. Arguments:
  1228. Context - Supplies a pointer to the disassembly context.
  1229. Return Value:
  1230. None.
  1231. --*/
  1232. {
  1233. ULONG Instruction;
  1234. Instruction = Context->Instruction;
  1235. if ((Instruction & THUMB16_CPS_DISABLE) != 0) {
  1236. strcpy(Context->Mnemonic, THUMB_CPS_DISABLE_MNEMONIC);
  1237. } else {
  1238. strcpy(Context->Mnemonic, THUMB_CPS_ENABLE_MNEMONIC);
  1239. }
  1240. strcpy(Context->Operand1, "");
  1241. if ((Instruction & THUMB16_CPS_FLAG_A) != 0) {
  1242. strcat(Context->Operand1, ARM_CPS_FLAG_A_STRING);
  1243. }
  1244. if ((Instruction & THUMB16_CPS_FLAG_I) != 0) {
  1245. strcat(Context->Operand1, ARM_CPS_FLAG_I_STRING);
  1246. }
  1247. if ((Instruction & THUMB16_CPS_FLAG_F) != 0) {
  1248. strcat(Context->Operand1, ARM_CPS_FLAG_F_STRING);
  1249. }
  1250. return;
  1251. }
  1252. VOID
  1253. DbgpThumb16DecodeReverseBytes (
  1254. PARM_DISASSEMBLY Context
  1255. )
  1256. /*++
  1257. Routine Description:
  1258. This routine decodes the Thumb 16-bit reverse bytes instructions.
  1259. Arguments:
  1260. Context - Supplies a pointer to the disassembly context.
  1261. Return Value:
  1262. None.
  1263. --*/
  1264. {
  1265. ULONG Instruction;
  1266. ULONG Op;
  1267. ULONG Rd;
  1268. ULONG Rn;
  1269. Instruction = Context->Instruction;
  1270. Op = (Instruction >> THUMB16_REVERSE_BYTES_OP_SHIFT) &
  1271. THUMB16_REVERSE_BYTES_OP_MASK;
  1272. Rd = (Instruction >> THUMB16_REVERSE_BYTES_RD_SHIFT) &
  1273. THUMB_REGISTER8_MASK;
  1274. Rn = (Instruction >> THUMB16_REVERSE_BYTES_RN_SHIFT) &
  1275. THUMB_REGISTER8_MASK;
  1276. strcpy(Context->Mnemonic, DbgThumb16ReverseBytesMnemonics[Op]);
  1277. strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
  1278. strcpy(Context->Operand2, DbgArmRegisterNames[Rn]);
  1279. return;
  1280. }
  1281. VOID
  1282. DbgpThumb16DecodeBreakpoint (
  1283. PARM_DISASSEMBLY Context
  1284. )
  1285. /*++
  1286. Routine Description:
  1287. This routine decodes the Thumb 16-bit breakpoint instruction.
  1288. Arguments:
  1289. Context - Supplies a pointer to the disassembly context.
  1290. Return Value:
  1291. None.
  1292. --*/
  1293. {
  1294. ULONG Immediate8;
  1295. ULONG Instruction;
  1296. Instruction = Context->Instruction;
  1297. Immediate8 = (Instruction >> THUMB16_BREAKPOINT_IMMEDIATE8_SHIFT) &
  1298. THUMB_IMMEDIATE8_MASK;
  1299. strcpy(Context->Mnemonic, THUMB_BKPT_MNEMONIC);
  1300. snprintf(Context->Operand1,
  1301. sizeof(Context->Operand1),
  1302. "#%d",
  1303. Immediate8);
  1304. return;
  1305. }
  1306. VOID
  1307. DbgpThumb16DecodeIfThenAndHints (
  1308. PARM_DISASSEMBLY Context
  1309. )
  1310. /*++
  1311. Routine Description:
  1312. This routine decodes the Thumb 16-bit if-then instruction, as well as
  1313. the category ARM describes as "hints" (NOP, YIELD, WFE, WFI, and SEV).
  1314. Arguments:
  1315. Context - Supplies a pointer to the disassembly context.
  1316. Return Value:
  1317. None.
  1318. --*/
  1319. {
  1320. ULONG Condition;
  1321. ULONG Condition0;
  1322. ULONG Instruction;
  1323. ULONG Mask;
  1324. ULONG Op;
  1325. Instruction = Context->Instruction;
  1326. Mask = Instruction & THUMB16_IF_THEN_MASK;
  1327. Condition = (Instruction >> THUMB16_IF_THEN_CONDITION_SHIFT) &
  1328. THUMB16_IF_THEN_CONDITION_MASK;
  1329. //
  1330. // If the mask is non-zero, then it's an if-then statement.
  1331. //
  1332. if (Mask != 0) {
  1333. Condition0 = Condition & 0x1;
  1334. snprintf(Context->Mnemonic,
  1335. sizeof(Context->Mnemonic),
  1336. "%s%s",
  1337. THUMB_IT_MNEMONIC,
  1338. DbgThumb16IfThenSuffixes[Condition0][Mask]);
  1339. strcpy(Context->Operand1, DbgArmConditionCodes[Condition]);
  1340. } else {
  1341. Op = (Instruction >> THUMB16_HINTS_OP_SHIFT) &
  1342. THUMB16_HINTS_OP_MASK;
  1343. strcpy(Context->Mnemonic, DbgThumb16HintsMnemonics[Op]);
  1344. }
  1345. return;
  1346. }