main.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. /*
  2. * Copyright (C) 2006-2010 Michael Buesch <m@bues.ch>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include "main.h"
  14. #include "list.h"
  15. #include "util.h"
  16. #include "args.h"
  17. #include <stdio.h>
  18. #include <stdint.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. struct bin_instruction {
  22. unsigned int opcode;
  23. unsigned int operands[3];
  24. };
  25. struct statement {
  26. enum {
  27. STMT_INSN,
  28. STMT_LABEL,
  29. } type;
  30. union {
  31. struct {
  32. struct bin_instruction *bin;
  33. const char *name;
  34. const char *operands[5];
  35. int labelref_operand;
  36. unsigned int labeladdr;
  37. struct statement *labelref;
  38. } insn;
  39. struct {
  40. char *name;
  41. } label;
  42. } u;
  43. struct list_head list;
  44. };
  45. struct disassembler_context {
  46. /* The architecture of the input file. */
  47. unsigned int arch;
  48. struct bin_instruction *code;
  49. size_t nr_insns;
  50. struct list_head stmt_list;
  51. };
  52. FILE *infile;
  53. FILE *outfile;
  54. const char *infile_name;
  55. const char *outfile_name;
  56. #define _msg_helper(type, msg, x...) do { \
  57. fprintf(stderr, "Disassembler " type \
  58. ":\n " msg "\n" ,##x); \
  59. } while (0)
  60. #define dasm_error(msg, x...) do { \
  61. _msg_helper("ERROR", msg ,##x); \
  62. exit(1); \
  63. } while (0)
  64. #define dasm_int_error(msg, x...) \
  65. dasm_error("Internal error (bug): " msg ,##x)
  66. #define dasm_warn(msg, x...) \
  67. _msg_helper("warning", msg ,##x)
  68. #define asm_info(msg, x...) \
  69. _msg_helper("info", msg ,##x)
  70. static const char * gen_raw_code(unsigned int operand)
  71. {
  72. char *ret;
  73. ret = xmalloc(6);
  74. snprintf(ret, 6, "@%X", operand);
  75. return ret;
  76. }
  77. static const char * disasm_mem_operand(unsigned int operand)
  78. {
  79. char *ret;
  80. ret = xmalloc(9);
  81. snprintf(ret, 9, "[0x%X]", operand);
  82. return ret;
  83. }
  84. static const char * disasm_indirect_mem_operand(unsigned int operand)
  85. {
  86. char *ret;
  87. unsigned int offset, reg;
  88. switch (cmdargs.arch) {
  89. case 5:
  90. offset = (operand & 0x3F);
  91. reg = ((operand >> 6) & 0x7);
  92. break;
  93. case 15:
  94. offset = (operand & 0x7F);
  95. reg = ((operand >> 7) & 0x7);
  96. break;
  97. default:
  98. dasm_int_error("disasm_indirect_mem_operand invalid arch");
  99. }
  100. ret = xmalloc(12);
  101. snprintf(ret, 12, "[0x%02X,off%u]", offset, reg);
  102. return ret;
  103. }
  104. static const char * disasm_imm_operand(unsigned int operand)
  105. {
  106. char *ret;
  107. unsigned int signmask;
  108. unsigned int mask;
  109. switch (cmdargs.arch) {
  110. case 5:
  111. signmask = (1 << 9);
  112. mask = 0x3FF;
  113. break;
  114. case 15:
  115. signmask = (1 << 10);
  116. mask = 0x7FF;
  117. break;
  118. default:
  119. dasm_int_error("disasm_imm_operand invalid arch");
  120. }
  121. operand &= mask;
  122. ret = xmalloc(7);
  123. if (operand & signmask)
  124. operand = (operand | (~mask & 0xFFFF));
  125. snprintf(ret, 7, "0x%X", operand);
  126. return ret;
  127. }
  128. static const char * disasm_spr_operand(unsigned int operand)
  129. {
  130. char *ret;
  131. unsigned int mask;
  132. switch (cmdargs.arch) {
  133. case 5:
  134. mask = 0x1FF;
  135. break;
  136. case 15:
  137. mask = 0x7FF;
  138. break;
  139. default:
  140. dasm_int_error("disasm_spr_operand invalid arch");
  141. }
  142. ret = xmalloc(8);
  143. snprintf(ret, 8, "spr%X", (operand & mask));
  144. return ret;
  145. }
  146. static const char * disasm_gpr_operand(unsigned int operand)
  147. {
  148. char *ret;
  149. unsigned int mask;
  150. switch (cmdargs.arch) {
  151. case 5:
  152. mask = 0x3F;
  153. break;
  154. case 15:
  155. mask = 0x7F;
  156. break;
  157. default:
  158. dasm_int_error("disasm_gpr_operand invalid arch");
  159. }
  160. ret = xmalloc(5);
  161. snprintf(ret, 5, "r%u", (operand & mask));
  162. return ret;
  163. }
  164. static void disasm_raw_operand(struct statement *stmt,
  165. int oper_idx,
  166. int out_idx)
  167. {
  168. unsigned int operand = stmt->u.insn.bin->operands[oper_idx];
  169. stmt->u.insn.operands[out_idx] = gen_raw_code(operand);
  170. }
  171. static void disasm_std_operand(struct statement *stmt,
  172. int oper_idx,
  173. int out_idx)
  174. {
  175. unsigned int operand = stmt->u.insn.bin->operands[oper_idx];
  176. switch (cmdargs.arch) {
  177. case 5:
  178. if (!(operand & 0x800)) {
  179. stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand);
  180. return;
  181. } else if ((operand & 0xC00) == 0xC00) {
  182. stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand);
  183. return;
  184. } else if ((operand & 0xFC0) == 0xBC0) {
  185. stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand);
  186. return;
  187. } else if ((operand & 0xE00) == 0x800) {
  188. stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand);
  189. return;
  190. } else if ((operand & 0xE00) == 0xA00) {
  191. stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand);
  192. return;
  193. }
  194. break;
  195. case 15:
  196. if (!(operand & 0x1000)) {
  197. stmt->u.insn.operands[out_idx] = disasm_mem_operand(operand);
  198. return;
  199. } else if ((operand & 0x1800) == 0x1800) {
  200. stmt->u.insn.operands[out_idx] = disasm_imm_operand(operand);
  201. return;
  202. } else if ((operand & 0x1F80) == 0x1780) {
  203. stmt->u.insn.operands[out_idx] = disasm_gpr_operand(operand);
  204. return;
  205. } else if ((operand & 0x1C00) == 0x1000) {
  206. stmt->u.insn.operands[out_idx] = disasm_spr_operand(operand);
  207. return;
  208. } else if ((operand & 0x1C00) == 0x1400) {
  209. stmt->u.insn.operands[out_idx] = disasm_indirect_mem_operand(operand);
  210. return;
  211. }
  212. break;
  213. default:
  214. dasm_int_error("disasm_std_operand invalid arch");
  215. }
  216. /* No luck. Disassemble to raw operand. */
  217. disasm_raw_operand(stmt, oper_idx, out_idx);
  218. }
  219. static void disasm_opcode_raw(struct disassembler_context *ctx,
  220. struct statement *stmt,
  221. int raw_operands)
  222. {
  223. stmt->u.insn.name = gen_raw_code(stmt->u.insn.bin->opcode);
  224. if (raw_operands) {
  225. disasm_raw_operand(stmt, 0, 0);
  226. disasm_raw_operand(stmt, 1, 1);
  227. disasm_raw_operand(stmt, 2, 2);
  228. } else {
  229. disasm_std_operand(stmt, 0, 0);
  230. disasm_std_operand(stmt, 1, 1);
  231. disasm_std_operand(stmt, 2, 2);
  232. }
  233. }
  234. static void disasm_constant_opcodes(struct disassembler_context *ctx,
  235. struct statement *stmt)
  236. {
  237. struct bin_instruction *bin = stmt->u.insn.bin;
  238. switch (bin->opcode) {
  239. case 0x101:
  240. stmt->u.insn.name = "mul";
  241. disasm_std_operand(stmt, 0, 0);
  242. disasm_std_operand(stmt, 1, 1);
  243. disasm_std_operand(stmt, 2, 2);
  244. break;
  245. case 0x1C0:
  246. stmt->u.insn.name = "add";
  247. disasm_std_operand(stmt, 0, 0);
  248. disasm_std_operand(stmt, 1, 1);
  249. disasm_std_operand(stmt, 2, 2);
  250. break;
  251. case 0x1C2:
  252. stmt->u.insn.name = "add.";
  253. disasm_std_operand(stmt, 0, 0);
  254. disasm_std_operand(stmt, 1, 1);
  255. disasm_std_operand(stmt, 2, 2);
  256. break;
  257. case 0x1C1:
  258. stmt->u.insn.name = "addc";
  259. disasm_std_operand(stmt, 0, 0);
  260. disasm_std_operand(stmt, 1, 1);
  261. disasm_std_operand(stmt, 2, 2);
  262. break;
  263. case 0x1C3:
  264. stmt->u.insn.name = "addc.";
  265. disasm_std_operand(stmt, 0, 0);
  266. disasm_std_operand(stmt, 1, 1);
  267. disasm_std_operand(stmt, 2, 2);
  268. break;
  269. case 0x1D0:
  270. stmt->u.insn.name = "sub";
  271. disasm_std_operand(stmt, 0, 0);
  272. disasm_std_operand(stmt, 1, 1);
  273. disasm_std_operand(stmt, 2, 2);
  274. break;
  275. case 0x1D2:
  276. stmt->u.insn.name = "sub.";
  277. disasm_std_operand(stmt, 0, 0);
  278. disasm_std_operand(stmt, 1, 1);
  279. disasm_std_operand(stmt, 2, 2);
  280. break;
  281. case 0x1D1:
  282. stmt->u.insn.name = "subc";
  283. disasm_std_operand(stmt, 0, 0);
  284. disasm_std_operand(stmt, 1, 1);
  285. disasm_std_operand(stmt, 2, 2);
  286. break;
  287. case 0x1D3:
  288. stmt->u.insn.name = "subc.";
  289. disasm_std_operand(stmt, 0, 0);
  290. disasm_std_operand(stmt, 1, 1);
  291. disasm_std_operand(stmt, 2, 2);
  292. break;
  293. case 0x130:
  294. stmt->u.insn.name = "sra";
  295. disasm_std_operand(stmt, 0, 0);
  296. disasm_std_operand(stmt, 1, 1);
  297. disasm_std_operand(stmt, 2, 2);
  298. break;
  299. case 0x160:
  300. stmt->u.insn.name = "or";
  301. disasm_std_operand(stmt, 0, 0);
  302. disasm_std_operand(stmt, 1, 1);
  303. disasm_std_operand(stmt, 2, 2);
  304. break;
  305. case 0x140:
  306. stmt->u.insn.name = "and";
  307. disasm_std_operand(stmt, 0, 0);
  308. disasm_std_operand(stmt, 1, 1);
  309. disasm_std_operand(stmt, 2, 2);
  310. break;
  311. case 0x170:
  312. stmt->u.insn.name = "xor";
  313. disasm_std_operand(stmt, 0, 0);
  314. disasm_std_operand(stmt, 1, 1);
  315. disasm_std_operand(stmt, 2, 2);
  316. break;
  317. case 0x120:
  318. stmt->u.insn.name = "sr";
  319. disasm_std_operand(stmt, 0, 0);
  320. disasm_std_operand(stmt, 1, 1);
  321. disasm_std_operand(stmt, 2, 2);
  322. break;
  323. case 0x110:
  324. stmt->u.insn.name = "sl";
  325. disasm_std_operand(stmt, 0, 0);
  326. disasm_std_operand(stmt, 1, 1);
  327. disasm_std_operand(stmt, 2, 2);
  328. break;
  329. case 0x1A0:
  330. stmt->u.insn.name = "rl";
  331. disasm_std_operand(stmt, 0, 0);
  332. disasm_std_operand(stmt, 1, 1);
  333. disasm_std_operand(stmt, 2, 2);
  334. break;
  335. case 0x1B0:
  336. stmt->u.insn.name = "rr";
  337. disasm_std_operand(stmt, 0, 0);
  338. disasm_std_operand(stmt, 1, 1);
  339. disasm_std_operand(stmt, 2, 2);
  340. break;
  341. case 0x150:
  342. stmt->u.insn.name = "nand";
  343. disasm_std_operand(stmt, 0, 0);
  344. disasm_std_operand(stmt, 1, 1);
  345. disasm_std_operand(stmt, 2, 2);
  346. break;
  347. case 0x040:
  348. stmt->u.insn.name = "jand";
  349. stmt->u.insn.labelref_operand = 2;
  350. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  351. disasm_std_operand(stmt, 0, 0);
  352. disasm_std_operand(stmt, 1, 1);
  353. break;
  354. case (0x040 | 0x1):
  355. stmt->u.insn.name = "jnand";
  356. stmt->u.insn.labelref_operand = 2;
  357. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  358. disasm_std_operand(stmt, 0, 0);
  359. disasm_std_operand(stmt, 1, 1);
  360. break;
  361. case 0x050:
  362. stmt->u.insn.name = "js";
  363. stmt->u.insn.labelref_operand = 2;
  364. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  365. disasm_std_operand(stmt, 0, 0);
  366. disasm_std_operand(stmt, 1, 1);
  367. break;
  368. case (0x050 | 0x1):
  369. stmt->u.insn.name = "jns";
  370. stmt->u.insn.labelref_operand = 2;
  371. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  372. disasm_std_operand(stmt, 0, 0);
  373. disasm_std_operand(stmt, 1, 1);
  374. break;
  375. case 0x0D0:
  376. stmt->u.insn.name = "je";
  377. stmt->u.insn.labelref_operand = 2;
  378. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  379. disasm_std_operand(stmt, 0, 0);
  380. disasm_std_operand(stmt, 1, 1);
  381. break;
  382. case (0x0D0 | 0x1):
  383. stmt->u.insn.name = "jne";
  384. stmt->u.insn.labelref_operand = 2;
  385. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  386. disasm_std_operand(stmt, 0, 0);
  387. disasm_std_operand(stmt, 1, 1);
  388. break;
  389. case 0x0D2:
  390. stmt->u.insn.name = "jls";
  391. stmt->u.insn.labelref_operand = 2;
  392. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  393. disasm_std_operand(stmt, 0, 0);
  394. disasm_std_operand(stmt, 1, 1);
  395. break;
  396. case (0x0D2 | 0x1):
  397. stmt->u.insn.name = "jges";
  398. stmt->u.insn.labelref_operand = 2;
  399. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  400. disasm_std_operand(stmt, 0, 0);
  401. disasm_std_operand(stmt, 1, 1);
  402. break;
  403. case 0x0D4:
  404. stmt->u.insn.name = "jgs";
  405. stmt->u.insn.labelref_operand = 2;
  406. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  407. disasm_std_operand(stmt, 0, 0);
  408. disasm_std_operand(stmt, 1, 1);
  409. break;
  410. case (0x0D4 | 0x1):
  411. stmt->u.insn.name = "jles";
  412. stmt->u.insn.labelref_operand = 2;
  413. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  414. disasm_std_operand(stmt, 0, 0);
  415. disasm_std_operand(stmt, 1, 1);
  416. break;
  417. case 0x0D6:
  418. stmt->u.insn.name = "jdn";
  419. stmt->u.insn.labelref_operand = 2;
  420. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  421. disasm_std_operand(stmt, 0, 0);
  422. disasm_std_operand(stmt, 1, 1);
  423. break;
  424. case (0x0D6 | 0x1):
  425. stmt->u.insn.name = "jdpz";
  426. stmt->u.insn.labelref_operand = 2;
  427. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  428. disasm_std_operand(stmt, 0, 0);
  429. disasm_std_operand(stmt, 1, 1);
  430. break;
  431. case 0x0D8:
  432. stmt->u.insn.name = "jdp";
  433. stmt->u.insn.labelref_operand = 2;
  434. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  435. disasm_std_operand(stmt, 0, 0);
  436. disasm_std_operand(stmt, 1, 1);
  437. break;
  438. case (0x0D8 | 0x1):
  439. stmt->u.insn.name = "jdnz";
  440. stmt->u.insn.labelref_operand = 2;
  441. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  442. disasm_std_operand(stmt, 0, 0);
  443. disasm_std_operand(stmt, 1, 1);
  444. break;
  445. case 0x0DA:
  446. stmt->u.insn.name = "jl";
  447. stmt->u.insn.labelref_operand = 2;
  448. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  449. disasm_std_operand(stmt, 0, 0);
  450. disasm_std_operand(stmt, 1, 1);
  451. break;
  452. case (0x0DA | 0x1):
  453. stmt->u.insn.name = "jge";
  454. stmt->u.insn.labelref_operand = 2;
  455. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  456. disasm_std_operand(stmt, 0, 0);
  457. disasm_std_operand(stmt, 1, 1);
  458. break;
  459. case 0x0DC:
  460. stmt->u.insn.name = "jg";
  461. stmt->u.insn.labelref_operand = 2;
  462. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  463. disasm_std_operand(stmt, 0, 0);
  464. disasm_std_operand(stmt, 1, 1);
  465. break;
  466. case (0x0DC | 0x1):
  467. stmt->u.insn.name = "jle";
  468. stmt->u.insn.labelref_operand = 2;
  469. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  470. disasm_std_operand(stmt, 0, 0);
  471. disasm_std_operand(stmt, 1, 1);
  472. break;
  473. case 0x002: {
  474. char *str;
  475. switch (cmdargs.arch) {
  476. case 5:
  477. stmt->u.insn.name = "call";
  478. stmt->u.insn.labelref_operand = 1;
  479. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  480. str = xmalloc(4);
  481. snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]);
  482. stmt->u.insn.operands[0] = str;
  483. break;
  484. case 15:
  485. //FIXME: This opcode is different on r15. Decode raw for now.
  486. disasm_opcode_raw(ctx, stmt, 1);
  487. break;
  488. }
  489. break;
  490. }
  491. case 0x003: {
  492. char *str;
  493. stmt->u.insn.name = "ret";
  494. str = xmalloc(4);
  495. snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]);
  496. stmt->u.insn.operands[0] = str;
  497. str = xmalloc(4);
  498. snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[2]);
  499. stmt->u.insn.operands[2] = str;
  500. break;
  501. }
  502. case 0x004: {
  503. if (cmdargs.arch != 15) {
  504. dasm_error("arch 15 'calls' instruction found in arch %d binary",
  505. cmdargs.arch);
  506. }
  507. stmt->u.insn.name = "calls";
  508. stmt->u.insn.labelref_operand = 0;
  509. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  510. if (stmt->u.insn.bin->operands[0] != 0x1780 ||
  511. stmt->u.insn.bin->operands[1] != 0x1780)
  512. dasm_warn("r15 calls: Invalid first or second argument");
  513. break;
  514. }
  515. case 0x005: {
  516. if (cmdargs.arch != 15) {
  517. dasm_error("arch 15 'rets' instruction found in arch %d binary",
  518. cmdargs.arch);
  519. }
  520. stmt->u.insn.name = "rets";
  521. if (stmt->u.insn.bin->operands[0] != 0x1780 ||
  522. stmt->u.insn.bin->operands[1] != 0x1780 ||
  523. stmt->u.insn.bin->operands[2] != 0)
  524. dasm_warn("r15 rets: Invalid argument(s)");
  525. break;
  526. }
  527. case 0x1E0: {
  528. unsigned int flags, mask;
  529. switch (cmdargs.arch) {
  530. case 5:
  531. mask = 0x3FF;
  532. break;
  533. case 15:
  534. mask = 0x7FF;
  535. break;
  536. default:
  537. dasm_int_error("TKIP invalid arch");
  538. }
  539. flags = stmt->u.insn.bin->operands[1];
  540. switch (flags & mask) {
  541. case 0x1:
  542. stmt->u.insn.name = "tkiph";
  543. break;
  544. case (0x1 | 0x2):
  545. stmt->u.insn.name = "tkiphs";
  546. break;
  547. case 0x0:
  548. stmt->u.insn.name = "tkipl";
  549. break;
  550. case (0x0 | 0x2):
  551. stmt->u.insn.name = "tkipls";
  552. break;
  553. default:
  554. dasm_error("Invalid TKIP flags %X", flags);
  555. }
  556. disasm_std_operand(stmt, 0, 0);
  557. disasm_std_operand(stmt, 2, 2);
  558. break;
  559. }
  560. case 0x001: {
  561. unsigned int mask;
  562. stmt->u.insn.name = "nap";
  563. switch (cmdargs.arch) {
  564. case 5:
  565. mask = 0xBC0;
  566. break;
  567. case 15:
  568. mask = 0x1780;
  569. break;
  570. default:
  571. dasm_int_error("NAP invalid arch");
  572. }
  573. if (stmt->u.insn.bin->operands[0] != mask) {
  574. dasm_warn("NAP: invalid first argument 0x%04X\n",
  575. stmt->u.insn.bin->operands[0]);
  576. }
  577. if (stmt->u.insn.bin->operands[1] != mask) {
  578. dasm_warn("NAP: invalid second argument 0x%04X\n",
  579. stmt->u.insn.bin->operands[1]);
  580. }
  581. if (stmt->u.insn.bin->operands[2] != 0) {
  582. dasm_warn("NAP: invalid third argument 0x%04X\n",
  583. stmt->u.insn.bin->operands[2]);
  584. }
  585. break;
  586. }
  587. case 0x000:
  588. disasm_opcode_raw(ctx, stmt, 1);
  589. break;
  590. default:
  591. disasm_opcode_raw(ctx, stmt, (cmdargs.unknown_decode == 0));
  592. break;
  593. }
  594. }
  595. static void disasm_opcodes(struct disassembler_context *ctx)
  596. {
  597. struct bin_instruction *bin;
  598. size_t i;
  599. struct statement *stmt;
  600. char *str;
  601. for (i = 0; i < ctx->nr_insns; i++) {
  602. bin = &(ctx->code[i]);
  603. stmt = xmalloc(sizeof(struct statement));
  604. stmt->type = STMT_INSN;
  605. INIT_LIST_HEAD(&stmt->list);
  606. stmt->u.insn.bin = bin;
  607. stmt->u.insn.labelref_operand = -1; /* none */
  608. switch (bin->opcode & 0xF00) {
  609. case 0x200:
  610. stmt->u.insn.name = "srx";
  611. str = xmalloc(3);
  612. snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
  613. stmt->u.insn.operands[0] = str;
  614. str = xmalloc(3);
  615. snprintf(str, 3, "%d", (bin->opcode & 0x00F));
  616. stmt->u.insn.operands[1] = str;
  617. disasm_std_operand(stmt, 0, 2);
  618. disasm_std_operand(stmt, 1, 3);
  619. disasm_std_operand(stmt, 2, 4);
  620. break;
  621. case 0x300:
  622. stmt->u.insn.name = "orx";
  623. str = xmalloc(3);
  624. snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
  625. stmt->u.insn.operands[0] = str;
  626. str = xmalloc(3);
  627. snprintf(str, 3, "%d", (bin->opcode & 0x00F));
  628. stmt->u.insn.operands[1] = str;
  629. disasm_std_operand(stmt, 0, 2);
  630. disasm_std_operand(stmt, 1, 3);
  631. disasm_std_operand(stmt, 2, 4);
  632. break;
  633. case 0x400:
  634. stmt->u.insn.name = "jzx";
  635. str = xmalloc(3);
  636. snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
  637. stmt->u.insn.operands[0] = str;
  638. str = xmalloc(3);
  639. snprintf(str, 3, "%d", (bin->opcode & 0x00F));
  640. stmt->u.insn.operands[1] = str;
  641. disasm_std_operand(stmt, 0, 2);
  642. disasm_std_operand(stmt, 1, 3);
  643. stmt->u.insn.labelref_operand = 4;
  644. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  645. break;
  646. case 0x500:
  647. stmt->u.insn.name = "jnzx";
  648. str = xmalloc(3);
  649. snprintf(str, 3, "%d", (bin->opcode & 0x0F0) >> 4);
  650. stmt->u.insn.operands[0] = str;
  651. str = xmalloc(3);
  652. snprintf(str, 3, "%d", (bin->opcode & 0x00F));
  653. stmt->u.insn.operands[1] = str;
  654. disasm_std_operand(stmt, 0, 2);
  655. disasm_std_operand(stmt, 1, 3);
  656. stmt->u.insn.labelref_operand = 4;
  657. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  658. break;
  659. case 0x600:
  660. stmt->u.insn.name = "jnext";
  661. str = xmalloc(5);
  662. snprintf(str, 5, "0x%02X", (bin->opcode & 0x0FF));
  663. stmt->u.insn.operands[0] = str;
  664. /* We don't disassemble the first and second operand, as
  665. * that always is a dummy r0 operand.
  666. * disasm_std_operand(stmt, 0, 1);
  667. * disasm_std_operand(stmt, 1, 2);
  668. * stmt->u.insn.labelref_operand = 3;
  669. */
  670. stmt->u.insn.labelref_operand = 1;
  671. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  672. break;
  673. case 0x700:
  674. stmt->u.insn.name = "jext";
  675. str = xmalloc(5);
  676. snprintf(str, 5, "0x%02X", (bin->opcode & 0x0FF));
  677. stmt->u.insn.operands[0] = str;
  678. /* We don't disassemble the first and second operand, as
  679. * that always is a dummy r0 operand.
  680. * disasm_std_operand(stmt, 0, 1);
  681. * disasm_std_operand(stmt, 1, 2);
  682. * stmt->u.insn.labelref_operand = 3;
  683. */
  684. stmt->u.insn.labelref_operand = 1;
  685. stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
  686. break;
  687. default:
  688. disasm_constant_opcodes(ctx, stmt);
  689. break;
  690. }
  691. list_add_tail(&stmt->list, &ctx->stmt_list);
  692. }
  693. }
  694. static struct statement * get_label_at(struct disassembler_context *ctx,
  695. unsigned int addr)
  696. {
  697. unsigned int addrcnt = 0;
  698. struct statement *stmt, *ret, *prev;
  699. list_for_each_entry(stmt, &ctx->stmt_list, list) {
  700. if (stmt->type != STMT_INSN)
  701. continue;
  702. if (addrcnt == addr) {
  703. prev = list_entry(stmt->list.prev, struct statement, list);
  704. if (prev->type == STMT_LABEL)
  705. return prev;
  706. ret = xmalloc(sizeof(struct statement));
  707. INIT_LIST_HEAD(&ret->list);
  708. ret->type = STMT_LABEL;
  709. list_add(&ret->list, &prev->list);
  710. return ret;
  711. }
  712. addrcnt++;
  713. }
  714. return NULL;
  715. }
  716. static void resolve_labels(struct disassembler_context *ctx)
  717. {
  718. struct statement *stmt;
  719. struct statement *label;
  720. struct statement *n;
  721. unsigned int labeladdr;
  722. unsigned int namecnt = 0;
  723. /* Resolve label references */
  724. list_for_each_entry_safe(stmt, n, &ctx->stmt_list, list) {
  725. if (stmt->type != STMT_INSN)
  726. continue;
  727. if (stmt->u.insn.labelref_operand < 0)
  728. continue; /* Doesn't have label reference operand. */
  729. labeladdr = stmt->u.insn.labeladdr;
  730. label = get_label_at(ctx, labeladdr);
  731. if (!label)
  732. dasm_error("Labeladdress %X out of bounds", labeladdr);
  733. stmt->u.insn.labelref = label;
  734. }
  735. /* Name the labels */
  736. list_for_each_entry(stmt, &ctx->stmt_list, list) {
  737. if (stmt->type != STMT_LABEL)
  738. continue;
  739. stmt->u.label.name = xmalloc(20);
  740. snprintf(stmt->u.label.name, 20, "L%u", namecnt);
  741. namecnt++;
  742. }
  743. }
  744. static void emit_asm(struct disassembler_context *ctx)
  745. {
  746. struct statement *stmt;
  747. int first;
  748. int err;
  749. unsigned int i, addr = 0;
  750. err = open_output_file();
  751. if (err)
  752. exit(1);
  753. fprintf(outfile, "%%arch %u\n", ctx->arch);
  754. fprintf(outfile, "%%start entry\n\n");
  755. fprintf(outfile, "entry:\n");
  756. list_for_each_entry(stmt, &ctx->stmt_list, list) {
  757. switch (stmt->type) {
  758. case STMT_INSN:
  759. if (cmdargs.print_addresses)
  760. fprintf(outfile, "/* %04X */", addr);
  761. fprintf(outfile, "\t%s", stmt->u.insn.name);
  762. first = 1;
  763. for (i = 0; i < ARRAY_SIZE(stmt->u.insn.operands); i++) {
  764. if (!stmt->u.insn.operands[i] &&
  765. (stmt->u.insn.labelref_operand < 0 ||
  766. (unsigned int)stmt->u.insn.labelref_operand != i))
  767. continue;
  768. if (first)
  769. fprintf(outfile, "\t");
  770. if (!first)
  771. fprintf(outfile, ", ");
  772. first = 0;
  773. if (stmt->u.insn.labelref_operand >= 0 &&
  774. (unsigned int)stmt->u.insn.labelref_operand == i) {
  775. fprintf(outfile, "%s",
  776. stmt->u.insn.labelref->u.label.name);
  777. } else {
  778. fprintf(outfile, "%s",
  779. stmt->u.insn.operands[i]);
  780. }
  781. }
  782. fprintf(outfile, "\n");
  783. addr++;
  784. break;
  785. case STMT_LABEL:
  786. fprintf(outfile, "%s:\n", stmt->u.label.name);
  787. break;
  788. }
  789. }
  790. close_output_file();
  791. }
  792. static int read_input(struct disassembler_context *ctx)
  793. {
  794. size_t size = 0, pos = 0;
  795. size_t ret;
  796. struct bin_instruction *code = NULL;
  797. unsigned char tmp[sizeof(uint64_t)];
  798. uint64_t codeword = 0;
  799. struct fw_header hdr;
  800. int err;
  801. err = open_input_file();
  802. if (err)
  803. goto error;
  804. switch (cmdargs.informat) {
  805. case FMT_RAW_LE32:
  806. case FMT_RAW_BE32:
  807. /* Nothing */
  808. break;
  809. case FMT_B43:
  810. ret = fread(&hdr, 1, sizeof(hdr), infile);
  811. if (ret != sizeof(hdr)) {
  812. fprintf(stderr, "Corrupt input file (no b43 header found)\n");
  813. goto err_close;
  814. }
  815. if (hdr.type != FW_TYPE_UCODE) {
  816. fprintf(stderr, "Corrupt input file. Not a b43 microcode image.\n");
  817. goto err_close;
  818. }
  819. if (hdr.ver != FW_HDR_VER) {
  820. fprintf(stderr, "Invalid input file header version.\n");
  821. goto err_close;
  822. }
  823. break;
  824. }
  825. while (1) {
  826. if (pos >= size) {
  827. size += 512;
  828. code = xrealloc(code, size * sizeof(struct bin_instruction));
  829. }
  830. ret = fread(tmp, 1, sizeof(uint64_t), infile);
  831. if (!ret)
  832. break;
  833. if (ret != sizeof(uint64_t)) {
  834. fprintf(stderr, "Corrupt input file (not 8 byte aligned)\n");
  835. goto err_free_code;
  836. }
  837. switch (cmdargs.informat) {
  838. case FMT_B43:
  839. case FMT_RAW_BE32:
  840. codeword = 0;
  841. codeword |= ((uint64_t)tmp[0]) << 56;
  842. codeword |= ((uint64_t)tmp[1]) << 48;
  843. codeword |= ((uint64_t)tmp[2]) << 40;
  844. codeword |= ((uint64_t)tmp[3]) << 32;
  845. codeword |= ((uint64_t)tmp[4]) << 24;
  846. codeword |= ((uint64_t)tmp[5]) << 16;
  847. codeword |= ((uint64_t)tmp[6]) << 8;
  848. codeword |= ((uint64_t)tmp[7]);
  849. codeword = ((codeword & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
  850. ((codeword & (uint64_t)0x00000000FFFFFFFFULL) << 32);
  851. break;
  852. case FMT_RAW_LE32:
  853. codeword = 0;
  854. codeword |= ((uint64_t)tmp[7]) << 56;
  855. codeword |= ((uint64_t)tmp[6]) << 48;
  856. codeword |= ((uint64_t)tmp[5]) << 40;
  857. codeword |= ((uint64_t)tmp[4]) << 32;
  858. codeword |= ((uint64_t)tmp[3]) << 24;
  859. codeword |= ((uint64_t)tmp[2]) << 16;
  860. codeword |= ((uint64_t)tmp[1]) << 8;
  861. codeword |= ((uint64_t)tmp[0]);
  862. break;
  863. }
  864. switch (cmdargs.arch) {
  865. case 5:
  866. if (codeword >> 48) {
  867. fprintf(stderr, "Instruction format error at 0x%X (upper not clear). "
  868. "Wrong input format or architecture?\n", (unsigned int)pos);
  869. goto err_free_code;
  870. }
  871. code[pos].opcode = (codeword >> 36) & 0xFFF;
  872. code[pos].operands[2] = codeword & 0xFFF;
  873. code[pos].operands[1] = (codeword >> 12) & 0xFFF;
  874. code[pos].operands[0] = (codeword >> 24) & 0xFFF;
  875. break;
  876. case 15:
  877. if (codeword >> 51) {
  878. fprintf(stderr, "Instruction format error at 0x%X (upper not clear). "
  879. "Wrong input format or architecture?\n", (unsigned int)pos);
  880. goto err_free_code;
  881. }
  882. code[pos].opcode = (codeword >> 39) & 0xFFF;
  883. code[pos].operands[2] = codeword & 0x1FFF;
  884. code[pos].operands[1] = (codeword >> 13) & 0x1FFF;
  885. code[pos].operands[0] = (codeword >> 26) & 0x1FFF;
  886. break;
  887. default:
  888. fprintf(stderr, "Internal error: read_input unknown arch %u\n",
  889. cmdargs.arch);
  890. goto err_free_code;
  891. }
  892. pos++;
  893. }
  894. ctx->code = code;
  895. ctx->nr_insns = pos;
  896. close_input_file();
  897. return 0;
  898. err_free_code:
  899. free(code);
  900. err_close:
  901. close_input_file();
  902. error:
  903. return -1;
  904. }
  905. static void disassemble(void)
  906. {
  907. struct disassembler_context ctx;
  908. int err;
  909. memset(&ctx, 0, sizeof(ctx));
  910. INIT_LIST_HEAD(&ctx.stmt_list);
  911. ctx.arch = cmdargs.arch;
  912. err = read_input(&ctx);
  913. if (err)
  914. exit(1);
  915. disasm_opcodes(&ctx);
  916. resolve_labels(&ctx);
  917. emit_asm(&ctx);
  918. }
  919. int main(int argc, char **argv)
  920. {
  921. int err, res = 1;
  922. err = parse_args(argc, argv);
  923. if (err < 0)
  924. goto out;
  925. if (err > 0) {
  926. res = 0;
  927. goto out;
  928. }
  929. disassemble();
  930. res = 0;
  931. out:
  932. /* Lazyman simply leaks all allocated memory. */
  933. return res;
  934. }