mirror of https://github.com/inolen/redream.git
initial mmu support for sq remaps
This commit is contained in:
parent
e06f450f02
commit
3fade7f1fb
|
@ -210,6 +210,7 @@ set(RELIB_SOURCES
|
|||
src/guest/sh4/sh4_dbg.c
|
||||
src/guest/sh4/sh4_dmac.c
|
||||
src/guest/sh4/sh4_intc.c
|
||||
src/guest/sh4/sh4_mmu.c
|
||||
src/guest/sh4/sh4_tmu.c
|
||||
src/guest/debugger.c
|
||||
src/guest/dreamcast.c
|
||||
|
|
|
@ -165,6 +165,7 @@ static int sh4_init(struct device *dev) {
|
|||
sh4->guest->mem = as_translate(sh4->memory_if->space, 0x0);
|
||||
sh4->guest->space = sh4->memory_if->space;
|
||||
sh4->guest->invalid_instr = &sh4_invalid_instr;
|
||||
sh4->guest->load_tlb = &sh4_mmu_load_tlb;
|
||||
sh4->guest->sq_prefetch = &sh4_ccn_sq_prefetch;
|
||||
sh4->guest->sleep = &sh4_sleep;
|
||||
sh4->guest->sr_updated = &sh4_sr_updated;
|
||||
|
@ -212,6 +213,10 @@ void sh4_reset(struct sh4 *sh4, uint32_t pc) {
|
|||
#include "guest/sh4/sh4_regs.inc"
|
||||
#undef SH4_REG
|
||||
|
||||
/* reset tlb */
|
||||
memset(sh4->utlb_sq_map, 0, sizeof(sh4->utlb_sq_map));
|
||||
memset(sh4->utlb, 0, sizeof(sh4->utlb));
|
||||
|
||||
/* reset interrupts */
|
||||
sh4_intc_reprioritize(sh4);
|
||||
|
||||
|
@ -351,16 +356,37 @@ AM_BEGIN(struct sh4, sh4_data_map)
|
|||
AM_RANGE(0x80000000, 0x9fffffff) AM_MIRROR(0x00000000) /* p1 */
|
||||
AM_RANGE(0xa0000000, 0xbfffffff) AM_MIRROR(0x00000000) /* p2 */
|
||||
AM_RANGE(0xc0000000, 0xdfffffff) AM_MIRROR(0x00000000) /* p3 */
|
||||
AM_RANGE(0xe0000000, 0xffffffff) AM_MIRROR(0x00000000) /* p4 */
|
||||
|
||||
/* internal cache and sq only accessible through p4 */
|
||||
/* internal cache is only accessible through p0, not any of the mirrors */
|
||||
AM_RANGE(0x7c000000, 0x7fffffff) AM_HANDLE("sh4 cache",
|
||||
(mmio_read_cb)&sh4_ccn_cache_read,
|
||||
(mmio_write_cb)&sh4_ccn_cache_write,
|
||||
NULL, NULL)
|
||||
|
||||
/* p4 area */
|
||||
AM_RANGE(0xe0000000, 0xe3ffffff) AM_HANDLE("sh4 sq",
|
||||
(mmio_read_cb)&sh4_ccn_sq_read,
|
||||
(mmio_write_cb)&sh4_ccn_sq_write,
|
||||
NULL, NULL)
|
||||
AM_RANGE(0xf0000000, 0xf1ffffff) AM_HANDLE("sh4 icache",
|
||||
(mmio_read_cb)&sh4_ccn_icache_read,
|
||||
(mmio_write_cb)&sh4_ccn_icache_write,
|
||||
NULL, NULL)
|
||||
AM_RANGE(0xf2000000, 0xf3ffffff) AM_HANDLE("sh4 itlb",
|
||||
(mmio_read_cb)&sh4_mmu_itlb_read,
|
||||
(mmio_write_cb)&sh4_mmu_itlb_write,
|
||||
NULL, NULL)
|
||||
AM_RANGE(0xf4000000, 0xf5ffffff) AM_HANDLE("sh4 ocache",
|
||||
(mmio_read_cb)&sh4_ccn_ocache_read,
|
||||
(mmio_write_cb)&sh4_ccn_ocache_write,
|
||||
NULL, NULL)
|
||||
AM_RANGE(0xf6000000, 0xf7ffffff) AM_HANDLE("sh4 utlb",
|
||||
(mmio_read_cb)&sh4_mmu_utlb_read,
|
||||
(mmio_write_cb)&sh4_mmu_utlb_write,
|
||||
NULL, NULL)
|
||||
AM_RANGE(0xfc000000, 0xffffffff) AM_HANDLE("sh4 reg",
|
||||
(mmio_read_cb)&sh4_reg_read,
|
||||
(mmio_write_cb)&sh4_reg_write,
|
||||
NULL, NULL)
|
||||
AM_END();
|
||||
/* clang-format on */
|
||||
|
|
|
@ -36,6 +36,11 @@ struct sh4_dtr {
|
|||
int size;
|
||||
};
|
||||
|
||||
struct sh4_tlb_entry {
|
||||
union pteh hi;
|
||||
union ptel lo;
|
||||
};
|
||||
|
||||
struct sh4 {
|
||||
struct device;
|
||||
|
||||
|
@ -61,6 +66,10 @@ struct sh4 {
|
|||
uint64_t requested_interrupts;
|
||||
/* pending interrupts moved to context for fast jit access */
|
||||
|
||||
/* mmu */
|
||||
uint32_t utlb_sq_map[64];
|
||||
struct sh4_tlb_entry utlb[64];
|
||||
|
||||
/* tmu */
|
||||
struct timer *tmu_timers[3];
|
||||
};
|
||||
|
@ -71,6 +80,7 @@ DECLARE_COUNTER(sh4_instrs);
|
|||
|
||||
AM_DECLARE(sh4_data_map);
|
||||
|
||||
/* ccn */
|
||||
void sh4_ccn_sq_prefetch(void *data, uint32_t addr);
|
||||
uint32_t sh4_ccn_cache_read(struct sh4 *sh4, uint32_t addr, uint32_t data_mask);
|
||||
void sh4_ccn_cache_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
|
@ -78,7 +88,16 @@ void sh4_ccn_cache_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
|||
uint32_t sh4_ccn_sq_read(struct sh4 *sh4, uint32_t addr, uint32_t data_mask);
|
||||
void sh4_ccn_sq_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
uint32_t data_mask);
|
||||
uint32_t sh4_ccn_icache_read(struct sh4 *sh4, uint32_t addr,
|
||||
uint32_t data_mask);
|
||||
void sh4_ccn_icache_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
uint32_t data_mask);
|
||||
uint32_t sh4_ccn_ocache_read(struct sh4 *sh4, uint32_t addr,
|
||||
uint32_t data_mask);
|
||||
void sh4_ccn_ocache_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
uint32_t data_mask);
|
||||
|
||||
/* dbg */
|
||||
int sh4_dbg_num_registers(struct device *dev);
|
||||
void sh4_dbg_step(struct device *dev);
|
||||
void sh4_dbg_add_breakpoint(struct device *dev, int type, uint32_t addr);
|
||||
|
@ -91,10 +110,20 @@ int sh4_dbg_invalid_instr(struct sh4 *sh4);
|
|||
|
||||
void sh4_dmac_ddt(struct sh4 *sh, struct sh4_dtr *dtr);
|
||||
|
||||
/* intc */
|
||||
void sh4_intc_update_pending(struct sh4 *sh4);
|
||||
void sh4_intc_check_pending(void *data);
|
||||
void sh4_intc_reprioritize(struct sh4 *sh4);
|
||||
|
||||
/* mmu */
|
||||
void sh4_mmu_load_tlb(void *data);
|
||||
uint32_t sh4_mmu_itlb_read(struct sh4 *sh4, uint32_t addr, uint32_t data_mask);
|
||||
uint32_t sh4_mmu_utlb_read(struct sh4 *sh4, uint32_t addr, uint32_t data_mask);
|
||||
void sh4_mmu_itlb_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
uint32_t data_mask);
|
||||
void sh4_mmu_utlb_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
uint32_t data_mask);
|
||||
|
||||
struct sh4 *sh4_create(struct dreamcast *dc);
|
||||
void sh4_destroy(struct sh4 *sh4);
|
||||
void sh4_debug_menu(struct sh4 *sh4);
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#include "guest/sh4/sh4.h"
|
||||
#include "jit/jit.h"
|
||||
|
||||
#if 0
|
||||
#define LOG_CCN LOG_INFO
|
||||
#else
|
||||
#define LOG_CCN(...)
|
||||
#endif
|
||||
|
||||
/* with OIX, bit 25, rather than bit 13, determines which 4kb bank to use */
|
||||
#define CACHE_OFFSET(addr, OIX) \
|
||||
((OIX ? ((addr & 0x2000000) >> 13) : ((addr & 0x2000) >> 1)) | (addr & 0xfff))
|
||||
|
@ -29,12 +35,27 @@ void sh4_ccn_sq_prefetch(void *data, uint32_t addr) {
|
|||
DCHECK(addr >= 0xe0000000 && addr <= 0xe3ffffff);
|
||||
|
||||
struct sh4 *sh4 = data;
|
||||
uint32_t dst = addr & 0x03ffffe0;
|
||||
|
||||
uint32_t dst = 0x0;
|
||||
uint32_t sqi = (addr & 0x20) >> 5;
|
||||
if (sqi) {
|
||||
dst |= (*sh4->QACR1 & 0x1c) << 24;
|
||||
|
||||
if (sh4->MMUCR->AT) {
|
||||
/* get upper 12 bits from UTLB */
|
||||
uint32_t vpn = addr >> 20;
|
||||
dst = sh4->utlb_sq_map[vpn & 0x3f];
|
||||
|
||||
/* get lower 20 bits from original address */
|
||||
dst |= addr & 0xfffe0;
|
||||
} else {
|
||||
dst |= (*sh4->QACR0 & 0x1c) << 24;
|
||||
/* get upper 6 bits from QACR* registers */
|
||||
if (sqi) {
|
||||
dst = (*sh4->QACR1 & 0x1c) << 24;
|
||||
} else {
|
||||
dst = (*sh4->QACR0 & 0x1c) << 24;
|
||||
}
|
||||
|
||||
/* get lower 26 bits from original address */
|
||||
dst |= addr & 0x3ffffe0;
|
||||
}
|
||||
|
||||
as_memcpy_to_guest(sh4->memory_if->space, dst, sh4->ctx.sq[sqi], 32);
|
||||
|
@ -69,10 +90,43 @@ void sh4_ccn_sq_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
|||
sh4->ctx.sq[sqi][idx] = data;
|
||||
}
|
||||
|
||||
uint32_t sh4_ccn_icache_read(struct sh4 *sh4, uint32_t addr,
|
||||
uint32_t data_mask) {
|
||||
LOG_CCN("sh4_ccn_icache_read 0x%08x", addr);
|
||||
|
||||
/* return an invalid entry */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sh4_ccn_icache_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
uint32_t data_mask) {
|
||||
LOG_CCN("sh4_ccn_icache_write 0x%08x", addr);
|
||||
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
uint32_t sh4_ccn_ocache_read(struct sh4 *sh4, uint32_t addr,
|
||||
uint32_t data_mask) {
|
||||
LOG_CCN("sh4_ccn_ocache_read 0x%08x", addr);
|
||||
|
||||
/* return an invalid entry */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sh4_ccn_ocache_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
uint32_t data_mask) {
|
||||
LOG_CCN("sh4_ccn_ocache_write 0x%08x", addr);
|
||||
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
REG_W32(sh4_cb, MMUCR) {
|
||||
struct sh4 *sh4 = dc->sh4;
|
||||
if (value) {
|
||||
LOG_FATAL("MMU not currently supported");
|
||||
|
||||
sh4->MMUCR->full = value;
|
||||
|
||||
if (sh4->MMUCR->AT) {
|
||||
LOG_WARNING("MMU not fully supported");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
#include "guest/sh4/sh4.h"
|
||||
|
||||
#if 0
|
||||
#define LOG_MMU LOG_INFO
|
||||
#else
|
||||
#define LOG_MMU(...)
|
||||
#endif
|
||||
|
||||
#define TLB_INDEX(addr) (((addr) >> 8) & 0x3f)
|
||||
|
||||
#define PAGE_SIZE(entry) (((entry)->lo.SZ1 << 1) | (entry)->lo.SZ0)
|
||||
|
||||
enum {
|
||||
PAGE_SIZE_1KB,
|
||||
PAGE_SIZE_4KB,
|
||||
PAGE_SIZE_64KB,
|
||||
PAGE_SIZE_1MB,
|
||||
};
|
||||
|
||||
static void sh4_mmu_utlb_sync(struct sh4 *sh4, struct sh4_tlb_entry *entry) {
|
||||
int n = entry - sh4->utlb;
|
||||
|
||||
/* check if entry maps to sq region [0xe0000000, 0xe3ffffff] */
|
||||
if ((entry->hi.VPN & (0xfc000000 >> 10)) == (0xe0000000 >> 10)) {
|
||||
/* assume page size is 1MB
|
||||
FIXME support all page sizes */
|
||||
uint32_t vpn = entry->hi.VPN >> 10;
|
||||
uint32_t ppn = entry->lo.PPN << 10;
|
||||
|
||||
sh4->utlb_sq_map[vpn & 0x3f] = ppn;
|
||||
|
||||
LOG_INFO("sh4_mmu_utlb_sync sq map (%d) 0x%x -> 0x%x", n, vpn, ppn);
|
||||
} else {
|
||||
LOG_FATAL("sh4_mmu_utlb_sync memory mapping not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static void sh4_mmu_translate(struct sh4 *sh4, uint32_t addr) {}
|
||||
|
||||
void sh4_mmu_load_tlb(void *data) {
|
||||
struct sh4 *sh4 = data;
|
||||
|
||||
uint32_t n = sh4->MMUCR->URC;
|
||||
struct sh4_tlb_entry *entry = &sh4->utlb[n];
|
||||
entry->lo = *sh4->PTEL;
|
||||
entry->hi = *sh4->PTEH;
|
||||
|
||||
sh4_mmu_utlb_sync(sh4, entry);
|
||||
}
|
||||
|
||||
uint32_t sh4_mmu_itlb_read(struct sh4 *sh4, uint32_t addr, uint32_t data_mask) {
|
||||
if (addr < 0x01000000) {
|
||||
LOG_MMU("sh4_mmu_itlb_read address array %08x", addr);
|
||||
} else {
|
||||
LOG_MMU("sh4_mmu_itlb_read data array %08x", addr);
|
||||
}
|
||||
|
||||
/* return an invalid entry */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t sh4_mmu_utlb_read(struct sh4 *sh4, uint32_t addr, uint32_t data_mask) {
|
||||
if (addr < 0x01000000) {
|
||||
LOG_MMU("sh4_mmu_utlb_read address array %08x", addr);
|
||||
|
||||
struct sh4_tlb_entry *entry = &sh4->utlb[TLB_INDEX(addr)];
|
||||
uint32_t data = entry->hi.full;
|
||||
data |= entry->lo.D << 9;
|
||||
data |= entry->lo.V << 8;
|
||||
return data;
|
||||
} else {
|
||||
if (addr & 0x800000) {
|
||||
LOG_FATAL("sh4_mmu_utlb_read data array 2 %08x", addr);
|
||||
} else {
|
||||
LOG_MMU("sh4_mmu_utlb_read data array 1 %08x", addr);
|
||||
|
||||
struct sh4_tlb_entry *entry = &sh4->utlb[TLB_INDEX(addr)];
|
||||
uint32_t data = entry->lo.full;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sh4_mmu_itlb_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
uint32_t data_mask) {
|
||||
if (addr < 0x01000000) {
|
||||
LOG_MMU("sh4_mmu_itlb_write address array %08x %08x", addr, data);
|
||||
} else {
|
||||
LOG_MMU("sh4_mmu_itlb_write data array %08x %08x", addr, data);
|
||||
}
|
||||
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
void sh4_mmu_utlb_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
|
||||
uint32_t data_mask) {
|
||||
if (addr < 0x01000000) {
|
||||
if (addr & 0x80) {
|
||||
LOG_FATAL("sh4_mmu_utlb_write address array (associative) %08x %08x",
|
||||
addr, data);
|
||||
} else {
|
||||
LOG_MMU("sh4_mmu_utlb_write address array %08x %08x", addr, data);
|
||||
|
||||
struct sh4_tlb_entry *entry = &sh4->utlb[TLB_INDEX(addr)];
|
||||
entry->hi.full = data & 0xfffffcff;
|
||||
entry->lo.D = (data >> 9) & 1;
|
||||
entry->lo.V = (data >> 8) & 1;
|
||||
|
||||
sh4_mmu_utlb_sync(sh4, entry);
|
||||
}
|
||||
} else {
|
||||
if (addr & 0x800000) {
|
||||
LOG_FATAL("sh4_mmu_utlb_write data array 2 %08x %08x", addr, data);
|
||||
} else {
|
||||
LOG_MMU("sh4_mmu_utlb_write data array 1 %08x %08x", addr, data);
|
||||
|
||||
struct sh4_tlb_entry *entry = &sh4->utlb[TLB_INDEX(addr)];
|
||||
entry->lo.full = data;
|
||||
|
||||
sh4_mmu_utlb_sync(sh4, entry);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
/* ADDR NAME DEFAULT TYPE */
|
||||
SH4_REG(0xff000000, PTEH, 0x00000000, uint32_t)
|
||||
SH4_REG(0xff000004, PTEL, 0x00000000, uint32_t)
|
||||
SH4_REG(0xff000000, PTEH, 0x00000000, union pteh)
|
||||
SH4_REG(0xff000004, PTEL, 0x00000000, union ptel)
|
||||
SH4_REG(0xff000008, TTB, 0x00000000, uint32_t)
|
||||
SH4_REG(0xff00000c, TEA, 0x00000000, uint32_t)
|
||||
SH4_REG(0xff000010, MMUCR, 0x00000000, uint32_t)
|
||||
SH4_REG(0xff000010, MMUCR, 0x00000000, union mmucr)
|
||||
SH4_REG(0xff000014, BASRA, 0x00000000, uint32_t)
|
||||
SH4_REG(0xff000018, BASRB, 0x00000000, uint32_t)
|
||||
SH4_REG(0xff00001c, CCR, 0x00000000, union ccr)
|
||||
|
|
|
@ -3,6 +3,47 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
union pteh {
|
||||
uint32_t full;
|
||||
struct {
|
||||
uint32_t ASID : 8;
|
||||
uint32_t : 2;
|
||||
uint32_t VPN : 22;
|
||||
};
|
||||
};
|
||||
|
||||
union ptel {
|
||||
uint32_t full;
|
||||
struct {
|
||||
uint32_t WT : 1;
|
||||
uint32_t SH : 1;
|
||||
uint32_t D : 1;
|
||||
uint32_t C : 1;
|
||||
uint32_t SZ0 : 1;
|
||||
uint32_t PR : 2;
|
||||
uint32_t SZ1 : 1;
|
||||
uint32_t V : 1;
|
||||
uint32_t : 1;
|
||||
uint32_t PPN : 19;
|
||||
uint32_t : 3;
|
||||
};
|
||||
};
|
||||
|
||||
union mmucr {
|
||||
uint32_t full;
|
||||
struct {
|
||||
uint32_t AT : 1;
|
||||
uint32_t : 1;
|
||||
uint32_t TI : 1;
|
||||
uint32_t : 5;
|
||||
uint32_t SV : 1;
|
||||
uint32_t SQMD : 1;
|
||||
uint32_t URC : 6;
|
||||
uint32_t URB : 6;
|
||||
uint32_t LRUI : 6;
|
||||
};
|
||||
};
|
||||
|
||||
union ccr {
|
||||
uint32_t full;
|
||||
struct {
|
||||
|
@ -10,16 +51,16 @@ union ccr {
|
|||
uint32_t WT : 1;
|
||||
uint32_t CB : 1;
|
||||
uint32_t OCI : 1;
|
||||
uint32_t reserved : 1;
|
||||
uint32_t : 1;
|
||||
uint32_t ORA : 1;
|
||||
uint32_t reserved1 : 1;
|
||||
uint32_t : 1;
|
||||
uint32_t OIX : 1;
|
||||
uint32_t ICE : 1;
|
||||
uint32_t reserved2 : 2;
|
||||
uint32_t : 2;
|
||||
uint32_t ICI : 1;
|
||||
uint32_t reserved3 : 3;
|
||||
uint32_t : 3;
|
||||
uint32_t IIX : 1;
|
||||
uint32_t reserved4 : 15;
|
||||
uint32_t : 15;
|
||||
uint32_t EMODE : 1;
|
||||
};
|
||||
};
|
||||
|
@ -40,7 +81,7 @@ union chcr {
|
|||
uint32_t AM : 1;
|
||||
uint32_t RL : 1;
|
||||
uint32_t DS : 1;
|
||||
uint32_t reserved : 4;
|
||||
uint32_t : 4;
|
||||
uint32_t DTC : 1;
|
||||
uint32_t DSA : 3;
|
||||
uint32_t STC : 1;
|
||||
|
@ -54,13 +95,13 @@ union dmaor {
|
|||
uint32_t DME : 1;
|
||||
uint32_t NMIF : 1;
|
||||
uint32_t AE : 1;
|
||||
uint32_t reserved : 5;
|
||||
uint32_t : 5;
|
||||
uint32_t PR0 : 1;
|
||||
uint32_t PR1 : 1;
|
||||
uint32_t reserved1 : 4;
|
||||
uint32_t : 4;
|
||||
uint32_t DBL : 1;
|
||||
uint32_t DDT : 1;
|
||||
uint32_t reserved2 : 16;
|
||||
uint32_t : 16;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -143,7 +143,8 @@ void input_poll(struct host *base) {
|
|||
|
||||
/* retroarch's API provides a binary [0, 1] value for the triggers. map from
|
||||
this to [0, INT16_MAX] as our host layer expects */
|
||||
if (desc->id == RETRO_DEVICE_ID_JOYPAD_L2 || desc->id == RETRO_DEVICE_ID_JOYPAD_R2) {
|
||||
if (desc->id == RETRO_DEVICE_ID_JOYPAD_L2 ||
|
||||
desc->id == RETRO_DEVICE_ID_JOYPAD_R2) {
|
||||
value = value ? INT16_MAX : 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -387,6 +387,8 @@ typedef int32_t int128_t[4];
|
|||
|
||||
#define SLEEP() guest->sleep(guest->data)
|
||||
|
||||
#define LDTLB() guest->load_tlb(guest->data)
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#define INSTR(name) \
|
||||
|
|
|
@ -8,6 +8,7 @@ struct sh4_guest {
|
|||
|
||||
/* runtime interface */
|
||||
void (*invalid_instr)(void *);
|
||||
void (*load_tlb)(void *);
|
||||
void (*sq_prefetch)(void *, uint32_t);
|
||||
void (*sleep)(void *);
|
||||
void (*sr_updated)(void *, uint32_t);
|
||||
|
|
|
@ -1379,6 +1379,11 @@ INSTR(SLEEP) {
|
|||
SLEEP();
|
||||
}
|
||||
|
||||
/* LDTLB */
|
||||
INSTR(LDTLB) {
|
||||
LDTLB();
|
||||
}
|
||||
|
||||
/* STC SR,Rn */
|
||||
INSTR(STCSR) {
|
||||
I32 v = LOAD_SR_I32();
|
||||
|
|
|
@ -135,6 +135,7 @@ SH4_INSTR(RTS, "rts", 0000000000001011, 2, SH4_FL
|
|||
|
||||
|
||||
// system control instructions
|
||||
SH4_INSTR(LDTLB, "ldtlb", 0000000000111000, 1, 0)
|
||||
SH4_INSTR(CLRMAC, "clrmac", 0000000000101000, 1, 0)
|
||||
SH4_INSTR(CLRS, "clrs", 0000000001001000, 1, 0)
|
||||
SH4_INSTR(CLRT, "clrt", 0000000000001000, 1, 0)
|
||||
|
|
|
@ -441,6 +441,12 @@ static void store_fpscr(struct sh4_guest *guest, struct ir *ir,
|
|||
struct ir_value *data = ir_alloc_i64(ir, (uint64_t)guest->data); \
|
||||
ir_call_1(ir, sleep, data); \
|
||||
}
|
||||
|
||||
#define LDTLB() { \
|
||||
struct ir_value *load_tlb = ir_alloc_i64(ir, (uint64_t)guest->load_tlb); \
|
||||
struct ir_value *data = ir_alloc_i64(ir, (uint64_t)guest->data); \
|
||||
ir_call_1(ir, load_tlb, data); \
|
||||
}
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
|
|
Loading…
Reference in New Issue