Add files to repository
This commit is contained in:
parent
9f200c9084
commit
23d704d496
542 changed files with 75775 additions and 0 deletions
51
System/FFI/Base.HC
Normal file
51
System/FFI/Base.HC
Normal file
|
@ -0,0 +1,51 @@
|
|||
#define PUSH_SYSV_REGS \
|
||||
asm {PUSH RCX PUSH RDX PUSH RBX PUSH RBP PUSH RSI PUSH RDI PUSH R8 PUSH R9 PUSH \
|
||||
R10 PUSH R11 PUSH R12 PUSH R13 PUSH R14 PUSH R15}
|
||||
#define POP_SYSV_REGS \
|
||||
p0 = p0; \
|
||||
p1 = p1; \
|
||||
p2 = p2; \
|
||||
p3 = p3; \
|
||||
p4 = p4; \
|
||||
p5 = p5; \
|
||||
asm {POP R15 POP R14 POP R13 POP R12 POP R11 POP R10 POP R9 POP R8 POP RDI POP \
|
||||
RSI POP RBP POP RBX POP RDX POP RCX}
|
||||
#define GET_SYSV_ARGS \
|
||||
asm {PUSH R9 PUSH R8 PUSH RCX PUSH RDX PUSH RSI PUSH RDI} \
|
||||
I64 reg RDI p0; \
|
||||
I64 reg RSI p1; \
|
||||
I64 reg RDX p2; \
|
||||
I64 reg RCX p3; \
|
||||
I64 reg R8 p4; \
|
||||
I64 reg R9 p5; \
|
||||
asm {POP RDI POP RSI POP RDX POP RCX POP R8 POP R9}
|
||||
|
||||
#define MOV_ANS_RAX asm { MOV[&ans], RAX }
|
||||
#define MOV_PARAM0_RDI asm {MOV [¶m0], RDI}
|
||||
|
||||
I64 param0;
|
||||
I64 elf_argc;
|
||||
U8** elf_argv;
|
||||
|
||||
asm {
|
||||
_ELF_CALL::
|
||||
PUSH RBP
|
||||
MOV RBP,RSP
|
||||
MOV RAX,U64 SF_ARG1[RBP]
|
||||
MOV RDI,U64 SF_ARG2[RBP]
|
||||
MOV RSI,U64 SF_ARG3[RBP]
|
||||
TEST RAX,RAX
|
||||
JZ @@05
|
||||
CALL RAX
|
||||
@@05: POP RBP
|
||||
RET1 8
|
||||
}
|
||||
|
||||
U0 _main()
|
||||
{
|
||||
MOV_PARAM0_RDI
|
||||
CallInd(_ELF_CALL, param0, elf_argc, elf_argv);
|
||||
UserTaskCont;
|
||||
}
|
||||
|
||||
//U0 _exit() { UserTaskCont; }
|
300
System/FFI/ELF64.HC
Normal file
300
System/FFI/ELF64.HC
Normal file
|
@ -0,0 +1,300 @@
|
|||
#define EI_NIDENT 16
|
||||
#define EM_X86_64 0x3E
|
||||
#define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
|
||||
U0 @elf64_debug_print(U8 fmt, ...)
|
||||
{
|
||||
// FIXME: Remove unnecessary debug_print statements and PrintErr for errors.
|
||||
no_warn fmt, argc, argv;
|
||||
}
|
||||
|
||||
class Elf64_Ehdr {
|
||||
U8 e_ident[EI_NIDENT]; /* Magic number and other info */
|
||||
U16 e_type; /* Object file type */
|
||||
U16 e_machine; /* Architecture */
|
||||
U32 e_version; /* Object file version */
|
||||
U64 e_entry; /* Entry point virtual address */
|
||||
U64 e_phoff; /* Program header table file offset */
|
||||
U64 e_shoff; /* Section header table file offset */
|
||||
U32 e_flags; /* Processor-specific flags */
|
||||
U16 e_ehsize; /* ELF header size in bytes */
|
||||
U16 e_phentsize; /* Program header table entry size */
|
||||
U16 e_phnum; /* Program header table entry count */
|
||||
U16 e_shentsize; /* Section header table entry size */
|
||||
U16 e_shnum; /* Section header table entry count */
|
||||
U16 e_shstrndx; /* Section header string table index */
|
||||
};
|
||||
|
||||
class Elf64_Shdr {
|
||||
U32 sh_name; /* Section name (string tbl index) */
|
||||
U32 sh_type; /* Section type */
|
||||
U64 sh_flags; /* Section flags */
|
||||
U64 sh_addr; /* Section virtual addr at execution */
|
||||
U64 sh_offset; /* Section file offset */
|
||||
U64 sh_size; /* Section size in bytes */
|
||||
U32 sh_link; /* Link to another section */
|
||||
U32 sh_info; /* Additional section information */
|
||||
U64 sh_addralign; /* Section alignment */
|
||||
U64 sh_entsize; /* Entry size if section holds table */
|
||||
};
|
||||
|
||||
class Elf64_Sym {
|
||||
U32 st_name; /* Symbol name (string tbl index) */
|
||||
U8 st_info; /* Symbol type and binding */
|
||||
U8 st_other; /* Symbol visibility */
|
||||
U16 st_shndx; /* Section index */
|
||||
U64 st_value; /* Symbol value */
|
||||
U64 st_size; /* Symbol size */
|
||||
};
|
||||
|
||||
class PLT_entry {
|
||||
U8 pad[0x10];
|
||||
};
|
||||
|
||||
class RELA_entry {
|
||||
U64 r_offset;
|
||||
U64 r_info;
|
||||
I64 r_addend;
|
||||
};
|
||||
|
||||
class Elf {
|
||||
union {
|
||||
U8* u8;
|
||||
Elf64_Ehdr* ehdr;
|
||||
} I64 size;
|
||||
U8* dynstr;
|
||||
Elf64_Sym* dynsym;
|
||||
PLT_entry* plt;
|
||||
RELA_entry* rela_dyn;
|
||||
RELA_entry* rela_plt;
|
||||
Elf64_Sym* strtab;
|
||||
Elf64_Sym* symtab;
|
||||
I64 rela_dyn_size;
|
||||
I64 rela_plt_size;
|
||||
I64 strtab_size;
|
||||
I64 symtab_size;
|
||||
};
|
||||
|
||||
U0 (*_start)();
|
||||
|
||||
U0 unimplemented_symbol()
|
||||
{
|
||||
I32 s = 0xDEADF00D;
|
||||
PrintWarn("Unimplemented symbol: %s\n", s);
|
||||
Dbg;
|
||||
while (1)
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
Bool is_valid_elf(Elf* elf)
|
||||
{
|
||||
Bool res = TRUE;
|
||||
if (MemCmp(elf->u8 + 1, "ELF", 3)) {
|
||||
@elf64_debug_print("Invalid signature (not ELF).\n");
|
||||
res = FALSE;
|
||||
}
|
||||
if (elf->ehdr->e_type != ET_EXEC && elf->ehdr->e_type != ET_DYN) {
|
||||
@elf64_debug_print("Invalid object file type.\n");
|
||||
res = FALSE;
|
||||
}
|
||||
if (elf->ehdr->e_machine != EM_X86_64) {
|
||||
@elf64_debug_print("Invalid architecture.\n");
|
||||
res = FALSE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
U0 process_elf_section_header_table(Elf* elf)
|
||||
{
|
||||
Elf64_Shdr* shdr = elf->u8 + elf->ehdr->e_shoff;
|
||||
Elf64_Shdr* shdr_shstrtab = shdr + elf->ehdr->e_shstrndx;
|
||||
U8* shstrtab = elf->u8 + shdr_shstrtab->sh_offset;
|
||||
I64 i = 0;
|
||||
while (i < elf->ehdr->e_shnum) {
|
||||
if (!StrCmp(shstrtab + shdr->sh_name, ".symtab")) {
|
||||
@elf64_debug_print("found symtab at 0x%08x, size = %d\n", shdr->sh_offset,
|
||||
shdr->sh_size);
|
||||
elf->symtab = elf->u8 + shdr->sh_offset;
|
||||
elf->symtab_size = shdr->sh_size;
|
||||
}
|
||||
if (!StrCmp(shstrtab + shdr->sh_name, ".strtab")) {
|
||||
@elf64_debug_print("found strtab at 0x%08x, size = %d\n", shdr->sh_offset,
|
||||
shdr->sh_size);
|
||||
elf->strtab = elf->u8 + shdr->sh_offset;
|
||||
elf->strtab_size = shdr->sh_size;
|
||||
}
|
||||
if (shdr->sh_addr) {
|
||||
MemCpy(shdr->sh_addr, elf->u8 + shdr->sh_offset, shdr->sh_size);
|
||||
if (!StrCmp(shstrtab + shdr->sh_name, ".dynstr"))
|
||||
elf->dynstr = shdr->sh_addr;
|
||||
if (!StrCmp(shstrtab + shdr->sh_name, ".dynsym"))
|
||||
elf->dynsym = shdr->sh_addr;
|
||||
if (!StrCmp(shstrtab + shdr->sh_name, ".plt"))
|
||||
elf->plt = shdr->sh_addr;
|
||||
if (!StrCmp(shstrtab + shdr->sh_name, ".rela.dyn")) {
|
||||
elf->rela_dyn = shdr->sh_addr;
|
||||
elf->rela_dyn_size = shdr->sh_size / shdr->sh_entsize;
|
||||
}
|
||||
if (!StrCmp(shstrtab + shdr->sh_name, ".rela.plt")) {
|
||||
elf->rela_plt = shdr->sh_addr;
|
||||
elf->rela_plt_size = shdr->sh_size / shdr->sh_entsize;
|
||||
}
|
||||
if (!StrCmp(shstrtab + shdr->sh_name, ".bss") || !StrCmp(shstrtab + shdr->sh_name, ".tbss")) {
|
||||
MemSet(shdr->sh_addr, NULL, shdr->sh_size);
|
||||
@elf64_debug_print(
|
||||
"Zeroed out section '%s' at physical address 0x%06x, size = %d bytes\n",
|
||||
shstrtab + shdr->sh_name, shdr->sh_addr, shdr->sh_size);
|
||||
} else
|
||||
@elf64_debug_print(
|
||||
"MemCpy section '%s' to physical address 0x%06x, size = %d bytes\n",
|
||||
shstrtab + shdr->sh_name, shdr->sh_addr, shdr->sh_size);
|
||||
if (!StrCmp(shstrtab + shdr->sh_name, ".bss")) {
|
||||
MemSet(shdr->sh_addr, NULL, shdr->sh_size);
|
||||
@elf64_debug_print("MemSet section '%s' at physical address 0x%06x to NULL, "
|
||||
"size = %d bytes\n",
|
||||
shstrtab + shdr->sh_name, shdr->sh_addr, shdr->sh_size);
|
||||
}
|
||||
}
|
||||
shdr++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
U0 process_elf_rela_dyn_entries(Elf* elf)
|
||||
{
|
||||
I64 i;
|
||||
U8* entry_name;
|
||||
RELA_entry* rela_dyn = elf->rela_dyn;
|
||||
for (i = 0; i < elf->rela_dyn_size; i++) {
|
||||
entry_name = elf->dynstr + elf->dynsym[(rela_dyn->r_info >> 32)].st_name;
|
||||
@elf64_debug_print("rela_dyn->r_offset = %08x\n", rela_dyn->r_offset);
|
||||
@elf64_debug_print("entry name = '%s'\n", entry_name);
|
||||
if (!StrCmp(entry_name, "__libc_start_main")) {
|
||||
*(rela_dyn->r_offset)(U64*) = &_main;
|
||||
@elf64_debug_print("Set value for .rela.dyn entry '%s' to: &_main\n",
|
||||
entry_name);
|
||||
}
|
||||
if (!StrCmp(entry_name, "stdin")) {
|
||||
*(rela_dyn->r_offset)(U64*) = 0;
|
||||
@elf64_debug_print("Set value for .rela.dyn entry '%s' to: %d\n", entry_name, 0);
|
||||
}
|
||||
if (!StrCmp(entry_name, "stdout")) {
|
||||
*(rela_dyn->r_offset)(U64*) = 1;
|
||||
@elf64_debug_print("Set value for .rela.dyn entry '%s' to: %d\n", entry_name, 1);
|
||||
}
|
||||
if (!StrCmp(entry_name, "stderr")) {
|
||||
*(rela_dyn->r_offset)(U64*) = 2;
|
||||
@elf64_debug_print("Set value for .rela.dyn entry '%s' to: %d\n", entry_name, 2);
|
||||
}
|
||||
rela_dyn++;
|
||||
}
|
||||
}
|
||||
|
||||
CHashClass* get_symbol_hash_entry(U8* entry_name)
|
||||
{
|
||||
I64 i;
|
||||
CHashSrcSym* sym;
|
||||
CHashTable* tbl = Fs->hash_table;
|
||||
while (tbl) {
|
||||
for (i = 0; i < tbl->mask; i++) {
|
||||
sym = tbl->body[i];
|
||||
while (sym) {
|
||||
if (sym->type == HTT_CLASS)
|
||||
if (!StrCmp(sym->str, entry_name))
|
||||
return sym;
|
||||
sym = sym->next;
|
||||
}
|
||||
}
|
||||
tbl = tbl->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
U64 get_symbol_address(U8* entry_name)
|
||||
{
|
||||
CHash* h = HashFind(entry_name, Fs->hash_table, Fs->hash_table->mask);
|
||||
if (!h)
|
||||
return NULL;
|
||||
switch (h->type) {
|
||||
case HTT_GLBL_VAR:
|
||||
return h(CHashGlblVar*)->data_addr;
|
||||
break;
|
||||
case HTT_FUN:
|
||||
return h(CHashFun*)->exe_addr;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
U0 process_elf_rela_plt_entries(Elf* elf)
|
||||
{
|
||||
I64 i;
|
||||
U32 handler;
|
||||
U32* patch;
|
||||
U8* entry_name;
|
||||
Bool symbol_exists;
|
||||
PLT_entry* plt = elf->plt;
|
||||
RELA_entry* rela_plt = elf->rela_plt;
|
||||
plt++;
|
||||
for (i = 0; i < elf->rela_plt_size; i++) {
|
||||
symbol_exists = FALSE;
|
||||
entry_name = elf->dynstr + elf->dynsym[(rela_plt->r_info >> 32)].st_name;
|
||||
handler = MAlloc(sizeof(unimplemented_symbol), adam_task->code_heap);
|
||||
MemCpy(handler, &unimplemented_symbol, sizeof(unimplemented_symbol));
|
||||
patch = handler + 0x0A;
|
||||
*patch = entry_name;
|
||||
@patch_jmp_rel32(plt, handler);
|
||||
@patch_call_rel32(handler + 0x16, &PrintErr);
|
||||
//@patch_call_rel32(handler + 0x21, &_exit);
|
||||
if (!StrCmp(entry_name, "__libc_start_main")) {
|
||||
symbol_exists = TRUE;
|
||||
@patch_jmp_rel32(plt, &_main);
|
||||
@elf64_debug_print("Set value for .rela.plt entry '%s' to &_main\n", entry_name);
|
||||
}
|
||||
if (get_symbol_address(entry_name)) {
|
||||
symbol_exists = TRUE;
|
||||
@patch_jmp_rel32(plt, get_symbol_address(entry_name));
|
||||
@elf64_debug_print("Set value for .rela.plt entry '%s' to &%s\n", entry_name,
|
||||
entry_name);
|
||||
}
|
||||
if (!symbol_exists)
|
||||
@elf64_debug_print(
|
||||
"Set value for .rela.plt entry '%s' to &unimplemented_symbol\n",
|
||||
entry_name);
|
||||
rela_plt++;
|
||||
plt++;
|
||||
}
|
||||
}
|
||||
|
||||
U0 load_elf(...)
|
||||
{
|
||||
if (argc < 1) {
|
||||
PrintErr("Not enough arguments.\n");
|
||||
return;
|
||||
}
|
||||
if (!FileFind(argv[0])) {
|
||||
PrintErr("File not found: %s\n", argv[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
Elf elf;
|
||||
elf.u8 = FileRead(argv[0], &elf.size);
|
||||
@elf64_debug_print("Load file '%s', size = %d bytes\n", argv[0], elf.size);
|
||||
|
||||
if (!is_valid_elf(&elf)) {
|
||||
PrintErr("File is not a valid ELF x86-64 executable.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
process_elf_section_header_table(&elf);
|
||||
process_elf_rela_dyn_entries(&elf);
|
||||
process_elf_rela_plt_entries(&elf);
|
||||
|
||||
_start = elf.ehdr->e_entry;
|
||||
elf_argc = argc;
|
||||
elf_argv = argv;
|
||||
}
|
373
System/FFI/LibC.HC
Normal file
373
System/FFI/LibC.HC
Normal file
|
@ -0,0 +1,373 @@
|
|||
asm {
|
||||
_SETJMP::
|
||||
MOV [RDI], RBX // Store caller saved registers
|
||||
MOV [RDI+8], RBP // ^
|
||||
MOV [RDI+16], R12 // ^
|
||||
MOV [RDI+24], R13 // ^
|
||||
MOV [RDI+32], R14 // ^
|
||||
MOV [RDI+40], R15 // ^
|
||||
LEA RDX, [RSP+8] // go one value up (as if setjmp wasn't called)
|
||||
MOV [RDI+48], RDX // Store the new rsp pointer in env[7]
|
||||
MOV RDX, [RSP] // go one value up (as if setjmp wasn't called)
|
||||
MOV [RDI+56], RDX // Store the address we will resume at in env[8]
|
||||
XOR EAX, EAX // Always return 0
|
||||
RET
|
||||
_LONGJMP::
|
||||
XOR EAX, EAX
|
||||
CMP ESI, 1
|
||||
ADC EAX, ESI
|
||||
MOV RBX, [RDI]
|
||||
MOV RBP, [RDI + 8]
|
||||
MOV R12, [RDI + 16]
|
||||
MOV R13, [RDI + 24]
|
||||
MOV R14, [RDI + 32]
|
||||
MOV R15, [RDI + 40]
|
||||
MOV RSP, [RDI + 48]
|
||||
JMP U64 [RDI + 56]
|
||||
}
|
||||
|
||||
_extern _SETJMP U64 _setjmp(U64 jmp_buf);
|
||||
_extern _LONGJMP U64 longjmp(U64 jmp_buf, U64 ret);
|
||||
|
||||
U0 free()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
Free(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 putchar()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
PutChars(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U64 @localtime(U64 p0)
|
||||
{
|
||||
// FIXME: implement this?
|
||||
no_warn p0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
U0 localtime()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@localtime(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
I64 @strncmp(U8* s1, U8* s2, I32 n)
|
||||
{
|
||||
U64 u1, u2;
|
||||
|
||||
while (n-- > 0) {
|
||||
u1 = *s1++;
|
||||
u2 = *s2++;
|
||||
u1 = u1 & 0xff;
|
||||
u2 = u2 & 0xff;
|
||||
if (u1 != u2)
|
||||
return u1 - u2;
|
||||
if (u1 == '\0')
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
U0 strncmp()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@strncmp(p0, p1, p2);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 strcpy()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
StrCpy(p0, p1);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 fprintf()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
Print(p1, p2, p3, p4, p5);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
|
||||
U0 printf()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
Print(p0, p1, p2, p3, p4, p5);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 puts()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
PutS(p0);
|
||||
"\n";
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 fputs()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
PutS(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 fputc()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
PutChars(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U64 @fwrite(U8* buffer, I64 size, I64 count, U64 stream)
|
||||
{
|
||||
if (!buffer || !size || !count || !stream)
|
||||
return NULL;
|
||||
I64 bytes = size * count;
|
||||
switch (stream) {
|
||||
case 1...2:
|
||||
U8* s = CAlloc(bytes + 1);
|
||||
MemCpy(s, buffer, bytes);
|
||||
"%s", s;
|
||||
Free(s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
U0 fwrite()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@fwrite(p0, p1, p2, p3);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 strerror()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
"strerror: %d\n", p0;
|
||||
PressAKey;
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 strlen()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
StrLen(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U8 *@strchr(U8 *str, I64 chr) {
|
||||
while (*str) {
|
||||
if (*str == chr) {
|
||||
return str;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
U0 strchr()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@strchr(p0, p1);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U8* @strrchr(U8 *str, I64 chr) {
|
||||
U8* str2 = str + (StrLen(str) - 1);
|
||||
while (str2 > str - 1) {
|
||||
if (*str2 == chr) {
|
||||
return str2;
|
||||
}
|
||||
str2--;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
U0 strrchr()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@strrchr(p0, p1);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 strcmp()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
//"strcmp: '%s', '%s'\n", p0, p1;
|
||||
StrCmp(p0, p1);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 memcpy()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
MemCpy(p0, p1, p2);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 memset()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
MemSet(p0, p1, p2);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 malloc()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
MAlloc(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U8* @realloc(U8* ptr, I64 size)
|
||||
{
|
||||
U8* new;
|
||||
if (!ptr) {
|
||||
new = MAlloc(size);
|
||||
} else {
|
||||
new = MAlloc(size);
|
||||
MemCpy(new, ptr, size);
|
||||
Free(ptr);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
U0 realloc()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@realloc(p0, p1);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
#define MY_TIME_OFFSET 9488
|
||||
|
||||
public
|
||||
I64 CDate2Unix(CDate dt)
|
||||
{ // TempleOS datetime to Unix timestamp.
|
||||
return ToI64((dt - Str2Date("1/1/1970")) / CDATE_FREQ) - MY_TIME_OFFSET;
|
||||
}
|
||||
|
||||
I64 @time(I64* ptr)
|
||||
{
|
||||
no_warn ptr;
|
||||
return CDate2Unix(Now);
|
||||
}
|
||||
|
||||
U0 time()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@time(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U64 @gettimeofday(U64* tv)
|
||||
{
|
||||
if (!tv)
|
||||
return 0;
|
||||
U64 seconds = CDate2Unix(Now);
|
||||
tv[0] = seconds;
|
||||
tv[1] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
U0 gettimeofday()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@gettimeofday(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 @fgets(U8* p0, I64 p1)
|
||||
{
|
||||
GetS(p0, p1);
|
||||
while (*p0) {
|
||||
if (*p0 == 0x1f)
|
||||
*p0 = 0x20;
|
||||
++p0;
|
||||
}
|
||||
Print("");
|
||||
}
|
||||
|
||||
U0 fgets()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@fgets(p0, p1);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U64 @ferror()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
U0 ferror()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@ferror;
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U64 @strcat(U8* dst, U8* src)
|
||||
{
|
||||
StrCpy(dst + StrLen(dst), src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
U0 strcat()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@strcat(p0, p1);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 strstr()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
StrFind(p1, p0);
|
||||
POP_SYSV_REGS
|
||||
|
||||
}
|
||||
|
||||
U0 sprintf()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
StrPrint(p0, p1, p2, p3, p4, p5);
|
||||
POP_SYSV_REGS
|
||||
}
|
60
System/LibTemple/OS.HC
Normal file
60
System/LibTemple/OS.HC
Normal file
|
@ -0,0 +1,60 @@
|
|||
U0 os_call_ext_str()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
CallExtStr(p0);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 os_call_ext_str_1()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
CallExtStr(p0, p1);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 os_call_ext_str_2()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
CallExtStr(p0, p1, p2);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 os_call_ext_str_3()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
CallExtStr(p0, p1, p2, p3);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 os_call_ext_str_4()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
CallExtStr(p0, p1, p2, p3, p4);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U0 os_call_ext_str_5()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
CallExtStr(p0, p1, p2, p3, p4, p5);
|
||||
POP_SYSV_REGS
|
||||
}
|
||||
|
||||
U64 @os_jiffies()
|
||||
{
|
||||
return cnts.jiffies;
|
||||
}
|
||||
|
||||
U0 os_jiffies()
|
||||
{
|
||||
PUSH_SYSV_REGS
|
||||
GET_SYSV_ARGS
|
||||
@os_jiffies();
|
||||
POP_SYSV_REGS
|
||||
}
|
44
System/MakeSystem.HC
Normal file
44
System/MakeSystem.HC
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* clang-format off */
|
||||
|
||||
WinMax;
|
||||
AutoComplete(0);
|
||||
|
||||
U0 @patch_call_rel32(U32 from, U32 to)
|
||||
{
|
||||
*(from(U8*)) = 0xE8;
|
||||
*((from + 1)(I32*)) = to - from - 5;
|
||||
}
|
||||
|
||||
U0 @patch_jmp_rel32(U32 from, U32 to)
|
||||
{
|
||||
*(from(U8*)) = 0xE9;
|
||||
*((from + 1)(I32*)) = to - from - 5;
|
||||
}
|
||||
|
||||
U0 @sse_enable()
|
||||
{
|
||||
/* clang-format off */
|
||||
asm
|
||||
{
|
||||
MOV_EAX_CR0
|
||||
AND AX, 0xFFFB // clear coprocessor emulation CR0.EM
|
||||
OR AX, 0x2 // set coprocessor monitoring CR0.MP
|
||||
MOV_CR0_EAX
|
||||
MOV_EAX_CR4
|
||||
OR AX, 3 << 9 // set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
|
||||
MOV_CR4_EAX
|
||||
}
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
@sse_enable;
|
||||
|
||||
// FFI support files
|
||||
#include "FFI/Base";
|
||||
#include "FFI/LibC";
|
||||
#include "FFI/ELF64";
|
||||
|
||||
// LibTemple support files
|
||||
#include "LibTemple/OS";
|
||||
|
||||
/* clang-format on */
|
Loading…
Add table
Add a link
Reference in a new issue