Fix 32/64 bit portability issue with upval->v.
[luajit-2.0/celess22.git] / src / buildvm_asm.c
blobcc821365a3474abae837bb0ba3827d31ec17e2e9
1 /*
2 ** LuaJIT VM builder: Assembler source code emitter.
3 ** Copyright (C) 2005-2010 Mike Pall. See Copyright Notice in luajit.h
4 */
6 #include "buildvm.h"
7 #include "lj_bc.h"
9 /* ------------------------------------------------------------------------ */
11 /* Emit bytes piecewise as assembler text. */
12 static void emit_asm_bytes(BuildCtx *ctx, uint8_t *p, int n)
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);
22 if ((n & 15) != 0) putc('\n', ctx->fp);
25 /* Emit relocation */
26 static void emit_asm_reloc(BuildCtx *ctx, BuildReloc *r)
28 const char *sym = ctx->extnames[r->sym];
29 const char *p = strchr(sym, '@');
30 char buf[80];
31 if (p) {
32 /* Always strip fastcall suffix. Wrong for (unused) COFF on Win32. */
33 strncpy(buf, sym, p-sym);
34 buf[p-sym] = '\0';
35 sym = buf;
37 switch (ctx->mode) {
38 case BUILD_elfasm:
39 if (r->type)
40 fprintf(ctx->fp, "\t.long %s-.-4\n", sym);
41 else
42 fprintf(ctx->fp, "\t.long %s\n", sym);
43 break;
44 case BUILD_coffasm:
45 fprintf(ctx->fp, "\t.def _%s; .scl 3; .type 32; .endef\n", sym);
46 if (r->type)
47 fprintf(ctx->fp, "\t.long _%s-.-4\n", sym);
48 else
49 fprintf(ctx->fp, "\t.long _%s\n", sym);
50 break;
51 default: /* BUILD_machasm for relative relocations handled below. */
52 fprintf(ctx->fp, "\t.long _%s\n", sym);
53 break;
57 static const char *const jccnames[] = {
58 "jo", "jno", "jb", "jnb", "jz", "jnz", "jbe", "ja",
59 "js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg"
62 /* Emit relocation for the incredibly stupid OSX assembler. */
63 static void emit_asm_reloc_mach(BuildCtx *ctx, uint8_t *cp, int n,
64 const char *sym)
66 const char *opname = NULL;
67 if (--n < 0) goto err;
68 if (cp[n] == 0xe8) {
69 opname = "call";
70 } else if (cp[n] == 0xe9) {
71 opname = "jmp";
72 } else if (cp[n] >= 0x80 && cp[n] <= 0x8f && n > 0 && cp[n-1] == 0x0f) {
73 opname = jccnames[cp[n]-0x80];
74 n--;
75 } else {
76 err:
77 fprintf(stderr, "Error: unsupported opcode for %s symbol relocation.\n",
78 sym);
79 exit(1);
81 emit_asm_bytes(ctx, cp, n);
82 fprintf(ctx->fp, "\t%s _%s\n", opname, sym);
85 /* Emit an assembler label. */
86 static void emit_asm_label(BuildCtx *ctx, const char *name, int size, int isfunc)
88 switch (ctx->mode) {
89 case BUILD_elfasm:
90 fprintf(ctx->fp,
91 "\n\t.globl %s\n"
92 "\t.hidden %s\n"
93 "\t.type %s, @%s\n"
94 "\t.size %s, %d\n"
95 "%s:\n",
96 name, name, name, isfunc ? "function" : "object", name, size, name);
97 break;
98 case BUILD_coffasm:
99 fprintf(ctx->fp, "\n\t.globl _%s\n", name);
100 if (isfunc)
101 fprintf(ctx->fp, "\t.def _%s; .scl 3; .type 32; .endef\n", name);
102 fprintf(ctx->fp, "_%s:\n", name);
103 break;
104 case BUILD_machasm:
105 fprintf(ctx->fp,
106 "\n\t.private_extern _%s\n"
107 "_%s:\n", name, name);
108 break;
109 default:
110 break;
114 /* Emit alignment. */
115 static void emit_asm_align(BuildCtx *ctx, int bits)
117 switch (ctx->mode) {
118 case BUILD_elfasm:
119 case BUILD_coffasm:
120 fprintf(ctx->fp, "\t.p2align %d\n", bits);
121 break;
122 case BUILD_machasm:
123 fprintf(ctx->fp, "\t.align %d\n", bits);
124 break;
125 default:
126 break;
130 /* ------------------------------------------------------------------------ */
132 /* Emit assembler source code. */
133 void emit_asm(BuildCtx *ctx)
135 char name[80];
136 int32_t prev;
137 int i, pi, rel;
139 fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch);
140 fprintf(ctx->fp, "\t.text\n");
141 emit_asm_align(ctx, 4);
143 emit_asm_label(ctx, LABEL_ASM_BEGIN, 0, 0);
144 if (ctx->mode == BUILD_elfasm)
145 fprintf(ctx->fp, ".Lbegin:\n");
147 i = 0;
148 do {
149 pi = ctx->perm[i++];
150 prev = ctx->sym_ofs[pi];
151 } while (prev < 0); /* Skip the _Z symbols. */
153 for (rel = 0; i <= ctx->nsym; i++) {
154 int ni = ctx->perm[i];
155 int32_t next = ctx->sym_ofs[ni];
156 int size = (int)(next - prev);
157 int32_t stop = next;
158 if (pi >= ctx->npc) {
159 char *p;
160 sprintf(name, LABEL_PREFIX "%s", ctx->globnames[pi-ctx->npc]);
161 /* Always strip fastcall suffix. Wrong for (unused) COFF on Win32. */
162 p = strchr(name, '@');
163 if (p) *p = '\0';
164 emit_asm_label(ctx, name, size, 1);
165 #if LJ_HASJIT
166 } else {
167 #else
168 } else if (!(pi == BC_JFORI || pi == BC_JFORL || pi == BC_JITERL ||
169 pi == BC_JLOOP || pi == BC_IFORL || pi == BC_IITERL ||
170 pi == BC_ILOOP)) {
171 #endif
172 sprintf(name, LABEL_PREFIX_BC "%s", bc_names[pi]);
173 emit_asm_label(ctx, name, size, 1);
175 while (rel < ctx->nreloc && ctx->reloc[rel].ofs < stop) {
176 int n = ctx->reloc[rel].ofs - prev;
177 if (ctx->mode == BUILD_machasm && ctx->reloc[rel].type != 0) {
178 emit_asm_reloc_mach(ctx, ctx->code+prev, n,
179 ctx->extnames[ctx->reloc[rel].sym]);
180 } else {
181 emit_asm_bytes(ctx, ctx->code+prev, n);
182 emit_asm_reloc(ctx, &ctx->reloc[rel]);
184 prev += n+4;
185 rel++;
187 emit_asm_bytes(ctx, ctx->code+prev, stop-prev);
188 prev = next;
189 pi = ni;
192 switch (ctx->mode) {
193 case BUILD_elfasm:
194 fprintf(ctx->fp, "\n\t.section .rodata\n");
195 break;
196 case BUILD_coffasm:
197 fprintf(ctx->fp, "\n\t.section .rdata,\"dr\"\n");
198 break;
199 case BUILD_machasm:
200 fprintf(ctx->fp, "\n\t.const\n");
201 break;
202 default:
203 break;
205 emit_asm_align(ctx, 5);
207 emit_asm_label(ctx, LABEL_OP_OFS, 2*ctx->npc, 0);
208 for (i = 0; i < ctx->npc; i++)
209 fprintf(ctx->fp, "\t.short %d\n", ctx->sym_ofs[i]);
211 fprintf(ctx->fp, "\n");
212 switch (ctx->mode) {
213 case BUILD_elfasm:
214 fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\",@progbits\n");
215 /* fallthrough */
216 case BUILD_coffasm:
217 fprintf(ctx->fp, "\t.ident \"%s\"\n", ctx->dasm_ident);
218 break;
219 case BUILD_machasm:
220 fprintf(ctx->fp,
221 "\t.cstring\n"
222 "\t.ascii \"%s\\0\"\n", ctx->dasm_ident);
223 break;
224 default:
225 break;
227 fprintf(ctx->fp, "\n");