History

arm64-win32 support: use arm64_sub_sp()

Benjamin Oldenburg committed 7 months ago

Commit 90d17c91 parent 99713bc1 file · +42 −32Browse files

Unified · Split

arm64-gen.c+42−32
@@ -993,6 +993,32 @@ static int n_func_args(CType *type) · 992 unmodified lines
993 return n_args;993 return n_args;
994}994}
995 995
996static void arm64_sub_sp(uint64_t diff)
997{
998 if (!diff)
999 return;
1000#ifdef TCC_TARGET_PE
1001 if (diff >= 4096) {
1002 Sym *sym = external_helper_sym(TOK___chkstk);
1003
1004 arm64_movimm(15, diff >> 4);
1005 greloca(cur_text_section, sym, ind, R_AARCH64_CALL26, 0);
1006 o(ARM64_BL); // bl __chkstk
1007 o(0xcb2f73ff); // sub sp,sp,x15,lsl #4
1008 return;
1009 }
1010#endif
1011 if (!(diff >> 24)) {
1012 if (diff & 0xffful)
1013 o(ARM64_SUB_IMM | ARM64_SF(1) | 0 | ARM64_RN(31) | ARM64_RD(31) | ARM64_IMM12(diff & 0xfff));
1014 if (diff >> 12)
1015 o(ARM64_SUB_IMM | ARM64_SF(1) | ARM64_SH(1) | ARM64_RN(31) | ARM64_RD(31) | ARM64_IMM12((diff >> 12) & 0xfff));
1016 } else {
1017 arm64_movimm(16, diff);
1018 o(0xCB3063FFU); // sub sp,sp,x16
1019 }
1020}
1021
996ST_FUNC void gfunc_call(int nb_args)1022ST_FUNC void gfunc_call(int nb_args)
997{1023{
998 CType *return_type;1024 CType *return_type;
@@ -1039,10 +1065,7 @@ ST_FUNC void gfunc_call(int nb_args) · 40 unmodified lines
1039 1065
1040 if (stack >= 0x1000000) // 16Mb1066 if (stack >= 0x1000000) // 16Mb
1041 tcc_error("stack size too big %lu", stack);1067 tcc_error("stack size too big %lu", stack);
1042 if (stack & 0xfff)1068 arm64_sub_sp(stack);
1043 o(0xd10003ff | (stack & 0xfff) << 10); // sub sp,sp,#(n)
1044 if (stack >> 12)
1045 o(0xd14003ff | (stack >> 12) << 10);
1046 1069
1047 // First pass: set all values on stack1070 // First pass: set all values on stack
1048 for (i = nb_args; i; i--) {1071 for (i = nb_args; i; i--) {
@@ -1178,6 +1201,9 @@ static int arm64_func_va_list_gr_offs; · 129 unmodified lines
1178static int arm64_func_va_list_vr_offs;1201static int arm64_func_va_list_vr_offs;
1179static int arm64_func_sub_sp_offset;1202static int arm64_func_sub_sp_offset;
1180 1203
1204static unsigned arm64_func_start_offset;
1205#define ARM64_FUNC_STACK_SETUP_SLOTS 6
1206
1181ST_FUNC void gfunc_prolog(Sym *func_sym)1207ST_FUNC void gfunc_prolog(Sym *func_sym)
1182{1208{
1183 CType *func_type = &func_sym->type;1209 CType *func_type = &func_sym->type;
@@ -1229,6 +1255,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 45 unmodified lines
1229 last_int = last_int > 4 ? 4 : last_int;1255 last_int = last_int > 4 ? 4 : last_int;
1230 last_float = last_float > 4 ? 4 : last_float;1256 last_float = last_float > 4 ? 4 : last_float;
1231 1257
1258 arm64_func_start_offset = ind;
1232 o(0xa9b27bfd); // stp x29,x30,[sp,#-224]!1259 o(0xa9b27bfd); // stp x29,x30,[sp,#-224]!
1233 for (i = 0; i < last_float; i++)1260 for (i = 0; i < last_float; i++)
1234 // stp q0,q1,[sp,#16], stp q2,q3,[sp,#48]1261 // stp q0,q1,[sp,#16], stp q2,q3,[sp,#48]
@@ -1279,9 +1306,9 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 44 unmodified lines
1279 1306
1280 o(0x910003fd); // mov x29,sp1307 o(0x910003fd); // mov x29,sp
1281 arm64_func_sub_sp_offset = ind;1308 arm64_func_sub_sp_offset = ind;
1282 // In gfunc_epilog these will be replaced with code to decrement SP:1309 /* In gfunc_epilog these will be replaced with stack setup code. */
1283 o(0xd503201f); // nop1310 for (i = 0; i < ARM64_FUNC_STACK_SETUP_SLOTS; ++i)
1284 o(0xd503201f); // nop1311 o(ARM64_NOP); // nop
1285 loc = 0;1312 loc = 0;
1286#ifdef CONFIG_TCC_BCHECK1313#ifdef CONFIG_TCC_BCHECK
1287 if (tcc_state->do_bounds_check)1314 if (tcc_state->do_bounds_check)
@@ -1478,32 +1505,15 @@ ST_FUNC void gfunc_epilog(void) · 190 unmodified lines
1478 1505
1479 if (loc) {1506 if (loc) {
1480 // Insert instructions to subtract size of stack frame from SP.1507 // Insert instructions to subtract size of stack frame from SP.
1481 unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset;1508 int i;
1509 addr_t saved_ind = ind;
1510 addr_t patch_end = arm64_func_sub_sp_offset + ARM64_FUNC_STACK_SETUP_SLOTS * 4;
1482 uint64_t diff = (-loc + 15) & ~15;1511 uint64_t diff = (-loc + 15) & ~15;
1483 if (!(diff >> 24)) {1512 ind = arm64_func_sub_sp_offset;
1484 if (diff & 0xfff) // sub sp,sp,#(diff & 0xfff)1513 arm64_sub_sp(diff);
1485 write32le(ptr, 0xd10003ff | (diff & 0xfff) << 10);1514 for (i = ind; i < patch_end; i += 4)
1486 if (diff >> 12) // sub sp,sp,#(diff >> 12),lsl #121515 write32le(cur_text_section->data + i, ARM64_NOP); // nop
1487 write32le(ptr + 4, 0xd14003ff | (diff >> 12) << 10);1516 ind = saved_ind;
1488 }
1489 else {
1490 // In this case we may subtract more than necessary,
1491 // but always less than 17/16 of what we were aiming for.
1492 int i = 0;
1493 int j = 0;
1494 while (diff >> 20) {
1495 diff = (diff + 0xffff) >> 16;
1496 ++i;
1497 }
1498 while (diff >> 16) {
1499 diff = (diff + 1) >> 1;
1500 ++j;
1501 }
1502 write32le(ptr, 0xd2800010 | diff << 5 | i << 21);
1503 // mov x16,#(diff),lsl #(16 * i)
1504 write32le(ptr + 4, 0xcb3063ff | j << 10);
1505 // sub sp,sp,x16,lsl #(j)
1506 }
1507 }1517 }
1508 o(0x910003bf); // mov sp,x291518 o(0x910003bf); // mov sp,x29
1509 o(0xa8ce7bfd); // ldp x29,x30,[sp],#2241519 o(0xa8ce7bfd); // ldp x29,x30,[sp],#224

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