Advertisement
Guest User

Untitled

a guest
Jun 19th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.57 KB | None | 0 0
  1. /****************************************************/
  2. /* File: tm.c */
  3. /* The TM ("Tiny Machine") computer */
  4. /* Compiler Construction: Principles and Practice */
  5. /* Kenneth C. Louden */
  6. /****************************************************/
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12.  
  13. #ifndef TRUE
  14. #define TRUE 1
  15. #endif
  16. #ifndef FALSE
  17. #define FALSE 0
  18. #endif
  19.  
  20. /******* const *******/
  21. #define IADDR_SIZE 1024 /* increase for large programs */
  22. #define DADDR_SIZE 1024 /* increase for large programs */
  23. #define NO_REGS 8
  24. #define PC_REG 7
  25.  
  26. #define LINESIZE 121
  27. #define WORDSIZE 20
  28.  
  29. /******* type *******/
  30.  
  31. typedef enum {
  32. opclRR, /* reg operands r,s,t */
  33. opclRM, /* reg r, mem d+s */
  34. opclRA /* reg r, int d+s */
  35. } OPCLASS;
  36.  
  37. typedef enum {
  38. /* RR instructions */
  39. opHALT=0, /* RR halt, operands are ignored */
  40. opIN, /* RR read into reg(r); s and t are ignored */
  41. opOUT, /* RR write from reg(r), s and t are ignored */
  42. opADD, /* RR reg(r) = reg(s)+reg(t) */
  43. opSUB, /* RR reg(r) = reg(s)-reg(t) */
  44. opMUL, /* RR reg(r) = reg(s)*reg(t) */
  45. opDIV, /* RR reg(r) = reg(s)/reg(t) */
  46. opRRLim, /* limit of RR opcodes */
  47.  
  48. /* RM instructions */
  49. opLD, /* RM reg(r) = mem(d+reg(s)) */
  50. opST, /* RM mem(d+reg(s)) = reg(r) */
  51. opRMLim, /* Limit of RM opcodes */
  52.  
  53. /* RA instructions */
  54. opLDA, /* RA reg(r) = d+reg(s) */
  55. opLDC, /* RA reg(r) = d ; reg(s) is ignored */
  56. opJLT, /* RA if reg(r)<0 then reg(7) = d+reg(s) */
  57. opJLE, /* RA if reg(r)<=0 then reg(7) = d+reg(s) */
  58. opJGT, /* RA if reg(r)>0 then reg(7) = d+reg(s) */
  59. opJGE, /* RA if reg(r)>=0 then reg(7) = d+reg(s) */
  60. opJEQ, /* RA if reg(r)==0 then reg(7) = d+reg(s) */
  61. opJNE, /* RA if reg(r)!=0 then reg(7) = d+reg(s) */
  62. opRALim /* Limit of RA opcodes */
  63. } OPCODE;
  64.  
  65. typedef enum {
  66. srOKAY,
  67. srHALT,
  68. srIMEM_ERR,
  69. srDMEM_ERR,
  70. srZERODIVIDE
  71. } STEPRESULT;
  72.  
  73. typedef struct {
  74. int iop ;
  75. int iarg1 ;
  76. int iarg2 ;
  77. int iarg3 ;
  78. } INSTRUCTION;
  79.  
  80. /******** vars ********/
  81. int iloc = 0 ;
  82. int dloc = 0 ;
  83. int traceflag = FALSE;
  84. int icountflag = FALSE;
  85.  
  86. INSTRUCTION iMem [IADDR_SIZE];
  87. int dMem [DADDR_SIZE];
  88. int reg [NO_REGS];
  89.  
  90. char * opCodeTab[]
  91. = {"HALT","IN","OUT","ADD","SUB","MUL","DIV","????",
  92. /* RR opcodes */
  93. "LD","ST","????", /* RM opcodes */
  94. "LDA","LDC","JLT","JLE","JGT","JGE","JEQ","JNE","????"
  95. /* RA opcodes */
  96. };
  97.  
  98. char * stepResultTab[]
  99. = {"OK","Halted","Instruction Memory Fault",
  100. "Data Memory Fault","Division by 0"
  101. };
  102.  
  103. char pgmName[20];
  104. FILE *pgm ;
  105.  
  106. char in_Line[LINESIZE] ;
  107. int lineLen ;
  108. int inCol ;
  109. int num ;
  110. char word[WORDSIZE] ;
  111. char ch ;
  112. int done ;
  113.  
  114. /********************************************/
  115. int opClass( int c )
  116. { if ( c <= opRRLim) return ( opclRR );
  117. else if ( c <= opRMLim) return ( opclRM );
  118. else return ( opclRA );
  119. } /* opClass */
  120.  
  121. /********************************************/
  122. void writeInstruction ( int loc )
  123. { printf( "%5d: ", loc) ;
  124. if ( (loc >= 0) && (loc < IADDR_SIZE) )
  125. { printf("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);
  126. switch ( opClass(iMem[loc].iop) )
  127. { case opclRR: printf("%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
  128. break;
  129. case opclRM:
  130. case opclRA: printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
  131. break;
  132. }
  133. printf ("\n") ;
  134. }
  135. } /* writeInstruction */
  136.  
  137. /********************************************/
  138. void getCh (void)
  139. { if (++inCol < lineLen)
  140. ch = in_Line[inCol] ;
  141. else ch = ' ' ;
  142. } /* getCh */
  143.  
  144. /********************************************/
  145. int nonBlank (void)
  146. { while ((inCol < lineLen)
  147. && (in_Line[inCol] == ' ') )
  148. inCol++ ;
  149. if (inCol < lineLen)
  150. { ch = in_Line[inCol] ;
  151. return TRUE ; }
  152. else
  153. { ch = ' ' ;
  154. return FALSE ; }
  155. } /* nonBlank */
  156.  
  157. /********************************************/
  158. int getNum (void)
  159. { int sign;
  160. int term;
  161. int temp = FALSE;
  162. num = 0 ;
  163. do
  164. { sign = 1;
  165. while ( nonBlank() && ((ch == '+') || (ch == '-')) )
  166. { temp = FALSE ;
  167. if (ch == '-') sign = - sign ;
  168. getCh();
  169. }
  170. term = 0 ;
  171. nonBlank();
  172. while (isdigit(ch))
  173. { temp = TRUE ;
  174. term = term * 10 + ( ch - '0' ) ;
  175. getCh();
  176. }
  177. num = num + (term * sign) ;
  178. } while ( (nonBlank()) && ((ch == '+') || (ch == '-')) ) ;
  179. return temp;
  180. } /* getNum */
  181.  
  182. /********************************************/
  183. int getWord (void)
  184. { int temp = FALSE;
  185. int length = 0;
  186. if (nonBlank ())
  187. { while (isalnum(ch))
  188. { if (length < WORDSIZE-1) word [length++] = ch ;
  189. getCh() ;
  190. }
  191. word[length] = '\0';
  192. temp = (length != 0);
  193. }
  194. return temp;
  195. } /* getWord */
  196.  
  197. /********************************************/
  198. int skipCh ( char c )
  199. { int temp = FALSE;
  200. if ( nonBlank() && (ch == c) )
  201. { getCh();
  202. temp = TRUE;
  203. }
  204. return temp;
  205. } /* skipCh */
  206.  
  207. /********************************************/
  208. int atEOL(void)
  209. { return ( ! nonBlank ());
  210. } /* atEOL */
  211.  
  212. /********************************************/
  213. int error( char * msg, int lineNo, int instNo)
  214. { printf("Line %d",lineNo);
  215. if (instNo >= 0) printf(" (Instruction %d)",instNo);
  216. printf(" %s\n",msg);
  217. return FALSE;
  218. } /* error */
  219.  
  220. /********************************************/
  221. int readInstructions (void)
  222. { OPCODE op;
  223. int arg1, arg2, arg3;
  224. int loc, regNo, lineNo;
  225. for (regNo = 0 ; regNo < NO_REGS ; regNo++)
  226. reg[regNo] = 0 ;
  227. dMem[0] = DADDR_SIZE - 1 ;
  228. for (loc = 1 ; loc < DADDR_SIZE ; loc++)
  229. dMem[loc] = 0 ;
  230. for (loc = 0 ; loc < IADDR_SIZE ; loc++)
  231. { iMem[loc].iop = opHALT ;
  232. iMem[loc].iarg1 = 0 ;
  233. iMem[loc].iarg2 = 0 ;
  234. iMem[loc].iarg3 = 0 ;
  235. }
  236. lineNo = 0 ;
  237. while (! feof(pgm))
  238. { fgets( in_Line, LINESIZE-2, pgm ) ;
  239. inCol = 0 ;
  240. lineNo++;
  241. lineLen = strlen(in_Line)-1 ;
  242. if (in_Line[lineLen]=='\n') in_Line[lineLen] = '\0' ;
  243. else in_Line[++lineLen] = '\0';
  244. if ( (nonBlank()) && (in_Line[inCol] != '*') )
  245. { if (! getNum())
  246. return error("Bad location", lineNo,-1);
  247. loc = num;
  248. if (loc > IADDR_SIZE)
  249. return error("Location too large",lineNo,loc);
  250. if (! skipCh(':'))
  251. return error("Missing colon", lineNo,loc);
  252. if (! getWord ())
  253. return error("Missing opcode", lineNo,loc);
  254. op = opHALT ;
  255. int opx;
  256. for (opx = opHALT; opx < opRALim; opx++){
  257. //printf("%s %s\n", opCodeTab[opx], word);
  258. if (strncmp(opCodeTab[opx], word, 4) == 0){
  259. break;
  260. }
  261. }
  262. /*while ((op < opRALim)
  263. && () )
  264. op++ ;
  265. if (strncmp(opCodeTab[op], word, 4) != 0)
  266. return error("Illegal opcode", lineNo,loc);*/
  267. switch ( opClass(opx) )
  268. { case opclRR :
  269. /***********************************/
  270. if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
  271. return error("Bad first register", lineNo,loc);
  272. arg1 = num;
  273. if ( ! skipCh(','))
  274. return error("Missing comma", lineNo, loc);
  275. if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
  276. return error("Bad second register", lineNo, loc);
  277. arg2 = num;
  278. if ( ! skipCh(','))
  279. return error("Missing comma", lineNo,loc);
  280. if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
  281. return error("Bad third register", lineNo,loc);
  282. arg3 = num;
  283. break;
  284.  
  285. case opclRM :
  286. case opclRA :
  287. /***********************************/
  288. if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
  289. return error("Bad first register", lineNo,loc);
  290. arg1 = num;
  291. if ( ! skipCh(','))
  292. return error("Missing comma", lineNo,loc);
  293. if (! getNum ())
  294. return error("Bad displacement", lineNo,loc);
  295. arg2 = num;
  296. if ( ! skipCh('(') && ! skipCh(',') )
  297. return error("Missing LParen", lineNo,loc);
  298. if ( (! getNum ()) || (num < 0) || (num >= NO_REGS))
  299. return error("Bad second register", lineNo,loc);
  300. arg3 = num;
  301. break;
  302. }
  303. iMem[loc].iop = opx;
  304. iMem[loc].iarg1 = arg1;
  305. iMem[loc].iarg2 = arg2;
  306. iMem[loc].iarg3 = arg3;
  307. }
  308. }
  309. return TRUE;
  310. } /* readInstructions */
  311.  
  312.  
  313. /********************************************/
  314. STEPRESULT stepTM (void)
  315. { INSTRUCTION currentinstruction ;
  316. int pc ;
  317. int r,s,t,m ;
  318. int ok ;
  319.  
  320. pc = reg[PC_REG] ;
  321. if ( (pc < 0) || (pc > IADDR_SIZE) )
  322. return srIMEM_ERR ;
  323. reg[PC_REG] = pc + 1 ;
  324. currentinstruction = iMem[ pc ] ;
  325. switch (opClass(currentinstruction.iop) )
  326. { case opclRR :
  327. /***********************************/
  328. r = currentinstruction.iarg1 ;
  329. s = currentinstruction.iarg2 ;
  330. t = currentinstruction.iarg3 ;
  331. break;
  332.  
  333. case opclRM :
  334. /***********************************/
  335. r = currentinstruction.iarg1 ;
  336. s = currentinstruction.iarg3 ;
  337. m = currentinstruction.iarg2 + reg[s] ;
  338. if ( (m < 0) || (m > DADDR_SIZE))
  339. return srDMEM_ERR ;
  340. break;
  341.  
  342. case opclRA :
  343. /***********************************/
  344. r = currentinstruction.iarg1 ;
  345. s = currentinstruction.iarg3 ;
  346. m = currentinstruction.iarg2 + reg[s] ;
  347. break;
  348. } /* case */
  349.  
  350. switch ( currentinstruction.iop)
  351. { /* RR instructions */
  352. case opHALT :
  353. /***********************************/
  354. printf("HALT: %1d,%1d,%1d\n",r,s,t);
  355. return srHALT ;
  356. /* break; */
  357.  
  358. case opIN :
  359. /***********************************/
  360. do
  361. { printf("Enter value for IN instruction: ") ;
  362. fflush (stdin);
  363. fflush (stdout);
  364. fgets(in_Line, LINESIZE, stdin);
  365. lineLen = strlen(in_Line) ;
  366. inCol = 0;
  367. ok = getNum();
  368. if ( ! ok ) printf ("Illegal value\n");
  369. else reg[r] = num;
  370. }
  371. while (! ok);
  372. break;
  373.  
  374. case opOUT :
  375. printf ("OUT instruction prints: %d\n", reg[r] ) ;
  376. break;
  377. case opADD : reg[r] = reg[s] + reg[t] ; break;
  378. case opSUB : reg[r] = reg[s] - reg[t] ; break;
  379. case opMUL : reg[r] = reg[s] * reg[t] ; break;
  380.  
  381. case opDIV :
  382. /***********************************/
  383. if ( reg[t] != 0 ) reg[r] = reg[s] / reg[t];
  384. else return srZERODIVIDE ;
  385. break;
  386.  
  387. /*************** RM instructions ********************/
  388. case opLD : reg[r] = dMem[m] ; break;
  389. case opST : dMem[m] = reg[r] ; break;
  390.  
  391. /*************** RA instructions ********************/
  392. case opLDA : reg[r] = m ; break;
  393. case opLDC : reg[r] = currentinstruction.iarg2 ; break;
  394. case opJLT : if ( reg[r] < 0 ) reg[PC_REG] = m ; break;
  395. case opJLE : if ( reg[r] <= 0 ) reg[PC_REG] = m ; break;
  396. case opJGT : if ( reg[r] > 0 ) reg[PC_REG] = m ; break;
  397. case opJGE : if ( reg[r] >= 0 ) reg[PC_REG] = m ; break;
  398. case opJEQ : if ( reg[r] == 0 ) reg[PC_REG] = m ; break;
  399. case opJNE : if ( reg[r] != 0 ) reg[PC_REG] = m ; break;
  400.  
  401. /* end of legal instructions */
  402. } /* case */
  403. return srOKAY ;
  404. } /* stepTM */
  405.  
  406. /********************************************/
  407. int doCommand (void)
  408. { char cmd;
  409. int stepcnt=0, i;
  410. int printcnt;
  411. int stepResult;
  412. int regNo, loc;
  413. do
  414. { printf ("Enter command: ");
  415. fflush (stdin);
  416. fflush (stdout);
  417. fgets(in_Line, LINESIZE, stdin);
  418. lineLen = strlen(in_Line);
  419. inCol = 0;
  420. }
  421. while (! getWord ());
  422.  
  423. cmd = word[0] ;
  424. switch ( cmd )
  425. { case 't' :
  426. /***********************************/
  427. traceflag = ! traceflag ;
  428. printf("Tracing now ");
  429. if ( traceflag ) printf("on.\n"); else printf("off.\n");
  430. break;
  431.  
  432. case 'h' :
  433. /***********************************/
  434. printf("Commands are:\n");
  435. printf(" s(tep <n> "\
  436. "Execute n (default 1) TM instructions\n");
  437. printf(" g(o "\
  438. "Execute TM instructions until HALT\n");
  439. printf(" r(egs "\
  440. "Print the contents of the registers\n");
  441. printf(" i(Mem <b <n>> "\
  442. "Print n iMem locations starting at b\n");
  443. printf(" d(Mem <b <n>> "\
  444. "Print n dMem locations starting at b\n");
  445. printf(" t(race "\
  446. "Toggle instruction trace\n");
  447. printf(" p(rint "\
  448. "Toggle print of total instructions executed"\
  449. " ('go' only)\n");
  450. printf(" c(lear "\
  451. "Reset simulator for new execution of program\n");
  452. printf(" h(elp "\
  453. "Cause this list of commands to be printed\n");
  454. printf(" q(uit "\
  455. "Terminate the simulation\n");
  456. break;
  457.  
  458. case 'p' :
  459. /***********************************/
  460. icountflag = ! icountflag ;
  461. printf("Printing instruction count now ");
  462. if ( icountflag ) printf("on.\n"); else printf("off.\n");
  463. break;
  464.  
  465. case 's' :
  466. /***********************************/
  467. if ( atEOL ()) stepcnt = 1;
  468. else if ( getNum ()) stepcnt = abs(num);
  469. else printf("Step count?\n");
  470. break;
  471.  
  472. case 'g' : stepcnt = 1 ; break;
  473.  
  474. case 'r' :
  475. /***********************************/
  476. for (i = 0; i < NO_REGS; i++)
  477. { printf("%1d: %4d ", i,reg[i]);
  478. if ( (i % 4) == 3 ) printf ("\n");
  479. }
  480. break;
  481.  
  482. case 'i' :
  483. /***********************************/
  484. printcnt = 1 ;
  485. if ( getNum ())
  486. { iloc = num ;
  487. if ( getNum ()) printcnt = num ;
  488. }
  489. if ( ! atEOL ())
  490. printf ("Instruction locations?\n");
  491. else
  492. { while ((iloc >= 0) && (iloc < IADDR_SIZE)
  493. && (printcnt > 0) )
  494. { writeInstruction(iloc);
  495. iloc++ ;
  496. printcnt-- ;
  497. }
  498. }
  499. break;
  500.  
  501. case 'd' :
  502. /***********************************/
  503. printcnt = 1 ;
  504. if ( getNum ())
  505. { dloc = num ;
  506. if ( getNum ()) printcnt = num ;
  507. }
  508. if ( ! atEOL ())
  509. printf("Data locations?\n");
  510. else
  511. { while ((dloc >= 0) && (dloc < DADDR_SIZE)
  512. && (printcnt > 0))
  513. { printf("%5d: %5d\n",dloc,dMem[dloc]);
  514. dloc++;
  515. printcnt--;
  516. }
  517. }
  518. break;
  519.  
  520. case 'c' :
  521. /***********************************/
  522. iloc = 0;
  523. dloc = 0;
  524. stepcnt = 0;
  525. for (regNo = 0; regNo < NO_REGS ; regNo++)
  526. reg[regNo] = 0 ;
  527. dMem[0] = DADDR_SIZE - 1 ;
  528. for (loc = 1 ; loc < DADDR_SIZE ; loc++)
  529. dMem[loc] = 0 ;
  530. break;
  531.  
  532. case 'q' : return FALSE; /* break; */
  533.  
  534. default : printf("Command %c unknown.\n", cmd); break;
  535. } /* case */
  536. stepResult = srOKAY;
  537. if ( stepcnt > 0 )
  538. { if ( cmd == 'g' )
  539. { stepcnt = 0;
  540. while (stepResult == srOKAY)
  541. { iloc = reg[PC_REG] ;
  542. if ( traceflag ) writeInstruction( iloc ) ;
  543. stepResult = stepTM ();
  544. stepcnt++;
  545. }
  546. if ( icountflag )
  547. printf("Number of instructions executed = %d\n",stepcnt);
  548. }
  549. else
  550. { while ((stepcnt > 0) && (stepResult == srOKAY))
  551. { iloc = reg[PC_REG] ;
  552. if ( traceflag ) writeInstruction( iloc ) ;
  553. stepResult = stepTM ();
  554. stepcnt-- ;
  555. }
  556. }
  557. printf( "%s\n",stepResultTab[stepResult] );
  558. }
  559. return TRUE;
  560. } /* doCommand */
  561.  
  562.  
  563. /********************************************/
  564. /* E X E C U T I O N B E G I N S H E R E */
  565. /********************************************/
  566.  
  567. main( int argc, char * argv[] )
  568. { if (argc != 2)
  569. { printf("usage: %s <filename>\n",argv[0]);
  570. exit(1);
  571. }
  572. strcpy(pgmName,argv[1]) ;
  573. if (strchr (pgmName, '.') == NULL)
  574. strcat(pgmName,".tm");
  575. pgm = fopen(pgmName,"r");
  576. if (pgm == NULL)
  577. { printf("file '%s' not found\n",pgmName);
  578. exit(1);
  579. }
  580.  
  581. /* read the program */
  582. if ( ! readInstructions ())
  583. exit(1) ;
  584. /* switch input file to terminal */
  585. /* reset( input ); */
  586. /* read-eval-print */
  587. printf("TM simulation (enter h for help)...\n");
  588. do
  589. done = ! doCommand ();
  590. while (! done );
  591. printf("Simulation done.\n");
  592. return 0;
  593. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement