ptrace_h8300h.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. * linux/arch/h8300/platform/h8300h/ptrace_h8300h.c
  3. * ptrace cpu depend helper functions
  4. *
  5. * Yoshinori Sato <ysato@users.sourceforge.jp>
  6. *
  7. * This file is subject to the terms and conditions of the GNU General
  8. * Public License. See the file COPYING in the main directory of
  9. * this archive for more details.
  10. */
  11. #include <linux/linkage.h>
  12. #include <linux/sched.h>
  13. #include <asm/ptrace.h>
  14. #define CCR_MASK 0x6f /* mode/imask not set */
  15. #define BREAKINST 0x5730 /* trapa #3 */
  16. /* Mapping from PT_xxx to the stack offset at which the register is
  17. saved. Notice that usp has no stack-slot and needs to be treated
  18. specially (see get_reg/put_reg below). */
  19. static const int h8300_register_offset[] = {
  20. PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
  21. PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
  22. PT_REG(ccr), PT_REG(pc)
  23. };
  24. /* read register */
  25. long h8300_get_reg(struct task_struct *task, int regno)
  26. {
  27. switch (regno) {
  28. case PT_USP:
  29. return task->thread.usp + sizeof(long)*2;
  30. case PT_CCR:
  31. return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
  32. default:
  33. return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
  34. }
  35. }
  36. /* write register */
  37. int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
  38. {
  39. unsigned short oldccr;
  40. switch (regno) {
  41. case PT_USP:
  42. task->thread.usp = data - sizeof(long)*2;
  43. case PT_CCR:
  44. oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
  45. oldccr &= ~CCR_MASK;
  46. data &= CCR_MASK;
  47. data |= oldccr;
  48. *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
  49. break;
  50. default:
  51. *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
  52. break;
  53. }
  54. return 0;
  55. }
  56. /* disable singlestep */
  57. void user_disable_single_step(struct task_struct *child)
  58. {
  59. if((long)child->thread.breakinfo.addr != -1L) {
  60. *child->thread.breakinfo.addr = child->thread.breakinfo.inst;
  61. child->thread.breakinfo.addr = (unsigned short *)-1L;
  62. }
  63. }
  64. /* calculate next pc */
  65. enum jump_type {none, /* normal instruction */
  66. jabs, /* absolute address jump */
  67. ind, /* indirect address jump */
  68. ret, /* return to subrutine */
  69. reg, /* register indexed jump */
  70. relb, /* pc relative jump (byte offset) */
  71. relw, /* pc relative jump (word offset) */
  72. };
  73. /* opcode decode table define
  74. ptn: opcode pattern
  75. msk: opcode bitmask
  76. len: instruction length (<0 next table index)
  77. jmp: jump operation mode */
  78. struct optable {
  79. unsigned char bitpattern;
  80. unsigned char bitmask;
  81. signed char length;
  82. signed char type;
  83. } __attribute__((aligned(1),packed));
  84. #define OPTABLE(ptn,msk,len,jmp) \
  85. { \
  86. .bitpattern = ptn, \
  87. .bitmask = msk, \
  88. .length = len, \
  89. .type = jmp, \
  90. }
  91. static const struct optable optable_0[] = {
  92. OPTABLE(0x00,0xff, 1,none), /* 0x00 */
  93. OPTABLE(0x01,0xff,-1,none), /* 0x01 */
  94. OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */
  95. OPTABLE(0x04,0xee, 1,none), /* 0x04-0x05/0x14-0x15 */
  96. OPTABLE(0x06,0xfe, 1,none), /* 0x06-0x07 */
  97. OPTABLE(0x08,0xea, 1,none), /* 0x08-0x09/0x0c-0x0d/0x18-0x19/0x1c-0x1d */
  98. OPTABLE(0x0a,0xee, 1,none), /* 0x0a-0x0b/0x1a-0x1b */
  99. OPTABLE(0x0e,0xee, 1,none), /* 0x0e-0x0f/0x1e-0x1f */
  100. OPTABLE(0x10,0xfc, 1,none), /* 0x10-0x13 */
  101. OPTABLE(0x16,0xfe, 1,none), /* 0x16-0x17 */
  102. OPTABLE(0x20,0xe0, 1,none), /* 0x20-0x3f */
  103. OPTABLE(0x40,0xf0, 1,relb), /* 0x40-0x4f */
  104. OPTABLE(0x50,0xfc, 1,none), /* 0x50-0x53 */
  105. OPTABLE(0x54,0xfd, 1,ret ), /* 0x54/0x56 */
  106. OPTABLE(0x55,0xff, 1,relb), /* 0x55 */
  107. OPTABLE(0x57,0xff, 1,none), /* 0x57 */
  108. OPTABLE(0x58,0xfb, 2,relw), /* 0x58/0x5c */
  109. OPTABLE(0x59,0xfb, 1,reg ), /* 0x59/0x5b */
  110. OPTABLE(0x5a,0xfb, 2,jabs), /* 0x5a/0x5e */
  111. OPTABLE(0x5b,0xfb, 2,ind ), /* 0x5b/0x5f */
  112. OPTABLE(0x60,0xe8, 1,none), /* 0x60-0x67/0x70-0x77 */
  113. OPTABLE(0x68,0xfa, 1,none), /* 0x68-0x69/0x6c-0x6d */
  114. OPTABLE(0x6a,0xfe,-2,none), /* 0x6a-0x6b */
  115. OPTABLE(0x6e,0xfe, 2,none), /* 0x6e-0x6f */
  116. OPTABLE(0x78,0xff, 4,none), /* 0x78 */
  117. OPTABLE(0x79,0xff, 2,none), /* 0x79 */
  118. OPTABLE(0x7a,0xff, 3,none), /* 0x7a */
  119. OPTABLE(0x7b,0xff, 2,none), /* 0x7b */
  120. OPTABLE(0x7c,0xfc, 2,none), /* 0x7c-0x7f */
  121. OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */
  122. };
  123. static const struct optable optable_1[] = {
  124. OPTABLE(0x00,0xff,-3,none), /* 0x0100 */
  125. OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */
  126. OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */
  127. OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */
  128. };
  129. static const struct optable optable_2[] = {
  130. OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */
  131. OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */
  132. };
  133. static const struct optable optable_3[] = {
  134. OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */
  135. OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */
  136. OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */
  137. OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */
  138. };
  139. static const struct optable optable_4[] = {
  140. OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */
  141. OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */
  142. };
  143. static const struct optables_list {
  144. const struct optable *ptr;
  145. int size;
  146. } optables[] = {
  147. #define OPTABLES(no) \
  148. { \
  149. .ptr = optable_##no, \
  150. .size = sizeof(optable_##no) / sizeof(struct optable), \
  151. }
  152. OPTABLES(0),
  153. OPTABLES(1),
  154. OPTABLES(2),
  155. OPTABLES(3),
  156. OPTABLES(4),
  157. };
  158. const unsigned char condmask[] = {
  159. 0x00,0x40,0x01,0x04,0x02,0x08,0x10,0x20
  160. };
  161. static int isbranch(struct task_struct *task,int reson)
  162. {
  163. unsigned char cond = h8300_get_reg(task, PT_CCR);
  164. /* encode complex conditions */
  165. /* B4: N^V
  166. B5: Z|(N^V)
  167. B6: C|Z */
  168. __asm__("bld #3,%w0\n\t"
  169. "bxor #1,%w0\n\t"
  170. "bst #4,%w0\n\t"
  171. "bor #2,%w0\n\t"
  172. "bst #5,%w0\n\t"
  173. "bld #2,%w0\n\t"
  174. "bor #0,%w0\n\t"
  175. "bst #6,%w0\n\t"
  176. :"=&r"(cond)::"cc");
  177. cond &= condmask[reson >> 1];
  178. if (!(reson & 1))
  179. return cond == 0;
  180. else
  181. return cond != 0;
  182. }
  183. static unsigned short *getnextpc(struct task_struct *child, unsigned short *pc)
  184. {
  185. const struct optable *op;
  186. unsigned char *fetch_p;
  187. unsigned char inst;
  188. unsigned long addr;
  189. unsigned long *sp;
  190. int op_len,regno;
  191. op = optables[0].ptr;
  192. op_len = optables[0].size;
  193. fetch_p = (unsigned char *)pc;
  194. inst = *fetch_p++;
  195. do {
  196. if ((inst & op->bitmask) == op->bitpattern) {
  197. if (op->length < 0) {
  198. op = optables[-op->length].ptr;
  199. op_len = optables[-op->length].size + 1;
  200. inst = *fetch_p++;
  201. } else {
  202. switch (op->type) {
  203. case none:
  204. return pc + op->length;
  205. case jabs:
  206. addr = *(unsigned long *)pc;
  207. return (unsigned short *)(addr & 0x00ffffff);
  208. case ind:
  209. addr = *pc & 0xff;
  210. return (unsigned short *)(*(unsigned long *)addr);
  211. case ret:
  212. sp = (unsigned long *)h8300_get_reg(child, PT_USP);
  213. /* user stack frames
  214. | er0 | temporary saved
  215. +--------+
  216. | exp | exception stack frames
  217. +--------+
  218. | ret pc | userspace return address
  219. */
  220. return (unsigned short *)(*(sp+2) & 0x00ffffff);
  221. case reg:
  222. regno = (*pc >> 4) & 0x07;
  223. if (regno == 0)
  224. addr = h8300_get_reg(child, PT_ER0);
  225. else
  226. addr = h8300_get_reg(child, regno-1+PT_ER1);
  227. return (unsigned short *)addr;
  228. case relb:
  229. if (inst == 0x55 || isbranch(child,inst & 0x0f))
  230. pc = (unsigned short *)((unsigned long)pc +
  231. ((signed char)(*fetch_p)));
  232. return pc+1; /* skip myself */
  233. case relw:
  234. if (inst == 0x5c || isbranch(child,(*fetch_p & 0xf0) >> 4))
  235. pc = (unsigned short *)((unsigned long)pc +
  236. ((signed short)(*(pc+1))));
  237. return pc+2; /* skip myself */
  238. }
  239. }
  240. } else
  241. op++;
  242. } while(--op_len > 0);
  243. return NULL;
  244. }
  245. /* Set breakpoint(s) to simulate a single step from the current PC. */
  246. void user_enable_single_step(struct task_struct *child)
  247. {
  248. unsigned short *nextpc;
  249. nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC));
  250. child->thread.breakinfo.addr = nextpc;
  251. child->thread.breakinfo.inst = *nextpc;
  252. *nextpc = BREAKINST;
  253. }
  254. asmlinkage void trace_trap(unsigned long bp)
  255. {
  256. if ((unsigned long)current->thread.breakinfo.addr == bp) {
  257. user_disable_single_step(current);
  258. force_sig(SIGTRAP,current);
  259. } else
  260. force_sig(SIGILL,current);
  261. }