Tsumida / MiniC

Lexer and syntax analysis for tiny c compiler.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TM虚拟机指令

Tsumida opened this issue · comments

commented

寄存器

编号 名称 用途
7 pc 程序计数器
6 mp 内存指针, 指向mem的顶部 (用于临时存储)
5 gp 全局指针,存放全局变量
1 ac1 第二个accumulator
0 ac 第一个accumulator

注意这是CODE模块中的定义,在TM.C模块中,明确标记7号寄存器是PC之外,没有任何其他限制,其他几个寄存器0-7都是通用的。

存储器

分为指令区和数据区,默认大小均为1024个单元。
指令区的存储单元大小为4 * 32 Byte的4个int,
数据区的存储单位为32Byte的整型(可负数)。

指令

RO指令

格式: number: op_code r,s,t, 如666: IN 10, 0, 2

  • HAL:停止执行
  • IN:读取一个数到寄存器r
  • OUT: 输出寄存器r的内容
  • ADD, SUB, MUL, DIV:reg(r) <- reg(s) op reg(t)

RM

格式: number: opcode r, d(s), 例如:996: LD 1, 2(3)

  • LD: load, mem[ d + reg(s) ] -> reg(r)
  • ST: store,mem [d + reg(s) ] <- reg(r)
  • LDA: 加载地址, d + reg(s) -> reg(r)
  • LDC: 加载常数, d -> reg(r)
  • JLT, JLE, JGE, JGT, TEQ, JNE:分别是>, >=, <=, <, ==, !=的条件跳转,可概况为 : if ( reg(r) op 0 ) then reg(PC) <- d + reg(s)

代码生成器

emitXX函数会打印一条指令。这些函数用到两个参数emitLoc, highEmitLoc,后者单调递增。前者在涉及代码回填时会暂时变小。

emitComment

打印一条注释

emitRO

输入参数: op, r, s, t, 注释

emitRM

参数:rop, r, d,s, 注释

emitSkip

参数: int howMany
增加emitLoc += howMany, 返回原来的emitLoc.

emitBackup

参数: int loc
回到先前的位置loc, 注意loc应该比当前index要小。

emitRestore

无参数,将当前代码位置index恢复到先前未emit的location的最大index, 即emitLoc = highEmitLoc(?).

emitRM_Abs

参数: op, r, a, 注释, 其中a是内存单元的绝对地址。
实际上,a = d + reg(s) , 将其转为 op_code r, d(s)的形式

代码生成

void codeGen(TreeNode * syntaxTree, char * codefile)
{  char * s = (char*)malloc(strlen(codefile)+7);
   strcpy(s,"File: ");
   strcat(s,codefile);
   emitComment("TINY Compilation to TM Code");
   emitComment(s);
   /* generate standard prelude */
   emitComment("Standard prelude:");
   emitRM("LD",mp,0,ac,"load maxaddress from location 0");
   emitRM("ST",ac,0,ac,"clear location 0");
   emitComment("End of standard prelude.");
   /* generate code for TINY program */
   cGen(syntaxTree);
   /* finish */
   emitComment("End of execution.");
   emitRO("HALT",0,0,0,"");
}