commit
08e3423a8c
9
Makefile
9
Makefile
|
@ -195,11 +195,12 @@ else ifeq ($(platform), vita)
|
||||||
TARGET := $(TARGET_NAME)_libretro_$(platform).a
|
TARGET := $(TARGET_NAME)_libretro_$(platform).a
|
||||||
CC = arm-vita-eabi-gcc$(EXE_EXT)
|
CC = arm-vita-eabi-gcc$(EXE_EXT)
|
||||||
AR = arm-vita-eabi-ar$(EXE_EXT)
|
AR = arm-vita-eabi-ar$(EXE_EXT)
|
||||||
CFLAGS += -DVITA
|
CFLAGS += -DVITA -g
|
||||||
CFLAGS += -marm -mcpu=cortex-a9
|
CFLAGS += -mthumb -mcpu=cortex-a9 -mfloat-abi=hard
|
||||||
ASFLAGS += -mcpu=cortex-a9
|
CFLAGS += -Wall -mword-relocations
|
||||||
|
CFLAGS += -fomit-frame-pointer -ffast-math
|
||||||
|
ASFLAGS += -mthumb -mcpu=cortex-a9
|
||||||
STATIC_LINKING = 1
|
STATIC_LINKING = 1
|
||||||
HAVE_DYNAREC = 1
|
|
||||||
CPU_ARCH := arm
|
CPU_ARCH := arm
|
||||||
|
|
||||||
# CTR(3DS)
|
# CTR(3DS)
|
||||||
|
|
|
@ -49,10 +49,8 @@ void execute_swi_thumb(u32 pc);
|
||||||
void execute_store_u32_safe(u32 address, u32 source);
|
void execute_store_u32_safe(u32 address, u32 source);
|
||||||
|
|
||||||
#define write32(value) \
|
#define write32(value) \
|
||||||
VITA_RW_INIT(); \
|
|
||||||
*((u32 *)translation_ptr) = value; \
|
*((u32 *)translation_ptr) = value; \
|
||||||
translation_ptr += 4; \
|
translation_ptr += 4 \
|
||||||
VITA_RW_END() \
|
|
||||||
|
|
||||||
#define arm_relative_offset(source, offset) \
|
#define arm_relative_offset(source, offset) \
|
||||||
(((((u32)offset - (u32)source) - 8) >> 2) & 0xFFFFFF) \
|
(((((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 \
|
cycle_count = 0 \
|
||||||
|
|
||||||
#define generate_branch_patch_conditional(dest, offset) \
|
#define generate_branch_patch_conditional(dest, offset) \
|
||||||
VITA_RW_INIT(); \
|
|
||||||
*((u32 *)(dest)) = (*((u32 *)dest) & 0xFF000000) | \
|
*((u32 *)(dest)) = (*((u32 *)dest) & 0xFF000000) | \
|
||||||
arm_relative_offset(dest, offset); \
|
arm_relative_offset(dest, offset) \
|
||||||
VITA_RW_END(); \
|
|
||||||
|
|
||||||
|
|
||||||
#define generate_branch_patch_unconditional(dest, offset) \
|
#define generate_branch_patch_unconditional(dest, offset) \
|
||||||
VITA_RW_INIT(); \
|
|
||||||
*((u32 *)(dest)) = (*((u32 *)dest) & 0xFF000000) | \
|
*((u32 *)(dest)) = (*((u32 *)dest) & 0xFF000000) | \
|
||||||
arm_relative_offset(dest, offset); \
|
arm_relative_offset(dest, offset) \
|
||||||
VITA_RW_END(); \
|
|
||||||
|
|
||||||
// A different function is called for idle updates because of the relative
|
// 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
|
// location of the embedded PC. The idle version could be optimized to put
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#if defined(VITA)
|
#if defined(VITA)
|
||||||
#include <psp2/kernel/sysmem.h>
|
#include <psp2/kernel/sysmem.h>
|
||||||
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u8 *last_rom_translation_ptr = NULL;
|
u8 *last_rom_translation_ptr = NULL;
|
||||||
|
@ -251,7 +252,7 @@ extern u8 bit_count[256];
|
||||||
|
|
||||||
#define invalidate_icache_region(addr, size) \
|
#define invalidate_icache_region(addr, size) \
|
||||||
{ \
|
{ \
|
||||||
sceKernelSyncVMDomain(sceBlock, addr, size); \
|
int ret = sceKernelSyncVMDomain(sceBlock, addr, size); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(_3DS)
|
#elif defined(_3DS)
|
||||||
|
@ -2837,8 +2838,10 @@ u8 *block_lookup_address_##type(u32 pc) \
|
||||||
u8 *block_address; \
|
u8 *block_address; \
|
||||||
\
|
\
|
||||||
/* Starting at the beginning, we allow for one translation cache flush. */ \
|
/* 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; \
|
translation_flush_count = 0; \
|
||||||
|
RW_INIT(); \
|
||||||
|
} \
|
||||||
block_lookup_address_pc_##type(); \
|
block_lookup_address_pc_##type(); \
|
||||||
\
|
\
|
||||||
switch(pc >> 24) \
|
switch(pc >> 24) \
|
||||||
|
@ -2871,7 +2874,6 @@ u8 *block_lookup_address_##type(u32 pc) \
|
||||||
(ROM_BRANCH_HASH_SIZE - 1); \
|
(ROM_BRANCH_HASH_SIZE - 1); \
|
||||||
u32 *block_ptr = rom_branch_hash[hash_target]; \
|
u32 *block_ptr = rom_branch_hash[hash_target]; \
|
||||||
u32 **block_ptr_address = rom_branch_hash + hash_target; \
|
u32 **block_ptr_address = rom_branch_hash + hash_target; \
|
||||||
RW_INIT(); \
|
|
||||||
while(block_ptr) \
|
while(block_ptr) \
|
||||||
{ \
|
{ \
|
||||||
if(block_ptr[0] == pc) \
|
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_address = (u32 **)(block_ptr + 1); \
|
||||||
block_ptr = (u32 *)block_ptr[1]; \
|
block_ptr = (u32 *)block_ptr[1]; \
|
||||||
} \
|
} \
|
||||||
RW_END(); \
|
|
||||||
if(!block_ptr) \
|
if(!block_ptr) \
|
||||||
{ \
|
{ \
|
||||||
__label__ redo; \
|
__label__ redo; \
|
||||||
|
@ -2891,13 +2892,11 @@ u8 *block_lookup_address_##type(u32 pc) \
|
||||||
redo: \
|
redo: \
|
||||||
\
|
\
|
||||||
translation_recursion_level++; \
|
translation_recursion_level++; \
|
||||||
RW_INIT(); \
|
|
||||||
((u32 *)rom_translation_ptr)[0] = pc; \
|
((u32 *)rom_translation_ptr)[0] = pc; \
|
||||||
((u32 **)rom_translation_ptr)[1] = NULL; \
|
((u32 **)rom_translation_ptr)[1] = NULL; \
|
||||||
*block_ptr_address = (u32 *)rom_translation_ptr; \
|
*block_ptr_address = (u32 *)rom_translation_ptr; \
|
||||||
rom_translation_ptr += 8; \
|
rom_translation_ptr += 8; \
|
||||||
block_address = rom_translation_ptr + block_prologue_size; \
|
block_address = rom_translation_ptr + block_prologue_size; \
|
||||||
RW_END(); \
|
|
||||||
block_lookup_translate_##type(rom, 0); \
|
block_lookup_translate_##type(rom, 0); \
|
||||||
translation_recursion_level--; \
|
translation_recursion_level--; \
|
||||||
\
|
\
|
||||||
|
@ -2937,7 +2936,9 @@ u8 *block_lookup_address_##type(u32 pc) \
|
||||||
block_address = (u8 *)(-1); \
|
block_address = (u8 *)(-1); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
\
|
if(translation_recursion_level == 0) \
|
||||||
|
RW_END(); \
|
||||||
|
\
|
||||||
return block_address; \
|
return block_address; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
@ -3292,6 +3293,7 @@ s32 translate_block_arm(u32 pc, translation_region_type
|
||||||
s32 i;
|
s32 i;
|
||||||
u32 flag_status;
|
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();
|
generate_block_extra_vars_arm();
|
||||||
arm_fix_pc();
|
arm_fix_pc();
|
||||||
|
|
||||||
|
@ -3399,7 +3401,7 @@ s32 translate_block_arm(u32 pc, translation_region_type
|
||||||
flush_translation_cache_bios();
|
flush_translation_cache_bios();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
RW_END();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3476,12 +3478,14 @@ s32 translate_block_arm(u32 pc, translation_region_type
|
||||||
{
|
{
|
||||||
branch_target = external_block_exits[i].branch_target;
|
branch_target = external_block_exits[i].branch_target;
|
||||||
arm_link_block();
|
arm_link_block();
|
||||||
if(!translation_target)
|
if(!translation_target){
|
||||||
return -1;
|
RW_END();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
generate_branch_patch_unconditional(
|
generate_branch_patch_unconditional(
|
||||||
external_block_exits[i].branch_source, translation_target);
|
external_block_exits[i].branch_source, translation_target);
|
||||||
}
|
}
|
||||||
|
RW_END();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3509,6 +3513,7 @@ s32 translate_block_thumb(u32 pc, translation_region_type
|
||||||
s32 i;
|
s32 i;
|
||||||
u32 flag_status;
|
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();
|
generate_block_extra_vars_thumb();
|
||||||
thumb_fix_pc();
|
thumb_fix_pc();
|
||||||
|
|
||||||
|
@ -3616,7 +3621,7 @@ s32 translate_block_thumb(u32 pc, translation_region_type
|
||||||
flush_translation_cache_bios();
|
flush_translation_cache_bios();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
RW_END();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3693,12 +3698,14 @@ s32 translate_block_thumb(u32 pc, translation_region_type
|
||||||
{
|
{
|
||||||
branch_target = external_block_exits[i].branch_target;
|
branch_target = external_block_exits[i].branch_target;
|
||||||
thumb_link_block();
|
thumb_link_block();
|
||||||
if(!translation_target)
|
if(!translation_target){
|
||||||
|
RW_END();
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
generate_branch_patch_unconditional(
|
generate_branch_patch_unconditional(
|
||||||
external_block_exits[i].branch_source, translation_target);
|
external_block_exits[i].branch_source, translation_target);
|
||||||
}
|
}
|
||||||
|
RW_END();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "amd64.c"
|
#include "amd64.c"
|
||||||
#elif defined(__GNUC__) && defined(_ARCH_PPC)
|
#elif defined(__GNUC__) && defined(_ARCH_PPC)
|
||||||
#include "ppc.c"
|
#include "ppc.c"
|
||||||
|
#elif defined(VITA)
|
||||||
|
#include "psp2.c"
|
||||||
#elif defined(__GNUC__) && (defined(__ARM_EABI__) || defined(__arm__))
|
#elif defined(__GNUC__) && (defined(__ARM_EABI__) || defined(__arm__))
|
||||||
#include "armeabi.c"
|
#include "armeabi.c"
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
|
|
|
@ -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
|
12
libretro.c
12
libretro.c
|
@ -9,7 +9,7 @@
|
||||||
#include "memmap.h"
|
#include "memmap.h"
|
||||||
|
|
||||||
|
|
||||||
#if defined(VITA)
|
#if defined(VITA) && defined(HAVE_DYNAREC)
|
||||||
#include <psp2/kernel/sysmem.h>
|
#include <psp2/kernel/sysmem.h>
|
||||||
static int translation_caches_inited = 0;
|
static int translation_caches_inited = 0;
|
||||||
static inline int align(int x, int n) {
|
static inline int align(int x, int n) {
|
||||||
|
@ -159,15 +159,13 @@ void retro_init(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(VITA)
|
#if defined(VITA) && defined(HAVE_DYNAREC)
|
||||||
if(!translation_caches_inited){
|
if(!translation_caches_inited){
|
||||||
void* currentHandle;
|
void* currentHandle;
|
||||||
|
|
||||||
sceBlock = sceKernelAllocMemBlockForVM("code", MB_ALIGN(FOUR_KB_ALIGN(ROM_TRANSLATION_CACHE_SIZE +
|
sceBlock = sceKernelAllocMemBlockForVM("code", MB_ALIGN(FOUR_KB_ALIGN(ROM_TRANSLATION_CACHE_SIZE +
|
||||||
RAM_TRANSLATION_CACHE_SIZE +
|
RAM_TRANSLATION_CACHE_SIZE +
|
||||||
BIOS_TRANSLATION_CACHE_SIZE)));
|
BIOS_TRANSLATION_CACHE_SIZE)));
|
||||||
FILE * fd = fopen("ux0:/temp/test.txt","w+");
|
|
||||||
fprintf(fd,"%x\n",sceBlock);
|
|
||||||
if (sceBlock < 0)
|
if (sceBlock < 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -179,9 +177,6 @@ void retro_init(void)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fprintf(fd,"%x %x\n",currentHandle,ret);
|
|
||||||
|
|
||||||
fclose(fd);
|
|
||||||
|
|
||||||
rom_translation_cache = (u8*)currentHandle;
|
rom_translation_cache = (u8*)currentHandle;
|
||||||
ram_translation_cache = rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE;
|
ram_translation_cache = rom_translation_cache + ROM_TRANSLATION_CACHE_SIZE;
|
||||||
|
@ -240,7 +235,7 @@ void retro_deinit(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(VITA)
|
#if defined(VITA) && defined(HAVE_DYNAREC)
|
||||||
if(translation_caches_inited){
|
if(translation_caches_inited){
|
||||||
sceKernelFreeMemBlock(sceBlock);
|
sceKernelFreeMemBlock(sceBlock);
|
||||||
|
|
||||||
|
@ -487,7 +482,6 @@ bool retro_load_game(const struct retro_game_info* info)
|
||||||
}
|
}
|
||||||
|
|
||||||
gamepak_filename[0] = 0;
|
gamepak_filename[0] = 0;
|
||||||
|
|
||||||
if (load_gamepak(info, info->path) != 0)
|
if (load_gamepak(info, info->path) != 0)
|
||||||
{
|
{
|
||||||
error_msg("Could not load the game file.");
|
error_msg("Could not load the game file.");
|
||||||
|
|
Loading…
Reference in New Issue