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