diff --git a/generator/arm64/assembler_arm64.cpp b/generator/arm64/assembler_arm64.cpp index 18575f0..c57f5f0 100644 --- a/generator/arm64/assembler_arm64.cpp +++ b/generator/arm64/assembler_arm64.cpp @@ -1063,26 +1063,14 @@ void generateData(MirData *mirData) { //todo } -void initProgramStart() { - emitLabel("_start"); - binaryOp2(INST_MOV, 1, X29, 0, true); - binaryOp2(INST_MOV, 1, X30, 0, true); - binaryOpBranch(INST_BL, UNUSED, "main"); - //keep the "main" ret value in X0 - binaryOp2(INST_MOV, 1, X8, SYS_EXIT, true); - binaryOpSvc(INST_SVC, 0); -} - int generateArm64Target(Mir *mir) { logd(ARM64_TAG, "arm64 target generation..."); - initProgramStart(); //.text MirMethod *mirMethod = mir->mirMethod; while (mirMethod != nullptr) { generateText(mirMethod); mirMethod = mirMethod->next; } - //.data if (mir->mirData != nullptr) { generateSection(SECTION_DATA); diff --git a/generator/arm64/binary_arm64.cpp b/generator/arm64/binary_arm64.cpp index b25c549..9ac030e 100644 --- a/generator/arm64/binary_arm64.cpp +++ b/generator/arm64/binary_arm64.cpp @@ -420,7 +420,7 @@ void binaryOpStoreLoad(Arm64Inst inst, uint32_t is64Bit, Operand reg1, Operand r } -void movInteger(Operand reg, uint64_t imm) { +void movInteger(Operand reg, int64_t imm) { uint64_t mark = 0xffff;//use for check imm size int e; if (!(imm & ~mark)) { @@ -432,6 +432,11 @@ void movInteger(Operand reg, uint64_t imm) { emitInst(0x52a00000 | reg | imm >> 11); // movz w(reg),#(imm >> 16),lsl #16 return; } + if (imm == -1) { + emitInst(0x92800000);// movn x0 (~#0); ~#0 == 0xFFFF... = #-1 + //fixme: this is a special case. + return; + } loge(BIN_TAG, "big imm (>16bit) need .data impl"); } @@ -644,7 +649,7 @@ void binaryOpNop(Arm64Inst inst) { /** * * @param inst - * @param sysCallImm always "0" on linux aarch64 + * @param sysCallImm ignore on linux, must be set on windows! */ void binaryOpSvc(Arm64Inst inst, uint32_t sysCallImm) { if (inst != INST_SVC) { diff --git a/generator/arm64/binary_arm64.h b/generator/arm64/binary_arm64.h index 64fa3c4..31cc0b3 100644 --- a/generator/arm64/binary_arm64.h +++ b/generator/arm64/binary_arm64.h @@ -7,7 +7,7 @@ #include -typedef uint32_t Operand; +typedef int64_t Operand; typedef uint32_t Inst; diff --git a/generator/arm64/linux_syscall.cpp b/generator/arm64/linux_syscall.cpp new file mode 100644 index 0000000..40dbeef --- /dev/null +++ b/generator/arm64/linux_syscall.cpp @@ -0,0 +1,14 @@ +// +// Created by Park Yu on 2024/11/21. +// +#include "linux_syscall.h" + +void initLinuxArm64ProgramStart() { + emitLabel("_start"); + binaryOp2(INST_MOV, 1, X29, 0, true); + binaryOp2(INST_MOV, 1, X30, 0, true); + binaryOpBranch(INST_BL, UNUSED, "main"); + //keep the "main" ret value in X0 + binaryOp2(INST_MOV, 1, X8, SYS_EXIT, true); + binaryOpSvc(INST_SVC, 0); +} \ No newline at end of file diff --git a/generator/arm64/linux_syscall.h b/generator/arm64/linux_syscall.h index 9ea4253..ec8b6d1 100644 --- a/generator/arm64/linux_syscall.h +++ b/generator/arm64/linux_syscall.h @@ -5,7 +5,10 @@ #ifndef PCC_LINUX_SYSCALL_H #define PCC_LINUX_SYSCALL_H -enum SysCallNumber{ +#include "binary_arm64.h" +#include "register_arm64.h" + +enum LinuxArm64SysCallNumber{ SYS_READ = 63, SYS_WRITE = 64, SYS_OPEN = 56, @@ -37,5 +40,6 @@ enum SysCallNumber{ // 根据需要添加其他系统调用 }; +void initLinuxArm64ProgramStart(); #endif //PCC_LINUX_SYSCALL_H diff --git a/generator/arm64/windows_syscall.cpp b/generator/arm64/windows_syscall.cpp new file mode 100644 index 0000000..7ba5c0b --- /dev/null +++ b/generator/arm64/windows_syscall.cpp @@ -0,0 +1,15 @@ +// +// Created by Park Yu on 2024/11/21. +// +#include "windows_syscall.h" + +void initWindowsArm64ProgramStart() { + emitLabel("_start"); + binaryOp2(INST_MOV, 1, X29, 0, true); + binaryOp2(INST_MOV, 1, X30, 0, true); + binaryOpBranch(INST_BL, UNUSED, "main"); + //keep the "main" ret value in X0 + binaryOp2(INST_MOV, 1, X1, X0, false); + binaryOp2(INST_MOV, 1, X0, INVALID_HANDLE_VALUE, true); + binaryOpSvc(INST_SVC, NtTerminateProcess); +} \ No newline at end of file diff --git a/generator/arm64/windows_syscall.h b/generator/arm64/windows_syscall.h new file mode 100644 index 0000000..004d653 --- /dev/null +++ b/generator/arm64/windows_syscall.h @@ -0,0 +1,24 @@ +// +// Created by Park Yu on 2024/10/17. +// + +#ifndef PCC_LINUX_WINDOWS_SYSCALL_H +#define PCC_LINUX_WINDOWS_SYSCALL_H + +#include "binary_arm64.h" +#include "register_arm64.h" + +enum WindowsArm64SysCallNumber { + NtWriteFile = 8, + NtTerminateProcess = 44, + NtTerminateThread = 83, + // 根据需要添加其他系统调用 +}; + +//00 00 80 92 + +#define INVALID_HANDLE_VALUE -1 + +void initWindowsArm64ProgramStart(); + +#endif //PCC_LINUX_WINDOWS_SYSCALL_H diff --git a/generator/assembler.cpp b/generator/assembler.cpp index 2703d41..b6968d3 100644 --- a/generator/assembler.cpp +++ b/generator/assembler.cpp @@ -5,6 +5,8 @@ #include "logger.h" #include "arm64/assembler_arm64.h" #include "arm64/binary_arm64.h" +#include "arm64/linux_syscall.h" +#include "arm64/windows_syscall.h" #include "elf.h" #include "file.h" #include "pe.h" @@ -22,7 +24,7 @@ void generateElfArm64(Mir *mir, int currentOffset = 0; int programHeaderCount = 0; int sectionHeaderCount = 1;//shstrtab - + initLinuxArm64ProgramStart(); int sectionCount = generateArm64Target(mir); currentOffset += sizeof(Elf64_Ehdr); programHeaderCount += sectionCount; @@ -107,6 +109,7 @@ void generatePeArm64(Mir *mir, int currentOffset = 0; // 1. 生成指令缓冲区 + initWindowsArm64ProgramStart(); int sectionCount = generateArm64Target(mir); // 根据 mir 生成指令 relocateBinary(0); InstBuffer *instBuffer = getEmittedInstBuffer(); // 获取生成的指令缓冲区