Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -237,15 +237,26 @@ LIB_OBJS_EXTRA = ${RUNTIME_RUNTIME_LIB_A} \ ${EXCEPTIONS_EXCEPTIONS_LIB_A} \ ${ENCODINGS_ENCODINGS_LIB_A} \ ${FORWARDING_FORWARDING_LIB_A} \ ${INVOCATION_INVOCATION_LIB_A} +AMIGA_LIB_OBJS_START = amiga-library.amigalib.o +AMIGA_LIB_OBJS_EXTRA = amiga-glue.amigalib.o \ + ${EXCEPTIONS_EXCEPTIONS_A} \ + ${ENCODINGS_ENCODINGS_A} \ + ${FORWARDING_FORWARDING_A} \ + ${INVOCATION_INVOCATION_A} \ + amiga-end.amigalib.o include ../buildsys.mk -CPPFLAGS += -I. -I.. -Iexceptions -Iruntime +CPPFLAGS += -I. -I.. -Iexceptions -Iruntime \ + -DOBJFW_AMIGA_LIB=\"${OBJFW_AMIGA_LIB}\" \ + -DOBJFW_LIB_MAJOR=${OBJFW_LIB_MAJOR} \ + -DOBJFW_LIB_MINOR=${OBJFW_LIB_MINOR} +AMIGA_LIB_CFLAGS += -DOF_COMPILING_AMIGA_LIBRARY LD = ${OBJC} FRAMEWORK_LIBS := -Fruntime \ ${RUNTIME_FRAMEWORK_LIBS} \ ${REEXPORT_RUNTIME_FRAMEWORK} \ ${LIBS} LIBS := -Lruntime ${RUNTIME_LIBS} ${REEXPORT_RUNTIME} ${LIBS} ADDED src/amiga-end.m Index: src/amiga-end.m ================================================================== --- src/amiga-end.m +++ src/amiga-end.m @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "platform.h" + +#ifdef OF_MORPHOS +__asm__ ( + ".section .ctors, \"aw\", @progbits\n" + " .long 0\n" +); +#else +__asm__ ( + "" +); +#endif ADDED src/amiga-glue.m Index: src/amiga-glue.m ================================================================== --- src/amiga-glue.m +++ src/amiga-glue.m @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "platform.h" + +#ifdef OF_AMIGAOS_M68K +# define PPC_PARAMS(...) (void) +# define M68K_ARG OBJC_M68K_ARG +#else +# define PPC_PARAMS(...) (__VA_ARGS__) +# define M68K_ARG(...) +#endif + +#ifdef OF_MORPHOS +/* All __saveds functions in this file need to use the SysV ABI */ +__asm__ ( + ".section .text\n" + ".align 2\n" + "__restore_r13:\n" + " lwz %r13, 44(%r12)\n" + " blr\n" +); +#endif + +/* To not have an empty compilation unit for now. */ +__asm__ ( + "" +); ADDED src/amiga-library.m Index: src/amiga-library.m ================================================================== --- src/amiga-library.m +++ src/amiga-library.m @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019, 2020 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFObject.h" + +#include +#include +#include +#include + +#define CONCAT_VERSION2(major, minor) #major "." #minor +#define CONCAT_VERSION(major, minor) CONCAT_VERSION2(major, minor) +#define VERSION_STRING CONCAT_VERSION(OBJFW_LIB_MAJOR, OBJFW_LIB_MINOR) + +#if defined(OF_AMIGAOS_M68K) +# define DATA_OFFSET 0x7FFE +#elif defined(OF_MORPHOS) +# define DATA_OFFSET 0x8000 +#endif + +#ifdef OF_AMIGAOS_M68K +# define OF_M68K_REG(reg) __asm__(#reg) +#else +# define OF_M68K_REG(reg) +#endif + +/* This always needs to be the first thing in the file. */ +int +_start() +{ + return -1; +} + +struct ObjFWBase { + struct Library library; + void *segList; + struct ObjFWBase *parent; + char *dataSeg; + bool initialized; +}; + +#ifdef OF_AMIGAOS_M68K +extern uintptr_t __CTOR_LIST__[]; +extern const void *_EH_FRAME_BEGINS__; +extern void *_EH_FRAME_OBJECTS__; +#endif + +#ifdef OF_MORPHOS +const ULONG __abox__ = 1; +#endif +struct ExecBase *SysBase; + +#if defined(OF_AMIGAOS_M68K) +__asm__ ( + ".text\n" + ".globl ___restore_a4\n" + ".align 1\n" + "___restore_a4:\n" + " movea.l 42(a6), a4\n" + " rts" +); +#elif defined(OF_MORPHOS) +/* All __saveds functions in this file need to use the M68K ABI */ +__asm__ ( + ".section .text\n" + ".align 2\n" + "__restore_r13:\n" + " lwz %r13, 56(%r2)\n" + " lwz %r13, 44(%r13)\n" + " blr\n" +); +#endif + +static OF_INLINE char * +getDataSeg(void) +{ + char *dataSeg; + +#if defined(OF_AMIGAOS_M68K) + __asm__ ( + "move.l #___a4_init, %0" + : "=r"(dataSeg) + ); +#elif defined(OF_MORPHOS) + __asm__ ( + "lis %0, __r13_init@ha\n\t" + "la %0, __r13_init@l(%0)" + : "=r"(dataSeg) + ); +#endif + + return dataSeg; +} + +static OF_INLINE size_t +getDataSize(void) +{ + size_t dataSize; + +#if defined(OF_AMIGAOS_M68K) + __asm__ ( + "move.l #___data_size, %0\n\t" + "add.l #___bss_size, %0" + : "=r"(dataSize) + ); +#elif defined(OF_MORPHOS) + __asm__ ( + "lis %0, __sdata_size@ha\n\t" + "la %0, __sdata_size@l(%0)\n\t" + "lis %%r9, __sbss_size@ha\n\t" + "la %%r9, __sbss_size@l(%%r9)\n\t" + "add %0, %0, %%r9" + : "=r"(dataSize) + :: "r9" + ); +#endif + + return dataSize; +} + +static OF_INLINE size_t * +getDataDataRelocs(void) +{ + size_t *dataDataRelocs; + +#if defined(OF_AMIGAOS_M68K) + __asm__ ( + "move.l #___datadata_relocs, %0" + : "=r"(dataDataRelocs) + ); +#elif defined(OF_MORPHOS) + __asm__ ( + "lis %0, __datadata_relocs@ha\n\t" + "la %0, __datadata_relocs@l(%0)\n\t" + : "=r"(dataDataRelocs) + ); +#endif + + return dataDataRelocs; +} + +static struct Library * +lib_init(struct ObjFWBase *base OF_M68K_REG(d0), void *segList OF_M68K_REG(a0), + struct ExecBase *sysBase OF_M68K_REG(a6)) +{ +#if defined(OF_AMIGAOS_M68K) + __asm__ __volatile__ ( + "move.l a6, _SysBase" + :: "a"(sysBase) + ); +#elif defined(OF_MORPHOS) + __asm__ __volatile__ ( + "lis %%r9, SysBase@ha\n\t" + "stw %0, SysBase@l(%%r9)" + :: "r"(sysBase) : "r9" + ); +#endif + + base->segList = segList; + base->parent = NULL; + base->dataSeg = getDataSeg(); + + return &base->library; +} + +struct Library *__saveds +lib_open(void) +{ + OF_M68K_ARG(struct ObjFWBase *, base, a6) + + struct ObjFWBase *child; + size_t dataSize, *dataDataRelocs; + ptrdiff_t displacement; + + if (base->parent != NULL) + return NULL; + + base->library.lib_OpenCnt++; + base->library.lib_Flags &= ~LIBF_DELEXP; + + /* + * We cannot use malloc here, as that depends on the libc passed from + * the application. + */ + if ((child = AllocMem(base->library.lib_NegSize + + base->library.lib_PosSize, MEMF_ANY)) == NULL) { + base->library.lib_OpenCnt--; + return NULL; + } + + memcpy(child, (char *)base - base->library.lib_NegSize, + base->library.lib_NegSize + base->library.lib_PosSize); + + child = (struct ObjFWBase *)((char *)child + base->library.lib_NegSize); + child->library.lib_OpenCnt = 1; + child->parent = base; + + dataSize = getDataSize(); + + if ((child->dataSeg = AllocMem(dataSize, MEMF_ANY)) == NULL) { + FreeMem((char *)child - child->library.lib_NegSize, + child->library.lib_NegSize + child->library.lib_PosSize); + base->library.lib_OpenCnt--; + return NULL; + } + + memcpy(child->dataSeg, base->dataSeg - DATA_OFFSET, dataSize); + + dataDataRelocs = getDataDataRelocs(); + displacement = child->dataSeg - (base->dataSeg - DATA_OFFSET); + + for (size_t i = 1; i <= dataDataRelocs[0]; i++) + *(long *)(child->dataSeg + dataDataRelocs[i]) += displacement; + + child->dataSeg += DATA_OFFSET; + + return &child->library; +} + +static void * +expunge(struct ObjFWBase *base) +{ + void *segList; + + if (base->parent != NULL) { + base->parent->library.lib_Flags |= LIBF_DELEXP; + return 0; + } + + if (base->library.lib_OpenCnt > 0) { + base->library.lib_Flags |= LIBF_DELEXP; + return 0; + } + + segList = base->segList; + + Remove(&base->library.lib_Node); + FreeMem((char *)base - base->library.lib_NegSize, + base->library.lib_NegSize + base->library.lib_PosSize); + + return segList; +} + +static void *__saveds +lib_expunge(void) +{ + OF_M68K_ARG(struct ObjFWBase *, base, a6) + + return expunge(base); +} + +static void *__saveds +lib_close(void) +{ + OF_M68K_ARG(struct ObjFWBase *, base, a6) + + if (base->parent != NULL) { + struct ObjFWBase *parent = base->parent; + + FreeMem(base->dataSeg - DATA_OFFSET, getDataSize()); + FreeMem((char *)base - base->library.lib_NegSize, + base->library.lib_NegSize + base->library.lib_PosSize); + + base = parent; + } + + if (--base->library.lib_OpenCnt == 0 && + (base->library.lib_Flags & LIBF_DELEXP)) + return expunge(base); + + return NULL; +} + +static void * +lib_null(void) +{ + return NULL; +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +static CONST_APTR functionTable[] = { +#ifdef OF_MORPHOS + (CONST_APTR)FUNCARRAY_BEGIN, + (CONST_APTR)FUNCARRAY_32BIT_NATIVE, +#endif + (CONST_APTR)lib_open, + (CONST_APTR)lib_close, + (CONST_APTR)lib_expunge, + (CONST_APTR)lib_null, +#ifdef OF_MORPHOS + (CONST_APTR)-1, + (CONST_APTR)FUNCARRAY_32BIT_SYSTEMV, +#endif +#ifdef OF_MORPHOS + (CONST_APTR)FUNCARRAY_END +#endif +}; +#pragma GCC diagnostic pop + +static struct { + ULONG dataSize; + CONST_APTR *functionTable; + ULONG *dataTable; + struct Library *(*initFunc)( + struct ObjFWBase *base OF_M68K_REG(d0), + void *segList OF_M68K_REG(a0), + struct ExecBase *execBase OF_M68K_REG(a6)); +} init_table = { + sizeof(struct ObjFWBase), + functionTable, + NULL, + lib_init +}; + +struct Resident resident = { + .rt_MatchWord = RTC_MATCHWORD, + .rt_MatchTag = &resident, + .rt_EndSkip = &resident + 1, + .rt_Flags = RTF_AUTOINIT +#ifdef OF_MORPHOS + | RTF_PPC | RTF_EXTENDED +#endif + , + .rt_Version = OBJFW_LIB_MAJOR, + .rt_Type = NT_LIBRARY, + .rt_Pri = 0, + .rt_Name = (char *)OBJFW_AMIGA_LIB, + .rt_IdString = (char *)"ObjFW " VERSION_STRING + " \xA9 2008-2020 Jonathan Schleifer", + .rt_Init = &init_table, +#ifdef OF_MORPHOS + .rt_Revision = OBJFW_LIB_MINOR, + .rt_Tags = NULL, +#endif +}; + +#ifdef OF_MORPHOS +__asm__ ( + ".section .ctors, \"aw\", @progbits\n" + "ctors:\n" + " .long -1\n" + ".section .text" +); +#endif Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -306,10 +306,21 @@ #if __has_attribute(__swift_name__) # define OF_SWIFT_NAME(name) __attribute__((__swift_name__(name))) #else # define OF_SWIFT_NAME(name) #endif + +#ifdef OF_COMPILING_AMIGA_LIBRARY +# if defined(__MORPHOS__) +# include +# define OF_M68K_ARG(type, name, reg) type name = (type)REG_##reg; +# else +# define OF_M68K_ARG(type, name, reg) \ + register type reg_##name __asm__(#reg); \ + type name = reg_##name; +# endif +#endif #ifdef __GNUC__ # ifdef OF_X86_64 # define OF_X86_64_ASM # endif Index: src/runtime/amiga-library.m ================================================================== --- src/runtime/amiga-library.m +++ src/runtime/amiga-library.m @@ -707,11 +707,11 @@ .rt_Version = OBJFWRT_LIB_MAJOR, .rt_Type = NT_LIBRARY, .rt_Pri = 0, .rt_Name = (char *)OBJFWRT_AMIGA_LIB, .rt_IdString = (char *)"ObjFWRT " VERSION_STRING - " \xA9 2008-2019 Jonathan Schleifer", + " \xA9 2008-2020 Jonathan Schleifer", .rt_Init = &init_table, #ifdef OF_MORPHOS .rt_Revision = OBJFWRT_LIB_MINOR, .rt_Tags = NULL, #endif