diff options
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | arm/arm_emit.h | 12 | ||||
-rw-r--r-- | cpu_threaded.c | 41 | ||||
-rw-r--r-- | libco/libco.c | 2 | ||||
-rw-r--r-- | libco/psp2.c | 116 | ||||
-rw-r--r-- | libretro.c | 12 |
6 files changed, 153 insertions, 39 deletions
@@ -195,11 +195,12 @@ else ifeq ($(platform), vita) TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = arm-vita-eabi-gcc$(EXE_EXT) AR = arm-vita-eabi-ar$(EXE_EXT) - CFLAGS += -DVITA - CFLAGS += -marm -mcpu=cortex-a9 - ASFLAGS += -mcpu=cortex-a9 + CFLAGS += -DVITA -g + CFLAGS += -mthumb -mcpu=cortex-a9 -mfloat-abi=hard + CFLAGS += -Wall -mword-relocations + CFLAGS += -fomit-frame-pointer -ffast-math + ASFLAGS += -mthumb -mcpu=cortex-a9 STATIC_LINKING = 1 - HAVE_DYNAREC = 1 CPU_ARCH := arm # CTR(3DS) diff --git a/arm/arm_emit.h b/arm/arm_emit.h index bfd1c49..185caef 100644 --- a/arm/arm_emit.h +++ b/arm/arm_emit.h @@ -49,10 +49,8 @@ void execute_swi_thumb(u32 pc); void execute_store_u32_safe(u32 address, u32 source); #define write32(value) \ - VITA_RW_INIT(); \ *((u32 *)translation_ptr) = value; \ - translation_ptr += 4; \ - VITA_RW_END() \ + translation_ptr += 4 \ #define arm_relative_offset(source, offset) \ (((((u32)offset - (u32)source) - 8) >> 2) & 0xFFFFFF) \ @@ -409,17 +407,13 @@ u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations) cycle_count = 0 \ #define generate_branch_patch_conditional(dest, offset) \ - VITA_RW_INIT(); \ *((u32 *)(dest)) = (*((u32 *)dest) & 0xFF000000) | \ - arm_relative_offset(dest, offset); \ - VITA_RW_END(); \ + arm_relative_offset(dest, offset) \ #define generate_branch_patch_unconditional(dest, offset) \ - VITA_RW_INIT(); \ *((u32 *)(dest)) = (*((u32 *)dest) & 0xFF000000) | \ - arm_relative_offset(dest, offset); \ - VITA_RW_END(); \ + arm_relative_offset(dest, offset) \ // A different function is called for idle updates because of the relative // location of the embedded PC. The idle version could be optimized to put diff --git a/cpu_threaded.c b/cpu_threaded.c index e3e1a14..ca5b99e 100644 --- a/cpu_threaded.c +++ b/cpu_threaded.c @@ -24,6 +24,7 @@ #include "common.h" #if defined(VITA) #include <psp2/kernel/sysmem.h> +#include <stdio.h> #endif u8 *last_rom_translation_ptr = NULL; @@ -251,7 +252,7 @@ extern u8 bit_count[256]; #define invalidate_icache_region(addr, size) \ { \ - sceKernelSyncVMDomain(sceBlock, addr, size); \ + int ret = sceKernelSyncVMDomain(sceBlock, addr, size); \ } #elif defined(_3DS) @@ -2837,8 +2838,10 @@ u8 *block_lookup_address_##type(u32 pc) \ u8 *block_address; \ \ /* Starting at the beginning, we allow for one translation cache flush. */ \ - if(translation_recursion_level == 0) \ + if(translation_recursion_level == 0){ \ translation_flush_count = 0; \ + RW_INIT(); \ + } \ block_lookup_address_pc_##type(); \ \ switch(pc >> 24) \ @@ -2871,7 +2874,6 @@ u8 *block_lookup_address_##type(u32 pc) \ (ROM_BRANCH_HASH_SIZE - 1); \ u32 *block_ptr = rom_branch_hash[hash_target]; \ u32 **block_ptr_address = rom_branch_hash + hash_target; \ - RW_INIT(); \ while(block_ptr) \ { \ if(block_ptr[0] == pc) \ @@ -2882,7 +2884,6 @@ u8 *block_lookup_address_##type(u32 pc) \ block_ptr_address = (u32 **)(block_ptr + 1); \ block_ptr = (u32 *)block_ptr[1]; \ } \ - RW_END(); \ if(!block_ptr) \ { \ __label__ redo; \ @@ -2891,13 +2892,11 @@ u8 *block_lookup_address_##type(u32 pc) \ redo: \ \ translation_recursion_level++; \ - RW_INIT(); \ ((u32 *)rom_translation_ptr)[0] = pc; \ ((u32 **)rom_translation_ptr)[1] = NULL; \ *block_ptr_address = (u32 *)rom_translation_ptr; \ rom_translation_ptr += 8; \ block_address = rom_translation_ptr + block_prologue_size; \ - RW_END(); \ block_lookup_translate_##type(rom, 0); \ translation_recursion_level--; \ \ @@ -2937,7 +2936,9 @@ u8 *block_lookup_address_##type(u32 pc) \ block_address = (u8 *)(-1); \ break; \ } \ - \ + if(translation_recursion_level == 0) \ + RW_END(); \ + \ return block_address; \ } \ @@ -3291,7 +3292,8 @@ s32 translate_block_arm(u32 pc, translation_region_type u8 *translation_cache_limit = NULL; s32 i; u32 flag_status; - block_exit_type external_block_exits[MAX_EXITS]; + block_exit_type external_block_exits[MAX_EXITS]; + RW_INIT(); generate_block_extra_vars_arm(); arm_fix_pc(); @@ -3399,7 +3401,7 @@ s32 translate_block_arm(u32 pc, translation_region_type flush_translation_cache_bios(); break; } - + RW_END(); return -1; } @@ -3476,12 +3478,14 @@ s32 translate_block_arm(u32 pc, translation_region_type { branch_target = external_block_exits[i].branch_target; arm_link_block(); - if(!translation_target) - return -1; + if(!translation_target){ + RW_END(); + return -1; + } generate_branch_patch_unconditional( external_block_exits[i].branch_source, translation_target); } - + RW_END(); return 0; } @@ -3508,7 +3512,8 @@ s32 translate_block_thumb(u32 pc, translation_region_type u8 *translation_cache_limit = NULL; s32 i; u32 flag_status; - block_exit_type external_block_exits[MAX_EXITS]; + block_exit_type external_block_exits[MAX_EXITS]; + RW_INIT(); generate_block_extra_vars_thumb(); thumb_fix_pc(); @@ -3616,7 +3621,7 @@ s32 translate_block_thumb(u32 pc, translation_region_type flush_translation_cache_bios(); break; } - + RW_END(); return -1; } @@ -3693,12 +3698,14 @@ s32 translate_block_thumb(u32 pc, translation_region_type { branch_target = external_block_exits[i].branch_target; thumb_link_block(); - if(!translation_target) - return -1; + if(!translation_target){ + RW_END(); + return -1; + } generate_branch_patch_unconditional( external_block_exits[i].branch_source, translation_target); } - + RW_END(); return 0; } diff --git a/libco/libco.c b/libco/libco.c index 63126d3..7bcbbd0 100644 --- a/libco/libco.c +++ b/libco/libco.c @@ -10,6 +10,8 @@ #include "amd64.c" #elif defined(__GNUC__) && defined(_ARCH_PPC) #include "ppc.c" +#elif defined(VITA) + #include "psp2.c" #elif defined(__GNUC__) && (defined(__ARM_EABI__) || defined(__arm__)) #include "armeabi.c" #elif defined(__GNUC__) diff --git a/libco/psp2.c b/libco/psp2.c new file mode 100644 index 0000000..3ab1bc7 --- /dev/null +++ b/libco/psp2.c @@ -0,0 +1,116 @@ +/* + libco.arm (2016-08-14) + author: frangarcj + license: public domain +*/ + +#define LIBCO_C +#include "libco.h" + +#include <assert.h> +#include <stdlib.h> +#include <unistd.h> +#include <psp2/kernel/sysmem.h> +#include <stdio.h> +#include <string.h> +#ifdef __cplusplus +extern "C" { +#endif + +static inline int align(int x, int n) { + return (((x >> n) + 1) << n ); +} +#define FOUR_KB_ALIGN(x) align(x, 12) +#define MB_ALIGN(x) align(x, 20) + +static thread_local unsigned long co_active_buffer[64]; +static thread_local cothread_t co_active_handle = 0; +static void (*co_swap)(cothread_t, cothread_t) = 0; +static int block; +static uint32_t co_swap_function[] = { + 0xe8a16ff0, /* stmia r1!, {r4-r11,sp,lr} */ + 0xe8b0aff0, /* ldmia r0!, {r4-r11,sp,pc} */ + 0xe12fff1e, /* bx lr */ +}; + +void co_init() { + int ret; + void *base; + + block = sceKernelAllocMemBlockForVM("libco", MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function))); + if (block < 0) + { + return; + } + + // get base address + ret = sceKernelGetMemBlockBase(block, &base); + if (ret < 0) + { + return; + } + + // set domain to be writable by user + ret = sceKernelOpenVMDomain(); + if (ret < 0) + { + return; + } + + + memcpy(base,co_swap_function,sizeof co_swap_function); + + // set domain back to read-only + ret = sceKernelCloseVMDomain(); + if (ret < 0) + { + return; + } + + // flush icache + ret = sceKernelSyncVMDomain(block, base, MB_ALIGN(FOUR_KB_ALIGN(sizeof co_swap_function))); + if (ret < 0) + { + return; + } + + co_swap = (void (*)(cothread_t, cothread_t))base; + + +} + +cothread_t co_active() { + if(!co_active_handle) co_active_handle = &co_active_buffer; + return co_active_handle; +} + +cothread_t co_create(unsigned int size, void (*entrypoint)(void)) { + unsigned long* handle = 0; + if(!co_swap) { + co_init(); + } + if(!co_active_handle) co_active_handle = &co_active_buffer; + size += 256; + size &= ~15; + + if((handle = (unsigned long*)malloc(size))) { + unsigned long* p = (unsigned long*)((unsigned char*)handle + size); + handle[8] = (unsigned long)p; + handle[9] = (unsigned long)entrypoint; + } + + return handle; +} + +void co_delete(cothread_t handle) { + free(handle); +} + +void co_switch(cothread_t handle) { + cothread_t co_previous_handle = co_active_handle; + co_swap(co_active_handle = handle, co_previous_handle); +} + +#ifdef __cplusplus +} +#endif @@ -9,7 +9,7 @@ #include "memmap.h" -#if defined(VITA) +#if defined(VITA) && defined(HAVE_DYNAREC) #include <psp2/kernel/sysmem.h> static int translation_caches_inited = 0; static inline int align(int x, int n) { @@ -159,15 +159,13 @@ void retro_init(void) } #endif -#if defined(VITA) +#if defined(VITA) && defined(HAVE_DYNAREC) if(!translation_caches_inited){ void* currentHandle; sceBlock = sceKernelAllocMemBlockForVM("code", MB_ALIGN(FOUR_KB_ALIGN(ROM_TRANSLATION_CACHE_SIZE + RAM_TRANSLATION_CACHE_SIZE + BIOS_TRANSLATION_CACHE_SIZE))); - FILE * fd = fopen("ux0:/temp/test.txt","w+"); - fprintf(fd,"%x\n",sceBlock); if (sceBlock < 0) { return; @@ -179,9 +177,6 @@ void retro_init(void) { return; } - fprintf(fd,"%x %x\n",currentHandle,ret); - - fclose(fd); rom_translation_cache = (u8*)currentHandle; ram_translation_cache = rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE; @@ -240,7 +235,7 @@ void retro_deinit(void) } #endif -#if defined(VITA) +#if defined(VITA) && defined(HAVE_DYNAREC) if(translation_caches_inited){ sceKernelFreeMemBlock(sceBlock); @@ -487,7 +482,6 @@ bool retro_load_game(const struct retro_game_info* info) } gamepak_filename[0] = 0; - if (load_gamepak(info, info->path) != 0) { error_msg("Could not load the game file."); |