PageRenderTime 28ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/lab4/pdp8.c

https://gitlab.com/jhw866/cs429
C | 654 lines | 485 code | 56 blank | 113 comment | 230 complexity | 4fc493487052aa32f16a47cd9b438105 MD5 | raw file
  1. /* Name of Program pdp8.c */
  2. /* Program Description: Simulates a 12-bit pdp8 machine when given and object file */
  3. /* Name Jeremy Wenzel */
  4. /* CSID/EID jhw866 */
  5. /* Section number: 53865 */
  6. /* Last update: 10/27/2013 23:30 */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. typedef short Boolean;
  11. #define TRUE 1;
  12. #define FALSE 0;
  13. int time = 0;
  14. short ep_found = 0;
  15. short skip;
  16. short memory[4096] = {0};
  17. short pc;
  18. short accumulator;
  19. short link_bit;
  20. short rotated = 0;
  21. short halt = 0;
  22. short indirect = 0;
  23. short dev = 0;
  24. short mode = 0;
  25. /* If this is called, we start writing to stderr with the verbose */
  26. /* Input: None */
  27. /* Return: None */
  28. void verbose(short opcode) {
  29. char str[30] = {0};
  30. short group;
  31. short placed = 0;
  32. short check = 0;
  33. short one_two = 0;
  34. /* For memory reference instructions */
  35. if(opcode == 0)
  36. strcat(str, "AND");
  37. if(opcode == 1)
  38. strcat(str, "TAD");
  39. if(opcode == 2)
  40. strcat(str, "ISZ");
  41. if(opcode == 3)
  42. strcat(str, "DCA");
  43. if(opcode == 4)
  44. strcat(str, "JMS");
  45. if(opcode == 5)
  46. strcat(str, "JMP");
  47. /* For Input/Output Instructions */
  48. if(opcode == 6) {
  49. if(dev == 3)
  50. strcat(str, "IOT 3");
  51. else if(dev == 4)
  52. strcat(str, "IOT 4");
  53. else
  54. fprintf(stderr, "IOT <bad-device>");
  55. }
  56. if(opcode == 7) {
  57. group = (memory[pc] >> 8) & 1;
  58. if(group == 0) {
  59. // Write CLA
  60. check = (memory[pc] >> 7) & 1;
  61. if(check == 1) {
  62. strcat(str, "CLA");
  63. placed = 1;
  64. }
  65. // write CLL
  66. check = (memory[pc] >> 6) & 1;
  67. if(check == 1) {
  68. if(placed == 1)
  69. strcat(str, " ");
  70. strcat(str, "CLL");
  71. placed = 1;
  72. }
  73. // Write CMA
  74. check = (memory[pc] >> 5) & 1;
  75. if(check == 1) {
  76. if(placed == 1)
  77. strcat(str, " ");
  78. strcat(str, "CMA");
  79. placed = 1;
  80. }
  81. // Write CML
  82. check = (memory[pc] >> 4) & 1;
  83. if(check == 1) {
  84. if(placed == 1)
  85. strcat(str, " ");
  86. strcat(str, "CML");
  87. placed = 1;
  88. }
  89. // Write IAC
  90. check = memory[pc] & 1;
  91. if(check == 1) {
  92. if(placed == 1)
  93. strcat(str, " ");
  94. strcat(str, "IAC");
  95. placed = 1;
  96. }
  97. // Write Rotate Right (Don't forget to do both)
  98. one_two = (memory[pc] >> 1) & 1;
  99. check = (memory[pc] >> 3) & 1;
  100. if(check == 1) {
  101. if(placed == 1)
  102. strcat(str, " ");
  103. if(one_two == 1)
  104. strcat(str, "RTR");
  105. else
  106. strcat(str, "RAR");
  107. placed = 1;
  108. }
  109. // Write Rotate Left (Don't forget to do both)
  110. check = (memory[pc] >> 2) & 1;
  111. if(check == 1) {
  112. if(placed == 1)
  113. strcat(str, " ");
  114. if(one_two == 1)
  115. strcat(str, "RTL");
  116. else
  117. strcat(str, "RAL");
  118. placed = 1;
  119. }
  120. }
  121. else if(group == 1) {
  122. // Write SMA
  123. check = (memory[pc] >> 6) & 1;
  124. if(check == 1) {
  125. if(placed == 1)
  126. strcat(str, " ");
  127. strcat(str, "SMA");
  128. placed = 1;
  129. }
  130. // Write SZA
  131. check = (memory[pc] >> 5) & 1;
  132. if(check == 1) {
  133. if(placed == 1)
  134. strcat(str, " ");
  135. strcat(str, "SZA");
  136. placed = 1;
  137. }
  138. // Write SNL
  139. check = (memory[pc] >> 4) & 1;
  140. if(check == 1) {
  141. if(placed == 1)
  142. strcat(str, " ");
  143. strcat(str, "SNL");
  144. placed = 1;
  145. }
  146. // Write RSS
  147. check = (memory[pc] >> 3) & 1;
  148. if(check == 1) {
  149. if(placed == 1)
  150. strcat(str, " ");
  151. strcat(str, "RSS");
  152. placed = 1;
  153. }
  154. // Write CLA
  155. check = (memory[pc] >> 7) & 1;
  156. if(check == 1) {
  157. if(placed == 1)
  158. strcat(str, " ");
  159. strcat(str, "CLA");
  160. placed = 1;
  161. }
  162. // Write HLT
  163. check = (memory[pc] >> 1) & 1;
  164. if(check == 1) {
  165. if(placed == 1)
  166. strcat(str, " ");
  167. strcat(str, "HLT");
  168. placed = 1;
  169. }
  170. }
  171. else {
  172. fprintf(stderr, "We have a problem in verbose op 7");
  173. exit(-1);
  174. }
  175. }
  176. if(indirect == 1) {
  177. strcat(str, " I");
  178. indirect = 0;
  179. }
  180. fprintf(stderr, "Time %i: PC=0x%03X instruction = 0x%03X (%s), rA = 0x%03X, rL = %i\n", time, pc, memory[pc], str, accumulator, link_bit);
  181. }
  182. /* Memory Reference call for the PDP-8 Instructions. Determines if input/direct, */
  183. /* Zero/Current Page and does all opcodes 0-5, which are AND, TAD, ISZ, DCA, JMS, JMP */
  184. /* Input: Opcode, which should be 0-5 */
  185. /* Return: None */
  186. void simple(short opcode) {
  187. short check_link = 0;
  188. short d_i;
  189. short z_c;
  190. short address;
  191. short value;
  192. // get D/I bit
  193. d_i = (memory[pc] >> 8) & 1;
  194. // get Z/C
  195. z_c = (memory[pc] >> 7) & 1;
  196. // check if zero or current
  197. if(z_c == 0)
  198. address = (memory[pc] & 127);
  199. else {
  200. z_c = pc & 3968;
  201. address = z_c + (memory[pc] & 127);
  202. }
  203. // check D/I bit
  204. if(d_i == 0)
  205. value = memory[address];
  206. else {
  207. address = memory[address];
  208. value = memory[address];
  209. indirect = 1;
  210. }
  211. // ANDING
  212. if(opcode == 0) {
  213. accumulator = value & accumulator;
  214. if(d_i == 0)
  215. time = time + 2;
  216. else
  217. time = time + 3;
  218. if(mode == 1)
  219. verbose(opcode);
  220. }
  221. // Two's complement add
  222. if(opcode == 1) {
  223. accumulator = value + accumulator;
  224. // if overflow set link to 1
  225. check_link = (accumulator & (1 << 12)) >> 12;
  226. accumulator = accumulator & 4095;
  227. if(check_link == 1)
  228. link_bit = ~link_bit & 1;
  229. if(d_i == 0)
  230. time = time + 2;
  231. else
  232. time = time + 3;
  233. if(mode == 1)
  234. verbose(opcode);
  235. }
  236. // Increment and skip if zero
  237. if(opcode == 2) {
  238. // increment
  239. value++;
  240. value = value & 4095;
  241. memory[address] = value;
  242. if(value == 0)
  243. skip = 1;
  244. if(d_i == 0)
  245. time = time + 2;
  246. else
  247. time = time + 3;
  248. if(mode == 1)
  249. verbose(opcode);
  250. }
  251. // Deposit and clear accumulator
  252. if(opcode == 3) {
  253. memory[address] = accumulator;
  254. accumulator = 0;
  255. if(d_i == 0)
  256. time = time + 2;
  257. else
  258. time = time + 3;
  259. if(mode == 1)
  260. verbose(opcode);
  261. }
  262. // jump to subroutine
  263. if(opcode == 4) {
  264. if(d_i == 0)
  265. time = time + 2;
  266. else
  267. time = time + 3;
  268. if(mode == 1)
  269. verbose(opcode);
  270. memory[address] = pc + 1;
  271. pc = address;
  272. }
  273. // just jump
  274. if(opcode == 5) {
  275. if(d_i == 0)
  276. time = time + 1;
  277. else
  278. time = time + 2;
  279. if(mode == 1)
  280. verbose(opcode);
  281. pc = address - 1;
  282. }
  283. }
  284. /* Device call for the PDP-8 Instructions. Determines if printing to stdout, */
  285. /* or taking something in from stdin */
  286. /* Input: Opcode, which should be 6 */
  287. /* Return: None */
  288. void devices(short opcode) {
  289. short device = (memory[pc] & (31 << 3)) >> 3;
  290. char output;
  291. time = time + 1;
  292. // we are reading in from stdin
  293. if(device == 3) {
  294. accumulator = getc(stdin);
  295. accumulator = accumulator & 4095;
  296. dev = 3;
  297. }
  298. // we are outputting to stdout
  299. else if(device == 4) {
  300. output = accumulator & 255;
  301. fprintf(stdout, "%c", output);
  302. dev = 4;
  303. }
  304. else {
  305. fprintf(stderr, "IOT to unknown device %i; halting\n", device);
  306. halt = 1;
  307. }
  308. if(mode == 1)
  309. verbose(opcode);
  310. }
  311. /* Group 0 for opcode 7 subinstruction. Checks all subinstructions in order: */
  312. /* CLA, CLL, CMA, CML, IAC, RAR, RTR, RAL, RTL */
  313. /* Input: None */
  314. /* Return: None */
  315. void group0(void) {
  316. int rotate = 0;
  317. // clearing the accumulator
  318. int check = (memory[pc] >> 7) & 1;
  319. if(check == 1) {
  320. accumulator = 0;
  321. }
  322. // clearing the link bit
  323. check = (memory[pc] >> 6) & 1;
  324. if(check == 1) {
  325. link_bit = 0;
  326. }
  327. // complement Accumulator
  328. check = (memory[pc] >> 5) & 1;
  329. if(check == 1) {
  330. accumulator = (accumulator ^ 4095);
  331. }
  332. // complement link_bit
  333. check = (memory[pc] >> 4) & 1;
  334. if(check == 1) {
  335. link_bit = ~link_bit & 1;
  336. }
  337. // increment Accumulator
  338. check = (memory[pc] & 1);
  339. if(check == 1) {
  340. accumulator = accumulator + 1;
  341. // do we check for overflow?
  342. check = (accumulator >> 12) & 1;
  343. accumulator = accumulator & 4095;
  344. if(check == 1)
  345. link_bit = ~link_bit & 1;
  346. }
  347. // how many rotations
  348. check = (memory[pc] >> 1) & 1;
  349. if(check == 1)
  350. rotate = 2;
  351. else
  352. rotate = 1;
  353. // rotate Accumulator RIGHT
  354. check = (memory[pc] >> 3) & 1;
  355. if(check == 1) {
  356. rotated = 1;
  357. while(rotate > 0) {
  358. link_bit = accumulator & 1;
  359. accumulator = accumulator >> 1;
  360. accumulator = accumulator + (link_bit << 11);
  361. rotate--;
  362. }
  363. }
  364. // rotate Accumulator LEFT
  365. check = (memory[pc] >> 2) & 1;
  366. if(check == 1) {
  367. if(rotated == 1) {
  368. fprintf(stderr, "Instruction has been rotated. Halting\n");
  369. halt = 1;
  370. }
  371. while(rotate > 0) {
  372. accumulator = accumulator << 1;
  373. accumulator = accumulator & 4095;
  374. accumulator = accumulator + link_bit;
  375. rotate--;
  376. }
  377. }
  378. time = time + 1;
  379. }
  380. /* Group 1 for opcode 7 subinstruction. Checks all subinstructions in order: */
  381. /* SMA, SZA, SNL, RSS, CMA, OSR (ignored), HLT */
  382. /* Input: None */
  383. /* Return: None */
  384. void group1(void) {
  385. // check SMA (skip if accumulator is negative number)
  386. int x;
  387. int check = (memory[pc] >> 6) & 1;
  388. if(check == 1) {
  389. x = (accumulator >> 11) & 1;
  390. if(x == 1)
  391. skip = 1;
  392. }
  393. // check SZA (skip if zero accumulator)
  394. check = (memory[pc] >> 5) & 1;
  395. if(check == 1) {
  396. if(accumulator == 0)
  397. skip = 1;
  398. }
  399. // check SNL (skip if link_bit is non-zero)
  400. check = (memory[pc] >> 4) & 1;
  401. if(check != 0) {
  402. if(link_bit != 0)
  403. skip = 1;
  404. }
  405. // check RSS (complement skip flag)
  406. check = (memory[pc] >> 3) & 1;
  407. if(check == 1) {
  408. skip = ~skip & 1;
  409. }
  410. // clearing the accumulator
  411. check = (memory[pc] >> 7) & 1;
  412. if(check == 1)
  413. accumulator = 0;
  414. // if OSR (treat as NOP)
  415. // Halting
  416. check = (memory[pc] >> 1) & 1;
  417. if(check == 1) {
  418. halt = 1;
  419. }
  420. time = time + 1;
  421. }
  422. /* Operate instruction. Checks whether group 0 or group 1 */
  423. /* and then sends to corresponding functions */
  424. /* Input: Opcode, which should be 7 */
  425. /* Return: None */
  426. void operate(short opcode) {
  427. short group = (memory[pc] >> 8) & 1;
  428. if(group == 0)
  429. group0();
  430. else
  431. group1();
  432. if(mode == 1)
  433. verbose(opcode);
  434. }
  435. /* Execute fucntion. Gets opcode of instrcution at PC,*/
  436. /* Then sends to corresponding fucntions. We also increment */
  437. /* the program counter here, as well as skiping lines. We also halt her */
  438. /* Input: None */
  439. /* Return: None */
  440. void execute(void) {
  441. short opcode;
  442. do{
  443. opcode = ((memory[pc] >> 9) & 7);
  444. // go to memory reference instructions
  445. if(opcode <= 5)
  446. simple(opcode);
  447. // go to device instructions
  448. else if(opcode == 6)
  449. devices(opcode);
  450. // go to operate instruction
  451. else
  452. operate(opcode);
  453. // if we were told to skip in any instruction, increment the pc by 1
  454. if(skip == 1)
  455. pc++;
  456. skip = 0;
  457. pc++;
  458. pc = pc & 4095; // makes sure pc always stays within 4095 words
  459. if(halt == 1)
  460. exit(0);
  461. } while(pc <= 4096);
  462. }
  463. /* ReadInput Funtion: It reads ascii values and puts them into memory */
  464. /* Determines if we have found EP or not */
  465. /* Input: char array, should be of size 3, no more */
  466. /* Return: returns -1 if ep, else returns hex instruction */
  467. short readInput(char values[]) {
  468. int i;
  469. short total = 0;
  470. short adder = 0;
  471. // If we have ep
  472. if((values[0] == 'E' || values[0] == 'e') && (values[1] == 'P' || values[1] == 'p')) {
  473. // if we have found the EP for the first time
  474. if(ep_found == 0) {
  475. ep_found = 1;
  476. return -1;
  477. }
  478. // if we find another error
  479. else {
  480. fprintf(stderr, "Error found: Multiple EP's found. Exiting\n");
  481. exit(-1);
  482. }
  483. }
  484. // we are getting a hex instruction
  485. else {
  486. for(i = 0; i < 3; i++) {
  487. // Get values in upper case hex
  488. if(values[i] >= 65 && values[i] <= 70)
  489. adder = values[i] - 55;
  490. // get values in lower case hex
  491. else if(values[i] >= 97 && values[i] <= 102)
  492. adder = values[i] - 87;
  493. // get ascii numbers
  494. else if(values[i] >= 48 && values[i] <= 57)
  495. adder = values[i] - 48;
  496. // Error in object File
  497. else {
  498. fprintf(stderr, "Error in object file: invalid input: %c; exiting\n", values[i]);
  499. exit(-1);
  500. }
  501. adder = (adder << (4 * (2 - i)));
  502. total = total + adder;
  503. }
  504. }
  505. return total;
  506. }
  507. /* Readfile Function: Reads the object file given by the command line */
  508. /* It puts ascii values into a char[] and then sends them to ReadInput. Then it goes to execute*/
  509. /* Input: File, should not be NULL */
  510. /* Return: None */
  511. void readFile(FILE *input) {
  512. int i = 0;
  513. // introduce an int to count up how many characters have been put
  514. // into values
  515. short address;
  516. short value;
  517. char values1[3];
  518. char values2[3];
  519. char c = getc(input);
  520. accumulator = 0;
  521. skip = 0;
  522. link_bit = 0;
  523. // go through file
  524. while(c != EOF) {
  525. // get address
  526. while(c != ':') {
  527. values1[i] = c;
  528. i++;
  529. c = getc(input);
  530. }
  531. // if we did get ep or 3 hex numbers, continue
  532. if((i == 2) || (i == 3))
  533. address = readInput(values1);
  534. else {
  535. fprintf(stderr, "Error in object file. Too many or too few characters in address space. Exiting\n");
  536. exit(-1);
  537. }
  538. i = 0;
  539. // skip over space
  540. c = getc(input);
  541. // if space is not there, we exit
  542. if(c != ' ') {
  543. fprintf(stderr, "Error in objec file. No space between : and address field. Exiting\n");
  544. exit(-1);
  545. }
  546. // get next character to read
  547. c = getc(input);
  548. // get value
  549. while(c != '\n') {
  550. values2[i] = c;
  551. i++;
  552. c = getc(input);
  553. }
  554. if(i != 3) {
  555. fprintf(stderr, "Error in object file. Not correct amount of characters in value field. Exiting\n");
  556. exit(-1);
  557. }
  558. i = 0;
  559. value = readInput(values2);
  560. /* Begin putting values into memory */
  561. // if we found the ep
  562. if(address == -1)
  563. pc = value;
  564. // else we got an address that we need to put a value in
  565. else
  566. memory[address] = value;
  567. c = getc(input);
  568. }
  569. execute();
  570. }
  571. // scans argument looking for verbose
  572. void scanargs(char *s) {
  573. s++;
  574. if(*s == 'v')
  575. mode = 1;
  576. else
  577. fprintf(stderr, "%c Flag not supported", *s);
  578. }
  579. // Main Driver of the program
  580. int main(int argc, char *argv[]) {
  581. char *read;
  582. FILE *input;
  583. while(argc > 1) {
  584. argc--, argv++;
  585. read = *argv;
  586. if(*read == '-')
  587. scanargs(read);
  588. else {
  589. input = fopen(read, "r");
  590. if(input == NULL) {
  591. printf("File did not open; exitting");
  592. return(-1);
  593. }
  594. readFile(input);
  595. }
  596. }
  597. return 0;
  598. }