1 /* pancake // nopcode.org 2011 -- trace emiter */
2
3 #include <r_egg.h>
4 #define attsyntax 0
5
6 #define EMIT_NAME emit_trace
7 #define R_ARCH "trace"
8 #define R_SZ 8
9 #define R_SP "sp"
10 #define R_BP "bp"
11 #define R_AX "a0"
12 #define R_GP { "a0", "a1", "a2", "a3", "a4" }
13 #define R_TMP "t0"
14 #define R_NGP 5
15
16 // no attsyntax for arm
17 static char *regs[] = R_GP;
18
emit_init(REgg * egg)19 static void emit_init (REgg *egg) {
20 /* TODO */
21 }
22
emit_syscall(REgg * egg,int num)23 static char *emit_syscall (REgg *egg, int num) {
24 char buf[32];
25 snprintf (buf, sizeof (buf), "syscall (%d)\n", num);
26 return strdup (buf);
27 }
28
emit_frame(REgg * egg,int sz)29 static void emit_frame (REgg *egg, int sz) {
30 r_egg_printf (egg, "frame (%d)\n", sz);
31 }
32
emit_frame_end(REgg * egg,int sz,int ctx)33 static void emit_frame_end (REgg *egg, int sz, int ctx) {
34 r_egg_printf (egg, "frame_end (%d, %d)\n", sz, ctx);
35 }
36
emit_comment(REgg * egg,const char * fmt,...)37 static void emit_comment(REgg *egg, const char *fmt, ...) {
38 va_list ap;
39 char buf[1024];
40 va_start (ap, fmt);
41 vsnprintf (buf, sizeof (buf), fmt, ap);
42 r_egg_printf (egg, "# %s\n", buf);
43 va_end (ap);
44 }
45
emit_equ(REgg * egg,const char * key,const char * value)46 static void emit_equ (REgg *egg, const char *key, const char *value) {
47 r_egg_printf (egg, "equ (%s, %s)\n", key, value);
48 }
49
emit_syscall_args(REgg * egg,int nargs)50 static void emit_syscall_args(REgg *egg, int nargs) {
51 r_egg_printf (egg, "syscall_args (%d)\n", nargs);
52 }
53
emit_set_string(REgg * egg,const char * dstvar,const char * str,int j)54 static void emit_set_string(REgg *egg, const char *dstvar, const char *str, int j) {
55 // what is j?
56 r_egg_printf (egg, "set (\"%s\", \"%s\", %d)\n", dstvar, str, j);
57 }
58
emit_call(REgg * egg,const char * str,int atr)59 static void emit_call(REgg *egg, const char *str, int atr) {
60 if (atr) {
61 r_egg_printf (egg, "call ([%s])\n", str);
62 } else {
63 r_egg_printf (egg, "call (%s)\n", str);
64 }
65 }
66
emit_jmp(REgg * egg,const char * str,int atr)67 static void emit_jmp(REgg *egg, const char *str, int atr) {
68 if (atr) {
69 r_egg_printf (egg, "goto ([%s])\n", str);
70 } else {
71 r_egg_printf (egg, "goto (%s)\n", str);
72 }
73 }
74
emit_arg(REgg * egg,int xs,int num,const char * str)75 static void emit_arg (REgg *egg, int xs, int num, const char *str) {
76 // TODO: enhance output here
77 r_egg_printf (egg, "arg.%d.%d=%s\n", xs, num, str);
78 }
79
emit_get_result(REgg * egg,const char * ocn)80 static void emit_get_result(REgg *egg, const char *ocn) {
81 r_egg_printf (egg, "get_result (%s)\n", ocn);
82 }
83
emit_restore_stack(REgg * egg,int size)84 static void emit_restore_stack (REgg *egg, int size) {
85 r_egg_printf (egg, "restore_stack (%d)\n", size);
86 // XXX: must die.. or add emit_store_stack. not needed by ARM
87 // r_egg_printf (egg, " add sp, %d\n", size);
88 }
89
emit_get_while_end(REgg * egg,char * str,const char * ctxpush,const char * label)90 static void emit_get_while_end (REgg *egg, char *str, const char *ctxpush, const char *label) {
91 r_egg_printf (egg, "get_while_end (%s, %s, %s)\n", str, ctxpush, label);
92 }
93
emit_while_end(REgg * egg,const char * labelback)94 static void emit_while_end (REgg *egg, const char *labelback) {
95 r_egg_printf (egg, "while_end (%s)\n", labelback);
96 }
97
emit_get_var(REgg * egg,int type,char * out,int idx)98 static void emit_get_var (REgg *egg, int type, char *out, int idx) {
99 switch (type) {
100 case 0: sprintf (out, "fp,$%d", -idx); break; /* variable */
101 case 1: sprintf (out, "sp,$%d", idx); break; /* argument */ // XXX: MUST BE r0, r1, r2, ..
102 }
103 }
104
emit_trap(REgg * egg)105 static void emit_trap (REgg *egg) {
106 r_egg_printf (egg, "trap\n");
107 }
108
109 // TODO atoi here?
emit_load_ptr(REgg * egg,const char * dst)110 static void emit_load_ptr(REgg *egg, const char *dst) {
111 r_egg_printf (egg, "loadptr (%s)\n", dst);
112 }
113
emit_branch(REgg * egg,char * b,char * g,char * e,char * n,int sz,const char * dst)114 static void emit_branch(REgg *egg, char *b, char *g, char *e, char *n, int sz, const char *dst) {
115 // This function signature is crap
116 char *p, str[64];
117 char *arg = NULL;
118 char *op = "beq";
119 /* NOTE that jb/ja are inverted to fit cmp opcode */
120 if (b) {
121 *b = '\0';
122 op = e?"bge":"bgt";
123 arg = b+1;
124 } else
125 if (g) {
126 *g = '\0';
127 op = e?"ble":"blt";
128 arg = g+1;
129 }
130 if (!arg) {
131 if (e) {
132 arg = e+1;
133 op = "bne";
134 } else {
135 arg = "0";
136 op = n?"bne":"beq";
137 }
138 }
139
140 if (*arg == '=') {
141 arg++; /* for <=, >=, ... */
142 }
143 p = r_egg_mkvar (egg, str, arg, 0);
144 r_egg_printf (egg, "%s (%s) => (%s)\n", op, p, dst);
145 free (p);
146 }
147
148 // XXX: sz must be char
emit_load(REgg * egg,const char * dst,int sz)149 static void emit_load(REgg *egg, const char *dst, int sz) {
150 r_egg_printf (egg, "load (\"%s\", %c)\n", dst, sz);
151 }
152
emit_mathop(REgg * egg,int ch,int vs,int type,const char * eq,const char * p)153 static void emit_mathop(REgg *egg, int ch, int vs, int type, const char *eq, const char *p) {
154 char *op;
155 switch (ch) {
156 case '^': op = "eor"; break;
157 case '&': op = "and"; break;
158 case '|': op = "orr"; break;
159 case '-': op = "sub"; break;
160 case '+': op = "add"; break;
161 case '*': op = "mul"; break;
162 case '/': op = "div"; break;
163 default: op = "mov"; break;
164 }
165 if (!eq) {
166 eq = R_AX;
167 }
168 if (!p) {
169 p = R_AX;
170 }
171 #if 0
172 // TODO:
173 eprintf ("TYPE = %c\n", type);
174 eprintf (" %s%c %c%s, %s\n", op, vs, type, eq, p);
175 eprintf (" %s %s, [%s]\n", op, p, eq);
176 #endif
177 if (type == '*') {
178 r_egg_printf (egg, "%s (%s, [%s])\n", op, p, eq);
179 } else {
180 r_egg_printf (egg, "%s (%s, %s)\n", op, p, eq);
181 }
182 }
183
emit_regs(REgg * egg,int idx)184 static const char* emit_regs(REgg *egg, int idx) {
185 return regs[idx%R_NGP];
186 }
187
188 REggEmit EMIT_NAME = {
189 .retvar = "a0",
190 .arch = R_ARCH,
191 .size = R_SZ,
192 .jmp = emit_jmp,
193 .call = emit_call,
194 .init = emit_init,
195 .equ = emit_equ,
196 .regs = emit_regs,
197 //.sc = emit_sc,
198 .trap = emit_trap,
199 .frame = emit_frame,
200 .frame_end = emit_frame_end,
201 .comment = emit_comment,
202 .push_arg = emit_arg,
203 .restore_stack = emit_restore_stack,
204 .get_result = emit_get_result,
205 .syscall_args = emit_syscall_args,
206 .set_string = emit_set_string,
207 .get_var = emit_get_var,
208 .while_end = emit_while_end,
209 .get_while_end = emit_get_while_end,
210 .branch = emit_branch,
211 .load = emit_load,
212 .load_ptr = emit_load_ptr,
213 .mathop = emit_mathop,
214 .syscall = emit_syscall,
215 };
216