summaryrefslogtreecommitdiff
path: root/src/buildvm_asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildvm_asm.c')
-rw-r--r--src/buildvm_asm.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/buildvm_asm.c b/src/buildvm_asm.c
new file mode 100644
index 00000000..e6972bd5
--- /dev/null
+++ b/src/buildvm_asm.c
@@ -0,0 +1,220 @@
1/*
2** LuaJIT VM builder: Assembler source code emitter.
3** Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#include "buildvm.h"
7#include "lj_bc.h"
8
9/* ------------------------------------------------------------------------ */
10
11/* Emit bytes piecewise as assembler text. */
12static void emit_asm_bytes(BuildCtx *ctx, uint8_t *p, int n)
13{
14 int i;
15 for (i = 0; i < n; i++) {
16 if ((i & 15) == 0)
17 fprintf(ctx->fp, "\t.byte %d", p[i]);
18 else
19 fprintf(ctx->fp, ",%d", p[i]);
20 if ((i & 15) == 15) putc('\n', ctx->fp);
21 }
22 if ((n & 15) != 0) putc('\n', ctx->fp);
23}
24
25/* Emit relocation */
26static void emit_asm_reloc(BuildCtx *ctx, BuildReloc *r)
27{
28 const char *sym = ctx->extnames[r->sym];
29 switch (ctx->mode) {
30 case BUILD_elfasm:
31 if (r->type)
32 fprintf(ctx->fp, "\t.long %s-.-4\n", sym);
33 else
34 fprintf(ctx->fp, "\t.long %s\n", sym);
35 break;
36 case BUILD_coffasm:
37 fprintf(ctx->fp, "\t.def _%s; .scl 3; .type 32; .endef\n", sym);
38 if (r->type)
39 fprintf(ctx->fp, "\t.long _%s-.-4\n", sym);
40 else
41 fprintf(ctx->fp, "\t.long _%s\n", sym);
42 break;
43 default: /* BUILD_machasm for relative relocations handled below. */
44 fprintf(ctx->fp, "\t.long _%s\n", sym);
45 break;
46 }
47}
48
49static const char *const jccnames[] = {
50 "jo", "jno", "jb", "jnb", "jz", "jnz", "jbe", "ja",
51 "js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg"
52};
53
54/* Emit relocation for the incredibly stupid OSX assembler. */
55static void emit_asm_reloc_mach(BuildCtx *ctx, uint8_t *cp, int n,
56 const char *sym)
57{
58 const char *opname = NULL;
59 if (--n < 0) goto err;
60 if (cp[n] == 0xe8) {
61 opname = "call";
62 } else if (cp[n] == 0xe9) {
63 opname = "jmp";
64 } else if (cp[n] >= 0x80 && cp[n] <= 0x8f && n > 0 && cp[n-1] == 0x0f) {
65 opname = jccnames[cp[n]-0x80];
66 n--;
67 } else {
68err:
69 fprintf(stderr, "Error: unsupported opcode for %s symbol relocation.\n",
70 sym);
71 exit(1);
72 }
73 emit_asm_bytes(ctx, cp, n);
74 if (!strncmp(sym, LABEL_PREFIX, sizeof(LABEL_PREFIX)-1))
75 fprintf(ctx->fp, "\t%s _%s\n", opname, sym);
76 else
77 fprintf(ctx->fp, "\t%s _" LABEL_PREFIX "wrapper_%s\n", opname, sym);
78}
79
80/* Emit an assembler label. */
81static void emit_asm_label(BuildCtx *ctx, const char *name, int size, int isfunc)
82{
83 switch (ctx->mode) {
84 case BUILD_elfasm:
85 fprintf(ctx->fp,
86 "\n\t.globl %s\n"
87 "\t.hidden %s\n"
88 "\t.type %s, @%s\n"
89 "\t.size %s, %d\n"
90 "%s:\n",
91 name, name, name, isfunc ? "function" : "object", name, size, name);
92 break;
93 case BUILD_coffasm:
94 fprintf(ctx->fp, "\n\t.globl _%s\n", name);
95 if (isfunc)
96 fprintf(ctx->fp, "\t.def _%s; .scl 3; .type 32; .endef\n", name);
97 fprintf(ctx->fp, "_%s:\n", name);
98 break;
99 case BUILD_machasm:
100 fprintf(ctx->fp,
101 "\n\t.private_extern _%s\n"
102 "_%s:\n", name, name);
103 break;
104 default:
105 break;
106 }
107}
108
109/* Emit alignment. */
110static void emit_asm_align(BuildCtx *ctx, int bits)
111{
112 switch (ctx->mode) {
113 case BUILD_elfasm:
114 case BUILD_coffasm:
115 fprintf(ctx->fp, "\t.p2align %d\n", bits);
116 break;
117 case BUILD_machasm:
118 fprintf(ctx->fp, "\t.align %d\n", bits);
119 break;
120 default:
121 break;
122 }
123}
124
125/* ------------------------------------------------------------------------ */
126
127/* Emit assembler source code. */
128void emit_asm(BuildCtx *ctx)
129{
130 char name[80];
131 int32_t prev;
132 int i, pi, rel;
133
134 fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch);
135 fprintf(ctx->fp, "\t.text\n");
136 emit_asm_align(ctx, 4);
137
138 emit_asm_label(ctx, LABEL_ASM_BEGIN, 0, 1);
139 if (ctx->mode == BUILD_elfasm)
140 fprintf(ctx->fp, ".Lbegin:\n");
141
142 i = 0;
143 do {
144 pi = ctx->perm[i++];
145 prev = ctx->sym_ofs[pi];
146 } while (prev < 0); /* Skip the _Z symbols. */
147
148 for (rel = 0; i <= ctx->nsym; i++) {
149 int ni = ctx->perm[i];
150 int32_t next = ctx->sym_ofs[ni];
151 int size = (int)(next - prev);
152 int32_t stop = next;
153 if (pi >= ctx->npc) {
154 sprintf(name, LABEL_PREFIX "%s", ctx->globnames[pi-ctx->npc]);
155 emit_asm_label(ctx, name, size, 1);
156#if LJ_HASJIT
157 } else {
158#else
159 } else if (!(pi == BC_JFORI || pi == BC_JFORL || pi == BC_JITERL ||
160 pi == BC_JLOOP || pi == BC_IFORL || pi == BC_IITERL ||
161 pi == BC_ILOOP)) {
162#endif
163 sprintf(name, LABEL_PREFIX_BC "%s", bc_names[pi]);
164 emit_asm_label(ctx, name, size, 1);
165 }
166 while (rel < ctx->nreloc && ctx->reloc[rel].ofs < stop) {
167 int n = ctx->reloc[rel].ofs - prev;
168 if (ctx->mode == BUILD_machasm && ctx->reloc[rel].type != 0) {
169 emit_asm_reloc_mach(ctx, ctx->code+prev, n,
170 ctx->extnames[ctx->reloc[rel].sym]);
171 } else {
172 emit_asm_bytes(ctx, ctx->code+prev, n);
173 emit_asm_reloc(ctx, &ctx->reloc[rel]);
174 }
175 prev += n+4;
176 rel++;
177 }
178 emit_asm_bytes(ctx, ctx->code+prev, stop-prev);
179 prev = next;
180 pi = ni;
181 }
182
183 switch (ctx->mode) {
184 case BUILD_elfasm:
185 fprintf(ctx->fp, "\n\t.section .rodata\n");
186 break;
187 case BUILD_coffasm:
188 fprintf(ctx->fp, "\n\t.section .rdata,\"dr\"\n");
189 break;
190 case BUILD_machasm:
191 fprintf(ctx->fp, "\n\t.const\n");
192 break;
193 default:
194 break;
195 }
196 emit_asm_align(ctx, 5);
197
198 emit_asm_label(ctx, LABEL_OP_OFS, 2*ctx->npc, 0);
199 for (i = 0; i < ctx->npc; i++)
200 fprintf(ctx->fp, "\t.short %d\n", ctx->sym_ofs[i]);
201
202 fprintf(ctx->fp, "\n");
203 switch (ctx->mode) {
204 case BUILD_elfasm:
205 fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\",@progbits\n");
206 /* fallthrough */
207 case BUILD_coffasm:
208 fprintf(ctx->fp, "\t.ident \"%s\"\n", ctx->dasm_ident);
209 break;
210 case BUILD_machasm:
211 fprintf(ctx->fp,
212 "\t.cstring\n"
213 "\t.ascii \"%s\\0\"\n", ctx->dasm_ident);
214 break;
215 default:
216 break;
217 }
218 fprintf(ctx->fp, "\n");
219}
220