TM虚拟机指令
Tsumida opened this issue · comments
Z_ 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,"");
}