mirror of
https://github.com/Dillonb/n64.git
synced 2024-05-17 03:20:34 -04:00
implement data cache
This commit is contained in:
parent
4a727909bd
commit
1e461dc014
|
@ -10,6 +10,7 @@ configure_file(../contrib/tools/dynasm/dasm_x86.lua dynasm/dasm_x86.lua COPYONLY
|
|||
|
||||
add_library(r4300i
|
||||
r4300i.c r4300i.h r4300i_register_access.h
|
||||
cache.c cache.h
|
||||
mips_instructions.c mips_instructions.h
|
||||
fpu_instructions.c fpu_instructions.h
|
||||
tlb_instructions.c tlb_instructions.h
|
||||
|
|
92
src/cpu/cache.c
Normal file
92
src/cpu/cache.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include "cache.h"
|
||||
#include <system/n64system.h>
|
||||
#include <mem/mem_util.h>
|
||||
|
||||
void writeback_dcache(u64 vaddr, u32 paddr) {
|
||||
int cache_line = get_dcache_line_index(vaddr);
|
||||
dcache_line_t* line = &N64CPU.dcache[cache_line];
|
||||
if (!line->valid) {
|
||||
logfatal("Writing back invalid dcache line");
|
||||
}
|
||||
u32 original_paddr = (line->ptag << 12) | (paddr & 0xFFF);
|
||||
u32 line_start = get_dcache_line_start(original_paddr);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
n64sys.mem.rdram[line_start + i] = line->data[i];
|
||||
}
|
||||
line->dirty = false;
|
||||
}
|
||||
|
||||
INLINE dcache_line_t* prep_dcache_line(u64 vaddr, u32 paddr) {
|
||||
int cache_line_index = get_dcache_line_index(vaddr);
|
||||
dcache_line_t* line = &N64CPU.dcache[cache_line_index];
|
||||
u32 ptag = get_paddr_ptag(paddr);
|
||||
|
||||
bool valid = line->valid;
|
||||
bool ptag_matches = line->ptag == ptag;
|
||||
bool hit = valid && ptag_matches;
|
||||
bool dirty = line->dirty;
|
||||
|
||||
// If the cache line is valid but dirty it contains data that is not written back to RAM yet.
|
||||
// If it's also not a hit, we are going to need to reload it next, so write it back.
|
||||
if (valid && dirty && !hit) {
|
||||
writeback_dcache(vaddr, paddr);
|
||||
}
|
||||
|
||||
// If the cache line is not valid or it's not a hit, load it from RAM
|
||||
if (!valid || !hit) {
|
||||
u32 line_start = get_dcache_line_start(paddr);
|
||||
if (paddr < N64_RDRAM_SIZE) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
line->data[i] = n64sys.mem.rdram[line_start + i];
|
||||
}
|
||||
} else {
|
||||
logfatal("Implement me: Loading dcache from something other than RDRAM");
|
||||
}
|
||||
line->valid = true;
|
||||
line->dirty = false;
|
||||
line->ptag = ptag;
|
||||
line->index = cache_line_index;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
u8 cache_read_byte(u64 vaddr, u32 paddr) {
|
||||
return prep_dcache_line(vaddr, paddr)->data[BYTE_ADDRESS(paddr & 0xF)];
|
||||
}
|
||||
|
||||
void cache_write_byte(u64 vaddr, u32 paddr, u8 value) {
|
||||
dcache_line_t* line = prep_dcache_line(vaddr, paddr);
|
||||
line->data[BYTE_ADDRESS(paddr & 0xF)] = value;
|
||||
line->dirty = true;
|
||||
}
|
||||
|
||||
u16 cache_read_half(u64 vaddr, u32 paddr) {
|
||||
return half_from_byte_array(prep_dcache_line(vaddr, paddr)->data, HALF_ADDRESS(paddr & 0xF));
|
||||
}
|
||||
|
||||
void cache_write_half(u64 vaddr, u32 paddr, u16 value) {
|
||||
dcache_line_t* line = prep_dcache_line(vaddr, paddr);
|
||||
half_to_byte_array(line->data, HALF_ADDRESS(paddr & 0xF), value);
|
||||
line->dirty = true;
|
||||
}
|
||||
|
||||
u32 cache_read_word(u64 vaddr, u32 paddr) {
|
||||
return word_from_byte_array(prep_dcache_line(vaddr, paddr)->data, WORD_ADDRESS(paddr & 0xF));
|
||||
}
|
||||
|
||||
void cache_write_word(u64 vaddr, u32 paddr, u32 value) {
|
||||
dcache_line_t* line = prep_dcache_line(vaddr, paddr);
|
||||
word_to_byte_array(line->data, WORD_ADDRESS(paddr & 0xF), value);
|
||||
line->dirty = true;
|
||||
}
|
||||
|
||||
u64 cache_read_dword(u64 vaddr, u32 paddr) {
|
||||
return dword_from_byte_array(prep_dcache_line(vaddr, paddr)->data, DWORD_ADDRESS(paddr & 0xF));
|
||||
}
|
||||
|
||||
void cache_write_dword(u64 vaddr, u32 paddr, u64 value) {
|
||||
dcache_line_t* line = prep_dcache_line(vaddr, paddr);
|
||||
dword_to_byte_array(line->data, DWORD_ADDRESS(paddr & 0xF), value);
|
||||
line->dirty = true;
|
||||
}
|
54
src/cpu/cache.h
Normal file
54
src/cpu/cache.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef N64_CACHE_H
|
||||
#define N64_CACHE_H
|
||||
|
||||
// #include <mem/n64bus.h>
|
||||
#include <util.h>
|
||||
|
||||
typedef struct icache_line {
|
||||
bool valid;
|
||||
u32 ptag;
|
||||
// since the icache will only ever be accessed as u32, just store it as u32
|
||||
u32 data[8]; // 32 bytes, 8 words
|
||||
} icache_line_t;
|
||||
|
||||
typedef struct dcache_line {
|
||||
bool valid;
|
||||
bool dirty;
|
||||
u32 ptag;
|
||||
u8 data[16];
|
||||
int index;
|
||||
} dcache_line_t;
|
||||
|
||||
INLINE int get_icache_line_index(u64 vaddr) {
|
||||
return (vaddr >> 5) & 0x1FF;
|
||||
}
|
||||
|
||||
INLINE u32 get_icache_line_start(u32 paddr) {
|
||||
return paddr & ~0x1F;
|
||||
}
|
||||
|
||||
INLINE int get_dcache_line_index(u64 vaddr) {
|
||||
return (vaddr >> 4) & 0x1FF;
|
||||
}
|
||||
|
||||
INLINE u32 get_dcache_line_start(u32 paddr) {
|
||||
return paddr & ~0xF;
|
||||
}
|
||||
|
||||
INLINE u32 get_paddr_ptag(u32 paddr) {
|
||||
return paddr >> 12;
|
||||
}
|
||||
|
||||
void writeback_dcache(u64 vaddr, u32 paddr);
|
||||
|
||||
u8 cache_read_byte(u64 vaddr, u32 paddr);
|
||||
void cache_write_byte(u64 vaddr, u32 paddr, u8 value);
|
||||
u16 cache_read_half(u64 vaddr, u32 paddr);
|
||||
void cache_write_half(u64 vaddr, u32 paddr, u16 value);
|
||||
u32 cache_read_word(u64 vaddr, u32 paddr);
|
||||
void cache_write_word(u64 vaddr, u32 paddr, u32 value);
|
||||
u64 cache_read_dword(u64 vaddr, u32 paddr);
|
||||
void cache_write_dword(u64 vaddr, u32 paddr, u64 value);
|
||||
|
||||
|
||||
#endif // N64_CACHE_H
|
|
@ -1,5 +1,6 @@
|
|||
#include "fpu_instructions.h"
|
||||
|
||||
#include <cache.h>
|
||||
#include <util.h>
|
||||
#include <mem/n64bus.h>
|
||||
#include <math.h>
|
||||
|
@ -1017,7 +1018,7 @@ MIPS_INSTR(mips_ldc1) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
u64 value = n64_read_physical_dword(physical);
|
||||
u64 value = conditional_cache_read_dword(cached, address, physical);
|
||||
set_fpu_register_dword_fr(instruction.i.rt, value);
|
||||
}
|
||||
}
|
||||
|
@ -1034,7 +1035,7 @@ MIPS_INSTR(mips_sdc1) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_STORE), 0);
|
||||
} else {
|
||||
n64_write_physical_dword(physical, value);
|
||||
conditional_cache_write_dword(cached, address, physical, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1049,7 +1050,7 @@ MIPS_INSTR(mips_lwc1) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
u32 value = n64_read_physical_word(physical);
|
||||
u32 value = conditional_cache_read_word(cached, address, physical);
|
||||
set_fpu_register_word_fr(instruction.fi.ft, value);
|
||||
}
|
||||
}
|
||||
|
@ -1066,7 +1067,7 @@ MIPS_INSTR(mips_swc1) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_STORE), 0);
|
||||
} else {
|
||||
n64_write_physical_word(physical, value);
|
||||
conditional_cache_write_word(cached, address, physical, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "mips_instructions.h"
|
||||
#include "r4300i_register_access.h"
|
||||
|
||||
#include <cache.h>
|
||||
#include <mem/n64bus.h>
|
||||
|
||||
MIPS_INSTR(mips_nop) {}
|
||||
|
@ -104,7 +105,8 @@ MIPS_INSTR(mips_cache) {
|
|||
case DCACHE_OP(0): { // Index_Write_Back_Invalidate
|
||||
int cache_line = get_dcache_line_index(virtual_address);
|
||||
if (N64CPU.dcache[cache_line].valid) {
|
||||
logfatal("writeback");
|
||||
writeback_dcache(virtual_address, physical);
|
||||
N64CPU.dcache[cache_line].valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -133,7 +135,7 @@ MIPS_INSTR(mips_cache) {
|
|||
case DCACHE_OP(4): {
|
||||
int cache_line = get_dcache_line_index(virtual_address);
|
||||
if (N64CPU.dcache[cache_line].valid && N64CPU.dcache[cache_line].ptag == physical_tag) {
|
||||
logfatal("Hit_Invalidate dcache unimplemented");
|
||||
N64CPU.dcache[cache_line].valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -143,7 +145,8 @@ MIPS_INSTR(mips_cache) {
|
|||
case DCACHE_OP(5): { // Hit_Write_Back_Invalidate
|
||||
int cache_line = get_dcache_line_index(virtual_address);
|
||||
if (N64CPU.dcache[cache_line].valid && N64CPU.dcache[cache_line].ptag == physical_tag) {
|
||||
logfatal("Hit_Write_Back_Invalidate dcache unimplemented\n");
|
||||
writeback_dcache(virtual_address, physical);
|
||||
N64CPU.dcache[cache_line].valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -153,7 +156,7 @@ MIPS_INSTR(mips_cache) {
|
|||
case DCACHE_OP(6): { // Hit_Write_Back dcache
|
||||
int cache_line = get_dcache_line_index(virtual_address);
|
||||
if (N64CPU.dcache[cache_line].valid && N64CPU.dcache[cache_line].ptag == physical_tag) {
|
||||
logfatal("Hit_Write_Back dcache unimplemented\n");
|
||||
writeback_dcache(virtual_address, physical);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -239,7 +242,7 @@ MIPS_INSTR(mips_ld) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
u64 value = n64_read_physical_dword(physical);
|
||||
u64 value = conditional_cache_read_dword(cached, address, physical);
|
||||
set_register(instruction.i.rt, value);
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +266,7 @@ MIPS_INSTR(mips_lbu) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
u8 value = n64_read_physical_byte(physical);
|
||||
u8 value = conditional_cache_read_byte(cached, address, physical);
|
||||
set_register(instruction.i.rt, value); // zero extend
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +285,7 @@ MIPS_INSTR(mips_lhu) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
u16 value = n64_read_physical_half(physical);
|
||||
u16 value = conditional_cache_read_half(cached, address, physical);
|
||||
set_register(instruction.i.rt, value); // zero extend
|
||||
}
|
||||
}
|
||||
|
@ -300,7 +303,7 @@ MIPS_INSTR(mips_lh) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
s16 value = n64_read_physical_half(physical);
|
||||
s16 value = conditional_cache_read_half(cached, address, physical);
|
||||
set_register(instruction.i.rt, (s64)value); // zero extend
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +323,7 @@ MIPS_INSTR(mips_lw) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
s32 value = n64_read_physical_word(physical);
|
||||
s32 value = conditional_cache_read_word(cached, address, physical);
|
||||
set_register(instruction.i.rt, (s64)value);
|
||||
}
|
||||
}
|
||||
|
@ -338,7 +341,7 @@ MIPS_INSTR(mips_lwu) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
u32 value = n64_read_physical_word(physical);
|
||||
u32 value = conditional_cache_read_word(cached, address, physical);
|
||||
set_register(instruction.i.rt, value);
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +358,7 @@ MIPS_INSTR(mips_sb) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_STORE), 0);
|
||||
} else {
|
||||
n64_write_physical_byte(physical, value);
|
||||
conditional_cache_write_byte(cached, address, physical, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,7 +373,7 @@ MIPS_INSTR(mips_sh) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_STORE), 0);
|
||||
} else {
|
||||
n64_write_physical_half(physical, value);
|
||||
conditional_cache_write_half(cached, address, physical, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,7 +394,7 @@ MIPS_INSTR(mips_sw) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_STORE), 0);
|
||||
} else {
|
||||
n64_write_physical_word(physical, get_register(instruction.i.rt));
|
||||
conditional_cache_write_word(cached, address, physical, get_register(instruction.i.rt));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +415,7 @@ MIPS_INSTR(mips_sd) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_STORE), 0);
|
||||
} else {
|
||||
n64_write_physical_dword(physical, value);
|
||||
conditional_cache_write_dword(cached, address, physical, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,7 +444,7 @@ MIPS_INSTR(mips_lb) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
s8 value = n64_read_physical_byte(physical);
|
||||
s8 value = conditional_cache_read_byte(cached, address, physical);
|
||||
set_register(instruction.i.rt, (s64)value);
|
||||
}
|
||||
}
|
||||
|
@ -459,7 +462,7 @@ MIPS_INSTR(mips_lwl) {
|
|||
} else {
|
||||
u32 shift = 8 * ((address ^ 0) & 3);
|
||||
u32 mask = 0xFFFFFFFF << shift;
|
||||
u32 data = n64_read_physical_word(physical & ~3);
|
||||
u32 data = conditional_cache_read_word(cached, address & ~3, physical & ~3);
|
||||
s32 result = (get_register(instruction.i.rt) & ~mask) | data << shift;
|
||||
set_register(instruction.i.rt, (s64)result);
|
||||
}
|
||||
|
@ -477,7 +480,7 @@ MIPS_INSTR(mips_lwr) {
|
|||
u32 shift = 8 * ((address ^ 3) & 3);
|
||||
|
||||
u32 mask = 0xFFFFFFFF >> shift;
|
||||
u32 data = n64_read_physical_word(physical & ~3);
|
||||
u32 data = conditional_cache_read_word(cached, address & ~3, physical & ~3);
|
||||
s32 result = (get_register(instruction.i.rt) & ~mask) | data >> shift;
|
||||
set_register(instruction.i.rt, (s64)result);
|
||||
}
|
||||
|
@ -495,9 +498,9 @@ MIPS_INSTR(mips_swl) {
|
|||
} else {
|
||||
u32 shift = 8 * ((address ^ 0) & 3);
|
||||
u32 mask = 0xFFFFFFFF >> shift;
|
||||
u32 data = n64_read_physical_word(physical & ~3);
|
||||
u32 data = conditional_cache_read_word(cached, address & ~3, physical & ~3);
|
||||
u32 oldreg = get_register(instruction.i.rt);
|
||||
n64_write_physical_word(physical & ~3, (data & ~mask) | (oldreg >> shift));
|
||||
conditional_cache_write_word(cached, address & ~3, physical & ~3, (data & ~mask) | (oldreg >> shift));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -512,9 +515,9 @@ MIPS_INSTR(mips_swr) {
|
|||
} else {
|
||||
u32 shift = 8 * ((address ^ 3) & 3);
|
||||
u32 mask = 0xFFFFFFFF << shift;
|
||||
u32 data = n64_read_physical_word(physical & ~3);
|
||||
u32 data = conditional_cache_read_word(cached, address & ~3, physical & ~3);
|
||||
u32 oldreg = get_register(instruction.i.rt);
|
||||
n64_write_physical_word(physical & ~3, (data & ~mask) | oldreg << shift);
|
||||
conditional_cache_write_word(cached, address & ~3, physical & ~3, (data & ~mask) | oldreg << shift);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -529,7 +532,7 @@ MIPS_INSTR(mips_ldl) {
|
|||
} else {
|
||||
int shift = 8 * ((address ^ 0) & 7);
|
||||
u64 mask = (u64) 0xFFFFFFFFFFFFFFFF << shift;
|
||||
u64 data = n64_read_physical_dword(physical & ~7);
|
||||
u64 data = conditional_cache_read_dword(cached, address & ~7, physical & ~7);
|
||||
u64 oldreg = get_register(instruction.i.rt);
|
||||
|
||||
set_register(instruction.i.rt, (oldreg & ~mask) | (data << shift));
|
||||
|
@ -547,7 +550,7 @@ MIPS_INSTR(mips_ldr) {
|
|||
} else {
|
||||
int shift = 8 * ((address ^ 7) & 7);
|
||||
u64 mask = (u64) 0xFFFFFFFFFFFFFFFF >> shift;
|
||||
u64 data = n64_read_physical_dword(physical & ~7);
|
||||
u64 data = conditional_cache_read_dword(cached, address & ~7, physical & ~7);
|
||||
u64 oldreg = get_register(instruction.i.rt);
|
||||
|
||||
set_register(instruction.i.rt, (oldreg & ~mask) | (data >> shift));
|
||||
|
@ -567,9 +570,9 @@ MIPS_INSTR(mips_sdl) {
|
|||
int shift = 8 * ((address ^ 0) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF;
|
||||
mask >>= shift;
|
||||
u64 data = n64_read_physical_dword(physical & ~7);
|
||||
u64 data = conditional_cache_read_dword(cached, address & ~7, physical & ~7);
|
||||
u64 oldreg = get_register(instruction.i.rt);
|
||||
n64_write_physical_dword(physical & ~7, (data & ~mask) | (oldreg >> shift));
|
||||
conditional_cache_write_dword(cached, address & ~7, physical & ~7, (data & ~mask) | (oldreg >> shift));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -585,9 +588,9 @@ MIPS_INSTR(mips_sdr) {
|
|||
int shift = 8 * ((address ^ 7) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF;
|
||||
mask <<= shift;
|
||||
u64 data = n64_read_physical_dword(physical & ~7);
|
||||
u64 data = conditional_cache_read_dword(cached, address & ~7, physical & ~7);
|
||||
u64 oldreg = get_register(instruction.i.rt);
|
||||
n64_write_physical_dword(physical & ~7, (data & ~mask) | (oldreg << shift));
|
||||
conditional_cache_write_dword(cached, address & ~7, physical & ~7, (data & ~mask) | (oldreg << shift));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,7 +605,7 @@ MIPS_INSTR(mips_ll) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
s32 result = n64_read_physical_word(physical);
|
||||
s32 result = conditional_cache_read_word(cached, address, physical);
|
||||
if ((address & 0b11) > 0) {
|
||||
logfatal("TODO: throw an 'address error' exception! Tried to load from unaligned address 0x%016" PRIX64, address);
|
||||
}
|
||||
|
@ -632,7 +635,7 @@ MIPS_INSTR(mips_lld) {
|
|||
on_tlb_exception(address);
|
||||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_LOAD), 0);
|
||||
} else {
|
||||
u64 result = n64_read_physical_dword(physical);
|
||||
u64 result = conditional_cache_read_dword(cached, address, physical);
|
||||
if ((address & 0b111) > 0) {
|
||||
logfatal("TODO: throw an 'address error' exception! Tried to load from unaligned address 0x%016" PRIX64, address);
|
||||
}
|
||||
|
@ -663,7 +666,7 @@ MIPS_INSTR(mips_sc) {
|
|||
r4300i_handle_exception(N64CPU.prev_pc, get_tlb_exception_code(N64CP0.tlb_error, BUS_STORE), 0);
|
||||
} else {
|
||||
u32 value = get_register(instruction.i.rt);
|
||||
n64_write_physical_word(physical_address, value);
|
||||
conditional_cache_write_word(cached, address, physical_address, value);
|
||||
set_register(instruction.i.rt, 1); // Success!
|
||||
}
|
||||
} else {
|
||||
|
@ -693,7 +696,7 @@ MIPS_INSTR(mips_scd) {
|
|||
u32 physical_address = resolve_virtual_address_or_die(address, BUS_STORE, &cached);
|
||||
|
||||
u64 value = get_register(instruction.i.rt);
|
||||
n64_write_physical_dword(physical_address, value);
|
||||
conditional_cache_write_dword(cached, address, physical_address, value);
|
||||
set_register(instruction.i.rt, 1); // Success!
|
||||
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef N64_R4300I_H
|
||||
#define N64_R4300I_H
|
||||
#include <cpu/cache.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
@ -621,44 +622,6 @@ typedef union fgr {
|
|||
|
||||
ASSERTDWORD(fgr_t);
|
||||
|
||||
typedef struct icache_line {
|
||||
struct {
|
||||
u32 valid:1;
|
||||
u32 ptag:20;
|
||||
};
|
||||
// since the icache will only ever be accessed as u32, just store it as u32
|
||||
u32 data[8]; // 32 bytes, 8 words
|
||||
} icache_line_t;
|
||||
|
||||
typedef struct dcache_line {
|
||||
struct {
|
||||
u32 valid:1;
|
||||
u32 dirty:1;
|
||||
u32 ptag:20;
|
||||
};
|
||||
u8 data[16];
|
||||
} dcache_line_t;
|
||||
|
||||
INLINE int get_icache_line_index(u64 vaddr) {
|
||||
return (vaddr >> 5) & 0x1FF;
|
||||
}
|
||||
|
||||
INLINE u32 get_icache_line_start(u32 paddr) {
|
||||
return paddr & ~0x1F;
|
||||
}
|
||||
|
||||
INLINE int get_dcache_line_index(u64 vaddr) {
|
||||
return (vaddr >> 4) & 0x1FF;
|
||||
}
|
||||
|
||||
INLINE u32 get_dcache_line_start(u32 paddr) {
|
||||
return paddr & ~0xF;
|
||||
}
|
||||
|
||||
INLINE u32 get_paddr_ptag(u32 paddr) {
|
||||
return paddr >> 13;
|
||||
}
|
||||
|
||||
typedef struct r4300i {
|
||||
u64 gpr[32];
|
||||
fgr_t f[32];
|
||||
|
|
|
@ -161,10 +161,10 @@ INLINE resolve_virtual_address_handler get_resolve_virtual_address_handler() {
|
|||
|
||||
#define resolve_virtual_address(vaddr, bus_access, cached, physical) N64CP0.resolve_virtual_address(vaddr, bus_access, cached, physical)
|
||||
|
||||
INLINE u32 resolve_virtual_address_or_die(u64 virtual, bus_access_t bus_access, bool* cached) {
|
||||
INLINE u32 resolve_virtual_address_or_die(u64 vaddr, bus_access_t bus_access, bool* cached) {
|
||||
u32 physical;
|
||||
if (!resolve_virtual_address(virtual, bus_access, cached, &physical)) {
|
||||
logfatal("Unhandled TLB exception at 0x%016" PRIX64 "! Stop calling resolve_virtual_address_or_die() here!", virtual);
|
||||
if (!resolve_virtual_address(vaddr, bus_access, cached, &physical)) {
|
||||
logfatal("Unhandled TLB exception at 0x%016" PRIX64 "! Stop calling resolve_virtual_address_or_die() here!", vaddr);
|
||||
}
|
||||
return physical;
|
||||
}
|
||||
|
@ -183,7 +183,73 @@ u8 n64_read_physical_byte(u32 address);
|
|||
|
||||
INLINE u8 n64_read_byte(u64 address) {
|
||||
bool cached;
|
||||
return n64_read_physical_byte(resolve_virtual_address_or_die(address, false, &cached));
|
||||
return n64_read_physical_byte(resolve_virtual_address_or_die(address, BUS_LOAD, &cached));
|
||||
}
|
||||
|
||||
INLINE u8 conditional_cache_read_byte(bool cached, u64 vaddr, u32 paddr) {
|
||||
if (cached) {
|
||||
return cache_read_byte(vaddr, paddr);
|
||||
} else {
|
||||
return n64_read_physical_byte(paddr);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void conditional_cache_write_byte(bool cached, u64 vaddr, u32 paddr, u8 value) {
|
||||
if (cached) {
|
||||
cache_write_byte(vaddr, paddr, value);
|
||||
} else {
|
||||
n64_write_physical_byte(paddr, value);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE u16 conditional_cache_read_half(bool cached, u64 vaddr, u32 paddr) {
|
||||
if (cached) {
|
||||
return cache_read_half(vaddr, paddr);
|
||||
} else {
|
||||
return n64_read_physical_half(paddr);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void conditional_cache_write_half(bool cached, u64 vaddr, u32 paddr, u16 value) {
|
||||
if (cached) {
|
||||
cache_write_half(vaddr, paddr, value);
|
||||
} else {
|
||||
n64_write_physical_half(paddr, value);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE u32 conditional_cache_read_word(bool cached, u64 vaddr, u32 paddr) {
|
||||
if (cached) {
|
||||
return cache_read_word(vaddr, paddr);
|
||||
} else {
|
||||
return n64_read_physical_word(paddr);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void conditional_cache_write_word(bool cached, u64 vaddr, u32 paddr, u32 value) {
|
||||
if (cached) {
|
||||
cache_write_word(vaddr, paddr, value);
|
||||
} else {
|
||||
n64_write_physical_word(paddr, value);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE u64 conditional_cache_read_dword(bool cached, u64 vaddr, u32 paddr) {
|
||||
if (cached) {
|
||||
return cache_read_dword(vaddr, paddr);
|
||||
} else {
|
||||
return n64_read_physical_dword(paddr);
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void conditional_cache_write_dword(bool cached, u64 vaddr, u32 paddr, u64 value) {
|
||||
if (cached) {
|
||||
cache_write_dword(vaddr, paddr, value);
|
||||
} else {
|
||||
n64_write_physical_dword(paddr, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //N64_N64BUS_H
|
||||
|
|
|
@ -165,8 +165,8 @@ typedef struct softrdp_state {
|
|||
void softrdp_init(softrdp_state_t* state, uint8_t* rdramptr);
|
||||
#define full_sync_softrdp() do {} while(0)
|
||||
void softrdp_enqueue_command(softrdp_state_t* rdp, int command_length, uint64_t* buffer);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
Loading…
Reference in a new issue