Skip to content

Commit 8c4e673

Browse files
author
grischka
committed
arm bits
arm-asm.c: add forward branches & some ops lib/armeabi.c: faster i/udivmod (asm) arm-gen.c: use movw/movt to load constants for CPUVER >= 70 configure: use dwarf-4 debug sections on android, detect idiv lib/Makefile: always add -I$(TOP) for access to config.h tcdbg.c: add a "code mapping symbol" to help out llvm-objdump tccelf.c: don't load SHT_ARM_EXIDX, modify ARM.attributes tccpp.c: accept '@' for arm asm comments
1 parent 0061744 commit 8c4e673

File tree

9 files changed

+174
-21
lines changed

9 files changed

+174
-21
lines changed

arm-asm.c

+28-4
Original file line numberDiff line numberDiff line change
@@ -971,13 +971,22 @@ static void asm_multiplication_opcode(TCCState *s1, int token)
971971
opcode |= 1 << 20; // Status
972972
/* fallthrough */
973973
case TOK_ASM_mlaeq:
974+
case_TOK_ASM_mlaeq:
974975
if (nb_ops != 4)
975976
expect("four operands");
976977
else {
977978
opcode |= 1 << 21; // Accumulate
978979
asm_emit_opcode(token, opcode);
979980
}
980981
break;
982+
case TOK_ASM_mlseq:
983+
opcode |= 0x00400000;
984+
goto case_TOK_ASM_mlaeq;
985+
case TOK_ASM_udiveq:
986+
opcode |= 0x00200000;
987+
case TOK_ASM_sdiveq:
988+
asm_emit_opcode(token, (opcode & ~0x80) | 0x0710f010);
989+
break;
981990
default:
982991
expect("known multiplication instruction");
983992
}
@@ -1084,6 +1093,7 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token)
10841093
next(); // skip ','
10851094

10861095
switch (ARM_INSTRUCTION_GROUP(token)) {
1096+
case TOK_ASM_strexheq:
10871097
case TOK_ASM_strexbeq:
10881098
case TOK_ASM_strexeq:
10891099
parse_operand(s1, &strex_operand);
@@ -1200,6 +1210,8 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token)
12001210
opcode |= asm_encode_shift(&shift);
12011211
asm_emit_opcode(token, opcode);
12021212
break;
1213+
case TOK_ASM_strexheq:
1214+
opcode |= 1 << 21;
12031215
case TOK_ASM_strexbeq:
12041216
opcode |= 1 << 22; // B
12051217
/* fallthrough */
@@ -1217,6 +1229,8 @@ static void asm_single_data_transfer_opcode(TCCState *s1, int token)
12171229
opcode |= strex_operand.reg;
12181230
asm_emit_opcode(token, opcode);
12191231
break;
1232+
case TOK_ASM_ldrexheq:
1233+
opcode |= 1 << 21;
12201234
case TOK_ASM_ldrexbeq:
12211235
opcode |= 1 << 22; // B
12221236
/* fallthrough */
@@ -2305,11 +2319,16 @@ static void asm_branch_opcode(TCCState *s1, int token)
23052319
case TOK_ASM_beq:
23062320
case TOK_ASM_bleq:
23072321
asm_expr(s1, &e);
2308-
esym = elfsym(e.sym);
2309-
if (!esym || esym->st_shndx != cur_text_section->sh_num) {
2310-
tcc_error("invalid branch target");
2322+
if (e.sym) {
2323+
esym = elfsym(e.sym);
2324+
if (esym && esym->st_shndx == cur_text_section->sh_num) {
2325+
jmp_disp = esym->st_value;
2326+
} else {
2327+
greloca(cur_text_section, e.sym, ind, R_ARM_PC24, 0);
2328+
jmp_disp = ind;
2329+
}
23112330
}
2312-
jmp_disp = encbranchoffset(ind, e.v + esym->st_value, 1);
2331+
jmp_disp = encbranchoffset(ind, e.v + jmp_disp, 1);
23132332
break;
23142333
default:
23152334
parse_operand(s1, &op);
@@ -2409,8 +2428,10 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
24092428
case TOK_ASM_strbeq:
24102429
case TOK_ASM_ldrexeq:
24112430
case TOK_ASM_ldrexbeq:
2431+
case TOK_ASM_ldrexheq:
24122432
case TOK_ASM_strexeq:
24132433
case TOK_ASM_strexbeq:
2434+
case TOK_ASM_strexheq:
24142435
asm_single_data_transfer_opcode(s1, token);
24152436
return;
24162437

@@ -2473,6 +2494,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
24732494
case TOK_ASM_mulseq:
24742495
case TOK_ASM_mlaeq:
24752496
case TOK_ASM_mlaseq:
2497+
case TOK_ASM_mlseq:
2498+
case TOK_ASM_udiveq:
2499+
case TOK_ASM_sdiveq:
24762500
asm_multiplication_opcode(s1, token);
24772501
return;
24782502

arm-gen.c

+9
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,15 @@ static int negcc(int cc)
541541
Use relative/got addressing to avoid setting DT_TEXTREL */
542542
static void load_value(SValue *sv, int r)
543543
{
544+
#if CONFIG_TCC_CPUVER >= 7
545+
if (!(sv->r & VT_SYM)) {
546+
unsigned x=sv->c.i;
547+
o(0xE3000000|intr(r)<<12|(x&0xFFF)|(x<<4&0xF0000)); /* movw rx,#x(lo) */
548+
if (x&0xFFFF0000)
549+
o(0xE3400000|intr(r)<<12|(x>>16&0xFFF)|(x>>12&0xF0000)); /* movt rx,#x(hi) */
550+
return;
551+
}
552+
#endif
544553
o(0xE59F0000|(intr(r)<<12)); /* ldr r, [pc] */
545554
o(0xEA000000); /* b $+4 */
546555
#ifndef CONFIG_TCC_PIC

arm-tok.h

+5
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@
238238
DEF_ASM_CONDED(smlals)
239239
DEF_ASM_CONDED(umlal)
240240
DEF_ASM_CONDED(umlals)
241+
DEF_ASM_CONDED(mls)
242+
DEF_ASM_CONDED(udiv)
243+
DEF_ASM_CONDED(sdiv)
241244

242245
/* load/store */
243246

@@ -247,8 +250,10 @@
247250
DEF_ASM_CONDED(strb)
248251
DEF_ASM_CONDED(ldrex)
249252
DEF_ASM_CONDED(ldrexb)
253+
DEF_ASM_CONDED(ldrexh)
250254
DEF_ASM_CONDED(strex)
251255
DEF_ASM_CONDED(strexb)
256+
DEF_ASM_CONDED(strexh)
252257
DEF_ASM_CONDED(ldrh)
253258
DEF_ASM_CONDED(ldrsh)
254259
DEF_ASM_CONDED(ldrsb)

configure

+7-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ case $targetos in
381381
default sysroot "/usr"
382382
fi
383383
default prefix "${sysroot}"
384-
confvars_set Android new_dtags rpath=no
384+
confvars_set Android new_dtags rpath=no dwarf=4
385385
test "${cpu}" != "i386" && confvars_set pie
386386
default_conf "static=no"
387387
case "$cpu" in
@@ -510,6 +510,11 @@ if test "$cpu" = "arm"; then
510510
confvars_set arm_vfp
511511
fi
512512
fi
513+
if test -z "$build_cross"; then
514+
if grep -s -q "^Features.* \(idiv\)" /proc/cpuinfo ; then
515+
confvars_set arm_idiv
516+
fi
517+
fi
513518
fi
514519

515520
# a final configuration tuning
@@ -648,6 +653,7 @@ for v in $cpu $confvars ; do
648653
print_num TCC_ARM_HARDFLOAT 1 ;;
649654
CONFIG_arm_eabi=yes) print_num TCC_ARM_EABI 1 ;;
650655
CONFIG_arm_vfp=yes) print_num TCC_ARM_VFP 1 ;;
656+
CONFIG_arm_idiv=yes) print_num __ARM_FEATURE_IDIV 1 ;;
651657
# OS
652658
CONFIG_WIN32=yes) print_num TCC_TARGET_PE 1 ;;
653659
CONFIG_OSX=yes) print_num TCC_TARGET_MACHO 1 ;;

lib/Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ ifeq "$($(T)-libtcc1-usegcc)" "yes"
3333
BFLAGS = $(if $(CONFIG_dwarf),-gdwarf,-gstabs)
3434
endif
3535

36+
XFLAGS += -I$(TOP)
37+
3638
I386_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O)
3739
X86_64_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O)
3840
ARM_O = libtcc1.o armeabi.o alloca.o armflush.o $(COMMON_O)
@@ -91,9 +93,7 @@ $(X)%.o : %.S $(TCC)
9193
$(TOP)/%.o : %.c $(TCC)
9294
$S$(XCC) -c $< -o $@ $(XFLAGS)
9395

94-
$(TOP)/bcheck.o : XFLAGS += $(BFLAGS) -I$(TOP)
95-
# includes tccrun.c, $(TOP) for config.h (tccrun.c prerequisite via $(TCC))
96-
$(TOP)/bt-exe.o : XFLAGS += -I$(TOP)
96+
$(TOP)/bcheck.o : XFLAGS += $(BFLAGS)
9797

9898
$(X)crt1w.o : crt1.c
9999
$(X)wincrt1w.o : wincrt1.c

lib/armeabi.c

+100-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ typedef struct unsigned_int_struct {
4747
} unsigned_int_struct;
4848

4949
#define REGS_RETURN(name, type) \
50-
void name ## _return(type ret) {}
50+
static void name ## _return(type ret) {}
5151

5252

5353
/* Float helper functions */
@@ -339,7 +339,7 @@ __AEABI_XL2D(ul2d, 0)
339339
/* long long to double conversion */
340340
__AEABI_XL2D(l2d, 1)
341341

342-
342+
#if 1
343343
/* Long long helper functions */
344344

345345
/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
@@ -474,6 +474,7 @@ void __aeabi_lasr(unsigned_int_struct val, int shift)
474474

475475
/* Integer division functions */
476476

477+
#if 0 /* very slow */
477478
AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
478479

479480
int __aeabi_idiv(int numerator, int denominator)
@@ -506,6 +507,9 @@ void __aeabi_uidivmod(unsigned num, unsigned den)
506507
{
507508
uidiv_t_return(aeabi_uidivmod(num, den));
508509
}
510+
#else
511+
# define UIDIVMOD_ASM 1
512+
#endif
509513

510514
/* Some targets do not have all eabi calls (OpenBSD) */
511515
typedef __SIZE_TYPE__ size_t;
@@ -542,3 +546,97 @@ __aeabi_memset (void *s, size_t n, int c)
542546
{
543547
return memset (s, c, n);
544548
}
549+
550+
/* ***************************************************************** */
551+
#if UIDIVMOD_ASM
552+
#include <config.h>
553+
__asm__(
554+
"\n .global __aeabi_idiv, __aeabi_idivmod"
555+
"\n .global __aeabi_uidiv, __aeabi_uidivmod"
556+
#if __ARM_FEATURE_IDIV
557+
"\n__aeabi_idiv:"
558+
"\n__aeabi_idivmod:"
559+
"\n mov r2, r0"
560+
"\n sdiv r0, r0, r1"
561+
"\n mls r1, r1, r0, r2"
562+
"\n bx lr"
563+
564+
"\n__aeabi_uidiv:"
565+
"\n__aeabi_uidivmod:"
566+
"\n mov r2, r0"
567+
"\n udiv r0, r0, r1"
568+
"\n mls r1, r1, r0, r2"
569+
"\n bx lr"
570+
#else
571+
/* Runtime ABI for the ARM Cortex-M0
572+
* idivmod.S: signed 32 bit division (quotient and remainder)
573+
*
574+
* Copyright (c) 2012 Jörg Mische <[email protected]>
575+
*
576+
* Permission to use, copy, modify, and/or distribute this software for any
577+
* purpose with or without fee is hereby granted, provided that the above
578+
* copyright notice and this permission notice appear in all copies.
579+
*/
580+
"\n__aeabi_idiv:"
581+
"\n__aeabi_idivmod:"
582+
"\n cmp r0, #0"
583+
"\n bge .Lnumerator_pos"
584+
"\n rsb r0, r0, #0" // num = -num
585+
"\n cmp r1, #0"
586+
"\n bge .Lboth_neg"
587+
"\n rsb r1, r1, #0" // den = -den
588+
"\n push {lr}"
589+
"\n bl __aeabi_uidivmod"
590+
"\n rsb r1, r1, #0" // rem = -rem
591+
"\n pop {pc}"
592+
"\n.Lboth_neg:"
593+
"\n push {lr}"
594+
"\n bl __aeabi_uidivmod"
595+
"\n rsb r0, r0, #0" // quot = -quot
596+
"\n rsb r1, r1, #0" // rem = -rem
597+
"\n pop {pc}"
598+
"\n.Ldenom_neg:"
599+
"\n rsb r1, r1, #0" // den = -den
600+
"\n push {lr}"
601+
"\n bl __aeabi_uidivmod"
602+
"\n rsb r0, r0, #0" // quot = -quot
603+
"\n pop {pc}"
604+
"\n.Lnumerator_pos:"
605+
"\n cmp r1, #0"
606+
"\n blt .Ldenom_neg"
607+
608+
// Divide r0 by r1 and return the quotient in r0 and the remainder in r1
609+
"\n__aeabi_uidiv:"
610+
"\n__aeabi_uidivmod:"
611+
// Shift left the denominator until it is greater than the numerator
612+
"\n mov r2, #1" // counter
613+
"\n mov r3, #0" // result
614+
"\n cmp r0, r1"
615+
"\n bls .Lsub_loop"
616+
"\n adds r1, #0" // dont shift if denominator would overflow
617+
"\n bmi .Lsub_loop"
618+
"\n beq .Luidiv0"
619+
"\n.Ldenom_shift_loop:"
620+
"\n lsl r2, #1"
621+
"\n lsls r1, #1"
622+
"\n bmi .Lsub_loop"
623+
"\n cmp r0, r1"
624+
"\n bhi .Ldenom_shift_loop"
625+
"\n.Lsub_loop:"
626+
"\n cmp r0, r1" // if (num >= den)...
627+
"\n subcs r0, r1" // numerator -= denom
628+
"\n orrcs r3, r2" // result(r3) |= bitmask(r2)
629+
"\n lsr r1, #1" // denom(r1) >>= 1
630+
"\n lsrs r2, #1" // bitmask(r2) >>= 1
631+
"\n bne .Lsub_loop"
632+
"\n mov r1, r0" // remainder(r1) = numerator(r0)
633+
"\n mov r0, r3" // quotient(r0) = result(r3)
634+
"\n bx lr"
635+
"\n.Luidiv0:" // XXX: division by zero
636+
"\n mov r0, #0"
637+
"\n bx lr"
638+
#endif
639+
);
640+
#endif /* UIDIVMOD_ASM */
641+
/* ***************************************************************** */
642+
#endif

tccdbg.c

+5
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,11 @@ ST_FUNC void tcc_debug_start(TCCState *s1)
10231023
SHN_ABS, filename);
10241024

10251025
if (s1->do_debug) {
1026+
/* put a "mapping symbol" '$a' for llvm-objdump etc. tools needed
1027+
to make them disassemble again when crt1.o had a '$d' before */
1028+
put_elf_sym(symtab_section, text_section->data_offset, 0,
1029+
ELFW(ST_INFO)(STB_LOCAL, STT_NOTYPE), 0,
1030+
text_section->sh_num, "$a");
10261031

10271032
new_file = last_line_num = 0;
10281033
debug_next_type = N_DEFAULT_DEBUG;

tccelf.c

+10-10
Original file line numberDiff line numberDiff line change
@@ -2115,15 +2115,6 @@ static int set_sec_sizes(TCCState *s1)
21152115
|| s1->do_debug) {
21162116
s->sh_size = s->data_offset;
21172117
}
2118-
2119-
#ifdef TCC_TARGET_ARM
2120-
/* XXX: Suppress stack unwinding section. */
2121-
if (s->sh_type == SHT_ARM_EXIDX) {
2122-
s->sh_flags = 0;
2123-
s->sh_size = 0;
2124-
}
2125-
#endif
2126-
21272118
}
21282119
return textrel;
21292120
}
@@ -2762,7 +2753,11 @@ static void create_arm_attribute_section(TCCState *s1)
27622753
'a', 'e', 'a', 'b', 'i', 0x00, // "aeabi"
27632754
0x01, 0x22, 0x00, 0x00, 0x00, // 'File Attributes', size 0x22
27642755
0x05, 0x36, 0x00, // 'CPU_name', "6"
2756+
#if CONFIG_TCC_CPUVER >= 7
2757+
0x06, 0x0a, // 'CPU_arch', 'v7'
2758+
#else
27652759
0x06, 0x06, // 'CPU_arch', 'v6'
2760+
#endif
27662761
0x08, 0x01, // 'ARM_ISA_use', 'Yes'
27672762
0x09, 0x01, // 'THUMB_ISA_use', 'Thumb-1'
27682763
0x0a, 0x02, // 'FP_arch', 'VFPv2'
@@ -3184,8 +3179,13 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
31843179
sh->sh_type != SHT_INIT_ARRAY &&
31853180
sh->sh_type != SHT_FINI_ARRAY
31863181
#ifdef TCC_ARM_EABI
3187-
&& sh->sh_type != SHT_ARM_EXIDX
3182+
/* Added in commit f99d3de221db23e322c6c18c8249282e27726c25
3183+
but suppressed in 3cfaaaf1eb97d858e583412616f68f75fdad5da5
3184+
So don't load it in order to avoid dangling references from
3185+
(STT_SECTION) symbols. */
3186+
// && sh->sh_type != SHT_ARM_EXIDX
31883187
#endif
3188+
31893189
#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
31903190
&& sh->sh_type != SHT_X86_64_UNWIND
31913191
#endif

tccpp.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -2933,6 +2933,13 @@ static void next_nomacro(void)
29332933
break;
29342934

29352935
/* simple tokens */
2936+
case '@': /* only used in assembler */
2937+
#ifdef TCC_TARGET_ARM /* comment on arm asm */
2938+
if (parse_flags & PARSE_FLAG_ASM_FILE) {
2939+
p = parse_line_comment(p);
2940+
goto redo_no_start;
2941+
}
2942+
#endif
29362943
case '(':
29372944
case ')':
29382945
case '[':
@@ -2944,7 +2951,6 @@ static void next_nomacro(void)
29442951
case ':':
29452952
case '?':
29462953
case '~':
2947-
case '@': /* only used in assembler */
29482954
parse_simple:
29492955
tok = c;
29502956
p++;

0 commit comments

Comments
 (0)