Tiny語言編譯器之TM虛擬機開發

  這裏的虛擬機是是Tiny語言的運行環境,源代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

#define IADDR_SIZE 1024 //指令存儲區大小
#define DADDR_SIZE 1024 //數據區大小
#define No_REGS 8 //寄存器數量
#define PC_REG 7 //程序寄存器,只有這一個爲專用寄存器

//操作符類型
typedef enum
{
 opclRR, //寄存器操作
 opclRM, //寄存器&內存操作
 opclRA, //寄存器&地址操作
}OPCLASS;

//opCode定義
typedef enum {
  
   opHALT,   
   opIN,     
   opOUT,    
   opADD,   
   opSUB,   
   opMUL,   
   opDIV,   
   opRRLim,  

  
   opLD,     
   opST,     
   opRMLim,  

  
   opLDA,    
   opLDC,    
   opJLT,    
   opJLE,    
   opJGT,    
   opJGE,    
   opJEQ,    
   opJNE,    
   opRALim   
   } OPCODE;

char * opCodeTab[]
        = {"HALT","IN","OUT","ADD","SUB","MUL","DIV","????",
           
           "LD","ST","????",
           "LDA","LDC","JLT","JLE","JGT","JGE","JEQ","JNE","????"
          
          };

int iloc = 0 ;
int dloc = 0 ;
int traceflag = FALSE;
int icountflag = FALSE;


typedef enum {
   srOKAY,
   srHALT,
   srIMEM_ERR,
   srDMEM_ERR,
   srZERODIVIDE
   } STEPRESULT;

char * stepResultTab[]
        = {"OK","Halted","Instruction Memory Fault",
           "Data Memory Fault","Division by 0"
          };
//指令定義
typedef struct {
      int iop  ;
      int iarg1  ;
      int iarg2  ;
      int iarg3  ;
   } INSTRUCTION;

//指令區
INSTRUCTION iMem[IADDR_SIZE];
//內存區
int dMem[DADDR_SIZE];
//寄存器
int reg[No_REGS];

FILE *pgm;
#define LINESIZE 256
#define WORDSIZE 20
char in_Line[LINESIZE];
int lineLen;
int inCol;
int num;
char word[WORDSIZE];
char ch;
int done;


//取得本行中下一個不是空格的字符
int nonBlank(void)
{
 while((inCol<lineLen) && (in_Line[inCol]==' '))
  inCol++;
 if(inCol<lineLen)
 {
  ch=in_Line[inCol];
  return TRUE;
 }
 else
 {
  ch=' ';
  return FALSE;
 }
}

int atEOL(void)
{ return ( ! nonBlank ());
}

//得到下一個字符
void getCh()
{
 if(++inCol<lineLen)
  ch=in_Line[inCol];
 else
   ch = ' '; 
}

//跳過一個字符
int skipCh(char c)
{
 int temp = FALSE;
 if(nonBlank() && (ch==c))
 {
  getCh();
  temp=TRUE;
 }
 return temp;
}

//得到下一個單詞
int getWord()
{
 int temp = FALSE;
 int length=0;
 if(nonBlank())
 {
  while(isalnum(ch))
  {
   if(length<WORDSIZE-1) word[length++]=ch;
   getCh();
  }
  word[length] = '\0';
  temp = (length!=0);
 }
 return temp; 
}


//得到本行中的一個整數
int getNum()
{
 int sign;
 int term;
 int temp=FALSE;
 num=0;
 do{
  sign =1;
     while(nonBlank() && ((ch=='+') || (ch=='-')))
  {
    temp = FALSE;
    if(ch=='-') sign=-sign;
    getCh();
  }
  term = 0;
  nonBlank();
  while(isdigit(ch))
  {
   temp = TRUE;
   term = term * 10 + ch - '0';
   getCh();
  }
  num = num + (term*sign);
 }
 while(nonBlank() && ((ch=='+') || (ch=='-')));
 return temp;
}

int error( char * msg, int lineNo, int instNo)
{ printf("Line %d",lineNo);
  if (instNo >= 0) printf(" (Instruction %d)",instNo);
  printf("   %s\n",msg);
  return FALSE;
}


int opClass( int c )
{ if      ( c <= opRRLim) return ( opclRR );
  else if ( c <= opRMLim) return ( opclRM );
  else                    return ( opclRA );
}

//讀取指令
int readInstructions()
{
  OPCODE op;
  int arg1, arg2, arg3;
  int regNo;
  int loc;
  int lineNo; 
  //寄存器清零
  for(regNo=0; regNo<No_REGS; regNo++)
   reg[regNo]=0;
  //初始化數據區
  dMem[0]=DADDR_SIZE-1;
  for(loc=1; loc < DADDR_SIZE; loc++)
   dMem[loc]=0;
  //初始化指令區
  for(loc=0;loc<IADDR_SIZE;loc++)
  {
   iMem[loc].iop = opHALT;
   iMem[loc].iarg1=0;
   iMem[loc].iarg2=0;
   iMem[loc].iarg3=0;
  }
  lineNo = 0;
  while(!feof(pgm))
  {
   //讀入一行代碼
   fgets(in_Line, LINESIZE, pgm);
   inCol=0;
   lineNo++;
   lineLen=strlen(in_Line)-1;
   if(in_Line[lineLen]=='\n')
    in_Line[lineLen]='\0';
   if(nonBlank() && ch!='*') /
      r = currentinstruction.iarg1 ;
      s = currentinstruction.iarg2 ;
      t = currentinstruction.iarg3 ;
      break;

    case opclRM :
   
      r = currentinstruction.iarg1 ;
      s = currentinstruction.iarg3 ;
      m = currentinstruction.iarg2 + reg[s] ; //此時m代表數據區地址
      if ( (m < 0) || (m > DADDR_SIZE))
         return srDMEM_ERR ;
      break;

    case opclRA :
   
      r = currentinstruction.iarg1 ;
      s = currentinstruction.iarg3 ;
      m = currentinstruction.iarg2 + reg[s] ;
      break;
  }

  switch ( currentinstruction.iop)
  {
    case opHALT :
   
      printf("HALT: %1d,%1d,%1d\n",r,s,t);
      return srHALT ;
     

    case opIN :
   
      do
      { printf("Enter value for IN instruction: ") ;
        fflush (stdin);
        fflush (stdout);
        gets(in_Line);
        lineLen = strlen(in_Line) ;
        inCol = 0;
        ok = getNum();
        if ( ! ok ) printf ("Illegal value\n");
        else reg[r] = num;
      }
      while (! ok);
      break;

    case opOUT : 
      printf ("OUT instruction prints: %d\n", reg[r] ) ;
      break;
    case opADD :  reg[r] = reg[s] + reg[t] ;  break;
    case opSUB :  reg[r] = reg[s] - reg[t] ;  break;
    case opMUL :  reg[r] = reg[s] * reg[t] ;  break;

    case opDIV :
   
      if ( reg[t] != 0 ) reg[r] = reg[s] / reg[t];
      else return srZERODIVIDE ;
      break;

   
    case opLD :    reg[r] = dMem[m] ;  break; //數據區複製給寄存器
    case opST :    dMem[m] = reg[r] ;  break; //寄存器複製給數據區

   
    case opLDA :    reg[r] = m ; break;
    case opLDC :    reg[r] = currentinstruction.iarg2 ;   break;
    case opJLT :    if ( reg[r] <  0 ) reg[PC_REG] = m ; break;
    case opJLE :    if ( reg[r] <=  0 ) reg[PC_REG] = m ; break;
    case opJGT :    if ( reg[r] >  0 ) reg[PC_REG] = m ; break;
    case opJGE :    if ( reg[r] >=  0 ) reg[PC_REG] = m ; break;
    case opJEQ :    if ( reg[r] == 0 ) reg[PC_REG] = m ; break;
    case opJNE :    if ( reg[r] != 0 ) reg[PC_REG] = m ; break;

   
  }
  return srOKAY ; 

 return srOKAY;

}

//執行指令

int doCommand (void)
{ char cmd;
  int stepcnt=0, i;
  int printcnt;
  int stepResult;
  int regNo, loc;
  do
  { printf ("Enter command: ");
    fflush (stdin);
    fflush (stdout);
    gets(in_Line);
    lineLen = strlen(in_Line);
    inCol = 0;
  }
  while (! getWord ());

  cmd = word[0] ;
  switch ( cmd )
  { case 't' :
   
      traceflag = ! traceflag ;
      printf("Tracing now ");
      if ( traceflag ) printf("on.\n"); else printf("off.\n");
      break;

    case 'h' :
   
      printf("Commands are:\n");
      printf("   s(tep <n>      "\
             "Execute n (default 1) TM instructions\n");
      printf("   g(o            "\
             "Execute TM instructions until HALT\n");
      printf("   r(egs          "\
             "Print the contents of the registers\n");
      printf("   i(Mem <b <n>>  "\
             "Print n iMem locations starting at b\n");
      printf("   d(Mem <b <n>>  "\
             "Print n dMem locations starting at b\n");
      printf("   t(race         "\
             "Toggle instruction trace\n");
      printf("   p(rint         "\
             "Toggle print of total instructions executed"\
             " ('go' only)\n");
      printf("   c(lear         "\
             "Reset simulator for new execution of program\n");
      printf("   h(elp          "\
           

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章