arm64-win32 support : tests

This commit is contained in:
Benjamin Oldenburg 2026-04-04 16:29:28 +02:00 committed by grischka
parent 03d58b0746
commit ea823189d6
9 changed files with 972 additions and 0 deletions

View File

@ -338,7 +338,16 @@ int main(int argc, char **argv)
#else
#include <tcclib.h>
#ifdef _WIN32
# ifdef __i386__
# define LIBTCC_TEST_WINAPI __attribute__((__stdcall__))
# else
# define LIBTCC_TEST_WINAPI
# endif
void LIBTCC_TEST_WINAPI Sleep(unsigned int milliseconds);
#else
unsigned int sleep(unsigned int seconds);
#endif
int fib(n)
{
@ -347,7 +356,11 @@ int fib(n)
int main(int argc, char **argv)
{
#ifdef _WIN32
Sleep(1000);
#else
sleep(1);
#endif
printf(" %d", fib(atoi(argv[1])));
return 0;
}

View File

@ -0,0 +1,280 @@
/* ARM64 instruction encoding verification test.
Exercises shift-by-immediate, load/store addressing modes,
conditional branches, and system register access. */
#include <stdio.h>
#include <stdint.h>
/* ---- shift-by-immediate helpers ---- */
static uint32_t lsl32(uint32_t x, int n) { return x << n; }
static uint32_t lsr32(uint32_t x, int n) { return x >> n; }
static int32_t asr32(int32_t x, int n) { return x >> n; }
static uint64_t lsl64(uint64_t x, int n) { return x << n; }
static uint64_t lsr64(uint64_t x, int n) { return x >> n; }
static int64_t asr64(int64_t x, int n) { return x >> n; }
static void test_shifts(void)
{
printf("shift-imm:\n");
printf("%x\n", lsl32(1, 0));
printf("%x\n", lsl32(1, 15));
printf("%x\n", lsl32(1, 31));
printf("%x\n", lsr32(0x80000000U, 31));
printf("%x\n", lsr32(0x80000000U, 16));
printf("%x\n", asr32(-1, 1));
printf("%x\n", asr32(-256, 4));
printf("%llx\n", (unsigned long long)lsl64(1ULL, 0));
printf("%llx\n", (unsigned long long)lsl64(1ULL, 32));
printf("%llx\n", (unsigned long long)lsl64(1ULL, 63));
printf("%llx\n", (unsigned long long)lsr64(0x8000000000000000ULL, 63));
printf("%llx\n", (unsigned long long)asr64(-1LL, 1));
printf("%llx\n", (unsigned long long)asr64(-256LL, 4));
}
/* ---- load/store with various addressing modes ---- */
static void test_ldr_str(void)
{
int64_t buf[4] = { 0x1122334455667788LL, 0x99AABBCCDDEEFF00LL,
0x0F1E2D3C4B5A6978LL, 0x0000000000000001LL };
int64_t val;
int32_t wval;
int64_t *p;
printf("ldr-str:\n");
/* LDR X, [Xn, #offset] */
val = buf[0];
printf("%llx\n", (unsigned long long)val);
val = buf[1];
printf("%llx\n", (unsigned long long)val);
/* LDR W, [Xn, #offset] (32-bit load) */
wval = *(int32_t*)&buf[0];
printf("%x\n", (unsigned)wval);
/* Pre-indexed: store pointer, modify */
p = &buf[0];
val = *(p + 2);
printf("%llx\n", (unsigned long long)val);
/* Post-indexed simulation via pointer arithmetic */
p = &buf[0];
val = *p;
p++;
printf("%llx %llx\n", (unsigned long long)val,
(unsigned long long)*p);
}
/* ---- STP/LDP (store/load pair) ---- */
static void test_ldp_stp(void)
{
int64_t src[2] = { 0xAAAABBBBCCCCDDDDLL, 0x1111222233334444LL };
int64_t dst[2];
/* The compiler should use stp/ldp for this */
dst[0] = src[0];
dst[1] = src[1];
printf("ldp-stp:\n");
printf("%llx %llx\n",
(unsigned long long)dst[0],
(unsigned long long)dst[1]);
}
/* ---- CBZ / CBNZ via C patterns ---- */
static const char *cbz_test(int x)
{
if (x == 0)
return "zero";
return "nonzero";
}
static const char *cbnz_test(int x)
{
if (x != 0)
return "nonzero";
return "zero";
}
static void test_cond_branches(void)
{
printf("cbz-cbnz:\n");
printf("%s\n", cbz_test(0));
printf("%s\n", cbz_test(42));
printf("%s\n", cbnz_test(0));
printf("%s\n", cbnz_test(42));
}
/* ---- conditional compare patterns (CCMP/CCMN) ---- */
static int cond_select(int a, int b)
{
/* TCC should generate csel or equivalent */
return a > b ? a : b;
}
static void test_cond_select(void)
{
printf("csel:\n");
printf("%d\n", cond_select(5, 10));
printf("%d\n", cond_select(10, 5));
printf("%d\n", cond_select(0, 0));
printf("%d\n", cond_select(-1, 1));
}
/* ---- MRS/MSR system registers (FPCR/FPSR) ---- */
static void test_sysregs(void)
{
unsigned int fpcr, fpsr;
printf("sysregs:\n");
/* Read FPCR */
__asm__ volatile ("mrs %0, fpcr" : "=r"(fpcr));
printf("%u\n", fpcr & 0x0F);
/* Read FPSR */
__asm__ volatile ("mrs %0, fpsr" : "=r"(fpsr));
printf("%u\n", fpsr);
/* Write/restore FPCR (should be same value) */
__asm__ volatile ("msr fpcr, %0" : : "r"(fpcr));
/* Read back and verify */
{
unsigned int check;
__asm__ volatile ("mrs %0, fpcr" : "=r"(check));
printf("%s\n", check == fpcr ? "ok" : "fail");
}
}
/* ---- NOP encoding (should not crash) ---- */
static void test_nop(void)
{
printf("nop:\n");
__asm__ volatile ("nop");
__asm__ volatile ("nop");
__asm__ volatile ("nop");
printf("ok\n");
}
/* ---- barrier instructions ---- */
static void test_barriers(void)
{
printf("barriers:\n");
__asm__ volatile ("dmb sy");
__asm__ volatile ("dsb sy");
__asm__ volatile ("isb");
printf("ok\n");
}
/* ---- MOV (register) patterns ---- */
static int64_t mov_x0_x1(int64_t x)
{
register int64_t r __asm__("x0") = x;
__asm__ volatile ("" : "=r"(r) : "0"(r));
return r;
}
static void test_mov_reg(void)
{
printf("mov-reg:\n");
printf("%lld\n", (long long)mov_x0_x1(42));
printf("%lld\n", (long long)mov_x0_x1(-1));
}
/* ---- large struct passing (reference semantics) ---- */
struct large { int64_t a, b, c, d; };
static int64_t sum_large(struct large s)
{
return s.a + s.b + s.c + s.d;
}
static struct large make_large(int64_t a, int64_t b, int64_t c, int64_t d)
{
struct large s = { a, b, c, d };
return s;
}
static void test_large_structs(void)
{
struct large s = { 1, 2, 3, 4 };
struct large t;
printf("large-struct:\n");
printf("%lld\n", (long long)sum_large(s));
t = make_large(10, 20, 30, 40);
printf("%lld %lld %lld %lld\n",
(long long)t.a, (long long)t.b,
(long long)t.c, (long long)t.d);
}
/* ---- boundary-sized structs ---- */
struct s18 { char x[18]; };
struct s24 { char x[24]; };
struct s32 { char x[32]; };
static void print_s18(struct s18 s) { printf("%.18s\n", s.x); }
static void print_s24(struct s24 s) { printf("%.24s\n", s.x); }
static void print_s32(struct s32 s) { printf("%.32s\n", s.x); }
static struct s18 ret_s18(void)
{
struct s18 s = { "123456789012345678" };
return s;
}
static struct s24 ret_s24(void)
{
struct s24 s = { "123456789012345678901234" };
return s;
}
static struct s32 ret_s32(void)
{
struct s32 s = { "12345678901234567890123456789012" };
return s;
}
static void test_boundary_structs(void)
{
struct s18 a;
struct s24 b;
struct s32 c;
printf("boundary-structs:\n");
a = ret_s18();
printf("%.18s\n", a.x);
b = ret_s24();
printf("%.24s\n", b.x);
c = ret_s32();
printf("%.32s\n", c.x);
}
int main(void)
{
test_shifts();
test_ldr_str();
test_ldp_stp();
test_cond_branches();
test_cond_select();
test_sysregs();
test_nop();
test_barriers();
test_mov_reg();
test_large_structs();
test_boundary_structs();
return 0;
}

View File

@ -0,0 +1,50 @@
shift-imm:
1
8000
80000000
1
8000
ffffffff
fffffff0
1
100000000
8000000000000000
1
ffffffffffffffff
fffffffffffffff0
ldr-str:
1122334455667788
99aabbccddeeff00
55667788
f1e2d3c4b5a6978
1122334455667788 99aabbccddeeff00
ldp-stp:
aaaabbbbccccdddd 1111222233334444
cbz-cbnz:
zero
nonzero
zero
nonzero
csel:
10
10
0
1
sysregs:
0
0
ok
nop:
ok
barriers:
ok
mov-reg:
42
-1
large-struct:
10
10 20 30 40
boundary-structs:
123456789012345678
123456789012345678901234
12345678901234567890123456789012

View File

@ -0,0 +1,91 @@
/* ARM64 inline assembly error tests.
Verify that invalid assembly produces proper error messages.
Run with -dt; skipped on non-arm64 architectures. */
#include <stdio.h>
#if defined test_unknown_instruction
int main(void)
{
__asm__("fubar x0, x1, x2");
return 0;
}
#elif defined test_shift_imm_range_32
int main(void)
{
/* LSL by 32 is out of range for 32-bit operand */
__asm__("lsl w0, w1, #32");
return 0;
}
#elif defined test_shift_imm_range_64
int main(void)
{
/* LSL by 64 is out of range for 64-bit operand */
__asm__("lsl x0, x1, #64");
return 0;
}
#elif defined test_invalid_sysreg
int main(void)
{
/* Bogus system register name */
__asm__("mrs x0, bogusreg");
return 0;
}
#elif defined test_invalid_barrier_option
int main(void)
{
/* Invalid barrier scope name */
__asm__("dmb xyz");
return 0;
}
#elif defined test_missing_third_operand
int main(void)
{
__asm__("add x0, x1");
return 0;
}
#elif defined test_movz_imm_range
int main(void)
{
__asm__("movz x0, #0x10000");
return 0;
}
#elif defined test_movz_shift_range
int main(void)
{
__asm__("movz x0, #1, lsl #8");
return 0;
}
#elif defined test_invalid_muls
int main(void)
{
__asm__("muls x0, x1, x2");
return 0;
}
#elif defined test_extended_inline_asm
int main(void)
{
int x = 1;
/* Invalid operand reference in extended inline asm */
__asm__("add %0, %1, #1" : "=r"(x) : "2"(x));
return 0;
}
#elif defined test_extended_inline_clobber
int main(void)
{
/* Invalid clobber register name */
__asm__ volatile ("nop" : : : "bogus");
return 0;
}
#endif

View File

@ -0,0 +1,32 @@
[test_unknown_instruction]
139_arm64_errors.c:10: error: ARM64 instruction 'fubar' not implemented
[test_shift_imm_range_32]
139_arm64_errors.c:17: error: shift immediate out of range
[test_shift_imm_range_64]
139_arm64_errors.c:25: error: shift immediate out of range
[test_invalid_sysreg]
139_arm64_errors.c:34: error: unsupported system register
[test_invalid_barrier_option]
139_arm64_errors.c:42: error: invalid operand 'xyz'
[test_missing_third_operand]
139_arm64_errors.c:48: error: missing third operand
[test_movz_imm_range]
139_arm64_errors.c:55: error: move wide immediate out of range
[test_movz_shift_range]
139_arm64_errors.c:62: error: move wide shift out of range
[test_invalid_muls]
139_arm64_errors.c:70: error: ARM64 instruction 'muls' not implemented
[test_extended_inline_asm]
139_arm64_errors.c:79: error: invalid reference in constraint 1 ('2')
[test_extended_inline_clobber]
139_arm64_errors.c:87: error: invalid clobber register 'bogus'

View File

@ -0,0 +1,451 @@
/*
* ARM64 Extended Inline Assembly Tests
* Tests for GCC-style extended inline assembly with operands, constraints, and clobbers
*/
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
struct pair64 {
uint64_t a;
uint64_t b;
};
static int arm64_symbol_target(void)
{
return 7;
}
static void test_symbolic_address_constraint_compile_only(void)
{
asm volatile("" : : "S"(arm64_symbol_target));
}
/* Test 1: Basic output operand */
void test_basic_output(void)
{
int x;
asm("mov %0, #42" : "=r"(x));
assert(x == 42);
printf("Test 1 (basic output): PASSED\n");
}
/* Test 2: Input operand */
void test_input_operand(void)
{
int x = 10;
int y;
asm("add %0, %1, #5" : "=r"(y) : "r"(x));
assert(y == 15);
printf("Test 2 (input operand): PASSED\n");
}
/* Test 3: Read-write operand */
void test_read_write_operand(void)
{
int x = 10;
asm("add %0, %0, #1" : "+r"(x));
assert(x == 11);
printf("Test 3 (read-write operand): PASSED\n");
}
/* Test 4: Memory operand - load */
void test_memory_load(void)
{
int x = 42;
int y;
asm("ldr %w0, [%1]" : "=r"(y) : "r"(&x));
assert(y == 42);
printf("Test 4 (memory load): PASSED\n");
}
/* Test 5: Memory operand - store */
void test_memory_store(void)
{
int x;
int val = 123;
asm("str %w1, [%0]" : : "r"(&x), "r"(val));
assert(x == 123);
printf("Test 5 (memory store): PASSED\n");
}
/* Test 5a: Stack memory operand with frame-relative offset */
void test_stack_memory_operand(void)
{
long x = 0;
long val = 321;
asm volatile("str %0, %1" : : "r"(val), "m"(x));
assert(x == 321);
printf("Test 5a (stack memory operand): PASSED\n");
}
/* Test 5b: Symbol memory operand */
static long arm64_symbol_mem;
void test_symbol_memory_operand(void)
{
long val = 654;
arm64_symbol_mem = 0;
asm volatile("str %0, %1" : : "r"(val), "m"(arm64_symbol_mem));
assert(arm64_symbol_mem == 654);
printf("Test 5b (symbol memory operand): PASSED\n");
}
/* Test 6: Clobber list */
void test_clobber_list(void)
{
int x = 10;
int y = 20;
int result;
asm("add %0, %1, %2"
: "=r"(result)
: "r"(x), "r"(y)
: "cc");
assert(result == 30);
printf("Test 6 (clobber list): PASSED\n");
}
/* Test 7: Multiple outputs */
void test_multiple_outputs(void)
{
int a, b;
asm("mov %0, #1; mov %1, #2"
: "=r"(a), "=r"(b));
assert(a == 1 && b == 2);
printf("Test 7 (multiple outputs): PASSED\n");
}
/* Test 8: Constraint reference */
void test_constraint_reference(void)
{
int x = 10;
int y;
asm("add %0, %1, #5" : "=r"(y) : "0"(x));
assert(y == 15);
printf("Test 8 (constraint reference): PASSED\n");
}
/* Test 9: Early clobber */
void test_early_clobber(void)
{
int x = 10;
int y;
asm("mov %0, #42" : "=&r"(y) : "r"(x));
assert(y == 42);
printf("Test 9 (early clobber): PASSED\n");
}
/* Test 10: 32-bit register modifier */
void test_w_register(void)
{
uint32_t x = 100;
uint32_t y;
asm("add %w0, %w1, #50" : "=r"(y) : "r"(x));
assert(y == 150);
printf("Test 10 (w register modifier): PASSED\n");
}
/* Test 11: Immediate constraint 'I' (12-bit immediate) */
void test_immediate_i_constraint(void)
{
int x = 100;
int y;
asm("add %0, %1, #200" : "=r"(y) : "r"(x), "I"(200));
assert(y == 300);
printf("Test 11 (immediate I constraint): PASSED\n");
}
/* Test 12: Register constraint */
void test_general_operand_constraint(void)
{
int x = 50;
int y;
asm("add %0, %1, #10" : "=r"(y) : "r"(x));
assert(y == 60);
printf("Test 12 (general operand constraint): PASSED\n");
}
/* Test 13: Multiple inputs and outputs */
void test_multiple_io(void)
{
int a = 10, b = 20;
int sum, diff;
asm("add %0, %1, %2" : "=r"(sum) : "r"(a), "r"(b));
asm("sub %0, %1, %2" : "=r"(diff) : "r"(a), "r"(b));
assert(sum == 30 && diff == -10);
printf("Test 13 (multiple IO): PASSED\n");
}
/* Test 14: Register variable preservation */
void test_regvar_preservation(void)
{
register uint64_t keep asm("x19") = 0x123456789abcdef0ULL;
uint64_t out;
asm volatile("mov x19, #7; add %0, x19, #1"
: "=r"(out)
:
: "x19");
assert(keep == 0x123456789abcdef0ULL);
assert(out == 8);
printf("Test 14 (regvar preservation): PASSED\n");
}
/* Test 15: Complex arithmetic */
void test_complex_arithmetic(void)
{
int a = 100, b = 50, c = 25;
int result;
asm("add %0, %1, %2; sub %0, %0, %3"
: "=&r"(result)
: "r"(a), "r"(b), "r"(c));
assert(result == 125);
printf("Test 15 (complex arithmetic): PASSED\n");
}
/* Test 16: Named operand (GCC extension) */
void test_named_operand(void)
{
int input = 10;
int output;
asm("add %[out], %[in], #5"
: [out] "=r"(output)
: [in] "r"(input));
assert(output == 15);
printf("Test 16 (named operand): PASSED\n");
}
/* Test 17: Memory clobber */
void test_memory_clobber(void)
{
int x = 10;
asm volatile("" : : : "memory");
assert(x == 10);
printf("Test 17 (memory clobber): PASSED\n");
}
/* Test 18: Condition flags clobber */
void test_cc_clobber(void)
{
int x = 100;
int y;
asm("adds %0, %1, #0" : "=r"(y) : "r"(x) : "cc");
assert(y == 100);
printf("Test 18 (cc clobber): PASSED\n");
}
/* Test 19: Large immediate with movz/movk */
void test_large_immediate(void)
{
uint64_t val;
asm("movz %0, #0x1234, lsl #16; movk %0, #0x5678" : "=r"(val));
assert(val == 0x12345678ULL);
printf("Test 19 (large immediate): PASSED\n");
}
/* Test 20: Bitwise operations */
void test_bitwise_ops(void)
{
uint64_t a = 0xf0f0f0f00f0f0f0fULL;
uint64_t b = 0x3333ffff0000ccccULL;
uint64_t andv;
uint64_t orv;
uint64_t xorv;
uint64_t imm_and;
asm("and %0, %1, %2" : "=r"(andv) : "r"(a), "r"(b));
asm("orr %0, %1, %2" : "=r"(orv) : "r"(a), "r"(b));
asm("eor %0, %1, %2" : "=r"(xorv) : "r"(a), "r"(b));
asm("and %0, %1, %2" : "=r"(imm_and)
: "r"(~0ULL), "L"(0xff00ff00ff00ff00ULL));
assert(andv == (a & b));
assert(orv == (a | b));
assert(xorv == (a ^ b));
assert(imm_and == 0xff00ff00ff00ff00ULL);
printf("Test 20 (bitwise ops): PASSED\n");
}
/* Test 21: Register shift operands */
void test_register_shift_operands(void)
{
uint64_t val = 3;
uint64_t amount = 4;
uint64_t shifted;
uint64_t rotated;
asm("lsl %0, %1, %2" : "=r"(shifted) : "r"(val), "r"(amount));
asm("ror %0, %1, %2" : "=r"(rotated)
: "r"(0x0123456789abcdefULL), "r"(8ULL));
assert(shifted == 48);
assert(rotated == 0xef0123456789abcdULL);
printf("Test 21 (register shifts): PASSED\n");
}
/* Test 22: ROR immediate alias of EXTR */
void test_ror_immediate(void)
{
uint64_t rotated;
asm("ror %0, %1, #8" : "=r"(rotated) : "r"(0x0123456789abcdefULL));
assert(rotated == 0xef0123456789abcdULL);
printf("Test 22 (ror immediate): PASSED\n");
}
/* Test 23: FP/SIMD register constraint and modifier */
void test_fp_register_operand(void)
{
double x = 3.5;
double y;
asm("ldr %d0, [%1]" : "=w"(y) : "r"(&x));
assert(y == x);
printf("Test 23 (fp register operand): PASSED\n");
}
/* Test 24: Zero constraint */
void test_zero_constraint(void)
{
uint64_t x = 41;
uint64_t y;
asm("add %0, %1, %x2" : "=r"(y) : "r"(x), "Z"(0));
assert(y == x);
printf("Test 24 (Z constraint): PASSED\n");
}
/* Test 25: 32-bit logical immediate constraint */
void test_logical_imm32_constraint(void)
{
uint32_t y;
asm("orr %w0, wzr, %1" : "=r"(y) : "K"(0xff));
assert(y == 0xff);
printf("Test 25 (K constraint): PASSED\n");
}
/* Test 26: 64-bit logical immediate constraint */
void test_logical_imm64_constraint(void)
{
uint64_t y;
asm("orr %0, xzr, %1" : "=r"(y) : "L"(0xff00ff00ff00ff00ULL));
assert(y == 0xff00ff00ff00ff00ULL);
printf("Test 26 (L constraint): PASSED\n");
}
/* Test 27: 32-bit MOV pseudo immediate constraint */
void test_mov_imm32_constraint(void)
{
uint32_t y;
asm("mov %w0, %1" : "=r"(y) : "M"(0x1234));
assert(y == 0x1234);
printf("Test 27 (M constraint): PASSED\n");
}
/* Test 28: 64-bit MOV pseudo immediate constraint */
void test_mov_imm64_constraint(void)
{
uint64_t y;
asm("mov %0, %1" : "=r"(y) : "N"(0x12340000ULL));
assert(y == 0x12340000ULL);
printf("Test 28 (N constraint): PASSED\n");
}
/* Test 29: x FP/SIMD register constraint */
void test_x_constraint_fp(void)
{
double x = 6.25;
double y;
asm("ldr %d0, [%1]" : "=x"(y) : "r"(&x));
assert(y == x);
printf("Test 29 (x constraint): PASSED\n");
}
/* Test 30: y FP/SIMD register constraint */
void test_y_constraint_fp(void)
{
double x = 7.25;
double y;
asm("ldr %d0, [%1]" : "=y"(y) : "r"(&x));
assert(y == x);
printf("Test 30 (y constraint): PASSED\n");
}
/* Test 31: Q memory constraint */
static int arm64_q_load(int *ptr)
{
int y;
asm("ldr %w0, %1" : "=r"(y) : "Q"(*ptr));
return y;
}
void test_q_memory_constraint(void)
{
int x = 91;
assert(arm64_q_load(&x) == 91);
printf("Test 31 (Q constraint): PASSED\n");
}
/* Test 32: Ump pair-memory constraint */
void test_ump_memory_constraint(void)
{
struct pair64 pair = { 0x1122334455667788ULL, 0x99aabbccddeeff00ULL };
uint64_t a;
uint64_t b;
asm("ldp %0, %1, %2" : "=r"(a), "=r"(b) : "Ump"(pair));
assert(a == pair.a);
assert(b == pair.b);
printf("Test 32 (Ump constraint): PASSED\n");
}
int main(void)
{
printf("ARM64 Extended Inline Assembly Tests\n");
test_basic_output();
test_input_operand();
test_read_write_operand();
test_memory_load();
test_memory_store();
test_stack_memory_operand();
test_symbol_memory_operand();
test_clobber_list();
test_multiple_outputs();
test_constraint_reference();
test_early_clobber();
test_w_register();
test_immediate_i_constraint();
test_general_operand_constraint();
test_multiple_io();
test_regvar_preservation();
test_complex_arithmetic();
test_named_operand();
test_memory_clobber();
test_cc_clobber();
test_large_immediate();
test_bitwise_ops();
test_register_shift_operands();
test_ror_immediate();
test_fp_register_operand();
test_zero_constraint();
test_logical_imm32_constraint();
test_logical_imm64_constraint();
test_mov_imm32_constraint();
test_mov_imm64_constraint();
test_x_constraint_fp();
test_y_constraint_fp();
test_q_memory_constraint();
test_ump_memory_constraint();
test_symbolic_address_constraint_compile_only();
printf("ARM64 Extended Inline Assembly Tests PASSED!\n");
return 0;
}

View File

@ -0,0 +1,36 @@
ARM64 Extended Inline Assembly Tests
Test 1 (basic output): PASSED
Test 2 (input operand): PASSED
Test 3 (read-write operand): PASSED
Test 4 (memory load): PASSED
Test 5 (memory store): PASSED
Test 5a (stack memory operand): PASSED
Test 5b (symbol memory operand): PASSED
Test 6 (clobber list): PASSED
Test 7 (multiple outputs): PASSED
Test 8 (constraint reference): PASSED
Test 9 (early clobber): PASSED
Test 10 (w register modifier): PASSED
Test 11 (immediate I constraint): PASSED
Test 12 (general operand constraint): PASSED
Test 13 (multiple IO): PASSED
Test 14 (regvar preservation): PASSED
Test 15 (complex arithmetic): PASSED
Test 16 (named operand): PASSED
Test 17 (memory clobber): PASSED
Test 18 (cc clobber): PASSED
Test 19 (large immediate): PASSED
Test 20 (bitwise ops): PASSED
Test 21 (register shifts): PASSED
Test 22 (ror immediate): PASSED
Test 23 (fp register operand): PASSED
Test 24 (Z constraint): PASSED
Test 25 (K constraint): PASSED
Test 26 (L constraint): PASSED
Test 27 (M constraint): PASSED
Test 28 (N constraint): PASSED
Test 29 (x constraint): PASSED
Test 30 (y constraint): PASSED
Test 31 (Q constraint): PASSED
Test 32 (Ump constraint): PASSED
ARM64 Extended Inline Assembly Tests PASSED!

View File

@ -38,6 +38,11 @@ struct hfa32 { long double a, b; } hfa32 = { 32.1, 32.2 };
struct hfa33 { long double a, b, c; } hfa33 = { 33.1, 33.2, 33.3 };
struct hfa34 { long double a, b, c, d; } hfa34 = { 34.1, 34.2, 34.3, 34.4 };
struct empty { };
/* Keep the top-level offsets at zero without changing the type into a union. */
struct hfae12 { struct empty e; struct hfa12 h; } hfae12 = { { }, { 112.1, 112.2 } };
struct hfae22 { struct empty e; struct hfa22 h; } hfae22 = { { }, { 122.1, 122.2 } };
void fa_s1(struct s1 a) { printf("%.1s\n", a.x); }
void fa_s2(struct s2 a) { printf("%.2s\n", a.x); }
void fa_s3(struct s3 a) { printf("%.3s\n", a.x); }
@ -82,6 +87,10 @@ void fa_hfa33(struct hfa33 a)
{ printf("%.1Lf %.1Lf %.1Lf\n", a.a, a.b, a.c); }
void fa_hfa34(struct hfa34 a)
{ printf("%.1Lf %.1Lf %.1Lf %.1Lf\n", a.a, a.b, a.c, a.d); }
void fa_hfae12(struct hfae12 a)
{ printf("%.1f %.1f\n", a.h.a, a.h.b); }
void fa_hfae22(struct hfae22 a)
{ printf("%.1f %.1f\n", a.h.a, a.h.b); }
void fa1(struct s8 a, struct s9 b, struct s10 c, struct s11 d,
struct s12 e, struct s13 f)
@ -140,6 +149,8 @@ void arg(void)
fa_hfa32(hfa32);
fa_hfa33(hfa33);
fa_hfa34(hfa34);
fa_hfae12(hfae12);
fa_hfae22(hfae22);
fa1(s8, s9, s10, s11, s12, s13);
fa2(s9, s10, s11, s12, s13, s14);
fa3(hfa14, hfa23, hfa32);
@ -178,6 +189,8 @@ struct hfa31 fr_hfa31(void) { return hfa31; }
struct hfa32 fr_hfa32(void) { return hfa32; }
struct hfa33 fr_hfa33(void) { return hfa33; }
struct hfa34 fr_hfa34(void) { return hfa34; }
struct hfae12 fr_hfae12(void) { return hfae12; }
struct hfae22 fr_hfae22(void) { return hfae22; }
void ret(void)
{
@ -228,6 +241,8 @@ void ret(void)
printf("%.1Lf %.1Lf\n", fr_hfa32().a, fr_hfa32().b);
printf("%.1Lf %.1Lf\n", fr_hfa33().a, fr_hfa33().c);
printf("%.1Lf %.1Lf\n", fr_hfa34().a, fr_hfa34().d);
printf("%.1f %.1f\n", fr_hfae12().h.a, fr_hfae12().h.b);
printf("%.1f %.1f\n", fr_hfae22().h.a, fr_hfae22().h.b);
}
void*

View File

@ -28,6 +28,8 @@ cdefghijklmnopqrs
32.1 32.1
33.1 33.2 33.3
34.1 34.2 34.3 34.4
112.1 112.2
122.1 122.2
stu ABC JKL TUV 456 ghi
ABC JKL TUV 456 ghi tuv
14.1 14.4 23.1 23.3 32.1 32.2
@ -62,6 +64,8 @@ cdefghijklmnopqrs
32.1 32.2
33.1 33.3
34.1 34.4
112.1 112.2
122.1 122.2
stdarg:
ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI
lmnopqr ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI