From 1cc5202ccfd3a73a614d492fce70a210cdc81b5c Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Fri, 17 Jul 2015 21:07:03 +0200 Subject: [PATCH] Reorganize startup code (make some parts publicly available) --- CMakeLists.txt | 1 + libretro/CMakeLists.txt | 5 +- libretro/Retro68Runtime.h | 46 +++++++++++++ libretro/relocate.c | 137 ++++++++++++++++++++++++++++++++++++++ libretro/start.c | 92 ++----------------------- 5 files changed, 192 insertions(+), 89 deletions(-) create mode 100644 libretro/Retro68Runtime.h create mode 100644 libretro/relocate.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 463aa92999..c45771fe17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ add_subdirectory(libretro) # add library path so that GCC picks up the freshly-built libretro link_directories(${CMAKE_CURRENT_BINARY_DIR}/libretro) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libretro) add_subdirectory(Console) add_subdirectory(TestApps) diff --git a/libretro/CMakeLists.txt b/libretro/CMakeLists.txt index 3327a0f7ff..428a65d493 100644 --- a/libretro/CMakeLists.txt +++ b/libretro/CMakeLists.txt @@ -23,7 +23,10 @@ cmake_minimum_required(VERSION 2.8) -add_library(retrocrt start.c +add_library(retrocrt + Retro68Runtime.h + start.c + relocate.c malloc.c syscalls.c glue.c diff --git a/libretro/Retro68Runtime.h b/libretro/Retro68Runtime.h new file mode 100644 index 0000000000..c2e1366dc8 --- /dev/null +++ b/libretro/Retro68Runtime.h @@ -0,0 +1,46 @@ +/* + Copyright 2015 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING and COPYING.RUNTIME respectively. If not, see + . +*/ + +#define RETRO68_GET_DISPLACEMENT(DISPLACEMENT) \ + do { \ + long virtualstart, realstart; \ + __asm__( "1:\n" \ + "\tmove.l #1b, %0\n" \ + "\tlea (1b:w,%%pc), %1" \ + : "=r"(virtualstart) , "=a"(realstart) ); \ + DISPLACEMENT = realstart - virtualstart; \ + } while(0) + +#define RETRO68_CALL_UNRELOCATED(FUN,ARGS) \ + do { \ + long displacement; \ + RETRO68_GET_DISPLACEMENT(displacement); \ + (*(typeof(&FUN)) ((char*)(&FUN) + displacement)) ARGS; \ + } while(0) + +void Retro68Relocate(); +void Retro68CallConstructors(); + +#define RETRO68_RELOCATE() RETRO68_CALL_UNRELOCATED(Retro68Relocate,()) diff --git a/libretro/relocate.c b/libretro/relocate.c new file mode 100644 index 0000000000..08e727e679 --- /dev/null +++ b/libretro/relocate.c @@ -0,0 +1,137 @@ +/* + Copyright 2015 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING and COPYING.RUNTIME respectively. If not, see + . +*/ + +#include +#include + +#include +#include +#include +#include + +#include "Retro68Runtime.h" + + +struct flat_hdr { + char magic[4]; + unsigned long rev; /* version */ + unsigned long entry; /* Offset of first executable instruction + with text segment from beginning of file */ + unsigned long data_start; /* Offset of data segment from beginning of + file */ + unsigned long data_end; /* Offset of end of data segment + from beginning of file */ + unsigned long bss_end; /* Offset of end of bss segment from beginning + of file */ + + /* (It is assumed that data_end through bss_end forms the bss segment.) */ + + unsigned long stack_size; /* Size of stack, in bytes */ + unsigned long reloc_start; /* Offset of relocation records from + beginning of file */ + unsigned long reloc_count; /* Number of relocation records */ + unsigned long flags; + unsigned long filler[6]; /* Reserved, set to zero */ +}; + +typedef void (*voidFunction)(void); + +extern void __init_section(void); +extern void __init_section_end(void); +extern void __fini_section(void); +extern void __fini_section_end(void); + + + +static long headerVirtualAddress = -0x40; +static Ptr savedBSS = (Ptr) -1; + +#define ACCESS_DISPLACED(VAR) \ + ( * (typeof(&VAR)) ((char*)(&VAR) + displacement) ) + +void Retro68Relocate() +{ + long displacement; + RETRO68_GET_DISPLACEMENT(displacement); + + struct flat_hdr *header = (struct flat_hdr*) (ACCESS_DISPLACED(headerVirtualAddress) + displacement); + + SysEnvRec env; + long bss_size; + + env.processor = 0; + SysEnvirons(0, &env); + + bss_size = header->bss_end - header->data_end; + + long n = header->reloc_count; + long *relocs = (long*)( (char*)header + header->reloc_start ); + long i; + long data_end = header->data_end - 0x40; + long bss_displacement = 0; + + Ptr bss = ACCESS_DISPLACED(savedBSS); + if(bss == (Ptr)-1) + { + bss = NewPtrClear(bss_size); + bss_displacement = (long)bss - data_end; + } + + for(i = 0; i < n; i++) + { + uint8_t *addrPtr = (uint8_t*)(relocs[i] + displacement); + long addr; + + addr = (addrPtr[0] << 24) | (addrPtr[1] << 16) | (addrPtr[2] << 8) | addrPtr[3]; + + addr += addr >= data_end ? bss_displacement : displacement; + + addrPtr[0] = addr >> 24; + addrPtr[1] = addr >> 16; + addrPtr[2] = addr >> 8; + addrPtr[3] = addr; + } + + if(env.processor >= env68040) + { + FlushCodeCache(); + } + // accessing globals and calling functions is OK below here. + + headerVirtualAddress += displacement; + savedBSS = bss; +} + +void Retro68CallConstructors() +{ + char *p = (char*)&__init_section; + char *e = (char*)&__init_section_end; + p += 2; + while( p < e ) + { + (*(voidFunction)(*(long*)p))(); + p += 6; + } +} diff --git a/libretro/start.c b/libretro/start.c index 89d187fd3d..52b8893dbb 100644 --- a/libretro/start.c +++ b/libretro/start.c @@ -25,101 +25,17 @@ #include #include +#include -#include -#include -#include -#include - +#include "Retro68Runtime.h" int main(int argc, char* argv[]); -struct flat_hdr { - char magic[4]; - unsigned long rev; /* version */ - unsigned long entry; /* Offset of first executable instruction - with text segment from beginning of file */ - unsigned long data_start; /* Offset of data segment from beginning of - file */ - unsigned long data_end; /* Offset of end of data segment - from beginning of file */ - unsigned long bss_end; /* Offset of end of bss segment from beginning - of file */ - - /* (It is assumed that data_end through bss_end forms the bss segment.) */ - - unsigned long stack_size; /* Size of stack, in bytes */ - unsigned long reloc_start; /* Offset of relocation records from - beginning of file */ - unsigned long reloc_count; /* Number of relocation records */ - unsigned long flags; - unsigned long filler[6]; /* Reserved, set to zero */ -}; - -typedef void (*voidFunction)(void); - -extern void __init_section(void); -extern void __init_section_end(void); -extern void __fini_section(void); -extern void __fini_section_end(void); - - void _start() { - - long virtualstart, realstart; - - __asm__( "move.l #_start, %0" : "=r"(virtualstart) ); - __asm__( "lea (_start:w,%%pc), %0" : "=a"(realstart) ); - - long displacement = realstart - virtualstart; - - struct flat_hdr *header = (struct flat_hdr*) (displacement - 0x40); - - SysEnvRec env; - long bss_size; - - env.processor = 0; - SysEnvirons(0, &env); + RETRO68_RELOCATE(); + Retro68CallConstructors(); - bss_size = header->bss_end - header->data_end; - Ptr bss = NewPtrClear(bss_size); - - long n = header->reloc_count; - long *relocs = (long*)( (char*)header + header->reloc_start ); - long i; - long data_end = header->data_end - 0x40; - long bss_displacement = (long)bss - data_end; - - for(i = 0; i < n; i++) - { - uint8_t *addrPtr = (uint8_t*)(relocs[i] + displacement); - long addr; - - addr = (addrPtr[0] << 24) | (addrPtr[1] << 16) | (addrPtr[2] << 8) | addrPtr[3]; - - addr += addr >= data_end ? bss_displacement : displacement; - - addrPtr[0] = addr >> 24; - addrPtr[1] = addr >> 16; - addrPtr[2] = addr >> 8; - addrPtr[3] = addr; - } - if(env.processor >= env68040) - { - FlushCodeCache(); - } - { - char *p = (char*)&__init_section; - char *e = (char*)&__init_section_end; - p += 2; - while( p < e ) - { - (*(voidFunction)(*(long*)p))(); - p += 6; - } - } - int result; { char *argv[2] = { "./a.out", NULL };