sa1110break.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "ureg.h"
  7. #include "../port/error.h"
  8. //
  9. // from trap.c
  10. //
  11. extern int (*breakhandler)(Ureg *ur, Proc*);
  12. extern Instr BREAK;
  13. extern void portbreakinit(void);
  14. //
  15. // Instructions that can have the PC as a destination register
  16. //
  17. enum {
  18. IADD = 1,
  19. IBRANCH,
  20. ILDM,
  21. ILDR,
  22. IMOV,
  23. //
  24. // These should eventually be implemented
  25. //
  26. IADC,
  27. IAND,
  28. IBIC,
  29. IEOR,
  30. ILDRT,
  31. IMRS,
  32. IMVN,
  33. IORR,
  34. IRSB,
  35. IRSC,
  36. ISBC,
  37. ISUB,
  38. };
  39. static int instrtype(Instr i);
  40. static ulong iadd(Ureg *ur, Instr i);
  41. static ulong ibranch(Ureg *ur, Instr i);
  42. static ulong ildm(Ureg *ur, Instr i);
  43. static ulong ildr(Ureg *ur, Instr i);
  44. static ulong imov(Ureg *ur, Instr i);
  45. static ulong shifterval(Ureg *ur, Instr i);
  46. static int condpass(Instr i, ulong psr);
  47. static ulong *address(Ureg *ur, Instr i);
  48. static ulong* multiaddr(Ureg *ur, Instr i);
  49. static int nbits(ulong v);
  50. #define COND_N(psr) (((psr) >> 31) & 1)
  51. #define COND_Z(psr) (((psr) >> 30) & 1)
  52. #define COND_C(psr) (((psr) >> 29) & 1)
  53. #define COND_V(psr) (((psr) >> 28) & 1)
  54. #define REG(i, a, b) (((i) & BITS((a), (b))) >> (a))
  55. #define REGVAL(ur, r) (*((ulong*)(ur) + (r)))
  56. #define LSR(v, s) ((ulong)(v) >> (s))
  57. #define ASR(v, s) ((long)(v) >> (s))
  58. #define ROR(v, s) (LSR((v), (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
  59. void
  60. machbreakinit(void)
  61. {
  62. portbreakinit();
  63. breakhandler = breakhit;
  64. }
  65. Instr
  66. machinstr(ulong addr)
  67. {
  68. if (addr < KTZERO)
  69. error(Ebadarg);
  70. return *(Instr*)addr;
  71. }
  72. void
  73. machbreakset(ulong addr)
  74. {
  75. if (addr < KTZERO)
  76. error(Ebadarg);
  77. *(Instr*)addr = BREAK;
  78. segflush((void*)addr, sizeof(Instr));
  79. }
  80. void
  81. machbreakclear(ulong addr, Instr i)
  82. {
  83. if (addr < KTZERO)
  84. error(Ebadarg);
  85. *(Instr*)addr = i;
  86. segflush((void*)addr, sizeof(Instr));
  87. }
  88. //
  89. // Return the address of the instruction that will be executed after the
  90. // instruction at address ur->pc.
  91. //
  92. // This means decoding the instruction at ur->pc.
  93. //
  94. // In the simple case, the PC will simply be the address of the next
  95. // sequential instruction following ur->pc.
  96. //
  97. // In the complex case, the instruction is a branch of some sort, so the
  98. // value of the PC after the instruction must be computed by decoding
  99. // and simulating the instruction enough to determine the PC.
  100. //
  101. ulong
  102. machnextaddr(Ureg *ur)
  103. {
  104. Instr i;
  105. i = machinstr(ur->pc);
  106. switch(instrtype(i)) {
  107. case IADD: return iadd(ur,i);
  108. case IBRANCH: return ibranch(ur,i);
  109. case ILDM: return ildm(ur,i);
  110. case ILDR: return ildr(ur,i);
  111. case IMOV: return imov(ur,i);
  112. case IADC:
  113. case IAND:
  114. case IBIC:
  115. case IEOR:
  116. case ILDRT:
  117. case IMRS:
  118. case IMVN:
  119. case IORR:
  120. case IRSB:
  121. case IRSC:
  122. case ISBC:
  123. case ISUB:
  124. // XXX - Tad: unimplemented
  125. //
  126. // any of these instructions could possibly have the
  127. // PC as Rd. Eventually, these should all be
  128. // checked just like the others.
  129. default:
  130. return ur->pc+4;
  131. }
  132. return 0;
  133. }
  134. static int
  135. instrtype(Instr i)
  136. {
  137. if(i & BITS(26,27) == 0) {
  138. switch((i >> 21) & 0xF) {
  139. case 0: return IAND;
  140. case 1: return IEOR;
  141. case 2: return ISUB;
  142. case 3: return IRSB;
  143. case 4: return IADD;
  144. case 5: return IADC;
  145. case 6: return ISBC;
  146. case 7: return IRSC;
  147. case 0xD: return IMOV;
  148. case 0xC: return IORR;
  149. case 0xE: return IBIC;
  150. case 0xF: return IMVN;
  151. }
  152. if(((i & BIT(25)|BITS(23,24)|BITS(20,21))) >> 20 == 0x10)
  153. return IMRS;
  154. return 0;
  155. }
  156. if(((i & BITS(27,25)|BIT(20)) >> 20) == 0x81) return ILDM;
  157. if(((i & BITS(26,27)|BIT(22)|BIT(20)) >> 20) == 0x41) return ILDR;
  158. if(((i & BITS(25,27)) >> 25) == 5) return IBRANCH;
  159. return 0;
  160. }
  161. static ulong
  162. iadd(Ureg *ur, Instr i)
  163. {
  164. ulong Rd = REG(i, 12, 15);
  165. ulong Rn = REG(i, 16, 19);
  166. if(Rd != 15 || !condpass(i, ur->psr))
  167. return ur->pc+4;
  168. return REGVAL(ur, Rn) + shifterval(ur, i);
  169. }
  170. static ulong
  171. ibranch(Ureg *ur, Instr i)
  172. {
  173. if(!condpass(i, ur->psr))
  174. return ur->pc+4;
  175. return ur->pc + ((signed long)(i << 8) >> 6) + 8;
  176. }
  177. static ulong
  178. ildm(Ureg *ur, Instr i)
  179. {
  180. if((i & BIT(15)) == 0)
  181. return ur->pc+4;
  182. return *(multiaddr(ur, i) + nbits(i & BITS(15, 0)));
  183. }
  184. static ulong
  185. ildr(Ureg *ur, Instr i)
  186. {
  187. if(REG(i, 12, 19) != 15 || !condpass(i, ur->psr))
  188. return ur->pc+4;
  189. return *address(ur, i);
  190. }
  191. static ulong
  192. imov(Ureg *ur, Instr i)
  193. {
  194. if(REG(i, 12, 15) != 15 || !condpass(i, ur->psr))
  195. return ur->pc+4;
  196. return shifterval(ur, i);
  197. }
  198. static int
  199. condpass(Instr i, ulong psr)
  200. {
  201. uchar n = COND_N(psr);
  202. uchar z = COND_Z(psr);
  203. uchar c = COND_C(psr);
  204. uchar v = COND_V(psr);
  205. switch(LSR(i,28)) {
  206. case 0: return z;
  207. case 1: return !z;
  208. case 2: return c;
  209. case 3: return !c;
  210. case 4: return n;
  211. case 5: return !n;
  212. case 6: return v;
  213. case 7: return !v;
  214. case 8: return c && !z;
  215. case 9: return !c || z;
  216. case 10: return n == v;
  217. case 11: return n != v;
  218. case 12: return !z && (n == v);
  219. case 13: return z && (n != v);
  220. case 14: return 1;
  221. case 15: return 0;
  222. }
  223. }
  224. static ulong
  225. shifterval(Ureg *ur, Instr i)
  226. {
  227. if(i & BIT(25)) { // IMMEDIATE
  228. ulong imm = i & BITS(0,7);
  229. ulong s = (i & BITS(8,11)) >> 7; // this contains the * 2
  230. return ROR(imm, s);
  231. } else {
  232. ulong Rm = REGVAL(ur, REG(i, 0, 3));
  233. ulong s = (i & BITS(7,11)) >> 7;
  234. switch((i & BITS(6,4)) >> 4) {
  235. case 0: // LSL
  236. return Rm << s;
  237. case 1: // LSLREG
  238. s = REGVAL(ur, s >> 1) & 0xFF;
  239. if(s >= 32) return 0;
  240. return Rm << s;
  241. case 2: // LSRIMM
  242. return LSR(Rm, s);
  243. case 3: // LSRREG
  244. s = REGVAL(ur, s >> 1) & 0xFF;
  245. if(s >= 32) return 0;
  246. return LSR(Rm, s);
  247. case 4: // ASRIMM
  248. if(s == 0) {
  249. if(Rm & BIT(31) == 0)
  250. return 0;
  251. return 0xFFFFFFFF;
  252. }
  253. return ASR(Rm, s);
  254. case 5: // ASRREG
  255. s = REGVAL(ur, s >> 1) & 0xFF;
  256. if(s >= 32) {
  257. if(Rm & BIT(31) == 0)
  258. return 0;
  259. return 0xFFFFFFFF;
  260. }
  261. return ASR(Rm, s);
  262. case 6: // RORIMM
  263. if(s == 0)
  264. return (COND_C(ur->psr) << 31) | LSR(Rm, 1);
  265. return ROR(Rm, s);
  266. case 7: // RORREG
  267. s = REGVAL(ur, s >> 1) & 0xFF;
  268. if(s == 0 || (s & 0xF) == 0)
  269. return Rm;
  270. return ROR(Rm, s & 0xF);
  271. }
  272. }
  273. }
  274. static ulong*
  275. address(Ureg *ur, Instr i)
  276. {
  277. ulong Rn = REGVAL(ur, REG(i, 16, 19));
  278. if(i & BIT(24) == 0) // POSTIDX
  279. return (ulong*)REGVAL(ur, Rn);
  280. if(i & BIT(25) == 0) { // OFFSET
  281. if(i & BIT(23))
  282. return (ulong*)(REGVAL(ur, Rn) + (i & BITS(0, 11)));
  283. return (ulong*)(REGVAL(ur, Rn) - (i & BITS(0, 11)));
  284. } else { // REGOFF
  285. ulong Rm = REGVAL(ur, REG(i, 0, 3));
  286. ulong index = 0;
  287. switch(i & BITS(5,6) >> 5) {
  288. case 0: index = Rm << ((i & BITS(7, 11)) >> 7); break;
  289. case 1: index = LSR(Rm, ((i & BITS(7, 11)) >> 7)); break;
  290. case 2: index = ASR(Rm, ((i & BITS(7, 11)) >> 7)); break;
  291. case 3:
  292. if(i & BITS(7, 11) == 0)
  293. index = (COND_C(ur->psr) << 31) | LSR(Rm, 1);
  294. else
  295. index = ROR(Rm, (i & BITS(7, 11)) >> 7);
  296. break;
  297. }
  298. if(i & BIT(23))
  299. return (ulong*)(Rn + index);
  300. return (ulong*)(Rn - index);
  301. }
  302. }
  303. static ulong*
  304. multiaddr(Ureg *ur, Instr i)
  305. {
  306. ulong Rn = REGVAL(ur, REG(i, 16, 19));
  307. switch((i >> 23) & 3) {
  308. case 0: return (ulong*)(Rn - (nbits(i & BITS(0,15))*4)+4);
  309. case 1: return (ulong*)Rn;
  310. case 2: return (ulong*)(Rn - (nbits(i & BITS(0,15))*4));
  311. case 3: return (ulong*)(Rn + 4);
  312. }
  313. }
  314. static int
  315. nbits(ulong v)
  316. {
  317. int n = 0;
  318. int i;
  319. for(i = 0; i < 32; i++) {
  320. if(v & 1)
  321. ++n;
  322. v = LSR(v, 1);
  323. }
  324. return n;
  325. }