-
Notifications
You must be signed in to change notification settings - Fork 0
/
code.aux.c
140 lines (116 loc) · 3.53 KB
/
code.aux.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "globals.h"
static int emitLoc = 0 ;
static int highEmitLoc = 0;
void emit_comment(char* c) {
printf("* %s\n", c);
}
void emit_RO(char* op, int r, int s, int t, char* c) {
printf("%4d: %5s %d, %d, %d \t %s \n", emitLoc++, op, r, s, t, c);
if(highEmitLoc < emitLoc) highEmitLoc = emitLoc;
}
void emit_RM(char* op, int r, int d, int s, char* c) {
printf("%4d: %5s %d, %d(%d) \t %s \n", emitLoc++, op, r, d, s, c);
if(highEmitLoc < emitLoc) highEmitLoc = emitLoc;
}
int emit_skip(int howMany) {
int i = emitLoc;
emitLoc += howMany;
if(highEmitLoc < emitLoc) highEmitLoc = emitLoc;
return i;
}
void emit_backup(int loc) {
if(loc > highEmitLoc) error(Bug, "loc > highEmitLoc in emit_backup()");
emitLoc = loc;
}
void emit_restore(void) {
emitLoc = highEmitLoc;
}
/******************************/
void pseudo_mov_reg(int dst, int src, int x, char* c) {
emit_RM("LDA", dst, x, src, c);
}
void pseudo_mov_const(int dst, int x, char* c) {
emit_RM("LDC", dst, x, ignore, c);
}
void pseudo_push(int reg, char* c) {
if(reg == sp || reg == pc) {
warning("push sp/pc");
}
pseudo_mov_reg(sp, sp, -1, c);
emit_RM("ST", reg, 0, sp, "");
}
void pseudo_pop(int reg, char* c) {
if(reg == sp) {
warning("pop sp");
}
// why this order? think about "pop pc"
pseudo_mov_reg(sp, sp, 1, c);
emit_RM("LD", reg, -1, sp, "");
}
/******************************/
void pseudo_return(void) {
emit_comment("-> [pseudo] return");
pseudo_mov_reg(sp, bp, 0, "sp = bp");
pseudo_pop(bp, "pop bp");
pseudo_pop(pc, "pop pc");
emit_comment("<- [pseudo] return");
}
void pseudo_fun_head(char* name) {
FunInfo funinfo = lookup_funinfo(name);
funinfo->address = emit_skip(0); // IMPORTANT: register address
int size = funinfo->var_size;
emit_comment("-> [pseudo] function head");
pseudo_push(bp, "push bp");
pseudo_mov_reg(bp, sp, 0, "bp = sp");
pseudo_mov_reg(sp, sp, -size, "sp = sp - param_size");
emit_comment("<- [pseudo] function head");
}
// note: unsafe ax
void pseudo_call(FunInfo funinfo) {
char* name = funinfo->name;
int address = funinfo->address;
int size = funinfo->param_size;
if(address < 0) {
error(Bug, "address of funtion \"%s\" < 0", name);
}
emit_comment("-> [pseudo] call");
emit_comment(name);
pseudo_mov_reg(ax, pc, 3, "ac = pc + 3 (next pc)"); // why 4? "push ax" capture 2 positions
pseudo_push(ax, "push ax (return address)");
pseudo_mov_const(pc, address, "pc = address (jmp)");
pseudo_mov_reg(sp, sp, size, "sp = sp + param_size"); // next pc: clean stack (parameter)
emit_comment("<- [pseudo] call");
}
// return: ax
void pseudo_get_var_addr(Ast node) {
Entry entry = lookup_entry(node->name);
int offset = entry->offset;
emit_comment("-> [pseudo] get var addr");
switch(entry->kind) {
case Global_Var:
emit_RM("LDA", ax, -offset, gp, "ax = gp-offset");
break;
case Compound_Var:
emit_RM("LDA", ax, -offset-1, bp, "ax = bp-offset-1");
break;
case Fun_Param:
if(entry->type == IntT) {
emit_RM("LDA", ax, offset+2, bp, "ax = bp+offset+2");
} else {
assert(entry->type == IntArrayT); // the value here is an address
emit_RM("LD", ax, offset+2, bp, "ax = data[bp+offset+2]");
}
break;
default: error(Bug, "unknown entry kind");
}
emit_comment("<- [pseudo] get var addr");
}
// input: bx, ax
// output: ax
void pseudo_compare(char* command) {
emit_RO("SUB", ax, bx, ax, "ax = bx - ax");
emit_RM(command, ax, 2, pc, "conditional jmp: if true");
pseudo_mov_const(ax, 0, "ax = 0 (false case)");
pseudo_mov_reg(pc, pc, 1, "unconditional jmp");
pseudo_mov_const(ax, 1, "ax = 1 (true case)");
}