arm_disasm.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. // Copyright 2006 The Android Open Source Project
  2. #include <string>
  3. #include "common/string_util.h"
  4. #include "core/arm/disassembler/arm_disasm.h"
  5. #include "core/arm/skyeye_common/armsupp.h"
  6. static const char *cond_names[] = {
  7. "eq",
  8. "ne",
  9. "cs",
  10. "cc",
  11. "mi",
  12. "pl",
  13. "vs",
  14. "vc",
  15. "hi",
  16. "ls",
  17. "ge",
  18. "lt",
  19. "gt",
  20. "le",
  21. "",
  22. "RESERVED"
  23. };
  24. static const char *opcode_names[] = {
  25. "invalid",
  26. "undefined",
  27. "adc",
  28. "add",
  29. "and",
  30. "b",
  31. "bl",
  32. "bic",
  33. "bkpt",
  34. "blx",
  35. "bx",
  36. "cdp",
  37. "clz",
  38. "cmn",
  39. "cmp",
  40. "eor",
  41. "ldc",
  42. "ldm",
  43. "ldr",
  44. "ldrb",
  45. "ldrbt",
  46. "ldrh",
  47. "ldrsb",
  48. "ldrsh",
  49. "ldrt",
  50. "mcr",
  51. "mla",
  52. "mov",
  53. "mrc",
  54. "mrs",
  55. "msr",
  56. "mul",
  57. "mvn",
  58. "nop",
  59. "orr",
  60. "pld",
  61. "rsb",
  62. "rsc",
  63. "sbc",
  64. "sev",
  65. "smlal",
  66. "smull",
  67. "stc",
  68. "stm",
  69. "str",
  70. "strb",
  71. "strbt",
  72. "strh",
  73. "strt",
  74. "sub",
  75. "swi",
  76. "swp",
  77. "swpb",
  78. "teq",
  79. "tst",
  80. "umlal",
  81. "umull",
  82. "wfe",
  83. "wfi",
  84. "yield",
  85. "undefined",
  86. "adc",
  87. "add",
  88. "and",
  89. "asr",
  90. "b",
  91. "bic",
  92. "bkpt",
  93. "bl",
  94. "blx",
  95. "bx",
  96. "cmn",
  97. "cmp",
  98. "eor",
  99. "ldmia",
  100. "ldr",
  101. "ldrb",
  102. "ldrh",
  103. "ldrsb",
  104. "ldrsh",
  105. "lsl",
  106. "lsr",
  107. "mov",
  108. "mul",
  109. "mvn",
  110. "neg",
  111. "orr",
  112. "pop",
  113. "push",
  114. "ror",
  115. "sbc",
  116. "stmia",
  117. "str",
  118. "strb",
  119. "strh",
  120. "sub",
  121. "swi",
  122. "tst",
  123. NULL
  124. };
  125. // Indexed by the shift type (bits 6-5)
  126. static const char *shift_names[] = {
  127. "LSL",
  128. "LSR",
  129. "ASR",
  130. "ROR"
  131. };
  132. static const char* cond_to_str(uint32_t cond) {
  133. return cond_names[cond];
  134. }
  135. std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
  136. {
  137. Opcode opcode = Decode(insn);
  138. switch (opcode) {
  139. case OP_INVALID:
  140. return "Invalid";
  141. case OP_UNDEFINED:
  142. return "Undefined";
  143. case OP_ADC:
  144. case OP_ADD:
  145. case OP_AND:
  146. case OP_BIC:
  147. case OP_CMN:
  148. case OP_CMP:
  149. case OP_EOR:
  150. case OP_MOV:
  151. case OP_MVN:
  152. case OP_ORR:
  153. case OP_RSB:
  154. case OP_RSC:
  155. case OP_SBC:
  156. case OP_SUB:
  157. case OP_TEQ:
  158. case OP_TST:
  159. return DisassembleALU(opcode, insn);
  160. case OP_B:
  161. case OP_BL:
  162. return DisassembleBranch(addr, opcode, insn);
  163. case OP_BKPT:
  164. return DisassembleBKPT(insn);
  165. case OP_BLX:
  166. // not supported yet
  167. break;
  168. case OP_BX:
  169. return DisassembleBX(insn);
  170. case OP_CDP:
  171. return "cdp";
  172. case OP_CLZ:
  173. return DisassembleCLZ(insn);
  174. case OP_LDC:
  175. return "ldc";
  176. case OP_LDM:
  177. case OP_STM:
  178. return DisassembleMemblock(opcode, insn);
  179. case OP_LDR:
  180. case OP_LDRB:
  181. case OP_LDRBT:
  182. case OP_LDRT:
  183. case OP_STR:
  184. case OP_STRB:
  185. case OP_STRBT:
  186. case OP_STRT:
  187. return DisassembleMem(insn);
  188. case OP_LDRH:
  189. case OP_LDRSB:
  190. case OP_LDRSH:
  191. case OP_STRH:
  192. return DisassembleMemHalf(insn);
  193. case OP_MCR:
  194. case OP_MRC:
  195. return DisassembleMCR(opcode, insn);
  196. case OP_MLA:
  197. return DisassembleMLA(opcode, insn);
  198. case OP_MRS:
  199. return DisassembleMRS(insn);
  200. case OP_MSR:
  201. return DisassembleMSR(insn);
  202. case OP_MUL:
  203. return DisassembleMUL(opcode, insn);
  204. case OP_NOP:
  205. case OP_SEV:
  206. case OP_WFE:
  207. case OP_WFI:
  208. case OP_YIELD:
  209. return DisassembleNoOperands(opcode, insn);
  210. case OP_PLD:
  211. return DisassemblePLD(insn);
  212. case OP_STC:
  213. return "stc";
  214. case OP_SWI:
  215. return DisassembleSWI(insn);
  216. case OP_SWP:
  217. case OP_SWPB:
  218. return DisassembleSWP(opcode, insn);
  219. case OP_UMLAL:
  220. case OP_UMULL:
  221. case OP_SMLAL:
  222. case OP_SMULL:
  223. return DisassembleUMLAL(opcode, insn);
  224. default:
  225. return "Error";
  226. }
  227. return NULL;
  228. }
  229. std::string ARM_Disasm::DisassembleALU(Opcode opcode, uint32_t insn)
  230. {
  231. static const uint8_t kNoOperand1 = 1;
  232. static const uint8_t kNoDest = 2;
  233. static const uint8_t kNoSbit = 4;
  234. std::string rn_str;
  235. std::string rd_str;
  236. uint8_t flags = 0;
  237. uint8_t cond = (insn >> 28) & 0xf;
  238. uint8_t is_immed = (insn >> 25) & 0x1;
  239. uint8_t bit_s = (insn >> 20) & 1;
  240. uint8_t rn = (insn >> 16) & 0xf;
  241. uint8_t rd = (insn >> 12) & 0xf;
  242. uint8_t immed = insn & 0xff;
  243. const char* opname = opcode_names[opcode];
  244. switch (opcode) {
  245. case OP_CMN:
  246. case OP_CMP:
  247. case OP_TEQ:
  248. case OP_TST:
  249. flags = kNoDest | kNoSbit;
  250. break;
  251. case OP_MOV:
  252. case OP_MVN:
  253. flags = kNoOperand1;
  254. break;
  255. default:
  256. break;
  257. }
  258. // The "mov" instruction ignores the first operand (rn).
  259. rn_str[0] = 0;
  260. if ((flags & kNoOperand1) == 0) {
  261. rn_str = Common::StringFromFormat("r%d, ", rn);
  262. }
  263. // The following instructions do not write the result register (rd):
  264. // tst, teq, cmp, cmn.
  265. rd_str[0] = 0;
  266. if ((flags & kNoDest) == 0) {
  267. rd_str = Common::StringFromFormat("r%d, ", rd);
  268. }
  269. const char *sbit_str = "";
  270. if (bit_s && !(flags & kNoSbit))
  271. sbit_str = "s";
  272. if (is_immed) {
  273. return Common::StringFromFormat("%s%s%s\t%s%s#%u ; 0x%x",
  274. opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed);
  275. }
  276. uint8_t shift_is_reg = (insn >> 4) & 1;
  277. uint8_t rotate = (insn >> 8) & 0xf;
  278. uint8_t rm = insn & 0xf;
  279. uint8_t shift_type = (insn >> 5) & 0x3;
  280. uint8_t rs = (insn >> 8) & 0xf;
  281. uint8_t shift_amount = (insn >> 7) & 0x1f;
  282. uint32_t rotated_val = immed;
  283. uint8_t rotate2 = rotate << 1;
  284. rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2));
  285. if (!shift_is_reg && shift_type == 0 && shift_amount == 0) {
  286. return Common::StringFromFormat("%s%s%s\t%s%sr%d",
  287. opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm);
  288. }
  289. const char *shift_name = shift_names[shift_type];
  290. if (shift_is_reg) {
  291. return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s r%d",
  292. opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm,
  293. shift_name, rs);
  294. }
  295. if (shift_amount == 0) {
  296. if (shift_type == 3) {
  297. return Common::StringFromFormat("%s%s%s\t%s%sr%d, RRX",
  298. opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm);
  299. }
  300. shift_amount = 32;
  301. }
  302. return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s #%u",
  303. opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm,
  304. shift_name, shift_amount);
  305. }
  306. std::string ARM_Disasm::DisassembleBranch(uint32_t addr, Opcode opcode, uint32_t insn)
  307. {
  308. uint8_t cond = (insn >> 28) & 0xf;
  309. uint32_t offset = insn & 0xffffff;
  310. // Sign-extend the 24-bit offset
  311. if ((offset >> 23) & 1)
  312. offset |= 0xff000000;
  313. // Pre-compute the left-shift and the prefetch offset
  314. offset <<= 2;
  315. offset += 8;
  316. addr += offset;
  317. const char *opname = opcode_names[opcode];
  318. return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr);
  319. }
  320. std::string ARM_Disasm::DisassembleBX(uint32_t insn)
  321. {
  322. uint8_t cond = (insn >> 28) & 0xf;
  323. uint8_t rn = insn & 0xf;
  324. return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn);
  325. }
  326. std::string ARM_Disasm::DisassembleBKPT(uint32_t insn)
  327. {
  328. uint8_t cond = (insn >> 28) & 0xf;
  329. uint32_t immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf);
  330. return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed);
  331. }
  332. std::string ARM_Disasm::DisassembleCLZ(uint32_t insn)
  333. {
  334. uint8_t cond = (insn >> 28) & 0xf;
  335. uint8_t rd = (insn >> 12) & 0xf;
  336. uint8_t rm = insn & 0xf;
  337. return Common::StringFromFormat("clz%s\tr%d, r%d", cond_to_str(cond), rd, rm);
  338. }
  339. std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, uint32_t insn)
  340. {
  341. std::string tmp_list;
  342. uint8_t cond = (insn >> 28) & 0xf;
  343. uint8_t write_back = (insn >> 21) & 0x1;
  344. uint8_t bit_s = (insn >> 22) & 0x1;
  345. uint8_t is_up = (insn >> 23) & 0x1;
  346. uint8_t is_pre = (insn >> 24) & 0x1;
  347. uint8_t rn = (insn >> 16) & 0xf;
  348. uint16_t reg_list = insn & 0xffff;
  349. const char *opname = opcode_names[opcode];
  350. const char *bang = "";
  351. if (write_back)
  352. bang = "!";
  353. const char *carret = "";
  354. if (bit_s)
  355. carret = "^";
  356. const char *comma = "";
  357. tmp_list[0] = 0;
  358. for (int ii = 0; ii < 16; ++ii) {
  359. if (reg_list & (1 << ii)) {
  360. tmp_list += Common::StringFromFormat("%sr%d", comma, ii);
  361. comma = ",";
  362. }
  363. }
  364. const char *addr_mode = "";
  365. if (is_pre) {
  366. if (is_up) {
  367. addr_mode = "ib";
  368. } else {
  369. addr_mode = "db";
  370. }
  371. } else {
  372. if (is_up) {
  373. addr_mode = "ia";
  374. } else {
  375. addr_mode = "da";
  376. }
  377. }
  378. return Common::StringFromFormat("%s%s%s\tr%d%s, {%s}%s",
  379. opname, cond_to_str(cond), addr_mode, rn, bang, tmp_list.c_str(), carret);
  380. }
  381. std::string ARM_Disasm::DisassembleMem(uint32_t insn)
  382. {
  383. uint8_t cond = (insn >> 28) & 0xf;
  384. uint8_t is_reg = (insn >> 25) & 0x1;
  385. uint8_t is_load = (insn >> 20) & 0x1;
  386. uint8_t write_back = (insn >> 21) & 0x1;
  387. uint8_t is_byte = (insn >> 22) & 0x1;
  388. uint8_t is_up = (insn >> 23) & 0x1;
  389. uint8_t is_pre = (insn >> 24) & 0x1;
  390. uint8_t rn = (insn >> 16) & 0xf;
  391. uint8_t rd = (insn >> 12) & 0xf;
  392. uint16_t offset = insn & 0xfff;
  393. const char *opname = "ldr";
  394. if (!is_load)
  395. opname = "str";
  396. const char *bang = "";
  397. if (write_back)
  398. bang = "!";
  399. const char *minus = "";
  400. if (is_up == 0)
  401. minus = "-";
  402. const char *byte = "";
  403. if (is_byte)
  404. byte = "b";
  405. if (is_reg == 0) {
  406. if (is_pre) {
  407. if (offset == 0) {
  408. return Common::StringFromFormat("%s%s%s\tr%d, [r%d]",
  409. opname, cond_to_str(cond), byte, rd, rn);
  410. } else {
  411. return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s",
  412. opname, cond_to_str(cond), byte, rd, rn, minus, offset, bang);
  413. }
  414. } else {
  415. const char *transfer = "";
  416. if (write_back)
  417. transfer = "t";
  418. return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], #%s%u",
  419. opname, cond_to_str(cond), byte, transfer, rd, rn, minus, offset);
  420. }
  421. }
  422. uint8_t rm = insn & 0xf;
  423. uint8_t shift_type = (insn >> 5) & 0x3;
  424. uint8_t shift_amount = (insn >> 7) & 0x1f;
  425. const char *shift_name = shift_names[shift_type];
  426. if (is_pre) {
  427. if (shift_amount == 0) {
  428. if (shift_type == 0) {
  429. return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s",
  430. opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang);
  431. }
  432. if (shift_type == 3) {
  433. return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, RRX]%s",
  434. opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang);
  435. }
  436. shift_amount = 32;
  437. }
  438. return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, %s #%u]%s",
  439. opname, cond_to_str(cond), byte, rd, rn, minus, rm,
  440. shift_name, shift_amount, bang);
  441. }
  442. const char *transfer = "";
  443. if (write_back)
  444. transfer = "t";
  445. if (shift_amount == 0) {
  446. if (shift_type == 0) {
  447. return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d",
  448. opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
  449. }
  450. if (shift_type == 3) {
  451. return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, RRX",
  452. opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
  453. }
  454. shift_amount = 32;
  455. }
  456. return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, %s #%u",
  457. opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm,
  458. shift_name, shift_amount);
  459. }
  460. std::string ARM_Disasm::DisassembleMemHalf(uint32_t insn)
  461. {
  462. uint8_t cond = (insn >> 28) & 0xf;
  463. uint8_t is_load = (insn >> 20) & 0x1;
  464. uint8_t write_back = (insn >> 21) & 0x1;
  465. uint8_t is_immed = (insn >> 22) & 0x1;
  466. uint8_t is_up = (insn >> 23) & 0x1;
  467. uint8_t is_pre = (insn >> 24) & 0x1;
  468. uint8_t rn = (insn >> 16) & 0xf;
  469. uint8_t rd = (insn >> 12) & 0xf;
  470. uint8_t bits_65 = (insn >> 5) & 0x3;
  471. uint8_t rm = insn & 0xf;
  472. uint8_t offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf);
  473. const char *opname = "ldr";
  474. if (is_load == 0)
  475. opname = "str";
  476. const char *width = "";
  477. if (bits_65 == 1)
  478. width = "h";
  479. else if (bits_65 == 2)
  480. width = "sb";
  481. else
  482. width = "sh";
  483. const char *bang = "";
  484. if (write_back)
  485. bang = "!";
  486. const char *minus = "";
  487. if (is_up == 0)
  488. minus = "-";
  489. if (is_immed) {
  490. if (is_pre) {
  491. if (offset == 0) {
  492. return Common::StringFromFormat("%s%sh\tr%d, [r%d]", opname, cond_to_str(cond), rd, rn);
  493. } else {
  494. return Common::StringFromFormat("%s%sh\tr%d, [r%d, #%s%u]%s",
  495. opname, cond_to_str(cond), rd, rn, minus, offset, bang);
  496. }
  497. } else {
  498. return Common::StringFromFormat("%s%sh\tr%d, [r%d], #%s%u",
  499. opname, cond_to_str(cond), rd, rn, minus, offset);
  500. }
  501. }
  502. if (is_pre) {
  503. return Common::StringFromFormat("%s%sh\tr%d, [r%d, %sr%d]%s",
  504. opname, cond_to_str(cond), rd, rn, minus, rm, bang);
  505. } else {
  506. return Common::StringFromFormat("%s%sh\tr%d, [r%d], %sr%d",
  507. opname, cond_to_str(cond), rd, rn, minus, rm);
  508. }
  509. }
  510. std::string ARM_Disasm::DisassembleMCR(Opcode opcode, uint32_t insn)
  511. {
  512. uint8_t cond = (insn >> 28) & 0xf;
  513. uint8_t crn = (insn >> 16) & 0xf;
  514. uint8_t crd = (insn >> 12) & 0xf;
  515. uint8_t cpnum = (insn >> 8) & 0xf;
  516. uint8_t opcode2 = (insn >> 5) & 0x7;
  517. uint8_t crm = insn & 0xf;
  518. const char *opname = opcode_names[opcode];
  519. return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}",
  520. opname, cond_to_str(cond), cpnum, crd, crn, crm, opcode2);
  521. }
  522. std::string ARM_Disasm::DisassembleMLA(Opcode opcode, uint32_t insn)
  523. {
  524. uint8_t cond = (insn >> 28) & 0xf;
  525. uint8_t rd = (insn >> 16) & 0xf;
  526. uint8_t rn = (insn >> 12) & 0xf;
  527. uint8_t rs = (insn >> 8) & 0xf;
  528. uint8_t rm = insn & 0xf;
  529. uint8_t bit_s = (insn >> 20) & 1;
  530. const char *opname = opcode_names[opcode];
  531. return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d",
  532. opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs, rn);
  533. }
  534. std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, uint32_t insn)
  535. {
  536. uint8_t cond = (insn >> 28) & 0xf;
  537. uint8_t rdhi = (insn >> 16) & 0xf;
  538. uint8_t rdlo = (insn >> 12) & 0xf;
  539. uint8_t rs = (insn >> 8) & 0xf;
  540. uint8_t rm = insn & 0xf;
  541. uint8_t bit_s = (insn >> 20) & 1;
  542. const char *opname = opcode_names[opcode];
  543. return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d",
  544. opname, cond_to_str(cond), bit_s ? "s" : "", rdlo, rdhi, rm, rs);
  545. }
  546. std::string ARM_Disasm::DisassembleMUL(Opcode opcode, uint32_t insn)
  547. {
  548. uint8_t cond = (insn >> 28) & 0xf;
  549. uint8_t rd = (insn >> 16) & 0xf;
  550. uint8_t rs = (insn >> 8) & 0xf;
  551. uint8_t rm = insn & 0xf;
  552. uint8_t bit_s = (insn >> 20) & 1;
  553. const char *opname = opcode_names[opcode];
  554. return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d",
  555. opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs);
  556. }
  557. std::string ARM_Disasm::DisassembleMRS(uint32_t insn)
  558. {
  559. uint8_t cond = (insn >> 28) & 0xf;
  560. uint8_t rd = (insn >> 12) & 0xf;
  561. uint8_t ps = (insn >> 22) & 1;
  562. return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr");
  563. }
  564. std::string ARM_Disasm::DisassembleMSR(uint32_t insn)
  565. {
  566. char flags[8];
  567. int flag_index = 0;
  568. uint8_t cond = (insn >> 28) & 0xf;
  569. uint8_t is_immed = (insn >> 25) & 0x1;
  570. uint8_t pd = (insn >> 22) & 1;
  571. uint8_t mask = (insn >> 16) & 0xf;
  572. if (mask & 1)
  573. flags[flag_index++] = 'c';
  574. if (mask & 2)
  575. flags[flag_index++] = 'x';
  576. if (mask & 4)
  577. flags[flag_index++] = 's';
  578. if (mask & 8)
  579. flags[flag_index++] = 'f';
  580. flags[flag_index] = 0;
  581. if (is_immed) {
  582. uint32_t immed = insn & 0xff;
  583. uint8_t rotate = (insn >> 8) & 0xf;
  584. uint8_t rotate2 = rotate << 1;
  585. uint32_t rotated_val = (immed >> rotate2) | (immed << (32 - rotate2));
  586. return Common::StringFromFormat("msr%s\t%s_%s, #0x%x",
  587. cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rotated_val);
  588. }
  589. uint8_t rm = insn & 0xf;
  590. return Common::StringFromFormat("msr%s\t%s_%s, r%d",
  591. cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm);
  592. }
  593. std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, uint32_t insn)
  594. {
  595. uint32_t cond = BITS(insn, 28, 31);
  596. return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond));
  597. }
  598. std::string ARM_Disasm::DisassemblePLD(uint32_t insn)
  599. {
  600. uint8_t is_reg = (insn >> 25) & 0x1;
  601. uint8_t is_up = (insn >> 23) & 0x1;
  602. uint8_t rn = (insn >> 16) & 0xf;
  603. const char *minus = "";
  604. if (is_up == 0)
  605. minus = "-";
  606. if (is_reg) {
  607. uint8_t rm = insn & 0xf;
  608. return Common::StringFromFormat("pld\t[r%d, %sr%d]", rn, minus, rm);
  609. }
  610. uint16_t offset = insn & 0xfff;
  611. if (offset == 0) {
  612. return Common::StringFromFormat("pld\t[r%d]", rn);
  613. } else {
  614. return Common::StringFromFormat("pld\t[r%d, #%s%u]", rn, minus, offset);
  615. }
  616. }
  617. std::string ARM_Disasm::DisassembleSWI(uint32_t insn)
  618. {
  619. uint8_t cond = (insn >> 28) & 0xf;
  620. uint32_t sysnum = insn & 0x00ffffff;
  621. return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum);
  622. }
  623. std::string ARM_Disasm::DisassembleSWP(Opcode opcode, uint32_t insn)
  624. {
  625. uint8_t cond = (insn >> 28) & 0xf;
  626. uint8_t rn = (insn >> 16) & 0xf;
  627. uint8_t rd = (insn >> 12) & 0xf;
  628. uint8_t rm = insn & 0xf;
  629. const char *opname = opcode_names[opcode];
  630. return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn);
  631. }
  632. Opcode ARM_Disasm::Decode(uint32_t insn) {
  633. uint32_t bits27_26 = (insn >> 26) & 0x3;
  634. switch (bits27_26) {
  635. case 0x0:
  636. return Decode00(insn);
  637. case 0x1:
  638. return Decode01(insn);
  639. case 0x2:
  640. return Decode10(insn);
  641. case 0x3:
  642. return Decode11(insn);
  643. }
  644. return OP_INVALID;
  645. }
  646. Opcode ARM_Disasm::Decode00(uint32_t insn) {
  647. uint8_t bit25 = (insn >> 25) & 0x1;
  648. uint8_t bit4 = (insn >> 4) & 0x1;
  649. if (bit25 == 0 && bit4 == 1) {
  650. if ((insn & 0x0ffffff0) == 0x012fff10) {
  651. // Bx instruction
  652. return OP_BX;
  653. }
  654. if ((insn & 0x0ff000f0) == 0x01600010) {
  655. // Clz instruction
  656. return OP_CLZ;
  657. }
  658. if ((insn & 0xfff000f0) == 0xe1200070) {
  659. // Bkpt instruction
  660. return OP_BKPT;
  661. }
  662. uint32_t bits7_4 = (insn >> 4) & 0xf;
  663. if (bits7_4 == 0x9) {
  664. if ((insn & 0x0ff00ff0) == 0x01000090) {
  665. // Swp instruction
  666. uint8_t bit22 = (insn >> 22) & 0x1;
  667. if (bit22)
  668. return OP_SWPB;
  669. return OP_SWP;
  670. }
  671. // One of the multiply instructions
  672. return DecodeMUL(insn);
  673. }
  674. uint8_t bit7 = (insn >> 7) & 0x1;
  675. if (bit7 == 1) {
  676. // One of the load/store halfword/byte instructions
  677. return DecodeLDRH(insn);
  678. }
  679. }
  680. uint32_t op1 = BITS(insn, 20, 24);
  681. if (bit25 && (op1 == 0x12 || op1 == 0x16)) {
  682. // One of the MSR (immediate) and hints instructions
  683. return DecodeMSRImmAndHints(insn);
  684. }
  685. // One of the data processing instructions
  686. return DecodeALU(insn);
  687. }
  688. Opcode ARM_Disasm::Decode01(uint32_t insn) {
  689. uint8_t is_reg = (insn >> 25) & 0x1;
  690. uint8_t bit4 = (insn >> 4) & 0x1;
  691. if (is_reg == 1 && bit4 == 1)
  692. return OP_UNDEFINED;
  693. uint8_t is_load = (insn >> 20) & 0x1;
  694. uint8_t is_byte = (insn >> 22) & 0x1;
  695. if ((insn & 0xfd70f000) == 0xf550f000) {
  696. // Pre-load
  697. return OP_PLD;
  698. }
  699. if (is_load) {
  700. if (is_byte) {
  701. // Load byte
  702. return OP_LDRB;
  703. }
  704. // Load word
  705. return OP_LDR;
  706. }
  707. if (is_byte) {
  708. // Store byte
  709. return OP_STRB;
  710. }
  711. // Store word
  712. return OP_STR;
  713. }
  714. Opcode ARM_Disasm::Decode10(uint32_t insn) {
  715. uint8_t bit25 = (insn >> 25) & 0x1;
  716. if (bit25 == 0) {
  717. // LDM/STM
  718. uint8_t is_load = (insn >> 20) & 0x1;
  719. if (is_load)
  720. return OP_LDM;
  721. return OP_STM;
  722. }
  723. // Branch or Branch with link
  724. uint8_t is_link = (insn >> 24) & 1;
  725. uint32_t offset = insn & 0xffffff;
  726. // Sign-extend the 24-bit offset
  727. if ((offset >> 23) & 1)
  728. offset |= 0xff000000;
  729. // Pre-compute the left-shift and the prefetch offset
  730. offset <<= 2;
  731. offset += 8;
  732. if (is_link == 0)
  733. return OP_B;
  734. return OP_BL;
  735. }
  736. Opcode ARM_Disasm::Decode11(uint32_t insn) {
  737. uint8_t bit25 = (insn >> 25) & 0x1;
  738. if (bit25 == 0) {
  739. // LDC, SDC
  740. uint8_t is_load = (insn >> 20) & 0x1;
  741. if (is_load) {
  742. // LDC
  743. return OP_LDC;
  744. }
  745. // STC
  746. return OP_STC;
  747. }
  748. uint8_t bit24 = (insn >> 24) & 0x1;
  749. if (bit24 == 0x1) {
  750. // SWI
  751. return OP_SWI;
  752. }
  753. uint8_t bit4 = (insn >> 4) & 0x1;
  754. uint8_t cpnum = (insn >> 8) & 0xf;
  755. if (cpnum == 15) {
  756. // Special case for coprocessor 15
  757. uint8_t opcode = (insn >> 21) & 0x7;
  758. if (bit4 == 0 || opcode != 0) {
  759. // This is an unexpected bit pattern. Create an undefined
  760. // instruction in case this is ever executed.
  761. return OP_UNDEFINED;
  762. }
  763. // MRC, MCR
  764. uint8_t is_mrc = (insn >> 20) & 0x1;
  765. if (is_mrc)
  766. return OP_MRC;
  767. return OP_MCR;
  768. }
  769. if (bit4 == 0) {
  770. // CDP
  771. return OP_CDP;
  772. }
  773. // MRC, MCR
  774. uint8_t is_mrc = (insn >> 20) & 0x1;
  775. if (is_mrc)
  776. return OP_MRC;
  777. return OP_MCR;
  778. }
  779. Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
  780. uint8_t bit24 = (insn >> 24) & 0x1;
  781. if (bit24 != 0) {
  782. // This is an unexpected bit pattern. Create an undefined
  783. // instruction in case this is ever executed.
  784. return OP_UNDEFINED;
  785. }
  786. uint8_t bit23 = (insn >> 23) & 0x1;
  787. uint8_t bit22_U = (insn >> 22) & 0x1;
  788. uint8_t bit21_A = (insn >> 21) & 0x1;
  789. if (bit23 == 0) {
  790. // 32-bit multiply
  791. if (bit22_U != 0) {
  792. // This is an unexpected bit pattern. Create an undefined
  793. // instruction in case this is ever executed.
  794. return OP_UNDEFINED;
  795. }
  796. if (bit21_A == 0)
  797. return OP_MUL;
  798. return OP_MLA;
  799. }
  800. // 64-bit multiply
  801. if (bit22_U == 0) {
  802. // Unsigned multiply long
  803. if (bit21_A == 0)
  804. return OP_UMULL;
  805. return OP_UMLAL;
  806. }
  807. // Signed multiply long
  808. if (bit21_A == 0)
  809. return OP_SMULL;
  810. return OP_SMLAL;
  811. }
  812. Opcode ARM_Disasm::DecodeMSRImmAndHints(uint32_t insn) {
  813. uint32_t op = BIT(insn, 22);
  814. uint32_t op1 = BITS(insn, 16, 19);
  815. uint32_t op2 = BITS(insn, 0, 7);
  816. if (op == 0 && op1 == 0) {
  817. switch (op2) {
  818. case 0x0:
  819. return OP_NOP;
  820. case 0x1:
  821. return OP_YIELD;
  822. case 0x2:
  823. return OP_WFE;
  824. case 0x3:
  825. return OP_WFI;
  826. case 0x4:
  827. return OP_SEV;
  828. default:
  829. return OP_UNDEFINED;
  830. }
  831. }
  832. return OP_MSR;
  833. }
  834. Opcode ARM_Disasm::DecodeLDRH(uint32_t insn) {
  835. uint8_t is_load = (insn >> 20) & 0x1;
  836. uint8_t bits_65 = (insn >> 5) & 0x3;
  837. if (is_load) {
  838. if (bits_65 == 0x1) {
  839. // Load unsigned halfword
  840. return OP_LDRH;
  841. } else if (bits_65 == 0x2) {
  842. // Load signed byte
  843. return OP_LDRSB;
  844. }
  845. // Signed halfword
  846. if (bits_65 != 0x3) {
  847. // This is an unexpected bit pattern. Create an undefined
  848. // instruction in case this is ever executed.
  849. return OP_UNDEFINED;
  850. }
  851. // Load signed halfword
  852. return OP_LDRSH;
  853. }
  854. // Store halfword
  855. if (bits_65 != 0x1) {
  856. // This is an unexpected bit pattern. Create an undefined
  857. // instruction in case this is ever executed.
  858. return OP_UNDEFINED;
  859. }
  860. // Store halfword
  861. return OP_STRH;
  862. }
  863. Opcode ARM_Disasm::DecodeALU(uint32_t insn) {
  864. uint8_t is_immed = (insn >> 25) & 0x1;
  865. uint8_t opcode = (insn >> 21) & 0xf;
  866. uint8_t bit_s = (insn >> 20) & 1;
  867. uint8_t shift_is_reg = (insn >> 4) & 1;
  868. uint8_t bit7 = (insn >> 7) & 1;
  869. if (!is_immed && shift_is_reg && (bit7 != 0)) {
  870. // This is an unexpected bit pattern. Create an undefined
  871. // instruction in case this is ever executed.
  872. return OP_UNDEFINED;
  873. }
  874. switch (opcode) {
  875. case 0x0:
  876. return OP_AND;
  877. case 0x1:
  878. return OP_EOR;
  879. case 0x2:
  880. return OP_SUB;
  881. case 0x3:
  882. return OP_RSB;
  883. case 0x4:
  884. return OP_ADD;
  885. case 0x5:
  886. return OP_ADC;
  887. case 0x6:
  888. return OP_SBC;
  889. case 0x7:
  890. return OP_RSC;
  891. case 0x8:
  892. if (bit_s)
  893. return OP_TST;
  894. return OP_MRS;
  895. case 0x9:
  896. if (bit_s)
  897. return OP_TEQ;
  898. return OP_MSR;
  899. case 0xa:
  900. if (bit_s)
  901. return OP_CMP;
  902. return OP_MRS;
  903. case 0xb:
  904. if (bit_s)
  905. return OP_CMN;
  906. return OP_MSR;
  907. case 0xc:
  908. return OP_ORR;
  909. case 0xd:
  910. return OP_MOV;
  911. case 0xe:
  912. return OP_BIC;
  913. case 0xf:
  914. return OP_MVN;
  915. }
  916. // Unreachable
  917. return OP_INVALID;
  918. }