three.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2002
  4. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  5. */
  6. #include <common.h>
  7. /*
  8. * CPU test
  9. * Ternary instructions instr rD,rA,rB
  10. *
  11. * Arithmetic instructions: add, addc, adde, subf, subfc, subfe,
  12. * mullw, mulhw, mulhwu, divw, divwu
  13. *
  14. * The test contains a pre-built table of instructions, operands and
  15. * expected results. For each table entry, the test will cyclically use
  16. * different sets of operand registers and result registers.
  17. */
  18. #include <post.h>
  19. #include "cpu_asm.h"
  20. #if CONFIG_POST & CONFIG_SYS_POST_CPU
  21. extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
  22. ulong op2);
  23. extern ulong cpu_post_makecr (long v);
  24. static struct cpu_post_three_s
  25. {
  26. ulong cmd;
  27. ulong op1;
  28. ulong op2;
  29. ulong res;
  30. } cpu_post_three_table[] =
  31. {
  32. {
  33. OP_ADD,
  34. 100,
  35. 200,
  36. 300
  37. },
  38. {
  39. OP_ADD,
  40. 100,
  41. -200,
  42. -100
  43. },
  44. {
  45. OP_ADDC,
  46. 100,
  47. 200,
  48. 300
  49. },
  50. {
  51. OP_ADDC,
  52. 100,
  53. -200,
  54. -100
  55. },
  56. {
  57. OP_ADDE,
  58. 100,
  59. 200,
  60. 300
  61. },
  62. {
  63. OP_ADDE,
  64. 100,
  65. -200,
  66. -100
  67. },
  68. {
  69. OP_SUBF,
  70. 100,
  71. 200,
  72. 100
  73. },
  74. {
  75. OP_SUBF,
  76. 300,
  77. 200,
  78. -100
  79. },
  80. {
  81. OP_SUBFC,
  82. 100,
  83. 200,
  84. 100
  85. },
  86. {
  87. OP_SUBFC,
  88. 300,
  89. 200,
  90. -100
  91. },
  92. {
  93. OP_SUBFE,
  94. 100,
  95. 200,
  96. 200 + ~100
  97. },
  98. {
  99. OP_SUBFE,
  100. 300,
  101. 200,
  102. 200 + ~300
  103. },
  104. {
  105. OP_MULLW,
  106. 200,
  107. 300,
  108. 200 * 300
  109. },
  110. {
  111. OP_MULHW,
  112. 0x10000000,
  113. 0x10000000,
  114. 0x1000000
  115. },
  116. {
  117. OP_MULHWU,
  118. 0x80000000,
  119. 0x80000000,
  120. 0x40000000
  121. },
  122. {
  123. OP_DIVW,
  124. -20,
  125. 5,
  126. -4
  127. },
  128. {
  129. OP_DIVWU,
  130. 0x8000,
  131. 0x200,
  132. 0x40
  133. },
  134. };
  135. static unsigned int cpu_post_three_size = ARRAY_SIZE(cpu_post_three_table);
  136. int cpu_post_test_three (void)
  137. {
  138. int ret = 0;
  139. unsigned int i, reg;
  140. int flag = disable_interrupts();
  141. for (i = 0; i < cpu_post_three_size && ret == 0; i++)
  142. {
  143. struct cpu_post_three_s *test = cpu_post_three_table + i;
  144. for (reg = 0; reg < 32 && ret == 0; reg++)
  145. {
  146. unsigned int reg0 = (reg + 0) % 32;
  147. unsigned int reg1 = (reg + 1) % 32;
  148. unsigned int reg2 = (reg + 2) % 32;
  149. unsigned int stk = reg < 16 ? 31 : 15;
  150. unsigned long code[] =
  151. {
  152. ASM_STW(stk, 1, -4),
  153. ASM_ADDI(stk, 1, -24),
  154. ASM_STW(3, stk, 12),
  155. ASM_STW(4, stk, 16),
  156. ASM_STW(reg0, stk, 8),
  157. ASM_STW(reg1, stk, 4),
  158. ASM_STW(reg2, stk, 0),
  159. ASM_LWZ(reg1, stk, 12),
  160. ASM_LWZ(reg0, stk, 16),
  161. ASM_12(test->cmd, reg2, reg1, reg0),
  162. ASM_STW(reg2, stk, 12),
  163. ASM_LWZ(reg2, stk, 0),
  164. ASM_LWZ(reg1, stk, 4),
  165. ASM_LWZ(reg0, stk, 8),
  166. ASM_LWZ(3, stk, 12),
  167. ASM_ADDI(1, stk, 24),
  168. ASM_LWZ(stk, 1, -4),
  169. ASM_BLR,
  170. };
  171. unsigned long codecr[] =
  172. {
  173. ASM_STW(stk, 1, -4),
  174. ASM_ADDI(stk, 1, -24),
  175. ASM_STW(3, stk, 12),
  176. ASM_STW(4, stk, 16),
  177. ASM_STW(reg0, stk, 8),
  178. ASM_STW(reg1, stk, 4),
  179. ASM_STW(reg2, stk, 0),
  180. ASM_LWZ(reg1, stk, 12),
  181. ASM_LWZ(reg0, stk, 16),
  182. ASM_12(test->cmd, reg2, reg1, reg0) | BIT_C,
  183. ASM_STW(reg2, stk, 12),
  184. ASM_LWZ(reg2, stk, 0),
  185. ASM_LWZ(reg1, stk, 4),
  186. ASM_LWZ(reg0, stk, 8),
  187. ASM_LWZ(3, stk, 12),
  188. ASM_ADDI(1, stk, 24),
  189. ASM_LWZ(stk, 1, -4),
  190. ASM_BLR,
  191. };
  192. ulong res;
  193. ulong cr;
  194. if (ret == 0)
  195. {
  196. cr = 0;
  197. cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
  198. ret = res == test->res && cr == 0 ? 0 : -1;
  199. if (ret != 0)
  200. {
  201. post_log ("Error at three test %d !\n", i);
  202. }
  203. }
  204. if (ret == 0)
  205. {
  206. cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
  207. ret = res == test->res &&
  208. (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
  209. if (ret != 0)
  210. {
  211. post_log ("Error at three test %d !\n", i);
  212. }
  213. }
  214. }
  215. }
  216. if (flag)
  217. enable_interrupts();
  218. return ret;
  219. }
  220. #endif