@@ -296,22 +296,17 @@ static void arm64_spoff(int reg, uint64_t off)
296296 }
297297}
298298
299- /* invert 0: return value to use for store/load */
300- /* invert 1: return value to use for arm64_sym */
301- static uint64_t arm64_check_offset (int invert , int sz_ , uint64_t off )
299+ static uint64_t arm64_check_offset (int sz_ , uint64_t off )
302300{
303301 uint32_t sz = sz_ ;
304302 uint64_t scaled_mask = 0xffful << sz ;
305-
306- if (!(off & ~scaled_mask ) ||
307- (off < 256 || - off <= 256 ))
308- return invert ? off : 0ul ;
309- else if (off & scaled_mask )
310- return invert ? off & scaled_mask : off & ~scaled_mask ;
311- else if (off & 0x1fful )
312- return invert ? off & 0x1fful : off & ~0x1fful ;
313- else
314- return invert ? 0ul : off ;
303+ if (!(off & ~scaled_mask ) || (off < 256 || - off <= 256 ))
304+ return ~0ull ;
305+ if (off & scaled_mask )
306+ return scaled_mask ;
307+ if (off & 0x1fful )
308+ return 0x1fful ;
309+ return 0 ;
315310}
316311
317312static void arm64_ldrx (int sg , int sz_ , int dst , int bas , uint64_t off )
@@ -468,8 +463,41 @@ static void arm64_strv(int sz_, int dst, int bas, uint64_t off)
468463 }
469464}
470465
471- static void arm64_add_offset (int r , unsigned long addend )
466+ static void arm64_sym (int r , Sym * sym , unsigned long addend )
472467{
468+ if (sym -> type .t & VT_TLS ) {
469+ #if TCC_TARGET_PE
470+ Sym * s2 = external_global_sym (TOK___tls_index , & int_type );
471+ int r2 = get_reg (RC_INT );
472+ arm64_sym (30 , s2 , 0 );
473+ o (0xb94003de ); // ldr w30, [x30]
474+ o (0xf9402e40 | r2 ); // ldr r2, [x18, #88]
475+ o (0x8b1e0c1e | r2 << 5 ); // add x30, r2, x30, lsl #3
476+ o (0xf94003c0 | r ); // ldr xr, [x30]
477+ #else
478+ o (0xd53bd040 | r ); /* mrs xr, tpidr_el0 */
479+ #endif
480+ greloca (cur_text_section , sym , ind , R_AARCH64_TLSLE_ADD_TPREL_HI12 , 0 );
481+ /* add xr, xr, #0, lsl #12 */
482+ o (ARM64_ADD_IMM | ARM64_SF (1 ) | ARM64_SH (1 ) | ARM64_RN (r ) | ARM64_RD (r ));
483+ greloca (cur_text_section , sym , ind , R_AARCH64_TLSLE_ADD_TPREL_LO12 , 0 );
484+ /* add xr, xr, #0 */
485+ o (ARM64_ADD_IMM | ARM64_SF (1 ) | ARM64_RN (r ) | ARM64_RD (r ));
486+ goto add_addend ;
487+ }
488+ #ifdef TCC_TARGET_PE
489+ /* PE links symbol addresses directly; there is no ELF-style GOT here. */
490+ greloca (cur_text_section , sym , ind , R_AARCH64_ADR_PREL_PG_HI21 , 0 );
491+ o (ARM64_ADRP | r ); // adrp xr, #sym
492+ greloca (cur_text_section , sym , ind , R_AARCH64_ADD_ABS_LO12_NC , 0 );
493+ o (ARM64_ADD_IMM | ARM64_SF (1 ) | ARM64_RN (r ) | r ); // add xr, xr, #sym
494+ #else
495+ greloca (cur_text_section , sym , ind , R_AARCH64_ADR_GOT_PAGE , 0 );
496+ o (ARM64_ADRP | r ); // adrp xr, #sym
497+ greloca (cur_text_section , sym , ind , R_AARCH64_LD64_GOT_LO12_NC , 0 );
498+ o (ARM64_LDR_X | ARM64_RN (r ) | r ); // ld xr,[xr, #sym]
499+ #endif
500+ add_addend :
473501 if (addend ) {
474502 // add xr, xr, #addend
475503 if (addend & 0xffful )
@@ -484,119 +512,68 @@ static void arm64_add_offset(int r, unsigned long addend)
484512 /* very unlikely */
485513 int t = r ? 0 : 1 ;
486514 o (ARM64_STR_X_PRE | 0x001F0FE0U | t ); /* str xt, [sp, #-16]! */
487- arm64_movimm (t , addend & ~0xfffffful ); // use xt for addent
515+ arm64_movimm (t , addend & ~0xffffffull ); // use xt for addent
488516 o (ARM64_ADD_REG | ARM64_SF (1 ) | ARM64_RM (t ) | ARM64_RN (r ) | r ); /* add xr, xr, xt */
489517 o (ARM64_LDR_X_POST | 0x000107E0U | t ); /* ldr xt, [sp], #16 */
490518 }
491519 }
492520 }
493521}
494522
495- static void arm64_sym (int r , Sym * sym , unsigned long addend )
496- {
497- #ifdef TCC_TARGET_PE
498- /* PE links symbol addresses directly; there is no ELF-style GOT here. */
499- greloca (cur_text_section , sym , ind , R_AARCH64_ADR_PREL_PG_HI21 , 0 );
500- o (ARM64_ADRP | r ); // adrp xr, #sym
501- greloca (cur_text_section , sym , ind , R_AARCH64_ADD_ABS_LO12_NC , 0 );
502- o (ARM64_ADD_IMM | ARM64_SF (1 ) | ARM64_RN (r ) | r ); // add xr, xr, #sym
503- #else
504- greloca (cur_text_section , sym , ind , R_AARCH64_ADR_GOT_PAGE , 0 );
505- o (ARM64_ADRP | r ); // adrp xr, #sym
506- greloca (cur_text_section , sym , ind , R_AARCH64_LD64_GOT_LO12_NC , 0 );
507- o (ARM64_LDR_X | ARM64_RN (r ) | r ); // ld xr,[xr, #sym]
508- #endif
509- arm64_add_offset (r , addend );
510- }
511-
512523static void arm64_load_cmp (int r , SValue * sv );
513524
514- static void arm64_tls_sym (int r , Sym * sym , unsigned long addend )
515- {
516- o (0xd53bd040 | r ); /* mrs xr, tpidr_el0 */
517- greloca (cur_text_section , sym , ind , R_AARCH64_TLSLE_ADD_TPREL_HI12 , 0 );
518- /* add xr, xr, #0, lsl #12 */
519- o (ARM64_ADD_IMM | ARM64_SF (1 ) | ARM64_SH (1 ) | ARM64_RN (r ) | ARM64_RD (r ));
520- greloca (cur_text_section , sym , ind , R_AARCH64_TLSLE_ADD_TPREL_LO12 , 0 );
521- /* add xr, xr, #0 */
522- o (ARM64_ADD_IMM | ARM64_SF (1 ) | ARM64_RN (r ) | ARM64_RD (r ));
523- arm64_add_offset (r , addend );
524- }
525-
526525ST_FUNC void load (int r , SValue * sv )
527526{
528527 int svtt = sv -> type .t ;
529- int svr = sv -> r & ~( VT_BOUNDED | VT_NONCONST );
528+ int svr = sv -> r & ( VT_VALMASK | VT_LVAL | VT_SYM );
530529 int svrv = svr & VT_VALMASK ;
531530 uint64_t svcul = sv -> c .i ;
532- uint64_t svcoff = (uint64_t )(int64_t )(int32_t )sv -> c .i ;
531+ uint64_t svcoff = (int32_t )sv -> c .i ;
532+ int sb = !(svtt & VT_UNSIGNED );
533+ int sz = arm64_type_size (svtt );
533534
534535 if (svr == (VT_LOCAL | VT_LVAL )) {
535536 if (IS_FREG (r ))
536- arm64_ldrv (arm64_type_size ( svtt ) , fltr (r ), 29 , svcoff );
537+ arm64_ldrv (sz , fltr (r ), 29 , svcoff );
537538 else
538- arm64_ldrx (!(svtt & VT_UNSIGNED ), arm64_type_size (svtt ),
539- intr (r ), 29 , svcoff );
539+ arm64_ldrx (sb , sz , intr (r ), 29 , svcoff );
540540 return ;
541541 }
542542
543543 if (svr == (VT_CONST | VT_LVAL )) {
544- uint64_t i = sv -> c .i ;
545-
546- if (sv -> sym && (sv -> sym -> type .t & VT_TLS ))
547- arm64_tls_sym (30 , sv -> sym , 0 );
548- else if (sv -> sym )
549- arm64_sym (30 , sv -> sym , // use x30 for address
550- arm64_check_offset (0 , arm64_type_size (svtt ), i ));
551- else
552- arm64_movimm (30 , i ), i = 0 ;
544+ arm64_movimm (30 , svcul );
553545 if (IS_FREG (r ))
554- arm64_ldrv (arm64_type_size (svtt ), fltr (r ), 30 ,
555- arm64_check_offset (1 , arm64_type_size (svtt ), i ));
546+ arm64_ldrv (sz , fltr (r ), 30 , 0 );
556547 else
557- arm64_ldrx (!(svtt & VT_UNSIGNED ), arm64_type_size (svtt ), intr (r ), 30 ,
558- arm64_check_offset (1 , arm64_type_size (svtt ), i ));
548+ arm64_ldrx (sb , sz , intr (r ), 30 , 0 );
559549 return ;
560550 }
561551
562- if ((svr & ~VT_VALMASK ) == VT_LVAL && svrv < VT_CONST ) {
563- if ((svtt & VT_BTYPE ) != VT_VOID ) {
564- if (IS_FREG (r ))
565- arm64_ldrv (arm64_type_size (svtt ), fltr (r ), intr (svrv ), 0 );
566- else
567- arm64_ldrx (!(svtt & VT_UNSIGNED ), arm64_type_size (svtt ),
568- intr (r ), intr (svrv ), 0 );
569- }
552+ if (svrv < VT_CONST && (svr & VT_LVAL )) {
553+ if (IS_FREG (r ))
554+ arm64_ldrv (sz , fltr (r ), intr (svrv ), 0 );
555+ else
556+ arm64_ldrx (sb , sz , intr (r ), intr (svrv ), 0 );
570557 return ;
571558 }
572559
573560 if (svr == (VT_CONST | VT_LVAL | VT_SYM )) {
574- if (sv -> sym -> type .t & VT_TLS )
575- arm64_tls_sym (30 , sv -> sym , 0 );
576- else
577- arm64_sym (30 , sv -> sym , // use x30 for address
578- arm64_check_offset (0 , arm64_type_size (svtt ), svcoff ));
561+ uint64_t mask = arm64_check_offset (sz , svcoff );
562+ arm64_sym (30 , sv -> sym , svcoff & ~mask );
579563 if (IS_FREG (r ))
580- arm64_ldrv (arm64_type_size (svtt ), fltr (r ), 30 ,
581- arm64_check_offset (1 , arm64_type_size (svtt ), svcoff ));
564+ arm64_ldrv (sz , fltr (r ), 30 , svcoff & mask );
582565 else
583- arm64_ldrx (!(svtt & VT_UNSIGNED ), arm64_type_size (svtt ), intr (r ), 30 ,
584- arm64_check_offset (1 , arm64_type_size (svtt ), svcoff ));
566+ arm64_ldrx (sb , sz , intr (r ), 30 , svcoff & mask );
585567 return ;
586568 }
587569
588570 if (svr == (VT_CONST | VT_SYM )) {
589- if (sv -> sym -> type .t & VT_TLS )
590- arm64_tls_sym (intr (r ), sv -> sym , svcul );
591- else
592- arm64_sym (intr (r ), sv -> sym , svcul );
571+ arm64_sym (intr (r ), sv -> sym , svcul );
593572 return ;
594573 }
595574
596575 if (svr == VT_CONST ) {
597- if ((svtt & VT_BTYPE ) != VT_VOID )
598- arm64_movimm (intr (r ), arm64_type_size (svtt ) == 3 ?
599- sv -> c .i : (uint32_t )svcul );
576+ arm64_movimm (intr (r ), sz == 3 ? svcul : (uint32_t )svcul );
600577 return ;
601578 }
602579
@@ -636,9 +613,9 @@ ST_FUNC void load(int r, SValue *sv)
636613 if (svr == (VT_LLOCAL | VT_LVAL )) {
637614 arm64_ldrx (0 , 3 , 30 , 29 , svcoff ); // use x30 for offset
638615 if (IS_FREG (r ))
639- arm64_ldrv (arm64_type_size ( svtt ) , fltr (r ), 30 , 0 );
616+ arm64_ldrv (sz , fltr (r ), 30 , 0 );
640617 else
641- arm64_ldrx (!( svtt & VT_UNSIGNED ), arm64_type_size ( svtt ) ,
618+ arm64_ldrx (sb , sz ,
642619 intr (r ), 30 , 0 );
643620 return ;
644621 }
@@ -655,63 +632,43 @@ ST_FUNC void load(int r, SValue *sv)
655632ST_FUNC void store (int r , SValue * sv )
656633{
657634 int svtt = sv -> type .t ;
658- int svr = sv -> r & ~ VT_BOUNDED ;
635+ int svr = sv -> r & ( VT_VALMASK | VT_LVAL | VT_SYM ) ;
659636 int svrv = svr & VT_VALMASK ;
660- uint64_t svcoff = (uint64_t )(int64_t )(int32_t )sv -> c .i ;
637+ uint64_t svcoff = (int32_t )sv -> c .i ;
638+ int sz = arm64_type_size (svtt );
661639
662640 if (svr == (VT_LOCAL | VT_LVAL )) {
663641 if (IS_FREG (r ))
664- arm64_strv (arm64_type_size ( svtt ) , fltr (r ), 29 , svcoff );
642+ arm64_strv (sz , fltr (r ), 29 , svcoff );
665643 else
666- arm64_strx (arm64_type_size ( svtt ) , intr (r ), 29 , svcoff );
644+ arm64_strx (sz , intr (r ), 29 , svcoff );
667645 return ;
668646 }
669647
670648 if (svr == (VT_CONST | VT_LVAL )) {
671- uint64_t i = sv -> c .i ;
672- if (sv -> sym && (sv -> sym -> type .t & VT_TLS ))
673- arm64_tls_sym (30 , sv -> sym , 0 );
674- else
675- if (sv -> sym )
676- arm64_sym (30 , sv -> sym , // use x30 for address
677- arm64_check_offset (0 , arm64_type_size (svtt ), i ));
678- else
679- arm64_movimm (30 , i ), i = 0 ;
680-
649+ arm64_movimm (30 , sv -> c .i );
681650 if (IS_FREG (r ))
682- arm64_strv (arm64_type_size (svtt ), fltr (r ), 30 ,
683- arm64_check_offset (1 , arm64_type_size (svtt ), i ));
651+ arm64_strv (sz , fltr (r ), 30 , 0 );
684652 else
685- arm64_strx (arm64_type_size (svtt ), intr (r ), 30 ,
686- arm64_check_offset (1 , arm64_type_size (svtt ), i ));
653+ arm64_strx (sz , intr (r ), 30 , 0 );
687654 return ;
688655 }
689656
690- if (( svr & ~ VT_VALMASK ) == VT_LVAL && svrv < VT_CONST ) {
657+ if (svrv < VT_CONST && ( svr & VT_LVAL ) ) {
691658 if (IS_FREG (r ))
692- arm64_strv (arm64_type_size ( svtt ) , fltr (r ), intr (svrv ), 0 );
659+ arm64_strv (sz , fltr (r ), intr (svrv ), 0 );
693660 else
694- arm64_strx (arm64_type_size ( svtt ) , intr (r ), intr (svrv ), 0 );
661+ arm64_strx (sz , intr (r ), intr (svrv ), 0 );
695662 return ;
696663 }
697664
698665 if (svr == (VT_CONST | VT_LVAL | VT_SYM )) {
699- if (sv -> sym -> type .t & VT_TLS ) {
700- arm64_tls_sym (30 , sv -> sym , 0 );
701- if (IS_FREG (r ))
702- arm64_strv (arm64_type_size (svtt ), fltr (r ), 30 , svcoff );
703- else
704- arm64_strx (arm64_type_size (svtt ), intr (r ), 30 , svcoff );
705- return ;
706- }
707- arm64_sym (30 , sv -> sym , // use x30 for address
708- arm64_check_offset (0 , arm64_type_size (svtt ), svcoff ));
666+ uint64_t mask = arm64_check_offset (sz , svcoff );
667+ arm64_sym (30 , sv -> sym , svcoff & ~mask );
709668 if (IS_FREG (r ))
710- arm64_strv (arm64_type_size (svtt ), fltr (r ), 30 ,
711- arm64_check_offset (1 , arm64_type_size (svtt ), svcoff ));
669+ arm64_strv (sz , fltr (r ), 30 , svcoff & mask );
712670 else
713- arm64_strx (arm64_type_size (svtt ), intr (r ), 30 ,
714- arm64_check_offset (1 , arm64_type_size (svtt ), svcoff ));
671+ arm64_strx (sz , intr (r ), 30 , svcoff & mask );
715672 return ;
716673 }
717674
@@ -1789,9 +1746,9 @@ static int arm64_gen_opic(int op, uint32_t l, int rev, uint64_t val,
17891746 uint32_t s = l ? val >> 63 : val >> 31 ;
17901747 val = s ? - val : val ;
17911748 val = l ? val : (uint32_t )val ;
1792- if (!(val & ~0xffful ))
1749+ if (!(val & ~0xfffull ))
17931750 o (0x11000000 | l << 31 | s << 30 | x | a << 5 | val << 10 );
1794- else if (!(val & ~0xfff000ul ))
1751+ else if (!(val & ~0xfff000ull ))
17951752 o (0x11400000 | l << 31 | s << 30 | x | a << 5 | val >> 12 << 10 );
17961753 else {
17971754 arm64_movimm (30 , val ); // use x30
0 commit comments