arm_dyncom_thumb.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Copyright 2012 Michael Kang, 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <cstddef>
  5. // We can provide simple Thumb simulation by decoding the Thumb instruction into its corresponding
  6. // ARM instruction, and using the existing ARM simulator.
  7. #include "core/arm/dyncom/arm_dyncom_thumb.h"
  8. #include "core/arm/skyeye_common/armsupp.h"
  9. // Decode a 16bit Thumb instruction. The instruction is in the low 16-bits of the tinstr field,
  10. // with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions
  11. // allows easier simulation of the special dual BL instruction.
  12. ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
  13. ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED;
  14. u32 tinstr = GetThumbInstruction(instr, addr);
  15. *ainstr = 0xDEADC0DE; // Debugging to catch non updates
  16. switch ((tinstr & 0xF800) >> 11) {
  17. case 0: // LSL
  18. case 1: // LSR
  19. case 2: // ASR
  20. *ainstr = 0xE1B00000 // base opcode
  21. | ((tinstr & 0x1800) >> (11 - 5)) // shift type
  22. | ((tinstr & 0x07C0) << (7 - 6)) // imm5
  23. | ((tinstr & 0x0038) >> 3) // Rs
  24. | ((tinstr & 0x0007) << 12); // Rd
  25. break;
  26. case 3: // ADD/SUB
  27. {
  28. static const u32 subset[4] = {
  29. 0xE0900000, // ADDS Rd,Rs,Rn
  30. 0xE0500000, // SUBS Rd,Rs,Rn
  31. 0xE2900000, // ADDS Rd,Rs,#imm3
  32. 0xE2500000 // SUBS Rd,Rs,#imm3
  33. };
  34. // It is quicker indexing into a table, than performing switch or conditionals:
  35. *ainstr = subset[(tinstr & 0x0600) >> 9] // base opcode
  36. | ((tinstr & 0x01C0) >> 6) // Rn or imm3
  37. | ((tinstr & 0x0038) << (16 - 3)) // Rs
  38. | ((tinstr & 0x0007) << (12 - 0)); // Rd
  39. } break;
  40. case 4: // MOV
  41. case 5: // CMP
  42. case 6: // ADD
  43. case 7: // SUB
  44. {
  45. static const u32 subset[4] = {
  46. 0xE3B00000, // MOVS Rd,#imm8
  47. 0xE3500000, // CMP Rd,#imm8
  48. 0xE2900000, // ADDS Rd,Rd,#imm8
  49. 0xE2500000, // SUBS Rd,Rd,#imm8
  50. };
  51. *ainstr = subset[(tinstr & 0x1800) >> 11] // base opcode
  52. | ((tinstr & 0x00FF) >> 0) // imm8
  53. | ((tinstr & 0x0700) << (16 - 8)) // Rn
  54. | ((tinstr & 0x0700) << (12 - 8)); // Rd
  55. } break;
  56. case 8: // Arithmetic and high register transfers
  57. // TODO: Since the subsets for both Format 4 and Format 5 instructions are made up of
  58. // different ARM encodings, we could save the following conditional, and just have one
  59. // large subset
  60. if ((tinstr & (1 << 10)) == 0) {
  61. enum otype { t_norm, t_shift, t_neg, t_mul };
  62. static const struct {
  63. u32 opcode;
  64. otype type;
  65. } subset[16] = {
  66. {0xE0100000, t_norm}, // ANDS Rd,Rd,Rs
  67. {0xE0300000, t_norm}, // EORS Rd,Rd,Rs
  68. {0xE1B00010, t_shift}, // MOVS Rd,Rd,LSL Rs
  69. {0xE1B00030, t_shift}, // MOVS Rd,Rd,LSR Rs
  70. {0xE1B00050, t_shift}, // MOVS Rd,Rd,ASR Rs
  71. {0xE0B00000, t_norm}, // ADCS Rd,Rd,Rs
  72. {0xE0D00000, t_norm}, // SBCS Rd,Rd,Rs
  73. {0xE1B00070, t_shift}, // MOVS Rd,Rd,ROR Rs
  74. {0xE1100000, t_norm}, // TST Rd,Rs
  75. {0xE2700000, t_neg}, // RSBS Rd,Rs,#0
  76. {0xE1500000, t_norm}, // CMP Rd,Rs
  77. {0xE1700000, t_norm}, // CMN Rd,Rs
  78. {0xE1900000, t_norm}, // ORRS Rd,Rd,Rs
  79. {0xE0100090, t_mul}, // MULS Rd,Rd,Rs
  80. {0xE1D00000, t_norm}, // BICS Rd,Rd,Rs
  81. {0xE1F00000, t_norm} // MVNS Rd,Rs
  82. };
  83. *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; // base
  84. switch (subset[(tinstr & 0x03C0) >> 6].type) {
  85. case t_norm:
  86. *ainstr |= ((tinstr & 0x0007) << 16) // Rn
  87. | ((tinstr & 0x0007) << 12) // Rd
  88. | ((tinstr & 0x0038) >> 3); // Rs
  89. break;
  90. case t_shift:
  91. *ainstr |= ((tinstr & 0x0007) << 12) // Rd
  92. | ((tinstr & 0x0007) >> 0) // Rm
  93. | ((tinstr & 0x0038) << (8 - 3)); // Rs
  94. break;
  95. case t_neg:
  96. *ainstr |= ((tinstr & 0x0007) << 12) // Rd
  97. | ((tinstr & 0x0038) << (16 - 3)); // Rn
  98. break;
  99. case t_mul:
  100. *ainstr |= ((tinstr & 0x0007) << 16) // Rd
  101. | ((tinstr & 0x0007) << 8) // Rs
  102. | ((tinstr & 0x0038) >> 3); // Rm
  103. break;
  104. }
  105. } else {
  106. u32 Rd = ((tinstr & 0x0007) >> 0);
  107. u32 Rs = ((tinstr & 0x0078) >> 3);
  108. if (tinstr & (1 << 7))
  109. Rd += 8;
  110. switch ((tinstr & 0x03C0) >> 6) {
  111. case 0x0: // ADD Rd,Rd,Rs
  112. case 0x1: // ADD Rd,Rd,Hs
  113. case 0x2: // ADD Hd,Hd,Rs
  114. case 0x3: // ADD Hd,Hd,Hs
  115. *ainstr = 0xE0800000 // base
  116. | (Rd << 16) // Rn
  117. | (Rd << 12) // Rd
  118. | (Rs << 0); // Rm
  119. break;
  120. case 0x4: // CMP Rd,Rs
  121. case 0x5: // CMP Rd,Hs
  122. case 0x6: // CMP Hd,Rs
  123. case 0x7: // CMP Hd,Hs
  124. *ainstr = 0xE1500000 // base
  125. | (Rd << 16) // Rn
  126. | (Rs << 0); // Rm
  127. break;
  128. case 0x8: // MOV Rd,Rs
  129. case 0x9: // MOV Rd,Hs
  130. case 0xA: // MOV Hd,Rs
  131. case 0xB: // MOV Hd,Hs
  132. *ainstr = 0xE1A00000 // base
  133. | (Rd << 12) // Rd
  134. | (Rs << 0); // Rm
  135. break;
  136. case 0xC: // BX Rs
  137. case 0xD: // BX Hs
  138. *ainstr = 0xE12FFF10 // base
  139. | ((tinstr & 0x0078) >> 3); // Rd
  140. break;
  141. case 0xE: // BLX
  142. case 0xF: // BLX
  143. *ainstr = 0xE1200030 // base
  144. | (Rs << 0); // Rm
  145. break;
  146. }
  147. }
  148. break;
  149. case 9: // LDR Rd,[PC,#imm8]
  150. *ainstr = 0xE59F0000 // base
  151. | ((tinstr & 0x0700) << (12 - 8)) // Rd
  152. | ((tinstr & 0x00FF) << (2 - 0)); // off8
  153. break;
  154. case 10:
  155. case 11: {
  156. static const u32 subset[8] = {
  157. 0xE7800000, // STR Rd,[Rb,Ro]
  158. 0xE18000B0, // STRH Rd,[Rb,Ro]
  159. 0xE7C00000, // STRB Rd,[Rb,Ro]
  160. 0xE19000D0, // LDRSB Rd,[Rb,Ro]
  161. 0xE7900000, // LDR Rd,[Rb,Ro]
  162. 0xE19000B0, // LDRH Rd,[Rb,Ro]
  163. 0xE7D00000, // LDRB Rd,[Rb,Ro]
  164. 0xE19000F0 // LDRSH Rd,[Rb,Ro]
  165. };
  166. *ainstr = subset[(tinstr & 0xE00) >> 9] // base
  167. | ((tinstr & 0x0007) << (12 - 0)) // Rd
  168. | ((tinstr & 0x0038) << (16 - 3)) // Rb
  169. | ((tinstr & 0x01C0) >> 6); // Ro
  170. } break;
  171. case 12: // STR Rd,[Rb,#imm5]
  172. case 13: // LDR Rd,[Rb,#imm5]
  173. case 14: // STRB Rd,[Rb,#imm5]
  174. case 15: // LDRB Rd,[Rb,#imm5]
  175. {
  176. static const u32 subset[4] = {
  177. 0xE5800000, // STR Rd,[Rb,#imm5]
  178. 0xE5900000, // LDR Rd,[Rb,#imm5]
  179. 0xE5C00000, // STRB Rd,[Rb,#imm5]
  180. 0xE5D00000 // LDRB Rd,[Rb,#imm5]
  181. };
  182. // The offset range defends on whether we are transferring a byte or word value:
  183. *ainstr = subset[(tinstr & 0x1800) >> 11] // base
  184. | ((tinstr & 0x0007) << (12 - 0)) // Rd
  185. | ((tinstr & 0x0038) << (16 - 3)) // Rb
  186. | ((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5
  187. } break;
  188. case 16: // STRH Rd,[Rb,#imm5]
  189. case 17: // LDRH Rd,[Rb,#imm5]
  190. *ainstr = ((tinstr & (1 << 11)) // base
  191. ? 0xE1D000B0 // LDRH
  192. : 0xE1C000B0) // STRH
  193. | ((tinstr & 0x0007) << (12 - 0)) // Rd
  194. | ((tinstr & 0x0038) << (16 - 3)) // Rb
  195. | ((tinstr & 0x01C0) >> (6 - 1)) // off5, low nibble
  196. | ((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble
  197. break;
  198. case 18: // STR Rd,[SP,#imm8]
  199. case 19: // LDR Rd,[SP,#imm8]
  200. *ainstr = ((tinstr & (1 << 11)) // base
  201. ? 0xE59D0000 // LDR
  202. : 0xE58D0000) // STR
  203. | ((tinstr & 0x0700) << (12 - 8)) // Rd
  204. | ((tinstr & 0x00FF) << 2); // off8
  205. break;
  206. case 20: // ADD Rd,PC,#imm8
  207. case 21: // ADD Rd,SP,#imm8
  208. if ((tinstr & (1 << 11)) == 0) {
  209. // NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the
  210. // rotate immediate field, so no shift of off8 is needed.
  211. *ainstr = 0xE28F0F00 // base
  212. | ((tinstr & 0x0700) << (12 - 8)) // Rd
  213. | (tinstr & 0x00FF); // off8
  214. } else {
  215. // We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is
  216. // needed.
  217. *ainstr = 0xE28D0F00 // base
  218. | ((tinstr & 0x0700) << (12 - 8)) // Rd
  219. | (tinstr & 0x00FF); // off8
  220. }
  221. break;
  222. case 22:
  223. case 23:
  224. if ((tinstr & 0x0F00) == 0x0000) {
  225. // NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30):
  226. *ainstr = ((tinstr & (1 << 7)) // base
  227. ? 0xE24DDF00 // SUB
  228. : 0xE28DDF00) // ADD
  229. | (tinstr & 0x007F); // off7
  230. } else if ((tinstr & 0x0F00) == 0x0e00) {
  231. // BKPT
  232. *ainstr = 0xEF000000 // base
  233. | BITS(tinstr, 0, 3) // imm4 field;
  234. | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12
  235. } else if ((tinstr & 0x0F00) == 0x0200) {
  236. static const u32 subset[4] = {
  237. 0xE6BF0070, // SXTH
  238. 0xE6AF0070, // SXTB
  239. 0xE6FF0070, // UXTH
  240. 0xE6EF0070, // UXTB
  241. };
  242. *ainstr = subset[BITS(tinstr, 6, 7)] // base
  243. | (BITS(tinstr, 0, 2) << 12) // Rd
  244. | BITS(tinstr, 3, 5); // Rm
  245. } else if ((tinstr & 0x0F00) == 0x600) {
  246. if (BIT(tinstr, 5) == 0) {
  247. // SETEND
  248. *ainstr = 0xF1010000 // base
  249. | (BIT(tinstr, 3) << 9); // endian specifier
  250. } else {
  251. // CPS
  252. *ainstr = 0xF1080000 // base
  253. | (BIT(tinstr, 0) << 6) // fiq bit
  254. | (BIT(tinstr, 1) << 7) // irq bit
  255. | (BIT(tinstr, 2) << 8) // abort bit
  256. | (BIT(tinstr, 4) << 18); // enable bit
  257. }
  258. } else if ((tinstr & 0x0F00) == 0x0a00) {
  259. static const u32 subset[4] = {
  260. 0xE6BF0F30, // REV
  261. 0xE6BF0FB0, // REV16
  262. 0, // undefined
  263. 0xE6FF0FB0, // REVSH
  264. };
  265. size_t subset_index = BITS(tinstr, 6, 7);
  266. if (subset_index == 2) {
  267. valid = ThumbDecodeStatus::UNDEFINED;
  268. } else {
  269. *ainstr = subset[subset_index] // base
  270. | (BITS(tinstr, 0, 2) << 12) // Rd
  271. | BITS(tinstr, 3, 5); // Rm
  272. }
  273. } else {
  274. static const u32 subset[4] = {
  275. 0xE92D0000, // STMDB sp!,{rlist}
  276. 0xE92D4000, // STMDB sp!,{rlist,lr}
  277. 0xE8BD0000, // LDMIA sp!,{rlist}
  278. 0xE8BD8000 // LDMIA sp!,{rlist,pc}
  279. };
  280. *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base
  281. | (tinstr & 0x00FF); // mask8
  282. }
  283. break;
  284. case 24: // STMIA
  285. case 25: // LDMIA
  286. if (tinstr & (1 << 11)) {
  287. unsigned int base = 0xE8900000;
  288. unsigned int rn = BITS(tinstr, 8, 10);
  289. // Writeback
  290. if ((tinstr & (1 << rn)) == 0)
  291. base |= (1 << 21);
  292. *ainstr = base // base (LDMIA)
  293. | (rn << 16) // Rn
  294. | (tinstr & 0x00FF); // Register list
  295. } else {
  296. *ainstr = 0xE8A00000 // base (STMIA)
  297. | (BITS(tinstr, 8, 10) << 16) // Rn
  298. | (tinstr & 0x00FF); // Register list
  299. }
  300. break;
  301. case 26: // Bcc
  302. case 27: // Bcc/SWI
  303. if ((tinstr & 0x0F00) == 0x0F00) {
  304. // Format 17 : SWI
  305. *ainstr = 0xEF000000;
  306. // Breakpoint must be handled specially.
  307. if ((tinstr & 0x00FF) == 0x18)
  308. *ainstr |= ((tinstr & 0x00FF) << 16);
  309. // New breakpoint value. See gdb/arm-tdep.c
  310. else if ((tinstr & 0x00FF) == 0xFE)
  311. *ainstr |= 0x180000; // base |= BKPT mask
  312. else
  313. *ainstr |= (tinstr & 0x00FF);
  314. } else if ((tinstr & 0x0F00) != 0x0E00)
  315. valid = ThumbDecodeStatus::BRANCH;
  316. else // UNDEFINED : cc=1110(AL) uses different format
  317. valid = ThumbDecodeStatus::UNDEFINED;
  318. break;
  319. case 28: // B
  320. valid = ThumbDecodeStatus::BRANCH;
  321. break;
  322. case 29:
  323. if (tinstr & 0x1)
  324. valid = ThumbDecodeStatus::UNDEFINED;
  325. else
  326. valid = ThumbDecodeStatus::BRANCH;
  327. break;
  328. case 30: // BL instruction 1
  329. // There is no single ARM instruction equivalent for this Thumb instruction. To keep the
  330. // simulation simple (from the user perspective) we check if the following instruction is
  331. // the second half of this BL, and if it is we simulate it immediately
  332. valid = ThumbDecodeStatus::BRANCH;
  333. break;
  334. case 31: // BL instruction 2
  335. // There is no single ARM instruction equivalent for this instruction. Also, it should only
  336. // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the
  337. // simulation of it on its own, with undefined results if r14 is not suitably initialised.
  338. valid = ThumbDecodeStatus::BRANCH;
  339. break;
  340. }
  341. *inst_size = 2;
  342. return valid;
  343. }