History

arm64-win32 support: target PE & varargs

Benjamin Oldenburg committed 7 months ago

Commit 44e68531 parent 5c728d61 file · +109 −11Browse files

Unified · Split

arm64-gen.c+109−11
@@ -38,7 +38,7 @@ · 37 unmodified lines
38 38
39#define MAX_ALIGN 1639#define MAX_ALIGN 16
40 40
41#ifndef TCC_TARGET_MACHO41#if !defined(TCC_TARGET_MACHO) && !defined(TCC_TARGET_PE)
42#define CHAR_IS_UNSIGNED42#define CHAR_IS_UNSIGNED
43#endif43#endif
44 44
@@ -79,7 +79,11 @@ ST_DATA const int reg_classes[NB_REGS] = { · 34 unmodified lines
79 RC_INT | RC_R(15),79 RC_INT | RC_R(15),
80 RC_INT | RC_R(16),80 RC_INT | RC_R(16),
81 RC_INT | RC_R(17),81 RC_INT | RC_R(17),
82#ifdef TCC_TARGET_PE
83 RC_R(18), /* (x18 reserved on Windows) */
84#else
82 RC_INT | RC_R(18),85 RC_INT | RC_R(18),
86#endif
83 RC_R30, // not in RC_INT as we make special use of x3087 RC_R30, // not in RC_INT as we make special use of x30
84 RC_FLOAT | RC_F(0),88 RC_FLOAT | RC_F(0),
85 RC_FLOAT | RC_F(1),89 RC_FLOAT | RC_F(1),
@@ -468,10 +472,18 @@ static void arm64_strv(int sz_, int dst, int bas, uint64_t off) · 382 unmodified lines
468 472
469static void arm64_sym(int r, Sym *sym, unsigned long addend)473static void arm64_sym(int r, Sym *sym, unsigned long addend)
470{474{
475#ifdef TCC_TARGET_PE
476 /* PE links symbol addresses directly; there is no ELF-style GOT here. */
477 greloca(cur_text_section, sym, ind, R_AARCH64_ADR_PREL_PG_HI21, 0);
478 o(ARM64_ADRP | r); // adrp xr, #sym
479 greloca(cur_text_section, sym, ind, R_AARCH64_ADD_ABS_LO12_NC, 0);
480 o(ARM64_ADD_IMM | ARM64_SF(1) | ARM64_RN(r) | r); // add xr, xr, #sym
481#else
471 greloca(cur_text_section, sym, ind, R_AARCH64_ADR_GOT_PAGE, 0);482 greloca(cur_text_section, sym, ind, R_AARCH64_ADR_GOT_PAGE, 0);
472 o(0x90000000 | r); // adrp xr, #sym483 o(0x90000000 | r); // adrp xr, #sym
473 greloca(cur_text_section, sym, ind, R_AARCH64_LD64_GOT_LO12_NC, 0);484 greloca(cur_text_section, sym, ind, R_AARCH64_LD64_GOT_LO12_NC, 0);
474 o(0xf9400000 | r | (r << 5)); // ld xr,[xr, #sym]485 o(0xf9400000 | r | (r << 5)); // ld xr,[xr, #sym]
486#endif
475 if (addend) {487 if (addend) {
476 // add xr, xr, #addend488 // add xr, xr, #addend
477 if (addend & 0xffful)489 if (addend & 0xffful)
@@ -820,6 +832,7 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l · 342 unmodified lines
820 832
821 for (i = 0; i < n; i++) {833 for (i = 0; i < n; i++) {
822 int hfa = arm64_hfa(type[i], 0);834 int hfa = arm64_hfa(type[i], 0);
835 int win_vararg_float = 0;
823 int size, align;836 int size, align;
824 837
825 if ((type[i]->t & VT_ARRAY) ||838 if ((type[i]->t & VT_ARRAY) ||
@@ -833,6 +846,16 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l · 7 unmodified lines
833 nx = 8;846 nx = 8;
834 nv = 8;847 nv = 8;
835 }848 }
849
850#elif defined(TCC_TARGET_PE)
851 if (variadic && i >= variadic && (hfa || is_float(type[i]->t))) {
852 hfa = 0;
853 if (is_float(type[i]->t)) {
854 win_vararg_float = 1;
855 size = 8;
856 align = 8;
857 }
858 }
836#endif859#endif
837 if (hfa)860 if (hfa)
838 // B.2861 // B.2
@@ -853,7 +876,7 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l · 14 unmodified lines
853 size = (size + 7) & ~7;876 size = (size + 7) & ~7;
854 877
855 // C.1878 // C.1
856 if (is_float(type[i]->t) && nv < 8) {879 if (!win_vararg_float && is_float(type[i]->t) && nv < 8) {
857 a[i] = 16 + (nv++ << 1);880 a[i] = 16 + (nv++ << 1);
858 continue;881 continue;
859 }882 }
@@ -882,7 +905,7 @@ static unsigned long arm64_pcs_aux(int variadic, int n, CType **type, unsigned l · 22 unmodified lines
882 size = 8;905 size = 8;
883 906
884 // C.6907 // C.6
885 if (hfa || is_float(type[i]->t)) {908 if (!win_vararg_float && (hfa || is_float(type[i]->t))) {
886 a[i] = ns;909 a[i] = ns;
887 ns += size;910 ns += size;
888 continue;911 continue;
@@ -1044,7 +1067,11 @@ ST_FUNC void gfunc_call(int nb_args) · 155 unmodified lines
1044 for (i = 0; i < nb_args; i++)1067 for (i = 0; i < nb_args; i++)
1045 t[nb_args - i] = &vtop[-i].type;1068 t[nb_args - i] = &vtop[-i].type;
1046 1069
1047 stack = arm64_pcs(variadic ? var_nb_arg : 0, nb_args, t, a);1070 stack = arm64_pcs(
1071#ifdef TCC_TARGET_PE
1072 old_style ? -1 :
1073#endif
1074 var_nb_arg, nb_args, t, a);
1048 1075
1049 // Allocate space for structs replaced by pointer:1076 // Allocate space for structs replaced by pointer:
1050 for (i = nb_args; i; i--)1077 for (i = nb_args; i; i--)
@@ -1214,11 +1241,21 @@ static int arm64_func_sub_sp_offset; · 163 unmodified lines
1214static unsigned arm64_func_start_offset;1241static unsigned arm64_func_start_offset;
1215#define ARM64_FUNC_STACK_SETUP_SLOTS 61242#define ARM64_FUNC_STACK_SETUP_SLOTS 6
1216 1243
1244#ifdef TCC_TARGET_PE
1245static unsigned long arm64_pe_param_off(unsigned long a)
1246{
1247 return a < 16 ? 160 + a / 2 * 8 :
1248 a < 32 ? 16 + (a - 16) / 2 * 16 :
1249 224 + ((a - 32) >> 1 << 1);
1250}
1251#endif
1252
1217ST_FUNC void gfunc_prolog(Sym *func_sym)1253ST_FUNC void gfunc_prolog(Sym *func_sym)
1218{1254{
1219 CType *func_type = &func_sym->type;1255 CType *func_type = &func_sym->type;
1220 int n = 0;1256 int n = 0;
1221 int i = 0;1257 int i = 0;
1258 int pcs_n;
1222 Sym *sym;1259 Sym *sym;
1223 CType **t;1260 CType **t;
1224 unsigned long *a;1261 unsigned long *a;
@@ -1227,18 +1264,34 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 2 unmodified lines
1227 int last_float = 0;1264 int last_float = 0;
1228 int variadic = func_sym->type.ref->f.func_type == FUNC_ELLIPSIS;1265 int variadic = func_sym->type.ref->f.func_type == FUNC_ELLIPSIS;
1229 int var_nb_arg = n_func_args(&func_sym->type);1266 int var_nb_arg = n_func_args(&func_sym->type);
1267 int c;
1230 1268
1231 func_vc = 144; // offset of where x8 is stored1269 func_vc = 144; // offset of where x8 is stored
1232 1270
1233 for (sym = func_type->ref; sym; sym = sym->next)1271 for (sym = func_type->ref; sym; sym = sym->next)
1234 ++n;1272 ++n;
1235 t = n ? tcc_malloc(n * sizeof(*t)) : NULL;1273 pcs_n = n - 1;
1236 a = n ? tcc_malloc(n * sizeof(*a)) : NULL;1274 c = n + variadic;
1275 t = tcc_malloc(c * sizeof(*t));
1276 a = tcc_malloc(c * sizeof(*a));
1237 1277
1238 for (sym = func_type->ref; sym; sym = sym->next)1278 for (sym = func_type->ref; sym; sym = sym->next)
1239 t[i++] = &sym->type;1279 t[i++] = &sym->type;
1240 1280
1241 arm64_func_va_list_stack = arm64_pcs(variadic ? var_nb_arg : 0, n - 1, t, a);1281#ifdef TCC_TARGET_PE
1282 if (variadic) {
1283 t[i++] = &int_type;
1284 ++pcs_n;
1285 }
1286#endif
1287
1288 arm64_func_va_list_stack = arm64_pcs(variadic ? var_nb_arg : 0,
1289 pcs_n, t, a);
1290
1291#ifdef TCC_TARGET_PE
1292 if (variadic)
1293 arm64_func_va_list_stack = arm64_pe_param_off(a[n]);
1294#endif
1242 1295
1243#if !defined(TCC_TARGET_MACHO)1296#if !defined(TCC_TARGET_MACHO)
1244 if (variadic) {1297 if (variadic) {
@@ -1333,6 +1386,14 @@ ST_FUNC void gen_va_start(void) · 88 unmodified lines
1333 gaddrof();1386 gaddrof();
1334 r = intr(gv(RC_INT));1387 r = intr(gv(RC_INT));
1335 1388
1389#ifdef TCC_TARGET_PE
1390 if (arm64_func_va_list_stack) {
1391 arm64_movimm(30, arm64_func_va_list_stack);
1392 o(0x8b1e03be); // add x30,x29,x30
1393 } else
1394 o(0x910283be); // add x30,x29,#160
1395 o(0xf900001e | r << 5); // str x30,[x(r)]
1396#else
1336 if (arm64_func_va_list_stack) {1397 if (arm64_func_va_list_stack) {
1337 //xx could use add (immediate) here1398 //xx could use add (immediate) here
1338 arm64_movimm(30, arm64_func_va_list_stack + 224);1399 arm64_movimm(30, arm64_func_va_list_stack + 224);
@@ -1359,6 +1420,7 @@ ST_FUNC void gen_va_start(void) · 20 unmodified lines
1359 1420
1360 arm64_movimm(30, arm64_func_va_list_vr_offs);1421 arm64_movimm(30, arm64_func_va_list_vr_offs);
1361 o(0xb9001c1e | r << 5); // str w30,[x(r),#28]1422 o(0xb9001c1e | r << 5); // str w30,[x(r),#28]
1423#endif
1362#endif1424#endif
1363 1425
1364 --vtop;1426 --vtop;
@@ -1367,14 +1429,45 @@ ST_FUNC void gen_va_start(void) · 2 unmodified lines
1367ST_FUNC void gen_va_arg(CType *t)1429ST_FUNC void gen_va_arg(CType *t)
1368{1430{
1369 int align, size = type_size(t, &align);1431 int align, size = type_size(t, &align);
1370 unsigned fsize, hfa = arm64_hfa(t, &fsize);
1371 uint32_t r0, r1;1432 uint32_t r0, r1;
1372 1433
1373 if (is_float(t->t)) {1434#ifdef TCC_TARGET_PE
1374 hfa = 1;1435 int indirect = 0, slot = (size + 7) & -8;
1375 fsize = size;1436
1437 if (size > 16)
1438 indirect = 1, slot = 8;
1439
1440 gaddrof();
1441 r0 = intr(gv(RC_INT));
1442 r1 = get_reg(RC_INT);
1443 vtop[0].r = r1 | VT_LVAL;
1444 r1 = intr(r1);
1445
1446 o(0xF9400000 | r0 << 5 | r1); // ldr x(r1),[x(r0)] // ap
1447 if (slot) {
1448 if (slot == 16) {
1449 o(0x910363be); // add x30,x29,#216
1450 o(0xeb1e003f | r1 << 5); // cmp x(r1),x30
1451 o(0x54000041); // b.ne .+8
1452 o(0x910383a0 | r1 | 29 << 5); // add x(r1),x29,#224
1453 }
1454 if (align == 16) {
1455 o(0x91003c00 | r1 | r1 << 5); // add x(r1),x(r1),#15
1456 o(0x927cec00 | r1 | r1 << 5); // and x(r1),x(r1),#-16
1457 }
1458 o(0x9100001e | r1 << 5 | slot << 10); // add x30,x(r1),#(slot)
1459 o(0xf900001e | r0 << 5); // str x30,[x(r0)] // ap += slot
1376 }1460 }
1377 1461
1462 if (indirect)
1463 o(0xF9400000 | ARM64_RN(r1) | r1); // ldr x(r1),[x(r1)]
1464
1465#else /* !PE */
1466 unsigned fsize = size, hfa = 1;
1467
1468 if (!is_float(t->t))
1469 hfa = arm64_hfa(t, &fsize);
1470
1378 gaddrof();1471 gaddrof();
1379 r0 = intr(gv(RC_INT));1472 r0 = intr(gv(RC_INT));
1380 r1 = get_reg(RC_INT);1473 r1 = get_reg(RC_INT);
@@ -1451,6 +1544,7 @@ ST_FUNC void gen_va_arg(CType *t) · 70 unmodified lines
1451 write32le(cur_text_section->data + b2, 0x14000000 | (ind - b2) >> 2);1544 write32le(cur_text_section->data + b2, 0x14000000 | (ind - b2) >> 2);
1452#endif1545#endif
1453 }1546 }
1547#endif /* not pe */
1454}1548}
1455 1549
1456ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,1550ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
@@ -1530,6 +1624,10 @@ ST_FUNC void gfunc_epilog(void) · 73 unmodified lines
1530 o(0xa8ce7bfd); // ldp x29,x30,[sp],#2241624 o(0xa8ce7bfd); // ldp x29,x30,[sp],#224
1531 1625
1532 o(0xd65f03c0); // ret1626 o(0xd65f03c0); // ret
1627
1628#ifdef TCC_TARGET_PE
1629 pe_add_unwind_data(arm64_func_start_offset, ind, -loc);
1630#endif
1533}1631}
1534 1632
1535ST_FUNC void gen_fill_nops(int bytes)1633ST_FUNC void gen_fill_nops(int bytes)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t