MipsProcessor.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. /*
  2. * To change this license header, choose License Headers in Project Properties.
  3. * To change this template file, choose Tools | Templates
  4. * and open the template in the editor.
  5. */
  6. package tools.mips;
  7. import API.Utils;
  8. import common.Instruction;
  9. import java.io.BufferedReader;
  10. import java.io.InputStreamReader;
  11. import java.util.HashMap;
  12. import java.util.Map;
  13. import java.util.logging.Level;
  14. import java.util.logging.Logger;
  15. import targets.mips.Mips;
  16. /**
  17. *
  18. * @author EUGENIO CARVALHO
  19. */
  20. public class MipsProcessor {
  21. public String ID = "default";
  22. public MipsSettings settings;
  23. public Memory MD;
  24. public Memory MI;
  25. public long PC = 0;
  26. public RegisterBank RBank;
  27. public HashMap<String, Instruction> instructions;
  28. public HashMap<String, Boolean> breakPoint = new HashMap<>();
  29. public MipsProcessor(MipsSettings settings) throws Exception {
  30. this.settings = new MipsSettings();
  31. this.settings.S("debugmode", "true").S("stepByStep", "false");
  32. MI = new Memory(
  33. settings.G("memory.instruction"),
  34. settings.getInt("memory.instruction.size"),
  35. false
  36. );
  37. MD = new Memory(
  38. settings.G("memory.data"),
  39. settings.getInt("memory.data.size"),
  40. true
  41. );
  42. // Limpa todos os dados armazenados
  43. // MD.Reset();
  44. // System.out.println("Init Md:" + MD.R(0L));
  45. RBank = new RegisterBank(32);
  46. InitInstructions();
  47. this.settings.copy(
  48. "debugmode,"
  49. + "mode,"
  50. + "stepByStep,"
  51. + "breakpoints,"
  52. + "memory.instruction,"
  53. + "memory.instruction.size,"
  54. + "memory.data,"
  55. + "memory.data.size",
  56. settings);
  57. SetBreak(this.settings.G("breakpoints"));
  58. // SetBreak("44,48,58,5c");
  59. // InitInstructions2();
  60. }
  61. public MipsProcessor SetBreak(String address) {
  62. for (String addr : address.split(",")) {
  63. if (!addr.equals("")) {
  64. breakPoint.put(addr, true);
  65. }
  66. }
  67. return this;
  68. }
  69. public MipsProcessor Persist() {
  70. MD.Save();
  71. return this;
  72. }
  73. protected void Log(String msg) {
  74. if (!settings.eq("mode", "debug")) {
  75. return;
  76. }
  77. if (breakPoint.size() > 0 && !breakPoint.containsKey(Integer.toHexString((int) PC))) {
  78. return;
  79. }
  80. System.out.println(msg);
  81. }
  82. public MipsProcessor Run() {
  83. BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  84. // Fetch
  85. // System.out.println("MI:" + MI);
  86. System.out.println("Start simulation ... " + ID);
  87. System.out.println();
  88. try {
  89. Instruction instruction;
  90. int i = 0;
  91. String cAddress;
  92. while (true) {
  93. long inst = MI.R(PC);
  94. instruction = Decode(inst);
  95. if (instruction.eq("inst", "stop")) {
  96. break;
  97. }
  98. cAddress = Integer.toHexString((int) PC);
  99. Log("Interation(" + (i++) + ")["
  100. + cAddress + "]"
  101. + instruction.G("inst"));
  102. Execute(instruction);
  103. Log("Registradores(\n" + RBank
  104. + ")\b nextPC:" + Integer.toHexString((int) PC));
  105. if (settings.eq("stepByStep", "true")
  106. || breakPoint.containsKey(cAddress)) {
  107. br.readLine();
  108. }
  109. // Decode
  110. // Exec
  111. // Persist
  112. } // return true;
  113. } catch (Exception ex) {
  114. Logger.getLogger(MipsProcessor.class.getName()).log(Level.SEVERE, null, ex);
  115. }
  116. return this;
  117. }
  118. public Instruction Decode(long instruction) {
  119. int val = (int) instruction;
  120. String bin = Utils.pad(32, Integer.toBinaryString(val));
  121. // System.out.println("Run:" + bin + ":" + bin.length());
  122. String codop = bin.substring(0, 6), key, func = "";
  123. if (codop.equals("000000")) {
  124. func = bin.substring(26);
  125. key = "@" + func;
  126. } else {
  127. key = codop;
  128. }
  129. // System.out.println(">>: "
  130. // // + "\n" + instruction
  131. // + "\n" + bin
  132. // // // + "\n" + val
  133. // // + "\nKey:" + key
  134. // + "\n" + instructions.get(key));
  135. if (!instructions.containsKey(key)) {
  136. System.out.println("Não encontrou a instrução " + key);
  137. return null;
  138. }
  139. Instruction i = instructions.get(key).copy();
  140. String rs = bin.substring(6, 11),
  141. rt = bin.substring(11, 16);
  142. switch (i.G("type")) {
  143. case "R":
  144. i.S("rs.bin", rs);
  145. i.S("rt.bin", rt);
  146. i.S("rd.bin", bin.substring(16, 21));
  147. i.S("shamt.bin", bin.substring(21, 26));
  148. i.S("funct.bin", func);
  149. i.S("rs", Long.parseLong(rs, 2));
  150. i.S("rt", Long.parseLong(rt, 2));
  151. i.S("rd", Long.parseLong(bin.substring(16, 21), 2));
  152. i.S("shamt", Long.parseLong(bin.substring(21, 26), 2));
  153. i.S("funct", func);
  154. break;
  155. case "I":
  156. i.S("rs.bin", rs);
  157. i.S("rt.bin", rt);
  158. i.S("imm.bin", bin.substring(16));
  159. i.S("rs", Long.parseLong(rs, 2));
  160. i.S("rt", Long.parseLong(rt, 2));
  161. i.S("imm", bin32ToDec(bin.substring(16)));
  162. // System.out.println("II:" + bin.substring(16)
  163. // + "\n:" + bin32ToDec(Utils.padPreserveSignal(32, bin.substring(16)))
  164. // + "\n:" + (Long.parseLong(Utils.padPreserveSignal(32, bin.substring(16)), 2) >> 0)
  165. // );
  166. // System.out.println("IIII:" + bin32ToDec(bin.substring(16)));
  167. break;
  168. case "J":
  169. i.S("addr.bin", bin.substring(6));
  170. i.S("imm", bin32ToDec(bin.substring(6)));
  171. // System.out.println("JJJJ:" + bin32ToDec(bin.substring(6)));
  172. }
  173. return i;
  174. }
  175. public static long bin32ToDec(String bin) {
  176. bin = Utils.padPreserveSignal(32, bin);
  177. // System.out.println("BIN32DEC:" + bin);
  178. if (bin.charAt(0) == '0') {
  179. return Long.parseLong(bin, 2);
  180. } else {
  181. long number = 0;
  182. for (int index = 0; index < 32; index++) {
  183. int b = bin.charAt(index) - '0';
  184. number = number << 1 | b;
  185. }
  186. return (int) number;
  187. }
  188. }
  189. public String IntToHexStr(Integer n) {
  190. return IntToHexStr(n) + "";
  191. }
  192. public Integer IntToHex(Integer n) {
  193. return Integer.valueOf(String.valueOf(n), 16);
  194. }
  195. protected void InitInstructions() {
  196. instructions = new HashMap<String, Instruction>();
  197. String key;
  198. for (Map.Entry<String, Instruction> entry : Mips.Codops.entrySet()) {
  199. // String string = entry.getKey();
  200. Instruction instruction = entry.getValue();
  201. key = instruction.G("codop");
  202. if (instruction.eq("codop", "000000")) {
  203. key = "@" + instruction.G("func");
  204. }
  205. // System.out.println("Add_Instruction: " + key + "\n");
  206. // System.out.println("===" + entry.getKey());
  207. instructions.put(key, instruction);
  208. };
  209. }
  210. private void Execute(Instruction inst) throws Exception {
  211. // System.out.println("Exec :" + inst);
  212. long rs = 0,
  213. rt = 0,
  214. imm = 0,
  215. rd = 0,
  216. shamt = 0;
  217. boolean hasImm = true;
  218. switch (inst.G("type")) {
  219. case "R":
  220. rd = inst.getInt("rd");
  221. shamt = inst.getInt("shamt");
  222. hasImm = false;
  223. case "I":
  224. rs = inst.getInt("rs");
  225. rt = inst.getInt("rt");
  226. case "J":
  227. if (hasImm) {
  228. // System.out.println("HAS_IMM:" + inst.G("imm"));
  229. imm = inst.getLong("imm");
  230. }
  231. }
  232. Log(inst.G("inst")
  233. + " [rd:" + RBank.names.get((int) rd)
  234. + "] [rs:" + RBank.names.get((int) rs)
  235. + "] [rt:" + RBank.names.get((int) rt)
  236. + "] [shamt:" + shamt
  237. + "] [imm:" + imm + "]");
  238. switch (inst.G("inst")) {
  239. // R
  240. case "add":
  241. case "addu":
  242. RBank.W(rd, RBank.R(rs) + RBank.R(rt));
  243. break;
  244. case "addi":
  245. case "addiu":
  246. // System.out.println("RBank.R(rs) + imm:" + RBank.R(rs) + ":" + imm);
  247. RBank.W(rt, RBank.R(rs) + imm);
  248. break;
  249. case "stop":
  250. break;
  251. case "and":
  252. case "andi":
  253. RBank.W(rd, RBank.R(rs) & RBank.R(rt));
  254. break;
  255. case "div":
  256. case "divu":
  257. RBank.W(RBank.REG_LO, RBank.R(rs) / RBank.R(rt));
  258. RBank.W(RBank.REG_HI, RBank.R(rs) % RBank.R(rt));
  259. break;
  260. case "jr":
  261. PC = RBank.R(rs);
  262. break;
  263. case "mfhi":
  264. RBank.W(rd, RBank.R(RBank.REG_HI));
  265. break;
  266. case "mflo":
  267. RBank.W(rd, RBank.R(RBank.REG_LO));
  268. break;
  269. case "mthi":
  270. RBank.W(RBank.R(RBank.REG_HI), RBank.R(rs));
  271. break;
  272. case "mtlo":
  273. RBank.W(RBank.R(RBank.REG_LO), RBank.R(rs));
  274. break;
  275. case "mult":
  276. case "multu":
  277. // verificar a questao do hi e lo
  278. // System.out.println("Mult:"
  279. // + rs + "(" + RBank.names.get((int) rs) + "):"
  280. // + rt + "(" + RBank.names.get((int) rt) + ")");
  281. RBank.W(RBank.REG_LO, RBank.R(rs) * RBank.R(rt));
  282. break;
  283. // case "nor":
  284. // RBank.W(rd, rs * rt);
  285. // break;
  286. case "or":
  287. RBank.W(rd, RBank.R(rs) | RBank.R(rt));
  288. break;
  289. case "sll":
  290. RBank.W(rd, RBank.R(rt) << shamt);
  291. break;
  292. case "slt":
  293. RBank.W(rd, (RBank.R(rs) < RBank.R(rt)) ? 1 : 0);
  294. break;
  295. case "sra":
  296. RBank.W(rd, RBank.R(rt) >> shamt);
  297. break;
  298. case "srl":
  299. RBank.W(rd, RBank.R(rt) >>> shamt);
  300. break;
  301. case "sub":
  302. case "subu":
  303. RBank.W(rd, RBank.R(rs) - RBank.R(rt));
  304. break;
  305. case "xor":
  306. RBank.W(rd, RBank.R(rs) ^ RBank.R(rt));
  307. break;
  308. // // I
  309. case "beq":
  310. if (RBank.R(rs) == RBank.R(rt)) {
  311. PC += ((imm + 1) << 2);
  312. return;
  313. }
  314. break;
  315. case "bgez":
  316. if (RBank.R(rs) >= 0) {
  317. PC += ((imm + 1) << 2);
  318. return;
  319. }
  320. break;
  321. case "bgtz":
  322. if (RBank.R(rs) > 0) {
  323. PC += ((imm + 1) << 2);
  324. return;
  325. }
  326. break;
  327. case "blez":
  328. if (RBank.R(rs) <= 0) {
  329. PC += ((imm + 1) << 2);
  330. return;
  331. }
  332. break;
  333. case "bltz":
  334. // System.out.println("BLTZ:" + rs);
  335. if (RBank.R(rs) < 0) {
  336. PC += ((imm + 1) << 2);
  337. return;
  338. }
  339. break;
  340. case "bne":
  341. if (RBank.R(rs) != RBank.R(rt)) {
  342. PC += ((imm + 1) << 2);
  343. return;
  344. }
  345. break;
  346. // case "lb":
  347. // if (RBank.R(rs) != RBank.R(rt)) {
  348. // PC += imm << 2;
  349. // return;
  350. // }
  351. // case "lbu":
  352. // case "lh":
  353. // case "lhu":
  354. case "lui":
  355. RBank.W(rt, imm);
  356. break;
  357. case "lw":
  358. RBank.W(rt, MD.R(RBank.R(rs) + imm));
  359. Log(String.format("Load endereco '%d' <- '%d'\n", RBank.R(rs) + imm, MD.R(RBank.R(rs) + imm)));
  360. break;
  361. case "ori":
  362. RBank.W(rt, RBank.R(rs) | imm);
  363. break;
  364. case "slti":
  365. // case "sltiu":
  366. case "sw":
  367. Log(String.format("Store '%d' no endereco '%d'\n", RBank.R(rt), RBank.R(rs) + imm));
  368. MD.W(RBank.R(rs) + imm, RBank.R(rt));
  369. break;
  370. // case "xori":
  371. // J
  372. case "jal":
  373. RBank.W(31, PC);
  374. case "j":
  375. PC = imm << 2;
  376. return;
  377. default:
  378. throw new Exception("Instrução " + inst.G("inst") + " não definida!");
  379. }
  380. PC += 4;
  381. }
  382. }
  383. // protected void InitInstructions2() {
  384. // HashMap<String, Integer> x = new HashMap<String, Integer>();
  385. // //Constantes da instruções (Codop e Funct)
  386. // x.put("FUNCT_ADD", 32);
  387. // x.put("FUNCT_ADDU", 33);
  388. // x.put("FUNCT_SUB", 34);
  389. // x.put("FUNCT_SUBU", 35);
  390. // x.put("FUNCT_MULT", 24);
  391. // x.put("FUNCT_MULTU", 25);
  392. // x.put("FUNCT_AND", 36);
  393. // x.put("FUNCT_OR", 37);
  394. // x.put("FUNCT_XOR", 38);
  395. // x.put("FUNCT_NOR", 39);
  396. // x.put("FUNCT_DIV", 26);
  397. // x.put("FUNCT_DIVU", 27);
  398. // x.put("FUNCT_SLT", 42);
  399. //
  400. // x.put("FUNCT_SRL", 2);
  401. // x.put("FUNCT_SLL", 0);
  402. // x.put("FUNCT_SRA", 3);
  403. // x.put("FUNCT_SRLV", 6);
  404. // x.put("FUNCT_SLLV", 4);
  405. // x.put("FUNCT_SRAV", 7);
  406. //
  407. // x.put("FUNCT_MFHI", 16);
  408. // x.put("FUNCT_MFLO", 18);
  409. // x.put("FUNCT_JR", 8);
  410. //
  411. // x.put("FUNCT_NOP", 63);
  412. // x.put("NOP", 63);
  413. //
  414. ////Constante dos CODOPs
  415. // x.put("CODOP_ADDI", 8);
  416. // x.put("CODOP_ADDIU", 9);
  417. // x.put("CODOP_SLTI", 10);
  418. // x.put("CODOP_SLTIU", 11);
  419. // x.put("CODOP_ANDI", 12);
  420. // x.put("CODOP_ORI", 13);
  421. // x.put("CODOP_LUI", 15);
  422. //
  423. // x.put("CODOP_LB", 32);
  424. // x.put("CODOP_LH", 33);
  425. // x.put("CODOP_LW", 35);
  426. // x.put("CODOP_LBU", 36);
  427. // x.put("CODOP_LHU", 37);
  428. // x.put("CODOP_SB", 40);
  429. // x.put("CODOP_SH", 41);
  430. // x.put("CODOP_SW", 43);
  431. //
  432. // x.put("CODOP_BGEZ", 1);
  433. // x.put("CODOP_BEQ", 4);
  434. // x.put("CODOP_BNE", 5);
  435. // x.put("CODOP_BGTZ", 7);
  436. //
  437. // x.put("CODOP_JUMP", 2);
  438. // x.put("CODOP_JAL", 3);
  439. //
  440. // x.put("CODOP_STOP", 63);
  441. ////Constante das operações da ULA
  442. // x.put("SOMA", 1);
  443. // x.put("SUBTRACAO", 2);
  444. // x.put("MULTIPLICACAO", 3);
  445. // x.put("AND", 4);
  446. // x.put("OR", 5);
  447. // x.put("XOR", 6);
  448. // x.put("NOR", 7);
  449. // x.put("DIVISAO", 8);
  450. // x.put("SLT", 9);
  451. // x.put("SLTU", 10);
  452. // x.put("LUI", 11);
  453. //
  454. // x.put("SRL", 12); //Faz o shift usando o campo shamt
  455. // x.put("SLL", 13); //Faz o shift usando o campo shamt
  456. // x.put("SRA", 14); //Faz o shift usando o campo shamt
  457. //
  458. // x.put("SRLV", 15); //Faz o shift usando registrador
  459. // x.put("SLLV", 16); //Faz o shift usando registrador
  460. // x.put("SRAV", 17); //Faz o shift usando registrador
  461. // x.put("MOVE", 18);
  462. //
  463. // for (Map.Entry<String, Integer> entry : x.entrySet()) {
  464. // String string = entry.getKey();
  465. // System.out.println(string + ":" + Utils.pad(6, Integer.toBinaryString(entry.getValue())));
  466. // }
  467. // }
  468. //CODOP_JUMP:000010
  469. //CODOP_LBU:100100
  470. //NOP:111111
  471. //CODOP_STOP:111111
  472. //FUNCT_DIVU:011011
  473. //CODOP_LH:100001
  474. //MULTIPLICACAO:000011
  475. //SRLV:001111
  476. //NOR:000111
  477. //SLL:001101
  478. //FUNCT_SRA:000011
  479. //CODOP_ANDI:001100
  480. //AND:000100
  481. //FUNCT_SRL:000010
  482. //CODOP_ORI:001101
  483. //SRAV:010001
  484. //SLT:001001
  485. //SUBTRACAO:000010
  486. //CODOP_LW:100011
  487. //FUNCT_ADD:100000
  488. //SOMA:000001
  489. //FUNCT_MULTU:011001
  490. //CODOP_SLTI:001010
  491. //SLLV:010000
  492. //SLTU:001010
  493. //FUNCT_MULT:011000
  494. //CODOP_ADDIU:001001
  495. //LUI:001011
  496. //CODOP_SH:101001
  497. //XOR:000110
  498. //FUNCT_MFLO:010010
  499. //FUNCT_SRAV:000111
  500. //DIVISAO:001000
  501. //SRL:001100
  502. //SRA:001110
  503. //CODOP_SB:101000
  504. //CODOP_ADDI:001000
  505. //FUNCT_JR:001000
  506. //FUNCT_MFHI:010000
  507. //FUNCT_NOR:100111
  508. //FUNCT_NOP:111111
  509. //FUNCT_SUBU:100011
  510. //FUNCT_OR:100101
  511. //FUNCT_AND:100100
  512. //FUNCT_XOR:100110
  513. //FUNCT_DIV:011010
  514. //FUNCT_SRLV:000110
  515. //FUNCT_ADDU:100001
  516. //CODOP_LUI:001111
  517. //CODOP_BGEZ:000001
  518. //MOVE:010010
  519. //CODOP_SLTIU:001011
  520. //CODOP_JAL:000011
  521. //OR:000101
  522. //CODOP_SW:101011
  523. //FUNCT_SUB:100010
  524. //FUNCT_SLLV:000100
  525. //CODOP_LB:100000
  526. //CODOP_BNE:000101
  527. //FUNCT_SLL:000000
  528. //CODOP_LHU:100101
  529. //CODOP_BGTZ:000111
  530. //CODOP_BEQ:000100
  531. //FUNCT_SLT:101010
  532. /*
  533. 1652044928
  534. 1100010011110000011010010000000
  535. 1100010011110000011010010000000
  536. 011000 10011110000011010010000000
  537. 011000
  538. 596080229
  539. 00100011100001110111011001100101 - js
  540. 100011100001110111011001100101
  541. c
  542. 10010110000010000000001000101001
  543. */
  544. //1652044928 -> 01010010000001000100100100101000 ->
  545. //0: 0062783480 addiu sp,sp,-8