Compare commits

...

14 Commits

Author SHA1 Message Date
Aleksi Hannula
cb41cbfe71
x86-64: Fix cvts*2si
Some checks failed
build and test / test-x86_64-linux (push) Has been cancelled
build and test / test-x86_64-osx (push) Has been cancelled
build and test / test-aarch64-osx (push) Has been cancelled
build and test / test-x86_64-win32 (push) Has been cancelled
build and test / test-i386-win32 (push) Has been cancelled
build and test / test-armv7-linux (push) Has been cancelled
build and test / test-aarch64-linux (push) Has been cancelled
build and test / test-riscv64-linux (push) Has been cancelled
Co-authored-by: Herman ten Brugge <hermantenbrugge@home.nl>
2025-12-03 17:21:00 +02:00
Reini Urban
831c3fa184 github CI: pinact run -u
for security
2025-12-02 16:31:13 +01:00
Aleksi Hannula
0fcd46f364
rv64: Generate VT_CMP output from float comparison 2025-12-02 07:30:31 +02:00
Aleksi Hannula
b4569233cb
Set TYPE_PARAM parsing mode in old-style param lists 2025-12-02 07:30:27 +02:00
herman ten brugge
f5f544f436 allow cross compiling for alloca on arm64 2025-12-01 18:09:04 +01:00
Aleksi Hannula
7479a5c21a
elf: Set ph sizes only if ph was allocated 2025-11-29 22:28:36 +02:00
Aleksi Hannula
78e5e690a2
rv64: Implement some pseudo-ops from Zicsr 2025-11-29 21:11:46 +02:00
herman ten brugge
6da45946ae Add bound check support for alloca on all targets
stddef.h, tccdefs.h, tccgen.c, tests/boundtest.c, tests/tcctest.c:
- remove ifdef arround alloca

lib/Makefile:
- move alloca-bt.o to COMMON_O

lib/alloca-bt.S:
- add alloca bound check code for arm, arm64, riscv64

lib/alloca.S:
- check for leading underscore

tcc.h, libtcc.c:
- include arm64-asm.c instead of arm-asm.c for arm64

tcctok.h, tccasm.c:
- add simple reloc support (only for R_AARCH64_CALL26)
2025-11-29 07:54:28 +01:00
Aleksi Hannula
fc424c9f7b
Reorder "pure" attribute
Placing the definition of "pure" prior to TOK_DEFINE would cause it to
be treated as a keyword by tccgen. This breaks building gcc, in which
"pure" is used as a struct field name.
2025-11-28 16:07:24 +02:00
Aleksi Hannula
5b96aeb7fc
Implement some SSE/2 instructions
This patch implements some instructions required by musl 1.1.24.
2025-11-28 15:23:09 +02:00
Aleksi Hannula
06e24e7eed
Implement some RV64F/D instructions
This patch implements some instructions required by musl 1.1.24.
2025-11-28 15:23:07 +02:00
Aleksi Hannula
3c631fdb6d
Implement alloca for RV64 2025-11-28 15:17:06 +02:00
Aleksi Hannula
e7be7b192d
Simplify RV64 function epilogue
Previous sp can be computed based from only frame pointer and short
offset. ra and s0 can be restored from stack with constant fp offset.
2025-11-28 15:17:06 +02:00
H-language
3327327e5d Add WM_MOUSEHWHEEL to winuser.h 2025-11-26 11:10:10 +13:00
19 changed files with 380 additions and 80 deletions

View File

@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 2
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: make & test tcc (x86_64-linux)
run: ./configure && make && make test -k
@ -17,7 +17,7 @@ jobs:
runs-on: macos-13
timeout-minutes: 2
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: make & test tcc (x86_64-osx)
run: ./configure && make && make test -k
@ -25,7 +25,7 @@ jobs:
runs-on: macos-14
timeout-minutes: 2
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: make & test tcc (aarch64-osx)
run: ./configure && make && make test -k
@ -33,7 +33,7 @@ jobs:
runs-on: windows-2025
timeout-minutes: 6
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: make & test tcc (x86_64-win32)
shell: cmd
run: |
@ -44,7 +44,7 @@ jobs:
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc"
echo ::endgroup::
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
- uses: ilammy/msvc-dev-cmd@v1
- uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
with:
arch: amd64
- name: build with MSVC (x86_64-win32)
@ -61,7 +61,7 @@ jobs:
runs-on: windows-2025
timeout-minutes: 6
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: make & test tcc (i386-win32)
shell: cmd
run: |
@ -72,7 +72,7 @@ jobs:
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc"
echo ::endgroup::
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
- uses: ilammy/msvc-dev-cmd@v1
- uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
with:
arch: x86
- name: build with MSVC (i386-win32)
@ -89,8 +89,8 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 8
steps:
- uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@v3
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1
name: make & test tcc (armv7-linux)
with:
arch: armv7
@ -107,8 +107,8 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 8
steps:
- uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@v3
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1
name: make & test tcc (aarch64-linux)
with:
arch: aarch64
@ -125,8 +125,8 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 8
steps:
- uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@v3
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1
name: make & test tcc (riscv64-linux)
with:
arch: riscv64

View File

@ -19,9 +19,7 @@ typedef union { long long __ll; long double __ld; } max_align_t;
#undef offsetof
#define offsetof(type, field) __builtin_offsetof(type, field)
#if defined __i386__ || defined __x86_64__
void *alloca(size_t size);
#endif
#endif

View File

@ -347,12 +347,8 @@
__MAYBE_REDIR(void*, calloc, (__SIZE_TYPE__, __SIZE_TYPE__))
__MAYBE_REDIR(void*, memalign, (__SIZE_TYPE__, __SIZE_TYPE__))
__MAYBE_REDIR(void, free, (void*))
#if defined __i386__ || defined __x86_64__
__BOTH(void*, alloca, (__SIZE_TYPE__))
void *alloca(__SIZE_TYPE__);
#else
__BUILTIN(void*, alloca, (__SIZE_TYPE__))
#endif
__BUILTIN(void, abort, (void))
__BOUND(void, longjmp, ())
#if !defined _WIN32

View File

@ -35,12 +35,12 @@ endif
XFLAGS += -I$(TOP)
I386_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O)
X86_64_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O)
ARM_O = libtcc1.o armeabi.o alloca.o armflush.o $(COMMON_O)
ARM64_O = lib-arm64.o alloca.o $(COMMON_O)
I386_O = libtcc1.o $(COMMON_O)
X86_64_O = libtcc1.o $(COMMON_O)
ARM_O = libtcc1.o armeabi.o armflush.o $(COMMON_O)
ARM64_O = lib-arm64.o $(COMMON_O)
RISCV64_O = lib-arm64.o $(COMMON_O)
COMMON_O = stdatomic.o atomic.o builtin.o
COMMON_O = stdatomic.o atomic.o builtin.o alloca.o alloca-bt.o
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
LIN_O = dsohandle.o
OSX_O =

View File

@ -92,5 +92,109 @@ p3:
ret
#endif
/* ---------------------------------------------- */
#elif defined __arm__
.globl _(__bound_alloca)
_(__bound_alloca):
mov r1, r0
add r0, r0, #1
rsb sp, r0, sp
bic sp, sp, #7
mov r0, sp
push { lr }
bl _(__bound_new_region)
pop { lr }
mov r0, sp
mov pc, lr
/* ---------------------------------------------- */
#elif defined __aarch64__ || defined __arm64__
.globl _(__bound_alloca)
_(__bound_alloca):
#ifdef __TINYC__
.int 0xaa0003e1
.int 0x91004000
.int 0x927cec00
#ifdef _WIN32
.int 0xb4000160
.int 0xd2820002
.int 0xeb02001f
.int 0x540000c3
.int 0xcb2263e3
.int 0xf940007f
.int 0xcb2263ff
.int 0xcb020000
.int 0x17fffffa
.int 0xb4000040
#endif
.int 0xcb2063ff
.int 0x910003e0
.int 0xa9bf7bfd
.reloc ., R_AARCH64_CALL26, _(__bound_new_region)
.int 0x94000000
.int 0xa8c17bfd
.int 0x910003e0
.int 0xd65f03c0
#else
mov x1, x0
add x0, x0, #16 // Round up to 16-byte boundary
and x0, x0, #-16 // Ensure 16-byte alignment
#ifdef _WIN32
cbz x0, p100 // If size is 0, skip to return
// Windows requires page-wise allocation with stack probing
mov x2, #4096 // Page size = 4096 bytes
p101:
cmp x0, x2 // Compare remaining size with page size
b.lo p102 // If less than page, jump to remainder
// Probe first, then allocate
sub x3, sp, x2 // Calculate guard page address (sp - 4096)
ldr xzr, [x3] // Touch guard page FIRST
sub sp, sp, x2 // THEN allocate the page
sub x0, x0, x2 // Decrement remaining size
b p101 // Continue loop
p102:
// Allocate remaining bytes (less than one page)
cbz x0, p100 // If no remaining bytes, skip
sub sp, sp, x0 // Allocate remaining space
#else
// Non-Windows: simple one-time allocation
sub sp, sp, x0 // Allocate space on stack
#endif
p100:
mov x0, sp // Return allocated address
stp x29, x30, [sp, #-16]!
bl _(__bound_new_region)
ldp x29, x30, [sp], #16
mov x0, sp // Return allocated address
ret // Return to caller
#endif
/* ---------------------------------------------- */
#elif defined __riscv
.globl _(__bound_alloca)
_(__bound_alloca):
mv a1, a0
sub sp, sp, a0
addi sp, sp, -16
andi sp, sp, -16
add a0, sp, zero
addi sp,sp,-16
sd s0,0(sp)
sd ra,8(sp)
jal _(__bound_new_region)
ld s0,0(sp)
ld ra,8(sp)
addi sp,sp,16
add a0, sp, zero
ret
/* ---------------------------------------------- */
#endif

View File

@ -70,25 +70,18 @@ p3:
/* ---------------------------------------------- */
#elif defined __arm__
.text
.align 2
.global alloca
.type alloca, %function
alloca:
.globl _(alloca)
_(alloca):
rsb sp, r0, sp
bic sp, sp, #7
mov r0, sp
mov pc, lr
.size alloca, .-alloca
/* ---------------------------------------------- */
#elif defined __aarch64__ || defined __arm64__
.text
.align 2
.global alloca
.type alloca, %function
alloca:
.globl _(alloca)
_(alloca):
#ifdef __TINYC__
.int 0x91003c00
.int 0x927cec00
@ -102,16 +95,16 @@ alloca:
.int 0xcb2163ff
.int 0xcb010000
.int 0x17fffffa
#endif
.int 0xb4000040
#endif
.int 0xcb2063ff
.int 0x910003e0
.int 0xd65f03c0
#else
add x0, x0, #15 // Round up to 16-byte boundary
and x0, x0, #-16 // Ensure 16-byte alignment
cbz x0, p100 // If size is 0, skip to return
#ifdef _WIN32
cbz x0, p100 // If size is 0, skip to return
// Windows requires page-wise allocation with stack probing
mov x1, #4096 // Page size = 4096 bytes
@ -140,6 +133,16 @@ p100:
mov x0, sp // Return allocated address
ret // Return to caller
#endif
.size alloca, .-alloca
/* ---------------------------------------------- */
#elif defined __riscv
.globl _(alloca)
_(alloca):
sub sp, sp, a0
addi sp, sp, -15
andi sp, sp, -16
add a0, sp, zero
ret
#endif

View File

@ -40,7 +40,7 @@
#elif defined(TCC_TARGET_ARM64)
#include "arm64-gen.c"
#include "arm64-link.c"
#include "arm-asm.c"
#include "arm64-asm.c"
#elif defined(TCC_TARGET_C67)
#include "c67-gen.c"
#include "c67-link.c"

View File

@ -63,6 +63,9 @@ static void asm_emit_opcode(uint32_t opcode);
static void asm_emit_r(int token, uint32_t opcode, const Operand *rd, const Operand *rs1, const Operand *rs2);
static void asm_emit_s(int token, uint32_t opcode, const Operand *rs1, const Operand *rs2, const Operand *imm);
static void asm_emit_u(int token, uint32_t opcode, const Operand *rd, const Operand *rs2);
static void asm_emit_f(int token, uint32_t opcode, const Operand *rd, const Operand *rs1, const Operand *rs2);
static void asm_emit_fb(int token, uint32_t opcode, const Operand *rd, const Operand *rs);
static void asm_emit_fq(int token, uint32_t opcode, const Operand *rd, const Operand *rs1, const Operand *rs2, const Operand *rs3);
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
static void asm_nullary_opcode(TCCState *s1, int token);
ST_FUNC void asm_opcode(TCCState *s1, int token);
@ -395,6 +398,15 @@ static void asm_unary_opcode(TCCState *s1, int token)
case TOK_ASM_rdinstreth:
asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_frflags:
asm_emit_opcode(opcode | (0x001 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_frrm:
asm_emit_opcode(opcode | (0x002 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_frcsr:
asm_emit_opcode(opcode | (0x003 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_jr:
/* jalr zero, 0(rs)*/
@ -428,6 +440,7 @@ static void asm_unary_opcode(TCCState *s1, int token)
case TOK_ASM_c_jr:
asm_emit_cr(token, 2 | (8 << 12), &op, &zero);
return;
default:
expect("unary instruction");
}
@ -587,6 +600,14 @@ static void asm_binary_opcode(TCCState* s1, int token)
asm_emit_css(token, 2 | (5 << 13), ops, ops + 1);
return;
/* F/D extension */
case TOK_ASM_fsqrt_d:
asm_emit_fb(token, 0x53 | (11 << 27) | (1 << 25) | (7 << 12), ops, ops + 1);
return;
case TOK_ASM_fsqrt_s:
asm_emit_fb(token, 0x53 | (11 << 27) | (0 << 25) | (7 << 12), ops, ops + 1);
return;
/* pseudoinstructions */
/* rd, sym */
case TOK_ASM_la:
@ -682,6 +703,31 @@ static void asm_binary_opcode(TCCState* s1, int token)
asm_emit_r(token, (0xC << 2) | 3 | (2 << 12), &ops[0], &zero, &ops[1]);
return;
case TOK_ASM_fabs_d:
/* fsgnjx.d rd, rs, rs */
asm_emit_f(token, 0x53 | (4 << 27) | (1 << 25) | (2 << 12), &ops[0], &ops[1], &ops[1]);
return;
case TOK_ASM_fabs_s:
/* fsgnjx.s rd, rs, rs */
asm_emit_f(token, 0x53 | (4 << 27) | (0 << 25) | (2 << 12), &ops[0], &ops[1], &ops[1]);
return;
case TOK_ASM_csrs:
/* csrrs x0, csr, rs */
asm_emit_opcode(0x73 | (2 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].reg));
return;
case TOK_ASM_csrc:
/* csrrc x0, csr, rs */
asm_emit_opcode(0x73 | (3 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].reg));
return;
case TOK_ASM_fsrm:
/* csrrw rd, frm, rs */
asm_emit_opcode(0x73 | (1 << 12) | (2 << 20) | ENCODE_RD(ops[0].reg) | ENCODE_RS1(ops[1].reg));
return;
case TOK_ASM_fscsr:
/* csrrw rd, fcsr, rs */
asm_emit_opcode(0x73 | (1 << 12) | (3 << 20) | ENCODE_RD(ops[0].reg) | ENCODE_RS1(ops[1].reg));
return;
default:
expect("binary instruction");
}
@ -709,6 +755,73 @@ static void asm_emit_r(int token, uint32_t opcode, const Operand* rd, const Oper
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg));
}
/* caller: Add rounding mode, fmt, funct5 to opcode */
static void asm_emit_f(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
{
if (rd->type != OP_REG || !REG_IS_FLOAT(rd->reg)) {
tcc_error("'%s': Expected destination operand that is a floating-point register", get_tok_str(token, NULL));
}
if (rs1->type != OP_REG || !REG_IS_FLOAT(rs1->reg)) {
tcc_error("'%s': Expected first source operand that is a floating-point register", get_tok_str(token, NULL));
}
if (rs2->type != OP_REG || !REG_IS_FLOAT(rs2->reg)) {
tcc_error("'%s': Expected second source operand that is a floating-point register", get_tok_str(token, NULL));
}
/* F-type instruction:
31...27 funct5
26...25 fmt
24...20 rs2
19...15 rs1
14...12 rm
11...7 rd
6...0 opcode = OP-FP */
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg));
}
/* caller: Add rounding mode, fmt, funct5 to opcode */
static void asm_emit_fb(int token, uint32_t opcode, const Operand* rd, const Operand* rs)
{
if (rd->type != OP_REG || !REG_IS_FLOAT(rd->reg)) {
tcc_error("'%s': Expected destination operand that is a floating-point register", get_tok_str(token, NULL));
}
if (rs->type != OP_REG || !REG_IS_FLOAT(rs->reg)) {
tcc_error("'%s': Expected source operand that is a floating-point register", get_tok_str(token, NULL));
}
/* F-type instruction:
31...27 funct5
26...25 fmt
24...20 rs2 = 0
19...15 rs1 = rs
14...12 rm
11...7 rd
6...0 opcode = OP-FP */
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs->reg) | ENCODE_RS2(0));
}
/* caller: Add rounding mode, fmt to opcode */
static void asm_emit_fq(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2, const Operand* rs3)
{
if (rd->type != OP_REG || !REG_IS_FLOAT(rd->reg)) {
tcc_error("'%s': Expected destination operand that is a floating-point register", get_tok_str(token, NULL));
}
if (rs1->type != OP_REG || !REG_IS_FLOAT(rs1->reg)) {
tcc_error("'%s': Expected first source operand that is a floating-point register", get_tok_str(token, NULL));
}
if (rs2->type != OP_REG || !REG_IS_FLOAT(rs2->reg)) {
tcc_error("'%s': Expected second source operand that is a floating-point register", get_tok_str(token, NULL));
}
if (rs3->type != OP_REG || !REG_IS_FLOAT(rs3->reg)) {
tcc_error("'%s': Expected third source operand that is a floating-point register", get_tok_str(token, NULL));
}
/* F-type instruction:
31...27 rs3
26...25 fmt
24...20 rs2
19...15 rs1
14...12 rm
11...7 rd
6...0 opcode */
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg) | (REG_VALUE(rs3->reg) << 27));
}
/* caller: Add funct3 into opcode */
static void asm_emit_i(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
{
@ -1089,11 +1202,49 @@ static void asm_ternary_opcode(TCCState *s1, int token)
asm_emit_cs(token, 6 << 13, ops, ops + 1, ops + 2);
return;
/* F/D extension */
case TOK_ASM_fsgnj_d:
asm_emit_f(token, 0x53 | (4 << 27) | (1 << 25) | (0 << 12), ops, ops + 1, ops + 2);
return;
case TOK_ASM_fsgnj_s:
asm_emit_f(token, 0x53 | (4 << 27) | (0 << 25) | (0 << 12), ops, ops + 1, ops + 2);
return;
case TOK_ASM_fmax_d:
asm_emit_f(token, 0x53 | (5 << 27) | (1 << 25) | (1 << 12), ops, ops + 1, ops + 2);
return;
case TOK_ASM_fmax_s:
asm_emit_f(token, 0x53 | (5 << 27) | (0 << 25) | (1 << 12), ops, ops + 1, ops + 2);
return;
case TOK_ASM_fmin_d:
asm_emit_f(token, 0x53 | (5 << 27) | (1 << 25) | (0 << 12), ops, ops + 1, ops + 2);
return;
case TOK_ASM_fmin_s:
asm_emit_f(token, 0x53 | (5 << 27) | (0 << 25) | (0 << 12), ops, ops + 1, ops + 2);
return;
default:
expect("ternary instruction");
}
}
static void asm_quaternary_opcode(TCCState *s1, int token)
{
Operand ops[4];
parse_operands(s1, &ops[0], 4);
switch (token) {
case TOK_ASM_fmadd_d:
asm_emit_fq(token, 0x43 | (1 << 25) | (7 << 12), ops, ops + 1, ops + 2, ops + 3);
return;
case TOK_ASM_fmadd_s:
asm_emit_fq(token, 0x43 | (0 << 25) | (7 << 12), ops, ops + 1, ops + 2, ops + 3);
return;
default:
expect("quaternary instruction");
}
}
static void asm_atomic_opcode(TCCState *s1, int token)
{
Operand ops[3];
@ -1271,6 +1422,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
case TOK_ASM_lui:
case TOK_ASM_auipc:
case TOK_ASM_fsqrt_s:
case TOK_ASM_fsqrt_d:
asm_binary_opcode(s1, token);
return;
@ -1349,8 +1502,19 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
case TOK_ASM_csrrsi:
case TOK_ASM_csrrw:
case TOK_ASM_csrrwi:
/* F/D extension */
case TOK_ASM_fsgnj_d:
case TOK_ASM_fsgnj_s:
case TOK_ASM_fmax_s:
case TOK_ASM_fmax_d:
case TOK_ASM_fmin_s:
case TOK_ASM_fmin_d:
asm_ternary_opcode(s1, token);
return;
case TOK_ASM_fmadd_d:
case TOK_ASM_fmadd_s:
asm_quaternary_opcode(s1, token);
return;
/* Branches */
case TOK_ASM_beq:
@ -1426,6 +1590,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
case TOK_ASM_jr:
case TOK_ASM_call:
case TOK_ASM_tail:
case TOK_ASM_frflags:
case TOK_ASM_frrm:
case TOK_ASM_frcsr:
asm_unary_opcode(s1, token);
return;
@ -1441,6 +1608,12 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
case TOK_ASM_not:
case TOK_ASM_neg:
case TOK_ASM_negw:
case TOK_ASM_fabs_s:
case TOK_ASM_fabs_d:
case TOK_ASM_csrc:
case TOK_ASM_csrs:
case TOK_ASM_fsrm:
case TOK_ASM_fscsr:
asm_binary_opcode(s1, token);
return;
@ -1556,7 +1729,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
if ((sv->type.t & VT_BTYPE) == VT_FLOAT ||
(sv->type.t & VT_BTYPE) == VT_DOUBLE) {
/* floating point register */
reg = TOK_ASM_f0 + reg;
reg = TOK_ASM_f0 + REG_VALUE(reg);
} else {
/* general purpose register */
reg = TOK_ASM_x0 + reg;
@ -1570,7 +1743,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
if ((sv->type.t & VT_BTYPE) == VT_FLOAT ||
(sv->type.t & VT_BTYPE) == VT_DOUBLE) {
/* floating point register */
reg = TOK_ASM_f0 + reg;
reg = TOK_ASM_f0 + REG_VALUE(reg);
} else {
/* general purpose register */
reg = TOK_ASM_x0 + reg;

View File

@ -911,18 +911,14 @@ ST_FUNC void gfunc_epilog(void)
loc = (loc - num_va_regs * 8);
d = v = (-loc + 15) & -16;
if (v >= (1 << 11)) {
d = 16;
o(0x37 | (5 << 7) | UPPER(v-16)); //lui t0, upper(v)
EI(0x13, 0, 5, 5, SIGN11(v-16)); // addi t0, t0, lo(v)
ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0
}
EI(0x03, 3, 1, 2, d - 8 - num_va_regs * 8); // ld ra, v-8(sp)
EI(0x03, 3, 8, 2, d - 16 - num_va_regs * 8); // ld s0, v-16(sp)
EI(0x13, 0, 2, 2, d); // addi sp, sp, v
EI(0x67, 0, 0, 1, 0); // jalr x0, 0(x1), aka ret
EI(0x13, 0, 2, 8, num_va_regs * 8); // addi sp, s0, num_va_regs*8
EI(0x03, 3, 1, 8, -8); // ld ra, -8(s0)
EI(0x03, 3, 8, 8, -16); // ld s0, -16(s0)
EI(0x67, 0, 0, 1, 0); // jalr x0, 0(x1), aka ret
large_ofs_ind = ind;
if (v >= (1 << 11)) {
d = 16;
EI(0x13, 0, 8, 2, d - num_va_regs * 8); // addi s0, sp, d
o(0x37 | (5 << 7) | UPPER(v-16)); //lui t0, upper(v)
EI(0x13, 0, 5, 5, SIGN11(v-16)); // addi t0, t0, lo(v)
@ -1233,6 +1229,10 @@ ST_FUNC void gen_opf(int op)
ER(0x53, op, rd, rs1, rs2, dbl | 0x50); // fcmp.[sd] RD, RS1, RS2 (op == eq/lt/le)
if (invert)
EI(0x13, 4, rd, rd, 1); // xori RD, 1
/* generate VT_CMP output */
vset_VT_CMP(TOK_NE);
vtop->cmp_r = rd | (0 << 8);
break;
case TOK_NE:
invert = 1;

View File

@ -266,6 +266,19 @@
DEF_ASM(remw)
DEF_ASM(remuw)
/* "F"/"D" Extension for Single/Double-Precision Floating Point Arithmetic, V2.2 */
/* enough implemented for musl */
DEF_ASM_WITH_SUFFIX(fsgnj, s)
DEF_ASM_WITH_SUFFIX(fsgnj, d)
DEF_ASM_WITH_SUFFIX(fmadd, s)
DEF_ASM_WITH_SUFFIX(fmadd, d)
DEF_ASM_WITH_SUFFIX(fmax, s)
DEF_ASM_WITH_SUFFIX(fmax, d)
DEF_ASM_WITH_SUFFIX(fmin, s)
DEF_ASM_WITH_SUFFIX(fmin, d)
DEF_ASM_WITH_SUFFIX(fsqrt, s)
DEF_ASM_WITH_SUFFIX(fsqrt, d)
/* "C" Extension for Compressed Instructions, V2.0 */
DEF_ASM_WITH_SUFFIX(c, nop)
/* Loads */

2
tcc.h
View File

@ -385,7 +385,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
#elif defined TCC_TARGET_ARM64
# include "arm64-gen.c"
# include "arm64-link.c"
# include "arm-asm.c"
# include "arm64-asm.c"
#elif defined TCC_TARGET_C67
# define TCC_TARGET_COFF
# include "coff.h"

View File

@ -984,6 +984,23 @@ static void asm_parse_directive(TCCState *s1, int global)
skip('@');
next();
break;
case TOK_ASMDIR_reloc:
{
ExprValue e;
next();
asm_expr(s1, &e);
skip(',');
#if defined(TCC_TARGET_ARM64)
if (strcmp(get_tok_str(tok, NULL), "R_AARCH64_CALL26"))
#endif
tcc_error("unimp: reloc '%s' unknown", get_tok_str(tok, NULL));
next();
skip(',');
greloca(cur_text_section, get_asm_sym(tok, NULL), e.v, R_AARCH64_CALL26, 0);
next();
}
break;
default:
tcc_error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
break;

View File

@ -2419,8 +2419,10 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
if (s->sh_type != SHT_NOBITS)
file_offset += s->sh_size;
ph->p_filesz = file_offset - ph->p_offset;
ph->p_memsz = addr - ph->p_vaddr;
if (ph) {
ph->p_filesz = file_offset - ph->p_offset;
ph->p_memsz = addr - ph->p_vaddr;
}
}
/* Fill other headers */

View File

@ -1701,10 +1701,8 @@ ST_FUNC void gbound_args(int nb_args)
gfunc_call(1);
func_bound_add_epilog = 1;
}
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
if (v == TOK_alloca)
func_bound_add_epilog = 1;
#endif
#if TARGETOS_NetBSD
if (v == TOK_longjmp) /* undo rename to __longjmp14 */
sv->sym->asm_label = TOK___bound_longjmp;
@ -8744,7 +8742,11 @@ static int decl(int l)
while (1) { /* iterate thru each declaration */
type = btype;
ad = adbase;
type_decl(&type, &ad, &v, TYPE_DIRECT);
if (l == VT_CMP) {
type_decl(&type, &ad, &v, TYPE_DIRECT | TYPE_PARAM);
} else {
type_decl(&type, &ad, &v, TYPE_DIRECT);
}
/*ptype("decl", &type, v);*/
if ((type.t & VT_BTYPE) == VT_FUNC) {

View File

@ -23,8 +23,6 @@
DEF(TOK_CONST1, "const")
DEF(TOK_CONST2, "__const") /* gcc keyword */
DEF(TOK_CONST3, "__const__") /* gcc keyword */
DEF(TOK_PURE1, "pure")
DEF(TOK_PURE2, "__pure__")
DEF(TOK_VOLATILE1, "volatile")
DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
@ -147,6 +145,8 @@
DEF(TOK_ALWAYS_INLINE1, "always_inline")
DEF(TOK_ALWAYS_INLINE2, "__always_inline__")
DEF(TOK_NOINLINE, "__noinline__")
DEF(TOK_PURE1, "pure")
DEF(TOK_PURE2, "__pure__")
DEF(TOK_MODE, "__mode__")
DEF(TOK_MODE_QI, "__QI__")
@ -301,9 +301,7 @@
DEF(TOK___fixxfdi, "__fixxfdi")
#endif
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
DEF(TOK_alloca, "alloca")
#endif
#if defined TCC_TARGET_PE
DEF(TOK___chkstk, "__chkstk")
@ -415,6 +413,7 @@
DEF_ASMDIR(long)
DEF_ASMDIR(int)
DEF_ASMDIR(symver)
DEF_ASMDIR(reloc)
DEF_ASMDIR(section) /* must be last directive */
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64

View File

@ -169,14 +169,6 @@ int test13(void)
return strlen(tab);
}
#if defined __i386__ || defined __x86_64__
#define allocf(x)
#else
#undef alloca
#define alloca(x) malloc(x)
#define allocf(x) free(x)
#endif
int test14(void)
{
char *p = alloca(TAB_SIZE);
@ -184,7 +176,6 @@ int test14(void)
memset(p, 'a', TAB_SIZE);
p[TAB_SIZE-1] = 0;
ret = strlen(p);
allocf(p);
return ret;
}
@ -196,7 +187,6 @@ int test15(void)
memset(p, 'a', TAB_SIZE);
p[TAB_SIZE-1] = 0;
ret = strlen(p);
allocf(p);
return ret;
}
@ -211,8 +201,6 @@ int test16()
/* Test alloca embedded in a larger expression */
printf("alloca : %s : %s\n", p, strcpy(q=alloca(strlen(demo)+1),demo) );
allocf(p);
allocf(q);
return 0;
}
@ -228,8 +216,6 @@ int test17()
/* Test alloca embedded in a larger expression */
printf("alloca : %s : %s\n", p, strcpy(q=alloca(strlen(demo)),demo) );
allocf(p);
allocf(q);
return 0;
}

View File

@ -2941,14 +2941,12 @@ void old_style_function_test(void)
void alloca_test()
{
#if defined __i386__ || defined __x86_64__ || defined __arm__
char *p = alloca(16);
strcpy(p,"123456789012345");
printf("alloca: p is %s\n", p);
char *demo = "This is only a test.\n";
/* Test alloca embedded in a larger expression */
printf("alloca: %s\n", strcpy(alloca(strlen(demo)+1),demo) );
#endif
}
void *bounds_checking_is_enabled()
@ -4208,7 +4206,6 @@ double get100 () { return 100.0; }
void callsave_test(void)
{
#if defined __i386__ || defined __x86_64__ || defined __arm__
int i, s; double *d; double t;
s = sizeof (double);
printf ("callsavetest: %d\n", s);
@ -4221,7 +4218,6 @@ void callsave_test(void)
generates a segfault. */
i = d[0] > get100 ();
printf ("%d\n", i);
#endif
}

View File

@ -1173,7 +1173,8 @@ extern "C" {
#define WM_XBUTTONDOWN 0x020B
#define WM_XBUTTONUP 0x020C
#define WM_XBUTTONDBLCLK 0x020D
#define WM_MOUSELAST 0x020D
#define WM_MOUSEHWHEEL 0x020E
#define WM_MOUSELAST 0x020E
#define WHEEL_DELTA 120
#define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))

View File

@ -509,7 +509,12 @@ ALT(DEF_ASM_OP2(movhps, 0x0f17, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
DEF_ASM_OP2(addps, 0x0f58, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
DEF_ASM_OP2(cvtpi2ps, 0x0f2a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_SSE )
DEF_ASM_OP2(cvtps2pi, 0x0f2d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX )
DEF_ASM_OP2(cvtss2si, 0xf30f2d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_REG32 )
ALT(DEF_ASM_OP2(cvtss2si, 0xf30f2d, 0, OPC_MODRM | OPC_48, OPT_EA | OPT_SSE, OPT_REG64 ))
DEF_ASM_OP2(cvtsd2si, 0xf20f2d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_REG32 )
ALT(DEF_ASM_OP2(cvtsd2si, 0xf20f2d, 0, OPC_MODRM | OPC_48, OPT_EA | OPT_SSE, OPT_REG64 ))
DEF_ASM_OP2(cvttps2pi, 0x0f2c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX )
DEF_ASM_OP2(andps, 0x0f54, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
DEF_ASM_OP2(divps, 0x0f5e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
DEF_ASM_OP2(maxps, 0x0f5f, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
DEF_ASM_OP2(minps, 0x0f5d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
@ -523,8 +528,13 @@ ALT(DEF_ASM_OP2(movhps, 0x0f17, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
DEF_ASM_OP2(rcpss, 0x0f53, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
DEF_ASM_OP2(rsqrtps, 0x0f52, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
DEF_ASM_OP2(sqrtps, 0x0f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
DEF_ASM_OP2(sqrtss, 0xf30f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
DEF_ASM_OP2(subps, 0x0f5c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
/* sse2 */
DEF_ASM_OP2(andpd, 0x660f54, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE)
DEF_ASM_OP2(sqrtsd, 0xf20f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE)
/* movnti should only accept REG32 and REG64, we accept more */
DEF_ASM_OP2(movnti, 0x0fc3, 0, OPC_MODRM, OPT_REG, OPT_EA)
DEF_ASM_OP2(movntil, 0x0fc3, 0, OPC_MODRM, OPT_REG32, OPT_EA)