6db.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. /*
  6. * i960-specific debugger interface
  7. * i960 has an as yet unknown stack format - presotto
  8. */
  9. static char *i960excep(Map*, Rgetter);
  10. static int i960inst(Map*, ulong, char, char*, int);
  11. static int i960das(Map*, ulong, char*, int);
  12. static int i960foll(Map*, ulong, Rgetter, ulong*);
  13. static int i960instlen(Map*, ulong);
  14. Machdata i960mach =
  15. {
  16. {0x66, 0, 0x06, 0}, /* break point: fmark */
  17. 4, /* break point size */
  18. leswab, /* convert short to local byte order */
  19. leswal, /* convert long to local byte order */
  20. leswav, /* vlong to local byte order */
  21. cisctrace, /* C traceback */
  22. ciscframe, /* frame finder */
  23. i960excep, /* print exception */
  24. 0, /* breakpoint fixup */
  25. leieeesftos, /* single precision float printer */
  26. leieeedftos, /* double precision float printer */
  27. i960foll, /* following addresses */
  28. i960inst, /* print instruction */
  29. i960das, /* dissembler */
  30. i960instlen, /* 0 */
  31. };
  32. static char*
  33. i960excep(Map *map, Rgetter rget)
  34. {
  35. USED(map, rget);
  36. return "intel machine exceptions are too hard to decode";
  37. }
  38. /* I960 disassembler and related functions */
  39. typedef struct Instr Instr;
  40. typedef struct Opcode Opcode;
  41. /*
  42. * operand types
  43. */
  44. enum
  45. {
  46. EA=1,
  47. R1, R2, R3,
  48. S1, S2, S3,
  49. IR1, IR2, IR3,
  50. };
  51. enum
  52. {
  53. Treg,
  54. Tctrl,
  55. Tcobr,
  56. Tmem,
  57. };
  58. struct Opcode
  59. {
  60. ushort code;
  61. char *name;
  62. uchar and[3];
  63. };
  64. struct Instr
  65. {
  66. Opcode *op; /* opcode line */
  67. ulong mem[2]; /* memory for this instruction */
  68. int n; /* # longs for this instruction */
  69. char and[3][64];
  70. ulong rel;
  71. char *err;
  72. int type;
  73. int index;
  74. int base;
  75. int mult;
  76. char *curr; /* fill point in output buffer */
  77. char *end; /* end of output buffer */
  78. ulong addr; /* pc of instruction */
  79. };
  80. static Map* mymap;
  81. Opcode optab[] = {
  82. { 0x08, "B", EA },
  83. { 0x09, "CALL", EA },
  84. { 0x0A, "RET" },
  85. { 0x0B, "BAL", EA },
  86. { 0x10, "BNO", EA },
  87. { 0x11, "BG", EA },
  88. { 0x12, "BE", EA },
  89. { 0x13, "BGE", EA },
  90. { 0x14, "BL", EA },
  91. { 0x15, "BNE", EA },
  92. { 0x16, "BLE", EA },
  93. { 0x17, "BO", EA },
  94. { 0x18, "FAULTNO" },
  95. { 0x19, "FAULTG" },
  96. { 0x1A, "FAULTE" },
  97. { 0x1B, "FAULTGE" },
  98. { 0x1C, "FAULTL" },
  99. { 0x1D, "FAULTNE" },
  100. { 0x1E, "FAULTLE" },
  101. { 0x1F, "FAULTO" },
  102. { 0x20, "TESTNO", R1 },
  103. { 0x21, "TESTG", R1 },
  104. { 0x22, "TESTE", R1 },
  105. { 0x23, "TESTGE", R1 },
  106. { 0x24, "TESTL", R1 },
  107. { 0x25, "TESTNE", R1 },
  108. { 0x26, "TESTLE", R1 },
  109. { 0x27, "TESTO", R1 },
  110. { 0x30, "BBC", S1, R2, EA },
  111. { 0x31, "CMPOBG", S1, R2, EA },
  112. { 0x32, "CMPOBE", S1, R2, EA },
  113. { 0x33, "CMPOBGE", S1, R2, EA },
  114. { 0x34, "CMPOBL", S1, R2, EA },
  115. { 0x35, "CMPOBNE", S1, R2, EA },
  116. { 0x36, "CMPOBLE", S1, R2, EA },
  117. { 0x37, "CMPOBO", S1, R2, EA },
  118. { 0x38, "CMPIBNO", S1, R2, EA },
  119. { 0x39, "CMPIBG", S1, R2, EA },
  120. { 0x3A, "CMPIBE", S1, R2, EA },
  121. { 0x3B, "CMPIBGE", S1, R2, EA },
  122. { 0x3C, "CMPIBL", S1, R2, EA },
  123. { 0x3D, "CMPIBNE", S1, R2, EA },
  124. { 0x3E, "CMPIBLE", S1, R2, EA },
  125. { 0x3F, "CMPIBO", S1, R2, EA },
  126. { 0x80, "MOVOB", EA, R1 },
  127. { 0x82, "MOVOB", R1, EA },
  128. { 0x84, "B", EA },
  129. { 0x85, "BAL", EA, R1 },
  130. { 0x86, "CALL", EA },
  131. { 0x88, "MOVOS", EA, R1 },
  132. { 0x8A, "MOVOS", R1, EA },
  133. { 0x8C, "LDA", EA, R1 },
  134. { 0x90, "MOV", EA, R1 },
  135. { 0x92, "MOV", R1, EA },
  136. { 0x98, "MOVV", EA, R1 },
  137. { 0x9A, "MOVV", R1, EA },
  138. { 0xA0, "MOVT", EA, R1 },
  139. { 0xA2, "MOVT", R1, EA },
  140. { 0xB0, "MOVQ", EA, R1 },
  141. { 0xB2, "MOVQ", R1, EA },
  142. { 0xC0, "MOVIB", EA, R1 },
  143. { 0xC2, "MOVIB", R1, EA },
  144. { 0xC8, "MOVIS", EA, R1 },
  145. { 0xCA, "MOVIS", R1, EA },
  146. { 0x580, "NOTBIT", S1, S2, R3 },
  147. { 0x581, "AND", S1, S2, R3 },
  148. { 0x582, "ANDNOT", S1, S2, R3 },
  149. { 0x583, "SETBIT", S1, S2, R3 },
  150. { 0x584, "NOTAND", S1, R3 },
  151. { 0x586, "XOR", S1, S2, R3 },
  152. { 0x587, "OR", S1, S2, R3 },
  153. { 0x588, "NOR", S1, S2, R3 },
  154. { 0x589, "XNOR", S1, S2, R3 },
  155. { 0x58A, "NOT", S1, R3 },
  156. { 0x58B, "ORNOT", S1, S2, R3 },
  157. { 0x58C, "CLRBIT", S1, S2, R3 },
  158. { 0x58D, "NOTOR", S1, S2, R3 },
  159. { 0x58E, "NAND", S1, S2, R3 },
  160. { 0x58F, "ALTERBIT", S1, S2, R3 },
  161. { 0x590, "ADDO", S1, S2, R3 },
  162. { 0x591, "ADDI", S1, S2, R3 },
  163. { 0x592, "SUBO", S1, S2, R3 },
  164. { 0x593, "SUBI", S1, S2, R3 },
  165. { 0x598, "SHRO", S1, S2, R3 },
  166. { 0x59A, "SHRDI", S1, S2, R3 },
  167. { 0x59B, "SHRI", S1, S2, R3 },
  168. { 0x59C, "SHLO", S1, S2, R3 },
  169. { 0x59D, "ROTATE", S1, S2, R3 },
  170. { 0x59E, "SHLI", S1, S2, R3 },
  171. { 0x5A0, "CMPO", S1, S2 },
  172. { 0x5A1, "CMPI", S1, S2 },
  173. { 0x5A2, "CONCMPO", S1, S2 },
  174. { 0x5A3, "CONCMPI", S1, S2 },
  175. { 0x5A4, "CMPINCI", S1, S2, R3 },
  176. { 0x5A5, "CMPINCO", S1, S2, R3 },
  177. { 0x5A6, "CMPDECI", S1, S2, R3 },
  178. { 0x5A7, "CMPDECO", S1, S2, R3 },
  179. { 0x5AC, "SCANBYTE", S1, S2 },
  180. { 0x5AE, "CHKBIT", S1, S2 },
  181. { 0x5B0, "ADDC", S1, S2, R3 },
  182. { 0x5B2, "SUBC", S1, S2, R3 },
  183. { 0x5CC, "MOV", S1, R3 },
  184. { 0x5DC, "MOVV", S1, R3 },
  185. { 0x5EC, "MOVT", S1, R3 },
  186. { 0x5FC, "MOVQ", S1, R3 },
  187. { 0x600, "SYNMOV", IR1, IR3 },
  188. { 0x601, "SYNMOVV", IR1, IR3 },
  189. { 0x602, "SYNMOVQ", IR1, IR3 },
  190. { 0x610, "ATMOD", IR1, S2, R3 },
  191. { 0x612, "ATADD", IR1, S2, R3 },
  192. { 0x615, "SYNMOV", IR1, R2 },
  193. { 0x640, "SPANBIT", S1, R2 },
  194. { 0x641, "SCANBIT", S1, R2 },
  195. { 0x642, "DADDC", S1, S2, R3 },
  196. { 0x643, "DSUBC", S1, S2, R3 },
  197. { 0x644, "DMOVT", S1, R2 },
  198. { 0x645, "MODAC", S1, S2, R3 },
  199. { 0x650, "MODIFY", S1, S2, R3 },
  200. { 0x651, "EXTRACT", S1, S2, R3 },
  201. { 0x654, "MODTC", S1, S2, R3 },
  202. { 0x655, "MODPC", S1, S2 },
  203. { 0x660, "CALLS", S1 },
  204. { 0x66B, "MARK" },
  205. { 0x66C, "FMARK" },
  206. { 0x66D, "FLUSHREG" },
  207. { 0x66F, "SYNCF" },
  208. { 0x670, "EMUL", S1, S2, R3 },
  209. { 0x671, "EDIV", S1, S2, R3 },
  210. { 0x674, "CVTIF", S1, R2 },
  211. { 0x675, "CVTILF", S1, R2 },
  212. { 0x676, "SCALED", S1, S2, R3 },
  213. { 0x677, "SCALEF", S1, S2, R3 },
  214. { 0x680, "ATANF", S1, S2, R3 },
  215. { 0x681, "LOGEPF", S1, S2, R3 },
  216. { 0x682, "LOGF", S1, S2, R3 },
  217. { 0x683, "REMF", S1, S2, R3 },
  218. { 0x684, "CMPOF", S1, S2 },
  219. { 0x685, "CMPF", S1, S2 },
  220. { 0x688, "SQRTF", S1, R2 },
  221. { 0x689, "EXPF", S1, R2 },
  222. { 0x68A, "LOGBNTF", S1, R2 },
  223. { 0x68B, "ROUNDF", S1, R2 },
  224. { 0x68C, "SINF", S1, R2 },
  225. { 0x68D, "COSF", S1, R2 },
  226. { 0x68E, "TANF", S1, R2 },
  227. { 0x68F, "CLASSF", S1 },
  228. { 0x690, "ATAND", S1, S2, R3 },
  229. { 0x691, "LOGEPD", S1, S2, R3 },
  230. { 0x692, "LOGD", S1, S2, R3 },
  231. { 0x693, "REMD", S1, S2, R3 },
  232. { 0x694, "CMPOD", S1, S2 },
  233. { 0x695, "CMPD", S1, S2 },
  234. { 0x698, "SQRTD", S1, S2 },
  235. { 0x699, "EXPD", S1, S2 },
  236. { 0x69A, "LOGBND", S1, S2 },
  237. { 0x69B, "ROUNDD", S1, S2 },
  238. { 0x69C, "SIND", S1, S2 },
  239. { 0x69D, "COSD", S1, S2 },
  240. { 0x69E, "TAND", S1, S2 },
  241. { 0x69F, "CLASSD", S1 },
  242. { 0x6C0, "CVTRI", S1, R2 },
  243. { 0x6C1, "CVTRI", S1, R2 },
  244. { 0x6C2, "CVTRI", S1, R2 },
  245. { 0x6C3, "CVTRI", S1, R2 },
  246. { 0x6C9, "MOVF", S1, R2 },
  247. { 0x6D9, "MOVD", S1, R2 },
  248. { 0x6E2, "CPYSRE", S1, S2, R3 },
  249. { 0x6E3, "CPYRSRE", S1, S2, R3 },
  250. { 0x6E3, "MOVRE", S1, R2 },
  251. { 0x701, "MULO", S1, S2, R3 },
  252. { 0x708, "REMO", S1, S2, R3 },
  253. { 0x70B, "DIVO", S1, S2, R3 },
  254. { 0x741, "MULI", S1, S2, R3 },
  255. { 0x748, "REMI", S1, S2, R3 },
  256. { 0x749, "MODI", S1, S2, R3 },
  257. { 0x74B, "DIVI", S1, S2, R3 },
  258. { 0x78B, "DIVF", S1, S2, R3 },
  259. { 0x78C, "MULF", S1, S2, R3 },
  260. { 0x78D, "SUBF", S1, S2, R3 },
  261. { 0x78F, "ADDR", S1, S2, R3 },
  262. { 0x79B, "DIVD", S1, S2, R3 },
  263. { 0x79C, "MULD", S1, S2, R3 },
  264. { 0x79D, "SUBD", S1, S2, R3 },
  265. { 0x79F, "MODI", S1, S2, R3 },
  266. { 0 },
  267. };
  268. #define NOP (sizeof(optab)/sizeof(Opcode))
  269. /*
  270. * get an instruction long
  271. */
  272. static int
  273. igetl(Instr *ip, long *lp)
  274. {
  275. if(ip->n >= 2){
  276. werrstr("instruction too big");
  277. return -1;
  278. }
  279. if (get4(mymap, ip->addr+ip->n*4, (long*) &ip->mem[ip->n]) < 0) {
  280. werrstr("can't read instruction: %r");
  281. return -1;
  282. }
  283. *lp = ip->mem[ip->n++];
  284. return 1;
  285. }
  286. static Opcode*
  287. findopcode(ushort code)
  288. {
  289. Opcode *o;
  290. for(o = optab; o->code; o++)
  291. if(code == o->code)
  292. return o;
  293. werrstr("unknown opcode");
  294. return 0;
  295. }
  296. static char*
  297. genname(ulong l, int reg, int mode, int regonly, int ind)
  298. {
  299. static char name[32];
  300. reg = (l>>reg) & 0x1f;
  301. if(mode >= 0)
  302. mode = (l>>mode) & 1;
  303. else
  304. mode = 0;
  305. if(mode)
  306. sprint(name, regonly?"?$%d?":"$%d", reg);
  307. else
  308. sprint(name, ind?"(R%d)":"R%d", reg);
  309. return name;
  310. }
  311. /*
  312. * decode a reg instruction
  313. */
  314. static char*
  315. regfield(Instr *ip, uchar and, ulong l)
  316. {
  317. switch(and){
  318. case S1:
  319. case R1:
  320. case IR1:
  321. return genname(l, 0, 11, and!=S1, and==IR1);
  322. case S2:
  323. case R2:
  324. case IR2:
  325. return genname(l, 14, 12, and!=S2, and==IR2);
  326. case S3:
  327. case R3:
  328. case IR3:
  329. return genname(l, 19, 13, and!=S3, and==IR3);
  330. default:
  331. ip->err = "missing regfield";
  332. return("???");
  333. }
  334. }
  335. static void
  336. chk56(Instr *ip, ulong l)
  337. {
  338. if(l & (3<<5))
  339. ip->err = "bits 5 and 6 not 0";
  340. }
  341. static int
  342. reginst(Instr *ip, ulong l)
  343. {
  344. ushort code;
  345. int i;
  346. ip->type = Treg;
  347. code = ((l>>20)&0xff0) | ((l>>7)&0xf);
  348. ip->op = findopcode(code);
  349. if(ip->op == 0)
  350. return -1;
  351. for(i = 0; i < 3; i++){
  352. if(ip->op->and[i] == 0)
  353. break;
  354. strcpy(ip->and[i], regfield(ip, ip->op->and[i], l));
  355. }
  356. return 0;
  357. }
  358. /*
  359. * decode a control and branch instruction
  360. */
  361. static char*
  362. cobrfield(Instr *ip, uchar and, ulong l)
  363. {
  364. long disp;
  365. switch(and){
  366. case S1:
  367. case R1:
  368. case IR1:
  369. return genname(l, 19, 13, and!=S1, and==IR1);
  370. case R2:
  371. case IR2:
  372. return genname(l, 14, -1, 1, and==IR2);
  373. case EA:
  374. if(l & (1<<12))
  375. disp = -(((~l) & 0xfff)+1);
  376. else
  377. disp = l & 0xfff;
  378. ip->rel = ip->addr + 4 + disp;
  379. return ".+";
  380. default:
  381. return "???";
  382. }
  383. }
  384. static int
  385. cobrinst(Instr *ip, ulong l)
  386. {
  387. ushort code;
  388. int i;
  389. ip->type = Tcobr;
  390. if(l&3)
  391. ip->err = "disp not mult of 4";
  392. code = l>>24;
  393. ip->op = findopcode(code);
  394. if(ip->op == 0)
  395. return -1;
  396. for(i = 0; i < 3; i++){
  397. if(ip->op->and[i] == 0)
  398. break;
  399. strcpy(ip->and[i], cobrfield(ip, ip->op->and[i], l));
  400. }
  401. return 0;
  402. }
  403. /*
  404. * decode a control instruction
  405. */
  406. static int
  407. ctrlinst(Instr *ip, ulong l)
  408. {
  409. ushort code;
  410. long disp;
  411. ip->type = Tctrl;
  412. if(l&3)
  413. ip->err = "disp not mult of 4";
  414. code = l>>24;
  415. ip->op = findopcode(code);
  416. if(ip->op == 0)
  417. return -1;
  418. if(ip->op->and[0] == 0)
  419. return 0;
  420. if(l & (1<<23))
  421. disp = -(((~l) & 0x7fffff)+1);
  422. else
  423. disp = l & 0x7fffff;
  424. ip->rel = ip->addr + 4 + disp;
  425. strcpy(ip->and[0], ".+");
  426. return 0;
  427. }
  428. static int
  429. sprintoff(char *addr, int n, char *fmt, ulong v)
  430. {
  431. Symbol s;
  432. long w;
  433. w = v+mach->sb;
  434. if (findsym(w, CDATA, &s)) {
  435. w = s.value-w;
  436. if (w <= 4096) {
  437. if (w)
  438. return snprint(addr, n, "%s+%lux(SB)", s.name, w);
  439. else
  440. return snprint(addr, n, "%s(SB)", s.name);
  441. }
  442. }
  443. return snprint(addr, n, fmt, v);
  444. }
  445. /*
  446. * decode a memory instruction
  447. */
  448. static char*
  449. memfield(Instr *ip, uchar and, ulong l)
  450. {
  451. long disp;
  452. static char addr[64];
  453. int abase;
  454. int scale;
  455. int index;
  456. ip->mult = 1;
  457. switch(and){
  458. case R1:
  459. case IR1:
  460. return genname(l, 19, -1, 1, and==IR1);
  461. case EA:
  462. abase = (l>>14)&0x1f;
  463. scale = 1 << ((l>>7)&0x7);
  464. index = l & 0x1f;
  465. switch((l>>10)&0xf){
  466. case 0x4:
  467. chk56(ip, l);
  468. ip->base = abase + 1;
  469. sprint(addr, "(R%d)", abase);
  470. break;
  471. case 0x5:
  472. chk56(ip, l);
  473. if (igetl(ip, &disp) < 0) {
  474. strcpy(addr, "???");
  475. break;
  476. }
  477. ip->rel = disp + ip->addr + 8;
  478. strcpy(addr, ".+");
  479. break;
  480. case 0x6:
  481. strcpy(addr, "???");
  482. break;
  483. case 0x7:
  484. chk56(ip, l);
  485. ip->base = abase + 1;
  486. ip->mult = scale;
  487. ip->index = index + 1;
  488. sprint(addr, "(R%d)(%d*R%d)", abase, scale, index);
  489. break;
  490. case 0xc:
  491. chk56(ip, l);
  492. if (igetl(ip, &disp) < 0) {
  493. strcpy(addr, "???");
  494. break;
  495. }
  496. ip->rel = disp;
  497. strcpy(addr, ".+");
  498. break;
  499. case 0xd:
  500. chk56(ip, l);
  501. if (igetl(ip, &disp) < 0) {
  502. strcpy(addr, "???");
  503. break;
  504. }
  505. ip->rel = disp;
  506. if(abase == 28)
  507. sprintoff(addr, sizeof(addr), "%lux(R28)", disp);
  508. else{
  509. ip->base = abase + 1;
  510. sprint(addr, "%lx(R%d)", disp, abase);
  511. }
  512. break;
  513. case 0xe:
  514. chk56(ip, l);
  515. if (igetl(ip, &disp) < 0) {
  516. strcpy(addr, "???");
  517. break;
  518. }
  519. ip->rel = disp;
  520. ip->mult = scale;
  521. ip->index = index + 1;
  522. sprint(addr, "%lx(%d*R%d)", disp, scale, index);
  523. break;
  524. case 0xf:
  525. chk56(ip, l);
  526. if (igetl(ip, &disp) < 0) {
  527. strcpy(addr, "???");
  528. break;
  529. }
  530. ip->rel = disp;
  531. ip->mult = scale;
  532. ip->index = index + 1;
  533. ip->base = abase + 1;
  534. sprint(addr, "%lx(R%d)(%d*R%d)", disp, abase,
  535. scale, index);
  536. break;
  537. default:
  538. disp = l&0xfff;
  539. ip->rel = disp;
  540. if(l & (1<<13)){
  541. if(abase == 28)
  542. sprintoff(addr, sizeof(addr), "%lux(R28)", disp);
  543. else{
  544. ip->base = abase + 1;
  545. sprint(addr, "%lux(R%d)", disp, abase);
  546. }
  547. } else {
  548. strcpy(addr, ".+");
  549. }
  550. break;
  551. }
  552. return addr;
  553. default:
  554. break;
  555. }
  556. return "???";
  557. }
  558. static int
  559. meminst(Instr *ip, ulong l)
  560. {
  561. ushort code;
  562. int i;
  563. ip->type = Tmem;
  564. code = l>>24;
  565. ip->op = findopcode(code);
  566. if(ip->op == 0)
  567. return -1;
  568. for(i = 0; i < 2; i++){
  569. if(ip->op->and[i] == 0)
  570. break;
  571. strcpy(ip->and[i], memfield(ip, ip->op->and[i], l));
  572. }
  573. return 0;
  574. }
  575. static int
  576. mkinstr(Instr *ip, ulong pc)
  577. {
  578. long l;
  579. memset(ip, 0, sizeof(Instr));
  580. ip->addr = pc;
  581. if (igetl(ip, &l) < 0)
  582. return -1;
  583. switch(l>>28){
  584. case 0x0:
  585. case 0x1:
  586. return ctrlinst(ip, l);
  587. case 0x2:
  588. case 0x3:
  589. return cobrinst(ip, l);
  590. case 0x5:
  591. case 0x6:
  592. case 0x7:
  593. return reginst(ip, l);
  594. case 0x8:
  595. case 0x9:
  596. case 0xa:
  597. case 0xb:
  598. case 0xc:
  599. return meminst(ip, l);
  600. }
  601. werrstr("unknown opcode");
  602. return -1;
  603. }
  604. static int
  605. i960inst(Map *map, ulong pc, char modifier, char *buf, int n)
  606. {
  607. Instr instr;
  608. int i;
  609. char *and;
  610. char *end;
  611. USED(modifier);
  612. mymap = map;
  613. if(mkinstr(&instr, pc) < 0)
  614. return -1;
  615. end = buf+n-1;
  616. buf += snprint(buf, end-buf, "%s ", instr.op->name);
  617. for(i = 0; i < 3; i++){
  618. and = instr.and[i];
  619. if(*and == 0)
  620. break;
  621. if(i != 0)
  622. buf += snprint(buf, end-buf, ",");
  623. if(strcmp(and, ".+") == 0){
  624. buf += sprintoff(buf, end-buf, "$%lux", instr.rel);
  625. } else
  626. buf += snprint(buf, end-buf, "%s", and);
  627. }
  628. if(instr.err)
  629. snprint(buf, end-buf, "\t\t;%s", instr.err);
  630. return instr.n*4;
  631. }
  632. static int
  633. i960das(Map *map, ulong pc, char *buf, int n)
  634. {
  635. Instr instr;
  636. mymap = map;
  637. if (mkinstr(&instr, pc) < 0)
  638. return -1;
  639. if (n > 8) {
  640. _hexify(buf, instr.mem[0], 7);
  641. n -= 8;
  642. buf += 8;
  643. }
  644. if (n > 9 && instr.n == 2) {
  645. *buf++ = ' ';
  646. _hexify(buf, instr.mem[1], 7);
  647. buf += 8;
  648. }
  649. *buf = 0;
  650. return instr.n*4;
  651. }
  652. static int
  653. i960instlen(Map *map, ulong pc)
  654. {
  655. Instr instr;
  656. mymap = map;
  657. if (mkinstr(&instr, pc) < 0)
  658. return -1;
  659. return instr.n*4;
  660. }
  661. static int
  662. i960foll(Map *map, ulong pc, Rgetter rget, ulong *foll)
  663. {
  664. Instr instr;
  665. ulong l;
  666. char buf[8];
  667. mymap = map;
  668. if (mkinstr(&instr, pc) < 0)
  669. return -1;
  670. foll[0] = pc + instr.n;
  671. switch(instr.type){
  672. case Tcobr:
  673. case Treg:
  674. break;
  675. case Tctrl:
  676. if(instr.op->name[0] == 'B'){
  677. foll[1] = instr.rel;
  678. return 2;
  679. }
  680. if(strcmp("CALL", instr.op->name) == 0){
  681. foll[0] = instr.rel;
  682. return 1;
  683. }
  684. if(strcmp("RET", instr.op->name) == 0)
  685. return -1;
  686. break;
  687. case Tmem:
  688. if(strcmp("BAL", instr.op->name) == 0
  689. || strcmp("CALL", instr.op->name) == 0){
  690. l = instr.rel;
  691. if(instr.index){
  692. sprint(buf, "R%d", instr.index - 1);
  693. l += (*rget)(map, buf) * instr.mult;
  694. }
  695. if(instr.base){
  696. sprint(buf, "R%d", instr.base - 1);
  697. l += (*rget)(map, buf);
  698. }
  699. foll[0] = l;
  700. return 1;
  701. }
  702. break;
  703. }
  704. return 1;
  705. }