2 ** LuaJIT VM builder: Assembler source code emitter.
3 ** Copyright (C) 2005-2010 Mike Pall. See Copyright Notice in luajit.h
9 /* ------------------------------------------------------------------------ */
11 /* Emit bytes piecewise as assembler text. */
12 static void emit_asm_bytes(BuildCtx
*ctx
, uint8_t *p
, int n
)
15 for (i
= 0; i
< n
; i
++) {
17 fprintf(ctx
->fp
, "\t.byte %d", p
[i
]);
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
);
26 static void emit_asm_reloc(BuildCtx
*ctx
, BuildReloc
*r
)
28 const char *sym
= ctx
->extnames
[r
->sym
];
29 const char *p
= strchr(sym
, '@');
32 /* Always strip fastcall suffix. Wrong for (unused) COFF on Win32. */
33 strncpy(buf
, sym
, p
-sym
);
40 fprintf(ctx
->fp
, "\t.long %s-.-4\n", sym
);
42 fprintf(ctx
->fp
, "\t.long %s\n", sym
);
45 fprintf(ctx
->fp
, "\t.def _%s; .scl 3; .type 32; .endef\n", sym
);
47 fprintf(ctx
->fp
, "\t.long _%s-.-4\n", sym
);
49 fprintf(ctx
->fp
, "\t.long _%s\n", sym
);
51 default: /* BUILD_machasm for relative relocations handled below. */
52 fprintf(ctx
->fp
, "\t.long _%s\n", sym
);
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
,
66 const char *opname
= NULL
;
67 if (--n
< 0) goto err
;
70 } else if (cp
[n
] == 0xe9) {
72 } else if (cp
[n
] >= 0x80 && cp
[n
] <= 0x8f && n
> 0 && cp
[n
-1] == 0x0f) {
73 opname
= jccnames
[cp
[n
]-0x80];
77 fprintf(stderr
, "Error: unsupported opcode for %s symbol relocation.\n",
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
)
96 name
, name
, name
, isfunc
? "function" : "object", name
, size
, name
);
99 fprintf(ctx
->fp
, "\n\t.globl _%s\n", name
);
101 fprintf(ctx
->fp
, "\t.def _%s; .scl 3; .type 32; .endef\n", name
);
102 fprintf(ctx
->fp
, "_%s:\n", name
);
106 "\n\t.private_extern _%s\n"
107 "_%s:\n", name
, name
);
114 /* Emit alignment. */
115 static void emit_asm_align(BuildCtx
*ctx
, int bits
)
120 fprintf(ctx
->fp
, "\t.p2align %d\n", bits
);
123 fprintf(ctx
->fp
, "\t.align %d\n", bits
);
130 /* ------------------------------------------------------------------------ */
132 /* Emit assembler source code. */
133 void emit_asm(BuildCtx
*ctx
)
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");
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
);
158 if (pi
>= ctx
->npc
) {
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
, '@');
164 emit_asm_label(ctx
, name
, size
, 1);
168 } else if (!(pi
== BC_JFORI
|| pi
== BC_JFORL
|| pi
== BC_JITERL
||
169 pi
== BC_JLOOP
|| pi
== BC_IFORL
|| pi
== BC_IITERL
||
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
]);
181 emit_asm_bytes(ctx
, ctx
->code
+prev
, n
);
182 emit_asm_reloc(ctx
, &ctx
->reloc
[rel
]);
187 emit_asm_bytes(ctx
, ctx
->code
+prev
, stop
-prev
);
194 fprintf(ctx
->fp
, "\n\t.section .rodata\n");
197 fprintf(ctx
->fp
, "\n\t.section .rdata,\"dr\"\n");
200 fprintf(ctx
->fp
, "\n\t.const\n");
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");
214 fprintf(ctx
->fp
, "\t.section .note.GNU-stack,\"\",@progbits\n");
217 fprintf(ctx
->fp
, "\t.ident \"%s\"\n", ctx
->dasm_ident
);
222 "\t.ascii \"%s\\0\"\n", ctx
->dasm_ident
);
227 fprintf(ctx
->fp
, "\n");