I am porting Mupen64plus to UWP. For good performance, I have to port the dynamic recompiler. So I rewrote the file linker_arm.s using MS grammar and gets the project built. But the pointers out and base_addr are automatically changed to 0xffffffff when the nearby variables are modified in new_dynarec_init, which I can see from the watch window while running the release version of the app.
This is the code for allocating space and declaring the variables.
GLOBAL_VARIABLE extra_memory
GLOBAL_VARIABLE dynarec_local
GLOBAL_VARIABLE next_interupt
GLOBAL_VARIABLE cycle_count
GLOBAL_VARIABLE last_count
GLOBAL_VARIABLE pending_exception
GLOBAL_VARIABLE pcaddr
GLOBAL_VARIABLE stop
GLOBAL_VARIABLE invc_ptr
GLOBAL_VARIABLE address
GLOBAL_VARIABLE readmem_dword
GLOBAL_VARIABLE cpu_dword
GLOBAL_VARIABLE cpu_word
GLOBAL_VARIABLE cpu_hword
GLOBAL_VARIABLE cpu_byte
GLOBAL_VARIABLE FCR0
GLOBAL_VARIABLE FCR31
GLOBAL_VARIABLE reg
GLOBAL_VARIABLE hi
GLOBAL_VARIABLE lo
GLOBAL_VARIABLE g_cp0_regs
GLOBAL_VARIABLE reg_cop1_simple
GLOBAL_VARIABLE reg_cop1_double
GLOBAL_VARIABLE rounding_modes
GLOBAL_VARIABLE branch_target
GLOBAL_VARIABLE aPC
GLOBAL_VARIABLE fake_pc
GLOBAL_VARIABLE ram_offset
GLOBAL_VARIABLE mini_ht
GLOBAL_VARIABLE restore_candidate
GLOBAL_VARIABLE memory_map
AREA |.bbs|,DATA,READWRITE,ALIGN=12
padding DCD 0
dyna_mem SPACE 33554432+64+4+4+4+4+4+4+4+4+8+8+4+2+2+4+4+256+8+8+128+128+128+16+4+4+132+4+256+512+4194304
MAP dyna_mem
extra_memory FIELD 33554432
dynarec_local FIELD 64
next_interupt FIELD 4
cycle_count FIELD 4
last_count FIELD 4
pending_exception FIELD 4
pcaddr FIELD 4
stop FIELD 4
invc_ptr FIELD 4
address FIELD 4
readmem_dword FIELD 8
cpu_dword FIELD 8
cpu_word FIELD 4
cpu_hword FIELD 2
cpu_byte FIELD 2 ;1 byte free
FCR0 FIELD 4
FCR31 FIELD 4
reg FIELD 256
hi FIELD 8
lo FIELD 8
g_cp0_regs FIELD 128
reg_cop1_simple FIELD 128
reg_cop1_double FIELD 128
rounding_modes FIELD 16
branch_target FIELD 4
aPC FIELD 4
fake_pc FIELD 132
ram_offset FIELD 4
mini_ht FIELD 256
restore_candidate FIELD 512
memory_map FIELD 4194304
This is the function where it automatically changes out and base_addr to 0xffffffff. When memset(mini_ht, -1, sizeof(mini_ht)); is executed out, base_addr is changed to 0xffffffff. When memory_map[n] = ((u_int)g_rdram - 0x80000000) >> 2; is about to be executed, out is changed to 0xffffffff.
void new_dynarec_init()
{
DebugMessage(M64MSG_INFO, "Init new dynarec");
protect_readwrite();
const DWORD size = 100 + 1;
WCHAR chErrMsg[101];
DWORD dwErr = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), chErrMsg, size, NULL);
char mbcErrMsg[300];
UnicodeToMByte(chErrMsg, mbcErrMsg, 300);
DebugMessage(M64MSG_INFO, "new_dynarec_init(): %s", mbcErrMsg);
base_addr = ((int)(&extra_memory));
out = (u_char *)base_addr;
rdword = &readmem_dword;
fake_pc.f.r.rs = (long long int *)&readmem_dword;
fake_pc.f.r.rt = (long long int *)&readmem_dword;
fake_pc.f.r.rd = (long long int *)&readmem_dword;
int n;
for (n = 0x80000; n < 0x80800; n++)
invalid_code[n] = 1;
for (n = 0; n < 65536; n++)
hash_table[n][0] = hash_table[n][2] = -1;
memset(mini_ht, -1, sizeof(mini_ht));
memset(restore_candidate, 0, sizeof(restore_candidate));
copy = shadow;
expirep = 16384; // Expiry pointer, +2 blocks
pending_exception = 0;
literalcount = 0;
#ifdef HOST_IMM8
// Copy this into local area so we don't have to put it in every literal pool
invc_ptr = invalid_code;
#endif
stop_after_jal = 0;
// TLB
using_tlb = 0;
for (n = 0; n < 524288; n++) // 0 .. 0x7FFFFFFF
memory_map[n] = -1;
for (n = 524288; n < 526336; n++) // 0x80000000 .. 0x807FFFFF
memory_map[n] = ((u_int)g_rdram - 0x80000000) >> 2;
for (n = 526336; n < 1048576; n++) // 0x80800000 .. 0xFFFFFFFF
memory_map[n] = -1;
for (n = 0; n < 0x8000; n++) { // 0 .. 0x7FFFFFFF
writemem[n] = write_nomem_new;
writememb[n] = write_nomemb_new;
writememh[n] = write_nomemh_new;
writememd[n] = write_nomemd_new;
readmem[n] = read_nomem_new;
readmemb[n] = read_nomemb_new;
readmemh[n] = read_nomemh_new;
readmemd[n] = read_nomemd_new;
}
for (n = 0x8000; n < 0x8080; n++) { // 0x80000000 .. 0x807FFFFF
writemem[n] = write_rdram_new;
writememb[n] = write_rdramb_new;
writememh[n] = write_rdramh_new;
writememd[n] = write_rdramd_new;
}
for (n = 0xC000; n < 0x10000; n++) { // 0xC0000000 .. 0xFFFFFFFF
writemem[n] = write_nomem_new;
writememb[n] = write_nomemb_new;
writememh[n] = write_nomemh_new;
writememd[n] = write_nomemd_new;
readmem[n] = read_nomem_new;
readmemb[n] = read_nomemb_new;
readmemh[n] = read_nomemh_new;
readmemd[n] = read_nomemd_new;
}
tlb_hacks();
arch_init();
}
The memory pointed to by out is firstly given read and write permissions with below function, which might relates to this issue, but I am not sure.
void protect_readwrite()
{
#if NEW_DYNAREC == NEW_DYNAREC_ARM
PVOID addr = BASE_ADDR;
#else
PVOID addr = base_addr;
#endif
BOOL bVirPro = VirtualProtectFromApp(addr, 1 << TARGET_SIZE_2, PAGE_READWRITE, &oldProt);
oldProt = PAGE_READWRITE;
if (!bVirPro)
{
OutputDebugString("PAGE_READWRITE fail");
}
}
The declarations of out and base_addr are as below.
void *base_addr;
u_char *out;
Basically out and base_addr both intend to point to BASE_ADDR, a label declared in assem_arm.h as below.
#define BASE_ADDR ((int)(&extra_memory))
The dyanrec would have written emitted code into the memory pointed to by out pointer. However the out pointer with value 0xffffffff causes an invalid memory access error so the app crashes. Please help.
It looks like what you're trying to do with the MAP and FIELD directives won't work. The field definitions aren't meant to be referenced outside of the assembly file they're used in. The linker is treating them as common symbols and allocating only 4 bytes for them in a different section, the .bss
section (note the spelling). Since the means memory_map
is allocated a total of 4 bytes, when you initialize the first half of the array with -1, it overwrites other variables in the .bss
section, like out
and base_addr
.
Since there doesn't seem to be any point in using the MAP and FIELD directives to define these variables you should allocate them in the normal way:
dyna_mem
extra_memory SPACE 33554432
dynarec_local SPACE 64
next_interupt SPACE 4
cycle_count SPACE 4
last_count SPACE 4
pending_exception SPACE 4
pcaddr SPACE 4
stop SPACE 4
invc_ptr SPACE 4
address SPACE 4
readmem_dword SPACE 8
cpu_dword SPACE 8
cpu_word SPACE 4
cpu_hword SPACE 2
cpu_byte SPACE 2 ;1 byte free
FCR0 SPACE 4
FCR31 SPACE 4
reg SPACE 256
hi SPACE 8
lo SPACE 8
g_cp0_regs SPACE 128
reg_cop1_simple SPACE 128
reg_cop1_double SPACE 128
rounding_modes SPACE 16
branch_target SPACE 4
aPC SPACE 4
fake_pc SPACE 132
ram_offset SPACE 4
mini_ht SPACE 256
restore_candidate SPACE 512
memory_map SPACE 4194304
User contributions licensed under CC BY-SA 3.0