run.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. #include "arm.h"
  6. static int dummy;
  7. static char* shtype[4] =
  8. {
  9. "<<",
  10. ">>",
  11. "->",
  12. "@>",
  13. };
  14. static char* cond[16] =
  15. {
  16. ".EQ", ".NE", ".HS", ".LO",
  17. ".MI", ".PL", ".VS", ".VC",
  18. ".HI", ".LS", ".GE", ".LT",
  19. ".GT", ".LE", "", ".NO",
  20. };
  21. void Idp0(ulong);
  22. void Idp1(ulong);
  23. void Idp2(ulong);
  24. void Idp3(ulong);
  25. void Imul(ulong);
  26. void Imula(ulong);
  27. void Imull(ulong);
  28. void Iswap(ulong);
  29. void Imem1(ulong);
  30. void Imem2(ulong);
  31. void Ilsm(ulong inst);
  32. void Ib(ulong);
  33. void Ibl(ulong);
  34. void Ssyscall(ulong);
  35. Inst itab[] =
  36. {
  37. { Idp0, "AND", Iarith }, /* 00 - r,r,r */
  38. { Idp0, "EOR", Iarith }, /* 01 */
  39. { Idp0, "SUB", Iarith }, /* 02 */
  40. { Idp0, "RSB", Iarith }, /* 03 */
  41. { Idp0, "ADD", Iarith }, /* 04 */
  42. { Idp0, "ADC", Iarith }, /* 05 */
  43. { Idp0, "SBC", Iarith }, /* 06 */
  44. { Idp0, "RSC", Iarith }, /* 07 */
  45. { Idp0, "TST", Iarith }, /* 08 */
  46. { Idp0, "TEQ", Iarith }, /* 09 */
  47. { Idp0, "CMP", Iarith }, /* 10 */
  48. { Idp0, "CMN", Iarith }, /* 11 */
  49. { Idp0, "ORR", Iarith }, /* 12 */
  50. { Idp0, "MOV", Iarith }, /* 13 */
  51. { Idp0, "BIC", Iarith }, /* 14 */
  52. { Idp0, "MVN", Iarith }, /* 15 */
  53. { Idp1, "AND", Iarith }, /* 16 */
  54. { Idp1, "EOR", Iarith }, /* 17 */
  55. { Idp1, "SUB", Iarith }, /* 18 */
  56. { Idp1, "RSB", Iarith }, /* 19 */
  57. { Idp1, "ADD", Iarith }, /* 20 */
  58. { Idp1, "ADC", Iarith }, /* 21 */
  59. { Idp1, "SBC", Iarith }, /* 22 */
  60. { Idp1, "RSC", Iarith }, /* 23 */
  61. { Idp1, "TST", Iarith }, /* 24 */
  62. { Idp1, "TEQ", Iarith }, /* 25 */
  63. { Idp1, "CMP", Iarith }, /* 26 */
  64. { Idp1, "CMN", Iarith }, /* 27 */
  65. { Idp1, "ORR", Iarith }, /* 28 */
  66. { Idp1, "MOV", Iarith }, /* 29 */
  67. { Idp1, "BIC", Iarith }, /* 30 */
  68. { Idp1, "MVN", Iarith }, /* 31 */
  69. { Idp2, "AND", Iarith }, /* 32 */
  70. { Idp2, "EOR", Iarith }, /* 33 */
  71. { Idp2, "SUB", Iarith }, /* 34 */
  72. { Idp2, "RSB", Iarith }, /* 35 */
  73. { Idp2, "ADD", Iarith }, /* 36 */
  74. { Idp2, "ADC", Iarith }, /* 37 */
  75. { Idp2, "SBC", Iarith }, /* 38 */
  76. { Idp2, "RSC", Iarith }, /* 39 */
  77. { Idp2, "TST", Iarith }, /* 40 */
  78. { Idp2, "TEQ", Iarith }, /* 41 */
  79. { Idp2, "CMP", Iarith }, /* 42 */
  80. { Idp2, "CMN", Iarith }, /* 43 */
  81. { Idp2, "ORR", Iarith }, /* 44 */
  82. { Idp2, "MOV", Iarith }, /* 45 */
  83. { Idp2, "BIC", Iarith }, /* 46 */
  84. { Idp2, "MVN", Iarith }, /* 47 */
  85. { Idp3, "AND", Iarith }, /* 48 - i,r,r */
  86. { Idp3, "EOR", Iarith }, /* 49 */
  87. { Idp3, "SUB", Iarith }, /* 50 */
  88. { Idp3, "RSB", Iarith }, /* 51 */
  89. { Idp3, "ADD", Iarith }, /* 52 */
  90. { Idp3, "ADC", Iarith }, /* 53 */
  91. { Idp3, "SBC", Iarith }, /* 54 */
  92. { Idp3, "RSC", Iarith }, /* 55 */
  93. { Idp3, "TST", Iarith }, /* 56 */
  94. { Idp3, "TEQ", Iarith }, /* 57 */
  95. { Idp3, "CMP", Iarith }, /* 58 */
  96. { Idp3, "CMN", Iarith }, /* 59 */
  97. { Idp3, "ORR", Iarith }, /* 60 */
  98. { Idp3, "MOV", Iarith }, /* 61 */
  99. { Idp3, "BIC", Iarith }, /* 62 */
  100. { Idp3, "MVN", Iarith }, /* 63 */
  101. { Imul, "MUL", Iarith }, /* 64 */
  102. { Imula, "MULA", Iarith }, /* 65 */
  103. { Iswap, "SWPW", Imem }, /* 66 */
  104. { Iswap, "SWPBU", Imem }, /* 67 */
  105. { Imem2, "MOV", Imem }, /* 68 load/store h/sb */
  106. { Imem2, "MOV", Imem }, /* 69 */
  107. { Imem2, "MOV", Imem }, /* 70 */
  108. { Imem2, "MOV", Imem }, /* 71 */
  109. { Imem1, "MOVW", Imem }, /* 72 load/store w/ub i,r */
  110. { Imem1, "MOVB", Imem }, /* 73 */
  111. { Imem1, "MOVW", Imem }, /* 74 */
  112. { Imem1, "MOVB", Imem }, /* 75 */
  113. { Imem1, "MOVW", Imem }, /* 76 load/store r,r */
  114. { Imem1, "MOVB", Imem }, /* 77 */
  115. { Imem1, "MOVW", Imem }, /* 78 */
  116. { Imem1, "MOVB", Imem }, /* 79 */
  117. { Ilsm, "LDM", Imem }, /* 80 block move r,r */
  118. { Ilsm, "STM", Imem }, /* 81 */
  119. { Ib, "B", Ibranch }, /* 82 branch */
  120. { Ibl, "BL", Ibranch }, /* 83 */
  121. { Ssyscall, "SWI", Isyscall }, /* 84 co processor */
  122. { undef, "undef" }, /* 85 */
  123. { undef, "undef" }, /* 86 */
  124. { undef, "undef" }, /* 87 */
  125. { Imull, "MULLU", Iarith }, /* 88 */
  126. { Imull, "MULALU", Iarith }, /* 89 */
  127. { Imull, "MULL", Iarith }, /* 90 */
  128. { Imull, "MULAL", Iarith }, /* 91 */
  129. { undef, "undef" }, /* 92 */
  130. { 0 }
  131. };
  132. int
  133. runcmp(void)
  134. {
  135. switch(reg.cond) {
  136. case 0x0: /* eq */ return (reg.cc1 == reg.cc2);
  137. case 0x1: /* ne */ return (reg.cc1 != reg.cc2);
  138. case 0x2: /* hs */ return ((ulong)reg.cc1 >= (ulong)reg.cc2);
  139. case 0x3: /* lo */ return ((ulong)reg.cc1 < (ulong)reg.cc2);
  140. case 0x4: /* mi */ return (reg.cc1 - reg.cc2 < 0);
  141. case 0x5: /* pl */ return (reg.cc1 - reg.cc2 >= 0);
  142. case 0x8: /* hi */ return ((ulong)reg.cc1 > (ulong)reg.cc2);
  143. case 0x9: /* ls */ return ((ulong)reg.cc1 <= (ulong)reg.cc2);
  144. case 0xa: /* ge */ return (reg.cc1 >= reg.cc2);
  145. case 0xb: /* lt */ return (reg.cc1 < reg.cc2);
  146. case 0xc: /* gt */ return (reg.cc1 > reg.cc2);
  147. case 0xd: /* le */ return (reg.cc1 <= reg.cc2);
  148. case 0xe: /* al */ return 1;
  149. case 0xf: /* nv */ return 0;
  150. default:
  151. Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
  152. reg.cond, reg.cc1, reg.cc2);
  153. undef(reg.ir);
  154. return 0;
  155. }
  156. }
  157. int
  158. runteq(void)
  159. {
  160. long res = reg.cc1 ^ reg.cc2;
  161. switch(reg.cond) {
  162. case 0x0: /* eq */ return res == 0;
  163. case 0x1: /* ne */ return res != 0;
  164. case 0x4: /* mi */ return (res & SIGNBIT) != 0;
  165. case 0x5: /* pl */ return (res & SIGNBIT) == 0;
  166. case 0xe: /* al */ return 1;
  167. case 0xf: /* nv */ return 0;
  168. default:
  169. Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
  170. reg.cond, reg.cc1, reg.cc2);
  171. undef(reg.ir);
  172. return 0;
  173. }
  174. }
  175. int
  176. runtst(void)
  177. {
  178. long res = reg.cc1 & reg.cc2;
  179. switch(reg.cond) {
  180. case 0x0: /* eq */ return res == 0;
  181. case 0x1: /* ne */ return res != 0;
  182. case 0x4: /* mi */ return (res & SIGNBIT) != 0;
  183. case 0x5: /* pl */ return (res & SIGNBIT) == 0;
  184. case 0xe: /* al */ return 1;
  185. case 0xf: /* nv */ return 0;
  186. default:
  187. Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
  188. reg.cond, reg.cc1, reg.cc2);
  189. undef(reg.ir);
  190. return 0;
  191. }
  192. }
  193. void
  194. run(void)
  195. {
  196. int execute;
  197. do {
  198. if(trace)
  199. Bflush(bioout);
  200. reg.ar = reg.r[REGPC];
  201. reg.ir = ifetch(reg.ar);
  202. reg.class = armclass(reg.ir);
  203. reg.ip = &itab[reg.class];
  204. reg.cond = (reg.ir>>28) & 0xf;
  205. switch(reg.compare_op) {
  206. case CCcmp:
  207. execute = runcmp();
  208. break;
  209. case CCteq:
  210. execute = runteq();
  211. break;
  212. case CCtst:
  213. execute = runtst();
  214. break;
  215. default:
  216. Bprint(bioout, "unimplemented compare operation %x\n",
  217. reg.compare_op);
  218. return;
  219. }
  220. if(execute) {
  221. reg.ip->count++;
  222. (*reg.ip->func)(reg.ir);
  223. } else {
  224. if(trace)
  225. itrace("%s%s IGNORED",
  226. reg.ip->name, cond[reg.cond]);
  227. }
  228. reg.r[REGPC] += 4;
  229. if(bplist)
  230. brkchk(reg.r[REGPC], Instruction);
  231. } while(--count);
  232. }
  233. void
  234. undef(ulong inst)
  235. {
  236. Bprint(bioout, "undefined instruction trap pc #%lux inst %.8lux class %d\n",
  237. reg.r[REGPC], inst, reg.class);
  238. longjmp(errjmp, 0);
  239. }
  240. long
  241. shift(long v, int st, int sc, int isreg)
  242. {
  243. if(sc == 0) {
  244. switch(st) {
  245. case 0: /* logical left */
  246. reg.cout = reg.cbit;
  247. break;
  248. case 1: /* logical right */
  249. reg.cout = (v >> 31) & 1;
  250. break;
  251. case 2: /* arith right */
  252. reg.cout = reg.cbit;
  253. break;
  254. case 3: /* rotate right */
  255. if(isreg) {
  256. reg.cout = reg.cbit;
  257. }
  258. else {
  259. reg.cout = v & 1;
  260. v = ((ulong)v >> 1) | (reg.cbit << 31);
  261. }
  262. }
  263. }
  264. else {
  265. switch(st) {
  266. case 0: /* logical left */
  267. reg.cout = (v >> (32 - sc)) & 1;
  268. v = v << sc;
  269. break;
  270. case 1: /* logical right */
  271. reg.cout = (v >> (sc - 1)) & 1;
  272. v = (ulong)v >> sc;
  273. break;
  274. case 2: /* arith right */
  275. if(sc >= 32) {
  276. reg.cout = (v >> 31) & 1;
  277. if(reg.cout)
  278. v = 0xFFFFFFFF;
  279. else
  280. v = 0;
  281. }
  282. else {
  283. reg.cout = (v >> (sc - 1)) & 1;
  284. v = (long)v >> sc;
  285. }
  286. break;
  287. case 3: /* rotate right */
  288. reg.cout = (v >> (sc - 1)) & 1;
  289. v = (v << (32-sc)) | ((ulong)v >> sc);
  290. break;
  291. }
  292. }
  293. return v;
  294. }
  295. void
  296. dpex(long inst, long o1, long o2, int rd)
  297. {
  298. int cbit;
  299. cbit = 0;
  300. switch((inst>>21) & 0xf) {
  301. case 0: /* and */
  302. reg.r[rd] = o1 & o2;
  303. cbit = 1;
  304. break;
  305. case 1: /* eor */
  306. reg.r[rd] = o1 ^ o2;
  307. cbit = 1;
  308. break;
  309. case 2: /* sub */
  310. reg.r[rd] = o1 - o2;
  311. case 10: /* cmp */
  312. if(inst & Sbit) {
  313. reg.cc1 = o1;
  314. reg.cc2 = o2;
  315. reg.compare_op = CCcmp;
  316. }
  317. return;
  318. case 3: /* rsb */
  319. reg.r[rd] = o2 - o1;
  320. if(inst & Sbit) {
  321. reg.cc1 = o2;
  322. reg.cc2 = o1;
  323. reg.compare_op = CCcmp;
  324. }
  325. return;
  326. case 4: /* add */
  327. if(calltree && rd == REGPC && o2 == 0) {
  328. Symbol s;
  329. findsym(o1 + o2, CTEXT, &s);
  330. Bprint(bioout, "%8lux return to %lux %s r0=%lux\n",
  331. reg.r[REGPC], o1 + o2, s.name, reg.r[REGRET]);
  332. }
  333. reg.r[rd] = o1 + o2;
  334. if(inst & Sbit) {
  335. if(((uvlong)(ulong)o1 + (uvlong)(ulong)o2) & (1LL << 32))
  336. reg.cbit = 1;
  337. else
  338. reg.cbit = 0;
  339. reg.cc1 = o2;
  340. reg.cc2 = -o1;
  341. reg.compare_op = CCcmp;
  342. }
  343. return;
  344. case 5: /* adc */
  345. case 6: /* sbc */
  346. case 7: /* rsc */
  347. undef(inst);
  348. case 8: /* tst */
  349. if(inst & Sbit) {
  350. reg.cc1 = o1;
  351. reg.cc2 = o2;
  352. reg.compare_op = CCtst;
  353. }
  354. return;
  355. case 9: /* teq */
  356. if(inst & Sbit) {
  357. reg.cc1 = o1;
  358. reg.cc2 = o2;
  359. reg.compare_op = CCteq;
  360. }
  361. return;
  362. case 11: /* cmn */
  363. if(inst & Sbit) {
  364. reg.cc1 = o1;
  365. reg.cc2 = -o2;
  366. reg.compare_op = CCcmp;
  367. }
  368. return;
  369. case 12: /* orr */
  370. reg.r[rd] = o1 | o2;
  371. cbit = 1;
  372. break;
  373. case 13: /* mov */
  374. reg.r[rd] = o2;
  375. cbit = 1;
  376. break;
  377. case 14: /* bic */
  378. reg.r[rd] = o1 & ~o2;
  379. cbit = 1;
  380. break;
  381. case 15: /* mvn */
  382. reg.r[rd] = ~o2;
  383. cbit = 1;
  384. break;
  385. }
  386. if(inst & Sbit) {
  387. if(cbit)
  388. reg.cbit = reg.cout;
  389. reg.cc1 = reg.r[rd];
  390. reg.cc2 = 0;
  391. reg.compare_op = CCcmp;
  392. }
  393. }
  394. /*
  395. * data processing instruction R,R,R
  396. */
  397. void
  398. Idp0(ulong inst)
  399. {
  400. int rn, rd, rm;
  401. long o1, o2;
  402. rn = (inst>>16) & 0xf;
  403. rd = (inst>>12) & 0xf;
  404. rm = inst & 0xf;
  405. o1 = reg.r[rn];
  406. if(rn == REGPC)
  407. o1 += 8;
  408. o2 = reg.r[rm];
  409. if(rm == REGPC)
  410. o2 += 8;
  411. dpex(inst, o1, o2, rd);
  412. if(trace)
  413. itrace("%s%s\tR%d,R%d,R%d =#%x",
  414. reg.ip->name, cond[reg.cond],
  415. rm, rn, rd,
  416. reg.r[rd]);
  417. if(rd == REGPC)
  418. reg.r[rd] -= 4;
  419. }
  420. /*
  421. * data processing instruction (R<>#),R,R
  422. */
  423. void
  424. Idp1(ulong inst)
  425. {
  426. int rn, rd, rm, st, sc;
  427. long o1, o2;
  428. rn = (inst>>16) & 0xf;
  429. rd = (inst>>12) & 0xf;
  430. rm = inst & 0xf;
  431. st = (inst>>5) & 0x3;
  432. sc = (inst>>7) & 0x1f;
  433. o1 = reg.r[rn];
  434. if(rn == REGPC)
  435. o1 += 8;
  436. o2 = reg.r[rm];
  437. if(rm == REGPC)
  438. o2 += 8;
  439. o2 = shift(o2, st, sc, 0);
  440. dpex(inst, o1, o2, rd);
  441. if(trace)
  442. itrace("%s%s\tR%d%s%d,R%d,R%d =#%x",
  443. reg.ip->name, cond[reg.cond], rm, shtype[st], sc, rn, rd,
  444. reg.r[rd]);
  445. if(rd == REGPC)
  446. reg.r[rd] -= 4;
  447. }
  448. /*
  449. * data processing instruction (R<>R),R,R
  450. */
  451. void
  452. Idp2(ulong inst)
  453. {
  454. int rn, rd, rm, rs, st;
  455. long o1, o2, o3;
  456. rn = (inst>>16) & 0xf;
  457. rd = (inst>>12) & 0xf;
  458. rm = inst & 0xf;
  459. st = (inst>>5) & 0x3;
  460. rs = (inst>>8) & 0xf;
  461. o1 = reg.r[rn];
  462. if(rn == REGPC)
  463. o1 += 8;
  464. o2 = reg.r[rm];
  465. if(rm == REGPC)
  466. o2 += 8;
  467. o3 = reg.r[rs];
  468. if(rs == REGPC)
  469. o3 += 8;
  470. o2 = shift(o2, st, o3, 1);
  471. dpex(inst, o1, o2, rd);
  472. if(trace)
  473. itrace("%s%s\tR%d%sR%d=%d,R%d,R%d =#%x",
  474. reg.ip->name, cond[reg.cond], rm, shtype[st], rs, o3, rn, rd,
  475. reg.r[rd]);
  476. if(rd == REGPC)
  477. reg.r[rd] -= 4;
  478. }
  479. /*
  480. * data processing instruction #<>#,R,R
  481. */
  482. void
  483. Idp3(ulong inst)
  484. {
  485. int rn, rd, sc;
  486. long o1, o2;
  487. rn = (inst>>16) & 0xf;
  488. rd = (inst>>12) & 0xf;
  489. o1 = reg.r[rn];
  490. if(rn == REGPC)
  491. o1 += 8;
  492. o2 = inst & 0xff;
  493. sc = (inst>>7) & 0x1e;
  494. o2 = (o2 >> sc) | (o2 << (32 - sc));
  495. dpex(inst, o1, o2, rd);
  496. if(trace)
  497. itrace("%s%s\t#%x,R%d,R%d =#%x",
  498. reg.ip->name, cond[reg.cond], o2, rn, rd,
  499. reg.r[rd]);
  500. if(rd == REGPC)
  501. reg.r[rd] -= 4;
  502. }
  503. void
  504. Imul(ulong inst)
  505. {
  506. int rs, rd, rm;
  507. rd = (inst>>16) & 0xf;
  508. rs = (inst>>8) & 0xf;
  509. rm = inst & 0xf;
  510. if(rd == REGPC || rs == REGPC || rm == REGPC || rd == rm)
  511. undef(inst);
  512. reg.r[rd] = reg.r[rm]*reg.r[rs];
  513. if(trace)
  514. itrace("%s%s\tR%d,R%d,R%d =#%x",
  515. reg.ip->name, cond[reg.cond], rs, rm, rd,
  516. reg.r[rd]);
  517. }
  518. void
  519. Imull(ulong inst)
  520. {
  521. vlong v;
  522. int rs, rd, rm, rn;
  523. rd = (inst>>16) & 0xf;
  524. rn = (inst>>12) & 0xf;
  525. rs = (inst>>8) & 0xf;
  526. rm = inst & 0xf;
  527. if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC
  528. || rd == rm || rn == rm || rd == rn)
  529. undef(inst);
  530. if(inst & (1<<22)){
  531. v = (vlong)reg.r[rm] * (vlong)reg.r[rs];
  532. if(inst & (1 << 21))
  533. v += reg.r[rn];
  534. }else{
  535. v = (uvlong)(ulong)reg.r[rm] * (uvlong)(ulong)reg.r[rs];
  536. if(inst & (1 << 21))
  537. v += (ulong)reg.r[rn];
  538. }
  539. reg.r[rd] = v >> 32;
  540. reg.r[rn] = v;
  541. if(trace)
  542. itrace("%s%s\tR%d,R%d,(R%d,R%d) =#%llx",
  543. reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
  544. v);
  545. }
  546. void
  547. Imula(ulong inst)
  548. {
  549. int rs, rd, rm, rn;
  550. rd = (inst>>16) & 0xf;
  551. rn = (inst>>12) & 0xf;
  552. rs = (inst>>8) & 0xf;
  553. rm = inst & 0xf;
  554. if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC || rd == rm)
  555. undef(inst);
  556. reg.r[rd] = reg.r[rm]*reg.r[rs] + reg.r[rn];
  557. if(trace)
  558. itrace("%s%s\tR%d,R%d,R%d,R%d =#%x",
  559. reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
  560. reg.r[rd]);
  561. }
  562. void
  563. Iswap(ulong inst)
  564. {
  565. int rn, rd, rm;
  566. ulong address, value, bbit;
  567. bbit = inst & (1<<22);
  568. rn = (inst>>16) & 0xf;
  569. rd = (inst>>12) & 0xf;
  570. rm = (inst>>0) & 0xf;
  571. address = reg.r[rn];
  572. if(bbit) {
  573. value = getmem_b(address);
  574. putmem_b(address, reg.r[rm]);
  575. } else {
  576. value = getmem_w(address);
  577. putmem_w(address, reg.r[rm]);
  578. }
  579. reg.r[rd] = value;
  580. if(trace) {
  581. char *bw, *dotc;
  582. bw = "";
  583. if(bbit)
  584. bw = "B";
  585. dotc = cond[reg.cond];
  586. itrace("SWP%s%s\t#%x(R%d),R%d #%lux=#%x",
  587. bw, dotc,
  588. rn, rd,
  589. address, value);
  590. }
  591. }
  592. /*
  593. * load/store word/byte
  594. */
  595. void
  596. Imem1(ulong inst)
  597. {
  598. int rn, rd, off, rm, sc, st;
  599. ulong address, value, pbit, ubit, bbit, wbit, lbit, bit25;
  600. bit25 = inst & (1<<25);
  601. pbit = inst & (1<<24);
  602. ubit = inst & (1<<23);
  603. bbit = inst & (1<<22);
  604. wbit = inst & (1<<21);
  605. lbit = inst & (1<<20);
  606. rn = (inst>>16) & 0xf;
  607. rd = (inst>>12) & 0xf;
  608. SET(st);
  609. SET(sc);
  610. SET(rm);
  611. if(bit25) {
  612. rm = inst & 0xf;
  613. st = (inst>>5) & 0x3;
  614. sc = (inst>>7) & 0x1f;
  615. off = reg.r[rm];
  616. if(rm == REGPC)
  617. off += 8;
  618. off = shift(off, st, sc, 0);
  619. } else {
  620. off = inst & 0xfff;
  621. }
  622. if(!ubit)
  623. off = -off;
  624. if(rn == REGPC)
  625. off += 8;
  626. address = reg.r[rn];
  627. if(pbit)
  628. address += off;
  629. if(lbit) {
  630. if(bbit)
  631. value = getmem_b(address);
  632. else
  633. value = getmem_w(address);
  634. if(rd == REGPC)
  635. value -= 4;
  636. reg.r[rd] = value;
  637. } else {
  638. value = reg.r[rd];
  639. if(rd == REGPC)
  640. value -= 4;
  641. if(bbit)
  642. putmem_b(address, value);
  643. else
  644. putmem_w(address, value);
  645. }
  646. if(!(pbit && !wbit))
  647. reg.r[rn] += off;
  648. if(trace) {
  649. char *bw, *dotp, *dotc;
  650. bw = "W";
  651. if(bbit)
  652. bw = "BU";
  653. dotp = "";
  654. if(!pbit)
  655. dotp = ".P";
  656. dotc = cond[reg.cond];
  657. if(lbit) {
  658. if(!bit25)
  659. itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
  660. bw, dotp, dotc,
  661. off, rn, rd,
  662. address, value);
  663. else
  664. itrace("MOV%s%s%s\t(R%d%s%d)(R%d),R%d #%lux=#%x",
  665. bw, dotp, dotc,
  666. rm, shtype[st], sc, rn, rd,
  667. address, value);
  668. } else {
  669. if(!bit25)
  670. itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
  671. bw, dotp, dotc,
  672. rd, off, rn,
  673. address, value);
  674. else
  675. itrace("MOV%s%s%s\tR%d,(R%d%s%d)(R%d) #%lux=#%x",
  676. bw, dotp, dotc,
  677. rd, rm, shtype[st], sc, rn,
  678. address, value);
  679. }
  680. }
  681. }
  682. /*
  683. * load/store unsigned byte/half word
  684. */
  685. void
  686. Imem2(ulong inst)
  687. {
  688. int rn, rd, off, rm;
  689. ulong address, value, pbit, ubit, hbit, sbit, wbit, lbit, bit22;
  690. pbit = inst & (1<<24);
  691. ubit = inst & (1<<23);
  692. bit22 = inst & (1<<22);
  693. wbit = inst & (1<<21);
  694. lbit = inst & (1<<20);
  695. sbit = inst & (1<<6);
  696. hbit = inst & (1<<5);
  697. rn = (inst>>16) & 0xf;
  698. rd = (inst>>12) & 0xf;
  699. SET(rm);
  700. if(bit22) {
  701. off = ((inst>>4) & 0xf0) | (inst & 0xf);
  702. } else {
  703. rm = inst & 0xf;
  704. off = reg.r[rm];
  705. if(rm == REGPC)
  706. off += 8;
  707. }
  708. if(!ubit)
  709. off = -off;
  710. if(rn == REGPC)
  711. off += 8;
  712. address = reg.r[rn];
  713. if(pbit)
  714. address += off;
  715. if(lbit) {
  716. if(hbit) {
  717. value = getmem_h(address);
  718. if(sbit && (value & 0x8000))
  719. value |= 0xffff0000;
  720. } else {
  721. value = getmem_b(address);
  722. if(value & 0x80)
  723. value |= 0xffffff00;
  724. }
  725. if(rd == REGPC)
  726. value -= 4;
  727. reg.r[rd] = value;
  728. } else {
  729. value = reg.r[rd];
  730. if(rd == REGPC)
  731. value -= 4;
  732. if(hbit) {
  733. putmem_h(address, value);
  734. } else {
  735. putmem_b(address, value);
  736. }
  737. }
  738. if(!(pbit && !wbit))
  739. reg.r[rn] += off;
  740. if(trace) {
  741. char *hb, *dotp, *dotc;
  742. hb = "B";
  743. if(hbit)
  744. hb = "H";
  745. dotp = "";
  746. if(!pbit)
  747. dotp = ".P";
  748. dotc = cond[reg.cond];
  749. if(lbit) {
  750. if(bit22)
  751. itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
  752. hb, dotp, dotc,
  753. off, rn, rd,
  754. address, value);
  755. else
  756. itrace("MOV%s%s%s\t(R%d)(R%d),R%d #%lux=#%x",
  757. hb, dotp, dotc,
  758. rm, rn, rd,
  759. address, value);
  760. } else {
  761. if(bit22)
  762. itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
  763. hb, dotp, dotc,
  764. rd, off, rn,
  765. address, value);
  766. else
  767. itrace("MOV%s%s%s\tR%d,(R%d)(R%d) #%lux=#%x",
  768. hb, dotp, dotc,
  769. rd, rm, rn,
  770. address, value);
  771. }
  772. }
  773. }
  774. void
  775. Ilsm(ulong inst)
  776. {
  777. char pbit, ubit, sbit, wbit, lbit;
  778. int i, rn, reglist;
  779. ulong address, predelta, postdelta;
  780. pbit = (inst>>24) & 0x1;
  781. ubit = (inst>>23) & 0x1;
  782. sbit = (inst>>22) & 0x1;
  783. wbit = (inst>>21) & 0x1;
  784. lbit = (inst>>20) & 0x1;
  785. rn = (inst>>16) & 0xf;
  786. reglist = inst & 0xffff;
  787. if(reglist & 0x8000)
  788. undef(reg.ir);
  789. if(sbit)
  790. undef(reg.ir);
  791. address = reg.r[rn];
  792. if(pbit) {
  793. predelta = 4;
  794. postdelta = 0;
  795. } else {
  796. predelta = 0;
  797. postdelta = 4;
  798. }
  799. if(ubit) {
  800. for (i = 0; i < 16; ++i) {
  801. if(!(reglist & (1 << i)))
  802. continue;
  803. address += predelta;
  804. if(lbit)
  805. reg.r[i] = getmem_w(address);
  806. else
  807. putmem_w(address, reg.r[i]);
  808. address += postdelta;
  809. }
  810. } else {
  811. for (i = 15; 0 <= i; --i) {
  812. if(!(reglist & (1 << i)))
  813. continue;
  814. address -= predelta;
  815. if(lbit)
  816. reg.r[i] = getmem_w(address);
  817. else
  818. putmem_w(address, reg.r[i]);
  819. address -= postdelta;
  820. }
  821. }
  822. if(wbit) {
  823. reg.r[rn] = address;
  824. }
  825. if(trace) {
  826. itrace("%s.%c%c\tR%d=%lux%s, <%lux>",
  827. (lbit ? "LDM" : "STM"), (ubit ? 'I' : 'D'), (pbit ? 'B' : 'A'),
  828. rn, reg.r[rn], (wbit ? "!" : ""), reglist);
  829. }
  830. }
  831. void
  832. Ib(ulong inst)
  833. {
  834. long v;
  835. v = inst & 0xffffff;
  836. v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
  837. if(trace)
  838. itrace("B%s\t#%lux", cond[reg.cond], v);
  839. reg.r[REGPC] = v - 4;
  840. }
  841. void
  842. Ibl(ulong inst)
  843. {
  844. long v;
  845. Symbol s;
  846. v = inst & 0xffffff;
  847. v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
  848. if(trace)
  849. itrace("BL%s\t#%lux", cond[reg.cond], v);
  850. if(calltree) {
  851. findsym(v, CTEXT, &s);
  852. Bprint(bioout, "%8lux %s(", reg.r[REGPC], s.name);
  853. printparams(&s, reg.r[13]);
  854. Bprint(bioout, "from ");
  855. printsource(reg.r[REGPC]);
  856. Bputc(bioout, '\n');
  857. }
  858. reg.r[REGLINK] = reg.r[REGPC] + 4;
  859. reg.r[REGPC] = v - 4;
  860. }