arm_dyncom_thumb.cpp 16 KB

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