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
993993 return n_args;
994994 }
995995
996+static 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+
9961022 ST_FUNC void gfunc_call(int nb_args)
9971023 {
9981024 CType *return_type;
@@ -1039,10 +1065,7 @@ ST_FUNC void gfunc_call(int nb_args) · 40 unmodified lines
10391065
10401066 if (stack >= 0x1000000) // 16Mb
10411067 tcc_error("stack size too big %lu", stack);
1042− if (stack & 0xfff)
1043− o(0xd10003ff | (stack & 0xfff) << 10); // sub sp,sp,#(n)
1044− if (stack >> 12)
1045− o(0xd14003ff | (stack >> 12) << 10);
1068+ arm64_sub_sp(stack);
10461069
10471070 // First pass: set all values on stack
10481071 for (i = nb_args; i; i--) {
@@ -1178,6 +1201,9 @@ static int arm64_func_va_list_gr_offs; · 129 unmodified lines
11781201 static int arm64_func_va_list_vr_offs;
11791202 static int arm64_func_sub_sp_offset;
11801203
1204+static unsigned arm64_func_start_offset;
1205+#define ARM64_FUNC_STACK_SETUP_SLOTS 6
1206+
11811207 ST_FUNC void gfunc_prolog(Sym *func_sym)
11821208 {
11831209 CType *func_type = &func_sym->type;
@@ -1229,6 +1255,7 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 45 unmodified lines
12291255 last_int = last_int > 4 ? 4 : last_int;
12301256 last_float = last_float > 4 ? 4 : last_float;
12311257
1258+ arm64_func_start_offset = ind;
12321259 o(0xa9b27bfd); // stp x29,x30,[sp,#-224]!
12331260 for (i = 0; i < last_float; i++)
12341261 // 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
12791306
12801307 o(0x910003fd); // mov x29,sp
12811308 arm64_func_sub_sp_offset = ind;
1282− // In gfunc_epilog these will be replaced with code to decrement SP:
1283− o(0xd503201f); // nop
1284− o(0xd503201f); // nop
1309+ /* In gfunc_epilog these will be replaced with stack setup code. */
1310+ for (i = 0; i < ARM64_FUNC_STACK_SETUP_SLOTS; ++i)
1311+ o(ARM64_NOP); // nop
12851312 loc = 0;
12861313 #ifdef CONFIG_TCC_BCHECK
12871314 if (tcc_state->do_bounds_check)
@@ -1478,32 +1505,15 @@ ST_FUNC void gfunc_epilog(void) · 190 unmodified lines
14781505
14791506 if (loc) {
14801507 // 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;
14821511 uint64_t diff = (-loc + 15) & ~15;
1483− if (!(diff >> 24)) {
1484− if (diff & 0xfff) // sub sp,sp,#(diff & 0xfff)
1485− write32le(ptr, 0xd10003ff | (diff & 0xfff) << 10);
1486− if (diff >> 12) // sub sp,sp,#(diff >> 12),lsl #12
1487− write32le(ptr + 4, 0xd14003ff | (diff >> 12) << 10);
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− }
1512+ ind = arm64_func_sub_sp_offset;
1513+ arm64_sub_sp(diff);
1514+ for (i = ind; i < patch_end; i += 4)
1515+ write32le(cur_text_section->data + i, ARM64_NOP); // nop
1516+ ind = saved_ind;
15071517 }
15081518 o(0x910003bf); // mov sp,x29
15091519 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