You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

411 lines
12 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2009 by David Brownell *
  3. * *
  4. * This program is free software; you can redistribute it and/or modify *
  5. * it under the terms of the GNU General Public License as published by *
  6. * the Free Software Foundation; either version 2 of the License, or *
  7. * (at your option) any later version. *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "replacements.h"
  23. #include "armv7a.h"
  24. #include "arm_disassembler.h"
  25. #include "target.h"
  26. #include "register.h"
  27. #include "log.h"
  28. #include "binarybuffer.h"
  29. #include "command.h"
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. bitfield_desc_t armv7a_psr_bitfield_desc[] =
  34. {
  35. {"M[4:0]", 5},
  36. {"T", 1},
  37. {"F", 1},
  38. {"I", 1},
  39. {"A", 1},
  40. {"E", 1},
  41. {"IT[7:2]", 6},
  42. {"GE[3:0]", 4},
  43. {"reserved(DNM)", 4},
  44. {"J", 1},
  45. {"IT[0:1]", 2},
  46. {"Q", 1},
  47. {"V", 1},
  48. {"C", 1},
  49. {"Z", 1},
  50. {"N", 1},
  51. };
  52. char* armv7a_core_reg_list[] =
  53. {
  54. "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  55. "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
  56. "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
  57. "r13_irq", "lr_irq",
  58. "r13_svc", "lr_svc",
  59. "r13_abt", "lr_abt",
  60. "r13_und", "lr_und",
  61. "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
  62. "r13_mon", "lr_mon", "spsr_mon"
  63. };
  64. char * armv7a_mode_strings_list[] =
  65. {
  66. "Illegal mode value", "User", "FIQ", "IRQ",
  67. "Supervisor", "Abort", "Undefined", "System", "Monitor"
  68. };
  69. /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
  70. char** armv7a_mode_strings = armv7a_mode_strings_list+1;
  71. char* armv7a_state_strings[] =
  72. {
  73. "ARM", "Thumb", "Jazelle", "ThumbEE"
  74. };
  75. armv7a_core_reg_t armv7a_core_reg_list_arch_info[] =
  76. {
  77. {0, ARMV4_5_MODE_ANY, NULL, NULL},
  78. {1, ARMV4_5_MODE_ANY, NULL, NULL},
  79. {2, ARMV4_5_MODE_ANY, NULL, NULL},
  80. {3, ARMV4_5_MODE_ANY, NULL, NULL},
  81. {4, ARMV4_5_MODE_ANY, NULL, NULL},
  82. {5, ARMV4_5_MODE_ANY, NULL, NULL},
  83. {6, ARMV4_5_MODE_ANY, NULL, NULL},
  84. {7, ARMV4_5_MODE_ANY, NULL, NULL},
  85. {8, ARMV4_5_MODE_ANY, NULL, NULL},
  86. {9, ARMV4_5_MODE_ANY, NULL, NULL},
  87. {10, ARMV4_5_MODE_ANY, NULL, NULL},
  88. {11, ARMV4_5_MODE_ANY, NULL, NULL},
  89. {12, ARMV4_5_MODE_ANY, NULL, NULL},
  90. {13, ARMV4_5_MODE_USR, NULL, NULL},
  91. {14, ARMV4_5_MODE_USR, NULL, NULL},
  92. {15, ARMV4_5_MODE_ANY, NULL, NULL},
  93. {8, ARMV4_5_MODE_FIQ, NULL, NULL},
  94. {9, ARMV4_5_MODE_FIQ, NULL, NULL},
  95. {10, ARMV4_5_MODE_FIQ, NULL, NULL},
  96. {11, ARMV4_5_MODE_FIQ, NULL, NULL},
  97. {12, ARMV4_5_MODE_FIQ, NULL, NULL},
  98. {13, ARMV4_5_MODE_FIQ, NULL, NULL},
  99. {14, ARMV4_5_MODE_FIQ, NULL, NULL},
  100. {13, ARMV4_5_MODE_IRQ, NULL, NULL},
  101. {14, ARMV4_5_MODE_IRQ, NULL, NULL},
  102. {13, ARMV4_5_MODE_SVC, NULL, NULL},
  103. {14, ARMV4_5_MODE_SVC, NULL, NULL},
  104. {13, ARMV4_5_MODE_ABT, NULL, NULL},
  105. {14, ARMV4_5_MODE_ABT, NULL, NULL},
  106. {13, ARMV4_5_MODE_UND, NULL, NULL},
  107. {14, ARMV4_5_MODE_UND, NULL, NULL},
  108. {16, ARMV4_5_MODE_ANY, NULL, NULL},
  109. {16, ARMV4_5_MODE_FIQ, NULL, NULL},
  110. {16, ARMV4_5_MODE_IRQ, NULL, NULL},
  111. {16, ARMV4_5_MODE_SVC, NULL, NULL},
  112. {16, ARMV4_5_MODE_ABT, NULL, NULL},
  113. {16, ARMV4_5_MODE_UND, NULL, NULL},
  114. {13, ARMV7A_MODE_MON, NULL, NULL},
  115. {14, ARMV7A_MODE_MON, NULL, NULL},
  116. {16, ARMV7A_MODE_MON, NULL, NULL}
  117. };
  118. /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
  119. int armv7a_core_reg_map[8][17] =
  120. {
  121. { /* USR */
  122. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
  123. },
  124. { /* FIQ */
  125. 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
  126. },
  127. { /* IRQ */
  128. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
  129. },
  130. { /* SVC */
  131. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
  132. },
  133. { /* ABT */
  134. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
  135. },
  136. { /* UND */
  137. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
  138. },
  139. { /* SYS */
  140. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
  141. },
  142. { /* MON */
  143. /* TODO Fix the register mapping for mon, we need r13_mon,
  144. * r14_mon and spsr_mon
  145. */
  146. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
  147. }
  148. };
  149. uint8_t armv7a_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  150. reg_t armv7a_gdb_dummy_fp_reg =
  151. {
  152. "GDB dummy floating-point register", armv7a_gdb_dummy_fp_value,
  153. 0, 1, 96, NULL, 0, NULL, 0
  154. };
  155. void armv7a_show_fault_registers(target_t *target)
  156. {
  157. uint32_t dfsr, ifsr, dfar, ifar;
  158. /* get pointers to arch-specific information */
  159. armv4_5_common_t *armv4_5 = target->arch_info;
  160. armv7a_common_t *armv7a = armv4_5->arch_info;
  161. armv7a->read_cp15(target, 0, 0, 5, 0, &dfsr);
  162. armv7a->read_cp15(target, 0, 1, 5, 0, &ifsr);
  163. armv7a->read_cp15(target, 0, 0, 6, 0, &dfar);
  164. armv7a->read_cp15(target, 0, 2, 6, 0, &ifar);
  165. LOG_USER("Data fault registers DFSR: %8.8" PRIx32
  166. ", DFAR: %8.8" PRIx32, dfsr, dfar);
  167. LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
  168. ", IFAR: %8.8" PRIx32, ifsr, ifar);
  169. }
  170. int armv7a_arch_state(struct target_s *target)
  171. {
  172. static const char *state[] =
  173. {
  174. "disabled", "enabled"
  175. };
  176. armv4_5_common_t *armv4_5 = target->arch_info;
  177. armv7a_common_t *armv7a = armv4_5->arch_info;
  178. if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
  179. {
  180. LOG_ERROR("BUG: called for a non-ARMv4/5 target");
  181. exit(-1);
  182. }
  183. LOG_USER("target halted in %s state due to %s, current mode: %s\n"
  184. "%s: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
  185. "MMU: %s, D-Cache: %s, I-Cache: %s",
  186. armv7a_state_strings[armv7a->core_state],
  187. Jim_Nvp_value2name_simple(nvp_target_debug_reason,
  188. target->debug_reason)->name,
  189. armv7a_mode_strings[
  190. armv7a_mode_to_number(armv4_5->core_mode)],
  191. armv7a_core_reg_list[armv7a_core_reg_map[
  192. armv7a_mode_to_number(armv4_5->core_mode)][16]],
  193. buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
  194. armv4_5->core_mode, 16).value, 0, 32),
  195. buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
  196. state[armv7a->armv4_5_mmu.mmu_enabled],
  197. state[armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
  198. state[armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
  199. if (armv4_5->core_mode == ARMV7A_MODE_ABT)
  200. armv7a_show_fault_registers(target);
  201. return ERROR_OK;
  202. }
  203. static int handle_dap_baseaddr_command(struct command_context_s *cmd_ctx,
  204. char *cmd, char **args, int argc)
  205. {
  206. target_t *target = get_current_target(cmd_ctx);
  207. armv4_5_common_t *armv4_5 = target->arch_info;
  208. armv7a_common_t *armv7a = armv4_5->arch_info;
  209. swjdp_common_t *swjdp = &armv7a->swjdp_info;
  210. return dap_baseaddr_command(cmd_ctx, swjdp, args, argc);
  211. }
  212. static int handle_dap_memaccess_command(struct command_context_s *cmd_ctx,
  213. char *cmd, char **args, int argc)
  214. {
  215. target_t *target = get_current_target(cmd_ctx);
  216. armv4_5_common_t *armv4_5 = target->arch_info;
  217. armv7a_common_t *armv7a = armv4_5->arch_info;
  218. swjdp_common_t *swjdp = &armv7a->swjdp_info;
  219. return dap_memaccess_command(cmd_ctx, swjdp, args, argc);
  220. }
  221. static int handle_dap_apsel_command(struct command_context_s *cmd_ctx,
  222. char *cmd, char **args, int argc)
  223. {
  224. target_t *target = get_current_target(cmd_ctx);
  225. armv4_5_common_t *armv4_5 = target->arch_info;
  226. armv7a_common_t *armv7a = armv4_5->arch_info;
  227. swjdp_common_t *swjdp = &armv7a->swjdp_info;
  228. return dap_apsel_command(cmd_ctx, swjdp, args, argc);
  229. }
  230. static int handle_dap_apid_command(struct command_context_s *cmd_ctx,
  231. char *cmd, char **args, int argc)
  232. {
  233. target_t *target = get_current_target(cmd_ctx);
  234. armv4_5_common_t *armv4_5 = target->arch_info;
  235. armv7a_common_t *armv7a = armv4_5->arch_info;
  236. swjdp_common_t *swjdp = &armv7a->swjdp_info;
  237. return dap_apid_command(cmd_ctx, swjdp, args, argc);
  238. }
  239. static int handle_dap_info_command(struct command_context_s *cmd_ctx,
  240. char *cmd, char **args, int argc)
  241. {
  242. target_t *target = get_current_target(cmd_ctx);
  243. armv4_5_common_t *armv4_5 = target->arch_info;
  244. armv7a_common_t *armv7a = armv4_5->arch_info;
  245. swjdp_common_t *swjdp = &armv7a->swjdp_info;
  246. uint32_t apsel;
  247. apsel = swjdp->apsel;
  248. if (argc > 0)
  249. apsel = strtoul(args[0], NULL, 0);
  250. return dap_info_command(cmd_ctx, swjdp, apsel);
  251. }
  252. static int
  253. handle_armv7a_disassemble_command(struct command_context_s *cmd_ctx,
  254. char *cmd, char **args, int argc)
  255. {
  256. target_t *target = get_current_target(cmd_ctx);
  257. armv4_5_common_t *armv4_5 = target->arch_info;
  258. int thumb = 0;
  259. int count = 1;
  260. uint32_t address;
  261. int i;
  262. if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) {
  263. command_print(cmd_ctx, "current target isn't an ARM target");
  264. return ERROR_OK;
  265. }
  266. /* REVISIT: eventually support ThumbEE disassembly too;
  267. * some opcodes work differently.
  268. */
  269. switch (argc) {
  270. case 3:
  271. if (strcmp(args[2], "thumb") != 0)
  272. goto usage;
  273. thumb = 1;
  274. /* FALL THROUGH */
  275. case 2:
  276. count = strtoul(args[1], NULL, 0);
  277. /* FALL THROUGH */
  278. case 1:
  279. address = strtoul(args[0], NULL, 0);
  280. if (address & 0x01) {
  281. if (!thumb) {
  282. command_print(cmd_ctx, "Disassemble as Thumb");
  283. thumb = 1;
  284. }
  285. address &= ~1;
  286. }
  287. break;
  288. default:
  289. usage:
  290. command_print(cmd_ctx,
  291. "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
  292. return ERROR_OK;
  293. }
  294. for (i = 0; i < count; i++) {
  295. arm_instruction_t cur_instruction;
  296. int retval;
  297. if (thumb) {
  298. retval = thumb2_opcode(target, address, &cur_instruction);
  299. if (retval != ERROR_OK)
  300. return retval;
  301. address += cur_instruction.instruction_size;
  302. } else {
  303. uint32_t opcode;
  304. retval = target_read_u32(target, address, &opcode);
  305. if (retval != ERROR_OK)
  306. return retval;
  307. retval = arm_evaluate_opcode(opcode, address,
  308. &cur_instruction);
  309. if (retval != ERROR_OK)
  310. return retval;
  311. address += 4;
  312. }
  313. command_print(cmd_ctx, "%s", cur_instruction.text);
  314. }
  315. return ERROR_OK;
  316. }
  317. int armv7a_register_commands(struct command_context_s *cmd_ctx)
  318. {
  319. command_t *arm_adi_v5_dap_cmd;
  320. command_t *armv7a_cmd;
  321. arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
  322. NULL, COMMAND_ANY,
  323. "cortex dap specific commands");
  324. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
  325. handle_dap_info_command, COMMAND_EXEC,
  326. "dap info for ap [num], "
  327. "default currently selected AP");
  328. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
  329. handle_dap_apsel_command, COMMAND_EXEC,
  330. "select a different AP [num] (default 0)");
  331. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
  332. handle_dap_apid_command, COMMAND_EXEC,
  333. "return id reg from AP [num], "
  334. "default currently selected AP");
  335. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
  336. handle_dap_baseaddr_command, COMMAND_EXEC,
  337. "return debug base address from AP [num], "
  338. "default currently selected AP");
  339. register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
  340. handle_dap_memaccess_command, COMMAND_EXEC,
  341. "set/get number of extra tck for mem-ap memory "
  342. "bus access [0-255]");
  343. armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a",
  344. NULL, COMMAND_ANY,
  345. "ARMv7-A specific commands");
  346. register_command(cmd_ctx, armv7a_cmd, "disassemble",
  347. handle_armv7a_disassemble_command, COMMAND_EXEC,
  348. "disassemble instructions <address> [<count> ['thumb']]");
  349. return ERROR_OK;
  350. }