arm_disasm.cpp 25 KB

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