goalc: Implement the bulk of ARM64 instructions from x86 (#4318)

Less than 100 instructions left to implement, with the vast vast
majority being load-and-stores. These will likely be knocked out quickly
but they require a more involved implementation than just simply
translating the instructions (several need multiple instructions, others
may need reserved registers (x16 or x17 are common for this purpose))

This is a good milestone to get something pushed to master.
This commit is contained in:
Tyler Wilding
2026-06-22 22:25:49 -04:00
committed by GitHub
parent f9a7fba6e2
commit 8daf33492e
17 changed files with 5359 additions and 4587 deletions
+28 -32
View File
@@ -150,10 +150,10 @@ TEST(CodeTester, simd_store_128_arm64) {
CodeTester tester(emitter::InstructionSet::ARM64);
tester.init_code_buffer(256);
tester.emit(IGen::store128_gpr64_simd128(tester.generator(), X2, Q3));
tester.emit(IGen::store128_gpr64_simd128(tester.generator(), X14, Q3));
tester.emit(IGen::store128_gpr64_simd128(tester.generator(), X2, Q14));
tester.emit(IGen::store128_gpr64_simd128(tester.generator(), X14, Q13));
tester.emit(IGen::store128_gpr64_simd128(tester.generator(), X2, V3));
tester.emit(IGen::store128_gpr64_simd128(tester.generator(), X14, V3));
tester.emit(IGen::store128_gpr64_simd128(tester.generator(), X2, V14));
tester.emit(IGen::store128_gpr64_simd128(tester.generator(), X14, V13));
EXPECT_EQ(tester.dump_to_hex_string(), "43 00 80 3d c3 01 80 3d 4e 00 80 3d cd 01 80 3d");
}
@@ -197,13 +197,25 @@ TEST(CodeTester, xmm_load_128_arm64) {
CodeTester tester(emitter::InstructionSet::ARM64);
tester.init_code_buffer(256);
tester.emit(IGen::load128_simd128_gpr64(tester.generator(), Q3, X1));
tester.emit(IGen::load128_simd128_gpr64(tester.generator(), Q3, X14));
tester.emit(IGen::load128_simd128_gpr64(tester.generator(), Q14, X1));
tester.emit(IGen::load128_simd128_gpr64(tester.generator(), Q13, X14));
tester.emit(IGen::load128_simd128_gpr64(tester.generator(), V3, X1));
tester.emit(IGen::load128_simd128_gpr64(tester.generator(), V3, X14));
tester.emit(IGen::load128_simd128_gpr64(tester.generator(), V14, X1));
tester.emit(IGen::load128_simd128_gpr64(tester.generator(), V13, X14));
EXPECT_EQ(tester.dump_to_hex_string(), "23 00 c0 3d c3 01 c0 3d 2e 00 c0 3d cd 01 c0 3d");
}
void execute_tester(CodeTester& tester) {
if (tester.generator().instr_set() == InstructionSet::ARM64) {
#ifdef __aarch64__
tester.execute();
#endif
} else if (tester.generator().instr_set() == InstructionSet::X86) {
#ifndef __aarch64__
tester.execute();
#endif
}
}
// These tests actually execute the code, you cannot execute arm64 code on x86 and vise versa
// so these tests have to be conditional based on the platform unfortunately.
TEST(CodeTester, execute_push_pop_simd_x86) {
@@ -225,9 +237,7 @@ TEST(CodeTester, execute_push_pop_simd_x86) {
"0f 6f 0c 24 48 83 c4 10 66 44 0f 6f 14 24 48 83 c4 10 66 44 0f 6f 1c 24 48 83 c4 10 66 44 "
"0f 6f 24 24 48 83 c4 10 66 44 0f 6f 2c 24 48 83 c4 10 66 44 0f 6f 34 24 48 83 c4 10 66 44 "
"0f 6f 3c 24 48 83 c4 10 48 83 c4 08 c3");
#ifndef __aarch64__
tester.execute();
#endif
execute_tester(tester);
}
TEST(CodeTester, execute_push_pop_simd_arm64) {
@@ -247,9 +257,7 @@ TEST(CodeTester, execute_push_pop_simd_arm64) {
"ff 43 00 91 e7 03 c0 3d ff 43 00 91 e8 03 c0 3d ff 43 00 91 e9 03 c0 3d ff 43 00 91 ea 03 "
"c0 3d ff 43 00 91 eb 03 c0 3d ff 43 00 91 ec 03 c0 3d ff 43 00 91 ed 03 c0 3d ff 43 00 91 "
"ee 03 c0 3d ff 43 00 91 ef 03 c0 3d ff 43 00 91 c0 03 5f d6");
#ifdef __aarch64__
tester.execute();
#endif
execute_tester(tester);
}
TEST(CodeTester, execute_push_pop_all_the_things_x86) {
@@ -276,9 +284,7 @@ TEST(CodeTester, execute_push_pop_all_the_things_x86) {
"04 24 48 83 c4 10 66 44 0f 6f 0c 24 48 83 c4 10 66 44 0f 6f 14 24 48 83 c4 10 66 44 "
"0f 6f 1c 24 48 83 c4 10 66 44 0f 6f 24 24 48 83 c4 10 66 44 0f 6f 2c 24 48 83 c4 10 "
"66 44 0f 6f 34 24 48 83 c4 10 66 44 0f 6f 3c 24 48 83 c4 10 48 83 c4 08 c3");
#ifndef __aarch64__
tester.execute();
#endif
execute_tester(tester);
}
TEST(CodeTester, execute_push_pop_all_the_things_arm64) {
@@ -310,9 +316,7 @@ TEST(CodeTester, execute_push_pop_all_the_things_arm64) {
"ff 43 00 91 e6 03 c0 3d ff 43 00 91 e7 03 c0 3d ff 43 00 91 e8 03 c0 3d ff 43 00 91 e9 03 "
"c0 3d ff 43 00 91 ea 03 c0 3d ff 43 00 91 eb 03 c0 3d ff 43 00 91 ec 03 c0 3d ff 43 00 91 "
"ed 03 c0 3d ff 43 00 91 ee 03 c0 3d ff 43 00 91 ef 03 c0 3d ff 43 00 91 c0 03 5f d6");
#ifdef __aarch64__
tester.execute();
#endif
execute_tester(tester);
}
TEST(CodeTester, execute_return_x86) {
@@ -322,9 +326,7 @@ TEST(CodeTester, execute_return_x86) {
tester.emit_return();
EXPECT_EQ(tester.dump_to_hex_string(), "c3");
// and execute it!
#ifndef __aarch64__
tester.execute();
#endif
execute_tester(tester);
}
TEST(CodeTester, execute_return_arm64) {
@@ -335,9 +337,7 @@ TEST(CodeTester, execute_return_arm64) {
tester.emit(IGen::ret(tester.generator()));
EXPECT_EQ(tester.dump_to_hex_string(), "00 04 00 91 c0 03 5f d6");
// and execute it!
#ifdef __aarch64__
tester.execute();
#endif
execute_tester(tester);
}
TEST(CodeTester, execute_push_pop_gprs_x86) {
@@ -350,9 +350,7 @@ TEST(CodeTester, execute_push_pop_gprs_x86) {
EXPECT_EQ(tester.dump_to_hex_string(),
"50 51 52 53 54 55 56 57 41 50 41 51 41 52 41 53 41 54 41 55 41 56 41 57 41 5f 41 5e "
"41 5d 41 5c 41 5b 41 5a 41 59 41 58 5f 5e 5d 5c 5b 5a 59 58 c3");
#ifndef __aarch64__
tester.execute();
#endif
execute_tester(tester);
}
TEST(CodeTester, execute_push_pop_gprs_arm64) {
@@ -372,7 +370,5 @@ TEST(CodeTester, execute_push_pop_gprs_arm64) {
"f3 07 41 f8 f2 07 41 f8 f1 07 41 f8 f0 07 41 f8 ef 07 41 f8 ee 07 41 f8 ed 07 41 f8 "
"ec 07 41 f8 eb 07 41 f8 ea 07 41 f8 e9 07 41 f8 e8 07 41 f8 e7 07 41 f8 e6 07 41 f8 "
"e5 07 41 f8 e4 07 41 f8 e3 07 41 f8 e2 07 41 f8 e1 07 41 f8 e0 07 41 f8 c0 03 5f d6");
#ifdef __aarch64__
tester.execute();
#endif
execute_tester(tester);
}