update core

This commit is contained in:
Logan McNaughton
2022-07-17 19:11:05 -06:00
parent c99c9fa0fd
commit 5e2028fb8b
52 changed files with 770 additions and 601 deletions
+98 -64
View File
@@ -20,31 +20,47 @@ jobs:
matrix:
include:
- cc: GCC
platform: x64
bits: 64
- cc: GCC
platform: x86
bits: 32
- cc: Clang
name: Linux / ${{ matrix.cc }} / x64 | x86
runs-on: ubuntu-20.04
platform: x64
bits: 64
- cc: Clang
platform: x86
bits: 32
name: Linux / ${{ matrix.cc }} / ${{ matrix.platform }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Get build dependencies and arrange the environment
run: |
sudo dpkg --add-architecture i386
if [[ "${{ matrix.platform }}" == "x86" ]]; then sudo dpkg --add-architecture i386; fi
sudo apt-get update
sudo apt-get -y install libfreetype6-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libsdl1.2-dev libsdl2-dev nasm zlib1g-dev
sudo apt-get --reinstall -y install gcc-multilib g++-multilib libc6 libc6-dev-i386 libfreetype6:i386 libgl1-mesa-glx:i386 libglu1-mesa:i386 libpng16-16:i386 libsdl1.2debian:i386 libsdl2-2.0-0:i386 zlib1g:i386
LINK="sudo ln -s -T"
cd /usr/lib/i386-linux-gnu
if ! [[ -f libfreetype.so ]]; then ${LINK} libfreetype.so.6.17.1 libfreetype.so; fi
if ! [[ -f libGL.so ]]; then ${LINK} libGL.so.1.7.0 libGL.so; fi
if ! [[ -f libGLU.so ]]; then ${LINK} libGLU.so.1.3.1 libGLU.so; fi
if ! [[ -f libpng16.so ]]; then ${LINK} libpng16.so.16.37.0 libpng16.so; fi
if ! [[ -f libSDL.so ]]; then ${LINK} libSDL-1.2.so.0.11.4 libSDL.so; fi
if ! [[ -f libSDL2.so ]]; then ${LINK} libSDL2-2.0.so.0.10.0 libSDL2.so; fi
if ! [[ -f libz.so ]]; then ${LINK} libz.so.1.2.11 libz.so; fi
cd /usr/include/SDL2
if ! [[ -f _real_SDL_config.h ]]; then ${LINK} ../x86_64-linux-gnu/SDL2/_real_SDL_config.h _real_SDL_config.h; fi
if [[ "${{ matrix.platform }}" == "x86" ]]; then
sudo apt-get --reinstall -y install gcc-multilib g++-multilib libc6 libc6-dev-i386 libfreetype6:i386 libgl1-mesa-glx:i386 libglu1-mesa:i386 libpng16-16:i386 libsdl1.2debian:i386 libsdl2-2.0-0:i386 zlib1g:i386
LINK="sudo ln -s -T"
cd /usr/lib/i386-linux-gnu
if ! [[ -f libfreetype.so ]]; then ${LINK} libfreetype.so.6.18.1 libfreetype.so; fi
if ! [[ -f libGL.so ]]; then ${LINK} libGL.so.1.7.0 libGL.so; fi
if ! [[ -f libGLU.so ]]; then ${LINK} libGLU.so.1.3.1 libGLU.so; fi
if ! [[ -f libpng16.so ]]; then ${LINK} libpng16.so.16.37.0 libpng16.so; fi
if ! [[ -f libSDL.so ]]; then ${LINK} libSDL-1.2.so.0.11.4 libSDL.so; fi
if ! [[ -f libSDL2.so ]]; then ${LINK} libSDL2-2.0.so.0.18.2 libSDL2.so; fi
if ! [[ -f libz.so ]]; then ${LINK} libz.so.1.2.11 libz.so; fi
cd /usr/include/SDL2
if ! [[ -f _real_SDL_config.h ]]; then ${LINK} ../x86_64-linux-gnu/SDL2/_real_SDL_config.h _real_SDL_config.h; fi
fi
sudo ldconfig
- name: Build and related stuff
run: |
if [[ ${{ matrix.bits }} -eq 32 ]]; then export OPTFLAGS="-O2 -flto -mtune=pentium4"; else export OPTFLAGS="-O2 -flto -mtune=core2"; fi
G_REV=$(git rev-parse --short HEAD)
echo "G_REV=${G_REV}" >> "${GITHUB_ENV}"
ORIG="$(pwd)"
if [[ "${{ matrix.cc }}" == "GCC" ]]; then
CC="gcc"
CXX="g++"
@@ -52,40 +68,45 @@ jobs:
CC="clang"
CXX="clang++"
fi
if [[ ${{ matrix.bits }} -eq 32 ]]; then export PIC="1"; fi
${CC} --version
for TSK in 1 2 3 4 5 6 7 8
SDL="sdl"
MSG="1.2"
mkdir tmp
for DYN in 0 1 0 1
do
unset PIC
if [[ ${TSK} -le 4 ]]; then
SDL="sdl"
MSG="SDL1.2"
if [[ ${DYN} -eq 0 ]]; then
export POSTFIX="-old"
else
SDL="sdl2"
MSG="SDL2"
fi
if [[ "${DYN}" == "0" ]]; then
DYN="1"
unset POSTFIX
MSG="${MSG} / NEW_DYNAREC"
else
DYN="0"
if [[ "${BITS}" == "64" ]]; then BITS="32"; else BITS="64"; fi
fi
if [[ ${BITS} -eq 32 ]]; then
if [[ "${CC}" == "clang" ]]; then export PIC="1"; fi
MSG="x86 / ${MSG}"
else
MSG="x64 / ${MSG}"
fi
echo ""
echo ":: ${{ matrix.cc }} ${MSG} ::"
echo ":: ${{ matrix.cc }} ${{ matrix.platform }} / SDL${MSG} ::"
echo ""
make -C projects/unix clean
make NEW_DYNAREC="${DYN}" -C projects/unix clean
echo ""
make CC="${CC}" CXX="${CXX}" BITS="${BITS}" SDL_CONFIG="${SDL}-config" NEW_DYNAREC="${DYN}" -C projects/unix all
make CC="${CC}" CXX="${CXX}" BITS="${{ matrix.bits }}" SDL_CONFIG="${SDL}-config" NEW_DYNAREC="${DYN}" -C projects/unix all -j4
echo ""
ls -gG projects/unix/*.so*
ldd projects/unix/libmupen64plus.so.2.0.0
make BITS="${{ matrix.bits }}" NEW_DYNAREC="${DYN}" -C projects/unix install DESTDIR="${ORIG}/tmp"
echo ""
cd tmp/usr/local/lib
ls -gG libmupen64plus${POSTFIX}.so*
ldd libmupen64plus${POSTFIX}.so.2.0.0
if [[ ${DYN} -eq 1 ]]; then
SDL="sdl2"
MSG="2"
fi
cd "${ORIG}"
done
mkdir pkg
if [[ "${CC}" == "gcc" ]]; then tar cvzf pkg/mupen64plus-core-${{ matrix.platform }}-g${G_REV}.tar.gz -C tmp/ "usr"; fi
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: mupen64plus-core-${{ matrix.platform }}-g${{ env.G_REV }}
path: pkg/*
if-no-files-found: ignore
MSYS2:
strategy:
@@ -106,13 +127,14 @@ jobs:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: msys2/setup-msys2@v2
with:
msystem: MINGW${{ matrix.bits }}
update: true
install: >-
git
libtool
make
mingw-w64-${{ matrix.cross }}-gcc
mingw-w64-${{ matrix.cross }}-toolchain
@@ -123,26 +145,28 @@ jobs:
mingw-w64-${{ matrix.cross }}-zlib
- name: Build and related stuff
run: |
export OPTFLAGS="-O2 -flto"
if [[ ${{ matrix.bits }} -eq 32 ]]; then export OPTFLAGS="-O2 -flto -mtune=pentium4"; else export OPTFLAGS="-O2 -flto -mtune=core2"; fi
echo "G_REV=$(git rev-parse --short HEAD)" >> "${GITHUB_ENV}"
ORIG="$(pwd)"
CC="gcc"
CXX="g++"
${CC} --version
mkdir backup
LIB="-old"
mkdir tmp
export POSTFIX="-old"
for DYN in 0 1
do
echo ""
echo ":: ${{ matrix.cc }} ${{ matrix.platform }} / SDL2${MSG} ::"
echo ""
make -C projects/unix clean
make NEW_DYNAREC="${DYN}" -C projects/unix clean
echo ""
make CC="${CC}" CXX="${CXX}" BITS="${{ matrix.bits }}" NEW_DYNAREC="${DYN}" -C projects/unix all
make CC="${CC}" CXX="${CXX}" BITS="${{ matrix.bits }}" NEW_DYNAREC="${DYN}" -C projects/unix all -j4
echo ""
cp projects/unix/*.dll backup/mupen64plus${LIB}.dll
ls -gG backup/mupen64plus${LIB}.dll
ldd backup/mupen64plus${LIB}.dll
unset LIB
make BITS="${{ matrix.bits }}" NEW_DYNAREC="${DYN}" -C projects/unix install PLUGINDIR="" SHAREDIR="" BINDIR="" MANDIR="" LIBDIR="" APPSDIR="" ICONSDIR="icons" INCDIR="api" LDCONFIG="true" DESTDIR="${ORIG}/tmp"
echo ""
ls -gG tmp/mupen64plus${POSTFIX}.dll
ldd tmp/mupen64plus${POSTFIX}.dll
unset POSTFIX
MSG=" / NEW_DYNAREC"
done
- name: Copy binaries, dependencies, etc...
@@ -162,14 +186,14 @@ jobs:
cp -r "${DAT}" ../pkg/
done
fi
cd ../backup
cd ../tmp
for BIN in *.dll
do
echo ":: Copying ${BIN}"
cp "${BIN}" ../pkg/
done
- name: Upload artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: mupen64plus-core-msys2-${{ matrix.platform }}-g${{ env.G_REV }}
path: pkg/*
@@ -189,8 +213,8 @@ jobs:
run:
shell: cmd
steps:
- uses: actions/checkout@v2
- uses: microsoft/setup-msbuild@v1.0.3
- uses: actions/checkout@v3
- uses: microsoft/setup-msbuild@v1
# with:
# vs-version: 16.11
- name: Build and related stuff
@@ -226,19 +250,19 @@ jobs:
copy "..\..\mupen64plus-win32-deps\SDL2_net-2.0.1\lib\${{ matrix.platform }}\*.dll" .
copy "..\..\mupen64plus-win32-deps\zlib-1.2.11\lib\${{ matrix.platform }}\*.dll" .
- name: Upload artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: mupen64plus-core-msvc-${{ matrix.platform }}-g${{ env.G_REV }}
path: pkg/*
Nightly-build:
runs-on: ubuntu-latest
needs: [MSYS2, MSVC]
needs: [Linux, MSYS2, MSVC]
if: github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Download artifacts
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
path: binaries
- name: Get some tools
@@ -251,20 +275,30 @@ jobs:
cd binaries
for BIN in *
do
echo ":: Creating ${BIN}.zip"
cd "${BIN}"
zip -r "../../pkg/${BIN}.zip" *
if [[ "${BIN:17:4}" == "msys" ]]; then
echo ":: Creating ${BIN}.zip"
zip -r "../../pkg/${BIN}.zip" *
elif [[ "${BIN:17:4}" == "msvc" ]]; then
echo ":: Creating ${BIN}.zip"
zip -r "../../pkg/${BIN}.zip" *
else
echo ":: Recovering ${BIN}.tar.gz"
mv *.tar.gz ../../pkg/
fi
cd ..
done
cd ../pkg
echo ""
for BIN in *.zip
for BIN in *
do
ls -gG ${BIN}
tigerdeep -l ${BIN} >> ${BIN:0:16}.tiger.txt
sha256sum ${BIN} >> ${BIN:0:16}.sha256.txt
sha512sum ${BIN} >> ${BIN:0:16}.sha512.txt
tigerdeep -l ${BIN} >> ../${BIN:0:16}.tiger.txt
sha256sum ${BIN} >> ../${BIN:0:16}.sha256.txt
sha512sum ${BIN} >> ../${BIN:0:16}.sha512.txt
done
mv ../*.tiger.txt .
mv ../*.sha*.txt .
echo ""
echo "TIGER:"
cat *.tiger.txt
File diff suppressed because it is too large Load Diff
@@ -160,6 +160,8 @@
<ClCompile Include="..\..\src\main\util.c" />
<ClCompile Include="..\..\src\main\workqueue.c" />
<ClCompile Include="..\..\src\device\memory\memory.c" />
<ClCompile Include="..\..\src\device\memory\dcache.c" />
<ClCompile Include="..\..\src\device\memory\icache.c" />
<ClCompile Include="..\..\src\osal\dynamiclib_unix.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -177,6 +177,12 @@
<ClCompile Include="..\..\src\device\memory\memory.c">
<Filter>device\memory</Filter>
</ClCompile>
<ClCompile Include="..\..\src\device\memory\dcache.c">
<Filter>device\memory</Filter>
</ClCompile>
<ClCompile Include="..\..\src\device\memory\icache.c">
<Filter>device\memory</Filter>
</ClCompile>
<ClCompile Include="..\..\src\osal\dynamiclib_unix.c">
<Filter>osal</Filter>
</ClCompile>
+3 -2
View File
@@ -182,7 +182,6 @@ ifeq ($(ARCH_DETECTED), 64BITS_32)
endif
ifneq ($(OS), OSX)
ifeq ($(OS), MINGW)
CFLAGS += -march=i686
LDFLAGS += -Wl,-m,i386pe
else
CFLAGS += -m32
@@ -551,6 +550,8 @@ SOURCE = \
$(SRCDIR)/device/gb/mbc3_rtc.c \
$(SRCDIR)/device/gb/m64282fp.c \
$(SRCDIR)/device/memory/memory.c \
$(SRCDIR)/device/memory/dcache.c \
$(SRCDIR)/device/memory/icache.c \
$(SRCDIR)/device/pif/bootrom_hle.c \
$(SRCDIR)/device/pif/cic.c \
$(SRCDIR)/device/pif/n64_cic_nus_6105.c \
@@ -805,7 +806,7 @@ uninstall:
$(RM) "$(DESTDIR)$(SHAREDIR)/mupencheat.txt"
clean:
$(RM) -r $(TARGET) $(SONAME) $(OBJDIR) $(SRCDIR)/asm_defines/asm_defines_*
$(RM) -r $(TARGET) $(SONAME) _obj $(OBJDIR) $(SRCDIR)/asm_defines/asm_defines_*
# build dependency files
CFLAGS += -MD -MP
+1 -1
View File
@@ -447,7 +447,7 @@ EXPORT uint32_t CALL DebugVirtualToPhysical(uint32_t address)
struct r4300_core* r4300 = &dev->r4300;
if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) {
address = virtual_to_physical_address(r4300, address, 0);
address = virtual_to_physical_address(r4300, address, 0, &(uint8_t){0});
if (address == 0) {
return 0;
}
-1
View File
@@ -425,7 +425,6 @@ EXPORT m64p_error CALL CoreGetRomSettings(m64p_rom_settings *RomSettings, int Ro
RomSettings->transferpak = entry->transferpak;
RomSettings->mempak = entry->mempak;
RomSettings->disableextramem = entry->disableextramem;
RomSettings->countperop = entry->countperop;
RomSettings->savetype = entry->savetype;
RomSettings->sidmaduration = entry->sidmaduration;
RomSettings->aidmamodifier = entry->aidmamodifier;
-1
View File
@@ -280,7 +280,6 @@ typedef struct
unsigned char mempak; /* 0 - No, 1 - Yes boolean for memory pak support. */
unsigned char biopak; /* 0 - No, 1 - Yes boolean for bio pak support. */
unsigned char disableextramem; /* 0 - No, 1 - Yes boolean for disabling 4MB expansion RAM pack */
unsigned int countperop; /* Number of CPU cycles per instruction. */
unsigned int sidmaduration; /* Default SI DMA duration */
unsigned int aidmamodifier; /* Percentage modifier for AI DMA duration */
unsigned int rspdelaytime; /* Cycles to delay RSP when needed */
@@ -113,7 +113,6 @@ DEFINE(cp0, regs);
DEFINE(cp0, next_interrupt);
#endif
DEFINE(cp0, last_addr);
DEFINE(cp0, count_per_op);
DEFINE(cp0, tlb);
DEFINE(tlb, entries);
+10 -16
View File
@@ -188,51 +188,45 @@ void write_cart_dom2(void* opaque, uint32_t address, uint32_t value, uint32_t ma
}
}
unsigned int cart_dom2_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void cart_dom2_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
struct cart* cart = (struct cart*)opaque;
unsigned int cycles;
if (cart->use_flashram != 1)
{
cycles = sram_dma_read(&cart->sram, dram, dram_addr, cart_addr, length);
sram_dma_read(&cart->sram, dram, dram_addr, cart_addr, length);
cart->use_flashram = -1;
}
else
{
cycles = flashram_dma_read(&cart->flashram, dram, dram_addr, cart_addr, length);
flashram_dma_read(&cart->flashram, dram, dram_addr, cart_addr, length);
}
return cycles;
}
unsigned int cart_dom2_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void cart_dom2_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
struct cart* cart = (struct cart*)opaque;
unsigned int cycles;
if (cart->use_flashram != 1)
{
cycles = sram_dma_write(&cart->sram, dram, dram_addr, cart_addr, length);
sram_dma_write(&cart->sram, dram, dram_addr, cart_addr, length);
cart->use_flashram = -1;
}
else
{
cycles = flashram_dma_write(&cart->flashram, dram, dram_addr, cart_addr, length);
flashram_dma_write(&cart->flashram, dram, dram_addr, cart_addr, length);
}
return cycles;
}
unsigned int cart_dom3_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void cart_dom3_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
struct cart* cart = (struct cart*)opaque;
return cart_rom_dma_read(&cart->cart_rom, dram, dram_addr, cart_addr, length);
cart_rom_dma_read(&cart->cart_rom, dram, dram_addr, cart_addr, length);
}
unsigned int cart_dom3_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void cart_dom3_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
struct cart* cart = (struct cart*)opaque;
return cart_rom_dma_write(&cart->cart_rom, dram, dram_addr, cart_addr, length);
cart_rom_dma_write(&cart->cart_rom, dram, dram_addr, cart_addr, length);
}
+4 -4
View File
@@ -72,10 +72,10 @@ void poweron_cart(struct cart* cart);
void read_cart_dom2(void* opaque, uint32_t address, uint32_t* value);
void write_cart_dom2(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
unsigned int cart_dom2_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
unsigned int cart_dom2_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
unsigned int cart_dom3_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
unsigned int cart_dom3_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void cart_dom2_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void cart_dom2_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void cart_dom3_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void cart_dom3_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
extern const struct joybus_device_interface
g_ijoybus_device_cart;
+2 -7
View File
@@ -78,20 +78,17 @@ void write_cart_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mas
/* Mark IO as busy */
cart_rom->pi->regs[PI_STATUS_REG] |= PI_STATUS_IO_BUSY;
cp0_update_count(cart_rom->r4300);
add_interrupt_event(&cart_rom->r4300->cp0, PI_INT, 0x1000);
}
unsigned int cart_rom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void cart_rom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
cart_addr &= CART_ROM_ADDR_MASK;
DebugMessage(M64MSG_WARNING, "DMA Writing to CART_ROM: 0x%" PRIX32 " -> 0x%" PRIX32 " (0x%" PRIX32 ")", dram_addr, cart_addr, length);
return /* length / 8 */0x1000;
}
unsigned int cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
size_t i;
struct cart_rom* cart_rom = (struct cart_rom*)opaque;
@@ -122,7 +119,5 @@ unsigned int cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr,
/* invalidate cached code */
invalidate_r4300_cached_code(cart_rom->r4300, 0x80000000 + dram_addr, length);
invalidate_r4300_cached_code(cart_rom->r4300, 0xa0000000 + dram_addr, length);
return (length / 8) + add_random_interrupt_time(cart_rom->r4300);
}
+2 -2
View File
@@ -56,7 +56,7 @@ void poweron_cart_rom(struct cart_rom* cart_rom);
void read_cart_rom(void* opaque, uint32_t address, uint32_t* value);
void write_cart_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
unsigned int cart_rom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
unsigned int cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void cart_rom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void cart_rom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
#endif
+2 -6
View File
@@ -181,7 +181,7 @@ void write_flashram(void* opaque, uint32_t address, uint32_t value, uint32_t mas
}
unsigned int flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
size_t i;
struct flashram* flashram = (struct flashram*)opaque;
@@ -216,11 +216,9 @@ unsigned int flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr,
DebugMessage(M64MSG_WARNING, "unknown Flashram DMA Write (mode=%x) @%08x <- %08x length=%08x",
flashram->mode, dram_addr, cart_addr, length);
}
return /* length / 8 */0x1000;
}
unsigned int flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
struct flashram* flashram = (struct flashram*)opaque;
unsigned int i;
@@ -236,7 +234,5 @@ unsigned int flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_
DebugMessage(M64MSG_WARNING, "unknown Flashram DMA Read (mode=%x) @%08x <- %08x length=%08x",
flashram->mode, cart_addr, dram_addr, length);
}
return /* length / 8 */0x1000;
}
+2 -2
View File
@@ -75,7 +75,7 @@ void format_flashram(uint8_t* flash);
void read_flashram(void* opaque, uint32_t address, uint32_t* value);
void write_flashram(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
unsigned int flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
unsigned int flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void flashram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void flashram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
#endif
+2 -6
View File
@@ -42,7 +42,7 @@ void init_sram(struct sram* sram,
sram->istorage = istorage;
}
unsigned int sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
size_t i;
struct sram* sram = (struct sram*)opaque;
@@ -55,11 +55,9 @@ unsigned int sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr
}
sram->istorage->save(sram->storage, cart_addr, length);
return /* length / 8 */0x1000;
}
unsigned int sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
size_t i;
struct sram* sram = (struct sram*)opaque;
@@ -70,8 +68,6 @@ unsigned int sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uin
for (i = 0; i < length; ++i) {
dram[(dram_addr+i)^S8] = mem[(cart_addr+i)^S8];
}
return /* length / 8 */0x1000;
}
void read_sram(void* opaque, uint32_t address, uint32_t* value)
+2 -2
View File
@@ -39,8 +39,8 @@ void format_sram(uint8_t* sram);
void init_sram(struct sram* sram,
void* storage, const struct storage_backend_interface* istorage);
unsigned int sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
unsigned int sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void sram_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void sram_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void read_sram(void* opaque, uint32_t address, uint32_t* value);
void write_sram(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
+5 -21
View File
@@ -547,7 +547,7 @@ void write_dd_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
DebugMessage(M64MSG_VERBOSE, "DD ROM: %08X <- %08x & %08x", address, value, mask);
}
unsigned int dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
struct dd_controller* dd = (struct dd_controller*)opaque;
uint8_t* mem;
@@ -562,29 +562,22 @@ unsigned int dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_ad
}
else if (cart_addr == MM_DD_MS_RAM) {
/* MS is not emulated, we silence warnings for now */
/* Recommended Count Per Op = 1, this seems to break very easily */
return (length * 63) / 25;
return;
}
else {
DebugMessage(M64MSG_ERROR, "Unknown DD dma read dram=%08x cart=%08x length=%08x",
dram_addr, cart_addr, length);
/* Recommended Count Per Op = 1, this seems to break very easily */
return (length * 63) / 25;
return;
}
for (i = 0; i < length; ++i) {
mem[(cart_addr + i) ^ S8] = dram[(dram_addr + i) ^ S8];
}
/* Recommended Count Per Op = 1, this seems to break very easily */
return (length * 63) / 25;
}
unsigned int dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
void dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length)
{
struct dd_controller* dd = (struct dd_controller*)opaque;
unsigned int cycles;
const uint8_t* mem;
size_t i;
@@ -606,20 +599,13 @@ unsigned int dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, u
DebugMessage(M64MSG_ERROR, "Unknown DD dma write dram=%08x cart=%08x length=%08x",
dram_addr, cart_addr, length);
/* Recommended Count Per Op = 1, this seems to break very easily */
return (length * 63) / 25;
return;
}
/* Recommended Count Per Op = 1, this seems to break very easily */
cycles = (length * 63) / 25;
}
else {
/* DD ROM */
cart_addr = (cart_addr - MM_DD_ROM);
mem = (const uint8_t*)dd->rom;
/* Recommended Count Per Op = 1, this seems to break very easily */
cycles = (length * 63) / 25;
}
for (i = 0; i < length; ++i) {
@@ -628,8 +614,6 @@ unsigned int dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, u
invalidate_r4300_cached_code(dd->r4300, R4300_KSEG0 + dram_addr, length);
invalidate_r4300_cached_code(dd->r4300, R4300_KSEG1 + dram_addr, length);
return cycles;
}
void dd_on_pi_cart_addr_write(struct dd_controller* dd, uint32_t address)
@@ -117,8 +117,8 @@ void write_dd_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask
void read_dd_rom(void* opaque, uint32_t address, uint32_t* value);
void write_dd_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
unsigned int dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
unsigned int dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void dd_on_pi_cart_addr_write(struct dd_controller* dd, uint32_t address);
void dd_update_bm(void* opaque);
+1 -3
View File
@@ -82,8 +82,6 @@ void init_device(struct device* dev,
void* base,
/* r4300 */
unsigned int emumode,
unsigned int count_per_op,
unsigned int count_per_op_denom_pot,
int no_compiled_jump,
int randomize_interrupt,
uint32_t start_address,
@@ -182,7 +180,7 @@ void init_device(struct device* dev,
init_rdram(&dev->rdram, mem_base_u32(base, MM_RDRAM_DRAM), dram_size, &dev->r4300);
init_r4300(&dev->r4300, &dev->mem, &dev->mi, &dev->rdram, interrupt_handlers,
emumode, count_per_op, count_per_op_denom_pot, no_compiled_jump, randomize_interrupt, start_address);
emumode, no_compiled_jump, randomize_interrupt, start_address);
init_rdp(&dev->dp, &dev->sp, &dev->mi, &dev->mem, &dev->rdram, &dev->r4300);
init_rsp(&dev->sp, mem_base_u32(base, MM_RSP_MEM), &dev->mi, &dev->dp, &dev->ri, rsp_delay_time);
init_ai(&dev->ai, &dev->mi, &dev->ri, &dev->vi, aout, iaout, dma_modifier);
-2
View File
@@ -120,8 +120,6 @@ void init_device(struct device* dev,
void* base,
/* r4300 */
unsigned int emumode,
unsigned int count_per_op,
unsigned int count_per_op_denom_pot,
int no_compiled_jump,
int randomize_interrupt,
uint32_t start_address,
@@ -0,0 +1,96 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - dcache.c *
* Mupen64Plus homepage: https://mupen64plus.org/ *
* Copyright (C) 2022 loganmc10 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <string.h>
#include "device/r4300/r4300_core.h"
#include "device/memory/memory.h"
void init_dcache(struct datacache *lines)
{
memset(lines, 0, 512 * sizeof(lines[0]));
for (uint32_t i = 0; i < 512; ++i)
lines[i].index = i << 4 & UINT32_C(0xFF0);
}
void dcache_writeback(struct r4300_core* r4300, struct datacache *line)
{
cp0_add_count(r4300, 22, 0);
line->dirty = 0;
uint32_t cache_address = line->tag | line->index;
invalidate_r4300_cached_code(r4300, cache_address, 16);
invalidate_r4300_cached_code(r4300, cache_address ^ UINT32_C(0x20000000), 16);
cache_address &= UINT32_C(0x1ffffffc);
const struct mem_handler* handler = mem_get_handler(r4300->mem, cache_address);
mem_write32(handler, cache_address | UINT32_C(0x0), line->words[0], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0x4), line->words[1], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0x8), line->words[2], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0xC), line->words[3], ~UINT32_C(0));
}
uint32_t dcache_hit(struct datacache *line, uint32_t address)
{
return line->valid && line->tag == (address & ~UINT32_C(0xFFF));
}
static void dcache_fill(struct datacache *line, struct r4300_core* r4300, uint32_t address)
{
cp0_add_count(r4300, 22, 0);
line->valid = 1;
line->dirty = 0;
line->tag = address & ~UINT32_C(0xFFF);
uint32_t cache_address = line->tag | line->index;
cache_address &= UINT32_C(0x1ffffffc);
const struct mem_handler* handler = mem_get_handler(r4300->mem, cache_address);
mem_read32(handler, cache_address | UINT32_C(0x0), &line->words[0]);
mem_read32(handler, cache_address | UINT32_C(0x4), &line->words[1]);
mem_read32(handler, cache_address | UINT32_C(0x8), &line->words[2]);
mem_read32(handler, cache_address | UINT32_C(0xC), &line->words[3]);
}
void dcache_read32(struct r4300_core* r4300, uint32_t address, uint32_t *value)
{
struct datacache *line = &r4300->mem->dcache[(address >> 4) & UINT32_C(0x1FF)];
if(!dcache_hit(line, address))
{
if(line->valid && line->dirty)
dcache_writeback(r4300, line);
dcache_fill(line, r4300, address);
}
else
cp0_add_count(r4300, 0, 1);
*value = line->words[(address >> 2) & UINT32_C(3)];
}
void dcache_write32(struct r4300_core* r4300, uint32_t address, uint32_t value, uint32_t mask)
{
struct datacache *line = &r4300->mem->dcache[(address >> 4) & UINT32_C(0x1FF)];
if(!dcache_hit(line, address))
{
if(line->valid && line->dirty)
dcache_writeback(r4300, line);
dcache_fill(line, r4300, address);
}
else
cp0_add_count(r4300, 0, 1);
masked_write(&line->words[(address >> 2) & UINT32_C(3)], value, mask);
line->dirty = 1;
}
@@ -0,0 +1,44 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - dcache.h *
* Mupen64Plus homepage: https://mupen64plus.org/ *
* Copyright (C) 2022 loganmc10 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef M64P_DEVICE_MEMORY_DCACHE_H
#define M64P_DEVICE_MEMORY_DCACHE_H
#include <stdint.h>
struct r4300_core;
struct datacache
{
uint8_t valid;
uint8_t dirty;
uint32_t tag;
uint16_t index;
uint32_t words[4];
};
void init_dcache(struct datacache *lines);
void dcache_writeback(struct r4300_core* r4300, struct datacache *line);
uint32_t dcache_hit(struct datacache *line, uint32_t address);
void dcache_read32(struct r4300_core* r4300, uint32_t address, uint32_t *value);
void dcache_write32(struct r4300_core* r4300, uint32_t address, uint32_t value, uint32_t mask);
#endif
+100
View File
@@ -0,0 +1,100 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - icache.c *
* Mupen64Plus homepage: https://mupen64plus.org/ *
* Copyright (C) 2022 loganmc10 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <string.h>
#include "device/r4300/r4300_core.h"
#include "device/memory/memory.h"
void init_icache(struct instcache *lines)
{
memset(lines, 0, 512 * sizeof(lines[0]));
for (uint32_t i = 0; i < 512; ++i)
lines[i].index = i << 5 & UINT32_C(0xFE0);
}
void icache_writeback(struct r4300_core* r4300, struct instcache *line)
{
cp0_add_count(r4300, 24, 0);
uint32_t cache_address = line->tag | line->index;
invalidate_r4300_cached_code(r4300, cache_address, 32);
invalidate_r4300_cached_code(r4300, cache_address ^ UINT32_C(0x20000000), 32);
cache_address &= UINT32_C(0x1ffffffc);
const struct mem_handler* handler = mem_get_handler(r4300->mem, cache_address);
mem_write32(handler, cache_address | UINT32_C(0x0), line->words[0], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0x4), line->words[1], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0x8), line->words[2], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0xC), line->words[3], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0x10), line->words[4], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0x14), line->words[5], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0x18), line->words[6], ~UINT32_C(0));
mem_write32(handler, cache_address | UINT32_C(0x1C), line->words[7], ~UINT32_C(0));
}
uint32_t icache_hit(struct instcache *line, uint32_t address)
{
return line->valid && line->tag == (address & ~UINT32_C(0xFFF));
}
void icache_fill(struct instcache *line, struct r4300_core* r4300, uint32_t address)
{
cp0_add_count(r4300, 24, 0);
line->valid = 1;
line->tag = address & ~UINT32_C(0xFFF);
uint32_t cache_address = line->tag | line->index;
cache_address &= UINT32_C(0x1ffffffc);
const struct mem_handler* handler = mem_get_handler(r4300->mem, cache_address);
mem_read32(handler, cache_address | UINT32_C(0x0), &line->words[0]);
mem_read32(handler, cache_address | UINT32_C(0x4), &line->words[1]);
mem_read32(handler, cache_address | UINT32_C(0x8), &line->words[2]);
mem_read32(handler, cache_address | UINT32_C(0xC), &line->words[3]);
mem_read32(handler, cache_address | UINT32_C(0x10), &line->words[4]);
mem_read32(handler, cache_address | UINT32_C(0x14), &line->words[5]);
mem_read32(handler, cache_address | UINT32_C(0x18), &line->words[6]);
mem_read32(handler, cache_address | UINT32_C(0x1C), &line->words[7]);
}
uint32_t* icache_fetch(struct r4300_core* r4300, uint32_t address)
{
struct instcache *line = &r4300->mem->icache[(address >> 5) & UINT32_C(0x1FF)];
if(!icache_hit(line, address))
icache_fill(line, r4300, address);
else
cp0_add_count(r4300, 1, 0);
return &line->words[address >> 2 & 7];
}
void icache_step(struct r4300_core* r4300, uint32_t address)
{
struct instcache *line = &r4300->mem->icache[(address >> 5) & UINT32_C(0x1FF)];
uint8_t cached = 0;
r4300_translate_address(r4300, &address, &cached, 2, 0);
if (cached)
{
if(!icache_hit(line, address))
icache_fill(line, r4300, address);
else
cp0_add_count(r4300, 1, 0);
}
else
cp0_add_count(r4300, 18, 1);
}
@@ -0,0 +1,44 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - icache.h *
* Mupen64Plus homepage: https://mupen64plus.org/ *
* Copyright (C) 2022 loganmc10 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef M64P_DEVICE_MEMORY_ICACHE_H
#define M64P_DEVICE_MEMORY_ICACHE_H
#include <stdint.h>
struct r4300_core;
struct instcache
{
uint8_t valid;
uint32_t tag;
uint16_t index;
uint32_t words[8];
};
void init_icache(struct instcache *lines);
void icache_writeback(struct r4300_core* r4300, struct instcache *line);
uint32_t icache_hit(struct instcache *line, uint32_t address);
void icache_fill(struct instcache *line, struct r4300_core* r4300, uint32_t address);
uint32_t* icache_fetch(struct r4300_core* r4300, uint32_t address);
void icache_step(struct r4300_core* r4300, uint32_t address);
#endif
@@ -180,6 +180,9 @@ void init_memory(struct memory* mem,
for(m = 0; m < mappings_count; ++m) {
apply_mem_mapping(mem, &mappings[m]);
}
init_dcache(&mem->dcache[0]);
init_icache(&mem->icache[0]);
}
static void map_region(struct memory* mem,
@@ -25,6 +25,8 @@
#include <stddef.h>
#include <stdint.h>
#include "dcache.h"
#include "icache.h"
#include "osal/preproc.h"
enum { RDRAM_MAX_SIZE = 0x800000 };
@@ -53,6 +55,8 @@ struct memory
{
struct mem_handler handlers[0x10000];
void* base;
struct datacache dcache[512];
struct instcache icache[512];
#ifdef DBG
int memtype[0x10000];
-10
View File
@@ -279,7 +279,6 @@ static void process_cic_challenge(struct pif* pif)
void poweron_pif(struct pif* pif)
{
memset(pif->ram, 0, PIF_RAM_SIZE);
pif->update_counter = 0;
reset_pif(pif, 0); /* cold reset */
}
@@ -309,7 +308,6 @@ void write_pif_mem(void* opaque, uint32_t address, uint32_t value, uint32_t mask
pif->si->dma_dir = SI_DMA_WRITE;
cp0_update_count(pif->r4300);
pif->si->regs[SI_STATUS_REG] |= (SI_STATUS_DMA_BUSY | SI_STATUS_IO_BUSY);
add_interrupt_event(&pif->r4300->cp0, SI_INT, pif->si->dma_duration);
}
@@ -368,13 +366,6 @@ void process_pif_ram(struct pif* pif)
pif->ram[0x3f] &= ~clrmask;
}
static void update_pif_counter(struct pif* pif)
{
/* check if controller 0 was polled for input */
if (pif->channels[0].tx && (pif->channels[0].tx_buf[0] == JCMD_CONTROLLER_READ))
++pif->update_counter;
}
void update_pif_ram(struct pif* pif)
{
size_t k;
@@ -388,7 +379,6 @@ void update_pif_ram(struct pif* pif)
if (input.readController) {
input.readController(-1, NULL);
}
update_pif_counter(pif);
netplay_update_input(pif);
-2
View File
@@ -59,8 +59,6 @@ struct pif
struct cic cic;
uint32_t update_counter;
struct r4300_core* r4300;
struct si_controller* si;
};
@@ -83,8 +83,8 @@ void cached_interp_##name(void) \
(*r4300_pc_struct(r4300))++; \
r4300->delay_slot=1; \
UPDATE_DEBUGGER(); \
icache_step(r4300, (*r4300_pc_struct(r4300))->addr); \
(*r4300_pc_struct(r4300))->ops(); \
cp0_update_count(r4300); \
r4300->delay_slot=0; \
if (take_jump && !r4300->skip_jump) \
{ \
@@ -94,7 +94,6 @@ void cached_interp_##name(void) \
else \
{ \
(*r4300_pc_struct(r4300)) += 2; \
cp0_update_count(r4300); \
} \
r4300->cp0.last_addr = *r4300_pc(r4300); \
if (*r4300_cp0_cycle_count(&r4300->cp0) >= 0) gen_interrupt(r4300); \
@@ -116,8 +115,8 @@ void cached_interp_##name##_OUT(void) \
(*r4300_pc_struct(r4300))++; \
r4300->delay_slot=1; \
UPDATE_DEBUGGER(); \
icache_step(r4300, (*r4300_pc_struct(r4300))->addr); \
(*r4300_pc_struct(r4300))->ops(); \
cp0_update_count(r4300); \
r4300->delay_slot=0; \
if (take_jump && !r4300->skip_jump) \
{ \
@@ -127,7 +126,6 @@ void cached_interp_##name##_OUT(void) \
else \
{ \
(*r4300_pc_struct(r4300)) += 2; \
cp0_update_count(r4300); \
} \
r4300->cp0.last_addr = *r4300_pc(r4300); \
if (*r4300_cp0_cycle_count(&r4300->cp0) >= 0) gen_interrupt(r4300); \
@@ -142,7 +140,6 @@ void cached_interp_##name##_IDLE(void) \
if (cop1 && check_cop1_unusable(r4300)) return; \
if (take_jump) \
{ \
cp0_update_count(r4300); \
if(*cp0_cycle_count < 0) \
{ \
cp0_regs[CP0_COUNT_REG] -= *cp0_cycle_count; \
@@ -203,6 +200,7 @@ void cached_interp_FIN_BLOCK(void)
#endif
Used by dynarec only, check should be unnecessary
*/
icache_step(r4300, (*r4300_pc_struct(r4300))->addr);
(*r4300_pc_struct(r4300))->ops();
}
else
@@ -219,6 +217,7 @@ Used by dynarec only, check should be unnecessary
*/
if (!r4300->skip_jump)
{
icache_step(r4300, (*r4300_pc_struct(r4300))->addr);
(*r4300_pc_struct(r4300))->ops();
r4300->cached_interp.actual = blk;
(*r4300_pc_struct(r4300)) = inst+1;
@@ -231,7 +230,7 @@ Used by dynarec only, check should be unnecessary
void cached_interp_NOTCOMPILED(void)
{
DECLARE_R4300
uint32_t *mem = fast_mem_access(r4300, r4300->cached_interp.blocks[*r4300_pc(r4300)>>12]->start);
uint32_t *mem = fast_mem_access(r4300, r4300->cached_interp.blocks[*r4300_pc(r4300)>>12]->start, 0);
#ifdef DBG
DebugMessage(M64MSG_INFO, "NOTCOMPILED: addr = %x ops = %lx", *r4300_pc(r4300), (long) (*r4300_pc_struct(r4300))->ops);
#endif
@@ -250,6 +249,7 @@ void cached_interp_NOTCOMPILED(void)
The preceeding update_debugger SHOULD be unnecessary since it should have been
called before NOTCOMPILED would have been executed
*/
icache_step(r4300, (*r4300_pc_struct(r4300))->addr);
(*r4300_pc_struct(r4300))->ops();
}
@@ -514,6 +514,7 @@ enum r4300_opcode r4300_decode(struct precomp_instr* inst, struct r4300_core* r4
case R4300_OP_LWC1:
case R4300_OP_SDC1:
case R4300_OP_SWC1:
case R4300_OP_CACHE:
idec_u53(iw, idec->u53[2], &inst->f.lf.base);
idec_u53(iw, idec->u53[1], &inst->f.lf.ft);
inst->f.lf.offset = (uint16_t)iw;
@@ -672,7 +673,6 @@ enum r4300_opcode r4300_decode(struct precomp_instr* inst, struct r4300_core* r4
break;
case R4300_OP_BREAK:
case R4300_OP_CACHE:
case R4300_OP_ERET:
case R4300_OP_SYNC:
case R4300_OP_SYSCALL:
@@ -714,7 +714,7 @@ static uint32_t update_invalid_addr(struct r4300_core* r4300, uint32_t addr)
}
else
{
uint32_t paddr = virtual_to_physical_address(r4300, addr, 2);
uint32_t paddr = virtual_to_physical_address(r4300, addr, 2, &(uint8_t){0});
if (paddr)
{
uint32_t beg_paddr = paddr - (addr - (addr & ~0xfff));
@@ -799,7 +799,7 @@ void cached_interp_init_block(struct r4300_core* r4300, uint32_t address)
if (b->end < UINT32_C(0x80000000) || b->start >= UINT32_C(0xc0000000))
{
uint32_t paddr = virtual_to_physical_address(r4300, b->start, 2);
uint32_t paddr = virtual_to_physical_address(r4300, b->start, 2, &(uint8_t){0});
r4300->cached_interp.invalid_code[paddr>>12] = 0;
cached_interp_init_block(r4300, paddr);
@@ -854,7 +854,7 @@ void cached_interp_recompile_block(struct r4300_core* r4300, const uint32_t* iw,
if (block_start_in_tlb)
{
uint32_t address2 = virtual_to_physical_address(r4300, inst->addr, 0);
uint32_t address2 = virtual_to_physical_address(r4300, inst->addr, 0, &(uint8_t){0});
if (r4300->cached_interp.blocks[address2>>12]->block[(address2&UINT32_C(0xFFF))/4].ops == cached_interp_NOTCOMPILED) {
r4300->cached_interp.blocks[address2>>12]->block[(address2&UINT32_C(0xFFF))/4].ops = cached_interp_NOTCOMPILED2;
}
@@ -992,12 +992,13 @@ void run_cached_interpreter(struct r4300_core* r4300)
{
#ifdef COMPARE_CORE
if ((*r4300_pc_struct(r4300))->ops == cached_interp_FIN_BLOCK && ((*r4300_pc_struct(r4300))->addr < 0x80000000 || (*r4300_pc_struct(r4300))->addr >= 0xc0000000))
virtual_to_physical_address(r4300, (*r4300_pc_struct(r4300))->addr, 2);
virtual_to_physical_address(r4300, (*r4300_pc_struct(r4300))->addr, 2, &(uint8_t){0});
CoreCompareCallback();
#endif
#ifdef DBG
if (g_DebuggerActive) update_debugger((*r4300_pc_struct(r4300))->addr);
#endif
icache_step(r4300, (*r4300_pc_struct(r4300))->addr);
(*r4300_pc_struct(r4300))->ops();
}
}
+9 -34
View File
@@ -36,10 +36,8 @@
#endif
/* global functions */
void init_cp0(struct cp0* cp0, unsigned int count_per_op, unsigned int count_per_op_denom_pot, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers)
void init_cp0(struct cp0* cp0, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers)
{
cp0->count_per_op = count_per_op;
cp0->count_per_op_denom_pot = count_per_op_denom_pot;
#ifdef NEW_DYNAREC
cp0->new_dynarec_hot_state = new_dynarec_hot_state;
#endif
@@ -73,6 +71,7 @@ void poweron_cp0(struct cp0* cp0)
cp0->interrupt_unsafe_state = 0;
*cp0_next_interrupt = 0;
*cp0_cycle_count = 0;
cp0->half_count = 0;
cp0->last_addr = UINT32_C(0xbfc00000);
init_interrupt(cp0);
@@ -125,41 +124,22 @@ int check_cop1_unusable(struct r4300_core* r4300)
return 0;
}
void cp0_update_count(struct r4300_core* r4300)
void cp0_add_count(struct r4300_core* r4300, uint32_t count, uint8_t half)
{
struct cp0* cp0 = &r4300->cp0;
uint32_t* cp0_regs = r4300_cp0_regs(cp0);
#ifdef NEW_DYNAREC
if (r4300->emumode != EMUMODE_DYNAREC)
if (half)
{
#endif
uint32_t count = ((*r4300_pc(r4300) - cp0->last_addr) >> 2) * cp0->count_per_op;
if (r4300->cp0.count_per_op_denom_pot) {
count += (1 << r4300->cp0.count_per_op_denom_pot) - 1;
count >>= r4300->cp0.count_per_op_denom_pot;
}
cp0_regs[CP0_COUNT_REG] += count;
*r4300_cp0_cycle_count(cp0) += count;
cp0->last_addr = *r4300_pc(r4300);
#ifdef NEW_DYNAREC
cp0->half_count ^= 1;
half = cp0->half_count;
}
else
cp0_regs[CP0_COUNT_REG] = *r4300_cp0_next_interrupt(cp0) + *r4300_cp0_cycle_count(cp0);
#endif
#ifdef COMPARE_CORE
if (r4300->delay_slot)
CoreCompareCallback();
#endif
/*#ifdef DBG
if (g_DebuggerActive && !r4300->delay_slot) update_debugger(*r4300_pc(r4300));
#endif
*/
cp0_regs[CP0_COUNT_REG] += count + half;
*r4300_cp0_cycle_count(cp0) += count + half;
}
static void exception_epilog(struct r4300_core* r4300)
{
cp0_add_count(r4300, 1, 0);
#ifndef NO_ASM
#ifndef NEW_DYNAREC
if (r4300->emumode == EMUMODE_DYNAREC)
@@ -193,10 +173,6 @@ void TLB_refill_exception(struct r4300_core* r4300, uint32_t address, int w)
uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0);
int usual_handler = 0, i;
if (r4300->emumode != EMUMODE_DYNAREC && w != 2) {
cp0_update_count(r4300);
}
cp0_regs[CP0_CAUSE_REG] = (w == 1)
? CP0_CAUSE_EXCCODE_TLBS
: CP0_CAUSE_EXCCODE_TLBL;
@@ -276,7 +252,6 @@ void exception_general(struct r4300_core* r4300)
{
uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0);
cp0_update_count(r4300);
cp0_regs[CP0_STATUS_REG] |= CP0_STATUS_EXL;
cp0_regs[CP0_EPC_REG] = *r4300_pc(r4300);
+3 -4
View File
@@ -201,10 +201,9 @@ struct cp0
#endif
uint32_t last_addr;
unsigned int count_per_op;
unsigned int count_per_op_denom_pot;
struct tlb tlb;
uint8_t half_count;
};
#ifndef NEW_DYNAREC
@@ -217,7 +216,7 @@ struct cp0
offsetof(struct new_dynarec_hot_state, cp0_regs))
#endif
void init_cp0(struct cp0* cp0, unsigned int count_per_op, unsigned int count_per_op_denom_pot, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers);
void init_cp0(struct cp0* cp0, struct new_dynarec_hot_state* new_dynarec_hot_state, const struct interrupt_handler* interrupt_handlers);
void poweron_cp0(struct cp0* cp0);
uint32_t* r4300_cp0_regs(struct cp0* cp0);
@@ -231,7 +230,7 @@ int* r4300_cp0_cycle_count(struct cp0* cp0);
int check_cop1_unusable(struct r4300_core* r4300);
void cp0_update_count(struct r4300_core* r4300);
void cp0_add_count(struct r4300_core* r4300, uint32_t count, uint8_t half);
void TLB_refill_exception(struct r4300_core* r4300, uint32_t address, int w);
void exception_general(struct r4300_core* r4300);
@@ -278,11 +278,11 @@ void translate_event_queue(struct cp0* cp0, unsigned int base)
cp0_regs[CP0_COUNT_REG] = base;
add_interrupt_event_count(cp0, SPECIAL_INT, ((cp0_regs[CP0_COUNT_REG] & UINT32_C(0x80000000)) ^ UINT32_C(0x80000000)));
/* Add count_per_op to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */
cp0_regs[CP0_COUNT_REG] += cp0->count_per_op;
*cp0_cycle_count += cp0->count_per_op;
/* Add 2 to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */
cp0_regs[CP0_COUNT_REG] += 2;
*cp0_cycle_count += 2;
add_interrupt_event_count(cp0, COMPARE_INT, cp0_regs[CP0_COMPARE_REG]);
cp0_regs[CP0_COUNT_REG] -= cp0->count_per_op;
cp0_regs[CP0_COUNT_REG] -= 2;
/* Update next interrupt in case first event is COMPARE_INT */
*cp0_cycle_count = cp0_regs[CP0_COUNT_REG] - cp0->q.first->data.count;
@@ -399,11 +399,11 @@ void compare_int_handler(void* opaque)
uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0);
int* cp0_cycle_count = r4300_cp0_cycle_count(&r4300->cp0);
/* Add count_per_op to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */
cp0_regs[CP0_COUNT_REG] += r4300->cp0.count_per_op;
*cp0_cycle_count += r4300->cp0.count_per_op;
/* Add 2 to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */
cp0_regs[CP0_COUNT_REG] += 2;
*cp0_cycle_count += 2;
add_interrupt_event_count(&r4300->cp0, COMPARE_INT, cp0_regs[CP0_COMPARE_REG]);
cp0_regs[CP0_COUNT_REG] -= r4300->cp0.count_per_op;
cp0_regs[CP0_COUNT_REG] -= 2;
/* Update next interrupt in case first event is COMPARE_INT */
*cp0_cycle_count = cp0_regs[CP0_COUNT_REG] - r4300->cp0.q.first->data.count;
@@ -105,7 +105,7 @@ DECLARE_INSTRUCTION(NI)
{
DECLARE_R4300
DebugMessage(M64MSG_ERROR, "NI() @ 0x%" PRIX32, PCADDR);
DebugMessage(M64MSG_ERROR, "opcode not implemented: %" PRIX32 ":%" PRIX32, PCADDR, *fast_mem_access(r4300, PCADDR));
DebugMessage(M64MSG_ERROR, "opcode not implemented: %" PRIX32 ":%" PRIX32, PCADDR, *fast_mem_access(r4300, PCADDR, 0));
*r4300_stop(r4300) = 1;
}
@@ -114,7 +114,7 @@ DECLARE_INSTRUCTION(NI)
DECLARE_INSTRUCTION(RESERVED)
{
DECLARE_R4300
DebugMessage(M64MSG_ERROR, "reserved opcode: %" PRIX32 ":%" PRIX32, PCADDR, *fast_mem_access(r4300, PCADDR));
DebugMessage(M64MSG_ERROR, "reserved opcode: %" PRIX32 ":%" PRIX32, PCADDR, *fast_mem_access(r4300, PCADDR, 0));
*r4300_stop(r4300) = 1;
}
@@ -591,6 +591,7 @@ DECLARE_INSTRUCTION(NOR)
{
DECLARE_R4300
rrd = ~(rrs | rrt);
cp0_add_count(r4300, 28, 1);
ADD_TO_PC(1);
}
@@ -723,6 +724,7 @@ DECLARE_INSTRUCTION(MULT)
temp = rrs32 * (int64_t)rrt32;
*r4300_mult_hi(r4300) = temp >> 32;
*r4300_mult_lo(r4300) = SE32(temp);
cp0_add_count(r4300, 2, 1);
ADD_TO_PC(1);
}
@@ -733,6 +735,7 @@ DECLARE_INSTRUCTION(MULTU)
temp = (uint32_t) rrs * (uint64_t) ((uint32_t) rrt);
*r4300_mult_hi(r4300) = (int64_t) temp >> 32;
*r4300_mult_lo(r4300) = SE32(temp);
cp0_add_count(r4300, 2, 1);
ADD_TO_PC(1);
}
@@ -780,6 +783,7 @@ DECLARE_INSTRUCTION(DMULT)
if (!*r4300_mult_lo(r4300)) { (*r4300_mult_hi(r4300))++; }
else { *r4300_mult_lo(r4300) = ~*r4300_mult_lo(r4300) + 1; }
}
cp0_add_count(r4300, 4, 0);
ADD_TO_PC(1);
}
@@ -808,6 +812,7 @@ DECLARE_INSTRUCTION(DMULTU)
*r4300_mult_lo(r4300) = result1 | (result2 << 32);
*r4300_mult_hi(r4300) = (result3 & UINT64_C(0xFFFFFFFF)) | (result4 << 32);
cp0_add_count(r4300, 4, 0);
ADD_TO_PC(1);
}
@@ -832,6 +837,7 @@ DECLARE_INSTRUCTION(DIV)
*r4300_mult_lo(r4300) = rrs32 < 0 ? 1 : -1;
*r4300_mult_hi(r4300) = SE32(rrs32);
}
cp0_add_count(r4300, 18, 1);
ADD_TO_PC(1);
}
@@ -848,6 +854,7 @@ DECLARE_INSTRUCTION(DIVU)
*r4300_mult_lo(r4300) = -1;
*r4300_mult_hi(r4300) = SE32(rrs32);
}
cp0_add_count(r4300, 18, 1);
ADD_TO_PC(1);
}
@@ -872,6 +879,7 @@ DECLARE_INSTRUCTION(DDIV)
*r4300_mult_lo(r4300) = rrs < 0 ? 1 : -1;
*r4300_mult_hi(r4300) = rrs;
}
cp0_add_count(r4300, 34, 1);
ADD_TO_PC(1);
}
@@ -888,6 +896,7 @@ DECLARE_INSTRUCTION(DDIVU)
*r4300_mult_lo(r4300) = -1;
*r4300_mult_hi(r4300) = rrs;
}
cp0_add_count(r4300, 34, 1);
ADD_TO_PC(1);
}
@@ -959,6 +968,83 @@ DECLARE_JUMP(BC1TL, PCADDR + (iimmediate+1)*4, ((*r4300_cp1_fcr31(&r4300->cp1))
DECLARE_INSTRUCTION(CACHE)
{
DECLARE_R4300
uint32_t lslfaddr = (uint32_t) r4300_regs(r4300)[lfbase] + lfoffset;
if (r4300_translate_address(r4300, &lslfaddr, &(uint8_t){0}, 2, 0))
return; // TLB exception
uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0);
const unsigned char lslfft = lfft;
struct datacache *dcache_line = &r4300->mem->dcache[lslfaddr >> 4 & UINT32_C(0x1FF)];
struct instcache *icache_line = &r4300->mem->icache[lslfaddr >> 5 & UINT32_C(0x1FF)];
switch (lslfft)
{
case 0x00: //icache index invalidate
icache_line->valid = 0;
break;
case 0x04: //icache load tag
masked_write(&cp0_regs[CP0_TAGLO_REG], icache_line->valid << 7, UINT32_C(0x80));
masked_write(&cp0_regs[CP0_TAGLO_REG], 0, UINT32_C(0x40));
masked_write(&cp0_regs[CP0_TAGLO_REG], icache_line->tag >> 4, UINT32_C(0xFFFFF00));
break;
case 0x08: //icache store tag
icache_line->valid = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0x80)) >> 7;
icache_line->tag = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0xFFFFF00)) << 4;
break;
case 0x10: //icache hit invalidate
if(icache_hit(icache_line, lslfaddr))
icache_line->valid = 0;
break;
case 0x14: //icache fill
icache_fill(icache_line, r4300, lslfaddr);
break;
case 0x18: //icache hit write back
if(icache_hit(icache_line, lslfaddr))
icache_writeback(r4300, icache_line);
break;
case 0x01: //dcache index write back invalidate
if (dcache_line->dirty && dcache_line->valid)
dcache_writeback(r4300, dcache_line);
dcache_line->valid = 0;
break;
case 0x05: //dcache index load tag
masked_write(&cp0_regs[CP0_TAGLO_REG], dcache_line->valid << 7, UINT32_C(0x80));
masked_write(&cp0_regs[CP0_TAGLO_REG], dcache_line->dirty << 6, UINT32_C(0x40));
masked_write(&cp0_regs[CP0_TAGLO_REG], dcache_line->tag >> 4, UINT32_C(0xFFFFF00));
break;
case 0x09: //dcache index store tag
dcache_line->valid = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0x80)) >> 7;
dcache_line->dirty = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0x40)) >> 6;
dcache_line->tag = (cp0_regs[CP0_TAGLO_REG] & UINT32_C(0xFFFFF00)) << 4;
break;
case 0x0D: //dcache create dirty exclusive
if(!dcache_hit(dcache_line, lslfaddr) && dcache_line->dirty)
dcache_writeback(r4300, dcache_line);
dcache_line->tag = lslfaddr & ~UINT32_C(0xFFF);
dcache_line->valid = 1;
dcache_line->dirty = 1;
break;
case 0x11: //dcache hit invalidate
if(dcache_hit(dcache_line, lslfaddr))
{
dcache_line->valid = 0;
dcache_line->dirty = 0;
}
break;
case 0x15: //dcache hit write back invalidate
if(dcache_hit(dcache_line, lslfaddr))
{
if(dcache_line->dirty)
dcache_writeback(r4300, dcache_line);
dcache_line->valid = 0;
}
break;
case 0x19: //dcache hit write back
if(dcache_hit(dcache_line, lslfaddr))
{
if(dcache_line->dirty)
dcache_writeback(r4300, dcache_line);
}
break;
}
ADD_TO_PC(1);
}
@@ -968,7 +1054,6 @@ DECLARE_INSTRUCTION(ERET)
uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0);
int* cp0_cycle_count = r4300_cp0_cycle_count(&r4300->cp0);
cp0_update_count(r4300);
if (cp0_regs[CP0_STATUS_REG] & CP0_STATUS_ERL)
{
DebugMessage(M64MSG_ERROR, "error in ERET");
@@ -1191,8 +1276,7 @@ DECLARE_INSTRUCTION(TLBWR)
{
DECLARE_R4300
uint32_t* cp0_regs = r4300_cp0_regs(&r4300->cp0);
cp0_update_count(r4300);
cp0_regs[CP0_RANDOM_REG] = (cp0_regs[CP0_COUNT_REG]/r4300->cp0.count_per_op % (32 - cp0_regs[CP0_WIRED_REG]))
cp0_regs[CP0_RANDOM_REG] = (cp0_regs[CP0_COUNT_REG]/2 % (32 - cp0_regs[CP0_WIRED_REG]))
+ cp0_regs[CP0_WIRED_REG];
TLBWrite(r4300, cp0_regs[CP0_RANDOM_REG]);
ADD_TO_PC(1);
@@ -1217,12 +1301,10 @@ DECLARE_INSTRUCTION(MFC0)
switch(rfs)
{
case CP0_RANDOM_REG:
cp0_update_count(r4300);
cp0_regs[CP0_RANDOM_REG] = (cp0_regs[CP0_COUNT_REG]/r4300->cp0.count_per_op % (32 - cp0_regs[CP0_WIRED_REG]))
cp0_regs[CP0_RANDOM_REG] = (cp0_regs[CP0_COUNT_REG]/2 % (32 - cp0_regs[CP0_WIRED_REG]))
+ cp0_regs[CP0_WIRED_REG];
break;
case CP0_COUNT_REG:
cp0_update_count(r4300);
break;
}
rrt = SE32(cp0_regs[rfs]);
@@ -1267,7 +1349,6 @@ DECLARE_INSTRUCTION(MTC0)
case CP0_BADVADDR_REG:
break;
case CP0_COUNT_REG:
cp0_update_count(r4300);
r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_R4300;
if (*cp0_cycle_count >= 0) { gen_interrupt(r4300); }
r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_R4300;
@@ -1277,14 +1358,13 @@ DECLARE_INSTRUCTION(MTC0)
cp0_regs[CP0_ENTRYHI_REG] = rrt32 & UINT32_C(0xFFFFE0FF);
break;
case CP0_COMPARE_REG:
cp0_update_count(r4300);
remove_event(&r4300->cp0.q, COMPARE_INT);
/* Add count_per_op to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */
cp0_regs[CP0_COUNT_REG] += r4300->cp0.count_per_op;
*cp0_cycle_count += r4300->cp0.count_per_op;
/* Add 2 to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */
cp0_regs[CP0_COUNT_REG] += 2;
*cp0_cycle_count += 2;
add_interrupt_event_count(&r4300->cp0, COMPARE_INT, rrt32);
cp0_regs[CP0_COUNT_REG] -= r4300->cp0.count_per_op;
cp0_regs[CP0_COUNT_REG] -= 2;
/* Update next interrupt in case first event is COMPARE_INT */
*cp0_cycle_count = cp0_regs[CP0_COUNT_REG] - r4300->cp0.q.first->data.count;
@@ -1297,7 +1377,6 @@ DECLARE_INSTRUCTION(MTC0)
cp0_regs[CP0_STATUS_REG] = rrt32;
ADD_TO_PC(1);
cp0_update_count(r4300);
r4300_check_interrupt(r4300, CP0_CAUSE_IP2, r4300->mi->regs[MI_INTR_REG] & r4300->mi->regs[MI_INTR_MASK_REG]); // ???
r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_R4300;
if (*cp0_cycle_count >= 0) { gen_interrupt(r4300); }
@@ -1858,7 +1858,6 @@ void* ERET_new(void)
struct r4300_core* r4300 = &g_dev.r4300;
struct new_dynarec_hot_state* state = &r4300->new_dynarec_hot_state;
cp0_update_count(r4300);
if (state->cp0_regs[CP0_STATUS_REG] & CP0_STATUS_ERL)
{
DebugMessage(M64MSG_ERROR, "error in ERET");
@@ -1976,7 +1975,6 @@ static void TLBWR_new(int pcaddr, int count)
unsigned int i;
UPDATE_COUNT_IN
state->pcaddr = pcaddr;
cp0_update_count(r4300);
state->cp0_regs[CP0_RANDOM_REG] = (state->cp0_regs[CP0_COUNT_REG]/r4300->cp0.count_per_op % (32 - state->cp0_regs[CP0_WIRED_REG])) + state->cp0_regs[CP0_WIRED_REG];
/* Remove old entries */
unsigned int old_start_even=r4300->cp0.tlb.entries[state->cp0_regs[CP0_RANDOM_REG]&0x3F].start_even;
@@ -3021,7 +3019,6 @@ void dynarec_gen_interrupt(void)
{
struct r4300_core* r4300 = &g_dev.r4300;
struct new_dynarec_hot_state* state = &r4300->new_dynarec_hot_state;
cp0_update_count(r4300);
uint32_t page = ((state->cp0_regs[CP0_COUNT_REG]>>19)&0x1fc);
unsigned int *candidate = (unsigned int *)&restore_candidate[page];
page <<= 3;
@@ -59,7 +59,6 @@ static void InterpretOpcode(struct r4300_core* r4300);
r4300->interp_PC.addr += 4; \
r4300->delay_slot=1; \
InterpretOpcode(r4300); \
cp0_update_count(r4300); \
r4300->delay_slot=0; \
if (take_jump && !r4300->skip_jump) \
{ \
@@ -69,7 +68,6 @@ static void InterpretOpcode(struct r4300_core* r4300);
else \
{ \
r4300->interp_PC.addr += 8; \
cp0_update_count(r4300); \
} \
r4300->cp0.last_addr = r4300->interp_PC.addr; \
if (*r4300_cp0_cycle_count(&r4300->cp0) >= 0) gen_interrupt(r4300); \
@@ -82,7 +80,6 @@ static void InterpretOpcode(struct r4300_core* r4300);
if (cop1 && check_cop1_unusable(r4300)) return; \
if (take_jump) \
{ \
cp0_update_count(r4300); \
if(*cp0_cycle_count < 0) \
{ \
cp0_regs[CP0_COUNT_REG] -= *cp0_cycle_count; \
@@ -108,7 +105,7 @@ static void InterpretOpcode(struct r4300_core* r4300);
* relative to the instruction in the delay slot, so 1 instruction backwards
* (-1) goes back to the jump. */
#define IS_RELATIVE_IDLE_LOOP(r4300, op, addr) \
(IMM16S_OF(op) == -1 && *fast_mem_access((r4300), (addr) + 4) == 0)
(IMM16S_OF(op) == -1 && *fast_mem_access((r4300), (addr) + 4, 0) == 0)
/* Determines whether an absolute jump in a 26-bit immediate goes back to the
* same instruction without doing any work in its delay slot. The jump is
@@ -117,7 +114,7 @@ static void InterpretOpcode(struct r4300_core* r4300);
#define IS_ABSOLUTE_IDLE_LOOP(r4300, op, addr) \
(JUMP_OF(op) == ((addr) & UINT32_C(0x0FFFFFFF)) >> 2 \
&& ((addr) & UINT32_C(0x0FFFFFFF)) != UINT32_C(0x0FFFFFFC) \
&& *fast_mem_access((r4300), (addr) + 4) == 0)
&& *fast_mem_access((r4300), (addr) + 4, 0) == 0)
/* These macros parse opcode fields. */
#define rrt r4300_regs(r4300)[RT_OF(op)]
@@ -164,7 +161,7 @@ static void InterpretOpcode(struct r4300_core* r4300);
void InterpretOpcode(struct r4300_core* r4300)
{
uint32_t* op_address = fast_mem_access(r4300, *r4300_pc(r4300));
uint32_t* op_address = fast_mem_access(r4300, *r4300_pc(r4300), 1);
if (op_address == NULL)
return;
uint32_t op = *op_address;
+82 -60
View File
@@ -41,7 +41,7 @@
#include <time.h>
void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controller* mi, struct rdram* rdram, const struct interrupt_handler* interrupt_handlers,
unsigned int emumode, unsigned int count_per_op, unsigned int count_per_op_denom_pot, int no_compiled_jump, int randomize_interrupt, uint32_t start_address)
unsigned int emumode, int no_compiled_jump, int randomize_interrupt, uint32_t start_address)
{
struct new_dynarec_hot_state* new_dynarec_hot_state =
#ifdef NEW_DYNAREC
@@ -51,7 +51,7 @@ void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controll
#endif
r4300->emumode = emumode;
init_cp0(&r4300->cp0, count_per_op, count_per_op_denom_pot, new_dynarec_hot_state, interrupt_handlers);
init_cp0(&r4300->cp0, new_dynarec_hot_state, interrupt_handlers);
init_cp1(&r4300->cp1, new_dynarec_hot_state);
#ifndef NEW_DYNAREC
@@ -63,6 +63,7 @@ void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controll
r4300->rdram = rdram;
r4300->randomize_interrupt = randomize_interrupt;
r4300->start_address = start_address;
r4300->clock_rate = 93750000 / 2;
srand((unsigned int) time(NULL));
}
@@ -277,19 +278,38 @@ unsigned int get_r4300_emumode(struct r4300_core* r4300)
return r4300->emumode;
}
uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address)
uint8_t r4300_translate_address(struct r4300_core* r4300, uint32_t* address, uint8_t* cached, uint8_t tlb_mode, uint8_t write)
{
if ((*address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) {
if (write)
invalidate_r4300_cached_code(r4300, *address, write);
*address = virtual_to_physical_address(r4300, *address, tlb_mode, cached);
if (*address == 0) // TLB exception
return 1;
} else if (!(*address & UINT32_C(0x20000000)))
*cached = 1;
if (write)
{
invalidate_r4300_cached_code(r4300, *address, write);
invalidate_r4300_cached_code(r4300, *address ^ UINT32_C(0x20000000), write);
}
return 0;
}
uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address, uint8_t use_cache)
{
/* This code is performance critical, specially on pure interpreter mode.
* Removing error checking saves some time, but the emulator may crash. */
uint8_t cached = 0;
if (r4300_translate_address(r4300, &address, &cached, 2, 0))
return NULL; // TLB exception
if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) {
address = virtual_to_physical_address(r4300, address, 2);
if (address == 0) // TLB exception
return NULL;
}
if (use_cache && cached)
return icache_fetch(r4300, address);
if (use_cache && !cached)
cp0_add_count(r4300, 18, 1);
address &= UINT32_C(0x1ffffffc);
return mem_base_u32(r4300->mem->base, address);
}
@@ -299,17 +319,19 @@ uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address)
*/
int r4300_read_aligned_word(struct r4300_core* r4300, uint32_t address, uint32_t* value)
{
if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) {
address = virtual_to_physical_address(r4300, address, 0);
if (address == 0) {
return 0;
}
uint8_t cached = 0;
if (r4300_translate_address(r4300, &address, &cached, 0, 0))
return 0; // TLB exception
if (cached)
dcache_read32(r4300, address & ~UINT32_C(3), value);
else
{
cp0_add_count(r4300, 18, 1);
address &= UINT32_C(0x1ffffffc);
mem_read32(mem_get_handler(r4300->mem, address), address & ~UINT32_C(3), value);
}
address &= UINT32_C(0x1ffffffc);
mem_read32(mem_get_handler(r4300->mem, address), address & ~UINT32_C(3), value);
return 1;
}
@@ -317,6 +339,7 @@ int r4300_read_aligned_word(struct r4300_core* r4300, uint32_t address, uint32_t
int r4300_read_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_t* value)
{
uint32_t w[2];
uint8_t cached = 0;
/* XXX: unaligned dword accesses should trigger a address error,
* but inaccurate timing of the core can lead to unaligned address on reset
@@ -325,18 +348,22 @@ int r4300_read_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_
DebugMessage(M64MSG_WARNING, "Unaligned dword read %08x", address);
}
if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) {
address = virtual_to_physical_address(r4300, address, 0);
if (address == 0) {
return 0;
}
if (r4300_translate_address(r4300, &address, &cached, 0, 0))
return 0; // TLB exception
if (cached)
{
dcache_read32(r4300, address + 0, &w[0]);
dcache_read32(r4300, address + 4, &w[1]);
}
else
{
cp0_add_count(r4300, 18, 1);
address &= UINT32_C(0x1ffffffc);
const struct mem_handler* handler = mem_get_handler(r4300->mem, address);
mem_read32(handler, address + 0, &w[0]);
mem_read32(handler, address + 4, &w[1]);
}
address &= UINT32_C(0x1ffffffc);
const struct mem_handler* handler = mem_get_handler(r4300->mem, address);
mem_read32(handler, address + 0, &w[0]);
mem_read32(handler, address + 4, &w[1]);
*value = ((uint64_t)w[0] << 32) | w[1];
@@ -349,29 +376,26 @@ int r4300_read_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_
*/
int r4300_write_aligned_word(struct r4300_core* r4300, uint32_t address, uint32_t value, uint32_t mask)
{
if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) {
uint8_t cached = 0;
if (r4300_translate_address(r4300, &address, &cached, 1, 4))
return 0; // TLB exception
invalidate_r4300_cached_code(r4300, address, 4);
address = virtual_to_physical_address(r4300, address, 1);
if (address == 0) {
return 0;
}
if (cached)
dcache_write32(r4300, address & ~UINT32_C(3), value, mask);
else
{
cp0_add_count(r4300, 18, 1);
address &= UINT32_C(0x1ffffffc);
mem_write32(mem_get_handler(r4300->mem, address), address & ~UINT32_C(3), value, mask);
}
invalidate_r4300_cached_code(r4300, address, 4);
invalidate_r4300_cached_code(r4300, address ^ UINT32_C(0x20000000), 4);
address &= UINT32_C(0x1ffffffc);
mem_write32(mem_get_handler(r4300->mem, address), address & ~UINT32_C(3), value, mask);
return 1;
}
/* Write aligned dword to memory */
int r4300_write_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_t value, uint64_t mask)
{
uint8_t cached = 0;
/* XXX: unaligned dword accesses should trigger a address error,
* but inaccurate timing of the core can lead to unaligned address on reset
* so just emit a warning and keep going */
@@ -379,24 +403,22 @@ int r4300_write_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64
DebugMessage(M64MSG_WARNING, "Unaligned dword write %08x", address);
}
if ((address & UINT32_C(0xc0000000)) != UINT32_C(0x80000000)) {
if (r4300_translate_address(r4300, &address, &cached, 1, 8))
return 0; // TLB exception
invalidate_r4300_cached_code(r4300, address, 8);
address = virtual_to_physical_address(r4300, address, 1);
if (address == 0) {
return 0;
}
if (cached)
{
dcache_write32(r4300, address + 0, value >> 32, mask >> 32);
dcache_write32(r4300, address + 4, (uint32_t) value, (uint32_t) mask);
}
else
{
cp0_add_count(r4300, 18, 1);
address &= UINT32_C(0x1ffffffc);
const struct mem_handler* handler = mem_get_handler(r4300->mem, address);
mem_write32(handler, address + 0, value >> 32, mask >> 32);
mem_write32(handler, address + 4, (uint32_t) value, (uint32_t) mask);
}
invalidate_r4300_cached_code(r4300, address, 8);
invalidate_r4300_cached_code(r4300, address ^ UINT32_C(0x20000000), 8);
address &= UINT32_C(0x1ffffffc);
const struct mem_handler* handler = mem_get_handler(r4300->mem, address);
mem_write32(handler, address + 0, value >> 32, mask >> 32);
mem_write32(handler, address + 4, (uint32_t) value, (uint32_t) mask );
return 1;
}
@@ -197,6 +197,7 @@ struct r4300_core
uint32_t randomize_interrupt;
uint32_t start_address;
uint32_t clock_rate;
};
#define R4300_KSEG0 UINT32_C(0x80000000)
@@ -211,7 +212,7 @@ struct r4300_core
offsetof(struct new_dynarec_hot_state, regs))
#endif
void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controller* mi, struct rdram* rdram, const struct interrupt_handler* interrupt_handlers, unsigned int emumode, unsigned int count_per_op, unsigned int count_per_op_denom_pot, int no_compiled_jump, int randomize_interrupt, uint32_t start_address);
void init_r4300(struct r4300_core* r4300, struct memory* mem, struct mi_controller* mi, struct rdram* rdram, const struct interrupt_handler* interrupt_handlers, unsigned int emumode, int no_compiled_jump, int randomize_interrupt, uint32_t start_address);
void poweron_r4300(struct r4300_core* r4300);
void run_r4300(struct r4300_core* r4300);
@@ -229,7 +230,9 @@ unsigned int get_r4300_emumode(struct r4300_core* r4300);
/* Returns a pointer to a block of contiguous memory
* Can access RDRAM, SP_DMEM, SP_IMEM and ROM, using TLB if necessary
* Useful for getting fast access to a zone with executable code. */
uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address);
uint32_t *fast_mem_access(struct r4300_core* r4300, uint32_t address, uint8_t use_cache);
uint8_t r4300_translate_address(struct r4300_core* r4300, uint32_t* address, uint8_t* cached, uint8_t tlb_mode, uint8_t write);
int r4300_read_aligned_word(struct r4300_core* r4300, uint32_t address, uint32_t* value);
int r4300_read_aligned_dword(struct r4300_core* r4300, uint32_t address, uint64_t* value);
+2 -3
View File
@@ -578,7 +578,7 @@ void dynarec_init_block(struct r4300_core* r4300, uint32_t address)
r4300->cached_interp.invalid_code[b->start>>12] = 0;
if (b->end < UINT32_C(0x80000000) || b->start >= UINT32_C(0xc0000000))
{
uint32_t paddr = virtual_to_physical_address(r4300, b->start, 2);
uint32_t paddr = virtual_to_physical_address(r4300, b->start, 2, &(uint8_t){0});
r4300->cached_interp.invalid_code[paddr>>12] = 0;
dynarec_init_block(r4300, paddr);
@@ -655,7 +655,7 @@ void dynarec_recompile_block(struct r4300_core* r4300, const uint32_t* iw, struc
if (block_start_in_tlb)
{
uint32_t address2 = virtual_to_physical_address(r4300, r4300->recomp.dst->addr, 0);
uint32_t address2 = virtual_to_physical_address(r4300, r4300->recomp.dst->addr, 0, &(uint8_t){0});
if (r4300->cached_interp.blocks[address2>>12]->block[(address2&UINT32_C(0xFFF))/4].ops == r4300->cached_interp.not_compiled) {
r4300->cached_interp.blocks[address2>>12]->block[(address2&UINT32_C(0xFFF))/4].ops = r4300->cached_interp.not_compiled2;
}
@@ -923,7 +923,6 @@ int dynarec_check_cop1_unusable(void)
/* Parameterless version of cp0_update_count to ease usage in dynarec. */
void dynarec_cp0_update_count(void)
{
cp0_update_count(&g_dev.r4300);
}
/* Parameterless version of gen_interrupt to ease usage in dynarec. */
+33 -1
View File
@@ -34,6 +34,8 @@ void poweron_tlb(struct tlb* tlb)
memset(tlb->entries, 0, 32 * sizeof(tlb->entries[0]));
memset(tlb->LUT_r, 0, 0x100000 * sizeof(tlb->LUT_r[0]));
memset(tlb->LUT_w, 0, 0x100000 * sizeof(tlb->LUT_w[0]));
memset(tlb->r_cached, 0, 0x100000 * sizeof(tlb->r_cached[0]));
memset(tlb->w_cached, 0, 0x100000 * sizeof(tlb->w_cached[0]));
}
void tlb_unmap(struct tlb* tlb, size_t entry)
@@ -47,19 +49,31 @@ void tlb_unmap(struct tlb* tlb, size_t entry)
if (e->v_even)
{
for (i=e->start_even; i<e->end_even; i += 0x1000)
{
tlb->LUT_r[i>>12] = 0;
tlb->r_cached[i>>12] = 0;
}
if (e->d_even)
for (i=e->start_even; i<e->end_even; i += 0x1000)
{
tlb->LUT_w[i>>12] = 0;
tlb->w_cached[i>>12] = 0;
}
}
if (e->v_odd)
{
for (i=e->start_odd; i<e->end_odd; i += 0x1000)
{
tlb->LUT_r[i>>12] = 0;
tlb->r_cached[i>>12] = 0;
}
if (e->d_odd)
for (i=e->start_odd; i<e->end_odd; i += 0x1000)
{
tlb->LUT_w[i>>12] = 0;
tlb->w_cached[i>>12] = 0;
}
}
}
@@ -78,10 +92,16 @@ void tlb_map(struct tlb* tlb, size_t entry)
e->phys_even < 0x20000000)
{
for (i=e->start_even;i<e->end_even;i+=0x1000)
{
tlb->LUT_r[i>>12] = UINT32_C(0x80000000) | (e->phys_even + (i - e->start_even) + 0xFFF);
tlb->r_cached[i>>12] = e->c_even != 2;
}
if (e->d_even)
for (i=e->start_even;i<e->end_even;i+=0x1000)
{
tlb->LUT_w[i>>12] = UINT32_C(0x80000000) | (e->phys_even + (i - e->start_even) + 0xFFF);
tlb->w_cached[i>>12] = e->c_even != 2;
}
}
}
@@ -92,15 +112,21 @@ void tlb_map(struct tlb* tlb, size_t entry)
e->phys_odd < 0x20000000)
{
for (i=e->start_odd;i<e->end_odd;i+=0x1000)
{
tlb->LUT_r[i>>12] = UINT32_C(0x80000000) | (e->phys_odd + (i - e->start_odd) + 0xFFF);
tlb->r_cached[i>>12] = e->c_odd != 2;
}
if (e->d_odd)
for (i=e->start_odd;i<e->end_odd;i+=0x1000)
{
tlb->LUT_w[i>>12] = UINT32_C(0x80000000) | (e->phys_odd + (i - e->start_odd) + 0xFFF);
tlb->w_cached[i>>12] = e->c_odd != 2;
}
}
}
}
uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, int w)
uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, int w, uint8_t *cached)
{
const struct tlb* tlb = &r4300->cp0.tlb;
unsigned int addr = address >> 12;
@@ -130,12 +156,18 @@ uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address,
if (w == 1)
{
if (tlb->LUT_w[addr])
{
*cached = tlb->w_cached[addr];
return (tlb->LUT_w[addr] & UINT32_C(0xFFFFF000)) | (address & UINT32_C(0xFFF));
}
}
else
{
if (tlb->LUT_r[addr])
{
*cached = tlb->r_cached[addr];
return (tlb->LUT_r[addr] & UINT32_C(0xFFFFF000)) | (address & UINT32_C(0xFFF));
}
}
//printf("tlb exception !!! @ %x, %x, add:%x\n", address, w, r4300->pc->addr);
//getchar();
+3 -1
View File
@@ -57,6 +57,8 @@ struct tlb
struct tlb_entry entries[32];
uint32_t LUT_r[0x100000];
uint32_t LUT_w[0x100000];
uint8_t r_cached[0x100000];
uint8_t w_cached[0x100000];
};
void poweron_tlb(struct tlb* tlb);
@@ -64,6 +66,6 @@ void poweron_tlb(struct tlb* tlb);
void tlb_unmap(struct tlb* tlb, size_t entry);
void tlb_map(struct tlb* tlb, size_t entry);
uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, int w);
uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, int w, uint8_t *cached);
#endif /* M64P_DEVICE_R4300_TLB_H */
@@ -45,7 +45,6 @@ static uint32_t get_remaining_dma_length(struct ai_controller* ai)
if (ai->fifo[0].duration == 0)
return 0;
cp0_update_count(ai->mi->r4300);
next_ai_event = get_event(&ai->mi->r4300->cp0.q, AI_INT);
if (next_ai_event == NULL)
return 0;
@@ -64,9 +63,9 @@ static unsigned int get_dma_duration(struct ai_controller* ai)
{
unsigned int samples_per_sec = ai->vi->clock / (1 + ai->regs[AI_DACRATE_REG]);
unsigned int bytes_per_sample = 4; /* XXX: assume 16bit stereo - should depends on bitrate instead */
unsigned int cpu_counts_per_sec = ai->vi->delay == 0 ? ai->vi->clock : ai->vi->delay * ai->vi->expected_refresh_rate; /* estimate cpu counts/sec using VI */
unsigned int length = (ai->regs[AI_LEN_REG] & ~UINT32_C(7)) - 8;
return ai->regs[AI_LEN_REG] * (cpu_counts_per_sec / (bytes_per_sample * samples_per_sec));
return length * (ai->mi->r4300->clock_rate / (bytes_per_sample * samples_per_sec));
}
@@ -94,7 +93,6 @@ static void do_dma(struct ai_controller* ai, struct ai_dma* dma)
ai->delayed_carry = 0;
/* schedule end of dma event */
cp0_update_count(ai->mi->r4300);
add_interrupt_event(&ai->mi->r4300->cp0, AI_INT, dma->duration);
}
@@ -105,7 +105,6 @@ void write_mi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask
update_mi_intr_mask(&mi->regs[MI_INTR_MASK_REG], value & mask);
r4300_check_interrupt(mi->r4300, CP0_CAUSE_IP2, mi->regs[MI_INTR_REG] & mi->regs[MI_INTR_MASK_REG]);
cp0_update_count(mi->r4300);
if (*cp0_cycle_count >= 0) gen_interrupt(mi->r4300);
break;
}
@@ -48,6 +48,54 @@ int validate_pi_request(struct pi_controller* pi)
return 1;
}
static uint32_t dma_pi_calculate_cycles(struct pi_controller* pi, uint32_t length)
{
uint32_t cycles = 0;
uint8_t domain = 0;
uint32_t latency;
uint32_t pulse_width;
uint32_t release;
uint32_t page_size;
uint32_t pages;
if (pi->regs[PI_CART_ADDR_REG] >= 0x1FC04000 && pi->regs[PI_CART_ADDR_REG] < 0x80000000)
domain = 1;
else if (pi->regs[PI_CART_ADDR_REG] >= 0x10000000 && pi->regs[PI_CART_ADDR_REG] < 0x1FC00000)
domain = 1;
else if (pi->regs[PI_CART_ADDR_REG] >= 0x08000000 && pi->regs[PI_CART_ADDR_REG] < 0x10000000)
domain = 2;
else if (pi->regs[PI_CART_ADDR_REG] >= 0x06000000 && pi->regs[PI_CART_ADDR_REG] < 0x08000000)
domain = 1;
else if (pi->regs[PI_CART_ADDR_REG] >= 0x05000000 && pi->regs[PI_CART_ADDR_REG] < 0x06000000)
domain = 2;
else
{
DebugMessage(M64MSG_WARNING, "Unknown PI DMA domain: 0x%x", pi->regs[PI_CART_ADDR_REG]);
return length / 8;
}
if (domain == 1)
{
latency = pi->regs[PI_BSD_DOM1_LAT_REG] + 1;
pulse_width = pi->regs[PI_BSD_DOM1_PWD_REG] + 1;
release = pi->regs[PI_BSD_DOM1_RLS_REG] + 1;
page_size = 2 ^ (pi->regs[PI_BSD_DOM1_PGS_REG] + 2);
}
else if (domain == 2)
{
latency = pi->regs[PI_BSD_DOM2_LAT_REG] + 1;
pulse_width = pi->regs[PI_BSD_DOM2_PWD_REG] + 1;
release = pi->regs[PI_BSD_DOM2_RLS_REG] + 1;
page_size = 2 ^ (pi->regs[PI_BSD_DOM2_PGS_REG] + 2);
}
pages = length / page_size;
cycles += (14 + latency) * pages;
cycles += (pulse_width + release) * (length / 2);
cycles += 5 * pages;
cycles /= 2;
return cycles;
}
static void dma_pi_read(struct pi_controller* pi)
{
if (!validate_pi_request(pi))
@@ -73,7 +121,7 @@ static void dma_pi_read(struct pi_controller* pi)
/* PI seems to treat the first 128 bytes differently, see https://n64brew.dev/wiki/Peripheral_Interface#Unaligned_DMA_transfer */
if (length >= 0x7f && (length & 1))
length += 1;
unsigned int cycles = handler->dma_read(opaque, dram, dram_addr, cart_addr, length);
handler->dma_read(opaque, dram, dram_addr, cart_addr, length);
/* Mark DMA as busy */
pi->regs[PI_STATUS_REG] |= PI_STATUS_DMA_BUSY;
@@ -82,7 +130,7 @@ static void dma_pi_read(struct pi_controller* pi)
pi->regs[PI_CART_ADDR_REG] = (pi->regs[PI_CART_ADDR_REG] + length + 1) & ~1;
/* schedule end of dma interrupt event */
cp0_update_count(pi->mi->r4300);
uint32_t cycles = dma_pi_calculate_cycles(pi, length);
add_interrupt_event(&pi->mi->r4300->cp0, PI_INT, cycles);
}
@@ -111,7 +159,7 @@ static void dma_pi_write(struct pi_controller* pi)
length += 1;
if (length <= 0x80)
length -= dram_addr & 0x7;
unsigned int cycles = handler->dma_write(opaque, dram, dram_addr, cart_addr, length);
handler->dma_write(opaque, dram, dram_addr, cart_addr, length);
post_framebuffer_write(&pi->dp->fb, dram_addr, length);
@@ -122,7 +170,7 @@ static void dma_pi_write(struct pi_controller* pi)
pi->regs[PI_CART_ADDR_REG] = (pi->regs[PI_CART_ADDR_REG] + length + 1) & ~1;
/* schedule end of dma interrupt event */
cp0_update_count(pi->mi->r4300);
uint32_t cycles = dma_pi_calculate_cycles(pi, length);
add_interrupt_event(&pi->mi->r4300->cp0, PI_INT, cycles);
}
@@ -146,6 +194,12 @@ void init_pi(struct pi_controller* pi,
void poweron_pi(struct pi_controller* pi)
{
memset(pi->regs, 0, PI_REGS_COUNT*sizeof(uint32_t));
pi->regs[PI_BSD_DOM1_LAT_REG] = 0xFF;
pi->regs[PI_BSD_DOM1_PWD_REG] = 0xFF;
pi->regs[PI_BSD_DOM1_PGS_REG] = 0x03;
pi->regs[PI_BSD_DOM2_LAT_REG] = 0xFF;
pi->regs[PI_BSD_DOM2_PWD_REG] = 0xFF;
pi->regs[PI_BSD_DOM2_PGS_REG] = 0x03;
}
void read_pi_regs(void* opaque, uint32_t address, uint32_t* value)
@@ -66,8 +66,8 @@ enum
struct pi_dma_handler
{
unsigned int (*dma_read)(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
unsigned int (*dma_write)(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void (*dma_read)(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
void (*dma_write)(void* opaque, uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length);
};
typedef void (*pi_dma_handler_getter)(struct cart* cart, struct dd_controller* dd, uint32_t address, void** opaque, const struct pi_dma_handler** handler);
+10 -10
View File
@@ -80,8 +80,7 @@ static void do_sp_dma(struct rsp_core* sp, const struct sp_dma* dma)
}
/* schedule end of dma event */
cp0_update_count(sp->mi->r4300);
add_interrupt_event(&sp->mi->r4300->cp0, RSP_DMA_EVT, (count * length) / 8);
add_interrupt_event(&sp->mi->r4300->cp0, RSP_DMA_EVT, ((count * length) / 16) + 4);
}
static void fifo_push(struct rsp_core* sp, uint32_t dir)
@@ -312,6 +311,7 @@ void do_SP_Task(struct rsp_core* sp)
uint32_t save_pc = sp->regs2[SP_PC_REG] & ~0xfff;
uint32_t sp_delay_time;
uint32_t saved_status = sp->regs[SP_STATUS_REG];
if (sp->mem[0xfc0/4] == 1)
{
@@ -335,11 +335,10 @@ void do_SP_Task(struct rsp_core* sp)
if (sp->dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_FREEZE) {
sp->dp->do_on_unfreeze |= DELAY_DP_INT;
} else {
cp0_update_count(sp->mi->r4300);
add_interrupt_event(&sp->mi->r4300->cp0, DP_INT, 4000);
}
}
sp_delay_time = 1000;
sp_delay_time = 4000;
protect_framebuffers(&sp->dp->fb);
}
@@ -356,7 +355,7 @@ void do_SP_Task(struct rsp_core* sp)
#endif
sp->regs2[SP_PC_REG] |= save_pc;
sp_delay_time = 4000;
sp_delay_time = 8000;
}
else
{
@@ -367,7 +366,6 @@ void do_SP_Task(struct rsp_core* sp)
sp_delay_time = 0;
}
cp0_update_count(sp->mi->r4300);
if (sp->mi->regs[MI_INTR_REG] & MI_INTR_SP)
{
add_interrupt_event(&sp->mi->r4300->cp0, SP_INT, sp_delay_time);
@@ -388,16 +386,18 @@ void do_SP_Task(struct rsp_core* sp)
add_interrupt_event(&sp->mi->r4300->cp0, RSP_TSK_EVT, sp_delay_time);
sp->mi->r4300->cp0.interrupt_unsafe_state |= INTR_UNSAFE_RSP_TASK;
}
sp->rsp_status = sp->regs[SP_STATUS_REG] & (SP_STATUS_BROKE | SP_STATUS_HALT);
sp->regs[SP_STATUS_REG] &= ~(SP_STATUS_BROKE | SP_STATUS_HALT);
sp->rsp_status = sp->regs[SP_STATUS_REG];
if (sp->regs[SP_STATUS_REG] & (SP_STATUS_HALT | SP_STATUS_BROKE))
{
sp->regs[SP_STATUS_REG] = saved_status;
}
}
void rsp_interrupt_event(void* opaque)
{
struct rsp_core* sp = (struct rsp_core*)opaque;
sp->regs[SP_STATUS_REG] |= sp->rsp_status;
sp->regs[SP_STATUS_REG] = sp->rsp_status;
sp->rsp_status = 0;
sp->mi->r4300->cp0.interrupt_unsafe_state &= ~INTR_UNSAFE_RSP;
raise_rcp_interrupt(sp->mi, MI_INTR_SP);
@@ -80,7 +80,6 @@ static void dma_si_write(struct si_controller* si)
copy_pif_rdram(si);
cp0_update_count(si->mi->r4300);
si->regs[SI_STATUS_REG] |= SI_STATUS_DMA_BUSY;
add_interrupt_event(&si->mi->r4300->cp0, SI_INT, si->dma_duration + add_random_interrupt_time(si->mi->r4300));
}
@@ -94,7 +93,6 @@ static void dma_si_read(struct si_controller* si)
update_pif_ram(si->pif);
cp0_update_count(si->mi->r4300);
si->regs[SI_STATUS_REG] |= SI_STATUS_DMA_BUSY;
add_interrupt_event(&si->mi->r4300->cp0, SI_INT, si->dma_duration + add_random_interrupt_time(si->mi->r4300));
}
@@ -174,14 +172,3 @@ void si_end_of_dma_event(void* opaque)
si->regs[SI_STATUS_REG] |= SI_STATUS_INTERRUPT;
raise_rcp_interrupt(si->mi, MI_INTR_SI);
}
void si_dynamic_dma_duration(struct si_controller* si)
{
/* try to keep controller polling to 1 per VI */
if (si->pif->update_counter > 1)
si->dma_duration += 1000;
else if (si->pif->update_counter < 1 && si->dma_duration > 0x900)
si->dma_duration -= 1000;
si->pif->update_counter = 0;
}
@@ -89,6 +89,4 @@ void write_si_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask
void si_end_of_dma_event(void* opaque);
void si_dynamic_dma_duration(struct si_controller* si);
#endif
@@ -61,7 +61,6 @@ void set_vi_vertical_interrupt(struct vi_controller* vi)
{
if (!get_event(&vi->mi->r4300->cp0.q, VI_INT) && (vi->regs[VI_V_INTR_REG] < vi->regs[VI_V_SYNC_REG]))
{
cp0_update_count(vi->mi->r4300);
add_interrupt_event(&vi->mi->r4300->cp0, VI_INT, vi->delay);
}
}
@@ -80,7 +79,7 @@ void poweron_vi(struct vi_controller* vi)
{
memset(vi->regs, 0, VI_REGS_COUNT*sizeof(uint32_t));
vi->field = 0;
vi->delay = 0;
vi->delay = vi->mi->r4300->clock_rate / vi->expected_refresh_rate;
vi->count_per_scanline = 0;
}
@@ -94,7 +93,6 @@ void read_vi_regs(void* opaque, uint32_t address, uint32_t* value)
{
uint32_t* next_vi = get_event(&vi->mi->r4300->cp0.q, VI_INT);
if (next_vi != NULL) {
cp0_update_count(vi->mi->r4300);
vi->regs[VI_CURRENT_REG] = (vi->delay - (*next_vi - cp0_regs[CP0_COUNT_REG])) / vi->count_per_scanline;
/* wrap around VI_CURRENT_REG if needed */
@@ -140,8 +138,7 @@ void write_vi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask
if ((vi->regs[VI_V_SYNC_REG] & mask) != (value & mask))
{
masked_write(&vi->regs[VI_V_SYNC_REG], value, mask);
vi->count_per_scanline = (vi->clock / vi->expected_refresh_rate) / (vi->regs[VI_V_SYNC_REG] + 1);
vi->delay = (vi->regs[VI_V_SYNC_REG] + 1) * vi->count_per_scanline;
vi->count_per_scanline = (vi->mi->r4300->clock_rate / vi->expected_refresh_rate) / (vi->regs[VI_V_SYNC_REG] + 1);
set_vi_vertical_interrupt(vi);
}
return;
@@ -165,7 +162,6 @@ void vi_vertical_interrupt_event(void* opaque)
/* allow main module to do things on VI event */
new_vi();
si_dynamic_dma_duration(vi->si);
/* toggle vi field if in interlaced mode */
vi->field ^= (vi->regs[VI_STATUS_REG] >> 6) & 0x1;
+2 -14
View File
@@ -347,8 +347,6 @@ int main_set_core_defaults(void)
#endif
ConfigSetDefaultBool(g_CoreConfig, "NoCompiledJump", 0, "Disable compiled jump commands in dynamic recompiler (should be set to False) ");
ConfigSetDefaultBool(g_CoreConfig, "DisableExtraMem", 0, "Disable 4MB expansion RAM pack. May be necessary for some games");
ConfigSetDefaultInt(g_CoreConfig, "CountPerOp", 0, "Force number of cycles per emulated instruction");
ConfigSetDefaultInt(g_CoreConfig, "CountPerOpDenomPot", 0, "Reduce number of cycles per update by power of two when set greater than 0 (overclock)");
ConfigSetDefaultBool(g_CoreConfig, "AutoStateSlotIncrement", 0, "Increment the save state slot after each save operation");
ConfigSetDefaultInt(g_CoreConfig, "CurrentStateSlot", 0, "Save state slot (0-9) to use when saving/loading the emulator state");
ConfigSetDefaultBool(g_CoreConfig, "EnableDebugger", 0, "Activate the R4300 debugger when ROM execution begins, if core was built with Debugger support");
@@ -1474,8 +1472,6 @@ m64p_error main_run(void)
{
size_t i, k;
size_t rdram_size;
uint32_t count_per_op;
uint32_t count_per_op_denom_pot;
uint32_t emumode;
uint32_t disable_extra_mem;
int32_t si_dma_duration;
@@ -1523,8 +1519,6 @@ m64p_error main_run(void)
no_compiled_jump = ConfigGetParamBool(g_CoreConfig, "NoCompiledJump");
//We disable any randomness for netplay
randomize_interrupt = !netplay_is_init() ? ConfigGetParamBool(g_CoreConfig, "RandomizeInterrupt") : 0;
count_per_op = ConfigGetParamInt(g_CoreConfig, "CountPerOp");
count_per_op_denom_pot = ConfigGetParamInt(g_CoreConfig, "CountPerOpDenomPot");
if (ROM_SETTINGS.disableextramem)
disable_extra_mem = ROM_SETTINGS.disableextramem;
@@ -1534,18 +1528,14 @@ m64p_error main_run(void)
rdram_size = (disable_extra_mem == 0) ? 0x800000 : 0x400000;
if (count_per_op <= 0)
count_per_op = ROM_SETTINGS.countperop;
if (count_per_op_denom_pot > 11)
count_per_op_denom_pot = 11;
si_dma_duration = ConfigGetParamInt(g_CoreConfig, "SiDmaDuration");
if (si_dma_duration < 0)
si_dma_duration = ROM_SETTINGS.sidmaduration;
rsp_delay_time = ROM_SETTINGS.rspdelaytime;
uint32_t count_per_op; //UNUSED
uint32_t count_per_op_denom_pot; //UNUSED
//During netplay, player 1 is the source of truth for these settings
netplay_sync_settings(&count_per_op, &count_per_op_denom_pot, &disable_extra_mem, &si_dma_duration, &emumode, &no_compiled_jump, &rsp_delay_time);
@@ -1789,8 +1779,6 @@ m64p_error main_run(void)
init_device(&g_dev,
g_mem_base,
emumode,
count_per_op,
count_per_op_denom_pot,
no_compiled_jump,
randomize_interrupt,
g_start_address,
+2 -22
View File
@@ -46,12 +46,10 @@
#define CHUNKSIZE 1024*128 /* Read files 128KB at a time. */
/* Number of cpu cycles per instruction */
enum { DEFAULT_COUNT_PER_OP = 2 };
/* by default, extra mem is enabled */
enum { DEFAULT_DISABLE_EXTRA_MEM = 0 };
/* Default SI DMA duration */
enum { DEFAULT_SI_DMA_DURATION = 0x900 };
enum { DEFAULT_SI_DMA_DURATION = 0x3000 };
/* Default AI DMA modifier */
enum { DEFAULT_AI_DMA_MODIFIER = 100 };
/* Default RSP delay time */
@@ -189,7 +187,6 @@ m64p_error open_rom(const unsigned char* romimage, unsigned int size)
ROM_SETTINGS.transferpak = entry->transferpak;
ROM_SETTINGS.mempak = entry->mempak;
ROM_SETTINGS.biopak = entry->biopak;
ROM_SETTINGS.countperop = entry->countperop;
ROM_SETTINGS.disableextramem = entry->disableextramem;
ROM_SETTINGS.sidmaduration = entry->sidmaduration;
ROM_SETTINGS.aidmamodifier = entry->aidmamodifier;
@@ -208,7 +205,6 @@ m64p_error open_rom(const unsigned char* romimage, unsigned int size)
ROM_SETTINGS.transferpak = 0;
ROM_SETTINGS.mempak = 1;
ROM_SETTINGS.biopak = 0;
ROM_SETTINGS.countperop = DEFAULT_COUNT_PER_OP;
ROM_SETTINGS.disableextramem = DEFAULT_DISABLE_EXTRA_MEM;
ROM_SETTINGS.sidmaduration = DEFAULT_SI_DMA_DURATION;
ROM_SETTINGS.aidmamodifier = DEFAULT_AI_DMA_MODIFIER;
@@ -338,12 +334,6 @@ static size_t romdatabase_resolve_round(void)
entry->entry.set_flags |= ROMDATABASE_ENTRY_RUMBLE;
}
if (!isset_bitmask(entry->entry.set_flags, ROMDATABASE_ENTRY_COUNTEROP) &&
isset_bitmask(ref->set_flags, ROMDATABASE_ENTRY_COUNTEROP)) {
entry->entry.countperop = ref->countperop;
entry->entry.set_flags |= ROMDATABASE_ENTRY_COUNTEROP;
}
if (!isset_bitmask(entry->entry.set_flags, ROMDATABASE_ENTRY_CHEATS) &&
isset_bitmask(ref->set_flags, ROMDATABASE_ENTRY_CHEATS)) {
if (ref->cheats)
@@ -482,7 +472,6 @@ void romdatabase_open(void)
search->entry.savetype = SAVETYPE_EEPROM_4K;
search->entry.players = 4;
search->entry.rumble = 1;
search->entry.countperop = DEFAULT_COUNT_PER_OP;
search->entry.disableextramem = DEFAULT_DISABLE_EXTRA_MEM;
search->entry.cheats = NULL;
search->entry.transferpak = 0;
@@ -598,15 +587,6 @@ void romdatabase_open(void)
DebugMessage(M64MSG_WARNING, "ROM Database: Invalid rumble string on line %i", lineno);
}
}
else if(!strcmp(l.name, "CountPerOp"))
{
if (string_to_int(l.value, &value) && value > 0 && value <= 4) {
search->entry.countperop = value;
search->entry.set_flags |= ROMDATABASE_ENTRY_COUNTEROP;
} else {
DebugMessage(M64MSG_WARNING, "ROM Database: Invalid CountPerOp on line %i", lineno);
}
}
else if (!strcmp(l.name, "DisableExtraMem"))
{
search->entry.disableextramem = atoi(l.value);
@@ -680,7 +660,7 @@ void romdatabase_open(void)
}
else if(!strcmp(l.name, "SiDmaDuration"))
{
if (string_to_int(l.value, &value) && value >= 0 && value <= 0x10000) {
if (string_to_int(l.value, &value) && value >= 0 && value <= 0x30000) {
search->entry.sidmaduration = value;
search->entry.set_flags |= ROMDATABASE_ENTRY_SIDMADURATION;
} else {
-2
View File
@@ -107,7 +107,6 @@ typedef struct
unsigned char savetype;
unsigned char players; /* Local players 0-4, 2/3/4 way Netplay indicated by 5/6/7. */
unsigned char rumble; /* 0 - No, 1 - Yes boolean for rumble support. */
unsigned char countperop;
unsigned char disableextramem;
unsigned char transferpak; /* 0 - No, 1 - Yes boolean for transferpak support. */
unsigned char mempak; /* 0 - No, 1 - Yes boolean for mempak support. */
@@ -125,7 +124,6 @@ typedef struct
#define ROMDATABASE_ENTRY_SAVETYPE BIT(3)
#define ROMDATABASE_ENTRY_PLAYERS BIT(4)
#define ROMDATABASE_ENTRY_RUMBLE BIT(5)
#define ROMDATABASE_ENTRY_COUNTEROP BIT(6)
#define ROMDATABASE_ENTRY_CHEATS BIT(7)
#define ROMDATABASE_ENTRY_EXTRAMEM BIT(8)
#define ROMDATABASE_ENTRY_TRANSFERPAK BIT(9)