Switched from lazyusf to lazyusf2
This commit is contained in:
parent
24730bdfa2
commit
4d8ec1960f
233 changed files with 61579 additions and 7949 deletions
File diff suppressed because it is too large
Load diff
240
Frameworks/lazyusf/lazyusf/ai/ai_controller.c
Normal file
240
Frameworks/lazyusf/lazyusf/ai/ai_controller.c
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - ai_controller.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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 "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "ai_controller.h"
|
||||||
|
|
||||||
|
#include "main/rom.h"
|
||||||
|
#include "memory/memory.h"
|
||||||
|
#include "r4300/cp0.h"
|
||||||
|
#include "r4300/r4300_core.h"
|
||||||
|
#include "r4300/interupt.h"
|
||||||
|
#include "ri/ri_controller.h"
|
||||||
|
#include "vi/vi_controller.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Clang complains that 0x80000000 is too large for enumerators, which it says must be 'int' */
|
||||||
|
static const uint32_t AI_STATUS_BUSY = 0x40000000;
|
||||||
|
static const uint32_t AI_STATUS_FULL = 0x80000000;
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t get_remaining_dma_length(struct ai_controller* ai)
|
||||||
|
{
|
||||||
|
unsigned int next_ai_event;
|
||||||
|
unsigned int remaining_dma_duration;
|
||||||
|
|
||||||
|
if (ai->fifo[0].duration == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
update_count(ai->r4300->state);
|
||||||
|
next_ai_event = get_event(ai->r4300->state, AI_INT);
|
||||||
|
if (next_ai_event == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
remaining_dma_duration = next_ai_event - ai->r4300->state->g_cp0_regs[CP0_COUNT_REG];
|
||||||
|
|
||||||
|
if (remaining_dma_duration >= 0x80000000)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (uint32_t)((uint64_t)remaining_dma_duration * ai->fifo[0].length / ai->fifo[0].duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int get_dma_duration(struct ai_controller* ai)
|
||||||
|
{
|
||||||
|
unsigned int samples_per_sec = ai->r4300->state->ROM_PARAMS.aidacrate / (1 + ai->regs[AI_DACRATE_REG]);
|
||||||
|
|
||||||
|
return (uint32_t)(((uint64_t)ai->regs[AI_LEN_REG]*ai->vi->delay*ai->r4300->state->ROM_PARAMS.vilimit)
|
||||||
|
/ (4 * samples_per_sec));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void do_dma(struct ai_controller* ai, const struct ai_dma* dma)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
fprintf(ai->r4300->state->debug_log, "Audio DMA push: %d %d\n", dma->address, dma->length);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* lazy initialization of sample format */
|
||||||
|
if (ai->samples_format_changed)
|
||||||
|
{
|
||||||
|
unsigned int frequency = (ai->regs[AI_DACRATE_REG] == 0)
|
||||||
|
? 44100
|
||||||
|
: ai->r4300->state->ROM_PARAMS.aidacrate / (1 + ai->regs[AI_DACRATE_REG]);
|
||||||
|
|
||||||
|
unsigned int bits = (ai->regs[AI_BITRATE_REG] == 0)
|
||||||
|
? 16
|
||||||
|
: 1 + ai->regs[AI_BITRATE_REG];
|
||||||
|
|
||||||
|
set_audio_format(ai, frequency, bits);
|
||||||
|
|
||||||
|
ai->samples_format_changed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* push audio samples to external sink */
|
||||||
|
push_audio_samples(ai, &ai->ri->rdram.dram[dma->address/4], dma->length);
|
||||||
|
|
||||||
|
/* schedule end of dma event */
|
||||||
|
update_count(ai->r4300->state);
|
||||||
|
if (!(ai->regs[AI_STATUS_REG] & AI_STATUS_FULL))
|
||||||
|
{
|
||||||
|
remove_event(ai->r4300->state, AI_INT);
|
||||||
|
add_interupt_event(ai->r4300->state, AI_INT, ai->r4300->state->g_delay_ai ? dma->duration : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ai_fifo_queue_int(struct ai_controller* ai)
|
||||||
|
{
|
||||||
|
add_interupt_event(ai->r4300->state, AI_INT, ai->r4300->state->g_delay_ai ? get_dma_duration(ai) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fifo_push(struct ai_controller* ai)
|
||||||
|
{
|
||||||
|
unsigned int duration = get_dma_duration(ai);
|
||||||
|
|
||||||
|
if (ai->regs[AI_STATUS_REG] & AI_STATUS_BUSY)
|
||||||
|
{
|
||||||
|
ai->fifo[1].address = ai->regs[AI_DRAM_ADDR_REG];
|
||||||
|
ai->fifo[1].length = ai->regs[AI_LEN_REG];
|
||||||
|
ai->fifo[1].duration = duration;
|
||||||
|
|
||||||
|
if (ai->r4300->state->enableFIFOfull)
|
||||||
|
ai->regs[AI_STATUS_REG] |= AI_STATUS_FULL;
|
||||||
|
else
|
||||||
|
do_dma(ai, &ai->fifo[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ai->fifo[0].address = ai->regs[AI_DRAM_ADDR_REG];
|
||||||
|
ai->fifo[0].length = ai->regs[AI_LEN_REG];
|
||||||
|
ai->fifo[0].duration = duration;
|
||||||
|
ai->regs[AI_STATUS_REG] |= AI_STATUS_BUSY;
|
||||||
|
|
||||||
|
do_dma(ai, &ai->fifo[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fifo_pop(struct ai_controller* ai)
|
||||||
|
{
|
||||||
|
if (ai->regs[AI_STATUS_REG] & AI_STATUS_FULL)
|
||||||
|
{
|
||||||
|
ai->fifo[0].address = ai->fifo[1].address;
|
||||||
|
ai->fifo[0].length = ai->fifo[1].length;
|
||||||
|
ai->fifo[0].duration = ai->fifo[1].duration;
|
||||||
|
ai->regs[AI_STATUS_REG] &= ~AI_STATUS_FULL;
|
||||||
|
|
||||||
|
do_dma(ai, &ai->fifo[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ai->regs[AI_STATUS_REG] &= ~AI_STATUS_BUSY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void set_audio_format(struct ai_controller* ai, unsigned int frequency, unsigned int bits)
|
||||||
|
{
|
||||||
|
ai->set_audio_format(ai->user_data, frequency, bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_audio_samples(struct ai_controller* ai, const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
ai->push_audio_samples(ai->user_data, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void connect_ai(struct ai_controller* ai,
|
||||||
|
struct r4300_core* r4300,
|
||||||
|
struct ri_controller* ri,
|
||||||
|
struct vi_controller* vi)
|
||||||
|
{
|
||||||
|
ai->r4300 = r4300;
|
||||||
|
ai->ri = ri;
|
||||||
|
ai->vi = vi;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_ai(struct ai_controller* ai)
|
||||||
|
{
|
||||||
|
memset(ai->regs, 0, AI_REGS_COUNT*sizeof(uint32_t));
|
||||||
|
memset(ai->fifo, 0, 2*sizeof(struct ai_dma));
|
||||||
|
ai->samples_format_changed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_ai_regs(void* opaque, uint32_t address, uint32_t* value)
|
||||||
|
{
|
||||||
|
struct ai_controller* ai = (struct ai_controller*)opaque;
|
||||||
|
uint32_t reg = ai_reg(address);
|
||||||
|
|
||||||
|
if (reg == AI_LEN_REG)
|
||||||
|
{
|
||||||
|
*value = get_remaining_dma_length(ai);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*value = ai->regs[reg];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_ai_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
|
||||||
|
{
|
||||||
|
struct ai_controller* ai = (struct ai_controller*)opaque;
|
||||||
|
uint32_t reg = ai_reg(address);
|
||||||
|
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case AI_LEN_REG:
|
||||||
|
masked_write(&ai->regs[AI_LEN_REG], value, mask);
|
||||||
|
fifo_push(ai);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case AI_STATUS_REG:
|
||||||
|
clear_rcp_interrupt(ai->r4300, MI_INTR_AI);
|
||||||
|
ai->r4300->mi.AudioIntrReg &= ~MI_INTR_AI;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case AI_BITRATE_REG:
|
||||||
|
case AI_DACRATE_REG:
|
||||||
|
/* lazy audio format setting */
|
||||||
|
if ((ai->regs[reg]) != (value & mask))
|
||||||
|
ai->samples_format_changed = 1;
|
||||||
|
|
||||||
|
masked_write(&ai->regs[reg], value, mask);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
masked_write(&ai->regs[reg], value, mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ai_end_of_dma_event(struct ai_controller* ai)
|
||||||
|
{
|
||||||
|
fifo_pop(ai);
|
||||||
|
ai->r4300->mi.AudioIntrReg |= MI_INTR_AI;
|
||||||
|
raise_rcp_interrupt(ai->r4300, MI_INTR_AI);
|
||||||
|
}
|
||||||
|
|
91
Frameworks/lazyusf/lazyusf/ai/ai_controller.h
Normal file
91
Frameworks/lazyusf/lazyusf/ai/ai_controller.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - ai_controller.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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_AI_AI_CONTROLLER_H
|
||||||
|
#define M64P_AI_AI_CONTROLLER_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
struct r4300_core;
|
||||||
|
struct ri_controller;
|
||||||
|
struct vi_controller;
|
||||||
|
|
||||||
|
enum ai_registers
|
||||||
|
{
|
||||||
|
AI_DRAM_ADDR_REG,
|
||||||
|
AI_LEN_REG,
|
||||||
|
AI_CONTROL_REG,
|
||||||
|
AI_STATUS_REG,
|
||||||
|
AI_DACRATE_REG,
|
||||||
|
AI_BITRATE_REG,
|
||||||
|
AI_REGS_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ai_dma
|
||||||
|
{
|
||||||
|
uint32_t address;
|
||||||
|
uint32_t length;
|
||||||
|
unsigned int duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ai_controller
|
||||||
|
{
|
||||||
|
uint32_t regs[AI_REGS_COUNT];
|
||||||
|
struct ai_dma fifo[2];
|
||||||
|
unsigned int samples_format_changed;
|
||||||
|
|
||||||
|
/* external speaker output */
|
||||||
|
void* user_data;
|
||||||
|
void (*set_audio_format)(void*,unsigned int, unsigned int);
|
||||||
|
void (*push_audio_samples)(void*,const void*,size_t);
|
||||||
|
|
||||||
|
struct r4300_core* r4300;
|
||||||
|
struct ri_controller* ri;
|
||||||
|
struct vi_controller* vi;
|
||||||
|
};
|
||||||
|
|
||||||
|
static osal_inline uint32_t ai_reg(uint32_t address)
|
||||||
|
{
|
||||||
|
return (address & 0xffff) >> 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is for enablefifofull */
|
||||||
|
void ai_fifo_queue_int(struct ai_controller* ai);
|
||||||
|
|
||||||
|
void set_audio_format(struct ai_controller* ai, unsigned int frequency, unsigned int bits);
|
||||||
|
void push_audio_samples(struct ai_controller* ai, const void* buffer, size_t size);
|
||||||
|
|
||||||
|
void connect_ai(struct ai_controller* ai,
|
||||||
|
struct r4300_core* r4300,
|
||||||
|
struct ri_controller* ri,
|
||||||
|
struct vi_controller* vi);
|
||||||
|
|
||||||
|
void init_ai(struct ai_controller* ai);
|
||||||
|
|
||||||
|
int read_ai_regs(void* opaque, uint32_t address, uint32_t* value);
|
||||||
|
int write_ai_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
|
||||||
|
|
||||||
|
void ai_end_of_dma_event(struct ai_controller* ai);
|
||||||
|
|
||||||
|
#endif
|
70
Frameworks/lazyusf/lazyusf/api/api_export.ver
Normal file
70
Frameworks/lazyusf/lazyusf/api/api_export.ver
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
{ global:
|
||||||
|
ConfigDeleteSection;
|
||||||
|
ConfigGetParamBool;
|
||||||
|
ConfigGetParameter;
|
||||||
|
ConfigGetParameterHelp;
|
||||||
|
ConfigGetParameterType;
|
||||||
|
ConfigGetParamFloat;
|
||||||
|
ConfigGetParamInt;
|
||||||
|
ConfigGetParamString;
|
||||||
|
ConfigGetSharedDataFilepath;
|
||||||
|
ConfigGetUserCachePath;
|
||||||
|
ConfigGetUserConfigPath;
|
||||||
|
ConfigGetUserDataPath;
|
||||||
|
ConfigHasUnsavedChanges;
|
||||||
|
ConfigListParameters;
|
||||||
|
ConfigListSections;
|
||||||
|
ConfigOpenSection;
|
||||||
|
ConfigRevertChanges;
|
||||||
|
ConfigSaveFile;
|
||||||
|
ConfigSaveSection;
|
||||||
|
ConfigSetDefaultBool;
|
||||||
|
ConfigSetDefaultFloat;
|
||||||
|
ConfigSetDefaultInt;
|
||||||
|
ConfigSetDefaultString;
|
||||||
|
ConfigSetParameter;
|
||||||
|
ConfigSetParameterHelp;
|
||||||
|
CoreAddCheat;
|
||||||
|
CoreAttachPlugin;
|
||||||
|
CoreCheatEnabled;
|
||||||
|
CoreDetachPlugin;
|
||||||
|
CoreDoCommand;
|
||||||
|
CoreErrorMessage;
|
||||||
|
CoreGetAPIVersions;
|
||||||
|
CoreGetRomSettings;
|
||||||
|
CoreOverrideVidExt;
|
||||||
|
CoreShutdown;
|
||||||
|
CoreStartup;
|
||||||
|
DebugBreakpointCommand;
|
||||||
|
DebugBreakpointLookup;
|
||||||
|
DebugDecodeOp;
|
||||||
|
DebugGetCPUDataPtr;
|
||||||
|
DebugGetState;
|
||||||
|
DebugMemGetMemInfo;
|
||||||
|
DebugMemGetPointer;
|
||||||
|
DebugMemGetRecompInfo;
|
||||||
|
DebugMemRead16;
|
||||||
|
DebugMemRead32;
|
||||||
|
DebugMemRead64;
|
||||||
|
DebugMemRead8;
|
||||||
|
DebugMemWrite16;
|
||||||
|
DebugMemWrite32;
|
||||||
|
DebugMemWrite64;
|
||||||
|
DebugMemWrite8;
|
||||||
|
DebugSetCallbacks;
|
||||||
|
DebugSetCoreCompare;
|
||||||
|
DebugSetRunState;
|
||||||
|
DebugStep;
|
||||||
|
PluginGetVersion;
|
||||||
|
VidExt_GL_GetProcAddress;
|
||||||
|
VidExt_GL_SetAttribute;
|
||||||
|
VidExt_GL_GetAttribute;
|
||||||
|
VidExt_GL_SwapBuffers;
|
||||||
|
VidExt_Init;
|
||||||
|
VidExt_ListFullscreenModes;
|
||||||
|
VidExt_Quit;
|
||||||
|
VidExt_SetCaption;
|
||||||
|
VidExt_SetVideoMode;
|
||||||
|
VidExt_ToggleFullScreen;
|
||||||
|
VidExt_ResizeWindow;
|
||||||
|
local: *; };
|
77
Frameworks/lazyusf/lazyusf/api/callbacks.c
Normal file
77
Frameworks/lazyusf/lazyusf/api/callbacks.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus-core - api/callbacks.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2009 Richard Goedeken *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* This file contains the Core functions for handling callbacks to the
|
||||||
|
* front-end application
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "m64p_types.h"
|
||||||
|
#include "callbacks.h"
|
||||||
|
|
||||||
|
void DebugMessage(usf_state_t * state, int level, const char *message, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
1 ||
|
||||||
|
#endif
|
||||||
|
level > 1 )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
char buffer[1024];
|
||||||
|
va_start(args, message);
|
||||||
|
vsprintf(buffer, message, args);
|
||||||
|
va_end(args);
|
||||||
|
fprintf(state->debug_log, "%s\n", buffer);
|
||||||
|
if ( level > 1 )
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen( state->error_message );
|
||||||
|
|
||||||
|
if ( len )
|
||||||
|
state->error_message[ len++ ] = '\n';
|
||||||
|
|
||||||
|
va_start(args, message);
|
||||||
|
#if _MSC_VER >= 1300
|
||||||
|
vsprintf_s(state->error_message + len, 16384 - len, message, args);
|
||||||
|
#else
|
||||||
|
vsprintf(state->error_message + len, message, args);
|
||||||
|
#endif
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
state->last_error = state->error_message;
|
||||||
|
state->stop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
41
Frameworks/lazyusf/lazyusf/api/callbacks.h
Normal file
41
Frameworks/lazyusf/lazyusf/api/callbacks.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus-core - api/callbacks.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2009 Richard Goedeken *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* This file contains the definitions for callback functions which will be
|
||||||
|
* called from the other Core modules
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(API_CALLBACKS_H)
|
||||||
|
#define API_CALLBACKS_H
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "m64p_types.h"
|
||||||
|
#include "m64p_frontend.h"
|
||||||
|
|
||||||
|
/* Functions for use by the Core, to send information back to the front-end app */
|
||||||
|
extern m64p_error SetDebugCallback(usf_state_t *, ptr_DebugCallback pFunc, void *Context);
|
||||||
|
extern m64p_error SetStateCallback(usf_state_t *, ptr_StateCallback pFunc, void *Context);
|
||||||
|
extern void DebugMessage(usf_state_t *, int level, const char *message, ...);
|
||||||
|
extern void StateChanged(usf_state_t *, m64p_core_param param_type, int new_value);
|
||||||
|
|
||||||
|
#endif /* API_CALLBACKS_H */
|
||||||
|
|
90
Frameworks/lazyusf/lazyusf/api/m64p_common.h
Normal file
90
Frameworks/lazyusf/lazyusf/api/m64p_common.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus-core - m64p_common.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2009 Richard Goedeken *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* This header file defines typedefs for function pointers to common Core
|
||||||
|
* and plugin functions, for use by the front-end and plugin modules to attach
|
||||||
|
* to the dynamic libraries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(M64P_COMMON_H)
|
||||||
|
#define M64P_COMMON_H
|
||||||
|
|
||||||
|
#include "m64p_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* PluginGetVersion()
|
||||||
|
*
|
||||||
|
* This function retrieves version information from a library. This
|
||||||
|
* function is the same for the core library and the plugins.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_PluginGetVersion)(m64p_plugin_type *, int *, int *, const char **, int *);
|
||||||
|
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *, int *, int *, const char **, int *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreGetAPIVersions()
|
||||||
|
*
|
||||||
|
* This function retrieves API version information from the core.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreGetAPIVersions)(int *, int *, int *, int *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreGetAPIVersions(int *, int *, int *, int *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreErrorMessage()
|
||||||
|
*
|
||||||
|
* This function returns a pointer to a NULL-terminated string giving a
|
||||||
|
* human-readable description of the error.
|
||||||
|
*/
|
||||||
|
typedef const char * (*ptr_CoreErrorMessage)(m64p_error);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT const char * CALL CoreErrorMessage(m64p_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* PluginStartup()
|
||||||
|
*
|
||||||
|
* This function initializes a plugin for use by allocating memory, creating
|
||||||
|
* data structures, and loading the configuration data.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_PluginStartup)(m64p_dynlib_handle, void *, void (*)(void *, int, const char *));
|
||||||
|
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle, void *, void (*)(void *, int, const char *));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* PluginShutdown()
|
||||||
|
*
|
||||||
|
* This function destroys data structures and releases memory allocated by
|
||||||
|
* the plugin library.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_PluginShutdown)(void);
|
||||||
|
#if defined(M64P_PLUGIN_PROTOTYPES) || defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL PluginShutdown(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* #define M64P_COMMON_H */
|
||||||
|
|
252
Frameworks/lazyusf/lazyusf/api/m64p_config.h
Normal file
252
Frameworks/lazyusf/lazyusf/api/m64p_config.h
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus-core - m64p_config.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2009 Richard Goedeken *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* This header file defines typedefs for function pointers to the Core's
|
||||||
|
* configuration handling functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(M64P_CONFIG_H)
|
||||||
|
#define M64P_CONFIG_H
|
||||||
|
|
||||||
|
#include "m64p_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigListSections()
|
||||||
|
*
|
||||||
|
* This function is called to enumerate the list of Sections in the Mupen64Plus
|
||||||
|
* configuration file. It is expected that there will be a section named "Core"
|
||||||
|
* for core-specific configuration data, "Graphics" for common graphics options,
|
||||||
|
* and one or more sections for each plugin library.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigListSections)(void *, void (*)(void *, const char *));
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigListSections(void *, void (*)(void *, const char *));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigOpenSection()
|
||||||
|
*
|
||||||
|
* This function is used to give a configuration section handle to the front-end
|
||||||
|
* which may be used to read or write configuration parameter values in a given
|
||||||
|
* section of the configuration file.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigOpenSection)(const char *, m64p_handle *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigOpenSection(const char *, m64p_handle *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigListParameters()
|
||||||
|
*
|
||||||
|
* This function is called to enumerate the list of Parameters in a given
|
||||||
|
* Section of the Mupen64Plus configuration file.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigListParameters)(m64p_handle, void *, void (*)(void *, const char *, m64p_type));
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigListParameters(m64p_handle, void *, void (*)(void *, const char *, m64p_type));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigSaveFile()
|
||||||
|
*
|
||||||
|
* This function saves the entire current Mupen64Plus configuration to disk.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigSaveFile)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigSaveFile(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigSaveSection()
|
||||||
|
*
|
||||||
|
* This function saves one section of the current Mupen64Plus configuration to disk.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigSaveSection)(const char *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigSaveSection(const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigHasUnsavedChanges()
|
||||||
|
*
|
||||||
|
* This function determines if a given Section (or all sections) of the Mupen64Plus Core configuration file has been modified since it was last saved or loaded.
|
||||||
|
*/
|
||||||
|
typedef int (*ptr_ConfigHasUnsavedChanges)(const char *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT int CALL ConfigHasUnsavedChanges(const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigDeleteSection()
|
||||||
|
*
|
||||||
|
* This function deletes a section from the Mupen64Plus configuration data.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigDeleteSection)(const char *SectionName);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigDeleteSection(const char *SectionName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigRevertChanges()
|
||||||
|
*
|
||||||
|
* This function reverts changes previously made to one section of the configuration file, so that it will match with the configuration at the last time that it was loaded from or saved to disk.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigRevertChanges)(const char *SectionName);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigRevertChanges(const char *SectionName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigSetParameter()
|
||||||
|
*
|
||||||
|
* This function sets the value of one of the emulator's configuration
|
||||||
|
* parameters.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigSetParameter)(m64p_handle, const char *, m64p_type, const void *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigSetParameter(m64p_handle, const char *, m64p_type, const void *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigSetParameterHelp()
|
||||||
|
*
|
||||||
|
* This function sets the help string of one of the emulator's configuration
|
||||||
|
* parameters.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigSetParameterHelp)(m64p_handle, const char *, const char *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigSetParameterHelp(m64p_handle, const char *, const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigGetParameter()
|
||||||
|
*
|
||||||
|
* This function retrieves the value of one of the emulator's parameters.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigGetParameter)(m64p_handle, const char *, m64p_type, void *, int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigGetParameter(m64p_handle, const char *, m64p_type, void *, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigGetParameterType()
|
||||||
|
*
|
||||||
|
* This function retrieves the type of one of the emulator's parameters.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigGetParameterType)(m64p_handle, const char *, m64p_type *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigGetParameterType(m64p_handle, const char *, m64p_type *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigGetParameterHelp()
|
||||||
|
*
|
||||||
|
* This function retrieves the help information about one of the emulator's
|
||||||
|
* parameters.
|
||||||
|
*/
|
||||||
|
typedef const char * (*ptr_ConfigGetParameterHelp)(m64p_handle, const char *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT const char * CALL ConfigGetParameterHelp(m64p_handle, const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigSetDefault***()
|
||||||
|
*
|
||||||
|
* These functions are used to set the value of a configuration parameter if it
|
||||||
|
* is not already present in the configuration file. This may happen if a new
|
||||||
|
* user runs the emulator, or an upgraded module uses a new parameter, or the
|
||||||
|
* user deletes his or her configuration file. If the parameter is already
|
||||||
|
* present in the given section of the configuration file, then no action will
|
||||||
|
* be taken and this function will return successfully.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_ConfigSetDefaultInt)(m64p_handle, const char *, int, const char *);
|
||||||
|
typedef m64p_error (*ptr_ConfigSetDefaultFloat)(m64p_handle, const char *, float, const char *);
|
||||||
|
typedef m64p_error (*ptr_ConfigSetDefaultBool)(m64p_handle, const char *, int, const char *);
|
||||||
|
typedef m64p_error (*ptr_ConfigSetDefaultString)(m64p_handle, const char *, const char *, const char *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL ConfigSetDefaultInt(m64p_handle, const char *, int, const char *);
|
||||||
|
EXPORT m64p_error CALL ConfigSetDefaultFloat(m64p_handle, const char *, float, const char *);
|
||||||
|
EXPORT m64p_error CALL ConfigSetDefaultBool(m64p_handle, const char *, int, const char *);
|
||||||
|
EXPORT m64p_error CALL ConfigSetDefaultString(m64p_handle, const char *, const char *, const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigGetParam***()
|
||||||
|
*
|
||||||
|
* These functions retrieve the value of one of the emulator's parameters in
|
||||||
|
* the given section, and return the value directly to the calling function. If
|
||||||
|
* an errors occurs (such as an invalid Section handle, or invalid
|
||||||
|
* configuration parameter name), then an error will be sent to the front-end
|
||||||
|
* via the DebugCallback() function, and either a 0 (zero) or an empty string
|
||||||
|
* will be returned.
|
||||||
|
*/
|
||||||
|
typedef int (*ptr_ConfigGetParamInt)(m64p_handle, const char *);
|
||||||
|
typedef float (*ptr_ConfigGetParamFloat)(m64p_handle, const char *);
|
||||||
|
typedef int (*ptr_ConfigGetParamBool)(m64p_handle, const char *);
|
||||||
|
typedef const char * (*ptr_ConfigGetParamString)(m64p_handle, const char *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT int CALL ConfigGetParamInt(m64p_handle, const char *);
|
||||||
|
EXPORT float CALL ConfigGetParamFloat(m64p_handle, const char *);
|
||||||
|
EXPORT int CALL ConfigGetParamBool(m64p_handle, const char *);
|
||||||
|
EXPORT const char * CALL ConfigGetParamString(m64p_handle, const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigGetSharedDataFilepath()
|
||||||
|
*
|
||||||
|
* This function is provided to allow a plugin to retrieve a full pathname to a
|
||||||
|
* given shared data file. This type of file is intended to be shared among
|
||||||
|
* multiple users on a system, so it is likely to be read-only.
|
||||||
|
*/
|
||||||
|
typedef const char * (*ptr_ConfigGetSharedDataFilepath)(const char *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT const char * CALL ConfigGetSharedDataFilepath(const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigGetUserConfigPath()
|
||||||
|
*
|
||||||
|
* This function may be used by the plugins or front-end to get a path to the
|
||||||
|
* directory for storing user-specific configuration files. This will be the
|
||||||
|
* directory where "mupen64plus.cfg" is located.
|
||||||
|
*/
|
||||||
|
typedef const char * (*ptr_ConfigGetUserConfigPath)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT const char * CALL ConfigGetUserConfigPath(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigGetUserDataPath()
|
||||||
|
*
|
||||||
|
* This function may be used by the plugins or front-end to get a path to the
|
||||||
|
* directory for storing user-specific data files. This may be used to store
|
||||||
|
* files such as screenshots, saved game states, or hi-res textures.
|
||||||
|
*/
|
||||||
|
typedef const char * (*ptr_ConfigGetUserDataPath)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT const char * CALL ConfigGetUserDataPath(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ConfigGetUserCachePath()
|
||||||
|
*
|
||||||
|
* This function may be used by the plugins or front-end to get a path to the
|
||||||
|
* directory for storing cached user-specific data files. Files in this
|
||||||
|
* directory may be deleted by the user to save space, so critical information
|
||||||
|
* should not be stored here. This directory may be used to store files such
|
||||||
|
* as the ROM browser cache.
|
||||||
|
*/
|
||||||
|
typedef const char * (*ptr_ConfigGetUserCachePath)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT const char * CALL ConfigGetUserCachePath(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* #define M64P_CONFIG_H */
|
||||||
|
|
202
Frameworks/lazyusf/lazyusf/api/m64p_debugger.h
Normal file
202
Frameworks/lazyusf/lazyusf/api/m64p_debugger.h
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus-core - m64p_debugger.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2009 Richard Goedeken *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* This header file defines typedefs for function pointers to Core Debugger
|
||||||
|
* functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(M64P_DEBUGGER_H)
|
||||||
|
#define M64P_DEBUGGER_H
|
||||||
|
|
||||||
|
#include "m64p_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugSetCallbacks()
|
||||||
|
*
|
||||||
|
* This function is called by the front-end to supply debugger callback
|
||||||
|
* function pointers. If debugger is enabled and then later disabled within the
|
||||||
|
* UI, this function may be called with NULL pointers in order to disable the
|
||||||
|
* callbacks.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_DebugSetCallbacks)(void (*)(void), void (*)(unsigned int), void (*)(void));
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL DebugSetCallbacks(void (*)(void), void (*)(unsigned int), void (*)(void));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugSetCoreCompare()
|
||||||
|
*
|
||||||
|
* This function is called by the front-end to supply callback function pointers
|
||||||
|
* for the Core Comparison feature.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_DebugSetCoreCompare)(void (*)(unsigned int), void (*)(int, void *));
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL DebugSetCoreCompare(void (*)(unsigned int), void (*)(int, void *));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugSetRunState()
|
||||||
|
*
|
||||||
|
* This function sets the run state of the R4300 CPU emulator.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_DebugSetRunState)(m64p_dbg_runstate);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL DebugSetRunState(m64p_dbg_runstate);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugGetState()
|
||||||
|
*
|
||||||
|
* This function reads and returns a debugger state variable, which are
|
||||||
|
* enumerated in m64p_types.h.
|
||||||
|
*/
|
||||||
|
typedef int (*ptr_DebugGetState)(m64p_dbg_state);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT int CALL DebugGetState(m64p_dbg_state);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugStep()
|
||||||
|
*
|
||||||
|
* This function signals the debugger to advance one instruction when in the
|
||||||
|
* stepping mode.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_DebugStep)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL DebugStep(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugDecodeOp()
|
||||||
|
*
|
||||||
|
* This is a helper function for the debugger front-end. This instruction takes
|
||||||
|
* a PC value and an R4300 instruction opcode and writes the disassembled
|
||||||
|
* instruction mnemonic and arguments into character buffers. This is intended
|
||||||
|
* to be used to display disassembled code.
|
||||||
|
*/
|
||||||
|
typedef void (*ptr_DebugDecodeOp)(unsigned int, char *, char *, int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT void CALL DebugDecodeOp(unsigned int, char *, char *, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugMemGetRecompInfo()
|
||||||
|
*
|
||||||
|
* This function is used by the front-end to retrieve disassembly information
|
||||||
|
* about recompiled code. For example, the dynamic recompiler may take a single
|
||||||
|
* R4300 instruction and compile it into 10 x86 instructions. This function may
|
||||||
|
* then be used to retrieve the disassembled code of the 10 x86 instructions.
|
||||||
|
*/
|
||||||
|
typedef void * (*ptr_DebugMemGetRecompInfo)(m64p_dbg_mem_info, unsigned int, int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT void * CALL DebugMemGetRecompInfo(m64p_dbg_mem_info, unsigned int, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugMemGetMemInfo()
|
||||||
|
*
|
||||||
|
* This function returns an integer value regarding the memory location address,
|
||||||
|
* corresponding to the information requested by mem_info_type, which is a type
|
||||||
|
* enumerated in m64p_types.h.
|
||||||
|
*/
|
||||||
|
typedef int (*ptr_DebugMemGetMemInfo)(m64p_dbg_mem_info, unsigned int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT int CALL DebugMemGetMemInfo(m64p_dbg_mem_info, unsigned int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugMemGetPointer()
|
||||||
|
*
|
||||||
|
* This function returns a memory pointer (in x86 memory space) to a block of
|
||||||
|
* emulated N64 memory. This may be used to retrieve a pointer to a special N64
|
||||||
|
* block (such as the serial, video, or audio registers) or the RDRAM.
|
||||||
|
*/
|
||||||
|
typedef void * (*ptr_DebugMemGetPointer)(m64p_dbg_memptr_type);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT void * CALL DebugMemGetPointer(m64p_dbg_memptr_type);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugMemRead**()
|
||||||
|
*
|
||||||
|
* These functions retrieve a value from the emulated N64 memory. The returned
|
||||||
|
* value will be correctly byte-swapped for the host architecture.
|
||||||
|
*/
|
||||||
|
typedef unsigned long long (*ptr_DebugMemRead64)(unsigned int);
|
||||||
|
typedef unsigned int (*ptr_DebugMemRead32)(unsigned int);
|
||||||
|
typedef unsigned short (*ptr_DebugMemRead16)(unsigned int);
|
||||||
|
typedef unsigned char (*ptr_DebugMemRead8)(unsigned int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT unsigned long long CALL DebugMemRead64(unsigned int);
|
||||||
|
EXPORT unsigned int CALL DebugMemRead32(unsigned int);
|
||||||
|
EXPORT unsigned short CALL DebugMemRead16(unsigned int);
|
||||||
|
EXPORT unsigned char CALL DebugMemRead8(unsigned int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugMemWrite**()
|
||||||
|
*
|
||||||
|
* These functions write a value into the emulated N64 memory. The given value
|
||||||
|
* will be correctly byte-swapped before storage.
|
||||||
|
*/
|
||||||
|
typedef void (*ptr_DebugMemWrite64)(unsigned int, unsigned long long);
|
||||||
|
typedef void (*ptr_DebugMemWrite32)(unsigned int, unsigned int);
|
||||||
|
typedef void (*ptr_DebugMemWrite16)(unsigned int, unsigned short);
|
||||||
|
typedef void (*ptr_DebugMemWrite8)(unsigned int, unsigned char);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT void CALL DebugMemWrite64(unsigned int, unsigned long long);
|
||||||
|
EXPORT void CALL DebugMemWrite32(unsigned int, unsigned int);
|
||||||
|
EXPORT void CALL DebugMemWrite16(unsigned int, unsigned short);
|
||||||
|
EXPORT void CALL DebugMemWrite8(unsigned int, unsigned char);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugGetCPUDataPtr()
|
||||||
|
*
|
||||||
|
* This function returns a memory pointer (in x86 memory space) to a specific
|
||||||
|
* register in the emulated R4300 CPU.
|
||||||
|
*/
|
||||||
|
typedef void * (*ptr_DebugGetCPUDataPtr)(m64p_dbg_cpu_data);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT void * CALL DebugGetCPUDataPtr(m64p_dbg_cpu_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugBreakpointLookup()
|
||||||
|
*
|
||||||
|
* This function searches through all current breakpoints in the debugger to
|
||||||
|
* find one that matches the given input parameters. If a matching breakpoint
|
||||||
|
* is found, the index number is returned. If no breakpoints are found, -1 is
|
||||||
|
* returned.
|
||||||
|
*/
|
||||||
|
typedef int (*ptr_DebugBreakpointLookup)(unsigned int, unsigned int, unsigned int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT int CALL DebugBreakpointLookup(unsigned int, unsigned int, unsigned int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DebugBreakpointCommand()
|
||||||
|
*
|
||||||
|
* This function is used to process common breakpoint commands, such as adding,
|
||||||
|
* removing, or searching the breakpoints. The meanings of the index and ptr
|
||||||
|
* input parameters vary by command.
|
||||||
|
*/
|
||||||
|
typedef int (*ptr_DebugBreakpointCommand)(m64p_dbg_bkp_command, unsigned int, m64p_breakpoint *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT int CALL DebugBreakpointCommand(m64p_dbg_bkp_command, unsigned int, m64p_breakpoint *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* #define M64P_DEBUGGER_H */
|
||||||
|
|
141
Frameworks/lazyusf/lazyusf/api/m64p_frontend.h
Normal file
141
Frameworks/lazyusf/lazyusf/api/m64p_frontend.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus-core - m64p_frontend.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2009 Richard Goedeken *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* This header file defines typedefs for function pointers to Core functions
|
||||||
|
* designed for use by the front-end user interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(M64P_FRONTEND_H)
|
||||||
|
#define M64P_FRONTEND_H
|
||||||
|
|
||||||
|
#include "m64p_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* pointer types to the callback functions in the front-end application */
|
||||||
|
typedef void (*ptr_DebugCallback)(void *Context, int level, const char *message);
|
||||||
|
typedef void (*ptr_StateCallback)(void *Context, m64p_core_param param_type, int new_value);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT void CALL DebugCallback(void *Context, int level, const char *message);
|
||||||
|
EXPORT void CALL StateCallback(void *Context, m64p_core_param param_type, int new_value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreStartup()
|
||||||
|
*
|
||||||
|
* This function initializes libmupen64plus for use by allocating memory,
|
||||||
|
* creating data structures, and loading the configuration file.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreStartup)(int, const char *, const char *, void *, ptr_DebugCallback, void *, ptr_StateCallback);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreStartup(int, const char *, const char *, void *, ptr_DebugCallback, void *, ptr_StateCallback);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreShutdown()
|
||||||
|
*
|
||||||
|
* This function saves the configuration file, then destroys data structures
|
||||||
|
* and releases memory allocated by the core library.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreShutdown)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreShutdown(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreAttachPlugin()
|
||||||
|
*
|
||||||
|
* This function attaches the given plugin to the emulator core. There can only
|
||||||
|
* be one plugin of each type attached to the core at any given time.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreAttachPlugin)(m64p_plugin_type, m64p_dynlib_handle);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreAttachPlugin(m64p_plugin_type, m64p_dynlib_handle);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreDetachPlugin()
|
||||||
|
*
|
||||||
|
* This function detaches the given plugin from the emulator core, and re-attaches
|
||||||
|
* the 'dummy' plugin functions.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreDetachPlugin)(m64p_plugin_type);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreDetachPlugin(m64p_plugin_type);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreDoCommand()
|
||||||
|
*
|
||||||
|
* This function sends a command to the emulator core.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreDoCommand)(m64p_command, int, void *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreDoCommand(m64p_command, int, void *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreOverrideVidExt()
|
||||||
|
*
|
||||||
|
* This function overrides the core's internal SDL-based OpenGL functions. This
|
||||||
|
* override functionality allows a front-end to define its own video extension
|
||||||
|
* functions to be used instead of the SDL functions. If any of the function
|
||||||
|
* pointers in the structure are NULL, the override function will be disabled
|
||||||
|
* and the core's internal SDL functions will be used.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreOverrideVidExt)(m64p_video_extension_functions *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreOverrideVidExt(m64p_video_extension_functions *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreAddCheat()
|
||||||
|
*
|
||||||
|
* This function will add a Cheat Function to a list of currently active cheats
|
||||||
|
* which are applied to the open ROM.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreAddCheat)(const char *, m64p_cheat_code *, int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreAddCheat(const char *, m64p_cheat_code *, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreCheatEnabled()
|
||||||
|
*
|
||||||
|
* This function will enable or disable a Cheat Function which is in the list of
|
||||||
|
* currently active cheats.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreCheatEnabled)(const char *, int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreCheatEnabled(const char *, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CoreGetRomSettings()
|
||||||
|
*
|
||||||
|
* This function will retrieve the ROM settings from the mupen64plus INI file for
|
||||||
|
* the ROM image corresponding to the given CRC values.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_CoreGetRomSettings)(m64p_rom_settings *, int, int, int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL CoreGetRomSettings(m64p_rom_settings *, int, int, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* #define M64P_FRONTEND_H */
|
||||||
|
|
273
Frameworks/lazyusf/lazyusf/api/m64p_plugin.h
Normal file
273
Frameworks/lazyusf/lazyusf/api/m64p_plugin.h
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus-core - m64p_plugin.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* Copyright (C) 2009 Richard Goedeken *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#if !defined(M64P_PLUGIN_H)
|
||||||
|
#define M64P_PLUGIN_H
|
||||||
|
|
||||||
|
#include "m64p_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*** Controller plugin's ****/
|
||||||
|
#define PLUGIN_NONE 1
|
||||||
|
#define PLUGIN_MEMPAK 2
|
||||||
|
#define PLUGIN_RUMBLE_PAK 3 /* not implemented for non raw data */
|
||||||
|
#define PLUGIN_TRANSFER_PAK 4 /* not implemented for non raw data */
|
||||||
|
#define PLUGIN_RAW 5 /* the controller plugin is passed in raw data */
|
||||||
|
|
||||||
|
/***** Structures *****/
|
||||||
|
typedef struct {
|
||||||
|
unsigned char * RDRAM;
|
||||||
|
unsigned char * DMEM;
|
||||||
|
unsigned char * IMEM;
|
||||||
|
|
||||||
|
unsigned int * MI_INTR_REG;
|
||||||
|
|
||||||
|
unsigned int * SP_MEM_ADDR_REG;
|
||||||
|
unsigned int * SP_DRAM_ADDR_REG;
|
||||||
|
unsigned int * SP_RD_LEN_REG;
|
||||||
|
unsigned int * SP_WR_LEN_REG;
|
||||||
|
unsigned int * SP_STATUS_REG;
|
||||||
|
unsigned int * SP_DMA_FULL_REG;
|
||||||
|
unsigned int * SP_DMA_BUSY_REG;
|
||||||
|
unsigned int * SP_PC_REG;
|
||||||
|
unsigned int * SP_SEMAPHORE_REG;
|
||||||
|
|
||||||
|
unsigned int * DPC_START_REG;
|
||||||
|
unsigned int * DPC_END_REG;
|
||||||
|
unsigned int * DPC_CURRENT_REG;
|
||||||
|
unsigned int * DPC_STATUS_REG;
|
||||||
|
unsigned int * DPC_CLOCK_REG;
|
||||||
|
unsigned int * DPC_BUFBUSY_REG;
|
||||||
|
unsigned int * DPC_PIPEBUSY_REG;
|
||||||
|
unsigned int * DPC_TMEM_REG;
|
||||||
|
|
||||||
|
void (*CheckInterrupts)(void);
|
||||||
|
void (*ProcessDlistList)(void);
|
||||||
|
void (*ProcessAlistList)(void);
|
||||||
|
void (*ProcessRdpList)(void);
|
||||||
|
void (*ShowCFB)(void);
|
||||||
|
} RSP_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char * HEADER; /* This is the rom header (first 40h bytes of the rom) */
|
||||||
|
unsigned char * RDRAM;
|
||||||
|
unsigned char * DMEM;
|
||||||
|
unsigned char * IMEM;
|
||||||
|
|
||||||
|
unsigned int * MI_INTR_REG;
|
||||||
|
|
||||||
|
unsigned int * DPC_START_REG;
|
||||||
|
unsigned int * DPC_END_REG;
|
||||||
|
unsigned int * DPC_CURRENT_REG;
|
||||||
|
unsigned int * DPC_STATUS_REG;
|
||||||
|
unsigned int * DPC_CLOCK_REG;
|
||||||
|
unsigned int * DPC_BUFBUSY_REG;
|
||||||
|
unsigned int * DPC_PIPEBUSY_REG;
|
||||||
|
unsigned int * DPC_TMEM_REG;
|
||||||
|
|
||||||
|
unsigned int * VI_STATUS_REG;
|
||||||
|
unsigned int * VI_ORIGIN_REG;
|
||||||
|
unsigned int * VI_WIDTH_REG;
|
||||||
|
unsigned int * VI_INTR_REG;
|
||||||
|
unsigned int * VI_V_CURRENT_LINE_REG;
|
||||||
|
unsigned int * VI_TIMING_REG;
|
||||||
|
unsigned int * VI_V_SYNC_REG;
|
||||||
|
unsigned int * VI_H_SYNC_REG;
|
||||||
|
unsigned int * VI_LEAP_REG;
|
||||||
|
unsigned int * VI_H_START_REG;
|
||||||
|
unsigned int * VI_V_START_REG;
|
||||||
|
unsigned int * VI_V_BURST_REG;
|
||||||
|
unsigned int * VI_X_SCALE_REG;
|
||||||
|
unsigned int * VI_Y_SCALE_REG;
|
||||||
|
|
||||||
|
void (*CheckInterrupts)(void);
|
||||||
|
} GFX_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char * RDRAM;
|
||||||
|
unsigned char * DMEM;
|
||||||
|
unsigned char * IMEM;
|
||||||
|
|
||||||
|
unsigned int * MI_INTR_REG;
|
||||||
|
|
||||||
|
unsigned int * AI_DRAM_ADDR_REG;
|
||||||
|
unsigned int * AI_LEN_REG;
|
||||||
|
unsigned int * AI_CONTROL_REG;
|
||||||
|
unsigned int * AI_STATUS_REG;
|
||||||
|
unsigned int * AI_DACRATE_REG;
|
||||||
|
unsigned int * AI_BITRATE_REG;
|
||||||
|
|
||||||
|
void (*CheckInterrupts)(void);
|
||||||
|
} AUDIO_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int Present;
|
||||||
|
int RawData;
|
||||||
|
int Plugin;
|
||||||
|
} CONTROL;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
unsigned int Value;
|
||||||
|
struct {
|
||||||
|
unsigned R_DPAD : 1;
|
||||||
|
unsigned L_DPAD : 1;
|
||||||
|
unsigned D_DPAD : 1;
|
||||||
|
unsigned U_DPAD : 1;
|
||||||
|
unsigned START_BUTTON : 1;
|
||||||
|
unsigned Z_TRIG : 1;
|
||||||
|
unsigned B_BUTTON : 1;
|
||||||
|
unsigned A_BUTTON : 1;
|
||||||
|
|
||||||
|
unsigned R_CBUTTON : 1;
|
||||||
|
unsigned L_CBUTTON : 1;
|
||||||
|
unsigned D_CBUTTON : 1;
|
||||||
|
unsigned U_CBUTTON : 1;
|
||||||
|
unsigned R_TRIG : 1;
|
||||||
|
unsigned L_TRIG : 1;
|
||||||
|
unsigned Reserved1 : 1;
|
||||||
|
unsigned Reserved2 : 1;
|
||||||
|
|
||||||
|
signed X_AXIS : 8;
|
||||||
|
signed Y_AXIS : 8;
|
||||||
|
};
|
||||||
|
} BUTTONS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CONTROL *Controls; /* A pointer to an array of 4 controllers .. eg:
|
||||||
|
CONTROL Controls[4]; */
|
||||||
|
} CONTROL_INFO;
|
||||||
|
|
||||||
|
/* common plugin function pointer types */
|
||||||
|
typedef void (*ptr_RomClosed)(void);
|
||||||
|
typedef int (*ptr_RomOpen)(void);
|
||||||
|
#if defined(M64P_PLUGIN_PROTOTYPES)
|
||||||
|
EXPORT int CALL RomOpen(void);
|
||||||
|
EXPORT void CALL RomClosed(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* video plugin function pointer types */
|
||||||
|
typedef void (*ptr_ChangeWindow)(void);
|
||||||
|
typedef int (*ptr_InitiateGFX)(GFX_INFO Gfx_Info);
|
||||||
|
typedef void (*ptr_MoveScreen)(int x, int y);
|
||||||
|
typedef void (*ptr_ProcessDList)(void);
|
||||||
|
typedef void (*ptr_ProcessRDPList)(void);
|
||||||
|
typedef void (*ptr_ShowCFB)(void);
|
||||||
|
typedef void (*ptr_UpdateScreen)(void);
|
||||||
|
typedef void (*ptr_ViStatusChanged)(void);
|
||||||
|
typedef void (*ptr_ViWidthChanged)(void);
|
||||||
|
typedef void (*ptr_ReadScreen2)(void *dest, int *width, int *height, int front);
|
||||||
|
typedef void (*ptr_SetRenderingCallback)(void (*callback)(int));
|
||||||
|
typedef void (*ptr_ResizeVideoOutput)(int width, int height);
|
||||||
|
#if defined(M64P_PLUGIN_PROTOTYPES)
|
||||||
|
EXPORT void CALL ChangeWindow(void);
|
||||||
|
EXPORT int CALL InitiateGFX(GFX_INFO Gfx_Info);
|
||||||
|
EXPORT void CALL MoveScreen(int x, int y);
|
||||||
|
EXPORT void CALL ProcessDList(void);
|
||||||
|
EXPORT void CALL ProcessRDPList(void);
|
||||||
|
EXPORT void CALL ShowCFB(void);
|
||||||
|
EXPORT void CALL UpdateScreen(void);
|
||||||
|
EXPORT void CALL ViStatusChanged(void);
|
||||||
|
EXPORT void CALL ViWidthChanged(void);
|
||||||
|
EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front);
|
||||||
|
EXPORT void CALL SetRenderingCallback(void (*callback)(int));
|
||||||
|
EXPORT void CALL ResizeVideoOutput(int width, int height);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* frame buffer plugin spec extension */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int addr;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
} FrameBufferInfo;
|
||||||
|
typedef void (*ptr_FBRead)(unsigned int addr);
|
||||||
|
typedef void (*ptr_FBWrite)(unsigned int addr, unsigned int size);
|
||||||
|
typedef void (*ptr_FBGetFrameBufferInfo)(void *p);
|
||||||
|
#if defined(M64P_PLUGIN_PROTOTYPES)
|
||||||
|
EXPORT void CALL FBRead(unsigned int addr);
|
||||||
|
EXPORT void CALL FBWrite(unsigned int addr, unsigned int size);
|
||||||
|
EXPORT void CALL FBGetFrameBufferInfo(void *p);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* audio plugin function pointers */
|
||||||
|
typedef void (*ptr_AiDacrateChanged)(int SystemType);
|
||||||
|
typedef void (*ptr_AiLenChanged)(void);
|
||||||
|
typedef int (*ptr_InitiateAudio)(AUDIO_INFO Audio_Info);
|
||||||
|
typedef void (*ptr_ProcessAList)(void);
|
||||||
|
typedef void (*ptr_SetSpeedFactor)(int percent);
|
||||||
|
typedef void (*ptr_VolumeUp)(void);
|
||||||
|
typedef void (*ptr_VolumeDown)(void);
|
||||||
|
typedef int (*ptr_VolumeGetLevel)(void);
|
||||||
|
typedef void (*ptr_VolumeSetLevel)(int level);
|
||||||
|
typedef void (*ptr_VolumeMute)(void);
|
||||||
|
typedef const char * (*ptr_VolumeGetString)(void);
|
||||||
|
#if defined(M64P_PLUGIN_PROTOTYPES)
|
||||||
|
EXPORT void CALL AiDacrateChanged(int SystemType);
|
||||||
|
EXPORT void CALL AiLenChanged(void);
|
||||||
|
EXPORT int CALL InitiateAudio(AUDIO_INFO Audio_Info);
|
||||||
|
EXPORT void CALL ProcessAList(void);
|
||||||
|
EXPORT void CALL SetSpeedFactor(int percent);
|
||||||
|
EXPORT void CALL VolumeUp(void);
|
||||||
|
EXPORT void CALL VolumeDown(void);
|
||||||
|
EXPORT int CALL VolumeGetLevel(void);
|
||||||
|
EXPORT void CALL VolumeSetLevel(int level);
|
||||||
|
EXPORT void CALL VolumeMute(void);
|
||||||
|
EXPORT const char * CALL VolumeGetString(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* input plugin function pointers */
|
||||||
|
typedef void (*ptr_ControllerCommand)(int Control, unsigned char *Command);
|
||||||
|
typedef void (*ptr_GetKeys)(int Control, BUTTONS *Keys);
|
||||||
|
typedef void (*ptr_InitiateControllers)(CONTROL_INFO ControlInfo);
|
||||||
|
typedef void (*ptr_ReadController)(int Control, unsigned char *Command);
|
||||||
|
typedef void (*ptr_SDL_KeyDown)(int keymod, int keysym);
|
||||||
|
typedef void (*ptr_SDL_KeyUp)(int keymod, int keysym);
|
||||||
|
typedef void (*ptr_RenderCallback)(void);
|
||||||
|
#if defined(M64P_PLUGIN_PROTOTYPES)
|
||||||
|
EXPORT void CALL ControllerCommand(int Control, unsigned char *Command);
|
||||||
|
EXPORT void CALL GetKeys(int Control, BUTTONS *Keys);
|
||||||
|
EXPORT void CALL InitiateControllers(CONTROL_INFO ControlInfo);
|
||||||
|
EXPORT void CALL ReadController(int Control, unsigned char *Command);
|
||||||
|
EXPORT void CALL SDL_KeyDown(int keymod, int keysym);
|
||||||
|
EXPORT void CALL SDL_KeyUp(int keymod, int keysym);
|
||||||
|
EXPORT void CALL RenderCallback(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* RSP plugin function pointers */
|
||||||
|
typedef unsigned int (*ptr_DoRspCycles)(unsigned int Cycles);
|
||||||
|
typedef void (*ptr_InitiateRSP)(RSP_INFO Rsp_Info, unsigned int *CycleCount);
|
||||||
|
#if defined(M64P_PLUGIN_PROTOTYPES)
|
||||||
|
EXPORT unsigned int CALL DoRspCycles(unsigned int Cycles);
|
||||||
|
EXPORT void CALL InitiateRSP(RSP_INFO Rsp_Info, unsigned int *CycleCount);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* M64P_PLUGIN_H */
|
||||||
|
|
||||||
|
|
365
Frameworks/lazyusf/lazyusf/api/m64p_types.h
Normal file
365
Frameworks/lazyusf/lazyusf/api/m64p_types.h
Normal file
|
@ -0,0 +1,365 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus-core - m64p_types.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2012 CasualJames *
|
||||||
|
* Copyright (C) 2009 Richard Goedeken *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#if !defined(M64P_TYPES_H)
|
||||||
|
#define M64P_TYPES_H
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Platform-specific stuff */
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
/* necessary headers */
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DLL handles and function declaration specifiers */
|
||||||
|
#if defined(WIN32)
|
||||||
|
#define IMPORT extern "C" __declspec(dllimport)
|
||||||
|
#define EXPORT __declspec(dllexport)
|
||||||
|
#define CALL __cdecl
|
||||||
|
typedef HMODULE m64p_dynlib_handle;
|
||||||
|
#else
|
||||||
|
#define IMPORT extern "C"
|
||||||
|
#define EXPORT __attribute__((visibility("default")))
|
||||||
|
#define CALL
|
||||||
|
typedef void * m64p_dynlib_handle;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Structures and Types for Core library API */
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
typedef void * m64p_handle;
|
||||||
|
|
||||||
|
typedef void (*m64p_frame_callback)(unsigned int FrameIndex);
|
||||||
|
typedef void (*m64p_input_callback)(void);
|
||||||
|
typedef void (*m64p_audio_callback)(void);
|
||||||
|
typedef void (*m64p_vi_callback)(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64TYPE_INT = 1,
|
||||||
|
M64TYPE_FLOAT,
|
||||||
|
M64TYPE_BOOL,
|
||||||
|
M64TYPE_STRING
|
||||||
|
} m64p_type;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64MSG_ERROR = 1,
|
||||||
|
M64MSG_WARNING,
|
||||||
|
M64MSG_INFO,
|
||||||
|
M64MSG_STATUS,
|
||||||
|
M64MSG_VERBOSE
|
||||||
|
} m64p_msg_level;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64ERR_SUCCESS = 0,
|
||||||
|
M64ERR_NOT_INIT, /* Function is disallowed before InitMupen64Plus() is called */
|
||||||
|
M64ERR_ALREADY_INIT, /* InitMupen64Plus() was called twice */
|
||||||
|
M64ERR_INCOMPATIBLE, /* API versions between components are incompatible */
|
||||||
|
M64ERR_INPUT_ASSERT, /* Invalid parameters for function call, such as ParamValue=NULL for GetCoreParameter() */
|
||||||
|
M64ERR_INPUT_INVALID, /* Invalid input data, such as ParamValue="maybe" for SetCoreParameter() to set a BOOL-type value */
|
||||||
|
M64ERR_INPUT_NOT_FOUND, /* The input parameter(s) specified a particular item which was not found */
|
||||||
|
M64ERR_NO_MEMORY, /* Memory allocation failed */
|
||||||
|
M64ERR_FILES, /* Error opening, creating, reading, or writing to a file */
|
||||||
|
M64ERR_INTERNAL, /* Internal error (bug) */
|
||||||
|
M64ERR_INVALID_STATE, /* Current program state does not allow operation */
|
||||||
|
M64ERR_PLUGIN_FAIL, /* A plugin function returned a fatal error */
|
||||||
|
M64ERR_SYSTEM_FAIL, /* A system function call, such as an SDL or file operation, failed */
|
||||||
|
M64ERR_UNSUPPORTED, /* Function call is not supported (ie, core not built with debugger) */
|
||||||
|
M64ERR_WRONG_TYPE /* A given input type parameter cannot be used for desired operation */
|
||||||
|
} m64p_error;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64CAPS_DYNAREC = 1,
|
||||||
|
M64CAPS_DEBUGGER = 2,
|
||||||
|
M64CAPS_CORE_COMPARE = 4
|
||||||
|
} m64p_core_caps;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64PLUGIN_NULL = 0,
|
||||||
|
M64PLUGIN_RSP = 1,
|
||||||
|
M64PLUGIN_GFX,
|
||||||
|
M64PLUGIN_AUDIO,
|
||||||
|
M64PLUGIN_INPUT,
|
||||||
|
M64PLUGIN_CORE
|
||||||
|
} m64p_plugin_type;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64EMU_STOPPED = 1,
|
||||||
|
M64EMU_RUNNING,
|
||||||
|
M64EMU_PAUSED
|
||||||
|
} m64p_emu_state;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64VIDEO_NONE = 1,
|
||||||
|
M64VIDEO_WINDOWED,
|
||||||
|
M64VIDEO_FULLSCREEN
|
||||||
|
} m64p_video_mode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64VIDEOFLAG_SUPPORT_RESIZING = 1
|
||||||
|
} m64p_video_flags;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64CORE_EMU_STATE = 1,
|
||||||
|
M64CORE_VIDEO_MODE,
|
||||||
|
M64CORE_SAVESTATE_SLOT,
|
||||||
|
M64CORE_SPEED_FACTOR,
|
||||||
|
M64CORE_SPEED_LIMITER,
|
||||||
|
M64CORE_VIDEO_SIZE,
|
||||||
|
M64CORE_AUDIO_VOLUME,
|
||||||
|
M64CORE_AUDIO_MUTE,
|
||||||
|
M64CORE_INPUT_GAMESHARK,
|
||||||
|
M64CORE_STATE_LOADCOMPLETE,
|
||||||
|
M64CORE_STATE_SAVECOMPLETE
|
||||||
|
} m64p_core_param;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64CMD_NOP = 0,
|
||||||
|
M64CMD_ROM_OPEN,
|
||||||
|
M64CMD_ROM_CLOSE,
|
||||||
|
M64CMD_ROM_GET_HEADER,
|
||||||
|
M64CMD_ROM_GET_SETTINGS,
|
||||||
|
M64CMD_EXECUTE,
|
||||||
|
M64CMD_STOP,
|
||||||
|
M64CMD_PAUSE,
|
||||||
|
M64CMD_RESUME,
|
||||||
|
M64CMD_CORE_STATE_QUERY,
|
||||||
|
M64CMD_STATE_LOAD,
|
||||||
|
M64CMD_STATE_SAVE,
|
||||||
|
M64CMD_STATE_SET_SLOT,
|
||||||
|
M64CMD_SEND_SDL_KEYDOWN,
|
||||||
|
M64CMD_SEND_SDL_KEYUP,
|
||||||
|
M64CMD_SET_FRAME_CALLBACK,
|
||||||
|
M64CMD_TAKE_NEXT_SCREENSHOT,
|
||||||
|
M64CMD_CORE_STATE_SET,
|
||||||
|
M64CMD_READ_SCREEN,
|
||||||
|
M64CMD_RESET,
|
||||||
|
M64CMD_ADVANCE_FRAME
|
||||||
|
} m64p_command;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int address;
|
||||||
|
int value;
|
||||||
|
} m64p_cheat_code;
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Structures to hold ROM image information */
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SYSTEM_NTSC = 0,
|
||||||
|
SYSTEM_PAL,
|
||||||
|
SYSTEM_MPAL
|
||||||
|
} m64p_system_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char init_PI_BSB_DOM1_LAT_REG; /* 0x00 */
|
||||||
|
unsigned char init_PI_BSB_DOM1_PGS_REG; /* 0x01 */
|
||||||
|
unsigned char init_PI_BSB_DOM1_PWD_REG; /* 0x02 */
|
||||||
|
unsigned char init_PI_BSB_DOM1_PGS_REG2; /* 0x03 */
|
||||||
|
unsigned int ClockRate; /* 0x04 */
|
||||||
|
unsigned int PC; /* 0x08 */
|
||||||
|
unsigned int Release; /* 0x0C */
|
||||||
|
unsigned int CRC1; /* 0x10 */
|
||||||
|
unsigned int CRC2; /* 0x14 */
|
||||||
|
unsigned int Unknown[2]; /* 0x18 */
|
||||||
|
unsigned char Name[20]; /* 0x20 */
|
||||||
|
unsigned int unknown; /* 0x34 */
|
||||||
|
unsigned int Manufacturer_ID; /* 0x38 */
|
||||||
|
unsigned short Cartridge_ID; /* 0x3C - Game serial number */
|
||||||
|
unsigned short Country_code; /* 0x3E */
|
||||||
|
} m64p_rom_header;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char goodname[256];
|
||||||
|
char MD5[33];
|
||||||
|
unsigned char savetype;
|
||||||
|
unsigned char status; /* Rom status on a scale from 0-5. */
|
||||||
|
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. */
|
||||||
|
} m64p_rom_settings;
|
||||||
|
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
/* Structures and Types for the Debugger */
|
||||||
|
/* ----------------------------------------- */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_DBG_RUN_STATE = 1,
|
||||||
|
M64P_DBG_PREVIOUS_PC,
|
||||||
|
M64P_DBG_NUM_BREAKPOINTS,
|
||||||
|
M64P_DBG_CPU_DYNACORE,
|
||||||
|
M64P_DBG_CPU_NEXT_INTERRUPT
|
||||||
|
} m64p_dbg_state;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_DBG_RUNSTATE_PAUSED = 0,
|
||||||
|
M64P_DBG_RUNSTATE_STEPPING,
|
||||||
|
M64P_DBG_RUNSTATE_RUNNING
|
||||||
|
} m64p_dbg_runstate;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_DBG_MEM_TYPE = 1,
|
||||||
|
M64P_DBG_MEM_FLAGS,
|
||||||
|
M64P_DBG_MEM_HAS_RECOMPILED,
|
||||||
|
M64P_DBG_MEM_NUM_RECOMPILED,
|
||||||
|
M64P_DBG_RECOMP_OPCODE = 16,
|
||||||
|
M64P_DBG_RECOMP_ARGS,
|
||||||
|
M64P_DBG_RECOMP_ADDR
|
||||||
|
} m64p_dbg_mem_info;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_MEM_NOMEM = 0,
|
||||||
|
M64P_MEM_NOTHING,
|
||||||
|
M64P_MEM_RDRAM,
|
||||||
|
M64P_MEM_RDRAMREG,
|
||||||
|
M64P_MEM_RSPMEM,
|
||||||
|
M64P_MEM_RSPREG,
|
||||||
|
M64P_MEM_RSP,
|
||||||
|
M64P_MEM_DP,
|
||||||
|
M64P_MEM_DPS,
|
||||||
|
M64P_MEM_VI,
|
||||||
|
M64P_MEM_AI,
|
||||||
|
M64P_MEM_PI,
|
||||||
|
M64P_MEM_RI,
|
||||||
|
M64P_MEM_SI,
|
||||||
|
M64P_MEM_FLASHRAMSTAT,
|
||||||
|
M64P_MEM_ROM,
|
||||||
|
M64P_MEM_PIF,
|
||||||
|
M64P_MEM_MI,
|
||||||
|
M64P_MEM_BREAKPOINT
|
||||||
|
} m64p_dbg_mem_type;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_MEM_FLAG_READABLE = 0x01,
|
||||||
|
M64P_MEM_FLAG_WRITABLE = 0x02,
|
||||||
|
M64P_MEM_FLAG_READABLE_EMUONLY = 0x04, /* the EMUONLY flags signify that emulated code can read/write here, but debugger cannot */
|
||||||
|
M64P_MEM_FLAG_WRITABLE_EMUONLY = 0x08
|
||||||
|
} m64p_dbg_mem_flags;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_DBG_PTR_RDRAM = 1,
|
||||||
|
M64P_DBG_PTR_PI_REG,
|
||||||
|
M64P_DBG_PTR_SI_REG,
|
||||||
|
M64P_DBG_PTR_VI_REG,
|
||||||
|
M64P_DBG_PTR_RI_REG,
|
||||||
|
M64P_DBG_PTR_AI_REG
|
||||||
|
} m64p_dbg_memptr_type;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_CPU_PC = 1,
|
||||||
|
M64P_CPU_REG_REG,
|
||||||
|
M64P_CPU_REG_HI,
|
||||||
|
M64P_CPU_REG_LO,
|
||||||
|
M64P_CPU_REG_COP0,
|
||||||
|
M64P_CPU_REG_COP1_DOUBLE_PTR,
|
||||||
|
M64P_CPU_REG_COP1_SIMPLE_PTR,
|
||||||
|
M64P_CPU_REG_COP1_FGR_64,
|
||||||
|
M64P_CPU_TLB
|
||||||
|
} m64p_dbg_cpu_data;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_BKP_CMD_ADD_ADDR = 1,
|
||||||
|
M64P_BKP_CMD_ADD_STRUCT,
|
||||||
|
M64P_BKP_CMD_REPLACE,
|
||||||
|
M64P_BKP_CMD_REMOVE_ADDR,
|
||||||
|
M64P_BKP_CMD_REMOVE_IDX,
|
||||||
|
M64P_BKP_CMD_ENABLE,
|
||||||
|
M64P_BKP_CMD_DISABLE,
|
||||||
|
M64P_BKP_CMD_CHECK
|
||||||
|
} m64p_dbg_bkp_command;
|
||||||
|
|
||||||
|
#define M64P_MEM_INVALID 0xFFFFFFFF /* invalid memory read will return this */
|
||||||
|
|
||||||
|
#define BREAKPOINTS_MAX_NUMBER 128
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_BKP_FLAG_ENABLED = 0x01,
|
||||||
|
M64P_BKP_FLAG_READ = 0x02,
|
||||||
|
M64P_BKP_FLAG_WRITE = 0x04,
|
||||||
|
M64P_BKP_FLAG_EXEC = 0x08,
|
||||||
|
M64P_BKP_FLAG_LOG = 0x10 /* Log to the console when this breakpoint hits */
|
||||||
|
} m64p_dbg_bkp_flags;
|
||||||
|
|
||||||
|
#define BPT_CHECK_FLAG(a, b) ((a.flags & b) == b)
|
||||||
|
#define BPT_SET_FLAG(a, b) a.flags = (a.flags | b);
|
||||||
|
#define BPT_CLEAR_FLAG(a, b) a.flags = (a.flags & (~b));
|
||||||
|
#define BPT_TOGGLE_FLAG(a, b) a.flags = (a.flags ^ b);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int address;
|
||||||
|
unsigned int endaddr;
|
||||||
|
unsigned int flags;
|
||||||
|
} m64p_breakpoint;
|
||||||
|
|
||||||
|
/* ------------------------------------------------- */
|
||||||
|
/* Structures and Types for Core Video Extension API */
|
||||||
|
/* ------------------------------------------------- */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int uiWidth;
|
||||||
|
unsigned int uiHeight;
|
||||||
|
} m64p_2d_size;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_GL_DOUBLEBUFFER = 1,
|
||||||
|
M64P_GL_BUFFER_SIZE,
|
||||||
|
M64P_GL_DEPTH_SIZE,
|
||||||
|
M64P_GL_RED_SIZE,
|
||||||
|
M64P_GL_GREEN_SIZE,
|
||||||
|
M64P_GL_BLUE_SIZE,
|
||||||
|
M64P_GL_ALPHA_SIZE,
|
||||||
|
M64P_GL_SWAP_CONTROL,
|
||||||
|
M64P_GL_MULTISAMPLEBUFFERS,
|
||||||
|
M64P_GL_MULTISAMPLESAMPLES,
|
||||||
|
M64P_GL_CONTEXT_MAJOR_VERSION,
|
||||||
|
M64P_GL_CONTEXT_MINOR_VERSION,
|
||||||
|
M64P_GL_CONTEXT_PROFILE_MASK
|
||||||
|
} m64p_GLattr;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
M64P_GL_CONTEXT_PROFILE_CORE,
|
||||||
|
M64P_GL_CONTEXT_PROFILE_COMPATIBILITY,
|
||||||
|
M64P_GL_CONTEXT_PROFILE_ES
|
||||||
|
} m64p_GLContextType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int Functions;
|
||||||
|
m64p_error (*VidExtFuncInit)(void);
|
||||||
|
m64p_error (*VidExtFuncQuit)(void);
|
||||||
|
m64p_error (*VidExtFuncListModes)(m64p_2d_size *, int *);
|
||||||
|
m64p_error (*VidExtFuncSetMode)(int, int, int, int, int);
|
||||||
|
void * (*VidExtFuncGLGetProc)(const char*);
|
||||||
|
m64p_error (*VidExtFuncGLSetAttr)(m64p_GLattr, int);
|
||||||
|
m64p_error (*VidExtFuncGLGetAttr)(m64p_GLattr, int *);
|
||||||
|
m64p_error (*VidExtFuncGLSwapBuf)(void);
|
||||||
|
m64p_error (*VidExtFuncSetCaption)(const char *);
|
||||||
|
m64p_error (*VidExtFuncToggleFS)(void);
|
||||||
|
m64p_error (*VidExtFuncResizeWindow)(int, int);
|
||||||
|
} m64p_video_extension_functions;
|
||||||
|
|
||||||
|
#endif /* define M64P_TYPES_H */
|
||||||
|
|
154
Frameworks/lazyusf/lazyusf/api/m64p_vidext.h
Normal file
154
Frameworks/lazyusf/lazyusf/api/m64p_vidext.h
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus-core - m64p_vidext.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2009 Richard Goedeken *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* This header file defines typedefs for function pointers to the core's
|
||||||
|
* video extension functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(M64P_VIDEXT_H)
|
||||||
|
#define M64P_VIDEXT_H
|
||||||
|
|
||||||
|
#include "m64p_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_Init()
|
||||||
|
*
|
||||||
|
* This function should be called from within the InitiateGFX() video plugin
|
||||||
|
* function call. The default SDL implementation of this function simply calls
|
||||||
|
* SDL_InitSubSystem(SDL_INIT_VIDEO). It does not open a rendering window or
|
||||||
|
* switch video modes.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_Init)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_Init(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_Quit()
|
||||||
|
*
|
||||||
|
* This function closes any open rendering window and shuts down the video
|
||||||
|
* system. The default SDL implementation of this function calls
|
||||||
|
* SDL_QuitSubSystem(SDL_INIT_VIDEO). This function should be called from
|
||||||
|
* within the RomClose() video plugin function.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_Quit)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_Quit(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_ListFullscreenModes()
|
||||||
|
*
|
||||||
|
* This function is used to enumerate the available resolutions for fullscreen
|
||||||
|
* video modes. A pointer to an array is passed into the function, which is
|
||||||
|
* then filled with resolution sizes.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_ListFullscreenModes)(m64p_2d_size *, int *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_ListFullscreenModes(m64p_2d_size *, int *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_SetVideoMode()
|
||||||
|
*
|
||||||
|
* This function creates a rendering window or switches into a fullscreen
|
||||||
|
* video mode. Any desired OpenGL attributes should be set before calling
|
||||||
|
* this function.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_SetVideoMode)(int, int, int, m64p_video_mode, m64p_video_flags);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_SetVideoMode(int, int, int, m64p_video_mode, m64p_video_flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_ResizeWindow()
|
||||||
|
*
|
||||||
|
* This function resizes the opengl rendering window to match the given size.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_ResizeWindow)(int, int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_ResizeWindow(int, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_SetCaption()
|
||||||
|
*
|
||||||
|
* This function sets the caption text of the emulator rendering window.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_SetCaption)(const char *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_SetCaption(const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_ToggleFullScreen()
|
||||||
|
*
|
||||||
|
* This function toggles between fullscreen and windowed rendering modes.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_ToggleFullScreen)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_ToggleFullScreen(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_GL_GetProcAddress()
|
||||||
|
*
|
||||||
|
* This function is used to get a pointer to an OpenGL extension function. This
|
||||||
|
* is only necessary on the Windows platform, because the OpenGL implementation
|
||||||
|
* shipped with Windows only supports OpenGL version 1.1.
|
||||||
|
*/
|
||||||
|
typedef void * (*ptr_VidExt_GL_GetProcAddress)(const char *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT void * CALL VidExt_GL_GetProcAddress(const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_GL_SetAttribute()
|
||||||
|
*
|
||||||
|
* This function is used to set certain OpenGL attributes which must be
|
||||||
|
* specified before creating the rendering window with VidExt_SetVideoMode.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_GL_SetAttribute)(m64p_GLattr, int);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_GL_SetAttribute(m64p_GLattr, int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_GL_GetAttribute()
|
||||||
|
*
|
||||||
|
* This function is used to get the value of OpenGL attributes. These values may
|
||||||
|
* be changed when calling VidExt_SetVideoMode.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_GL_GetAttribute)(m64p_GLattr, int *);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_GL_GetAttribute(m64p_GLattr, int *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* VidExt_GL_SwapBuffers()
|
||||||
|
*
|
||||||
|
* This function is used to swap the front/back buffers after rendering an
|
||||||
|
* output video frame.
|
||||||
|
*/
|
||||||
|
typedef m64p_error (*ptr_VidExt_GL_SwapBuffers)(void);
|
||||||
|
#if defined(M64P_CORE_PROTOTYPES)
|
||||||
|
EXPORT m64p_error CALL VidExt_GL_SwapBuffers(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* #define M64P_VIDEXT_H */
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
#include "usf.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "audio.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
void AddBuffer(usf_state_t *state, unsigned char *buf, unsigned int length) {
|
|
||||||
unsigned int i, do_max;
|
|
||||||
int16_t * sample_buffer = state->sample_buffer;
|
|
||||||
|
|
||||||
if(!state->cpu_running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
do_max = length >> 2;
|
|
||||||
if ( do_max > state->sample_buffer_count )
|
|
||||||
do_max = (unsigned int) state->sample_buffer_count;
|
|
||||||
|
|
||||||
if ( sample_buffer )
|
|
||||||
for (i = 0; i < do_max; ++i)
|
|
||||||
{
|
|
||||||
*sample_buffer++ = ((int16_t*)buf)[1];
|
|
||||||
*sample_buffer++ = ((int16_t*)buf)[0];
|
|
||||||
buf += 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buf += 4 * do_max;
|
|
||||||
|
|
||||||
state->sample_buffer_count -= do_max;
|
|
||||||
state->sample_buffer = sample_buffer;
|
|
||||||
|
|
||||||
length -= do_max << 2;
|
|
||||||
|
|
||||||
if ( length )
|
|
||||||
{
|
|
||||||
sample_buffer = state->samplebuf;
|
|
||||||
do_max = length >> 2;
|
|
||||||
for (i = 0; i < do_max; ++i)
|
|
||||||
{
|
|
||||||
*sample_buffer++ = ((int16_t*)buf)[1];
|
|
||||||
*sample_buffer++ = ((int16_t*)buf)[0];
|
|
||||||
buf += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->samples_in_buffer = do_max;
|
|
||||||
state->cpu_running = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AiLenChanged(usf_state_t * state) {
|
|
||||||
int32_t length = 0;
|
|
||||||
uint32_t address = (AI_DRAM_ADDR_REG & 0x00FFFFF8);
|
|
||||||
|
|
||||||
length = AI_LEN_REG & 0x3FFF8;
|
|
||||||
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
fprintf(state->debug_log, "Audio DMA push: %d %d\n", AI_DRAM_ADDR_REG, length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AddBuffer(state, state->RDRAM+address, length);
|
|
||||||
|
|
||||||
if(length && !(AI_STATUS_REG&0x80000000)) {
|
|
||||||
const float VSyncTiming = 789000.0f;
|
|
||||||
double BytesPerSecond = 48681812.0 / (AI_DACRATE_REG + 1) * 4;
|
|
||||||
double CountsPerSecond = (double)((((double)VSyncTiming) * (double)60.0)) * 2.0;
|
|
||||||
double CountsPerByte = (double)CountsPerSecond / (double)BytesPerSecond;
|
|
||||||
unsigned int IntScheduled = (unsigned int)((double)AI_LEN_REG * CountsPerByte);
|
|
||||||
|
|
||||||
ChangeTimer(state,AiTimer,IntScheduled);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(state->enableFIFOfull) {
|
|
||||||
if(AI_STATUS_REG&0x40000000)
|
|
||||||
AI_STATUS_REG|=0x80000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
AI_STATUS_REG|=0x40000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int AiReadLength(usf_state_t * state) {
|
|
||||||
AI_LEN_REG = 0;
|
|
||||||
return AI_LEN_REG;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AiDacrateChanged(usf_state_t * state, unsigned int value) {
|
|
||||||
AI_DACRATE_REG = value;
|
|
||||||
state->SampleRate = 48681812 / (AI_DACRATE_REG + 1);
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
#ifndef _AUDIO_H_
|
|
||||||
#define _AUDIO_H_
|
|
||||||
|
|
||||||
#include "usf.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
uint32_t AiReadLength(usf_state_t *);
|
|
||||||
void AiLenChanged(usf_state_t *);
|
|
||||||
void AiDacrateChanged(usf_state_t *, uint32_t value);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,271 +0,0 @@
|
||||||
#include "usf.h"
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
#include "cpu_hle.h"
|
|
||||||
#include "audiolib.h"
|
|
||||||
#include "os.h"
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
#define N64WORD(x) (*(uint32_t*)PageVRAM((x)))
|
|
||||||
#define N64HALF(x) (*(uint16_t*)PageVRAM((x)))
|
|
||||||
#define N64BYTE(x) (*(uint8_t*)PageVRAM((x)))
|
|
||||||
|
|
||||||
|
|
||||||
int alCopy(usf_state_t * state, int paddr) {
|
|
||||||
uint32_t source = (state->GPR[4].UW[0]);
|
|
||||||
uint32_t dest = (state->GPR[5].UW[0]);
|
|
||||||
uint32_t len = (state->GPR[6].UW[0]);
|
|
||||||
|
|
||||||
if(len&3)
|
|
||||||
DisplayError(state, "OMG!!!! - alCopy length & 3\n");
|
|
||||||
|
|
||||||
memcpyn642n64(state, dest, source, len);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int alLink(usf_state_t * state, int paddr) {
|
|
||||||
ALLink *element = (ALLink*)PageVRAM(state->GPR[4].UW[0]);
|
|
||||||
ALLink *after = (ALLink*)PageVRAM(state->GPR[5].UW[0]);
|
|
||||||
ALLink *afterNext;
|
|
||||||
|
|
||||||
element->next = after->next;
|
|
||||||
element->prev = state->GPR[5].UW[0];
|
|
||||||
|
|
||||||
if (after->next) {
|
|
||||||
afterNext = (ALLink*)PageVRAM(after->next);
|
|
||||||
afterNext->prev = state->GPR[4].UW[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
after->next = state->GPR[4].UW[0];
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int alUnLink(usf_state_t * state, int paddr) {
|
|
||||||
ALLink *element = (ALLink*)PageVRAM(state->GPR[4].UW[0]);
|
|
||||||
ALLink *elementNext = (ALLink*)PageVRAM(element->next);
|
|
||||||
ALLink *elementPrev = (ALLink*)PageVRAM(element->prev);
|
|
||||||
// _asm int 3
|
|
||||||
|
|
||||||
if (element->next)
|
|
||||||
elementNext->prev = element->prev;
|
|
||||||
if (element->prev)
|
|
||||||
elementPrev->next = element->next;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int alEvtqPostEvent(usf_state_t * state, int paddr) {
|
|
||||||
ALEventQueue *evtq;
|
|
||||||
ALEvent *events;
|
|
||||||
|
|
||||||
uint32_t A0 = state->GPR[4].UW[0];
|
|
||||||
uint32_t A1 = state->GPR[5].UW[0];
|
|
||||||
uint32_t DeltaTime = state->GPR[6].UW[0];
|
|
||||||
|
|
||||||
uint32_t nodeNext = 0;
|
|
||||||
uint32_t nextItem = 0;
|
|
||||||
uint32_t node = 0;
|
|
||||||
uint32_t nextDelta = 0;
|
|
||||||
uint32_t item = 0;
|
|
||||||
uint32_t postWhere = 0;
|
|
||||||
uint32_t NEXT = 0;
|
|
||||||
uint32_t nextItemDelta = 0;
|
|
||||||
|
|
||||||
evtq = (ALEventQueue *)PageVRAM(A0);
|
|
||||||
events = (ALEvent *)PageVRAM(A1);
|
|
||||||
//_asm int 3
|
|
||||||
|
|
||||||
NEXT = evtq->freeList.next;
|
|
||||||
|
|
||||||
if(NEXT == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
//DisplayError("%08x", N64WORD(0x800533E4));
|
|
||||||
//cprintf("%08x\t%08x\n", N64WORD(0x800533D4), N64WORD(0x800533D8));
|
|
||||||
|
|
||||||
item = NEXT;
|
|
||||||
state->GPR[4].UW[0] = NEXT;
|
|
||||||
alUnLink(state, 0);
|
|
||||||
|
|
||||||
state->GPR[4].UW[0] = A1; state->GPR[5].UW[0] = NEXT + 0xC; state->GPR[6].UW[0] = 0x10;
|
|
||||||
alCopy(state, 0);
|
|
||||||
|
|
||||||
postWhere = (DeltaTime==0x7FFFFFFF)?1:0;
|
|
||||||
nodeNext = A0;
|
|
||||||
node = nodeNext + 8;
|
|
||||||
|
|
||||||
while(nodeNext !=0 ) {
|
|
||||||
nodeNext = *(uint32_t*)PageVRAM(node);
|
|
||||||
|
|
||||||
if(nodeNext != 0) {
|
|
||||||
nextDelta = *(uint32_t*)PageVRAM(nodeNext + 8);
|
|
||||||
nextItem = nodeNext;
|
|
||||||
if(DeltaTime < nextDelta) {
|
|
||||||
*(uint32_t*)PageVRAM(item + 8) = DeltaTime;
|
|
||||||
nextItemDelta = *(uint32_t*)PageVRAM(nextItem + 8);
|
|
||||||
*(uint32_t*)PageVRAM(nextItem + 8) = nextItemDelta - DeltaTime;
|
|
||||||
|
|
||||||
state->GPR[4].UW[0] = item; state->GPR[5].UW[0] = node;
|
|
||||||
alLink(state, 0);
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
node = nodeNext;
|
|
||||||
DeltaTime -= nextDelta;
|
|
||||||
if(node == 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(postWhere == 0)
|
|
||||||
*(uint32_t*)PageVRAM(item + 8) = DeltaTime;
|
|
||||||
else
|
|
||||||
*(uint32_t*)PageVRAM(item + 8) = 0;
|
|
||||||
|
|
||||||
|
|
||||||
state->GPR[4].UW[0] = item; state->GPR[5].UW[0] = node;
|
|
||||||
alLink(state, 0);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int alEvtqPostEvent_Alt(usf_state_t * state, int paddr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t __nextSampleTime(usf_state_t * state, uint32_t driver, uint32_t *client) {
|
|
||||||
|
|
||||||
uint32_t c = 0;
|
|
||||||
int32_t deltaTime = 0x7FFFFFFF;
|
|
||||||
*client = 0;
|
|
||||||
|
|
||||||
for(c = N64WORD(driver); c != 0; c = N64WORD(c)) {
|
|
||||||
int samplesLeft = N64WORD(c + 0x10);
|
|
||||||
int curSamples = N64WORD(driver + 0x20);
|
|
||||||
if((samplesLeft - curSamples) < deltaTime) {
|
|
||||||
*client = c;
|
|
||||||
deltaTime = samplesLeft - curSamples;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return N64WORD((*client)+0x10);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t _timeToSamplesNoRound(usf_state_t * state, long synth, long micros)
|
|
||||||
{
|
|
||||||
uint32_t outputRate = N64WORD(synth+0x44);
|
|
||||||
float tmp = ((float)micros) * outputRate / 1000000.0 + 0.5;
|
|
||||||
//DisplayError("Smaple rate is %d", outputRate);
|
|
||||||
|
|
||||||
return (int32_t)tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t byteswap(char b[4] ) {
|
|
||||||
uint32_t out = 0;
|
|
||||||
out += b[3];
|
|
||||||
out += b[2] << 8;
|
|
||||||
out += b[1] << 16;
|
|
||||||
out += b[0] << 24;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
int alAudioFrame(usf_state_t * state, int paddr) {
|
|
||||||
|
|
||||||
uint32_t alGlobals = 0;
|
|
||||||
uint32_t driver = 0, *paramSamples, *curSamples, client = 0, dl = 0;
|
|
||||||
uint32_t A0 = state->GPR[4].UW[0];
|
|
||||||
uint32_t A1 = state->GPR[5].UW[0];
|
|
||||||
uint32_t A2 = state->GPR[6].UW[0];
|
|
||||||
uint32_t outLen = state->GPR[7].UW[0];
|
|
||||||
uint32_t cmdlEnd = A0;
|
|
||||||
uint32_t lOutBuf = A2;
|
|
||||||
|
|
||||||
alGlobals = ((*(uint16_t*)PageRAM2(paddr + 0x8)) & 0xFFFF) << 16; //alGlobals->drvr
|
|
||||||
alGlobals += *(int16_t*)PageRAM2(paddr + 0xc);
|
|
||||||
//alGlobals = 0x80750C74;
|
|
||||||
driver = N64WORD(alGlobals);
|
|
||||||
paramSamples = (uint32_t*) PageVRAM(driver + 0x1c);
|
|
||||||
curSamples = (uint32_t*) PageVRAM(driver + 0x20);
|
|
||||||
|
|
||||||
if(N64WORD(driver) == 0) { // if(drvr->head == 0)
|
|
||||||
N64WORD(A1) = 0;
|
|
||||||
state->GPR[2].UW[0] = A0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(*paramSamples = __nextSampleTime(state, driver, &client); (*paramSamples - *curSamples) < outLen; *paramSamples = __nextSampleTime(state, driver, &client)) {
|
|
||||||
int32_t *cSamplesLeft;
|
|
||||||
cSamplesLeft = (int32_t *) PageVRAM(client + 0x10);
|
|
||||||
*paramSamples &= ~0xf;
|
|
||||||
|
|
||||||
//run handler (not-HLE'd)
|
|
||||||
state->GPR[4].UW[0] = client;
|
|
||||||
RunFunction(state, N64WORD(client+0x8));
|
|
||||||
*cSamplesLeft += _timeToSamplesNoRound(state, driver, state->GPR[2].UW[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
*paramSamples &= ~0xf;
|
|
||||||
|
|
||||||
//give us some stack
|
|
||||||
state->GPR[0x1d].UW[0] -= 0x20;
|
|
||||||
N64WORD(state->GPR[0x1d].UW[0]+0x4) = 0; //tmp
|
|
||||||
|
|
||||||
while (outLen > 0) {
|
|
||||||
|
|
||||||
uint32_t maxOutSamples = 0, nOut = 0, cmdPtr = 0, output = 0, setParam = 0, handler = 0;
|
|
||||||
|
|
||||||
maxOutSamples = N64WORD(driver + 0x48);
|
|
||||||
nOut = MIN(maxOutSamples, outLen);
|
|
||||||
cmdPtr = cmdlEnd;//+8;
|
|
||||||
|
|
||||||
output = N64WORD(driver + 0x38);
|
|
||||||
setParam = N64WORD(output+8); // alSaveParam
|
|
||||||
|
|
||||||
state->GPR[4].DW = output;
|
|
||||||
state->GPR[5].DW = 0x6; // AL_FILTER_SET_DRAM
|
|
||||||
state->GPR[6].DW = lOutBuf;
|
|
||||||
RunFunction(state, setParam);
|
|
||||||
|
|
||||||
handler = N64WORD(output+4); // alSavePull
|
|
||||||
state->GPR[4].DW = output;
|
|
||||||
state->GPR[5].DW = state->GPR[0x1d].UW[0]+0x12; //&tmp
|
|
||||||
state->GPR[6].DW = nOut;
|
|
||||||
state->GPR[7].DW = *curSamples;
|
|
||||||
N64WORD(state->GPR[0x1d].UW[0]+0x10) = cmdPtr;
|
|
||||||
RunFunction(state, handler);
|
|
||||||
|
|
||||||
curSamples = (uint32_t *) PageVRAM(driver + 0x20);
|
|
||||||
|
|
||||||
cmdlEnd = state->GPR[2].UW[0];
|
|
||||||
outLen -= nOut;
|
|
||||||
lOutBuf += (nOut<<2);
|
|
||||||
*curSamples += nOut;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
state->GPR[0x1d].UW[0] += 0x20;
|
|
||||||
|
|
||||||
N64WORD(A1) = (int32_t) ((cmdlEnd - A0) >> 3);
|
|
||||||
|
|
||||||
state->GPR[4].UW[0] = driver;
|
|
||||||
|
|
||||||
while( (dl = N64WORD(driver+0x14)) ) {
|
|
||||||
state->GPR[4].UW[0] = dl;
|
|
||||||
alUnLink(state, 0);
|
|
||||||
state->GPR[4].UW[0] = dl;
|
|
||||||
state->GPR[5].UW[0] = driver + 4;
|
|
||||||
alLink(state, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
state->GPR[2].UW[0] = cmdlEnd;
|
|
||||||
return 1;
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
#ifndef _CPU_HLE_AUDIOLIB_
|
|
||||||
#define _CPU_HLE_AUDIOLIB_
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "cpu_hle.h"
|
|
||||||
#include "os.h"
|
|
||||||
|
|
||||||
// a few of these structures/type were sequestered from SGI\Nindendo's code
|
|
||||||
|
|
||||||
typedef struct ALLink_s {
|
|
||||||
uint32_t next;
|
|
||||||
uint32_t prev;
|
|
||||||
} ALLink;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ALLink freeList;
|
|
||||||
ALLink allocList;
|
|
||||||
int32_t eventCount;
|
|
||||||
} ALEventQueue;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t type;
|
|
||||||
uint8_t msg[12];
|
|
||||||
} ALEvent;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ALLink node;
|
|
||||||
int32_t delta; //microtime
|
|
||||||
ALEvent event;
|
|
||||||
} ALEventListItem;
|
|
||||||
|
|
||||||
int alCopy(usf_state_t *, int paddr);
|
|
||||||
int alLink(usf_state_t *, int paddr);
|
|
||||||
int alUnLink(usf_state_t *, int paddr);
|
|
||||||
int alEvtqPostEvent(usf_state_t *, int paddr) ;
|
|
||||||
int alEvtqPostEvent_Alt(usf_state_t *, int paddr);
|
|
||||||
int alAudioFrame(usf_state_t *, int paddr);
|
|
||||||
|
|
||||||
// need to remove these
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t *base;
|
|
||||||
uint8_t *cur;
|
|
||||||
int32_t len;
|
|
||||||
int32_t count;
|
|
||||||
} ALHeap;
|
|
||||||
|
|
||||||
typedef struct ALPlayer_s {
|
|
||||||
struct ALPlayer_s *next;
|
|
||||||
void *clientData;
|
|
||||||
void *handler;
|
|
||||||
int32_t callTime;
|
|
||||||
int32_t samplesLeft;
|
|
||||||
} ALPlayer;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,63 +0,0 @@
|
||||||
/* config.h. Generated from config.h.in by configure. */
|
|
||||||
/* config.h.in. Generated from configure.in by autoheader. */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
|
||||||
#define HAVE_DLFCN_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#define HAVE_MEMORY_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#define HAVE_STRINGS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#define HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
|
||||||
*/
|
|
||||||
#define LT_OBJDIR ".libs/"
|
|
||||||
|
|
||||||
/* Name of package */
|
|
||||||
#define PACKAGE "lazyusf"
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#define PACKAGE_BUGREPORT ""
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#define PACKAGE_NAME "lazyusf"
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#define PACKAGE_STRING "lazyusf 1.0.0"
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#define PACKAGE_TARNAME "lazyusf"
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#define PACKAGE_VERSION "1.0.0"
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* Version number of package */
|
|
||||||
#define VERSION "1.0.0"
|
|
||||||
|
|
||||||
/* Define to 1 if the X Window System is missing or not being used. */
|
|
||||||
/* #undef X_DISPLAY_MISSING */
|
|
|
@ -1,604 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "usf.h"
|
|
||||||
#include "audio.h"
|
|
||||||
#include "registers.h"
|
|
||||||
#include "rsp.h"
|
|
||||||
#include "cpu_hle.h"
|
|
||||||
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void ChangeCompareTimer(usf_state_t * state) {
|
|
||||||
uint32_t NextCompare = COMPARE_REGISTER - COUNT_REGISTER;
|
|
||||||
if ((NextCompare & 0x80000000) != 0) { NextCompare = 0x7FFFFFFF; }
|
|
||||||
if (NextCompare == 0) { NextCompare = 0x1; }
|
|
||||||
ChangeTimer(state,CompareTimer,NextCompare);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChangeTimer(usf_state_t * state, int32_t Type, int32_t Value) {
|
|
||||||
if (Value == 0) {
|
|
||||||
state->Timers->NextTimer[Type] = 0;
|
|
||||||
state->Timers->Active[Type] = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state->Timers->NextTimer[Type] = Value - state->Timers->Timer;
|
|
||||||
state->Timers->Active[Type] = 1;
|
|
||||||
CheckTimer(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckTimer (usf_state_t * state) {
|
|
||||||
int32_t count;
|
|
||||||
|
|
||||||
for (count = 0; count < MaxTimers; count++) {
|
|
||||||
if (!state->Timers->Active[count]) { continue; }
|
|
||||||
if (!(count == CompareTimer && state->Timers->NextTimer[count] == 0x7FFFFFFF)) {
|
|
||||||
state->Timers->NextTimer[count] += state->Timers->Timer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state->Timers->CurrentTimerType = -1;
|
|
||||||
state->Timers->Timer = 0x7FFFFFFF;
|
|
||||||
for (count = 0; count < MaxTimers; count++) {
|
|
||||||
if (!state->Timers->Active[count]) { continue; }
|
|
||||||
if (state->Timers->NextTimer[count] >= state->Timers->Timer) { continue; }
|
|
||||||
state->Timers->Timer = state->Timers->NextTimer[count];
|
|
||||||
state->Timers->CurrentTimerType = count;
|
|
||||||
}
|
|
||||||
if (state->Timers->CurrentTimerType == -1) {
|
|
||||||
DisplayError(state, "No active timers ???\nEmulation Stopped");
|
|
||||||
StopEmulation(state);
|
|
||||||
}
|
|
||||||
for (count = 0; count < MaxTimers; count++) {
|
|
||||||
if (!state->Timers->Active[count]) { continue; }
|
|
||||||
if (!(count == CompareTimer && state->Timers->NextTimer[count] == 0x7FFFFFFF)) {
|
|
||||||
state->Timers->NextTimer[count] -= state->Timers->Timer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state->Timers->NextTimer[CompareTimer] == 0x7FFFFFFF) {
|
|
||||||
uint32_t NextCompare = COMPARE_REGISTER - COUNT_REGISTER;
|
|
||||||
if ((NextCompare & 0x80000000) == 0 && NextCompare != 0x7FFFFFFF) {
|
|
||||||
ChangeCompareTimer(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CloseCpu (usf_state_t * state) {
|
|
||||||
uint32_t count = 0;
|
|
||||||
|
|
||||||
if(!state->MemChunk) return;
|
|
||||||
if (!state->cpu_running) { return; }
|
|
||||||
|
|
||||||
state->cpu_running = 0;
|
|
||||||
|
|
||||||
for (count = 0; count < 3; count ++ ) {
|
|
||||||
state->CPU_Action->CloseCPU = 1;
|
|
||||||
state->CPU_Action->DoSomething = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->CPURunning = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t DelaySlotEffectsCompare (usf_state_t * state, uint32_t PC, uint32_t Reg1, uint32_t Reg2) {
|
|
||||||
OPCODE Command;
|
|
||||||
|
|
||||||
if (!r4300i_LW_VAddr(state, PC + 4, (uint32_t*)&Command.u.Hex)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (Command.u.b.op) {
|
|
||||||
case R4300i_SPECIAL:
|
|
||||||
switch (Command.u.e.funct) {
|
|
||||||
case R4300i_SPECIAL_SLL:
|
|
||||||
case R4300i_SPECIAL_SRL:
|
|
||||||
case R4300i_SPECIAL_SRA:
|
|
||||||
case R4300i_SPECIAL_SLLV:
|
|
||||||
case R4300i_SPECIAL_SRLV:
|
|
||||||
case R4300i_SPECIAL_SRAV:
|
|
||||||
case R4300i_SPECIAL_MFHI:
|
|
||||||
case R4300i_SPECIAL_MTHI:
|
|
||||||
case R4300i_SPECIAL_MFLO:
|
|
||||||
case R4300i_SPECIAL_MTLO:
|
|
||||||
case R4300i_SPECIAL_DSLLV:
|
|
||||||
case R4300i_SPECIAL_DSRLV:
|
|
||||||
case R4300i_SPECIAL_DSRAV:
|
|
||||||
case R4300i_SPECIAL_ADD:
|
|
||||||
case R4300i_SPECIAL_ADDU:
|
|
||||||
case R4300i_SPECIAL_SUB:
|
|
||||||
case R4300i_SPECIAL_SUBU:
|
|
||||||
case R4300i_SPECIAL_AND:
|
|
||||||
case R4300i_SPECIAL_OR:
|
|
||||||
case R4300i_SPECIAL_XOR:
|
|
||||||
case R4300i_SPECIAL_NOR:
|
|
||||||
case R4300i_SPECIAL_SLT:
|
|
||||||
case R4300i_SPECIAL_SLTU:
|
|
||||||
case R4300i_SPECIAL_DADD:
|
|
||||||
case R4300i_SPECIAL_DADDU:
|
|
||||||
case R4300i_SPECIAL_DSUB:
|
|
||||||
case R4300i_SPECIAL_DSUBU:
|
|
||||||
case R4300i_SPECIAL_DSLL:
|
|
||||||
case R4300i_SPECIAL_DSRL:
|
|
||||||
case R4300i_SPECIAL_DSRA:
|
|
||||||
case R4300i_SPECIAL_DSLL32:
|
|
||||||
case R4300i_SPECIAL_DSRL32:
|
|
||||||
case R4300i_SPECIAL_DSRA32:
|
|
||||||
if (Command.u.e.rd == 0) { return 0; }
|
|
||||||
if (Command.u.e.rd == Reg1) { return 1; }
|
|
||||||
if (Command.u.e.rd == Reg2) { return 1; }
|
|
||||||
break;
|
|
||||||
case R4300i_SPECIAL_MULT:
|
|
||||||
case R4300i_SPECIAL_MULTU:
|
|
||||||
case R4300i_SPECIAL_DIV:
|
|
||||||
case R4300i_SPECIAL_DIVU:
|
|
||||||
case R4300i_SPECIAL_DMULT:
|
|
||||||
case R4300i_SPECIAL_DMULTU:
|
|
||||||
case R4300i_SPECIAL_DDIV:
|
|
||||||
case R4300i_SPECIAL_DDIVU:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case R4300i_CP0:
|
|
||||||
switch (Command.u.b.rs) {
|
|
||||||
case R4300i_COP0_MT: break;
|
|
||||||
case R4300i_COP0_MF:
|
|
||||||
if (Command.u.b.rt == 0) { return 0; }
|
|
||||||
if (Command.u.b.rt == Reg1) { return 1; }
|
|
||||||
if (Command.u.b.rt == Reg2) { return 1; }
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if ( (Command.u.b.rs & 0x10 ) != 0 ) {
|
|
||||||
switch( state->Opcode.u.e.funct ) {
|
|
||||||
case R4300i_COP0_CO_TLBR: break;
|
|
||||||
case R4300i_COP0_CO_TLBWI: break;
|
|
||||||
case R4300i_COP0_CO_TLBWR: break;
|
|
||||||
case R4300i_COP0_CO_TLBP: break;
|
|
||||||
default:
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case R4300i_CP1:
|
|
||||||
switch (Command.u.f.fmt) {
|
|
||||||
case R4300i_COP1_MF:
|
|
||||||
if (Command.u.b.rt == 0) { return 0; }
|
|
||||||
if (Command.u.b.rt == Reg1) { return 1; }
|
|
||||||
if (Command.u.b.rt == Reg2) { return 1; }
|
|
||||||
break;
|
|
||||||
case R4300i_COP1_CF: break;
|
|
||||||
case R4300i_COP1_MT: break;
|
|
||||||
case R4300i_COP1_CT: break;
|
|
||||||
case R4300i_COP1_S: break;
|
|
||||||
case R4300i_COP1_D: break;
|
|
||||||
case R4300i_COP1_W: break;
|
|
||||||
case R4300i_COP1_L: break;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case R4300i_ANDI:
|
|
||||||
case R4300i_ORI:
|
|
||||||
case R4300i_XORI:
|
|
||||||
case R4300i_LUI:
|
|
||||||
case R4300i_ADDI:
|
|
||||||
case R4300i_ADDIU:
|
|
||||||
case R4300i_SLTI:
|
|
||||||
case R4300i_SLTIU:
|
|
||||||
case R4300i_DADDI:
|
|
||||||
case R4300i_DADDIU:
|
|
||||||
case R4300i_LB:
|
|
||||||
case R4300i_LH:
|
|
||||||
case R4300i_LW:
|
|
||||||
case R4300i_LWL:
|
|
||||||
case R4300i_LWR:
|
|
||||||
case R4300i_LDL:
|
|
||||||
case R4300i_LDR:
|
|
||||||
case R4300i_LBU:
|
|
||||||
case R4300i_LHU:
|
|
||||||
case R4300i_LD:
|
|
||||||
case R4300i_LWC1:
|
|
||||||
case R4300i_LDC1:
|
|
||||||
if (Command.u.b.rt == 0) { return 0; }
|
|
||||||
if (Command.u.b.rt == Reg1) { return 1; }
|
|
||||||
if (Command.u.b.rt == Reg2) { return 1; }
|
|
||||||
break;
|
|
||||||
case R4300i_CACHE: break;
|
|
||||||
case R4300i_SB: break;
|
|
||||||
case R4300i_SH: break;
|
|
||||||
case R4300i_SW: break;
|
|
||||||
case R4300i_SWR: break;
|
|
||||||
case R4300i_SWL: break;
|
|
||||||
case R4300i_SWC1: break;
|
|
||||||
case R4300i_SDC1: break;
|
|
||||||
case R4300i_SD: break;
|
|
||||||
default:
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t DelaySlotEffectsJump (usf_state_t * state, uint32_t JumpPC) {
|
|
||||||
OPCODE Command;
|
|
||||||
|
|
||||||
if (!r4300i_LW_VAddr(state, JumpPC, &Command.u.Hex)) { return 1; }
|
|
||||||
|
|
||||||
switch (Command.u.b.op) {
|
|
||||||
case R4300i_SPECIAL:
|
|
||||||
switch (Command.u.e.funct) {
|
|
||||||
case R4300i_SPECIAL_JR: return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,0);
|
|
||||||
case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,31);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case R4300i_REGIMM:
|
|
||||||
switch (Command.u.b.rt) {
|
|
||||||
case R4300i_REGIMM_BLTZ:
|
|
||||||
case R4300i_REGIMM_BGEZ:
|
|
||||||
case R4300i_REGIMM_BLTZL:
|
|
||||||
case R4300i_REGIMM_BGEZL:
|
|
||||||
case R4300i_REGIMM_BLTZAL:
|
|
||||||
case R4300i_REGIMM_BGEZAL:
|
|
||||||
return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case R4300i_JAL:
|
|
||||||
case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(state,JumpPC,31,0); break;
|
|
||||||
case R4300i_J: return 0;
|
|
||||||
case R4300i_BEQ:
|
|
||||||
case R4300i_BNE:
|
|
||||||
case R4300i_BLEZ:
|
|
||||||
case R4300i_BGTZ:
|
|
||||||
return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,Command.u.b.rt);
|
|
||||||
case R4300i_CP1:
|
|
||||||
switch (Command.u.f.fmt) {
|
|
||||||
case R4300i_COP1_BC:
|
|
||||||
switch (Command.u.f.ft) {
|
|
||||||
case R4300i_COP1_BC_BCF:
|
|
||||||
case R4300i_COP1_BC_BCT:
|
|
||||||
case R4300i_COP1_BC_BCFL:
|
|
||||||
case R4300i_COP1_BC_BCTL:
|
|
||||||
{
|
|
||||||
int32_t EffectDelaySlot;
|
|
||||||
OPCODE NewCommand;
|
|
||||||
|
|
||||||
if (!r4300i_LW_VAddr(state, JumpPC + 4, &NewCommand.u.Hex)) { return 1; }
|
|
||||||
|
|
||||||
EffectDelaySlot = 0;
|
|
||||||
if (NewCommand.u.b.op == R4300i_CP1) {
|
|
||||||
if (NewCommand.u.f.fmt == R4300i_COP1_S && (NewCommand.u.e.funct & 0x30) == 0x30 ) {
|
|
||||||
EffectDelaySlot = 1;
|
|
||||||
}
|
|
||||||
if (NewCommand.u.f.fmt == R4300i_COP1_D && (NewCommand.u.e.funct & 0x30) == 0x30 ) {
|
|
||||||
EffectDelaySlot = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EffectDelaySlot;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case R4300i_BEQL:
|
|
||||||
case R4300i_BNEL:
|
|
||||||
case R4300i_BLEZL:
|
|
||||||
case R4300i_BGTZL:
|
|
||||||
return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,Command.u.b.rt);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoSomething ( usf_state_t * state ) {
|
|
||||||
if (state->CPU_Action->CloseCPU) {
|
|
||||||
//StopEmulation();
|
|
||||||
state->cpu_running = 0;
|
|
||||||
//printf("Stopping?\n");
|
|
||||||
}
|
|
||||||
if (state->CPU_Action->CheckInterrupts) {
|
|
||||||
state->CPU_Action->CheckInterrupts = 0;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
}
|
|
||||||
if (state->CPU_Action->DoInterrupt) {
|
|
||||||
state->CPU_Action->DoInterrupt = 0;
|
|
||||||
DoIntrException(state, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
state->CPU_Action->DoSomething = 0;
|
|
||||||
|
|
||||||
if (state->CPU_Action->DoInterrupt) { state->CPU_Action->DoSomething = 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void InPermLoop ( usf_state_t * state ) {
|
|
||||||
// *** Changed ***/
|
|
||||||
if (state->CPU_Action->DoInterrupt) { return; }
|
|
||||||
|
|
||||||
/* Interrupts enabled */
|
|
||||||
if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { goto InterruptsDisabled; }
|
|
||||||
if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { goto InterruptsDisabled; }
|
|
||||||
if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { goto InterruptsDisabled; }
|
|
||||||
if (( STATUS_REGISTER & 0xFF00) == 0) { goto InterruptsDisabled; }
|
|
||||||
|
|
||||||
/* check sound playing */
|
|
||||||
|
|
||||||
/* check RSP running */
|
|
||||||
/* check RDP running */
|
|
||||||
if (state->Timers->Timer >= 0) {
|
|
||||||
COUNT_REGISTER += state->Timers->Timer + 1;
|
|
||||||
state->Timers->Timer = -1;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
|
|
||||||
InterruptsDisabled:
|
|
||||||
DisplayError(state, "Stuck in Permanent Loop");
|
|
||||||
StopEmulation(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadFromMem(const void * source, void * target, uint32_t length, uint32_t *offset) {
|
|
||||||
memcpy((uint8_t*)target,((uint8_t*)source)+*offset,length);
|
|
||||||
*offset+=length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t Machine_LoadStateFromRAM(usf_state_t * state, void * savestatespace) {
|
|
||||||
uint8_t LoadHeader[0x40];
|
|
||||||
uint32_t Value, count, SaveRDRAMSize, offset=0;
|
|
||||||
|
|
||||||
ReadFromMem( savestatespace,&Value,sizeof(Value),&offset);
|
|
||||||
if (Value != 0x23D8A6C8) { return 0; }
|
|
||||||
ReadFromMem( savestatespace,&SaveRDRAMSize,sizeof(SaveRDRAMSize),&offset);
|
|
||||||
ReadFromMem( savestatespace,&LoadHeader,0x40,&offset);
|
|
||||||
|
|
||||||
state->Timers->CurrentTimerType = -1;
|
|
||||||
state->Timers->Timer = 0;
|
|
||||||
for (count = 0; count < MaxTimers; count ++) { state->Timers->Active[count] = 0; }
|
|
||||||
|
|
||||||
//fix rdram size
|
|
||||||
if (SaveRDRAMSize != state->RdramSize) {
|
|
||||||
// dothis :)
|
|
||||||
}
|
|
||||||
|
|
||||||
state->RdramSize = SaveRDRAMSize;
|
|
||||||
|
|
||||||
ReadFromMem( savestatespace,&Value,sizeof(Value),&offset);
|
|
||||||
ChangeTimer(state,ViTimer,Value);
|
|
||||||
ReadFromMem( savestatespace,&state->PROGRAM_COUNTER,sizeof(state->PROGRAM_COUNTER),&offset);
|
|
||||||
ReadFromMem( savestatespace,state->GPR,sizeof(int64_t)*32,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->FPR,sizeof(int64_t)*32,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->CP0,sizeof(uint32_t)*32,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->FPCR,sizeof(uint32_t)*32,&offset);
|
|
||||||
ReadFromMem( savestatespace,&state->HI,sizeof(int64_t),&offset);
|
|
||||||
ReadFromMem( savestatespace,&state->LO,sizeof(int64_t),&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RegRDRAM,sizeof(uint32_t)*10,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RegSP,sizeof(uint32_t)*10,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RegDPC,sizeof(uint32_t)*10,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RegMI,sizeof(uint32_t)*4,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RegVI,sizeof(uint32_t)*14,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RegAI,sizeof(uint32_t)*6,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RegPI,sizeof(uint32_t)*13,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RegRI,sizeof(uint32_t)*8,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RegSI,sizeof(uint32_t)*4,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->tlb,sizeof(TLB)*32,&offset);
|
|
||||||
ReadFromMem( savestatespace,(uint8_t*)state->PIF_Ram,0x40,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->RDRAM,SaveRDRAMSize,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->DMEM,0x1000,&offset);
|
|
||||||
ReadFromMem( savestatespace,state->IMEM,0x1000,&offset);
|
|
||||||
|
|
||||||
state->CP0[32] = 0;
|
|
||||||
|
|
||||||
SetupTLB(state);
|
|
||||||
ChangeCompareTimer(state);
|
|
||||||
AI_STATUS_REG = 0;
|
|
||||||
AiDacrateChanged(state, AI_DACRATE_REG);
|
|
||||||
|
|
||||||
// StartAiInterrupt(state);
|
|
||||||
|
|
||||||
SetFpuLocations(state); // important if FR=1
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartEmulationFromSave ( usf_state_t * state, void * savestate ) {
|
|
||||||
uint32_t count = 0;
|
|
||||||
|
|
||||||
//printf("Starting generic Cpu\n");
|
|
||||||
|
|
||||||
//CloseCpu();
|
|
||||||
memset(state->N64MEM, 0, state->RdramSize);
|
|
||||||
|
|
||||||
memset(state->DMEM, 0, 0x1000);
|
|
||||||
memset(state->IMEM, 0, 0x1000);
|
|
||||||
memset(state->TLB_Map, 0, 0x100000 * sizeof(uintptr_t) + 0x10000);
|
|
||||||
|
|
||||||
memset(state->CPU_Action,0,sizeof(*state->CPU_Action));
|
|
||||||
state->WrittenToRom = 0;
|
|
||||||
|
|
||||||
InitilizeTLB(state);
|
|
||||||
|
|
||||||
SetupRegisters(state, state->Registers);
|
|
||||||
|
|
||||||
BuildInterpreter(state);
|
|
||||||
|
|
||||||
state->Timers->CurrentTimerType = -1;
|
|
||||||
state->Timers->Timer = 0;
|
|
||||||
|
|
||||||
for (count = 0; count < MaxTimers; count ++) { state->Timers->Active[count] = 0; }
|
|
||||||
ChangeTimer(state,ViTimer,5000);
|
|
||||||
ChangeCompareTimer(state);
|
|
||||||
state->ViFieldNumber = 0;
|
|
||||||
state->CPURunning = 1;
|
|
||||||
*state->WaitMode = 0;
|
|
||||||
|
|
||||||
init_rsp(state);
|
|
||||||
|
|
||||||
Machine_LoadStateFromRAM(state, savestate);
|
|
||||||
|
|
||||||
state->SampleRate = 48681812 / (AI_DACRATE_REG + 1);
|
|
||||||
|
|
||||||
if(state->enableFIFOfull) {
|
|
||||||
const float VSyncTiming = 789000.0f;
|
|
||||||
double BytesPerSecond = 48681812.0 / (AI_DACRATE_REG + 1) * 4;
|
|
||||||
double CountsPerSecond = (double)(((double)VSyncTiming) * (double)60.0);
|
|
||||||
double CountsPerByte = (double)CountsPerSecond / (double)BytesPerSecond;
|
|
||||||
uint32_t IntScheduled = (uint32_t)((double)AI_LEN_REG * CountsPerByte);
|
|
||||||
|
|
||||||
ChangeTimer(state,AiTimer,IntScheduled);
|
|
||||||
AI_STATUS_REG|=0x40000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->OLD_VI_V_SYNC_REG = ~VI_V_SYNC_REG;
|
|
||||||
|
|
||||||
CPUHLE_Scan(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void RefreshScreen (usf_state_t * state){
|
|
||||||
if (state->OLD_VI_V_SYNC_REG != VI_V_SYNC_REG)
|
|
||||||
{
|
|
||||||
state->OLD_VI_V_SYNC_REG = VI_V_SYNC_REG;
|
|
||||||
if (VI_V_SYNC_REG == 0)
|
|
||||||
{
|
|
||||||
state->VI_INTR_TIME = 500000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state->VI_INTR_TIME = (VI_V_SYNC_REG + 1) * 1500;
|
|
||||||
if ((VI_V_SYNC_REG & 1) != 0)
|
|
||||||
{
|
|
||||||
state->VI_INTR_TIME -= 38;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChangeTimer(state,ViTimer,state->Timers->Timer + state->Timers->NextTimer[ViTimer] + state->VI_INTR_TIME);
|
|
||||||
|
|
||||||
if ((VI_STATUS_REG & 0x10) != 0)
|
|
||||||
{
|
|
||||||
if (state->ViFieldNumber == 0)
|
|
||||||
{
|
|
||||||
state->ViFieldNumber = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state->ViFieldNumber = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state->ViFieldNumber = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunRsp (usf_state_t * state) {
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
fprintf(state->debug_log, "RSP Task:");
|
|
||||||
#endif
|
|
||||||
if ( ( SP_STATUS_REG & SP_STATUS_HALT ) == 0) {
|
|
||||||
if ( ( SP_STATUS_REG & SP_STATUS_BROKE ) == 0 ) {
|
|
||||||
|
|
||||||
uint32_t Task = *( uint32_t *)(state->DMEM + 0xFC0);
|
|
||||||
|
|
||||||
switch (Task) {
|
|
||||||
case 1: {
|
|
||||||
MI_INTR_REG |= 0x20;
|
|
||||||
|
|
||||||
SP_STATUS_REG |= (0x0203 );
|
|
||||||
if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 )
|
|
||||||
MI_INTR_REG |= 1;
|
|
||||||
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
fprintf(state->debug_log, " DList - interrupts %d\n", MI_INTR_REG);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CheckInterrupts(state);
|
|
||||||
|
|
||||||
DPC_STATUS_REG &= ~0x0002;
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2: {
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
fprintf(state->debug_log, " AList");
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
real_run_rsp(state, 100);
|
|
||||||
SP_STATUS_REG |= (0x0203 );
|
|
||||||
if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) {
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
fprintf(state->debug_log, " - interrupt");
|
|
||||||
#endif
|
|
||||||
MI_INTR_REG |= 1;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
fprintf(state->debug_log, "\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerDone (usf_state_t * state) {
|
|
||||||
switch (state->Timers->CurrentTimerType) {
|
|
||||||
case CompareTimer:
|
|
||||||
if(state->enablecompare)
|
|
||||||
FAKE_CAUSE_REGISTER |= CAUSE_IP7;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
ChangeCompareTimer(state);
|
|
||||||
break;
|
|
||||||
case ViTimer:
|
|
||||||
RefreshScreen(state);
|
|
||||||
MI_INTR_REG |= MI_INTR_VI;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
*state->WaitMode=0;
|
|
||||||
break;
|
|
||||||
case AiTimer:
|
|
||||||
ChangeTimer(state,AiTimer,0);
|
|
||||||
AI_STATUS_REG=0;
|
|
||||||
state->AudioIntrReg|=4;
|
|
||||||
//CheckInterrupts(state);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CheckTimer(state);
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef _CPU_H_
|
|
||||||
#define _CPU_H_
|
|
||||||
|
|
||||||
#include "interpreter_cpu.h"
|
|
||||||
#include "interpreter_ops.h"
|
|
||||||
#include "registers.h"
|
|
||||||
#include "tlb.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "dma.h"
|
|
||||||
#include "exception.h"
|
|
||||||
#include "pif.h"
|
|
||||||
#include "opcode.h"
|
|
||||||
#include "usf.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t DoSomething;
|
|
||||||
int32_t CloseCPU;
|
|
||||||
int32_t CheckInterrupts;
|
|
||||||
int32_t DoInterrupt;
|
|
||||||
} CPU_ACTION;
|
|
||||||
|
|
||||||
#define MaxTimers 3
|
|
||||||
#define CompareTimer 0
|
|
||||||
#define ViTimer 1
|
|
||||||
#define AiTimer 2
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t NextTimer[MaxTimers];
|
|
||||||
int32_t Active[MaxTimers];
|
|
||||||
int32_t CurrentTimerType;
|
|
||||||
int32_t Timer;
|
|
||||||
} SYSTEM_TIMERS;
|
|
||||||
|
|
||||||
void ChangeCompareTimer ( usf_state_t * );
|
|
||||||
void ChangeTimer ( usf_state_t *, int32_t Type, int32_t Value );
|
|
||||||
void CheckTimer ( usf_state_t * );
|
|
||||||
void CloseCpu ( usf_state_t * );
|
|
||||||
int32_t DelaySlotEffectsCompare ( usf_state_t *, uint32_t PC, uint32_t Reg1, uint32_t Reg2 );
|
|
||||||
int32_t DelaySlotEffectsJump ( usf_state_t *, uint32_t JumpPC);
|
|
||||||
void DoSomething ( usf_state_t * );
|
|
||||||
void InPermLoop ( usf_state_t * );
|
|
||||||
void InitiliazeCPUFlags ( usf_state_t * );
|
|
||||||
void RefreshScreen ( usf_state_t * );
|
|
||||||
void RunRsp ( usf_state_t * );
|
|
||||||
void StartEmulation ( usf_state_t * );
|
|
||||||
void TimerDone ( usf_state_t * );
|
|
||||||
void RecompileTimerDone ( usf_state_t * );
|
|
||||||
|
|
||||||
#define NORMAL 0
|
|
||||||
#define DO_DELAY_SLOT 1
|
|
||||||
#define DO_END_DELAY_SLOT 2
|
|
||||||
#define DELAY_SLOT 3
|
|
||||||
#define END_DELAY_SLOT 4
|
|
||||||
#define LIKELY_DELAY_SLOT 5
|
|
||||||
#define JUMP 6
|
|
||||||
#define DELAY_SLOT_DONE 7
|
|
||||||
#define LIKELY_DELAY_SLOT_DONE 8
|
|
||||||
#define END_BLOCK 9
|
|
||||||
|
|
||||||
enum SaveType {
|
|
||||||
Auto,
|
|
||||||
Eeprom_4K,
|
|
||||||
Eeprom_16K,
|
|
||||||
Sram,
|
|
||||||
FlashRam
|
|
||||||
};
|
|
||||||
|
|
||||||
void StartEmulationFromSave ( usf_state_t * state, void * savestate );
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,161 +0,0 @@
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "usf.h"
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
#include "cpu_hle.h"
|
|
||||||
#include "os.h"
|
|
||||||
#include "audiolib.h"
|
|
||||||
|
|
||||||
// Nintendo 64 Standard (and non standard) library functions, for HLE
|
|
||||||
|
|
||||||
|
|
||||||
int numEntries = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_HLE_Entry entrys[] = {
|
|
||||||
{"__osEnqueueThread",0,20,{0x8C,0x98,0,0,0x8C,0xAF,0,4,0,0x80,0xC8,0x25,0x8F,0xE,0,4,1,0xCF,8,0x2A},0,0,__osEnqueueThread},
|
|
||||||
|
|
||||||
{"__osRestoreInt",0,28,{0x40,8,0x60,0 ,1,4,0x40,0x25,0x40,0x88,0x60,0,0,0,0,0,0,0,0,0,3,0xE0,0,8,0,0,0,0},0,0,__osRestoreInt},
|
|
||||||
{"__osDisableInt",0,32,{0x40,8,0x60,0,0x24,1,0xFF,0xFE,1,1,0x48,0x24,0x40,0x89,0x60,0,0x31,2,0,1,0,0,0,0,3,0xE0,0,8,0,0,0,0},0,0,__osDisableInt},
|
|
||||||
// {"osStartThread",0,32,{0x27,0xBD,0xFF,0xD8,0xAF,0xBF,0,0x1C,0xAF,0xA4,0,0x28,0xAF,0xB1,0,0x18,0xC,-1,-1,-1,0xAF,0xB0,0,0x14,0x8F,0xAE,0,0x28,0x24,1,0,1,0,0x40,0x80,0x25},0,0,osStartThread},
|
|
||||||
//{"osPiStartDma",0,52,{0x27,0xBD,0xFF,0xD8,0x3C,0xE,-1,-1,0x8D,0xCE,-1,-1,0xAF,0xBF,0,0x1C,0xAF,0xA4,0,0x28,0xAF,0xA5,0,0x2C,0xAF,0xA6,0,0x30,0xAF,0xA7,0,0x34,0xAF,0xB1,0,0x18,0x15,0xC0,0,3,0xAF,0xB0,0,0x14,0x10,0,0,0x32,0x24,2,0xFF,0xFF},0,0,osPiStartDma}
|
|
||||||
//{"osRecvMesg",0,60,{0x27,0xBD,0xFF,0xD8,0xAF,0xBF,0,0x1C,0xAF,0xA4,0,0x28,0xAF,0xA5,0,0x2C,0xAF,0xA6,0,0x30,0xAF,0xB1,0,0x18,0xC,-1,-1,-1,0xAF,0xB0,0,0x14,0x8F,0xAE,0,0x28,0,0x40,0x80,0x25,0x8D,0xCF,0,8,0x15,0xE0,0,0x12,0,0,0,0,0x8f,0xb8,0,0x30,0x17,0,0,5},0,0,osRecvMesg},
|
|
||||||
|
|
||||||
{"saveThreadContext",0,32,{0x3C,5,-1,-1,0x8C,0xA5,-1,-1,0x40,8,0x60,0,0x8C,0xBB,0,0x18,0x35,8,0,2,0xAC,0xA8,1,0x18,0xFC,0xB0,0,0x98,0xFC,0xB1,0,0xA0},0,0,saveThreadContext},
|
|
||||||
{"loadThreadContext",0,40,{0x3C,4,-1,-1,0xC,-1,-1,-1,0x24,0x84,-1,-1,0x3C,1,-1,-1,0xAC,0x22,-1,-1,0x24,8,0,4,0xA4,0x48,0,0x10,0,0x40,0xD0,0x25,0x3C,8,-1,-1,0x8F,0x5B,1,0x18},0,0,loadThreadContext},
|
|
||||||
|
|
||||||
|
|
||||||
{"osSetIntMask",0,44,{0x40,0xC,0x60,0,0x31,0x82,0xFF,1,0x3C,8,-1,-1,0x25,8,-1,-1,0x8D,0xB,0,0,0x24,1,0xFF,0xFF,1,0x61,0x40,0x26,0x31,8,0xFF,0,0,0x48,0x10,0x25,0x3C,0xA,0xA4,0x30,0x8D,0x4A,0,0xC},0,0,osSetIntMask},
|
|
||||||
{"osVirtualToPhysical",0,36,{0x27,0xBD,0xFF,0xE8,0xAF,0xA4,0,0x18,0x8F,0xAE,0,0x18,0x3C,1,0x80,0,0xAF,0xBF,0,0x14,1,0xC1,8,0x2B,0x14,0x20,0,7,0x3C,1,0xA0,0,1,0xC1,8,0x2B},0,0,osVirtualToPhysical},
|
|
||||||
|
|
||||||
|
|
||||||
{"alCopy",0,32,{0,0x80,0x10,0x25,0,0xA0,0x18,0x25,0x18,0xC0,0,0x18,0,0,0x38,0x25,0x30,0xC5,0,3,0x10,0xA0,0,9,0,0xA0,0x20,0x25,0x90,0x4E,0,0},0,0,alCopy},
|
|
||||||
{"alLink",0,28,{0x8C,0xAE,0,0,0xAC,0x85,0,4,0xAC,0x8E,0,0,0x8C,0xA2,0,0,0x10,0x40,0,2,0,0,0,0,0xAC,0x44,0,4},0,0,alLink},
|
|
||||||
{"alUnlink",0,28,{0x8C,0x82,0,0,0x50,0x40,0,4,0x8C,0x82,0,4,0x8C,0x8E,0,4,0xAC,0x4E,0,4,0x8C,0x82,0,4,0x10,0x40,0,3},0,0,alUnLink},
|
|
||||||
|
|
||||||
{"osAiSetNextBuffer",0,32,{0x27,0xBD,0xFF,0xE0,0x3C,0xF,-1,-1,0x91,0xEF,-1,-1,0xAF,0xA4,0,0x20,0x8F,0xAE,0,0x20,0xAF,0xBF,0,0x14,0xAF,0xA5,0,0x24,0x11,0xE0,0,3},0,0,osAiSetNextBuffer},
|
|
||||||
|
|
||||||
{"alLink (DK64)",0,20,{0x8C,0xAE,0,0,0xAC,0x8E,0,0,0xAC,0x85,0,4,0x8C,0xAF,0,0,0x11,0xE0,0,3},0,0,alLink},
|
|
||||||
{"alUnLink (DK64)",0,28,{0x8C,0x8E,0,0,0x11,0xC0,0,4,0,0,0,0,0x8C,0x8F,0,4,0x8C,0x98,0,0,0xAF,0xF,0,4,0x8C,0x99,0,4},0,0,alUnLink},
|
|
||||||
|
|
||||||
{"alEvtqPostEvent",0,64,{0x27,0xBD,0xFF,0xD0,0xAF,0xBF,0,0x14,0xAF,0xA4,0,0x30,0xAF,0xA5,0,0x34,0xAF,0xA0,0,0x20,0x24,4,0,1,0xC,-1,-1,-1,0xAF,0xA6,0,0x38,0x8F,0xAE,0,0x30,0x8F,0xA7,0,0x38,0,0x40,0x28,0x25,0x8D,0xC8,0,0,0x15,0,0,5,1,0,0x20,0x25,0xC,-1,-1,-1,0,0x40,0x20,0x25},0,0,alEvtqPostEvent},
|
|
||||||
|
|
||||||
{"alEvtqPostEvent (DK64)",0,64,{0x27,0xBD,0xFF,0xD0,0xAF,0xBF,0,0x14,0xAF,0xA4,0,0x30,0xAF,0xA5,0,0x34,0xAF,0xA6,0,0x38,0xAF,0xA0,0,0x20,0xC,-1,-1,-1,0x24,4,0,1,0xAF,0xA2,0,0x1C,0x8F,0xAE,0,0x30,0x8D,0xCF,0,0,0xAF,0xAF,0,0x2C,0x8F,0xB8,0,0x2C,0x17,0,0,5,0,0,0,0,0xC,-1,-1,-1,0x8F,0xA4,0,0x1C},0,0,alEvtqPostEvent},
|
|
||||||
{"alEvtqPostEvent (CBFD)",0,56,{0x27,0xBD,0xFF,0xC0,0xAF,0xBF,0,0x14,0xAF,0xA4,0,0x40,0xAF,0xA5,0,0x44,0xAF,0xA6,0,0x48,0xAF,0xA7,0,0x4C,0xAF,0xA0,0,0x30,0x8F,0xAE,0,0x4C,0x31,0xCF,0,2,0x11,0xE0,0,4,0,0,0,0,0xC,-1,-1,-1,0x24,4,0,1,0xAF,0xA2,0,0x2C},0,0,alEvtqPostEvent},
|
|
||||||
{"alEvtqPostEvent (BT)",0,60,{0x27,0xBD,0xFF,0xD0,0xAF,0xBF,0,0x14,0xAF,0xA4,0,0x30,0xAF,0xA5,0,0x34,0xAF,0xA6,0,0x38,0xAF,0xA7,0,0x3C,0xAF,0xA0,0,0x20,0xC,-1,-1,-1,0x24,4,0,1,0xAF,0xA2,0,0x1C,0x8F,0xAE,0,0x30,0x8D,0xCF,0,0,0xAF,0xAF,0,0x2C,0x8F,0xB8,0,0x2C,0x17,0,0,5},0,0,alEvtqPostEvent},
|
|
||||||
|
|
||||||
{"alAudioFrame",0,52,{0x27,0xBD,0xFF,0x48,0xAF,0xB1,0,0x30,0x3C,0x11,-1,-1,0x8E,0x31,0-1,-1,0xAF,0xBF,0,0x4C,0xAF,0xB7,0,0x48,0xAF,0xB6,0,0x44,0xAF,0xB5,0,0x40,0xAF,0xB4,0,0x3C,0xAF,0xB3,0,0x38,0xAF,0xB2,0,0x34,0xAF,0xB0,0,0x2C,0xF7,0xB6,0,0x20},0,0,alAudioFrame},
|
|
||||||
|
|
||||||
//{"alAudioFrame (DK64)",0,64,{0x27,0xBD,0xFF,0xC0,0xAF,0xBF,0,0x1C,0xAF,0xA4,0,0x40,0xAF,0xA5,0,0x44,0xAF,0xA6,0,0x48,0xAF,0xA7,0,0x4C,0xAF,0xB1,0,0x18,0xAF,0xB0,0,0x14,0xA7,0xA0,0,0x3A,0x8F,0xAE,0,0x40,0xAF,0xAE,0,0x34,0x8F,0xAF,0,0x48,0xAF,0xAF,0,0x28,0x3C,0x18,0x80,0x75,0x8F,0x18,0xC,0x74,0x8F,0x19,0,0},0,0,alAudioFrame},
|
|
||||||
|
|
||||||
};
|
|
||||||
//int 0xA4,0xA6,0,0x38
|
|
||||||
|
|
||||||
//char foundlist[2048];
|
|
||||||
|
|
||||||
int sort_entrys(void * a, void * b)
|
|
||||||
{
|
|
||||||
_HLE_Entry * _a = (_HLE_Entry *)a;
|
|
||||||
_HLE_Entry * _b = (_HLE_Entry *)b;
|
|
||||||
return _b->used - _a->used;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CPUHLE_Scan(usf_state_t * state)
|
|
||||||
{
|
|
||||||
int i = 0, j = 0;
|
|
||||||
unsigned char c = 0;
|
|
||||||
long d = 0;
|
|
||||||
int entrySize = 0;
|
|
||||||
int entry = 0;
|
|
||||||
void * address = 0;
|
|
||||||
int good = 1; //, needcomma = 0;
|
|
||||||
_HLE_Entry * entries;
|
|
||||||
unsigned entries_used = 0;
|
|
||||||
|
|
||||||
numEntries = sizeof(entrys) / sizeof(_HLE_Entry);
|
|
||||||
|
|
||||||
entries = state->cpu_hle_entries = realloc( state->cpu_hle_entries, sizeof(entrys) );
|
|
||||||
memcpy( entries, entrys, sizeof(entrys) );
|
|
||||||
|
|
||||||
//for(i=0; i < numEntries; i++)
|
|
||||||
// entries[i].used = 0;
|
|
||||||
|
|
||||||
//memset(foundlist,0,2048);
|
|
||||||
|
|
||||||
for(i=0; i < (state->RdramSize - 64); i+=4) {
|
|
||||||
|
|
||||||
for(entry = 0; entry < numEntries; entry++) {
|
|
||||||
|
|
||||||
if(entries[entry].used)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
good = 1;
|
|
||||||
entrySize = entries[entry].length;
|
|
||||||
|
|
||||||
for(j=0; j < entrySize; j++) {
|
|
||||||
address = state->N64MEM + i + j;
|
|
||||||
//address = i;
|
|
||||||
c = *(unsigned char *)(address);
|
|
||||||
d = entries[entry].bytes[j^3];
|
|
||||||
|
|
||||||
if((c != d) && (d!=-1)) {
|
|
||||||
good = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(good == 1 && i< (state->RdramSize-64)) {
|
|
||||||
//char buf[256];
|
|
||||||
//if(needcomma) {
|
|
||||||
// sprintf(buf,", %s", entries[entry].name);
|
|
||||||
//} else {
|
|
||||||
// sprintf(buf,"%s", entries[entry].name);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//needcomma = 1;
|
|
||||||
//strcat(foundlist,buf);
|
|
||||||
|
|
||||||
entries[entry].used = 1;
|
|
||||||
entries[entry].phys = i;
|
|
||||||
++entries_used;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(entries, numEntries, sizeof(*entries), sort_entrys);
|
|
||||||
state->cpu_hle_entry_count = entries_used;
|
|
||||||
|
|
||||||
//printf("<--------------HLE Functions Found--------------->\n%s<------------------------------------------------>\n", foundlist);
|
|
||||||
//printf("HLE Functions found: %s\n", foundlist);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DoCPUHLE(usf_state_t * state, unsigned long loc)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
uintptr_t real_addr = PageVRAM2(loc);
|
|
||||||
_HLE_Entry * entries = state->cpu_hle_entries;
|
|
||||||
unsigned numEntries = state->cpu_hle_entry_count;
|
|
||||||
|
|
||||||
for(i = 0; i < numEntries; i++) {
|
|
||||||
|
|
||||||
if(entries[i].phys == real_addr) {
|
|
||||||
//printf("CPU HLEing using %d at %08x (phys: %08x) \"%s\"\n", entries[i].name, loc, entries[i].phys, entries[i].name);
|
|
||||||
|
|
||||||
if(entries[i].location(state, entries[i].phys)) {
|
|
||||||
// printf("done\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
#ifndef _CPU_HLE_
|
|
||||||
#define _CPU_HLE_
|
|
||||||
|
|
||||||
#include "usf.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "interpreter_ops.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *name;
|
|
||||||
int num;
|
|
||||||
int length;
|
|
||||||
long bytes[80];
|
|
||||||
int used;
|
|
||||||
int phys;
|
|
||||||
int (*location)(usf_state_t *, int);
|
|
||||||
} _HLE_Entry;
|
|
||||||
|
|
||||||
int CPUHLE_Scan(usf_state_t *);
|
|
||||||
int DoCPUHLE(usf_state_t *, unsigned long loc);
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// OS Thread Stuff
|
|
||||||
// found this stuff in daedalus
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,183 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
|
|
||||||
#include "usf.h"
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
void PI_DMA_READ (usf_state_t * state) {
|
|
||||||
|
|
||||||
PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
||||||
MI_INTR_REG |= MI_INTR_PI;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PI_DMA_WRITE (usf_state_t * state) {
|
|
||||||
uint32_t i;
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
fprintf(state->debug_log, "PI DMA WRITE: %08x to %08x for %08x bytes\n", PI_CART_ADDR_REG, PI_DRAM_ADDR_REG, PI_WR_LEN_REG + 1);
|
|
||||||
#endif
|
|
||||||
PI_STATUS_REG |= PI_STATUS_DMA_BUSY;
|
|
||||||
if ( PI_DRAM_ADDR_REG + PI_WR_LEN_REG + 1 > state->RdramSize) {
|
|
||||||
PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
||||||
MI_INTR_REG |= MI_INTR_PI;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( PI_CART_ADDR_REG >= 0x08000000 && PI_CART_ADDR_REG <= 0x08010000) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( PI_CART_ADDR_REG >= 0x10000000 && PI_CART_ADDR_REG <= 0x1FBFFFFF) {
|
|
||||||
PI_CART_ADDR_REG -= 0x10000000;
|
|
||||||
for (i = 0; i < PI_WR_LEN_REG + 1; i ++) {
|
|
||||||
*(state->N64MEM+((PI_DRAM_ADDR_REG + i) ^ 3)) = *PageROM(state, (PI_CART_ADDR_REG + i) ^ 3);
|
|
||||||
}
|
|
||||||
PI_CART_ADDR_REG += 0x10000000;
|
|
||||||
|
|
||||||
PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
||||||
MI_INTR_REG |= MI_INTR_PI;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
CheckTimer(state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
||||||
MI_INTR_REG |= MI_INTR_PI;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SI_DMA_READ (usf_state_t * state) {
|
|
||||||
|
|
||||||
if ((int32_t)SI_DRAM_ADDR_REG > (int32_t)state->RdramSize) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PifRamRead(state);
|
|
||||||
SI_DRAM_ADDR_REG &= 0xFFFFFFF8;
|
|
||||||
if ((int32_t)SI_DRAM_ADDR_REG < 0) {
|
|
||||||
int32_t count, RdramPos;
|
|
||||||
|
|
||||||
RdramPos = (int32_t)SI_DRAM_ADDR_REG;
|
|
||||||
for (count = 0; count < 0x40; count++, RdramPos++) {
|
|
||||||
if (RdramPos < 0) { continue; }
|
|
||||||
state->N64MEM[RdramPos ^3] = state->PIF_Ram[count];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int32_t count, RdramPos;
|
|
||||||
|
|
||||||
RdramPos = (uint32_t)SI_DRAM_ADDR_REG;
|
|
||||||
for (count = 0; count < 0x40; count++, RdramPos++) {
|
|
||||||
if (RdramPos < 0) { continue; }
|
|
||||||
state->N64MEM[RdramPos ^3] = state->PIF_Ram[count];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MI_INTR_REG |= MI_INTR_SI;
|
|
||||||
SI_STATUS_REG |= SI_STATUS_INTERRUPT;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SI_DMA_WRITE (usf_state_t * state) {
|
|
||||||
|
|
||||||
if ((int32_t)SI_DRAM_ADDR_REG > (int32_t)state->RdramSize) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SI_DRAM_ADDR_REG &= 0xFFFFFFF8;
|
|
||||||
if ((int32_t)SI_DRAM_ADDR_REG < 0) {
|
|
||||||
int32_t count, RdramPos;
|
|
||||||
|
|
||||||
RdramPos = (int32_t)SI_DRAM_ADDR_REG;
|
|
||||||
for (count = 0; count < 0x40; count++, RdramPos++) {
|
|
||||||
if (RdramPos < 0) { state->PIF_Ram[count] = 0; continue; }
|
|
||||||
state->PIF_Ram[count] = state->N64MEM[RdramPos ^3];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int32_t count, RdramPos;
|
|
||||||
|
|
||||||
RdramPos = (int32_t)SI_DRAM_ADDR_REG;
|
|
||||||
for (count = 0; count < 0x40; count++, RdramPos++) {
|
|
||||||
if (RdramPos < 0) { state->PIF_Ram[count] = 0; continue; }
|
|
||||||
state->PIF_Ram[count] = state->N64MEM[RdramPos ^3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PifRamWrite(state);
|
|
||||||
|
|
||||||
MI_INTR_REG |= MI_INTR_SI;
|
|
||||||
SI_STATUS_REG |= SI_STATUS_INTERRUPT;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SP_DMA_READ (usf_state_t * state) {
|
|
||||||
SP_DRAM_ADDR_REG &= 0x1FFFFFFF;
|
|
||||||
|
|
||||||
if (SP_DRAM_ADDR_REG > state->RdramSize) {
|
|
||||||
SP_DMA_BUSY_REG = 0;
|
|
||||||
SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SP_RD_LEN_REG + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy( state->DMEM + (SP_MEM_ADDR_REG & 0x1FFF), state->N64MEM + SP_DRAM_ADDR_REG,
|
|
||||||
SP_RD_LEN_REG + 1 );
|
|
||||||
|
|
||||||
SP_DMA_BUSY_REG = 0;
|
|
||||||
SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
|
|
||||||
MI_INTR_REG &= ~MI_INTR_SP;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
CheckTimer(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SP_DMA_WRITE (usf_state_t * state) {
|
|
||||||
if (SP_DRAM_ADDR_REG > state->RdramSize) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SP_WR_LEN_REG + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy( state->N64MEM + SP_DRAM_ADDR_REG, state->DMEM + (SP_MEM_ADDR_REG & 0x1FFF),
|
|
||||||
SP_WR_LEN_REG + 1);
|
|
||||||
|
|
||||||
SP_DMA_BUSY_REG = 0;
|
|
||||||
SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void PI_DMA_READ ( usf_state_t * );
|
|
||||||
void PI_DMA_WRITE ( usf_state_t * );
|
|
||||||
void SI_DMA_READ ( usf_state_t * );
|
|
||||||
void SI_DMA_WRITE ( usf_state_t * );
|
|
||||||
void SP_DMA_READ ( usf_state_t * );
|
|
||||||
void SP_DMA_WRITE ( usf_state_t * );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
void CheckInterrupts ( usf_state_t * state ) {
|
|
||||||
|
|
||||||
MI_INTR_REG &= ~MI_INTR_AI;
|
|
||||||
MI_INTR_REG |= (state->AudioIntrReg & MI_INTR_AI);
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
if (MI_INTR_REG)
|
|
||||||
fprintf(state->debug_log, "Interrupt %d - ", MI_INTR_REG);
|
|
||||||
#endif
|
|
||||||
if ((MI_INTR_MASK_REG & MI_INTR_REG) != 0) {
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
fprintf(state->debug_log, "triggered\n");
|
|
||||||
#endif
|
|
||||||
FAKE_CAUSE_REGISTER |= CAUSE_IP2;
|
|
||||||
} else {
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
if (MI_INTR_REG)
|
|
||||||
fprintf(state->debug_log, "masked\n");
|
|
||||||
#endif
|
|
||||||
FAKE_CAUSE_REGISTER &= ~CAUSE_IP2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { return; }
|
|
||||||
if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { return; }
|
|
||||||
if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { return; }
|
|
||||||
|
|
||||||
if (( STATUS_REGISTER & FAKE_CAUSE_REGISTER & 0xFF00) != 0) {
|
|
||||||
if (!state->CPU_Action->DoInterrupt) {
|
|
||||||
state->CPU_Action->DoSomething = 1;
|
|
||||||
state->CPU_Action->DoInterrupt = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoAddressError ( usf_state_t * state, uint32_t DelaySlot, uint32_t BadVaddr, uint32_t FromRead) {
|
|
||||||
if (FromRead) {
|
|
||||||
CAUSE_REGISTER = EXC_RADE;
|
|
||||||
} else {
|
|
||||||
CAUSE_REGISTER = EXC_WADE;
|
|
||||||
}
|
|
||||||
BAD_VADDR_REGISTER = BadVaddr;
|
|
||||||
if (DelaySlot) {
|
|
||||||
CAUSE_REGISTER |= CAUSE_BD;
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
|
|
||||||
} else {
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER;
|
|
||||||
}
|
|
||||||
STATUS_REGISTER |= STATUS_EXL;
|
|
||||||
state->PROGRAM_COUNTER = 0x80000180;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoBreakException ( usf_state_t * state, uint32_t DelaySlot) {
|
|
||||||
CAUSE_REGISTER = EXC_BREAK;
|
|
||||||
if (DelaySlot) {
|
|
||||||
CAUSE_REGISTER |= CAUSE_BD;
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
|
|
||||||
} else {
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER;
|
|
||||||
}
|
|
||||||
STATUS_REGISTER |= STATUS_EXL;
|
|
||||||
state->PROGRAM_COUNTER = 0x80000180;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoCopUnusableException ( usf_state_t * state, uint32_t DelaySlot, uint32_t Coprocessor ) {
|
|
||||||
CAUSE_REGISTER = EXC_CPU;
|
|
||||||
if (Coprocessor == 1) { CAUSE_REGISTER |= 0x10000000; }
|
|
||||||
if (DelaySlot) {
|
|
||||||
CAUSE_REGISTER |= CAUSE_BD;
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
|
|
||||||
} else {
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER;
|
|
||||||
}
|
|
||||||
STATUS_REGISTER |= STATUS_EXL;
|
|
||||||
state->PROGRAM_COUNTER = 0x80000180;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoIntrException ( usf_state_t * state, uint32_t DelaySlot ) {
|
|
||||||
|
|
||||||
if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { return; }
|
|
||||||
if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { return; }
|
|
||||||
if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { return; }
|
|
||||||
CAUSE_REGISTER = FAKE_CAUSE_REGISTER;
|
|
||||||
CAUSE_REGISTER |= EXC_INT;
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER;
|
|
||||||
if (DelaySlot) {
|
|
||||||
CAUSE_REGISTER |= CAUSE_BD;
|
|
||||||
EPC_REGISTER -= 4;
|
|
||||||
}
|
|
||||||
STATUS_REGISTER |= STATUS_EXL;
|
|
||||||
state->PROGRAM_COUNTER = 0x80000180;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoTLBMiss ( usf_state_t * state, uint32_t DelaySlot, uint32_t BadVaddr ) {
|
|
||||||
|
|
||||||
CAUSE_REGISTER = EXC_RMISS;
|
|
||||||
BAD_VADDR_REGISTER = BadVaddr;
|
|
||||||
CONTEXT_REGISTER &= 0xFF80000F;
|
|
||||||
CONTEXT_REGISTER |= (BadVaddr >> 9) & 0x007FFFF0;
|
|
||||||
ENTRYHI_REGISTER = (BadVaddr & 0xFFFFE000);
|
|
||||||
if ((STATUS_REGISTER & STATUS_EXL) == 0) {
|
|
||||||
if (DelaySlot) {
|
|
||||||
CAUSE_REGISTER |= CAUSE_BD;
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
|
|
||||||
} else {
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER;
|
|
||||||
}
|
|
||||||
if (AddressDefined(state, BadVaddr)) {
|
|
||||||
state->PROGRAM_COUNTER = 0x80000180;
|
|
||||||
} else {
|
|
||||||
state->PROGRAM_COUNTER = 0x80000000;
|
|
||||||
}
|
|
||||||
STATUS_REGISTER |= STATUS_EXL;
|
|
||||||
} else {
|
|
||||||
state->PROGRAM_COUNTER = 0x80000180;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoSysCallException ( usf_state_t * state, uint32_t DelaySlot) {
|
|
||||||
CAUSE_REGISTER = EXC_SYSCALL;
|
|
||||||
if (DelaySlot) {
|
|
||||||
CAUSE_REGISTER |= CAUSE_BD;
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER - 4;
|
|
||||||
} else {
|
|
||||||
EPC_REGISTER = state->PROGRAM_COUNTER;
|
|
||||||
}
|
|
||||||
STATUS_REGISTER |= STATUS_EXL;
|
|
||||||
state->PROGRAM_COUNTER = 0x80000180;
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define EXC_CODE(x) ((x)<<2)
|
|
||||||
#define EXC_INT EXC_CODE(0) /* interrupt */
|
|
||||||
#define EXC_MOD EXC_CODE(1) /* TLB mod */
|
|
||||||
#define EXC_RMISS EXC_CODE(2) /* Read TLB Miss */
|
|
||||||
#define EXC_WMISS EXC_CODE(3) /* Write TLB Miss */
|
|
||||||
#define EXC_RADE EXC_CODE(4) /* Read Address Error */
|
|
||||||
#define EXC_WADE EXC_CODE(5) /* Write Address Error */
|
|
||||||
#define EXC_IBE EXC_CODE(6) /* Instruction Bus Error */
|
|
||||||
#define EXC_DBE EXC_CODE(7) /* Data Bus Error */
|
|
||||||
#define EXC_SYSCALL EXC_CODE(8) /* SYSCALL */
|
|
||||||
#define EXC_BREAK EXC_CODE(9) /* BREAKpoint */
|
|
||||||
#define EXC_II EXC_CODE(10)/* Illegal Instruction */
|
|
||||||
#define EXC_CPU EXC_CODE(11)/* CoProcessor Unusable */
|
|
||||||
#define EXC_OV EXC_CODE(12)/* OVerflow */
|
|
||||||
#define EXC_TRAP EXC_CODE(13)/* Trap exception */
|
|
||||||
#define EXC_VCEI EXC_CODE(14)/* Virt. Coherency on Inst. fetch */
|
|
||||||
#define EXC_FPE EXC_CODE(15)/* Floating Point Exception */
|
|
||||||
#define EXC_WATCH EXC_CODE(23)/* Watchpoint reference */
|
|
||||||
#define EXC_VCED EXC_CODE(31)/* Virt. Coherency on data read */
|
|
||||||
|
|
||||||
#define Exception_Name(Except)\
|
|
||||||
(Except) == EXC_INT ? "interrupt" :\
|
|
||||||
(Except) == EXC_MOD ? "TLB mod" :\
|
|
||||||
(Except) == EXC_RMISS ? "Read TLB Miss" :\
|
|
||||||
(Except) == EXC_WMISS ? "Write TLB Miss" :\
|
|
||||||
(Except) == EXC_RADE ? "Read Address Error" :\
|
|
||||||
(Except) == EXC_WADE ? "Write Address Error" :\
|
|
||||||
(Except) == EXC_IBE ? "Instruction Bus Error" :\
|
|
||||||
(Except) == EXC_DBE ? "Data Bus Error" :\
|
|
||||||
(Except) == EXC_SYSCALL ? "SYSCALL" :\
|
|
||||||
(Except) == EXC_BREAK ? "Break" :\
|
|
||||||
(Except) == EXC_II ? "Illegal Instruction" :\
|
|
||||||
(Except) == EXC_CPU ? "CoProcessor Unusable" :\
|
|
||||||
(Except) == EXC_OV ? "OVerflow" :\
|
|
||||||
(Except) == EXC_TRAP ? "Trap exception" :\
|
|
||||||
(Except) == EXC_VCEI ? "Virt. Coherency on Inst. fetch" :\
|
|
||||||
(Except) == EXC_FPE ? "Floating Point Exception" :\
|
|
||||||
(Except) == EXC_WATCH ? "Watchpoint reference" :\
|
|
||||||
(Except) == EXC_VCED ? "Virt. Coherency on data read" :\
|
|
||||||
"Unkown"
|
|
||||||
|
|
||||||
void AiCheckInterrupts ( usf_state_t * );
|
|
||||||
void CheckInterrupts ( usf_state_t * );
|
|
||||||
void DoAddressError ( usf_state_t *, uint32_t DelaySlot, uint32_t BadVaddr, uint32_t FromRead );
|
|
||||||
void DoBreakException ( usf_state_t *, uint32_t DelaySlot );
|
|
||||||
void DoCopUnusableException ( usf_state_t *, uint32_t DelaySlot, uint32_t Coprocessor );
|
|
||||||
void DoIntrException ( usf_state_t *, uint32_t DelaySlot );
|
|
||||||
void DoTLBMiss ( usf_state_t *, uint32_t DelaySlot, uint32_t BadVaddr );
|
|
||||||
void DoSysCallException ( usf_state_t *, uint32_t DelaySlot);
|
|
||||||
|
|
|
@ -1,799 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include <float.h>
|
|
||||||
#include "main.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "usf.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "cpu_hle.h"
|
|
||||||
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
void (* R4300i_Opcode[64])(usf_state_t *);
|
|
||||||
void (* R4300i_Special[64])(usf_state_t *);
|
|
||||||
void (* R4300i_Regimm[32])(usf_state_t *);
|
|
||||||
void (* R4300i_CoP0[32])(usf_state_t *);
|
|
||||||
void (* R4300i_CoP0_Function[64])(usf_state_t *);
|
|
||||||
void (* R4300i_CoP1[32])(usf_state_t *);
|
|
||||||
void (* R4300i_CoP1_BC[32])(usf_state_t *);
|
|
||||||
void (* R4300i_CoP1_S[64])(usf_state_t *);
|
|
||||||
void (* R4300i_CoP1_D[64])(usf_state_t *);
|
|
||||||
void (* R4300i_CoP1_W[64])(usf_state_t *);
|
|
||||||
void (* R4300i_CoP1_L[64])(usf_state_t *);
|
|
||||||
|
|
||||||
void R4300i_opcode_SPECIAL (usf_state_t * state) {
|
|
||||||
R4300i_Special[ state->Opcode.u.e.funct ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R4300i_opcode_REGIMM (usf_state_t * state) {
|
|
||||||
R4300i_Regimm[ state->Opcode.u.b.rt ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R4300i_opcode_COP0 (usf_state_t * state) {
|
|
||||||
R4300i_CoP0[ state->Opcode.u.b.rs ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R4300i_opcode_COP0_CO (usf_state_t * state) {
|
|
||||||
R4300i_CoP0_Function[ state->Opcode.u.e.funct ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R4300i_opcode_COP1 (usf_state_t * state) {
|
|
||||||
R4300i_CoP1[ state->Opcode.u.f.fmt ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R4300i_opcode_COP1_BC (usf_state_t * state) {
|
|
||||||
R4300i_CoP1_BC[ state->Opcode.u.f.ft ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R4300i_opcode_COP1_S (usf_state_t * state) {
|
|
||||||
// controlfp(RoundingModel);
|
|
||||||
R4300i_CoP1_S[ state->Opcode.u.e.funct ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R4300i_opcode_COP1_D (usf_state_t * state) {
|
|
||||||
// controlfp(RoundingModel);
|
|
||||||
R4300i_CoP1_D[ state->Opcode.u.e.funct ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R4300i_opcode_COP1_W (usf_state_t * state) {
|
|
||||||
R4300i_CoP1_W[ state->Opcode.u.e.funct ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void R4300i_opcode_COP1_L (usf_state_t * state) {
|
|
||||||
R4300i_CoP1_L[ state->Opcode.u.e.funct ](state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BuildInterpreter (usf_state_t * state) {
|
|
||||||
(void)state;
|
|
||||||
R4300i_Opcode[ 0] = R4300i_opcode_SPECIAL;
|
|
||||||
R4300i_Opcode[ 1] = R4300i_opcode_REGIMM;
|
|
||||||
R4300i_Opcode[ 2] = r4300i_J;
|
|
||||||
R4300i_Opcode[ 3] = r4300i_JAL;
|
|
||||||
R4300i_Opcode[ 4] = r4300i_BEQ;
|
|
||||||
R4300i_Opcode[ 5] = r4300i_BNE;
|
|
||||||
R4300i_Opcode[ 6] = r4300i_BLEZ;
|
|
||||||
R4300i_Opcode[ 7] = r4300i_BGTZ;
|
|
||||||
R4300i_Opcode[ 8] = r4300i_ADDI;
|
|
||||||
R4300i_Opcode[ 9] = r4300i_ADDIU;
|
|
||||||
R4300i_Opcode[10] = r4300i_SLTI;
|
|
||||||
R4300i_Opcode[11] = r4300i_SLTIU;
|
|
||||||
R4300i_Opcode[12] = r4300i_ANDI;
|
|
||||||
R4300i_Opcode[13] = r4300i_ORI;
|
|
||||||
R4300i_Opcode[14] = r4300i_XORI;
|
|
||||||
R4300i_Opcode[15] = r4300i_LUI;
|
|
||||||
R4300i_Opcode[16] = R4300i_opcode_COP0;
|
|
||||||
R4300i_Opcode[17] = R4300i_opcode_COP1;
|
|
||||||
R4300i_Opcode[18] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[19] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[20] = r4300i_BEQL;
|
|
||||||
R4300i_Opcode[21] = r4300i_BNEL;
|
|
||||||
R4300i_Opcode[22] = r4300i_BLEZL;
|
|
||||||
R4300i_Opcode[23] = r4300i_BGTZL;
|
|
||||||
R4300i_Opcode[24] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[25] = r4300i_DADDIU;
|
|
||||||
R4300i_Opcode[26] = r4300i_LDL;
|
|
||||||
R4300i_Opcode[27] = r4300i_LDR;
|
|
||||||
R4300i_Opcode[28] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[29] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[30] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[31] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[32] = r4300i_LB;
|
|
||||||
R4300i_Opcode[33] = r4300i_LH;
|
|
||||||
R4300i_Opcode[34] = r4300i_LWL;
|
|
||||||
R4300i_Opcode[35] = r4300i_LW;
|
|
||||||
R4300i_Opcode[36] = r4300i_LBU;
|
|
||||||
R4300i_Opcode[37] = r4300i_LHU;
|
|
||||||
R4300i_Opcode[38] = r4300i_LWR;
|
|
||||||
R4300i_Opcode[39] = r4300i_LWU;
|
|
||||||
R4300i_Opcode[40] = r4300i_SB;
|
|
||||||
R4300i_Opcode[41] = r4300i_SH;
|
|
||||||
R4300i_Opcode[42] = r4300i_SWL;
|
|
||||||
R4300i_Opcode[43] = r4300i_SW;
|
|
||||||
R4300i_Opcode[44] = r4300i_SDL;
|
|
||||||
R4300i_Opcode[45] = r4300i_SDR;
|
|
||||||
R4300i_Opcode[46] = r4300i_SWR;
|
|
||||||
R4300i_Opcode[47] = r4300i_CACHE;
|
|
||||||
R4300i_Opcode[48] = r4300i_LL;
|
|
||||||
R4300i_Opcode[49] = r4300i_LWC1;
|
|
||||||
R4300i_Opcode[50] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[51] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[52] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[53] = r4300i_LDC1;
|
|
||||||
R4300i_Opcode[54] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[55] = r4300i_LD;
|
|
||||||
R4300i_Opcode[56] = r4300i_SC;
|
|
||||||
R4300i_Opcode[57] = r4300i_SWC1;
|
|
||||||
R4300i_Opcode[58] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[59] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[60] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[61] = r4300i_SDC1;
|
|
||||||
R4300i_Opcode[62] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Opcode[63] = r4300i_SD;
|
|
||||||
|
|
||||||
R4300i_Special[ 0] = r4300i_SPECIAL_SLL;
|
|
||||||
R4300i_Special[ 1] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[ 2] = r4300i_SPECIAL_SRL;
|
|
||||||
R4300i_Special[ 3] = r4300i_SPECIAL_SRA;
|
|
||||||
R4300i_Special[ 4] = r4300i_SPECIAL_SLLV;
|
|
||||||
R4300i_Special[ 5] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[ 6] = r4300i_SPECIAL_SRLV;
|
|
||||||
R4300i_Special[ 7] = r4300i_SPECIAL_SRAV;
|
|
||||||
R4300i_Special[ 8] = r4300i_SPECIAL_JR;
|
|
||||||
R4300i_Special[ 9] = r4300i_SPECIAL_JALR;
|
|
||||||
R4300i_Special[10] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[11] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[12] = r4300i_SPECIAL_SYSCALL;
|
|
||||||
R4300i_Special[13] = r4300i_SPECIAL_BREAK;
|
|
||||||
R4300i_Special[14] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[15] = r4300i_SPECIAL_SYNC;
|
|
||||||
R4300i_Special[16] = r4300i_SPECIAL_MFHI;
|
|
||||||
R4300i_Special[17] = r4300i_SPECIAL_MTHI;
|
|
||||||
R4300i_Special[18] = r4300i_SPECIAL_MFLO;
|
|
||||||
R4300i_Special[19] = r4300i_SPECIAL_MTLO;
|
|
||||||
R4300i_Special[20] = r4300i_SPECIAL_DSLLV;
|
|
||||||
R4300i_Special[21] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[22] = r4300i_SPECIAL_DSRLV;
|
|
||||||
R4300i_Special[23] = r4300i_SPECIAL_DSRAV;
|
|
||||||
R4300i_Special[24] = r4300i_SPECIAL_MULT;
|
|
||||||
R4300i_Special[25] = r4300i_SPECIAL_MULTU;
|
|
||||||
R4300i_Special[26] = r4300i_SPECIAL_DIV;
|
|
||||||
R4300i_Special[27] = r4300i_SPECIAL_DIVU;
|
|
||||||
R4300i_Special[28] = r4300i_SPECIAL_DMULT;
|
|
||||||
R4300i_Special[29] = r4300i_SPECIAL_DMULTU;
|
|
||||||
R4300i_Special[30] = r4300i_SPECIAL_DDIV;
|
|
||||||
R4300i_Special[31] = r4300i_SPECIAL_DDIVU;
|
|
||||||
R4300i_Special[32] = r4300i_SPECIAL_ADD;
|
|
||||||
R4300i_Special[33] = r4300i_SPECIAL_ADDU;
|
|
||||||
R4300i_Special[34] = r4300i_SPECIAL_SUB;
|
|
||||||
R4300i_Special[35] = r4300i_SPECIAL_SUBU;
|
|
||||||
R4300i_Special[36] = r4300i_SPECIAL_AND;
|
|
||||||
R4300i_Special[37] = r4300i_SPECIAL_OR;
|
|
||||||
R4300i_Special[38] = r4300i_SPECIAL_XOR;
|
|
||||||
R4300i_Special[39] = r4300i_SPECIAL_NOR;
|
|
||||||
R4300i_Special[40] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[41] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[42] = r4300i_SPECIAL_SLT;
|
|
||||||
R4300i_Special[43] = r4300i_SPECIAL_SLTU;
|
|
||||||
R4300i_Special[44] = r4300i_SPECIAL_DADD;
|
|
||||||
R4300i_Special[45] = r4300i_SPECIAL_DADDU;
|
|
||||||
R4300i_Special[46] = r4300i_SPECIAL_DSUB;
|
|
||||||
R4300i_Special[47] = r4300i_SPECIAL_DSUBU;
|
|
||||||
R4300i_Special[48] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[49] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[50] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[51] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[52] = r4300i_SPECIAL_TEQ;
|
|
||||||
R4300i_Special[53] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[54] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[55] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[56] = r4300i_SPECIAL_DSLL;
|
|
||||||
R4300i_Special[57] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[58] = r4300i_SPECIAL_DSRL;
|
|
||||||
R4300i_Special[59] = r4300i_SPECIAL_DSRA;
|
|
||||||
R4300i_Special[60] = r4300i_SPECIAL_DSLL32;
|
|
||||||
R4300i_Special[61] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Special[62] = r4300i_SPECIAL_DSRL32;
|
|
||||||
R4300i_Special[63] = r4300i_SPECIAL_DSRA32;
|
|
||||||
|
|
||||||
R4300i_Regimm[ 0] = r4300i_REGIMM_BLTZ;
|
|
||||||
R4300i_Regimm[ 1] = r4300i_REGIMM_BGEZ;
|
|
||||||
R4300i_Regimm[ 2] = r4300i_REGIMM_BLTZL;
|
|
||||||
R4300i_Regimm[ 3] = r4300i_REGIMM_BGEZL;
|
|
||||||
R4300i_Regimm[ 4] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[ 5] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[ 6] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[ 7] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[ 8] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[ 9] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[10] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[11] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[12] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[13] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[14] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[15] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[16] = r4300i_REGIMM_BLTZAL;
|
|
||||||
R4300i_Regimm[17] = r4300i_REGIMM_BGEZAL;
|
|
||||||
R4300i_Regimm[18] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[19] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[20] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[21] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[22] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[23] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[24] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[25] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[26] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[27] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[28] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[29] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[30] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_Regimm[31] = R4300i_UnknownOpcode;
|
|
||||||
|
|
||||||
R4300i_CoP0[ 0] = r4300i_COP0_MF;
|
|
||||||
R4300i_CoP0[ 1] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[ 2] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[ 3] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[ 4] = r4300i_COP0_MT;
|
|
||||||
R4300i_CoP0[ 5] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[ 6] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[ 7] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[ 8] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[ 9] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[10] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[11] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[12] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[13] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[14] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[15] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0[16] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[17] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[18] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[19] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[20] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[21] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[22] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[23] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[24] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[25] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[26] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[27] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[28] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[29] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[30] = R4300i_opcode_COP0_CO;
|
|
||||||
R4300i_CoP0[31] = R4300i_opcode_COP0_CO;
|
|
||||||
|
|
||||||
R4300i_CoP0_Function[ 0] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[ 1] = r4300i_COP0_CO_TLBR;
|
|
||||||
R4300i_CoP0_Function[ 2] = r4300i_COP0_CO_TLBWI;
|
|
||||||
R4300i_CoP0_Function[ 3] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[ 4] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[ 5] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[ 6] = r4300i_COP0_CO_TLBWR;
|
|
||||||
R4300i_CoP0_Function[ 7] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[ 8] = r4300i_COP0_CO_TLBP;
|
|
||||||
R4300i_CoP0_Function[ 9] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[10] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[11] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[12] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[13] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[14] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[15] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[16] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[17] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[18] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[19] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[20] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[21] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[22] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[23] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[24] = r4300i_COP0_CO_ERET;
|
|
||||||
R4300i_CoP0_Function[25] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[26] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[27] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[28] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[29] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[30] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[31] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[32] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[33] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[34] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[35] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[36] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[37] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[38] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[39] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[40] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[41] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[42] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[43] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[44] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[45] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[46] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[47] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[48] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[49] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[50] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[51] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[52] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[53] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[54] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[55] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[56] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[57] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[58] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[59] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[60] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[61] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[62] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP0_Function[63] = R4300i_UnknownOpcode;
|
|
||||||
|
|
||||||
R4300i_CoP1[ 0] = r4300i_COP1_MF;
|
|
||||||
R4300i_CoP1[ 1] = r4300i_COP1_DMF;
|
|
||||||
R4300i_CoP1[ 2] = r4300i_COP1_CF;
|
|
||||||
R4300i_CoP1[ 3] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[ 4] = r4300i_COP1_MT;
|
|
||||||
R4300i_CoP1[ 5] = r4300i_COP1_DMT;
|
|
||||||
R4300i_CoP1[ 6] = r4300i_COP1_CT;
|
|
||||||
R4300i_CoP1[ 7] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[ 8] = R4300i_opcode_COP1_BC;
|
|
||||||
R4300i_CoP1[ 9] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[10] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[11] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[12] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[13] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[14] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[15] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[16] = R4300i_opcode_COP1_S;
|
|
||||||
R4300i_CoP1[17] = R4300i_opcode_COP1_D;
|
|
||||||
R4300i_CoP1[18] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[19] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[20] = R4300i_opcode_COP1_W;
|
|
||||||
R4300i_CoP1[21] = R4300i_opcode_COP1_L;
|
|
||||||
R4300i_CoP1[22] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[23] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[24] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[25] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[26] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[27] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[28] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[29] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[30] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1[31] = R4300i_UnknownOpcode;
|
|
||||||
|
|
||||||
R4300i_CoP1_BC[ 0] = r4300i_COP1_BCF;
|
|
||||||
R4300i_CoP1_BC[ 1] = r4300i_COP1_BCT;
|
|
||||||
R4300i_CoP1_BC[ 2] = r4300i_COP1_BCFL;
|
|
||||||
R4300i_CoP1_BC[ 3] = r4300i_COP1_BCTL;
|
|
||||||
R4300i_CoP1_BC[ 4] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[ 5] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[ 6] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[ 7] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[ 8] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[ 9] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[10] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[11] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[12] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[13] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[14] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[15] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[16] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[17] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[18] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[19] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[20] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[21] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[22] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[23] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[24] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[25] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[26] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[27] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[28] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[29] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[30] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_BC[31] = R4300i_UnknownOpcode;
|
|
||||||
|
|
||||||
R4300i_CoP1_S[ 0] = r4300i_COP1_S_ADD;
|
|
||||||
R4300i_CoP1_S[ 1] = r4300i_COP1_S_SUB;
|
|
||||||
R4300i_CoP1_S[ 2] = r4300i_COP1_S_MUL;
|
|
||||||
R4300i_CoP1_S[ 3] = r4300i_COP1_S_DIV;
|
|
||||||
R4300i_CoP1_S[ 4] = r4300i_COP1_S_SQRT;
|
|
||||||
R4300i_CoP1_S[ 5] = r4300i_COP1_S_ABS;
|
|
||||||
R4300i_CoP1_S[ 6] = r4300i_COP1_S_MOV;
|
|
||||||
R4300i_CoP1_S[ 7] = r4300i_COP1_S_NEG;
|
|
||||||
R4300i_CoP1_S[ 8] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[ 9] = r4300i_COP1_S_TRUNC_L;
|
|
||||||
R4300i_CoP1_S[10] = r4300i_COP1_S_CEIL_L; //added by Witten
|
|
||||||
R4300i_CoP1_S[11] = r4300i_COP1_S_FLOOR_L; //added by Witten
|
|
||||||
R4300i_CoP1_S[12] = r4300i_COP1_S_ROUND_W;
|
|
||||||
R4300i_CoP1_S[13] = r4300i_COP1_S_TRUNC_W;
|
|
||||||
R4300i_CoP1_S[14] = r4300i_COP1_S_CEIL_W; //added by Witten
|
|
||||||
R4300i_CoP1_S[15] = r4300i_COP1_S_FLOOR_W;
|
|
||||||
R4300i_CoP1_S[16] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[17] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[18] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[19] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[20] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[21] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[22] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[23] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[24] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[25] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[26] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[27] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[28] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[29] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[30] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[31] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[32] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[33] = r4300i_COP1_S_CVT_D;
|
|
||||||
R4300i_CoP1_S[34] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[35] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[36] = r4300i_COP1_S_CVT_W;
|
|
||||||
R4300i_CoP1_S[37] = r4300i_COP1_S_CVT_L;
|
|
||||||
R4300i_CoP1_S[38] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[39] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[40] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[41] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[42] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[43] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[44] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[45] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[46] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[47] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_S[48] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[49] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[50] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[51] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[52] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[53] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[54] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[55] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[56] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[57] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[58] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[59] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[60] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[61] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[62] = r4300i_COP1_S_CMP;
|
|
||||||
R4300i_CoP1_S[63] = r4300i_COP1_S_CMP;
|
|
||||||
|
|
||||||
R4300i_CoP1_D[ 0] = r4300i_COP1_D_ADD;
|
|
||||||
R4300i_CoP1_D[ 1] = r4300i_COP1_D_SUB;
|
|
||||||
R4300i_CoP1_D[ 2] = r4300i_COP1_D_MUL;
|
|
||||||
R4300i_CoP1_D[ 3] = r4300i_COP1_D_DIV;
|
|
||||||
R4300i_CoP1_D[ 4] = r4300i_COP1_D_SQRT;
|
|
||||||
R4300i_CoP1_D[ 5] = r4300i_COP1_D_ABS;
|
|
||||||
R4300i_CoP1_D[ 6] = r4300i_COP1_D_MOV;
|
|
||||||
R4300i_CoP1_D[ 7] = r4300i_COP1_D_NEG;
|
|
||||||
R4300i_CoP1_D[ 8] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[ 9] = r4300i_COP1_D_TRUNC_L; //added by Witten
|
|
||||||
R4300i_CoP1_D[10] = r4300i_COP1_D_CEIL_L; //added by Witten
|
|
||||||
R4300i_CoP1_D[11] = r4300i_COP1_D_FLOOR_L; //added by Witten
|
|
||||||
R4300i_CoP1_D[12] = r4300i_COP1_D_ROUND_W;
|
|
||||||
R4300i_CoP1_D[13] = r4300i_COP1_D_TRUNC_W;
|
|
||||||
R4300i_CoP1_D[14] = r4300i_COP1_D_CEIL_W; //added by Witten
|
|
||||||
R4300i_CoP1_D[15] = r4300i_COP1_D_FLOOR_W; //added by Witten
|
|
||||||
R4300i_CoP1_D[16] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[17] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[18] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[19] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[20] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[21] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[22] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[23] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[24] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[25] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[26] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[27] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[28] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[29] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[30] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[31] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[32] = r4300i_COP1_D_CVT_S;
|
|
||||||
R4300i_CoP1_D[33] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[34] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[35] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[36] = r4300i_COP1_D_CVT_W;
|
|
||||||
R4300i_CoP1_D[37] = r4300i_COP1_D_CVT_L;
|
|
||||||
R4300i_CoP1_D[38] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[39] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[40] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[41] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[42] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[43] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[44] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[45] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[46] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[47] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_D[48] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[49] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[50] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[51] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[52] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[53] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[54] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[55] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[56] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[57] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[58] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[59] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[60] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[61] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[62] = r4300i_COP1_D_CMP;
|
|
||||||
R4300i_CoP1_D[63] = r4300i_COP1_D_CMP;
|
|
||||||
|
|
||||||
R4300i_CoP1_W[ 0] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[ 1] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[ 2] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[ 3] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[ 4] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[ 5] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[ 6] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[ 7] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[ 8] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[ 9] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[10] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[11] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[12] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[13] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[14] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[15] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[16] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[17] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[18] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[19] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[20] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[21] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[22] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[23] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[24] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[25] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[26] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[27] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[28] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[29] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[30] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[31] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[32] = r4300i_COP1_W_CVT_S;
|
|
||||||
R4300i_CoP1_W[33] = r4300i_COP1_W_CVT_D;
|
|
||||||
R4300i_CoP1_W[34] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[35] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[36] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[37] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[38] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[39] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[40] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[41] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[42] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[43] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[44] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[45] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[46] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[47] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[48] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[49] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[50] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[51] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[52] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[53] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[54] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[55] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[56] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[57] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[58] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[59] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[60] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[61] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[62] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_W[63] = R4300i_UnknownOpcode;
|
|
||||||
|
|
||||||
R4300i_CoP1_L[ 0] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[ 1] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[ 2] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[ 3] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[ 4] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[ 5] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[ 6] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[ 7] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[ 8] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[ 9] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[10] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[11] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[12] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[13] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[14] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[15] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[16] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[17] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[18] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[19] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[20] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[21] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[22] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[23] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[24] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[25] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[26] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[27] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[28] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[29] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[30] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[31] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[32] = r4300i_COP1_L_CVT_S;
|
|
||||||
R4300i_CoP1_L[33] = r4300i_COP1_L_CVT_D;
|
|
||||||
R4300i_CoP1_L[34] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[35] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[36] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[37] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[38] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[39] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[40] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[41] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[42] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[43] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[44] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[45] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[46] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[47] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[48] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[49] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[50] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[51] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[52] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[53] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[54] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[55] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[56] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[57] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[58] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[59] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[60] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[61] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[62] = R4300i_UnknownOpcode;
|
|
||||||
R4300i_CoP1_L[63] = R4300i_UnknownOpcode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void RunFunction(usf_state_t * state, uint32_t address) {
|
|
||||||
uint32_t oldPC = state->PROGRAM_COUNTER, oldRA = state->GPR[31].UW[0], la = state->NextInstruction;
|
|
||||||
int callStack = 0;
|
|
||||||
|
|
||||||
state->NextInstruction = NORMAL;
|
|
||||||
state->PROGRAM_COUNTER = address;
|
|
||||||
|
|
||||||
while( (state->PROGRAM_COUNTER != oldRA) || callStack) {
|
|
||||||
|
|
||||||
if(state->PROGRAM_COUNTER == address)
|
|
||||||
callStack++;
|
|
||||||
|
|
||||||
ExecuteInterpreterOpCode(state);
|
|
||||||
|
|
||||||
if(state->PROGRAM_COUNTER == oldRA)
|
|
||||||
callStack--;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->PROGRAM_COUNTER = oldPC;
|
|
||||||
state->GPR[31].UW[0] = oldRA;
|
|
||||||
state->NextInstruction = la;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
#include "debugger/dbg_decoder.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ExecuteInterpreterOpCode (usf_state_t * state) {
|
|
||||||
|
|
||||||
|
|
||||||
if (*state->WaitMode) state->Timers->Timer = -1;
|
|
||||||
|
|
||||||
if (!r4300i_LW_VAddr(state, state->PROGRAM_COUNTER, &state->Opcode.u.Hex)) {
|
|
||||||
DoTLBMiss(state, state->NextInstruction == JUMP,state->PROGRAM_COUNTER);
|
|
||||||
state->NextInstruction = NORMAL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
{
|
|
||||||
char opcode[256];
|
|
||||||
char arguments[256];
|
|
||||||
r4300_decode_op(state->Opcode.u.Hex, opcode, arguments, state->PROGRAM_COUNTER);
|
|
||||||
fprintf(state->debug_log, "%08x: %-16s %s\n", state->PROGRAM_COUNTER, opcode, arguments);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
COUNT_REGISTER += 2;
|
|
||||||
state->Timers->Timer -= 2;
|
|
||||||
|
|
||||||
RANDOM_REGISTER -= 1;
|
|
||||||
if ((int32_t)RANDOM_REGISTER < (int32_t)WIRED_REGISTER) {
|
|
||||||
RANDOM_REGISTER = 31;
|
|
||||||
}
|
|
||||||
|
|
||||||
R4300i_Opcode[ state->Opcode.u.b.op ](state);
|
|
||||||
|
|
||||||
if (state->GPR[0].DW != 0) {
|
|
||||||
state->GPR[0].DW = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state->NextInstruction) {
|
|
||||||
case NORMAL:
|
|
||||||
state->PROGRAM_COUNTER += 4;
|
|
||||||
break;
|
|
||||||
case DELAY_SLOT:
|
|
||||||
state->NextInstruction = JUMP;
|
|
||||||
state->PROGRAM_COUNTER += 4;
|
|
||||||
break;
|
|
||||||
case JUMP:
|
|
||||||
if (
|
|
||||||
#ifdef DEBUG_INFO
|
|
||||||
0 &&
|
|
||||||
#endif
|
|
||||||
state->cpu_hle_entry_count &&
|
|
||||||
DoCPUHLE(state, state->JumpToLocation)) {
|
|
||||||
state->PROGRAM_COUNTER = state->GPR[31].UW[0];
|
|
||||||
state->NextInstruction = NORMAL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state->PROGRAM_COUNTER = state->JumpToLocation;
|
|
||||||
state->NextInstruction = NORMAL;
|
|
||||||
}
|
|
||||||
if ((int32_t)state->Timers->Timer < 0) { TimerDone(state); }
|
|
||||||
if (state->CPU_Action->DoSomething) { DoSomething(state); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartInterpreterCPU (usf_state_t * state) {
|
|
||||||
const int safety_count_max = 20000000;
|
|
||||||
int safety_count = safety_count_max;
|
|
||||||
size_t last_sample_buffer_count = state->sample_buffer_count;
|
|
||||||
|
|
||||||
state->NextInstruction = NORMAL;
|
|
||||||
|
|
||||||
while(state->cpu_running) {
|
|
||||||
ExecuteInterpreterOpCode(state);
|
|
||||||
if (!--safety_count) {
|
|
||||||
if (last_sample_buffer_count == state->sample_buffer_count) {
|
|
||||||
DisplayError( state, "Emulator core is not generating any samples after 20 million instructions" );
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
safety_count = safety_count_max;
|
|
||||||
last_sample_buffer_count = state->sample_buffer_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state->cpu_stopped = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestInterpreterJump (usf_state_t * state, uint32_t PC, uint32_t TargetPC, int32_t Reg1, int32_t Reg2) {
|
|
||||||
if (PC != TargetPC) { return; }
|
|
||||||
if (DelaySlotEffectsCompare(state,PC,Reg1,Reg2)) { return; }
|
|
||||||
InPermLoop(state);
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
void BuildInterpreter ( usf_state_t * );
|
|
||||||
void ExecuteInterpreterOpCode ( usf_state_t * );
|
|
||||||
void StartInterpreterCPU ( usf_state_t * );
|
|
||||||
void TestInterpreterJump ( usf_state_t *, uint32_t PC, uint32_t TargetPC, int32_t Reg1, int32_t Reg2 );
|
|
||||||
|
|
||||||
void RunFunction( usf_state_t *, uint32_t address );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern void (* R4300i_Opcode[64])(usf_state_t *);
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,206 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/************************* OpCode functions *************************/
|
|
||||||
void r4300i_J ( usf_state_t * );
|
|
||||||
void r4300i_JAL ( usf_state_t * );
|
|
||||||
void r4300i_BNE ( usf_state_t * );
|
|
||||||
void r4300i_BEQ ( usf_state_t * );
|
|
||||||
void r4300i_BLEZ ( usf_state_t * );
|
|
||||||
void r4300i_BGTZ ( usf_state_t * );
|
|
||||||
void r4300i_ADDI ( usf_state_t * );
|
|
||||||
void r4300i_ADDIU ( usf_state_t * );
|
|
||||||
void r4300i_SLTI ( usf_state_t * );
|
|
||||||
void r4300i_SLTIU ( usf_state_t * );
|
|
||||||
void r4300i_ANDI ( usf_state_t * );
|
|
||||||
void r4300i_ORI ( usf_state_t * );
|
|
||||||
void r4300i_XORI ( usf_state_t * );
|
|
||||||
void r4300i_LUI ( usf_state_t * );
|
|
||||||
void r4300i_BEQL ( usf_state_t * );
|
|
||||||
void r4300i_BNEL ( usf_state_t * );
|
|
||||||
void r4300i_BLEZL ( usf_state_t * );
|
|
||||||
void r4300i_BGTZL ( usf_state_t * );
|
|
||||||
void r4300i_DADDIU ( usf_state_t * );
|
|
||||||
void r4300i_LDL ( usf_state_t * );
|
|
||||||
void r4300i_LDR ( usf_state_t * );
|
|
||||||
void r4300i_LB ( usf_state_t * );
|
|
||||||
void r4300i_LH ( usf_state_t * );
|
|
||||||
void r4300i_LWL ( usf_state_t * );
|
|
||||||
void r4300i_LW ( usf_state_t * );
|
|
||||||
void r4300i_LBU ( usf_state_t * );
|
|
||||||
void r4300i_LHU ( usf_state_t * );
|
|
||||||
void r4300i_LWR ( usf_state_t * );
|
|
||||||
void r4300i_LWU ( usf_state_t * );
|
|
||||||
void r4300i_SB ( usf_state_t * );
|
|
||||||
void r4300i_SH ( usf_state_t * );
|
|
||||||
void r4300i_SWL ( usf_state_t * );
|
|
||||||
void r4300i_SW ( usf_state_t * );
|
|
||||||
void r4300i_SDL ( usf_state_t * );
|
|
||||||
void r4300i_SDR ( usf_state_t * );
|
|
||||||
void r4300i_SWR ( usf_state_t * );
|
|
||||||
void r4300i_CACHE ( usf_state_t * );
|
|
||||||
void r4300i_LL ( usf_state_t * );
|
|
||||||
void r4300i_LWC1 ( usf_state_t * );
|
|
||||||
void r4300i_LDC1 ( usf_state_t * );
|
|
||||||
void r4300i_LD ( usf_state_t * );
|
|
||||||
void r4300i_SC ( usf_state_t * );
|
|
||||||
void r4300i_SWC1 ( usf_state_t * );
|
|
||||||
void r4300i_SDC1 ( usf_state_t * );
|
|
||||||
void r4300i_SD ( usf_state_t * );
|
|
||||||
|
|
||||||
/********************** R4300i OpCodes: Special **********************/
|
|
||||||
void r4300i_SPECIAL_SLL ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SRL ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SRA ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SLLV ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SRLV ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SRAV ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_JR ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_JALR ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SYSCALL ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_BREAK ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SYNC ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_MFHI ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_MTHI ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_MFLO ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_MTLO ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSLLV ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSRLV ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSRAV ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_MULT ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_MULTU ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DIV ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DIVU ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DMULT ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DMULTU ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DDIV ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DDIVU ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_ADD ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_ADDU ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SUB ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SUBU ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_AND ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_OR ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_XOR ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_NOR ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SLT ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_SLTU ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DADD ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DADDU ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSUB ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSUBU ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_TEQ ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSLL ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSRL ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSRA ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSLL32 ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSRL32 ( usf_state_t * );
|
|
||||||
void r4300i_SPECIAL_DSRA32 ( usf_state_t * );
|
|
||||||
|
|
||||||
/********************** R4300i OpCodes: RegImm **********************/
|
|
||||||
void r4300i_REGIMM_BLTZ ( usf_state_t * );
|
|
||||||
void r4300i_REGIMM_BGEZ ( usf_state_t * );
|
|
||||||
void r4300i_REGIMM_BLTZL ( usf_state_t * );
|
|
||||||
void r4300i_REGIMM_BGEZL ( usf_state_t * );
|
|
||||||
void r4300i_REGIMM_BLTZAL ( usf_state_t * );
|
|
||||||
void r4300i_REGIMM_BGEZAL ( usf_state_t * );
|
|
||||||
|
|
||||||
/************************** COP0 functions **************************/
|
|
||||||
void r4300i_COP0_MF ( usf_state_t * );
|
|
||||||
void r4300i_COP0_MT ( usf_state_t * );
|
|
||||||
|
|
||||||
/************************** COP0 CO functions ***********************/
|
|
||||||
void r4300i_COP0_CO_TLBR ( usf_state_t * );
|
|
||||||
void r4300i_COP0_CO_TLBWI ( usf_state_t * );
|
|
||||||
void r4300i_COP0_CO_TLBWR ( usf_state_t * );
|
|
||||||
void r4300i_COP0_CO_TLBP ( usf_state_t * );
|
|
||||||
void r4300i_COP0_CO_ERET ( usf_state_t * );
|
|
||||||
|
|
||||||
/************************** COP1 functions **************************/
|
|
||||||
void r4300i_COP1_MF ( usf_state_t * );
|
|
||||||
void r4300i_COP1_DMF ( usf_state_t * );
|
|
||||||
void r4300i_COP1_CF ( usf_state_t * );
|
|
||||||
void r4300i_COP1_MT ( usf_state_t * );
|
|
||||||
void r4300i_COP1_DMT ( usf_state_t * );
|
|
||||||
void r4300i_COP1_CT ( usf_state_t * );
|
|
||||||
|
|
||||||
/************************* COP1: BC1 functions ***********************/
|
|
||||||
void r4300i_COP1_BCF ( usf_state_t * );
|
|
||||||
void r4300i_COP1_BCT ( usf_state_t * );
|
|
||||||
void r4300i_COP1_BCFL ( usf_state_t * );
|
|
||||||
void r4300i_COP1_BCTL ( usf_state_t * );
|
|
||||||
|
|
||||||
/************************** COP1: S functions ************************/
|
|
||||||
void r4300i_COP1_S_ADD ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_SUB ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_MUL ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_DIV ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_SQRT ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_ABS ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_MOV ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_NEG ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_TRUNC_L ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_CEIL_L ( usf_state_t * ); //added by Witten
|
|
||||||
void r4300i_COP1_S_FLOOR_L ( usf_state_t * ); //added by Witten
|
|
||||||
void r4300i_COP1_S_ROUND_W ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_TRUNC_W ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_CEIL_W ( usf_state_t * ); //added by Witten
|
|
||||||
void r4300i_COP1_S_FLOOR_W ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_CVT_D ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_CVT_W ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_CVT_L ( usf_state_t * );
|
|
||||||
void r4300i_COP1_S_CMP ( usf_state_t * );
|
|
||||||
|
|
||||||
/************************** COP1: D functions ************************/
|
|
||||||
void r4300i_COP1_D_ADD ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_SUB ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_MUL ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_DIV ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_SQRT ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_ABS ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_MOV ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_NEG ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_TRUNC_L ( usf_state_t * ); //added by Witten
|
|
||||||
void r4300i_COP1_D_CEIL_L ( usf_state_t * ); //added by Witten
|
|
||||||
void r4300i_COP1_D_FLOOR_L ( usf_state_t * ); //added by Witten
|
|
||||||
void r4300i_COP1_D_ROUND_W ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_TRUNC_W ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_CEIL_W ( usf_state_t * ); //added by Witten
|
|
||||||
void r4300i_COP1_D_FLOOR_W ( usf_state_t * ); //added by Witten
|
|
||||||
void r4300i_COP1_D_CVT_S ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_CVT_W ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_CVT_L ( usf_state_t * );
|
|
||||||
void r4300i_COP1_D_CMP ( usf_state_t * );
|
|
||||||
|
|
||||||
/************************** COP1: W functions ************************/
|
|
||||||
void r4300i_COP1_W_CVT_S ( usf_state_t * );
|
|
||||||
void r4300i_COP1_W_CVT_D ( usf_state_t * );
|
|
||||||
|
|
||||||
/************************** COP1: L functions ************************/
|
|
||||||
void r4300i_COP1_L_CVT_S ( usf_state_t * );
|
|
||||||
void r4300i_COP1_L_CVT_D ( usf_state_t * );
|
|
||||||
|
|
||||||
/************************** Other functions **************************/
|
|
||||||
void R4300i_UnknownOpcode ( usf_state_t * );
|
|
|
@ -1,37 +0,0 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "usf.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
void StopEmulation(usf_state_t * state)
|
|
||||||
{
|
|
||||||
//asm("int $3");
|
|
||||||
//printf("Arrivederci!\n\n");
|
|
||||||
//Release_Memory();
|
|
||||||
//exit(0);
|
|
||||||
state->cpu_running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayError (usf_state_t * state, char * Message, ...) {
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
size_t len = strlen( state->error_message );
|
|
||||||
|
|
||||||
if ( len )
|
|
||||||
state->error_message[ len++ ] = '\n';
|
|
||||||
|
|
||||||
va_start( ap, Message );
|
|
||||||
vsprintf( state->error_message + len, Message, ap );
|
|
||||||
va_end( ap );
|
|
||||||
|
|
||||||
state->last_error = state->error_message;
|
|
||||||
StopEmulation( state );
|
|
||||||
|
|
||||||
//printf("Error: %s\n", Msg);
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "usf.h"
|
|
||||||
|
|
||||||
void DisplayError (usf_state_t *, char * Message, ...);
|
|
||||||
void StopEmulation(usf_state_t *);
|
|
127
Frameworks/lazyusf/lazyusf/main/list.h
Normal file
127
Frameworks/lazyusf/lazyusf/main/list.h
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - util.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2012 Mupen64plus development team *
|
||||||
|
* *
|
||||||
|
* 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 __LIST_H__
|
||||||
|
#define __LIST_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
struct list_head {
|
||||||
|
struct list_head *prev;
|
||||||
|
struct list_head *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LIST_HEAD(list) \
|
||||||
|
struct list_head list = { &(list), &(list) }
|
||||||
|
|
||||||
|
static osal_inline void INIT_LIST_HEAD(struct list_head *head)
|
||||||
|
{
|
||||||
|
head->next = head;
|
||||||
|
head->prev = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
static osal_inline void list_add(struct list_head *new_item, struct list_head *head)
|
||||||
|
{
|
||||||
|
struct list_head *next = head->next;
|
||||||
|
|
||||||
|
next->prev = new_item;
|
||||||
|
new_item->next = next;
|
||||||
|
new_item->prev = head;
|
||||||
|
head->next = new_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static osal_inline void list_add_tail(struct list_head *new_item, struct list_head *head)
|
||||||
|
{
|
||||||
|
struct list_head *prev = head->prev;
|
||||||
|
|
||||||
|
prev->next = new_item;
|
||||||
|
new_item->next = head;
|
||||||
|
new_item->prev = prev;
|
||||||
|
head->prev = new_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static osal_inline void list_del(struct list_head *entry)
|
||||||
|
{
|
||||||
|
struct list_head *next = entry->next;
|
||||||
|
struct list_head *prev = entry->prev;
|
||||||
|
|
||||||
|
next->prev = prev;
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static osal_inline void list_del_init(struct list_head *entry)
|
||||||
|
{
|
||||||
|
list_del(entry);
|
||||||
|
INIT_LIST_HEAD(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static osal_inline int list_empty(const struct list_head *head)
|
||||||
|
{
|
||||||
|
return (head->next == head);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
|
||||||
|
#define container_of(ptr, type, member) ({ \
|
||||||
|
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||||
|
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define container_of(ptr, type, member) \
|
||||||
|
((type *)((char *)(ptr) - offsetof(type, member)))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define list_entry(ptr, type, member) container_of(ptr, type, member)
|
||||||
|
|
||||||
|
#define list_first_entry(ptr, type, member) \
|
||||||
|
list_entry((ptr)->next, type, member)
|
||||||
|
|
||||||
|
#define list_for_each(pos, head) \
|
||||||
|
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||||
|
|
||||||
|
#define list_for_each_entry_t(pos, head, type, member) \
|
||||||
|
for (pos = list_entry((head)->next, type, member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = list_entry(pos->member.next, type, member))
|
||||||
|
|
||||||
|
#define list_for_each_safe(pos, safe, head) \
|
||||||
|
for (pos = (head)->next, safe = pos->next; pos != (head); \
|
||||||
|
pos = safe, safe = pos->next)
|
||||||
|
|
||||||
|
#define list_for_each_entry_safe_t(pos, safe, head, type, member) \
|
||||||
|
for (pos = list_entry((head)->next, type, member), \
|
||||||
|
safe = list_entry(pos->member.next, type, member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = safe, \
|
||||||
|
safe = list_entry(safe->member.next, type, member))
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
185
Frameworks/lazyusf/lazyusf/main/main.c
Normal file
185
Frameworks/lazyusf/lazyusf/main/main.c
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - main.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2012 CasualJames *
|
||||||
|
* Copyright (C) 2008-2009 Richard Goedeken *
|
||||||
|
* Copyright (C) 2008 Ebenblues Nmn Okaygo Tillin9 *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* This is MUPEN64's main entry point. It contains code that is common
|
||||||
|
* to both the gui and non-gui versions of mupen64. See
|
||||||
|
* gui subdirectories for the gui-specific code.
|
||||||
|
* if you want to implement an interface, you should look here
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#define M64P_CORE_PROTOTYPES 1
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "rom.h"
|
||||||
|
#include "savestates.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "ai/ai_controller.h"
|
||||||
|
#include "memory/memory.h"
|
||||||
|
#include "pi/pi_controller.h"
|
||||||
|
#include "r4300/r4300.h"
|
||||||
|
#include "r4300/r4300_core.h"
|
||||||
|
#include "r4300/interupt.h"
|
||||||
|
#include "r4300/reset.h"
|
||||||
|
#include "rdp/rdp_core.h"
|
||||||
|
#include "ri/ri_controller.h"
|
||||||
|
#include "rsp/rsp_core.h"
|
||||||
|
#include "si/si_controller.h"
|
||||||
|
#include "vi/vi_controller.h"
|
||||||
|
|
||||||
|
/* version number for Core config section */
|
||||||
|
#define CONFIG_PARAM_VERSION 1.01
|
||||||
|
|
||||||
|
/*********************************************************************************************************
|
||||||
|
* helper functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
void main_message(usf_state_t * state, m64p_msg_level level, unsigned int corner, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char buffer[2049];
|
||||||
|
va_start(ap, format);
|
||||||
|
vsnprintf(buffer, 2047, format, ap);
|
||||||
|
buffer[2048]='\0';
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
/* send message to front-end */
|
||||||
|
DebugMessage(state, level, "%s", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************************
|
||||||
|
* global functions, for adjusting the core emulator behavior
|
||||||
|
*/
|
||||||
|
|
||||||
|
m64p_error main_reset(usf_state_t * state, int do_hard_reset)
|
||||||
|
{
|
||||||
|
if (do_hard_reset)
|
||||||
|
state->reset_hard_job |= 1;
|
||||||
|
else
|
||||||
|
reset_soft(state);
|
||||||
|
return M64ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************************
|
||||||
|
* global functions, callbacks from the r4300 core or from other plugins
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* called on vertical interrupt.
|
||||||
|
* Allow the core to perform various things */
|
||||||
|
static void connect_all(
|
||||||
|
usf_state_t* state,
|
||||||
|
struct r4300_core* r4300,
|
||||||
|
struct rdp_core* dp,
|
||||||
|
struct rsp_core* sp,
|
||||||
|
struct ai_controller* ai,
|
||||||
|
struct pi_controller* pi,
|
||||||
|
struct ri_controller* ri,
|
||||||
|
struct si_controller* si,
|
||||||
|
struct vi_controller* vi,
|
||||||
|
uint32_t* dram,
|
||||||
|
size_t dram_size,
|
||||||
|
uint8_t* rom,
|
||||||
|
size_t rom_size)
|
||||||
|
{
|
||||||
|
connect_r4300(r4300, state);
|
||||||
|
connect_rdp(dp, r4300, sp, ri);
|
||||||
|
connect_rsp(sp, r4300, dp, ri);
|
||||||
|
connect_ai(ai, r4300, ri, vi);
|
||||||
|
connect_pi(pi, r4300, ri, rom, rom_size);
|
||||||
|
connect_ri(ri, dram, dram_size);
|
||||||
|
connect_si(si, r4300, ri);
|
||||||
|
connect_vi(vi, r4300);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************************
|
||||||
|
* emulation thread - runs the core
|
||||||
|
*/
|
||||||
|
m64p_error main_start(usf_state_t * state)
|
||||||
|
{
|
||||||
|
unsigned int RDRAMSize;
|
||||||
|
unsigned int disable_extra_mem;
|
||||||
|
|
||||||
|
memcpy(&RDRAMSize, state->save_state + 4, 4);
|
||||||
|
to_little_endian_buffer(&RDRAMSize, 4, 1);
|
||||||
|
|
||||||
|
/* take the r4300 emulator mode from the config file at this point and cache it in a global variable */
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
state->r4300emu = 0;
|
||||||
|
#else
|
||||||
|
state->r4300emu = state->enable_trimming_mode ? 1 : 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* set some other core parameters based on the config file values */
|
||||||
|
state->no_compiled_jump = 0;
|
||||||
|
//state->g_delay_si = 1;
|
||||||
|
state->g_delay_sp = 1;
|
||||||
|
disable_extra_mem = RDRAMSize == 0x400000;
|
||||||
|
state->count_per_op = COUNT_PER_OP_DEFAULT;
|
||||||
|
if (state->count_per_op <= 0)
|
||||||
|
state->count_per_op = state->ROM_PARAMS.countperop;
|
||||||
|
|
||||||
|
connect_all(state, &state->g_r4300, &state->g_dp, &state->g_sp,
|
||||||
|
&state->g_ai, &state->g_pi, &state->g_ri, &state->g_si, &state->g_vi,
|
||||||
|
state->g_rdram, (disable_extra_mem == 0) ? 0x800000 : 0x400000,
|
||||||
|
state->g_rom, state->g_rom_size);
|
||||||
|
|
||||||
|
init_memory(state, (disable_extra_mem == 0) ? 0x800000 : 0x400000);
|
||||||
|
|
||||||
|
/* connect external audio sink to AI component */
|
||||||
|
state->g_ai.user_data = state;
|
||||||
|
state->g_ai.set_audio_format = usf_set_audio_format;
|
||||||
|
state->g_ai.push_audio_samples = usf_push_audio_samples;
|
||||||
|
|
||||||
|
/* call r4300 CPU core and run the game */
|
||||||
|
r4300_reset_hard(state);
|
||||||
|
r4300_reset_soft(state);
|
||||||
|
r4300_begin(state);
|
||||||
|
|
||||||
|
if (!savestates_load(state, state->save_state, state->save_state_size, 0))
|
||||||
|
return M64ERR_INVALID_STATE;
|
||||||
|
|
||||||
|
if (state->enableFIFOfull)
|
||||||
|
{
|
||||||
|
state->g_delay_ai = 1;
|
||||||
|
ai_fifo_queue_int(&state->g_ai);
|
||||||
|
state->g_ai.regs[AI_STATUS_REG] |= 0x40000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return M64ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_run(usf_state_t * state)
|
||||||
|
{
|
||||||
|
r4300_execute(state);
|
||||||
|
}
|
48
Frameworks/lazyusf/lazyusf/main/main.h
Normal file
48
Frameworks/lazyusf/lazyusf/main/main.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - main.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2012 CasualJames *
|
||||||
|
* Copyright (C) 2002 Blight *
|
||||||
|
* *
|
||||||
|
* 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 __MAIN_H__
|
||||||
|
#define __MAIN_H__
|
||||||
|
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct r4300_core;
|
||||||
|
struct rdp_core;
|
||||||
|
struct rsp_core;
|
||||||
|
struct ai_controller;
|
||||||
|
struct pi_controller;
|
||||||
|
struct ri_controller;
|
||||||
|
struct si_controller;
|
||||||
|
struct vi_controller;
|
||||||
|
|
||||||
|
enum { RDRAM_MAX_SIZE = 0x800000 };
|
||||||
|
|
||||||
|
/* globals */
|
||||||
|
void main_message(usf_state_t *, m64p_msg_level level, unsigned int osd_corner, const char *format, ...);
|
||||||
|
|
||||||
|
m64p_error main_start(usf_state_t *);
|
||||||
|
void main_run(usf_state_t *);
|
||||||
|
|
||||||
|
#endif /* __MAIN_H__ */
|
||||||
|
|
133
Frameworks/lazyusf/lazyusf/main/rom.c
Normal file
133
Frameworks/lazyusf/lazyusf/main/rom.c
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - rom.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2008 Tillin9 *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#define M64P_CORE_PROTOTYPES 1
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
|
||||||
|
#include "rom.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "memory/memory.h"
|
||||||
|
#include "r4300/r4300.h"
|
||||||
|
|
||||||
|
#define DEFAULT 16
|
||||||
|
|
||||||
|
#define CHUNKSIZE 1024*128 /* Read files 128KB at a time. */
|
||||||
|
|
||||||
|
static m64p_system_type rom_country_code_to_system_type(unsigned short country_code);
|
||||||
|
static int rom_system_type_to_ai_dac_rate(m64p_system_type system_type);
|
||||||
|
static int rom_system_type_to_vi_limit(m64p_system_type system_type);
|
||||||
|
|
||||||
|
m64p_error open_rom(usf_state_t * state)
|
||||||
|
{
|
||||||
|
if (state->g_rom_size >= sizeof(m64p_rom_header))
|
||||||
|
memcpy(&state->ROM_HEADER, state->g_rom, sizeof(m64p_rom_header));
|
||||||
|
|
||||||
|
/* add some useful properties to ROM_PARAMS */
|
||||||
|
state->ROM_PARAMS.systemtype = SYSTEM_NTSC /*rom_country_code_to_system_type(ROM_HEADER.Country_code)*/;
|
||||||
|
state->ROM_PARAMS.vilimit = rom_system_type_to_vi_limit(state->ROM_PARAMS.systemtype);
|
||||||
|
state->ROM_PARAMS.aidacrate = rom_system_type_to_ai_dac_rate(state->ROM_PARAMS.systemtype);
|
||||||
|
state->ROM_PARAMS.countperop = COUNT_PER_OP_DEFAULT;
|
||||||
|
|
||||||
|
return M64ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
m64p_error close_rom(usf_state_t * state)
|
||||||
|
{
|
||||||
|
free(state->g_rom);
|
||||||
|
state->g_rom = NULL;
|
||||||
|
|
||||||
|
DebugMessage(state, M64MSG_STATUS, "Rom closed.");
|
||||||
|
|
||||||
|
return M64ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
/* ROM utility functions */
|
||||||
|
|
||||||
|
// Get the system type associated to a ROM country code.
|
||||||
|
static m64p_system_type rom_country_code_to_system_type(unsigned short country_code)
|
||||||
|
{
|
||||||
|
switch (country_code & 0xFF)
|
||||||
|
{
|
||||||
|
// PAL codes
|
||||||
|
case 0x44:
|
||||||
|
case 0x46:
|
||||||
|
case 0x49:
|
||||||
|
case 0x50:
|
||||||
|
case 0x53:
|
||||||
|
case 0x55:
|
||||||
|
case 0x58:
|
||||||
|
case 0x59:
|
||||||
|
return SYSTEM_PAL;
|
||||||
|
|
||||||
|
// NTSC codes
|
||||||
|
case 0x37:
|
||||||
|
case 0x41:
|
||||||
|
case 0x45:
|
||||||
|
case 0x4a:
|
||||||
|
default: // Fallback for unknown codes
|
||||||
|
return SYSTEM_NTSC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the VI (vertical interrupt) limit associated to a ROM system type.
|
||||||
|
static int rom_system_type_to_vi_limit(m64p_system_type system_type)
|
||||||
|
{
|
||||||
|
switch (system_type)
|
||||||
|
{
|
||||||
|
case SYSTEM_PAL:
|
||||||
|
case SYSTEM_MPAL:
|
||||||
|
return 50;
|
||||||
|
|
||||||
|
case SYSTEM_NTSC:
|
||||||
|
default:
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rom_system_type_to_ai_dac_rate(m64p_system_type system_type)
|
||||||
|
{
|
||||||
|
switch (system_type)
|
||||||
|
{
|
||||||
|
case SYSTEM_PAL:
|
||||||
|
return 49656530;
|
||||||
|
case SYSTEM_MPAL:
|
||||||
|
return 48628316;
|
||||||
|
case SYSTEM_NTSC:
|
||||||
|
default:
|
||||||
|
return 48681812;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
92
Frameworks/lazyusf/lazyusf/main/rom.h
Normal file
92
Frameworks/lazyusf/lazyusf/main/rom.h
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - rom.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2008 Tillin9 *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 __ROM_H__
|
||||||
|
#define __ROM_H__
|
||||||
|
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define BIT(bitnr) (1ULL << (bitnr))
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define isset_bitmask(x, bitmask) ({ typeof(bitmask) _bitmask = (bitmask); \
|
||||||
|
(_bitmask & (x)) == _bitmask; })
|
||||||
|
#else
|
||||||
|
#define isset_bitmask(x, bitmask) ((bitmask & (x)) == bitmask)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ROM Loading and Saving functions */
|
||||||
|
|
||||||
|
m64p_error open_rom(usf_state_t *);
|
||||||
|
m64p_error close_rom(usf_state_t *);
|
||||||
|
|
||||||
|
typedef struct _rom_params
|
||||||
|
{
|
||||||
|
m64p_system_type systemtype;
|
||||||
|
int vilimit;
|
||||||
|
int aidacrate;
|
||||||
|
char headername[21]; /* ROM Name as in the header, removing trailing whitespace */
|
||||||
|
unsigned char countperop;
|
||||||
|
} rom_params;
|
||||||
|
|
||||||
|
/* Supported rom compressiontypes. */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
UNCOMPRESSED,
|
||||||
|
ZIP_COMPRESSION,
|
||||||
|
GZIP_COMPRESSION,
|
||||||
|
BZIP2_COMPRESSION,
|
||||||
|
LZMA_COMPRESSION,
|
||||||
|
SZIP_COMPRESSION
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Supported rom image types. */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Z64IMAGE,
|
||||||
|
V64IMAGE,
|
||||||
|
N64IMAGE
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Supported CIC chips. */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CIC_NUS_6101,
|
||||||
|
CIC_NUS_6102,
|
||||||
|
CIC_NUS_6103,
|
||||||
|
CIC_NUS_6105,
|
||||||
|
CIC_NUS_6106
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Supported save types. */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
EEPROM_4KB,
|
||||||
|
EEPROM_16KB,
|
||||||
|
SRAM,
|
||||||
|
FLASH_RAM,
|
||||||
|
CONTROLLER_PACK,
|
||||||
|
NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ROM_H__ */
|
||||||
|
|
639
Frameworks/lazyusf/lazyusf/main/savestates.c
Normal file
639
Frameworks/lazyusf/lazyusf/main/savestates.c
Normal file
|
@ -0,0 +1,639 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - savestates.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2012 CasualJames *
|
||||||
|
* Copyright (C) 2009 Olejl Tillin9 *
|
||||||
|
* Copyright (C) 2008 Richard42 Tillin9 *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#define M64P_CORE_PROTOTYPES 1
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
|
||||||
|
#include "savestates.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "rom.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "ai/ai_controller.h"
|
||||||
|
#include "memory/memory.h"
|
||||||
|
#include "r4300/tlb.h"
|
||||||
|
#include "r4300/cp0.h"
|
||||||
|
#include "r4300/cp1.h"
|
||||||
|
#include "r4300/r4300.h"
|
||||||
|
#include "r4300/r4300_core.h"
|
||||||
|
#include "r4300/cached_interp.h"
|
||||||
|
#include "r4300/interupt.h"
|
||||||
|
#include "pi/pi_controller.h"
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
#include "r4300/new_dynarec/new_dynarec.h"
|
||||||
|
#endif
|
||||||
|
#include "rdp/rdp_core.h"
|
||||||
|
#include "ri/ri_controller.h"
|
||||||
|
#include "rsp/rsp_core.h"
|
||||||
|
#include "si/si_controller.h"
|
||||||
|
#include "vi/vi_controller.h"
|
||||||
|
|
||||||
|
static const char* savestate_magic = "M64+SAVE";
|
||||||
|
static const int savestate_latest_version = 0x00010000; /* 1.0 */
|
||||||
|
static const unsigned char pj64_magic[4] = { 0xC8, 0xA6, 0xD8, 0x23 };
|
||||||
|
|
||||||
|
#define GETARRAY(buff, type, count) \
|
||||||
|
(to_little_endian_buffer(buff, sizeof(type),count), \
|
||||||
|
buff += count*sizeof(type), \
|
||||||
|
(type *)(buff-count*sizeof(type)))
|
||||||
|
#define COPYARRAY(dst, buff, type, count) \
|
||||||
|
memcpy(dst, GETARRAY(buff, type, count), sizeof(type)*count)
|
||||||
|
#define GETDATA(buff, type) *GETARRAY(buff, type, 1)
|
||||||
|
|
||||||
|
#define PUTARRAY(src, buff, type, count) \
|
||||||
|
memcpy(buff, src, sizeof(type)*count); \
|
||||||
|
to_little_endian_buffer(buff, sizeof(type), count); \
|
||||||
|
buff += count*sizeof(type);
|
||||||
|
|
||||||
|
#define PUTDATA(buff, type, value) \
|
||||||
|
do { type x = value; PUTARRAY(&x, buff, type, 1); } while(0)
|
||||||
|
|
||||||
|
#define read_bytes(ptr, size) \
|
||||||
|
{ \
|
||||||
|
if ((size) > state_size) \
|
||||||
|
{ \
|
||||||
|
if (savestateData) free(savestateData); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
memcpy((ptr), state_ptr, (size)); \
|
||||||
|
state_ptr += (size); \
|
||||||
|
state_size -= (size); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static int savestates_load_m64p(usf_state_t * state, unsigned char * ptr, unsigned int size)
|
||||||
|
{
|
||||||
|
unsigned char header[44];
|
||||||
|
int version;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
unsigned char * state_ptr = ptr;
|
||||||
|
unsigned int state_size = size;
|
||||||
|
|
||||||
|
size_t savestateSize;
|
||||||
|
unsigned char *savestateData = 0, *curr;
|
||||||
|
char queue[1024];
|
||||||
|
|
||||||
|
/* Read and check Mupen64Plus magic number. */
|
||||||
|
read_bytes(header, 44);
|
||||||
|
curr = header;
|
||||||
|
|
||||||
|
if(strncmp((char *)curr, savestate_magic, 8)!=0)
|
||||||
|
return 0;
|
||||||
|
curr += 8;
|
||||||
|
|
||||||
|
version = *curr++;
|
||||||
|
version = (version << 8) | *curr++;
|
||||||
|
version = (version << 8) | *curr++;
|
||||||
|
version = (version << 8) | *curr++;
|
||||||
|
if(version != 0x00010000)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* skip MD5 */
|
||||||
|
curr += 32;
|
||||||
|
|
||||||
|
/* Read the rest of the savestate */
|
||||||
|
savestateSize = 16788244;
|
||||||
|
if (state_size < savestateSize + sizeof(queue))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
savestateData = curr = malloc(savestateSize);
|
||||||
|
if (!savestateData)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
read_bytes(savestateData, savestateSize);
|
||||||
|
read_bytes(queue, sizeof(queue));
|
||||||
|
|
||||||
|
// Parse savestate
|
||||||
|
state->g_ri.rdram.regs[RDRAM_CONFIG_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_DEVICE_ID_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_DELAY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_MODE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_REF_INTERVAL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_REF_ROW_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_RAS_INTERVAL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_MIN_INTERVAL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_ADDR_SELECT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_DEVICE_MANUF_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
curr += 4; /* Padding from old implementation */
|
||||||
|
state->g_r4300.mi.regs[MI_INIT_MODE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
curr += 4; // Duplicate MI init mode flags from old implementation
|
||||||
|
state->g_r4300.mi.regs[MI_VERSION_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_r4300.mi.regs[MI_INTR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_r4300.mi.regs[MI_INTR_MASK_REG] = GETDATA(curr, uint32_t);
|
||||||
|
curr += 4; /* Padding from old implementation */
|
||||||
|
curr += 8; // Duplicated MI intr flags and padding from old implementation
|
||||||
|
|
||||||
|
state->g_pi.regs[PI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_CART_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_RD_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_WR_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_LAT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_PWD_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_PGS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_RLS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM2_LAT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM2_PWD_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM2_PGS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM2_RLS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
state->g_sp.regs[SP_MEM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_RD_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_WR_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
curr += 4; /* Padding from old implementation */
|
||||||
|
state->g_sp.regs[SP_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
curr += 16; // Duplicated SP flags and padding from old implementation
|
||||||
|
state->g_sp.regs[SP_DMA_FULL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_DMA_BUSY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_SEMAPHORE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
state->g_sp.regs2[SP_PC_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs2[SP_IBIST_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
state->g_si.regs[SI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_si.regs[SI_PIF_ADDR_RD64B_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_si.regs[SI_PIF_ADDR_WR64B_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_si.regs[SI_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
state->g_vi.regs[VI_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_ORIGIN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_WIDTH_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_V_INTR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_CURRENT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_BURST_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_V_SYNC_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_H_SYNC_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_LEAP_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_H_START_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_V_START_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_V_BURST_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_X_SCALE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_Y_SCALE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.delay = GETDATA(curr, unsigned int);
|
||||||
|
|
||||||
|
state->g_ri.regs[RI_MODE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_CONFIG_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_CURRENT_LOAD_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_SELECT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_REFRESH_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_LATENCY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_ERROR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_WERROR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
state->g_ai.regs[AI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_CONTROL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_DACRATE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_BITRATE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.fifo[1].duration = GETDATA(curr, unsigned int);
|
||||||
|
state->g_ai.fifo[1].length = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.fifo[0].duration = GETDATA(curr, unsigned int);
|
||||||
|
state->g_ai.fifo[0].length = GETDATA(curr, uint32_t);
|
||||||
|
/* best effort initialization of fifo addresses...
|
||||||
|
* You might get a small sound "pop" because address might be wrong.
|
||||||
|
* Proper initialization requires changes to savestate format
|
||||||
|
*/
|
||||||
|
state->g_ai.fifo[0].address = state->g_ai.regs[AI_DRAM_ADDR_REG];
|
||||||
|
state->g_ai.fifo[1].address = state->g_ai.regs[AI_DRAM_ADDR_REG];
|
||||||
|
state->g_ai.samples_format_changed = 1;
|
||||||
|
|
||||||
|
state->g_dp.dpc_regs[DPC_START_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_END_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_CURRENT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
curr += 4; // Padding from old implementation
|
||||||
|
state->g_dp.dpc_regs[DPC_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
curr += 12; // Duplicated DPC flags and padding from old implementation
|
||||||
|
state->g_dp.dpc_regs[DPC_CLOCK_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_BUFBUSY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_PIPEBUSY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_TMEM_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
state->g_dp.dps_regs[DPS_TBIST_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dps_regs[DPS_TEST_MODE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dps_regs[DPS_BUFTEST_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dps_regs[DPS_BUFTEST_DATA_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
COPYARRAY(state->g_rdram, curr, uint32_t, RDRAM_MAX_SIZE/4);
|
||||||
|
COPYARRAY(state->g_sp.mem, curr, uint32_t, SP_MEM_SIZE/4);
|
||||||
|
COPYARRAY(state->g_si.pif.ram, curr, uint8_t, PIF_RAM_SIZE);
|
||||||
|
|
||||||
|
/*state->g_pi.use_flashram =*/ (void)GETDATA(curr, int);
|
||||||
|
/*state->g_pi.flashram.mode =*/ (void)GETDATA(curr, int);
|
||||||
|
/*state->g_pi.flashram.status =*/ (void)GETDATA(curr, unsigned long long);
|
||||||
|
/*state->g_pi.flashram.erase_offset =*/ (void)GETDATA(curr, unsigned int);
|
||||||
|
/*state->g_pi.flashram.write_pointer =*/ (void)GETDATA(curr, unsigned int);
|
||||||
|
|
||||||
|
COPYARRAY(state->tlb_LUT_r, curr, unsigned int, 0x100000);
|
||||||
|
COPYARRAY(state->tlb_LUT_w, curr, unsigned int, 0x100000);
|
||||||
|
|
||||||
|
state->llbit = GETDATA(curr, unsigned int);
|
||||||
|
COPYARRAY(state->reg, curr, long long int, 32);
|
||||||
|
COPYARRAY(state->g_cp0_regs, curr, unsigned int, CP0_REGS_COUNT);
|
||||||
|
set_fpr_pointers(state, state->g_cp0_regs[CP0_STATUS_REG]);
|
||||||
|
state->lo = GETDATA(curr, long long int);
|
||||||
|
state->hi = GETDATA(curr, long long int);
|
||||||
|
COPYARRAY(state->reg_cop1_fgr_64, curr, long long int, 32);
|
||||||
|
if ((state->g_cp0_regs[CP0_STATUS_REG] & 0x04000000) == 0) // 32-bit FPR mode requires data shuffling because 64-bit layout is always stored in savestate file
|
||||||
|
shuffle_fpr_data(state, 0x04000000, 0);
|
||||||
|
state->FCR0 = GETDATA(curr, int);
|
||||||
|
state->FCR31 = GETDATA(curr, int);
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
state->tlb_e[i].mask = GETDATA(curr, short);
|
||||||
|
curr += 2;
|
||||||
|
state->tlb_e[i].vpn2 = GETDATA(curr, int);
|
||||||
|
state->tlb_e[i].g = GETDATA(curr, char);
|
||||||
|
state->tlb_e[i].asid = GETDATA(curr, unsigned char);
|
||||||
|
curr += 2;
|
||||||
|
state->tlb_e[i].pfn_even = GETDATA(curr, int);
|
||||||
|
state->tlb_e[i].c_even = GETDATA(curr, char);
|
||||||
|
state->tlb_e[i].d_even = GETDATA(curr, char);
|
||||||
|
state->tlb_e[i].v_even = GETDATA(curr, char);
|
||||||
|
curr++;
|
||||||
|
state->tlb_e[i].pfn_odd = GETDATA(curr, int);
|
||||||
|
state->tlb_e[i].c_odd = GETDATA(curr, char);
|
||||||
|
state->tlb_e[i].d_odd = GETDATA(curr, char);
|
||||||
|
state->tlb_e[i].v_odd = GETDATA(curr, char);
|
||||||
|
state->tlb_e[i].r = GETDATA(curr, char);
|
||||||
|
|
||||||
|
state->tlb_e[i].start_even = GETDATA(curr, unsigned int);
|
||||||
|
state->tlb_e[i].end_even = GETDATA(curr, unsigned int);
|
||||||
|
state->tlb_e[i].phys_even = GETDATA(curr, unsigned int);
|
||||||
|
state->tlb_e[i].start_odd = GETDATA(curr, unsigned int);
|
||||||
|
state->tlb_e[i].end_odd = GETDATA(curr, unsigned int);
|
||||||
|
state->tlb_e[i].phys_odd = GETDATA(curr, unsigned int);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
if (state->r4300emu == CORE_DYNAREC) {
|
||||||
|
state->pcaddr = GETDATA(curr, unsigned int);
|
||||||
|
state->pending_exception = 1;
|
||||||
|
invalidate_all_pages(state);
|
||||||
|
} else {
|
||||||
|
if(state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 0x100000; i++)
|
||||||
|
state->invalid_code[i] = 1;
|
||||||
|
}
|
||||||
|
generic_jump_to(state, GETDATA(curr, unsigned int)); // PC
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 0x100000; i++)
|
||||||
|
state->invalid_code[i] = 1;
|
||||||
|
}
|
||||||
|
generic_jump_to(state, GETDATA(curr, unsigned int)); // PC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
state->next_interupt = GETDATA(curr, unsigned int);
|
||||||
|
state->g_vi.next_vi = GETDATA(curr, unsigned int);
|
||||||
|
state->g_vi.field = GETDATA(curr, unsigned int);
|
||||||
|
|
||||||
|
free(savestateData);
|
||||||
|
|
||||||
|
// assert(savestateData+savestateSize == curr)
|
||||||
|
|
||||||
|
to_little_endian_buffer(queue, 4, 256);
|
||||||
|
load_eventqueue_infos(state, queue);
|
||||||
|
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
if (state->r4300emu == CORE_DYNAREC)
|
||||||
|
state->last_addr = state->pcaddr;
|
||||||
|
else
|
||||||
|
state->last_addr = state->PC->addr;
|
||||||
|
#else
|
||||||
|
state->last_addr = state->PC->addr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int savestates_load_pj64(usf_state_t * state, unsigned char * ptr, unsigned int size)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
unsigned int vi_timer, SaveRDRAMSize;
|
||||||
|
int i;
|
||||||
|
#ifdef DYNAREC
|
||||||
|
unsigned long long dummy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned char header[8];
|
||||||
|
|
||||||
|
unsigned char * state_ptr = ptr;
|
||||||
|
unsigned int state_size = size;
|
||||||
|
|
||||||
|
size_t savestateSize;
|
||||||
|
unsigned char *savestateData = 0, *curr;
|
||||||
|
|
||||||
|
/* Read and check Project64 magic number. */
|
||||||
|
read_bytes(header, 8);
|
||||||
|
|
||||||
|
curr = header;
|
||||||
|
if (memcmp(curr, pj64_magic, 4) != 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
curr += 4;
|
||||||
|
|
||||||
|
SaveRDRAMSize = GETDATA(curr, unsigned int);
|
||||||
|
|
||||||
|
/* Read the rest of the savestate into memory. */
|
||||||
|
savestateSize = SaveRDRAMSize + 0x2754;
|
||||||
|
savestateData = curr = malloc(savestateSize);
|
||||||
|
if (!savestateData)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (state_size < savestateSize)
|
||||||
|
{
|
||||||
|
free(savestateData);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_bytes(savestateData, savestateSize);
|
||||||
|
|
||||||
|
// skip ROM header
|
||||||
|
curr += 0x40;
|
||||||
|
|
||||||
|
// vi_timer
|
||||||
|
vi_timer = GETDATA(curr, unsigned int);
|
||||||
|
|
||||||
|
// Program Counter
|
||||||
|
state->last_addr = GETDATA(curr, unsigned int);
|
||||||
|
|
||||||
|
// GPR
|
||||||
|
COPYARRAY(state->reg, curr, long long int, 32);
|
||||||
|
|
||||||
|
// FPR
|
||||||
|
COPYARRAY(state->reg_cop1_fgr_64, curr, long long int, 32);
|
||||||
|
|
||||||
|
// CP0
|
||||||
|
COPYARRAY(state->g_cp0_regs, curr, unsigned int, CP0_REGS_COUNT);
|
||||||
|
|
||||||
|
set_fpr_pointers(state, state->g_cp0_regs[CP0_STATUS_REG]);
|
||||||
|
if ((state->g_cp0_regs[CP0_STATUS_REG] & 0x04000000) == 0) // TODO not sure how pj64 handles this
|
||||||
|
shuffle_fpr_data(state, 0x04000000, 0);
|
||||||
|
|
||||||
|
// Initialze the interupts
|
||||||
|
vi_timer += state->g_cp0_regs[CP0_COUNT_REG];
|
||||||
|
state->next_interupt = (state->g_cp0_regs[CP0_COMPARE_REG] < vi_timer)
|
||||||
|
? state->g_cp0_regs[CP0_COMPARE_REG]
|
||||||
|
: vi_timer;
|
||||||
|
state->g_vi.next_vi = vi_timer;
|
||||||
|
state->g_vi.field = 0;
|
||||||
|
*((unsigned int*)&buffer[0]) = VI_INT;
|
||||||
|
*((unsigned int*)&buffer[4]) = vi_timer;
|
||||||
|
*((unsigned int*)&buffer[8]) = COMPARE_INT;
|
||||||
|
*((unsigned int*)&buffer[12]) = state->g_cp0_regs[CP0_COMPARE_REG];
|
||||||
|
*((unsigned int*)&buffer[16]) = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
load_eventqueue_infos(state, buffer);
|
||||||
|
|
||||||
|
// FPCR
|
||||||
|
state->FCR0 = GETDATA(curr, int);
|
||||||
|
curr += 30 * 4; // FCR1...FCR30 not supported
|
||||||
|
state->FCR31 = GETDATA(curr, int);
|
||||||
|
|
||||||
|
// hi / lo
|
||||||
|
state->hi = GETDATA(curr, long long int);
|
||||||
|
state->lo = GETDATA(curr, long long int);
|
||||||
|
|
||||||
|
// rdram register
|
||||||
|
state->g_ri.rdram.regs[RDRAM_CONFIG_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_DEVICE_ID_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_DELAY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_MODE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_REF_INTERVAL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_REF_ROW_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_RAS_INTERVAL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_MIN_INTERVAL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_ADDR_SELECT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.rdram.regs[RDRAM_DEVICE_MANUF_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
// sp_register
|
||||||
|
state->g_sp.regs[SP_MEM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_RD_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_WR_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_DMA_FULL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_DMA_BUSY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs[SP_SEMAPHORE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs2[SP_PC_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_sp.regs2[SP_IBIST_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
// dpc_register
|
||||||
|
state->g_dp.dpc_regs[DPC_START_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_END_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_CURRENT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_CLOCK_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_BUFBUSY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_PIPEBUSY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_dp.dpc_regs[DPC_TMEM_REG] = GETDATA(curr, uint32_t);
|
||||||
|
(void)GETDATA(curr, unsigned int); // Dummy read
|
||||||
|
(void)GETDATA(curr, unsigned int); // Dummy read
|
||||||
|
|
||||||
|
// mi_register
|
||||||
|
state->g_r4300.mi.regs[MI_INIT_MODE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_r4300.mi.regs[MI_VERSION_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_r4300.mi.regs[MI_INTR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_r4300.mi.regs[MI_INTR_MASK_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
// vi_register
|
||||||
|
state->g_vi.regs[VI_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_ORIGIN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_WIDTH_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_V_INTR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_CURRENT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_BURST_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_V_SYNC_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_H_SYNC_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_LEAP_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_H_START_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_V_START_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_V_BURST_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_X_SCALE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.regs[VI_Y_SCALE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_vi.delay = (state->g_vi.regs[VI_V_SYNC_REG] == 0)
|
||||||
|
? 500000
|
||||||
|
: (state->g_vi.regs[VI_V_SYNC_REG] + 1)*1500;
|
||||||
|
|
||||||
|
// ai_register
|
||||||
|
state->g_ai.regs[AI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_CONTROL_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_DACRATE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.regs[AI_BITRATE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ai.samples_format_changed = 1;
|
||||||
|
// XXX USF
|
||||||
|
state->g_ai.regs[AI_STATUS_REG] = 0;
|
||||||
|
|
||||||
|
// pi_register
|
||||||
|
state->g_pi.regs[PI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_CART_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_RD_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_WR_LEN_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_LAT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_PWD_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_PGS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_RLS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM2_LAT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM2_PWD_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM2_PGS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_pi.regs[PI_BSD_DOM2_RLS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
// ri_register
|
||||||
|
state->g_ri.regs[RI_MODE_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_CONFIG_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_CURRENT_LOAD_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_SELECT_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_REFRESH_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_LATENCY_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_ERROR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_ri.regs[RI_WERROR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
// si_register
|
||||||
|
state->g_si.regs[SI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_si.regs[SI_PIF_ADDR_RD64B_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_si.regs[SI_PIF_ADDR_WR64B_REG] = GETDATA(curr, uint32_t);
|
||||||
|
state->g_si.regs[SI_STATUS_REG] = GETDATA(curr, uint32_t);
|
||||||
|
|
||||||
|
// tlb
|
||||||
|
memset(state->tlb_LUT_r, 0, 0x400000);
|
||||||
|
memset(state->tlb_LUT_w, 0, 0x400000);
|
||||||
|
for (i=0; i < 32; i++)
|
||||||
|
{
|
||||||
|
unsigned int MyPageMask, MyEntryHi, MyEntryLo0, MyEntryLo1;
|
||||||
|
|
||||||
|
(void)GETDATA(curr, unsigned int); // Dummy read - EntryDefined
|
||||||
|
MyPageMask = GETDATA(curr, unsigned int);
|
||||||
|
MyEntryHi = GETDATA(curr, unsigned int);
|
||||||
|
MyEntryLo0 = GETDATA(curr, unsigned int);
|
||||||
|
MyEntryLo1 = GETDATA(curr, unsigned int);
|
||||||
|
|
||||||
|
// This is copied from TLBWI instruction
|
||||||
|
state->tlb_e[i].g = (MyEntryLo0 & MyEntryLo1 & 1);
|
||||||
|
state->tlb_e[i].pfn_even = (MyEntryLo0 & 0x3FFFFFC0) >> 6;
|
||||||
|
state->tlb_e[i].pfn_odd = (MyEntryLo1 & 0x3FFFFFC0) >> 6;
|
||||||
|
state->tlb_e[i].c_even = (MyEntryLo0 & 0x38) >> 3;
|
||||||
|
state->tlb_e[i].c_odd = (MyEntryLo1 & 0x38) >> 3;
|
||||||
|
state->tlb_e[i].d_even = (MyEntryLo0 & 0x4) >> 2;
|
||||||
|
state->tlb_e[i].d_odd = (MyEntryLo1 & 0x4) >> 2;
|
||||||
|
state->tlb_e[i].v_even = (MyEntryLo0 & 0x2) >> 1;
|
||||||
|
state->tlb_e[i].v_odd = (MyEntryLo1 & 0x2) >> 1;
|
||||||
|
state->tlb_e[i].asid = (MyEntryHi & 0xFF);
|
||||||
|
state->tlb_e[i].vpn2 = (MyEntryHi & 0xFFFFE000) >> 13;
|
||||||
|
//state->tlb_e[i].r = (MyEntryHi & 0xC000000000000000LL) >> 62;
|
||||||
|
state->tlb_e[i].mask = (MyPageMask & 0x1FFE000) >> 13;
|
||||||
|
|
||||||
|
state->tlb_e[i].start_even = state->tlb_e[i].vpn2 << 13;
|
||||||
|
state->tlb_e[i].end_even = state->tlb_e[i].start_even+
|
||||||
|
(state->tlb_e[i].mask << 12) + 0xFFF;
|
||||||
|
state->tlb_e[i].phys_even = state->tlb_e[i].pfn_even << 12;
|
||||||
|
|
||||||
|
state->tlb_e[i].start_odd = state->tlb_e[i].end_even+1;
|
||||||
|
state->tlb_e[i].end_odd = state->tlb_e[i].start_odd+
|
||||||
|
(state->tlb_e[i].mask << 12) + 0xFFF;
|
||||||
|
state->tlb_e[i].phys_odd = state->tlb_e[i].pfn_odd << 12;
|
||||||
|
|
||||||
|
tlb_map(state, &state->tlb_e[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pif ram
|
||||||
|
COPYARRAY(state->g_si.pif.ram, curr, uint8_t, PIF_RAM_SIZE);
|
||||||
|
|
||||||
|
// RDRAM
|
||||||
|
memset(state->g_rdram, 0, RDRAM_MAX_SIZE);
|
||||||
|
COPYARRAY(state->g_rdram, curr, uint32_t, SaveRDRAMSize/4);
|
||||||
|
|
||||||
|
// DMEM + IMEM
|
||||||
|
COPYARRAY(state->g_sp.mem, curr, uint32_t, SP_MEM_SIZE/4);
|
||||||
|
|
||||||
|
// The following values should not matter because we don't have any AI interrupt
|
||||||
|
// g_ai.fifo[1].delay = 0; g_ai.fifo[1].length = 0;
|
||||||
|
// g_ai.fifo[0].delay = 0; g_ai.fifo[0].length = 0;
|
||||||
|
|
||||||
|
// The following is not available in PJ64 savestate. Keep the values as is.
|
||||||
|
// g_dp.dps_regs[DPS_TBIST_REG] = 0; g_dp.dps_regs[DPS_TEST_MODE_REG] = 0;
|
||||||
|
// g_dp.dps_regs[DPS_BUFTEST_ADDR_REG] = 0; g_dp.dps_regs[DPS_BUFTEST_DATA_REG] = 0; llbit = 0;
|
||||||
|
|
||||||
|
// No flashram info in pj64 savestate.
|
||||||
|
//init_flashram(&state->g_pi.flashram);
|
||||||
|
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
if (state->r4300emu == CORE_DYNAREC) {
|
||||||
|
state->pcaddr = state->last_addr;
|
||||||
|
state->pending_exception = 1;
|
||||||
|
invalidate_all_pages(state);
|
||||||
|
} else {
|
||||||
|
if(state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 0x100000; i++)
|
||||||
|
state->invalid_code[i] = 1;
|
||||||
|
}
|
||||||
|
generic_jump_to(state, state->last_addr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 0x100000; i++)
|
||||||
|
state->invalid_code[i] = 1;
|
||||||
|
}
|
||||||
|
#ifdef DYNAREC
|
||||||
|
*(void **)&state->return_address = (void *)&dummy;
|
||||||
|
#endif
|
||||||
|
generic_jump_to(state, state->last_addr);
|
||||||
|
#ifdef DYNAREC
|
||||||
|
*(void **)&state->return_address = (void *)0;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// assert(savestateData+savestateSize == curr)
|
||||||
|
|
||||||
|
free(savestateData);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int savestates_load(usf_state_t * state, unsigned char * ptr, unsigned int size, unsigned int is_m64p)
|
||||||
|
{
|
||||||
|
if (is_m64p)
|
||||||
|
return savestates_load_m64p(state, ptr, size);
|
||||||
|
else
|
||||||
|
return savestates_load_pj64(state, ptr, size);
|
||||||
|
}
|
31
Frameworks/lazyusf/lazyusf/main/savestates.h
Normal file
31
Frameworks/lazyusf/lazyusf/main/savestates.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - savestates.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2012 CasualJames *
|
||||||
|
* Copyright (C) 2009 Olejl Tillin9 *
|
||||||
|
* Copyright (C) 2008 Richard42 Tillin9 *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 __SAVESTAVES_H__
|
||||||
|
#define __SAVESTAVES_H__
|
||||||
|
|
||||||
|
int savestates_load(usf_state_t *, unsigned char * ptr, unsigned int size, unsigned int is_m64p);
|
||||||
|
|
||||||
|
#endif /* __SAVESTAVES_H__ */
|
||||||
|
|
186
Frameworks/lazyusf/lazyusf/main/util.c
Normal file
186
Frameworks/lazyusf/lazyusf/main/util.c
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - util.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2012 CasualJames *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides common utilities to the rest of the code:
|
||||||
|
* -String functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "rom.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
Byte swap utilities
|
||||||
|
**********************/
|
||||||
|
void swap_buffer(void *buffer, size_t length, size_t count)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (length == 2)
|
||||||
|
{
|
||||||
|
unsigned short *pun = (unsigned short *)buffer;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
pun[i] = m64p_swap16(pun[i]);
|
||||||
|
}
|
||||||
|
else if (length == 4)
|
||||||
|
{
|
||||||
|
unsigned int *pun = (unsigned int *)buffer;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
pun[i] = m64p_swap32(pun[i]);
|
||||||
|
}
|
||||||
|
else if (length == 8)
|
||||||
|
{
|
||||||
|
unsigned long long *pun = (unsigned long long *)buffer;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
pun[i] = m64p_swap64(pun[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_little_endian_buffer(void *buffer, size_t length, size_t count)
|
||||||
|
{
|
||||||
|
#ifdef M64P_BIG_ENDIAN
|
||||||
|
swap_buffer(buffer, length, count);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_big_endian_buffer(void *buffer, size_t length, size_t count)
|
||||||
|
{
|
||||||
|
#ifndef M64P_BIG_ENDIAN
|
||||||
|
swap_buffer(buffer, length, count);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
String utilities
|
||||||
|
**********************/
|
||||||
|
char *trim(char *str)
|
||||||
|
{
|
||||||
|
char *start = str, *end = str + strlen(str);
|
||||||
|
|
||||||
|
while (start < end && isspace(*start))
|
||||||
|
start++;
|
||||||
|
|
||||||
|
while (end > start && isspace(*(end-1)))
|
||||||
|
end--;
|
||||||
|
|
||||||
|
memmove(str, start, end - start);
|
||||||
|
str[end - start] = '\0';
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int string_to_int(const char *str, int *result)
|
||||||
|
{
|
||||||
|
char *endptr;
|
||||||
|
long int n;
|
||||||
|
if (*str == '\0' || isspace(*str))
|
||||||
|
return 0;
|
||||||
|
errno = 0;
|
||||||
|
n = strtol(str, &endptr, 10);
|
||||||
|
if (*endptr != '\0' || errno != 0 || n < INT_MIN || n > INT_MAX)
|
||||||
|
return 0;
|
||||||
|
*result = (int)n;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char char2hex(char c)
|
||||||
|
{
|
||||||
|
c = tolower(c);
|
||||||
|
if(c >= '0' && c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
else if(c >= 'a' && c <= 'f')
|
||||||
|
return c - 'a' + 10;
|
||||||
|
else
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_hex(const char *str, unsigned char *output, size_t output_size)
|
||||||
|
{
|
||||||
|
size_t i, j;
|
||||||
|
for (i = 0; i < output_size; i++)
|
||||||
|
{
|
||||||
|
output[i] = 0;
|
||||||
|
for (j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
unsigned char h = char2hex(*str++);
|
||||||
|
if (h == 0xFF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
output[i] = (output[i] << 4) | h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*str != '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *formatstr(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
int size = 128, ret;
|
||||||
|
char *str = (char *)malloc(size), *newstr;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
/* There are two implementations of vsnprintf we have to deal with:
|
||||||
|
* C99 version: Returns the number of characters which would have been written
|
||||||
|
* if the buffer had been large enough, and -1 on failure.
|
||||||
|
* Windows version: Returns the number of characters actually written,
|
||||||
|
* and -1 on failure or truncation.
|
||||||
|
* NOTE: An implementation equivalent to the Windows one appears in glibc <2.1.
|
||||||
|
*/
|
||||||
|
while (str != NULL)
|
||||||
|
{
|
||||||
|
va_start(args, fmt);
|
||||||
|
ret = vsnprintf(str, size, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
// Successful result?
|
||||||
|
if (ret >= 0 && ret < size)
|
||||||
|
return str;
|
||||||
|
|
||||||
|
// Increment the capacity of the buffer
|
||||||
|
if (ret >= size)
|
||||||
|
size = ret + 1; // C99 version: We got the needed buffer size
|
||||||
|
else
|
||||||
|
size *= 2; // Windows version: Keep guessing
|
||||||
|
|
||||||
|
newstr = (char *)realloc(str, size);
|
||||||
|
if (newstr == NULL)
|
||||||
|
free(str);
|
||||||
|
str = newstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
213
Frameworks/lazyusf/lazyusf/main/util.h
Normal file
213
Frameworks/lazyusf/lazyusf/main/util.h
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - util.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2012 CasualJames *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 __UTIL_H__
|
||||||
|
#define __UTIL_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
File utilities
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
typedef enum _file_status
|
||||||
|
{
|
||||||
|
file_ok,
|
||||||
|
file_open_error,
|
||||||
|
file_read_error,
|
||||||
|
file_write_error
|
||||||
|
} file_status_t;
|
||||||
|
|
||||||
|
/** read_from_file
|
||||||
|
* opens a file and reads the specified number of bytes.
|
||||||
|
* returns zero on success, nonzero on failure
|
||||||
|
*/
|
||||||
|
file_status_t read_from_file(const char *filename, void *data, size_t size);
|
||||||
|
|
||||||
|
/** write_to_file
|
||||||
|
* opens a file and writes the specified number of bytes.
|
||||||
|
* returns zero on sucess, nonzero on failure
|
||||||
|
*/
|
||||||
|
file_status_t write_to_file(const char *filename, const void *data, size_t size);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
Byte swap utilities
|
||||||
|
**********************/
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* GCC has also byte swap intrinsics (__builtin_bswap32, etc.), but they were
|
||||||
|
* added in relatively recent versions. In addition, GCC can detect the byte
|
||||||
|
* swap code and optimize it with a high enough optimization level. */
|
||||||
|
|
||||||
|
static osal_inline unsigned short m64p_swap16(unsigned short x)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _byteswap_ushort(x);
|
||||||
|
#else
|
||||||
|
return ((x & 0x00FF) << 8) |
|
||||||
|
((x & 0xFF00) >> 8);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static osal_inline unsigned int m64p_swap32(unsigned int x)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _byteswap_ulong(x); // long is always 32-bit in Windows
|
||||||
|
#else
|
||||||
|
return ((x & 0x000000FF) << 24) |
|
||||||
|
((x & 0x0000FF00) << 8) |
|
||||||
|
((x & 0x00FF0000) >> 8) |
|
||||||
|
((x & 0xFF000000) >> 24);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static osal_inline unsigned long long int m64p_swap64(unsigned long long int x)
|
||||||
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
return _byteswap_uint64(x);
|
||||||
|
#else
|
||||||
|
return ((x & 0x00000000000000FFULL) << 56) |
|
||||||
|
((x & 0x000000000000FF00ULL) << 40) |
|
||||||
|
((x & 0x0000000000FF0000ULL) << 24) |
|
||||||
|
((x & 0x00000000FF000000ULL) << 8) |
|
||||||
|
((x & 0x000000FF00000000ULL) >> 8) |
|
||||||
|
((x & 0x0000FF0000000000ULL) >> 24) |
|
||||||
|
((x & 0x00FF000000000000ULL) >> 40) |
|
||||||
|
((x & 0xFF00000000000000ULL) >> 56);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef M64P_BIG_ENDIAN
|
||||||
|
#define big16(x) (x)
|
||||||
|
#define big32(x) (x)
|
||||||
|
#define big64(x) (x)
|
||||||
|
#define little16(x) m64p_swap16(x)
|
||||||
|
#define little32(x) m64p_swap32(x)
|
||||||
|
#define little64(x) m64p_swap64(x)
|
||||||
|
#else
|
||||||
|
#define big16(x) m64p_swap16(x)
|
||||||
|
#define big32(x) m64p_swap32(x)
|
||||||
|
#define big64(x) m64p_swap64(x)
|
||||||
|
#define little16(x) (x)
|
||||||
|
#define little32(x) (x)
|
||||||
|
#define little64(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Byte swaps, converts to little endian or converts to big endian a buffer,
|
||||||
|
* containing 'count' elements, each of size 'length'. */
|
||||||
|
void swap_buffer(void *buffer, size_t length, size_t count);
|
||||||
|
void to_little_endian_buffer(void *buffer, size_t length, size_t count);
|
||||||
|
void to_big_endian_buffer(void *buffer, size_t length, size_t count);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
GUI utilities
|
||||||
|
**********************/
|
||||||
|
void countrycodestring(unsigned short countrycode, char *string);
|
||||||
|
void imagestring(unsigned char imagetype, char *string);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
Path utilities
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/* Extracts the full file name (with extension) from a path string.
|
||||||
|
* Returns the same string, advanced until the file name. */
|
||||||
|
const char* namefrompath(const char* path);
|
||||||
|
|
||||||
|
/* Creates a path string by joining two path strings.
|
||||||
|
* The given path strings may or may not start or end with a path separator.
|
||||||
|
* Returns a malloc'd string with the resulting path. */
|
||||||
|
char* combinepath(const char* first, const char *second);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
String utilities
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/** trim
|
||||||
|
* Removes leading and trailing whitespace from str. Function modifies str
|
||||||
|
* and also returns modified string.
|
||||||
|
*/
|
||||||
|
char *trim(char *str);
|
||||||
|
|
||||||
|
/* Converts an string to an integer.
|
||||||
|
* Returns 1 on success, 0 on failure. 'result' is undefined on failure.
|
||||||
|
*
|
||||||
|
* The following conditions cause this function to fail:
|
||||||
|
* - Empty string
|
||||||
|
* - Leading characters (including whitespace)
|
||||||
|
* - Trailing characters (including whitespace)
|
||||||
|
* - Overflow or underflow.
|
||||||
|
*/
|
||||||
|
int string_to_int(const char *str, int *result);
|
||||||
|
|
||||||
|
/* Converts an string of hexadecimal characters to a byte array.
|
||||||
|
* 'output_size' is the number of bytes (hex digraphs) to convert.
|
||||||
|
* Returns 1 on success, 0 on failure. 'output' is undefined on failure. */
|
||||||
|
int parse_hex(const char *str, unsigned char *output, size_t output_size);
|
||||||
|
|
||||||
|
/* Formats an string, using the same syntax as printf.
|
||||||
|
* Returns the result in a malloc'd string. */
|
||||||
|
char* formatstr(const char* fmt, ...);
|
||||||
|
|
||||||
|
typedef enum _ini_line_type
|
||||||
|
{
|
||||||
|
INI_BLANK,
|
||||||
|
INI_COMMENT,
|
||||||
|
INI_SECTION,
|
||||||
|
INI_PROPERTY,
|
||||||
|
INI_TRASH
|
||||||
|
} ini_line_type;
|
||||||
|
|
||||||
|
typedef struct _ini_line
|
||||||
|
{
|
||||||
|
ini_line_type type;
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
|
} ini_line;
|
||||||
|
|
||||||
|
/* Parses the INI file line pointer by 'lineptr'.
|
||||||
|
* The first line pointed by 'lineptr' may be modifed.
|
||||||
|
* 'lineptr' will point to the next line after this function runs.
|
||||||
|
*
|
||||||
|
* Returns a ini_line structure with information about the line.
|
||||||
|
* For INI_COMMENT, the value field contains the comment.
|
||||||
|
* For INI_SECTION, the name field contains the section name.
|
||||||
|
* For INI_PROPERTY, the name and value fields contain the property parameters.
|
||||||
|
* The line type is INI_BLANK if the line is blank or invalid.
|
||||||
|
*
|
||||||
|
* The name and value fields (if any) of ini_line point to 'lineptr'
|
||||||
|
* (so their lifetime is associated to that of 'lineptr').
|
||||||
|
*/
|
||||||
|
ini_line ini_parse_line(char **lineptr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __UTIL_H__
|
||||||
|
|
39
Frameworks/lazyusf/lazyusf/main/version.h
Normal file
39
Frameworks/lazyusf/lazyusf/main/version.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - version.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2008-2012 Richard42 DarkJeztr Tillin9 *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* Version macros automatically replaced by Makefiles. */
|
||||||
|
|
||||||
|
#ifndef __VERSION_H__
|
||||||
|
#define __VERSION_H__
|
||||||
|
|
||||||
|
#define MUPEN_CORE_NAME "Mupen64Plus Core"
|
||||||
|
#define MUPEN_CORE_VERSION 0x020000
|
||||||
|
|
||||||
|
#define FRONTEND_API_VERSION 0x020101
|
||||||
|
#define CONFIG_API_VERSION 0x020300
|
||||||
|
#define DEBUG_API_VERSION 0x020000
|
||||||
|
#define VIDEXT_API_VERSION 0x030000
|
||||||
|
|
||||||
|
#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff)
|
||||||
|
|
||||||
|
#endif /* __VERSION_H__ */
|
||||||
|
|
||||||
|
|
|
@ -1,839 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "usf.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "audio.h"
|
|
||||||
#include "rsp.h"
|
|
||||||
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
uint8_t * PageROM(usf_state_t * state, uint32_t addr) {
|
|
||||||
return (state->ROMPages[addr/0x10000])?state->ROMPages[addr/0x10000]+(addr%0x10000):&state->EmptySpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
void * large_alloc(size_t);
|
|
||||||
void large_free(void *, size_t);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
void * large_alloc(size_t size)
|
|
||||||
{
|
|
||||||
return VirtualAlloc( NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
|
|
||||||
}
|
|
||||||
|
|
||||||
void large_free(void * p, size_t size)
|
|
||||||
{
|
|
||||||
VirtualFree( p, size, MEM_RELEASE );
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#define MAP_ANONYMOUS MAP_ANON
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void * large_alloc(size_t size)
|
|
||||||
{
|
|
||||||
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void large_free(void * p, size_t size)
|
|
||||||
{
|
|
||||||
munmap( p, size );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int32_t Allocate_Memory ( void * state ) {
|
|
||||||
//uint32_t i = 0;
|
|
||||||
//RdramSize = 0x800000;
|
|
||||||
|
|
||||||
// Allocate the N64MEM and TLB_Map so that they are in each others 4GB range
|
|
||||||
// Also put the registers there :)
|
|
||||||
|
|
||||||
|
|
||||||
// the mmap technique works craptacular when the regions don't overlay
|
|
||||||
|
|
||||||
USF_STATE->MemChunk = (uint8_t *) large_alloc( 0x100000 * sizeof(uintptr_t) + 0x1D000 + USF_STATE->RdramSize );
|
|
||||||
|
|
||||||
USF_STATE->TLB_Map = (uintptr_t*)USF_STATE->MemChunk;
|
|
||||||
if (USF_STATE->TLB_Map == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(USF_STATE->TLB_Map, 0, 0x100000 * sizeof(uintptr_t) + 0x10000);
|
|
||||||
|
|
||||||
USF_STATE->N64MEM = USF_STATE->MemChunk + 0x100000 * sizeof(uintptr_t) + 0x10000;
|
|
||||||
if(USF_STATE->N64MEM == NULL) {
|
|
||||||
DisplayError(USF_STATE, "Failed to allocate N64MEM");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//memset(state->N64MEM, 0, USF_STATE->RdramSize);
|
|
||||||
|
|
||||||
USF_STATE->NOMEM = USF_STATE->N64MEM + USF_STATE->RdramSize;
|
|
||||||
|
|
||||||
//if(USF_STATE->RdramSize == 0x400000)
|
|
||||||
//{
|
|
||||||
// munmap(N64MEM + 0x400000, 0x400000);
|
|
||||||
//}
|
|
||||||
|
|
||||||
USF_STATE->Registers = (N64_REGISTERS *)((uintptr_t)USF_STATE->MemChunk + 0x100000 * sizeof(uintptr_t));
|
|
||||||
//USF_STATE->TLBLoadAddress = (uint32_t *)((uintptr_t)USF_STATE->Registers + 0x500);
|
|
||||||
//USF_STATE->Timers = (SYSTEM_TIMERS*)(USF_STATE->TLBLoadAddress + 4);
|
|
||||||
USF_STATE->Timers = (SYSTEM_TIMERS*)((uintptr_t)USF_STATE->Registers + 0x500);
|
|
||||||
USF_STATE->WaitMode = (uint32_t *)(USF_STATE->Timers + sizeof(SYSTEM_TIMERS));
|
|
||||||
USF_STATE->CPU_Action = (CPU_ACTION *)(USF_STATE->WaitMode + 4);
|
|
||||||
//USF_STATE->RSP_GPR = (struct RSP_GPR_TYPE *)(USF_STATE->CPU_Action + sizeof(CPU_ACTION));
|
|
||||||
//USF_STATE->DMEM = (uint8_t *)(USF_STATE->RSP_GPR + (32 * 16));
|
|
||||||
USF_STATE->DMEM = (uint8_t *)(USF_STATE->CPU_Action + sizeof(CPU_ACTION));
|
|
||||||
//state->RSP_ACCUM = (struct RSP_ACCUM_TYPE *)(USF_STATE->DMEM + 0x2000);
|
|
||||||
|
|
||||||
USF_STATE->RDRAM = (uint8_t *)(USF_STATE->N64MEM);
|
|
||||||
USF_STATE->IMEM = USF_STATE->DMEM + 0x1000;
|
|
||||||
|
|
||||||
USF_STATE->MemoryState = 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PreAllocate_Memory(usf_state_t * state) {
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
// Moved the savestate allocation here :) (for better management later)
|
|
||||||
state->savestatespace = (uint8_t *) malloc(0x80275C);
|
|
||||||
|
|
||||||
if(state->savestatespace == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memset(state->savestatespace, 0, 0x80275C);
|
|
||||||
|
|
||||||
for (i = 0; i < 0x400; i++) {
|
|
||||||
state->ROMPages[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Release_Memory ( usf_state_t * state ) {
|
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < 0x400; i++) {
|
|
||||||
if (state->ROMPages[i]) {
|
|
||||||
free(state->ROMPages[i]); state->ROMPages[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//printf("Freeing memory\n");
|
|
||||||
|
|
||||||
state->MemoryState = 0;
|
|
||||||
|
|
||||||
if (state->MemChunk != 0) { large_free( state->MemChunk, 0x100000 * sizeof(uintptr_t) + 0x1D000 + state->RdramSize ); state->MemChunk=0; }
|
|
||||||
|
|
||||||
if(state->cpu_hle_entries)
|
|
||||||
free(state->cpu_hle_entries);
|
|
||||||
state->cpu_hle_entries = NULL;
|
|
||||||
|
|
||||||
if(state->savestatespace)
|
|
||||||
free(state->savestatespace);
|
|
||||||
state->savestatespace = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32_t r4300i_LB_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t * Value, uint32_t SignExtend ) {
|
|
||||||
if (PAddr >= 0x10000000 && PAddr < 0x16000000) {
|
|
||||||
if (state->WrittenToRom) { return 0; }
|
|
||||||
if ((PAddr & 2) == 0) { PAddr = (PAddr + 4) ^ 2; }
|
|
||||||
if ((PAddr - 0x10000000) < state->RomFileSize) {
|
|
||||||
if (SignExtend) {
|
|
||||||
*Value = (char)*PageROM(state, (PAddr - 0x10000000)^3);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
*Value = *PageROM(state, (PAddr - 0x10000000)^3);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
*Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (PAddr & 0xFFF00000) {
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t r4300i_LB_VAddr ( usf_state_t * state, uint32_t VAddr, uint8_t * Value ) {
|
|
||||||
uintptr_t address;
|
|
||||||
address = state->TLB_Map[VAddr >> 12];
|
|
||||||
if (address == 0) { return 0; }
|
|
||||||
*Value = *(uint8_t *)(address + (VAddr ^ 3));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t r4300i_LD_VAddr ( usf_state_t * state, uint32_t VAddr, uint64_t * Value ) {
|
|
||||||
uintptr_t address;
|
|
||||||
address = state->TLB_Map[VAddr >> 12];
|
|
||||||
if (address == 0) { return 0; }
|
|
||||||
if (address + VAddr + 7 - (uintptr_t)state->N64MEM >= state->RdramSize)
|
|
||||||
{
|
|
||||||
*((uint32_t *)(Value) + 1) = 0;
|
|
||||||
*((uint32_t *)(Value)) = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*((uint32_t *)(Value) + 1) = *(uint32_t *)(address + VAddr);
|
|
||||||
*((uint32_t *)(Value)) = *(uint32_t *)(address + VAddr + 4);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t r4300i_LH_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t * Value, int32_t SignExtend ) {
|
|
||||||
(void)state;
|
|
||||||
(void)SignExtend;
|
|
||||||
switch (PAddr & 0xFFF00000) {
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t r4300i_LH_VAddr ( usf_state_t * state, uint32_t VAddr, uint16_t * Value ) {
|
|
||||||
uintptr_t address;
|
|
||||||
address = state->TLB_Map[VAddr >> 12];
|
|
||||||
if (address == 0)
|
|
||||||
return 0;
|
|
||||||
if (address + (VAddr ^ 2) + 1 - (uintptr_t)state->N64MEM >= state->RdramSize)
|
|
||||||
{
|
|
||||||
*Value = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*Value = *(uint16_t *)(address + (VAddr ^ 2));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t r4300i_LW_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t * Value ) {
|
|
||||||
if (PAddr >= 0x10000000 && PAddr < 0x16000000) {
|
|
||||||
if (state->WrittenToRom) {
|
|
||||||
*Value = state->WroteToRom;
|
|
||||||
//LogMessage("%X: Read crap from Rom %X from %X",PROGRAM_COUNTER,*Value,PAddr);
|
|
||||||
state->WrittenToRom = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ((PAddr - 0x10000000) < state->RomFileSize) {
|
|
||||||
*Value = *(uint32_t *)PageROM(state, (PAddr - 0x10000000));
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
*Value = PAddr & 0xFFFF;
|
|
||||||
*Value = (*Value << 16) | *Value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (PAddr & 0xFFF00000) {
|
|
||||||
case 0x03F00000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x03F00000: * Value = RDRAM_CONFIG_REG; break;
|
|
||||||
case 0x03F00004: * Value = RDRAM_DEVICE_ID_REG; break;
|
|
||||||
case 0x03F00008: * Value = RDRAM_DELAY_REG; break;
|
|
||||||
case 0x03F0000C: * Value = RDRAM_MODE_REG; break;
|
|
||||||
case 0x03F00010: * Value = RDRAM_REF_INTERVAL_REG; break;
|
|
||||||
case 0x03F00014: * Value = RDRAM_REF_ROW_REG; break;
|
|
||||||
case 0x03F00018: * Value = RDRAM_RAS_INTERVAL_REG; break;
|
|
||||||
case 0x03F0001C: * Value = RDRAM_MIN_INTERVAL_REG; break;
|
|
||||||
case 0x03F00020: * Value = RDRAM_ADDR_SELECT_REG; break;
|
|
||||||
case 0x03F00024: * Value = RDRAM_DEVICE_MANUF_REG; break;
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04000000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04040010: *Value = SP_STATUS_REG; break;
|
|
||||||
case 0x04040014: *Value = SP_DMA_FULL_REG; break;
|
|
||||||
case 0x04040018: *Value = SP_DMA_BUSY_REG; break;
|
|
||||||
case 0x04080000: *Value = SP_PC_REG; break;
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04100000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x0410000C: *Value = DPC_STATUS_REG; break;
|
|
||||||
case 0x04100010: *Value = DPC_CLOCK_REG; break;
|
|
||||||
case 0x04100014: *Value = DPC_BUFBUSY_REG; break;
|
|
||||||
case 0x04100018: *Value = DPC_PIPEBUSY_REG; break;
|
|
||||||
case 0x0410001C: *Value = DPC_TMEM_REG; break;
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04300000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04300000: * Value = MI_MODE_REG; break;
|
|
||||||
case 0x04300004: * Value = MI_VERSION_REG; break;
|
|
||||||
case 0x04300008: * Value = MI_INTR_REG; break;
|
|
||||||
case 0x0430000C: * Value = MI_INTR_MASK_REG; break;
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04400000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04400000: *Value = VI_STATUS_REG; break;
|
|
||||||
case 0x04400004: *Value = VI_ORIGIN_REG; break;
|
|
||||||
case 0x04400008: *Value = VI_WIDTH_REG; break;
|
|
||||||
case 0x0440000C: *Value = VI_INTR_REG; break;
|
|
||||||
case 0x04400010:
|
|
||||||
*Value = 0;
|
|
||||||
break;
|
|
||||||
case 0x04400014: *Value = VI_BURST_REG; break;
|
|
||||||
case 0x04400018: *Value = VI_V_SYNC_REG; break;
|
|
||||||
case 0x0440001C: *Value = VI_H_SYNC_REG; break;
|
|
||||||
case 0x04400020: *Value = VI_LEAP_REG; break;
|
|
||||||
case 0x04400024: *Value = VI_H_START_REG; break;
|
|
||||||
case 0x04400028: *Value = VI_V_START_REG ; break;
|
|
||||||
case 0x0440002C: *Value = VI_V_BURST_REG; break;
|
|
||||||
case 0x04400030: *Value = VI_X_SCALE_REG; break;
|
|
||||||
case 0x04400034: *Value = VI_Y_SCALE_REG; break;
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04500000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04500004: *Value = AiReadLength(state); break;
|
|
||||||
case 0x0450000C: *Value = AI_STATUS_REG; break;
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04600000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04600010: *Value = PI_STATUS_REG; break;
|
|
||||||
case 0x04600014: *Value = PI_DOMAIN1_REG; break;
|
|
||||||
case 0x04600018: *Value = PI_BSD_DOM1_PWD_REG; break;
|
|
||||||
case 0x0460001C: *Value = PI_BSD_DOM1_PGS_REG; break;
|
|
||||||
case 0x04600020: *Value = PI_BSD_DOM1_RLS_REG; break;
|
|
||||||
case 0x04600024: *Value = PI_DOMAIN2_REG; break;
|
|
||||||
case 0x04600028: *Value = PI_BSD_DOM2_PWD_REG; break;
|
|
||||||
case 0x0460002C: *Value = PI_BSD_DOM2_PGS_REG; break;
|
|
||||||
case 0x04600030: *Value = PI_BSD_DOM2_RLS_REG; break;
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04700000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04700000: * Value = RI_MODE_REG; break;
|
|
||||||
case 0x04700004: * Value = RI_CONFIG_REG; break;
|
|
||||||
case 0x04700008: * Value = RI_CURRENT_LOAD_REG; break;
|
|
||||||
case 0x0470000C: * Value = RI_SELECT_REG; break;
|
|
||||||
case 0x04700010: * Value = RI_REFRESH_REG; break;
|
|
||||||
case 0x04700014: * Value = RI_LATENCY_REG; break;
|
|
||||||
case 0x04700018: * Value = RI_RERROR_REG; break;
|
|
||||||
case 0x0470001C: * Value = RI_WERROR_REG; break;
|
|
||||||
default:
|
|
||||||
* Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04800000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04800018: *Value = SI_STATUS_REG; break;
|
|
||||||
default:
|
|
||||||
*Value = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x05000000:
|
|
||||||
*Value = PAddr & 0xFFFF;
|
|
||||||
*Value = (*Value << 16) | *Value;
|
|
||||||
return 0;
|
|
||||||
case 0x08000000:
|
|
||||||
*Value = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*Value = PAddr & 0xFFFF;
|
|
||||||
*Value = (*Value << 16) | *Value;
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void r4300i_LW_PAddr ( usf_state_t * state, uint32_t PAddr, uint32_t * Value ) {
|
|
||||||
*Value = *(uint32_t *)(state->N64MEM+PAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t r4300i_LW_VAddr ( usf_state_t * state, uint32_t VAddr, uint32_t * Value ) {
|
|
||||||
uintptr_t address = state->TLB_Map[VAddr >> 12];
|
|
||||||
if (address == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
address += VAddr;
|
|
||||||
|
|
||||||
if((address - (uintptr_t)state->RDRAM) > state->RdramSize) {
|
|
||||||
address = address - (uintptr_t)state->RDRAM;
|
|
||||||
return r4300i_LW_NonMemory(state, (uint32_t) address, Value);
|
|
||||||
}
|
|
||||||
*Value = *(uint32_t *)address;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t r4300i_SB_NonMemory ( usf_state_t * state, uint32_t PAddr, uint8_t Value ) {
|
|
||||||
switch (PAddr & 0xFFF00000) {
|
|
||||||
case 0x00000000:
|
|
||||||
case 0x00100000:
|
|
||||||
case 0x00200000:
|
|
||||||
case 0x00300000:
|
|
||||||
case 0x00400000:
|
|
||||||
case 0x00500000:
|
|
||||||
case 0x00600000:
|
|
||||||
case 0x00700000:
|
|
||||||
if (PAddr < state->RdramSize) {
|
|
||||||
*(uint8_t *)(state->N64MEM+PAddr) = Value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t r4300i_SB_VAddr ( usf_state_t * state, uint32_t VAddr, uint8_t Value ) {
|
|
||||||
uintptr_t address;
|
|
||||||
address = state->TLB_Map[VAddr >> 12];
|
|
||||||
|
|
||||||
if (address == 0) { return 0; }
|
|
||||||
if (address + (VAddr ^ 3) - (uintptr_t)state->N64MEM < state->RdramSize)
|
|
||||||
*(uint8_t *)(address + (VAddr ^ 3)) = Value;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t r4300i_SH_NonMemory ( usf_state_t * state, uint32_t PAddr, uint16_t Value ) {
|
|
||||||
switch (PAddr & 0xFFF00000) {
|
|
||||||
case 0x00000000:
|
|
||||||
case 0x00100000:
|
|
||||||
case 0x00200000:
|
|
||||||
case 0x00300000:
|
|
||||||
case 0x00400000:
|
|
||||||
case 0x00500000:
|
|
||||||
case 0x00600000:
|
|
||||||
case 0x00700000:
|
|
||||||
if (PAddr < state->RdramSize) {
|
|
||||||
*(uint16_t *)(state->N64MEM+PAddr) = Value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t r4300i_SD_VAddr ( usf_state_t * state, uint32_t VAddr, uint64_t Value ) {
|
|
||||||
uintptr_t address;
|
|
||||||
address = state->TLB_Map[VAddr >> 12];
|
|
||||||
if (address == 0) { return 0; }
|
|
||||||
if (address + VAddr + 7 - (uintptr_t)state->N64MEM < state->RdramSize)
|
|
||||||
{
|
|
||||||
*(uint32_t *)(address + VAddr) = *((uint32_t *)(&Value) + 1);
|
|
||||||
*(uint32_t *)(address + VAddr + 4) = *((uint32_t *)(&Value));
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t r4300i_SH_VAddr ( usf_state_t * state, uint32_t VAddr, uint16_t Value ) {
|
|
||||||
uintptr_t address;
|
|
||||||
address = state->TLB_Map[VAddr >> 12];
|
|
||||||
|
|
||||||
if (address == 0) { return 0; }
|
|
||||||
if (address + 1 + (VAddr ^ 2) - (uintptr_t)state->N64MEM < state->RdramSize)
|
|
||||||
*(uint16_t *)(address + (VAddr ^ 2)) = Value;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t r4300i_SW_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t Value ) {
|
|
||||||
if (PAddr >= 0x10000000 && PAddr < 0x16000000) {
|
|
||||||
if ((PAddr - 0x10000000) < state->RomFileSize) {
|
|
||||||
state->WrittenToRom = 1;
|
|
||||||
state->WroteToRom = Value;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (PAddr & 0xFFF00000) {
|
|
||||||
case 0x00000000:
|
|
||||||
case 0x00100000:
|
|
||||||
case 0x00200000:
|
|
||||||
case 0x00300000:
|
|
||||||
case 0x00400000:
|
|
||||||
case 0x00500000:
|
|
||||||
case 0x00600000:
|
|
||||||
case 0x00700000:
|
|
||||||
if (PAddr < state->RdramSize) {
|
|
||||||
*(uint32_t *)(state->N64MEM+PAddr) = Value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x03F00000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x03F00000: RDRAM_CONFIG_REG = Value; break;
|
|
||||||
case 0x03F00004: RDRAM_DEVICE_ID_REG = Value; break;
|
|
||||||
case 0x03F00008: RDRAM_DELAY_REG = Value; break;
|
|
||||||
case 0x03F0000C: RDRAM_MODE_REG = Value; break;
|
|
||||||
case 0x03F00010: RDRAM_REF_INTERVAL_REG = Value; break;
|
|
||||||
case 0x03F00014: RDRAM_REF_ROW_REG = Value; break;
|
|
||||||
case 0x03F00018: RDRAM_RAS_INTERVAL_REG = Value; break;
|
|
||||||
case 0x03F0001C: RDRAM_MIN_INTERVAL_REG = Value; break;
|
|
||||||
case 0x03F00020: RDRAM_ADDR_SELECT_REG = Value; break;
|
|
||||||
case 0x03F00024: RDRAM_DEVICE_MANUF_REG = Value; break;
|
|
||||||
case 0x03F04004: break;
|
|
||||||
case 0x03F08004: break;
|
|
||||||
case 0x03F80004: break;
|
|
||||||
case 0x03F80008: break;
|
|
||||||
case 0x03F8000C: break;
|
|
||||||
case 0x03F80014: break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04000000:
|
|
||||||
if (PAddr < 0x04002000) {
|
|
||||||
*(uint32_t *)(state->N64MEM+PAddr) = Value;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04040000: SP_MEM_ADDR_REG = Value; break;
|
|
||||||
case 0x04040004: SP_DRAM_ADDR_REG = Value; break;
|
|
||||||
case 0x04040008:
|
|
||||||
SP_RD_LEN_REG = Value;
|
|
||||||
SP_DMA_READ(state);
|
|
||||||
break;
|
|
||||||
case 0x0404000C:
|
|
||||||
SP_WR_LEN_REG = Value;
|
|
||||||
SP_DMA_WRITE(state);
|
|
||||||
break;
|
|
||||||
case 0x04040010:
|
|
||||||
if ( ( Value & SP_CLR_HALT ) != 0) { SP_STATUS_REG &= ~SP_STATUS_HALT; }
|
|
||||||
if ( ( Value & SP_SET_HALT ) != 0) { SP_STATUS_REG |= SP_STATUS_HALT; }
|
|
||||||
if ( ( Value & SP_CLR_BROKE ) != 0) { SP_STATUS_REG &= ~SP_STATUS_BROKE; }
|
|
||||||
if ( ( Value & SP_CLR_INTR ) != 0) {
|
|
||||||
MI_INTR_REG &= ~MI_INTR_SP;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
}
|
|
||||||
if ( ( Value & SP_CLR_SSTEP ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SSTEP; }
|
|
||||||
if ( ( Value & SP_SET_SSTEP ) != 0) { SP_STATUS_REG |= SP_STATUS_SSTEP; }
|
|
||||||
if ( ( Value & SP_CLR_INTR_BREAK ) != 0) { SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; }
|
|
||||||
if ( ( Value & SP_SET_INTR_BREAK ) != 0) { SP_STATUS_REG |= SP_STATUS_INTR_BREAK; }
|
|
||||||
if ( ( Value & SP_CLR_SIG0 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG0; }
|
|
||||||
if ( ( Value & SP_SET_SIG0 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG0; }
|
|
||||||
if ( ( Value & SP_CLR_SIG1 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG1; }
|
|
||||||
if ( ( Value & SP_SET_SIG1 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG1; }
|
|
||||||
if ( ( Value & SP_CLR_SIG2 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG2; }
|
|
||||||
if ( ( Value & SP_SET_SIG2 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG2; }
|
|
||||||
if ( ( Value & SP_CLR_SIG3 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG3; }
|
|
||||||
if ( ( Value & SP_SET_SIG3 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG3; }
|
|
||||||
if ( ( Value & SP_CLR_SIG4 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG4; }
|
|
||||||
if ( ( Value & SP_SET_SIG4 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG4; }
|
|
||||||
if ( ( Value & SP_CLR_SIG5 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG5; }
|
|
||||||
if ( ( Value & SP_SET_SIG5 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG5; }
|
|
||||||
if ( ( Value & SP_CLR_SIG6 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG6; }
|
|
||||||
if ( ( Value & SP_SET_SIG6 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG6; }
|
|
||||||
if ( ( Value & SP_CLR_SIG7 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG7; }
|
|
||||||
if ( ( Value & SP_SET_SIG7 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG7; }
|
|
||||||
|
|
||||||
RunRsp(state);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 0x0404001C: SP_SEMAPHORE_REG = 0; break;
|
|
||||||
case 0x04080000: SP_PC_REG = Value & 0xFFC; break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04100000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04100000:
|
|
||||||
DPC_START_REG = Value;
|
|
||||||
DPC_CURRENT_REG = Value;
|
|
||||||
break;
|
|
||||||
case 0x04100004:
|
|
||||||
DPC_END_REG = Value;
|
|
||||||
break;
|
|
||||||
case 0x04100008: DPC_CURRENT_REG = Value; break;
|
|
||||||
case 0x0410000C:
|
|
||||||
if ( ( Value & DPC_CLR_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_XBUS_DMEM_DMA; }
|
|
||||||
if ( ( Value & DPC_SET_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG |= DPC_STATUS_XBUS_DMEM_DMA; }
|
|
||||||
if ( ( Value & DPC_CLR_FREEZE ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FREEZE; }
|
|
||||||
if ( ( Value & DPC_SET_FREEZE ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FREEZE; }
|
|
||||||
if ( ( Value & DPC_CLR_FLUSH ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FLUSH; }
|
|
||||||
if ( ( Value & DPC_SET_FLUSH ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FLUSH; }
|
|
||||||
if ( ( Value & DPC_CLR_FREEZE ) != 0)
|
|
||||||
{
|
|
||||||
if ( ( SP_STATUS_REG & SP_STATUS_HALT ) == 0)
|
|
||||||
{
|
|
||||||
if ( ( SP_STATUS_REG & SP_STATUS_BROKE ) == 0 )
|
|
||||||
{
|
|
||||||
RunRsp(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04300000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04300000:
|
|
||||||
MI_MODE_REG &= ~0x7F;
|
|
||||||
MI_MODE_REG |= (Value & 0x7F);
|
|
||||||
if ( ( Value & MI_CLR_INIT ) != 0 ) { MI_MODE_REG &= ~MI_MODE_INIT; }
|
|
||||||
if ( ( Value & MI_SET_INIT ) != 0 ) { MI_MODE_REG |= MI_MODE_INIT; }
|
|
||||||
if ( ( Value & MI_CLR_EBUS ) != 0 ) { MI_MODE_REG &= ~MI_MODE_EBUS; }
|
|
||||||
if ( ( Value & MI_SET_EBUS ) != 0 ) { MI_MODE_REG |= MI_MODE_EBUS; }
|
|
||||||
if ( ( Value & MI_CLR_DP_INTR ) != 0 ) {
|
|
||||||
MI_INTR_REG &= ~MI_INTR_DP;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
}
|
|
||||||
if ( ( Value & MI_CLR_RDRAM ) != 0 ) { MI_MODE_REG &= ~MI_MODE_RDRAM; }
|
|
||||||
if ( ( Value & MI_SET_RDRAM ) != 0 ) { MI_MODE_REG |= MI_MODE_RDRAM; }
|
|
||||||
break;
|
|
||||||
case 0x0430000C:
|
|
||||||
if ( ( Value & MI_INTR_MASK_CLR_SP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SP; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_SET_SP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SP; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_CLR_SI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SI; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_SET_SI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SI; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_CLR_AI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_AI; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_SET_AI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_AI; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_CLR_VI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_VI; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_SET_VI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_VI; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_CLR_PI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_PI; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_SET_PI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_PI; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_CLR_DP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_DP; }
|
|
||||||
if ( ( Value & MI_INTR_MASK_SET_DP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_DP; }
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04400000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04400000:
|
|
||||||
//if (VI_STATUS_REG != Value) {
|
|
||||||
VI_STATUS_REG = Value;
|
|
||||||
// if (ViStatusChanged != NULL ) { ViStatusChanged(); }
|
|
||||||
//}
|
|
||||||
break;
|
|
||||||
case 0x04400004:
|
|
||||||
|
|
||||||
VI_ORIGIN_REG = (Value & 0xFFFFFF);
|
|
||||||
//if (UpdateScreen != NULL ) { UpdateScreen(); }
|
|
||||||
break;
|
|
||||||
case 0x04400008:
|
|
||||||
//if (VI_WIDTH_REG != Value) {
|
|
||||||
VI_WIDTH_REG = Value;
|
|
||||||
// if (ViWidthChanged != NULL ) { ViWidthChanged(); }
|
|
||||||
//}
|
|
||||||
break;
|
|
||||||
case 0x0440000C: VI_INTR_REG = Value; break;
|
|
||||||
case 0x04400010:
|
|
||||||
MI_INTR_REG &= ~MI_INTR_VI;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
break;
|
|
||||||
case 0x04400014: VI_BURST_REG = Value; break;
|
|
||||||
case 0x04400018: VI_V_SYNC_REG = Value; break;
|
|
||||||
case 0x0440001C: VI_H_SYNC_REG = Value; break;
|
|
||||||
case 0x04400020: VI_LEAP_REG = Value; break;
|
|
||||||
case 0x04400024: VI_H_START_REG = Value; break;
|
|
||||||
case 0x04400028: VI_V_START_REG = Value; break;
|
|
||||||
case 0x0440002C: VI_V_BURST_REG = Value; break;
|
|
||||||
case 0x04400030: VI_X_SCALE_REG = Value; break;
|
|
||||||
case 0x04400034: VI_Y_SCALE_REG = Value; break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04500000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04500000: AI_DRAM_ADDR_REG = Value; break;
|
|
||||||
case 0x04500004:
|
|
||||||
AI_LEN_REG = Value;
|
|
||||||
AiLenChanged(state);
|
|
||||||
break;
|
|
||||||
case 0x04500008: AI_CONTROL_REG = (Value & 0x1); break;
|
|
||||||
case 0x0450000C:
|
|
||||||
/* Clear Interrupt */;
|
|
||||||
MI_INTR_REG &= ~MI_INTR_AI;
|
|
||||||
state->AudioIntrReg &= ~MI_INTR_AI;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
break;
|
|
||||||
case 0x04500010:
|
|
||||||
AI_DACRATE_REG = Value;
|
|
||||||
//if (AiDacrateChanged != NULL) { AiDacrateChanged(SYSTEM_NTSC); }
|
|
||||||
break;
|
|
||||||
case 0x04500014: AI_BITRATE_REG = Value; break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04600000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04600000: PI_DRAM_ADDR_REG = Value; break;
|
|
||||||
case 0x04600004: PI_CART_ADDR_REG = Value; break;
|
|
||||||
case 0x04600008:
|
|
||||||
PI_RD_LEN_REG = Value;
|
|
||||||
PI_DMA_READ(state);
|
|
||||||
break;
|
|
||||||
case 0x0460000C:
|
|
||||||
PI_WR_LEN_REG = Value;
|
|
||||||
PI_DMA_WRITE(state);
|
|
||||||
break;
|
|
||||||
case 0x04600010:
|
|
||||||
//if ((Value & PI_SET_RESET) != 0 ) { DisplayError(state, "reset Controller"); }
|
|
||||||
if ((Value & PI_CLR_INTR) != 0 ) {
|
|
||||||
MI_INTR_REG &= ~MI_INTR_PI;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04600014: PI_DOMAIN1_REG = (Value & 0xFF); break;
|
|
||||||
case 0x04600018: PI_BSD_DOM1_PWD_REG = (Value & 0xFF); break;
|
|
||||||
case 0x0460001C: PI_BSD_DOM1_PGS_REG = (Value & 0xFF); break;
|
|
||||||
case 0x04600020: PI_BSD_DOM1_RLS_REG = (Value & 0xFF); break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04700000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04700000: RI_MODE_REG = Value; break;
|
|
||||||
case 0x04700004: RI_CONFIG_REG = Value; break;
|
|
||||||
case 0x04700008: RI_CURRENT_LOAD_REG = Value; break;
|
|
||||||
case 0x0470000C: RI_SELECT_REG = Value; break;
|
|
||||||
case 0x04700010: RI_REFRESH_REG = Value; break;
|
|
||||||
case 0x04700014: RI_LATENCY_REG = Value; break;
|
|
||||||
case 0x04700018: RI_RERROR_REG = Value; break;
|
|
||||||
case 0x0470001C: RI_WERROR_REG = Value; break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x04800000:
|
|
||||||
switch (PAddr) {
|
|
||||||
case 0x04800000: SI_DRAM_ADDR_REG = Value; break;
|
|
||||||
case 0x04800004:
|
|
||||||
SI_PIF_ADDR_RD64B_REG = Value;
|
|
||||||
SI_DMA_READ (state);
|
|
||||||
break;
|
|
||||||
case 0x04800010:
|
|
||||||
SI_PIF_ADDR_WR64B_REG = Value;
|
|
||||||
SI_DMA_WRITE(state);
|
|
||||||
break;
|
|
||||||
case 0x04800018:
|
|
||||||
MI_INTR_REG &= ~MI_INTR_SI;
|
|
||||||
SI_STATUS_REG &= ~SI_STATUS_INTERRUPT;
|
|
||||||
CheckInterrupts(state);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 0x08000000:
|
|
||||||
if (PAddr != 0x08010000) { return 0; }
|
|
||||||
break;
|
|
||||||
case 0x1FC00000:
|
|
||||||
if (PAddr < 0x1FC007C0) {
|
|
||||||
return 0;
|
|
||||||
} else if (PAddr < 0x1FC00800) {
|
|
||||||
|
|
||||||
if (PAddr == 0x1FC007FC) {
|
|
||||||
PifRamWrite(state);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t r4300i_SW_VAddr ( usf_state_t * state, uint32_t VAddr, uint32_t Value ) {
|
|
||||||
|
|
||||||
uintptr_t address;
|
|
||||||
address = state->TLB_Map[VAddr >> 12];
|
|
||||||
|
|
||||||
if (address == 0) { return 0; }
|
|
||||||
address = (address + VAddr);
|
|
||||||
|
|
||||||
if((address - (uintptr_t)state->RDRAM) > state->RdramSize) {
|
|
||||||
address = address - (uintptr_t)state->RDRAM;
|
|
||||||
return r4300i_SW_NonMemory(state, (uint32_t) address, Value);
|
|
||||||
}
|
|
||||||
*(uint32_t *)address = Value;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void memcpyn642n64(usf_state_t * state, uint32_t dest, uint32_t src, uint32_t len)
|
|
||||||
{
|
|
||||||
uint32_t i;
|
|
||||||
uint32_t temp;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i += 4)
|
|
||||||
{
|
|
||||||
uintptr_t dstAddr = state->TLB_Map[(dest + i) >> 12];
|
|
||||||
uintptr_t srcAddr = state->TLB_Map[(src + i) >> 12];
|
|
||||||
|
|
||||||
if (srcAddr)
|
|
||||||
temp = *(uint32_t*)(srcAddr + src + i);
|
|
||||||
else
|
|
||||||
temp = 0;
|
|
||||||
|
|
||||||
if (dstAddr)
|
|
||||||
*(uint32_t*)(dstAddr + dest + i) = temp;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define LargeCompileBufferSize 0x03200000
|
|
||||||
#define NormalCompileBufferSize 0x01500000
|
|
||||||
|
|
||||||
#define RSP_RECOMPMEM_SIZE 0x400000
|
|
||||||
#define RSP_SECRECOMPMEM_SIZE 0x200000
|
|
||||||
|
|
||||||
#define ROM_IN_MAPSPACE
|
|
||||||
|
|
||||||
#define PageRAM2(x) (state->N64MEM+(uint32_t)(x))
|
|
||||||
#define PageVRAM(x) (state->TLB_Map[((uint32_t)(x))>>12]+(uint32_t)(x))
|
|
||||||
#define PageVRAM2(x) (uint32_t)(PageVRAM(x)-(uintptr_t)state->N64MEM)
|
|
||||||
|
|
||||||
/* Memory Control */
|
|
||||||
int Allocate_Memory ( void * );
|
|
||||||
void Release_Memory ( usf_state_t * );
|
|
||||||
int PreAllocate_Memory( usf_state_t * );
|
|
||||||
|
|
||||||
/* CPU memory functions */
|
|
||||||
//int r4300i_Command_MemoryFilter ( uint32_t dwExptCode, LPEXCEPTION_POINTERS lpEP );
|
|
||||||
//int r4300i_CPU_MemoryFilter ( uint32_t dwExptCode, LPEXCEPTION_POINTERS lpEP );
|
|
||||||
int32_t r4300i_LB_NonMemory ( usf_state_t *, uint32_t PAddr, uint32_t * Value, uint32_t SignExtend );
|
|
||||||
uint32_t r4300i_LB_VAddr ( usf_state_t *, uint32_t VAddr, uint8_t * Value );
|
|
||||||
uint32_t r4300i_LD_VAddr ( usf_state_t *, uint32_t VAddr, uint64_t * Value );
|
|
||||||
int32_t r4300i_LH_NonMemory ( usf_state_t *, uint32_t PAddr, uint32_t * Value, int32_t SignExtend );
|
|
||||||
uint32_t r4300i_LH_VAddr ( usf_state_t *, uint32_t VAddr, uint16_t * Value );
|
|
||||||
int32_t r4300i_LW_NonMemory ( usf_state_t *, uint32_t PAddr, uint32_t * Value );
|
|
||||||
void r4300i_LW_PAddr ( usf_state_t *, uint32_t PAddr, uint32_t * Value );
|
|
||||||
uint32_t r4300i_LW_VAddr ( usf_state_t *, uint32_t VAddr, uint32_t * Value );
|
|
||||||
int32_t r4300i_SB_NonMemory ( usf_state_t *, uint32_t PAddr, uint8_t Value );
|
|
||||||
uint32_t r4300i_SB_VAddr ( usf_state_t *, uint32_t VAddr, uint8_t Value );
|
|
||||||
uint32_t r4300i_SD_VAddr ( usf_state_t *, uint32_t VAddr, uint64_t Value );
|
|
||||||
int32_t r4300i_SH_NonMemory ( usf_state_t *, uint32_t PAddr, uint16_t Value );
|
|
||||||
uint32_t r4300i_SH_VAddr ( usf_state_t *, uint32_t VAddr, uint16_t Value );
|
|
||||||
int32_t r4300i_SW_NonMemory ( usf_state_t *, uint32_t PAddr, uint32_t Value );
|
|
||||||
uint32_t r4300i_SW_VAddr ( usf_state_t *, uint32_t VAddr, uint32_t Value );
|
|
||||||
|
|
||||||
uint8_t * PageROM(usf_state_t *, uint32_t addr);
|
|
||||||
|
|
||||||
void memcpyn642n64(usf_state_t *, uint32_t dest, uint32_t src, uint32_t len);
|
|
1257
Frameworks/lazyusf/lazyusf/memory/memory.c
Normal file
1257
Frameworks/lazyusf/lazyusf/memory/memory.c
Normal file
File diff suppressed because it is too large
Load diff
106
Frameworks/lazyusf/lazyusf/memory/memory.h
Normal file
106
Frameworks/lazyusf/lazyusf/memory/memory.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - memory.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_MEMORY_MEMORY_H
|
||||||
|
#define M64P_MEMORY_MEMORY_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define read_word_in_memory() state->readmem[state->address>>16](state)
|
||||||
|
#define read_byte_in_memory() state->readmemb[state->address>>16](state)
|
||||||
|
#define read_hword_in_memory() state->readmemh[state->address>>16](state)
|
||||||
|
#define read_dword_in_memory() state->readmemd[state->address>>16](state)
|
||||||
|
#define write_word_in_memory() state->writemem[state->address>>16](state)
|
||||||
|
#define write_byte_in_memory() state->writememb[state->address >>16](state)
|
||||||
|
#define write_hword_in_memory() state->writememh[state->address >>16](state)
|
||||||
|
#define write_dword_in_memory() state->writememd[state->address >>16](state)
|
||||||
|
|
||||||
|
#ifndef M64P_BIG_ENDIAN
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
|
||||||
|
#define sl(x) __builtin_bswap32(x)
|
||||||
|
#else
|
||||||
|
#define sl(mot) \
|
||||||
|
( \
|
||||||
|
((mot & 0x000000FF) << 24) | \
|
||||||
|
((mot & 0x0000FF00) << 8) | \
|
||||||
|
((mot & 0x00FF0000) >> 8) | \
|
||||||
|
((mot & 0xFF000000) >> 24) \
|
||||||
|
)
|
||||||
|
#endif
|
||||||
|
#define S8 3
|
||||||
|
#define S16 2
|
||||||
|
#define Sh16 1
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define sl(mot) mot
|
||||||
|
#define S8 0
|
||||||
|
#define S16 0
|
||||||
|
#define Sh16 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
static osal_inline void masked_write(uint32_t* dst, uint32_t value, uint32_t mask)
|
||||||
|
{
|
||||||
|
*dst = (*dst & ~mask) | (value & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
int init_memory(usf_state_t *, uint32_t rdram_size);
|
||||||
|
|
||||||
|
void map_region(usf_state_t *,
|
||||||
|
uint16_t region,
|
||||||
|
int type,
|
||||||
|
void (osal_fastcall *read8)(usf_state_t *),
|
||||||
|
void (osal_fastcall *read16)(usf_state_t *),
|
||||||
|
void (osal_fastcall *read32)(usf_state_t *),
|
||||||
|
void (osal_fastcall *read64)(usf_state_t *),
|
||||||
|
void (osal_fastcall *write8)(usf_state_t *),
|
||||||
|
void (osal_fastcall *write16)(usf_state_t *),
|
||||||
|
void (osal_fastcall *write32)(usf_state_t *),
|
||||||
|
void (osal_fastcall *write64)(usf_state_t *));
|
||||||
|
|
||||||
|
/* XXX: cannot make them static because of dynarec + rdp fb */
|
||||||
|
void osal_fastcall read_rdram(usf_state_t *);
|
||||||
|
void osal_fastcall read_rdramb(usf_state_t *);
|
||||||
|
void osal_fastcall read_rdramh(usf_state_t *);
|
||||||
|
void osal_fastcall read_rdramd(usf_state_t *);
|
||||||
|
void osal_fastcall write_rdram(usf_state_t *);
|
||||||
|
void osal_fastcall write_rdramb(usf_state_t *);
|
||||||
|
void osal_fastcall write_rdramh(usf_state_t *);
|
||||||
|
void osal_fastcall write_rdramd(usf_state_t *);
|
||||||
|
void osal_fastcall read_rdramFB(usf_state_t *);
|
||||||
|
void osal_fastcall read_rdramFBb(usf_state_t *);
|
||||||
|
void osal_fastcall read_rdramFBh(usf_state_t *);
|
||||||
|
void osal_fastcall read_rdramFBd(usf_state_t *);
|
||||||
|
void osal_fastcall write_rdramFB(usf_state_t *);
|
||||||
|
void osal_fastcall write_rdramFBb(usf_state_t *);
|
||||||
|
void osal_fastcall write_rdramFBh(usf_state_t *);
|
||||||
|
void osal_fastcall write_rdramFBd(usf_state_t *);
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
unsigned int * osal_fastcall fast_mem_access(usf_state_t *, unsigned int address);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,274 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef __OpCode
|
|
||||||
#define __OpCode
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
union {
|
|
||||||
|
|
||||||
uint32_t Hex;
|
|
||||||
uint8_t Ascii[4];
|
|
||||||
|
|
||||||
struct {
|
|
||||||
unsigned offset : 16;
|
|
||||||
unsigned rt : 5;
|
|
||||||
unsigned rs : 5;
|
|
||||||
unsigned op : 6;
|
|
||||||
} b;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
unsigned immediate : 16;
|
|
||||||
unsigned : 5;
|
|
||||||
unsigned base : 5;
|
|
||||||
unsigned : 6;
|
|
||||||
} c;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
unsigned target : 26;
|
|
||||||
unsigned : 6;
|
|
||||||
} d;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
unsigned funct : 6;
|
|
||||||
unsigned sa : 5;
|
|
||||||
unsigned rd : 5;
|
|
||||||
unsigned : 5;
|
|
||||||
unsigned : 5;
|
|
||||||
unsigned : 6;
|
|
||||||
} e;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
unsigned : 6;
|
|
||||||
unsigned fd : 5;
|
|
||||||
unsigned fs : 5;
|
|
||||||
unsigned ft : 5;
|
|
||||||
unsigned fmt : 5;
|
|
||||||
unsigned : 6;
|
|
||||||
} f;
|
|
||||||
} u;
|
|
||||||
|
|
||||||
} OPCODE;
|
|
||||||
|
|
||||||
//R4300i OpCodes
|
|
||||||
#define R4300i_SPECIAL 0
|
|
||||||
#define R4300i_REGIMM 1
|
|
||||||
#define R4300i_J 2
|
|
||||||
#define R4300i_JAL 3
|
|
||||||
#define R4300i_BEQ 4
|
|
||||||
#define R4300i_BNE 5
|
|
||||||
#define R4300i_BLEZ 6
|
|
||||||
#define R4300i_BGTZ 7
|
|
||||||
#define R4300i_ADDI 8
|
|
||||||
#define R4300i_ADDIU 9
|
|
||||||
#define R4300i_SLTI 10
|
|
||||||
#define R4300i_SLTIU 11
|
|
||||||
#define R4300i_ANDI 12
|
|
||||||
#define R4300i_ORI 13
|
|
||||||
#define R4300i_XORI 14
|
|
||||||
#define R4300i_LUI 15
|
|
||||||
#define R4300i_CP0 16
|
|
||||||
#define R4300i_CP1 17
|
|
||||||
#define R4300i_BEQL 20
|
|
||||||
#define R4300i_BNEL 21
|
|
||||||
#define R4300i_BLEZL 22
|
|
||||||
#define R4300i_BGTZL 23
|
|
||||||
#define R4300i_DADDI 24
|
|
||||||
#define R4300i_DADDIU 25
|
|
||||||
#define R4300i_LDL 26
|
|
||||||
#define R4300i_LDR 27
|
|
||||||
#define R4300i_LB 32
|
|
||||||
#define R4300i_LH 33
|
|
||||||
#define R4300i_LWL 34
|
|
||||||
#define R4300i_LW 35
|
|
||||||
#define R4300i_LBU 36
|
|
||||||
#define R4300i_LHU 37
|
|
||||||
#define R4300i_LWR 38
|
|
||||||
#define R4300i_LWU 39
|
|
||||||
#define R4300i_SB 40
|
|
||||||
#define R4300i_SH 41
|
|
||||||
#define R4300i_SWL 42
|
|
||||||
#define R4300i_SW 43
|
|
||||||
#define R4300i_SDL 44
|
|
||||||
#define R4300i_SDR 45
|
|
||||||
#define R4300i_SWR 46
|
|
||||||
#define R4300i_CACHE 47
|
|
||||||
#define R4300i_LL 48
|
|
||||||
#define R4300i_LWC1 49
|
|
||||||
#define R4300i_LWC2 0x32
|
|
||||||
#define R4300i_LLD 0x34
|
|
||||||
#define R4300i_LDC1 53
|
|
||||||
#define R4300i_LDC2 0x36
|
|
||||||
#define R4300i_LD 55
|
|
||||||
#define R4300i_SC 0x38
|
|
||||||
#define R4300i_SWC1 57
|
|
||||||
#define R4300i_SWC2 0x3A
|
|
||||||
#define R4300i_SCD 0x3C
|
|
||||||
#define R4300i_SDC1 61
|
|
||||||
#define R4300i_SDC2 62
|
|
||||||
#define R4300i_SD 63
|
|
||||||
|
|
||||||
/* R4300i Special opcodes */
|
|
||||||
#define R4300i_SPECIAL_SLL 0
|
|
||||||
#define R4300i_SPECIAL_SRL 2
|
|
||||||
#define R4300i_SPECIAL_SRA 3
|
|
||||||
#define R4300i_SPECIAL_SLLV 4
|
|
||||||
#define R4300i_SPECIAL_SRLV 6
|
|
||||||
#define R4300i_SPECIAL_SRAV 7
|
|
||||||
#define R4300i_SPECIAL_JR 8
|
|
||||||
#define R4300i_SPECIAL_JALR 9
|
|
||||||
#define R4300i_SPECIAL_SYSCALL 12
|
|
||||||
#define R4300i_SPECIAL_BREAK 13
|
|
||||||
#define R4300i_SPECIAL_SYNC 15
|
|
||||||
#define R4300i_SPECIAL_MFHI 16
|
|
||||||
#define R4300i_SPECIAL_MTHI 17
|
|
||||||
#define R4300i_SPECIAL_MFLO 18
|
|
||||||
#define R4300i_SPECIAL_MTLO 19
|
|
||||||
#define R4300i_SPECIAL_DSLLV 20
|
|
||||||
#define R4300i_SPECIAL_DSRLV 22
|
|
||||||
#define R4300i_SPECIAL_DSRAV 23
|
|
||||||
#define R4300i_SPECIAL_MULT 24
|
|
||||||
#define R4300i_SPECIAL_MULTU 25
|
|
||||||
#define R4300i_SPECIAL_DIV 26
|
|
||||||
#define R4300i_SPECIAL_DIVU 27
|
|
||||||
#define R4300i_SPECIAL_DMULT 28
|
|
||||||
#define R4300i_SPECIAL_DMULTU 29
|
|
||||||
#define R4300i_SPECIAL_DDIV 30
|
|
||||||
#define R4300i_SPECIAL_DDIVU 31
|
|
||||||
#define R4300i_SPECIAL_ADD 32
|
|
||||||
#define R4300i_SPECIAL_ADDU 33
|
|
||||||
#define R4300i_SPECIAL_SUB 34
|
|
||||||
#define R4300i_SPECIAL_SUBU 35
|
|
||||||
#define R4300i_SPECIAL_AND 36
|
|
||||||
#define R4300i_SPECIAL_OR 37
|
|
||||||
#define R4300i_SPECIAL_XOR 38
|
|
||||||
#define R4300i_SPECIAL_NOR 39
|
|
||||||
#define R4300i_SPECIAL_SLT 42
|
|
||||||
#define R4300i_SPECIAL_SLTU 43
|
|
||||||
#define R4300i_SPECIAL_DADD 44
|
|
||||||
#define R4300i_SPECIAL_DADDU 45
|
|
||||||
#define R4300i_SPECIAL_DSUB 46
|
|
||||||
#define R4300i_SPECIAL_DSUBU 47
|
|
||||||
#define R4300i_SPECIAL_TGE 48
|
|
||||||
#define R4300i_SPECIAL_TGEU 49
|
|
||||||
#define R4300i_SPECIAL_TLT 50
|
|
||||||
#define R4300i_SPECIAL_TLTU 51
|
|
||||||
#define R4300i_SPECIAL_TEQ 52
|
|
||||||
#define R4300i_SPECIAL_TNE 54
|
|
||||||
#define R4300i_SPECIAL_DSLL 56
|
|
||||||
#define R4300i_SPECIAL_DSRL 58
|
|
||||||
#define R4300i_SPECIAL_DSRA 59
|
|
||||||
#define R4300i_SPECIAL_DSLL32 60
|
|
||||||
#define R4300i_SPECIAL_DSRL32 62
|
|
||||||
#define R4300i_SPECIAL_DSRA32 63
|
|
||||||
|
|
||||||
/* R4300i RegImm opcodes */
|
|
||||||
#define R4300i_REGIMM_BLTZ 0
|
|
||||||
#define R4300i_REGIMM_BGEZ 1
|
|
||||||
#define R4300i_REGIMM_BLTZL 2
|
|
||||||
#define R4300i_REGIMM_BGEZL 3
|
|
||||||
#define R4300i_REGIMM_TGEI 0x08
|
|
||||||
#define R4300i_REGIMM_TGEIU 0x09
|
|
||||||
#define R4300i_REGIMM_TLTI 0x0A
|
|
||||||
#define R4300i_REGIMM_TLTIU 0x0B
|
|
||||||
#define R4300i_REGIMM_TEQI 0x0C
|
|
||||||
#define R4300i_REGIMM_TNEI 0x0E
|
|
||||||
#define R4300i_REGIMM_BLTZAL 0x10
|
|
||||||
#define R4300i_REGIMM_BGEZAL 17
|
|
||||||
#define R4300i_REGIMM_BLTZALL 0x12
|
|
||||||
#define R4300i_REGIMM_BGEZALL 0x13
|
|
||||||
|
|
||||||
/* R4300i COP0 opcodes */
|
|
||||||
#define R4300i_COP0_MF 0
|
|
||||||
#define R4300i_COP0_MT 4
|
|
||||||
|
|
||||||
/* R4300i COP0 CO opcodes */
|
|
||||||
#define R4300i_COP0_CO_TLBR 1
|
|
||||||
#define R4300i_COP0_CO_TLBWI 2
|
|
||||||
#define R4300i_COP0_CO_TLBWR 6
|
|
||||||
#define R4300i_COP0_CO_TLBP 8
|
|
||||||
#define R4300i_COP0_CO_ERET 24
|
|
||||||
|
|
||||||
/* R4300i COP1 opcodes */
|
|
||||||
#define R4300i_COP1_MF 0
|
|
||||||
#define R4300i_COP1_DMF 1
|
|
||||||
#define R4300i_COP1_CF 2
|
|
||||||
#define R4300i_COP1_MT 4
|
|
||||||
#define R4300i_COP1_DMT 5
|
|
||||||
#define R4300i_COP1_CT 6
|
|
||||||
#define R4300i_COP1_BC 8
|
|
||||||
#define R4300i_COP1_S 16
|
|
||||||
#define R4300i_COP1_D 17
|
|
||||||
#define R4300i_COP1_W 20
|
|
||||||
#define R4300i_COP1_L 21
|
|
||||||
|
|
||||||
/* R4300i COP1 BC opcodes */
|
|
||||||
#define R4300i_COP1_BC_BCF 0
|
|
||||||
#define R4300i_COP1_BC_BCT 1
|
|
||||||
#define R4300i_COP1_BC_BCFL 2
|
|
||||||
#define R4300i_COP1_BC_BCTL 3
|
|
||||||
|
|
||||||
#define R4300i_COP1_FUNCT_ADD 0
|
|
||||||
#define R4300i_COP1_FUNCT_SUB 1
|
|
||||||
#define R4300i_COP1_FUNCT_MUL 2
|
|
||||||
#define R4300i_COP1_FUNCT_DIV 3
|
|
||||||
#define R4300i_COP1_FUNCT_SQRT 4
|
|
||||||
#define R4300i_COP1_FUNCT_ABS 5
|
|
||||||
#define R4300i_COP1_FUNCT_MOV 6
|
|
||||||
#define R4300i_COP1_FUNCT_NEG 7
|
|
||||||
#define R4300i_COP1_FUNCT_ROUND_L 8
|
|
||||||
#define R4300i_COP1_FUNCT_TRUNC_L 9
|
|
||||||
#define R4300i_COP1_FUNCT_CEIL_L 10
|
|
||||||
#define R4300i_COP1_FUNCT_FLOOR_L 11
|
|
||||||
#define R4300i_COP1_FUNCT_ROUND_W 12
|
|
||||||
#define R4300i_COP1_FUNCT_TRUNC_W 13
|
|
||||||
#define R4300i_COP1_FUNCT_CEIL_W 14
|
|
||||||
#define R4300i_COP1_FUNCT_FLOOR_W 15
|
|
||||||
#define R4300i_COP1_FUNCT_CVT_S 32
|
|
||||||
#define R4300i_COP1_FUNCT_CVT_D 33
|
|
||||||
#define R4300i_COP1_FUNCT_CVT_W 36
|
|
||||||
#define R4300i_COP1_FUNCT_CVT_L 37
|
|
||||||
#define R4300i_COP1_FUNCT_C_F 48
|
|
||||||
#define R4300i_COP1_FUNCT_C_UN 49
|
|
||||||
#define R4300i_COP1_FUNCT_C_EQ 50
|
|
||||||
#define R4300i_COP1_FUNCT_C_UEQ 51
|
|
||||||
#define R4300i_COP1_FUNCT_C_OLT 52
|
|
||||||
#define R4300i_COP1_FUNCT_C_ULT 53
|
|
||||||
#define R4300i_COP1_FUNCT_C_OLE 54
|
|
||||||
#define R4300i_COP1_FUNCT_C_ULE 55
|
|
||||||
#define R4300i_COP1_FUNCT_C_SF 56
|
|
||||||
#define R4300i_COP1_FUNCT_C_NGLE 57
|
|
||||||
#define R4300i_COP1_FUNCT_C_SEQ 58
|
|
||||||
#define R4300i_COP1_FUNCT_C_NGL 59
|
|
||||||
#define R4300i_COP1_FUNCT_C_LT 60
|
|
||||||
#define R4300i_COP1_FUNCT_C_NGE 61
|
|
||||||
#define R4300i_COP1_FUNCT_C_LE 62
|
|
||||||
#define R4300i_COP1_FUNCT_C_NGT 63
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
|
@ -1,285 +0,0 @@
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "usf.h"
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
#include "os.h"
|
|
||||||
#include "cpu_hle.h"
|
|
||||||
|
|
||||||
#include "audio.h"
|
|
||||||
#include "interpreter_cpu.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define N64WORD(x) (*(uint32_t*)PageVRAM((x)))
|
|
||||||
#define N64HALF(x) (*(uint16_t*)PageVRAM((x)))
|
|
||||||
#define N64BYTE(x) (*(uint8_t*)PageVRAM((x^3)))
|
|
||||||
|
|
||||||
#define N64DWORD(addr) (((long long)N64WORD((addr))) << 32) + N64WORD((addr)+4);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int __osRestoreInt(usf_state_t * state, int n)
|
|
||||||
{
|
|
||||||
STATUS_REGISTER |= state->GPR[0x4].UW[0];
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __osDisableInt(usf_state_t * state, int n)
|
|
||||||
{
|
|
||||||
state->GPR[0x2].UW[0] = STATUS_REGISTER & 1;
|
|
||||||
STATUS_REGISTER &= 0xFFFFFFFE;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void osEnqueueThread(usf_state_t * state, uint32_t osThreadQueueAddr, uint32_t threadVAddr)
|
|
||||||
{
|
|
||||||
|
|
||||||
OSThread *thread = (OSThread*) PageVRAM(threadVAddr);
|
|
||||||
OSThread *oldThread = (OSThread*) PageVRAM(osThreadQueueAddr);
|
|
||||||
OSThread *curThread = (OSThread*) PageVRAM(oldThread->next);
|
|
||||||
|
|
||||||
while((int32_t)curThread->priority >= (int32_t)thread->priority) {
|
|
||||||
oldThread = curThread;
|
|
||||||
curThread = (OSThread*) PageVRAM(curThread->next);
|
|
||||||
}
|
|
||||||
|
|
||||||
thread->next = oldThread->next;
|
|
||||||
oldThread->next = threadVAddr;
|
|
||||||
thread->queue = osThreadQueueAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __osEnqueueThread(usf_state_t * state, int n) {
|
|
||||||
osEnqueueThread(state, state->GPR[4].UW[0],state->GPR[5].UW[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int osStartThread(usf_state_t * state, int n)
|
|
||||||
{
|
|
||||||
OSMesgQueue *osThreadQueue = NULL;
|
|
||||||
uint32_t osThreadQueueAddr = 0;
|
|
||||||
uint32_t oldStatus = STATUS_REGISTER & 1;
|
|
||||||
uint32_t osActiveThreadAddr = 0;
|
|
||||||
uint32_t osActiveThread = 0;
|
|
||||||
|
|
||||||
OSThread *thread = (OSThread*)PageVRAM(state->GPR[4].UW[0]);
|
|
||||||
|
|
||||||
STATUS_REGISTER &= 0xFFFFFFFE;
|
|
||||||
|
|
||||||
osThreadQueueAddr = ((*(uint32_t*)PageRAM2(n + 0x40)) & 0xFFFF) << 16;
|
|
||||||
osThreadQueueAddr += *(int16_t*)PageRAM2(n + 0x50);
|
|
||||||
|
|
||||||
osThreadQueue = (OSMesgQueue*) PageVRAM(osThreadQueueAddr);
|
|
||||||
|
|
||||||
if(thread->state != 8 ) {
|
|
||||||
DisplayError(state, "OMG, thread state is not OS_STATE_WAITING!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
thread->state = OS_STATE_RUNNABLE;
|
|
||||||
osEnqueueThread(state,osThreadQueueAddr,state->GPR[4].UW[0]);
|
|
||||||
|
|
||||||
osActiveThreadAddr = ((*(uint32_t*)PageRAM2(n + 0xDC)) & 0xFFFF) << 16;
|
|
||||||
osActiveThreadAddr += *(int16_t*)PageRAM2(n + 0xE0);
|
|
||||||
|
|
||||||
osActiveThread = *(uint32_t*)PageVRAM(osActiveThreadAddr);
|
|
||||||
|
|
||||||
if(osActiveThread==0) {
|
|
||||||
DisplayError(state,"OMG, active thread is NULL!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATUS_REGISTER |= oldStatus;
|
|
||||||
// CheckInterrupts();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int osRecvMesg(usf_state_t * state, int n)
|
|
||||||
{
|
|
||||||
//unsigned long devAddr = state->GPR[7].UW[0];
|
|
||||||
//unsigned long vAddr = state->GPR[0x11].UW[0];
|
|
||||||
//unsigned long nbytes = state->GPR[0x10].UW[0];
|
|
||||||
|
|
||||||
//unsigned long oldStatus = STATUS_REGISTER & 1;
|
|
||||||
|
|
||||||
RunFunction(state, n | (state->PROGRAM_COUNTER & 0xF0000000));
|
|
||||||
|
|
||||||
//DisplayError("%08x\n%08x\n%08x",devAddr, vAddr, nbytes);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// doesnt even use?
|
|
||||||
int osSetIntMask(usf_state_t * state, int paddr) {
|
|
||||||
#if 0
|
|
||||||
uint32_t globalIntMask = 0;
|
|
||||||
uint32_t mask = STATUS_REGISTER & 0xFF01;
|
|
||||||
uint32_t interrupts = 0;
|
|
||||||
uint32_t intAddress = 0, newMask = 0, workMask = 0;
|
|
||||||
|
|
||||||
uint32_t baseAddress = 0;
|
|
||||||
|
|
||||||
globalIntMask = ((*(uint16_t*)PageRAM2(paddr + 0x8)) & 0xFFFF) << 16;
|
|
||||||
globalIntMask += *(uint16_t*)PageRAM2(paddr + 0xc);
|
|
||||||
globalIntMask = *(uint32_t*)PageVRAM(globalIntMask);
|
|
||||||
|
|
||||||
interrupts = (globalIntMask ^ 0xffffffff) & 0xff00;
|
|
||||||
mask |= interrupts;
|
|
||||||
newMask = MI_INTR_MASK_REG;
|
|
||||||
|
|
||||||
if(!newMask)
|
|
||||||
newMask = ((globalIntMask >> 16) ^ 0xFFFFFFFF) & 0x3F;
|
|
||||||
|
|
||||||
mask |= (newMask << 16);
|
|
||||||
|
|
||||||
baseAddress = ((*(uint16_t*)PageRAM2(paddr + 0x5C)) & 0xFFFF) << 16;
|
|
||||||
baseAddress += *(int16_t*)PageRAM2(paddr + 0x64);
|
|
||||||
baseAddress += ((state->GPR[4].UW[0] & 0x3F0000) & globalIntMask) >> 15;;
|
|
||||||
|
|
||||||
MI_INTR_MASK_REG = *(uint16_t*)PageVRAM(baseAddress);
|
|
||||||
|
|
||||||
state->STATUS_REGISTER = ((state->GPR[4].UW[0] & 0xff01) & (globalIntMask & 0xff00)) | (STATUS_REGISTER & 0xFFFF00FF);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int osVirtualToPhysical(usf_state_t * state, int paddr) {
|
|
||||||
uintptr_t address = 0;
|
|
||||||
uintptr_t vaddr = state->GPR[4].UW[0];
|
|
||||||
|
|
||||||
address = (state->TLB_Map[vaddr >> 12] + vaddr) - (uintptr_t)state->N64MEM;
|
|
||||||
|
|
||||||
if(address < 0x800000) {
|
|
||||||
state->GPR[2].UW[0] = (uint32_t)address;
|
|
||||||
} else
|
|
||||||
state->GPR[2].UW[0] = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int osAiSetNextBuffer(usf_state_t * state, int paddr) {
|
|
||||||
uint32_t var = 0, var2 = 0;
|
|
||||||
var = ((*(int16_t*)PageRAM2(paddr + 0x4)) & 0xFFFF) << 16;
|
|
||||||
var += *(int16_t*)PageRAM2(paddr + 0x8);
|
|
||||||
|
|
||||||
var2 = N64WORD(var);
|
|
||||||
if(AI_CONTROL_REG & 0x80000000)
|
|
||||||
state->GPR[2].UW[0] = -1;
|
|
||||||
|
|
||||||
AI_DRAM_ADDR_REG = state->GPR[4].UW[0];
|
|
||||||
AI_LEN_REG = state->GPR[5].UW[0]&0x3FFF;
|
|
||||||
AiLenChanged(state);
|
|
||||||
state->GPR[2].UW[0] = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int saveThreadContext(usf_state_t * state, int paddr) {
|
|
||||||
#if 0
|
|
||||||
uint32_t OSThreadContextAddr = 0;
|
|
||||||
|
|
||||||
OSThreadContextAddr = ((*(int16_t*)PageRAM2(paddr)) & 0xFFFF) << 16;
|
|
||||||
OSThreadContextAddr += *(int16_t*)PageRAM2(paddr + 0x4);
|
|
||||||
|
|
||||||
OSThreadContextAddr = N64WORD(OSThreadContextAddr);
|
|
||||||
|
|
||||||
if((PageVRAM2(OSThreadContextAddr) & 0xffff) > 0xFF00) {
|
|
||||||
DisplayError(state,"OMG! Too high!");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int loadThreadContext(usf_state_t * state, int paddr) {
|
|
||||||
#if 0
|
|
||||||
uint32_t i = 0, OSThreadContextAddr = 0, T9 = 0, osOSThread = 0, Addr2 = 0, GlobalBitMask = 0, Tmp = 0;
|
|
||||||
uint32_t K0 = 0, K1 = 0, T0 = 0, R1 = 0, RCP = 0, intrList = 0;
|
|
||||||
OSThread t;
|
|
||||||
OSThreadContextAddr = ((*(int16_t*)PageRAM2(paddr)) & 0xFFFF) << 16;
|
|
||||||
OSThreadContextAddr += *(int16_t*)PageRAM2(paddr + 0x8);
|
|
||||||
|
|
||||||
Addr2 = ((*(int16_t*)PageRAM2(paddr + 0xC)) & 0xFFFF) << 16;
|
|
||||||
Addr2 += *(int16_t*)PageRAM2(paddr + 0x10);
|
|
||||||
|
|
||||||
GlobalBitMask = ((*(int16_t*)PageRAM2(paddr + 0x20)) & 0xFFFF) << 16;
|
|
||||||
GlobalBitMask += *(int16_t*)PageRAM2(paddr + 0x28);
|
|
||||||
GlobalBitMask = N64WORD(GlobalBitMask);
|
|
||||||
|
|
||||||
intrList = ((*(int16_t*)PageRAM2(paddr + 0x14C + 0x0)) & 0xFFFF) << 16;
|
|
||||||
intrList += *(int16_t*)PageRAM2(paddr + 0x150 + 0x0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if((PageVRAM2(OSThreadContextAddr) & 0xffff) > 0xFE80) {
|
|
||||||
DisplayError(state, "OMG this number is too high!!!!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
osOSThread = N64WORD(OSThreadContextAddr);
|
|
||||||
T9 = N64WORD(osOSThread);
|
|
||||||
|
|
||||||
N64WORD(OSThreadContextAddr) = T9;
|
|
||||||
N64WORD(Addr2) = osOSThread;
|
|
||||||
|
|
||||||
N64WORD(osOSThread + 0x10) = OS_STATE_RUNNING; //T0 is globalbitmask
|
|
||||||
|
|
||||||
K1 = N64WORD(osOSThread + 0x118); //osOSThread.context.k0
|
|
||||||
|
|
||||||
STATUS_REGISTER = (K1 & 0xFFFF00FF) | (GlobalBitMask & 0xFF00);
|
|
||||||
|
|
||||||
for(i = 1; i <= 0x19; i++) {
|
|
||||||
state->GPR[i].DW = N64DWORD(osOSThread + 0x18 + (i * 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0x1C; i <= 0x1F; i++) {
|
|
||||||
state->GPR[i].DW = N64DWORD(osOSThread + 0x8 + (i * 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
state->LO.DW = N64DWORD(osOSThread + 0x108);
|
|
||||||
state->HI.DW = N64DWORD(osOSThread + 0x110);
|
|
||||||
|
|
||||||
EPC_REGISTER = (uint32_t) N64WORD(osOSThread + 0x11C);
|
|
||||||
|
|
||||||
state->FPCR[31] = (uint32_t) N64WORD(osOSThread + 0x12C);
|
|
||||||
|
|
||||||
if(N64WORD(osOSThread + 0x18)) {
|
|
||||||
for(i = 0; i <= 30; i+=2) {
|
|
||||||
(*(uint64_t *)state->FPRDoubleLocation[i]) = N64DWORD(osOSThread + 0x130 + (i * 4));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
|
|
||||||
state->GPR[0x1A].UW[0] = (uint32_t) osOSThread;
|
|
||||||
|
|
||||||
RCP = N64WORD(osOSThread + 0x128);
|
|
||||||
|
|
||||||
K0 = (intrList + ((RCP & (GlobalBitMask >> 16)) << 1));
|
|
||||||
K1 = 0;
|
|
||||||
|
|
||||||
r4300i_LH_VAddr(state, K0, &K1);
|
|
||||||
|
|
||||||
// cheap hack?
|
|
||||||
//K1 = 0xAAA;
|
|
||||||
|
|
||||||
SW_Register(0x0430000C, K1);
|
|
||||||
|
|
||||||
NextInstruction = JUMP;
|
|
||||||
|
|
||||||
if ((STATUS_REGISTER & STATUS_ERL) != 0) {
|
|
||||||
JumpToLocation = ERROREPC_REGISTER;
|
|
||||||
STATUS_REGISTER &= ~STATUS_ERL;
|
|
||||||
} else {
|
|
||||||
JumpToLocation = EPC_REGISTER;
|
|
||||||
STATUS_REGISTER &= ~STATUS_EXL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLBit = 0;
|
|
||||||
CheckInterrupts();
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
#ifndef _CPU_HLE_OS_
|
|
||||||
#define _CPU_HLE_OS_
|
|
||||||
|
|
||||||
#include "cpu_hle.h"
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(1)
|
|
||||||
|
|
||||||
|
|
||||||
#define OS_STATE_STOPPED 1
|
|
||||||
#define OS_STATE_RUNNABLE 2
|
|
||||||
#define OS_STATE_RUNNING 4
|
|
||||||
#define OS_STATE_WAITING 8
|
|
||||||
|
|
||||||
typedef uint32_t OSPri;
|
|
||||||
typedef uint32_t OSId;
|
|
||||||
typedef
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
float f_odd;
|
|
||||||
float f_even;
|
|
||||||
} f;
|
|
||||||
double d;
|
|
||||||
}
|
|
||||||
__OSfp;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t at, v0, v1, a0, a1, a2, a3;
|
|
||||||
uint64_t t0, t1, t2, t3, t4, t5, t6, t7;
|
|
||||||
uint64_t s0, s1, s2, s3, s4, s5, s6, s7;
|
|
||||||
uint64_t t8, t9, gp, sp, s8, ra;
|
|
||||||
uint64_t lo, hi;
|
|
||||||
uint32_t sr, pc, cause, badvaddr, rcp;
|
|
||||||
uint32_t fpcsr;
|
|
||||||
__OSfp fp0, fp2, fp4, fp6, fp8, fp10, fp12, fp14;
|
|
||||||
__OSfp fp16, fp18, fp20, fp22, fp24, fp26, fp28, fp30;
|
|
||||||
} __OSThreadContext;
|
|
||||||
|
|
||||||
typedef struct OSThread_s
|
|
||||||
{
|
|
||||||
uint32_t next; // run/mesg queue link
|
|
||||||
OSPri priority; // run/mesg queue priority
|
|
||||||
uint32_t queue; // queue thread is on
|
|
||||||
uint32_t tlnext; // all threads queue link
|
|
||||||
#if 0
|
|
||||||
uint16_t state; // OS_STATE_*
|
|
||||||
uint16_t flags; // flags for rmon
|
|
||||||
#endif
|
|
||||||
//swap these because of byteswapping
|
|
||||||
uint16_t flags; // flags for rmon
|
|
||||||
uint16_t state; // OS_STATE_*
|
|
||||||
OSId id; // id for debugging
|
|
||||||
int fp; // thread has used fp unit
|
|
||||||
__OSThreadContext context; // register/interrupt mask
|
|
||||||
} OSThread;
|
|
||||||
|
|
||||||
typedef void * OSMesg;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Structure for message queue
|
|
||||||
//
|
|
||||||
typedef struct OSMesgQueue_s
|
|
||||||
{
|
|
||||||
OSThread *mtqueue; // Queue to store threads blocked
|
|
||||||
// on empty mailboxes (receive)
|
|
||||||
OSThread *fullqueue; // Queue to store threads blocked
|
|
||||||
// on full mailboxes (send)
|
|
||||||
int32_t validCount; // Contains number of valid message
|
|
||||||
int32_t first; // Points to first valid message
|
|
||||||
int32_t msgCount; // Contains total # of messages
|
|
||||||
OSMesg *msg; // Points to message buffer array
|
|
||||||
} OSMesgQueue;
|
|
||||||
|
|
||||||
|
|
||||||
int __osRestoreInt(usf_state_t *, int n);
|
|
||||||
int __osDisableInt(usf_state_t *, int n);
|
|
||||||
int __osEnqueueThread(usf_state_t *, int n) ;
|
|
||||||
|
|
||||||
int osStartThread(usf_state_t *, int n);
|
|
||||||
int osRecvMesg(usf_state_t *, int n);
|
|
||||||
int osSetIntMask(usf_state_t *, int paddr) ;
|
|
||||||
int osVirtualToPhysical(usf_state_t *, int paddr);
|
|
||||||
int osAiSetNextBuffer(usf_state_t *, int paddr);
|
|
||||||
|
|
||||||
int saveThreadContext(usf_state_t *, int paddr);
|
|
||||||
int loadThreadContext(usf_state_t *, int paddr);
|
|
||||||
#endif
|
|
|
@ -30,6 +30,7 @@
|
||||||
#define OSAL_BREAKPOINT_INTERRUPT __asm{ int 3 };
|
#define OSAL_BREAKPOINT_INTERRUPT __asm{ int 3 };
|
||||||
#define ALIGN(BYTES,DATA) __declspec(align(BYTES)) DATA
|
#define ALIGN(BYTES,DATA) __declspec(align(BYTES)) DATA
|
||||||
#define osal_inline __inline
|
#define osal_inline __inline
|
||||||
|
#define osal_fastcall __fastcall
|
||||||
|
|
||||||
/* string functions */
|
/* string functions */
|
||||||
#define osal_insensitive_strcmp(x, y) _stricmp(x, y)
|
#define osal_insensitive_strcmp(x, y) _stricmp(x, y)
|
||||||
|
@ -46,6 +47,11 @@
|
||||||
#define OSAL_BREAKPOINT_INTERRUPT __asm__(" int $3; ");
|
#define OSAL_BREAKPOINT_INTERRUPT __asm__(" int $3; ");
|
||||||
#define ALIGN(BYTES,DATA) DATA __attribute__((aligned(BYTES)))
|
#define ALIGN(BYTES,DATA) DATA __attribute__((aligned(BYTES)))
|
||||||
#define osal_inline inline
|
#define osal_inline inline
|
||||||
|
#ifdef __i386__
|
||||||
|
#define osal_fastcall __attribute__((fastcall))
|
||||||
|
#else
|
||||||
|
#define osal_fastcall
|
||||||
|
#endif
|
||||||
|
|
||||||
/* string functions */
|
/* string functions */
|
||||||
#define osal_insensitive_strcmp(x, y) strcasecmp(x, y)
|
#define osal_insensitive_strcmp(x, y) strcasecmp(x, y)
|
||||||
|
|
91
Frameworks/lazyusf/lazyusf/pi/cart_rom.c
Normal file
91
Frameworks/lazyusf/lazyusf/pi/cart_rom.c
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - cart_rom.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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 "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "usf/barray.h"
|
||||||
|
|
||||||
|
#include "cart_rom.h"
|
||||||
|
#include "pi_controller.h"
|
||||||
|
|
||||||
|
void connect_cart_rom(struct cart_rom* cart_rom,
|
||||||
|
uint8_t* rom, size_t rom_size)
|
||||||
|
{
|
||||||
|
cart_rom->rom = rom;
|
||||||
|
cart_rom->rom_size = rom_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_cart_rom(struct cart_rom* cart_rom)
|
||||||
|
{
|
||||||
|
cart_rom->last_write = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_cart_rom(void* opaque, uint32_t address, uint32_t* value)
|
||||||
|
{
|
||||||
|
struct pi_controller* pi = (struct pi_controller*)opaque;
|
||||||
|
uint32_t addr = rom_address(address);
|
||||||
|
|
||||||
|
if (pi->cart_rom.last_write != 0)
|
||||||
|
{
|
||||||
|
*value = pi->cart_rom.last_write;
|
||||||
|
pi->cart_rom.last_write = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*value = *(uint32_t*)(pi->cart_rom.rom + addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_cart_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
|
||||||
|
{
|
||||||
|
struct pi_controller* pi = (struct pi_controller*)opaque;
|
||||||
|
pi->cart_rom.last_write = value & mask;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_cart_rom_tracked(void* opaque, uint32_t address, uint32_t* value)
|
||||||
|
{
|
||||||
|
usf_state_t* state = (usf_state_t*)opaque;
|
||||||
|
struct pi_controller* pi = &state->g_pi;
|
||||||
|
uint32_t addr = rom_address(address);
|
||||||
|
|
||||||
|
if (pi->cart_rom.last_write != 0)
|
||||||
|
{
|
||||||
|
*value = pi->cart_rom.last_write;
|
||||||
|
pi->cart_rom.last_write = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bit_array_set(state->barray_rom, addr / 4);
|
||||||
|
|
||||||
|
*value = *(uint32_t*)(pi->cart_rom.rom + addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
53
Frameworks/lazyusf/lazyusf/pi/cart_rom.h
Normal file
53
Frameworks/lazyusf/lazyusf/pi/cart_rom.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - cart_rom.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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_PI_CART_ROM_H
|
||||||
|
#define M64P_PI_CART_ROM_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
struct cart_rom
|
||||||
|
{
|
||||||
|
uint8_t* rom;
|
||||||
|
size_t rom_size;
|
||||||
|
|
||||||
|
uint32_t last_write;
|
||||||
|
};
|
||||||
|
|
||||||
|
static osal_inline uint32_t rom_address(uint32_t address)
|
||||||
|
{
|
||||||
|
return (address & 0x03fffffc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect_cart_rom(struct cart_rom* cart_rom,
|
||||||
|
uint8_t* rom, size_t rom_size);
|
||||||
|
|
||||||
|
void init_cart_rom(struct cart_rom* cart_rom);
|
||||||
|
|
||||||
|
int read_cart_rom(void* opaque, uint32_t address, uint32_t* value);
|
||||||
|
int write_cart_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
|
||||||
|
|
||||||
|
int read_cart_rom_tracked(void* opaque, uint32_t address, uint32_t* value);
|
||||||
|
|
||||||
|
#endif
|
249
Frameworks/lazyusf/lazyusf/pi/pi_controller.c
Normal file
249
Frameworks/lazyusf/lazyusf/pi/pi_controller.c
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - pi_controller.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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 "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "usf/barray.h"
|
||||||
|
|
||||||
|
#include "pi_controller.h"
|
||||||
|
|
||||||
|
#define M64P_CORE_PROTOTYPES 1
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
#include "main/rom.h"
|
||||||
|
#include "memory/memory.h"
|
||||||
|
#include "r4300/cached_interp.h"
|
||||||
|
#include "r4300/cp0.h"
|
||||||
|
#include "r4300/interupt.h"
|
||||||
|
#include "r4300/new_dynarec/new_dynarec.h"
|
||||||
|
#include "r4300/ops.h"
|
||||||
|
#include "r4300/r4300.h"
|
||||||
|
#include "r4300/r4300_core.h"
|
||||||
|
#include "ri/rdram_detection_hack.h"
|
||||||
|
#include "ri/ri_controller.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void dma_pi_read(usf_state_t * state, struct pi_controller* pi)
|
||||||
|
{
|
||||||
|
if (pi->regs[PI_CART_ADDR_REG] >= 0x08000000 && pi->regs[PI_CART_ADDR_REG] < 0x08010000)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_WARNING, "Unknown dma read in dma_pi_read()");
|
||||||
|
}
|
||||||
|
|
||||||
|
pi->regs[PI_STATUS_REG] |= 1;
|
||||||
|
update_count(state);
|
||||||
|
add_interupt_event(state, PI_INT, state->g_delay_pi ? 0x1000/*pi->regs[PI_RD_LEN_REG]*/ : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dma_pi_write(usf_state_t * state, struct pi_controller* pi)
|
||||||
|
{
|
||||||
|
unsigned int longueur;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
fprintf(state->debug_log, "PI DMA WRITE: %08x to %08x for %08x bytes\n", pi->regs[PI_CART_ADDR_REG], pi->regs[PI_DRAM_ADDR_REG], pi->regs[PI_WR_LEN_REG] + 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (pi->regs[PI_CART_ADDR_REG] < 0x10000000)
|
||||||
|
{
|
||||||
|
if (pi->regs[PI_CART_ADDR_REG] >= 0x08000000 && pi->regs[PI_CART_ADDR_REG] < 0x08010000)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (pi->regs[PI_CART_ADDR_REG] >= 0x06000000 && pi->regs[PI_CART_ADDR_REG] < 0x08000000)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_WARNING, "Unknown dma write 0x%x in dma_pi_write()", (int)pi->regs[PI_CART_ADDR_REG]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pi->regs[PI_STATUS_REG] |= 1;
|
||||||
|
update_count(state);
|
||||||
|
add_interupt_event(state, PI_INT, state->g_delay_pi ? /*pi->regs[PI_WR_LEN_REG]*/0x1000 : 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pi->regs[PI_CART_ADDR_REG] >= 0x1fc00000) // for paper mario
|
||||||
|
{
|
||||||
|
pi->regs[PI_STATUS_REG] |= 1;
|
||||||
|
update_count(state);
|
||||||
|
add_interupt_event(state, PI_INT, state->g_delay_pi ? 0x1000 : 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
longueur = (pi->regs[PI_WR_LEN_REG] & 0xFFFFFF)+1;
|
||||||
|
i = (pi->regs[PI_CART_ADDR_REG]-0x10000000)&0x3FFFFFF;
|
||||||
|
longueur = (i + (int) longueur) > pi->cart_rom.rom_size ?
|
||||||
|
(pi->cart_rom.rom_size - i) : longueur;
|
||||||
|
longueur = (pi->regs[PI_DRAM_ADDR_REG] + longueur) > 0x7FFFFF ?
|
||||||
|
(0x7FFFFF - pi->regs[PI_DRAM_ADDR_REG]) : longueur;
|
||||||
|
|
||||||
|
if (i > pi->cart_rom.rom_size || pi->regs[PI_DRAM_ADDR_REG] > 0x7FFFFF)
|
||||||
|
{
|
||||||
|
pi->regs[PI_STATUS_REG] |= 3;
|
||||||
|
update_count(state);
|
||||||
|
add_interupt_event(state, PI_INT, state->g_delay_pi ? longueur/8 : 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
for (i=0; i<(int)longueur; i++)
|
||||||
|
{
|
||||||
|
unsigned long rdram_address1 = pi->regs[PI_DRAM_ADDR_REG]+i+0x80000000;
|
||||||
|
unsigned long rdram_address2 = pi->regs[PI_DRAM_ADDR_REG]+i+0xa0000000;
|
||||||
|
unsigned long rom_address = (((pi->regs[PI_CART_ADDR_REG]-0x10000000)&0x3FFFFFF)+i);
|
||||||
|
|
||||||
|
if (state->enable_trimming_mode)
|
||||||
|
bit_array_set(state->barray_rom, rom_address / 4);
|
||||||
|
|
||||||
|
((unsigned char*)pi->ri->rdram.dram)[(pi->regs[PI_DRAM_ADDR_REG]+i)^S8]=
|
||||||
|
pi->cart_rom.rom[rom_address^S8];
|
||||||
|
|
||||||
|
if (!state->invalid_code[rdram_address1>>12])
|
||||||
|
{
|
||||||
|
if (!state->blocks[rdram_address1>>12] ||
|
||||||
|
state->blocks[rdram_address1>>12]->block[(rdram_address1&0xFFF)/4].ops !=
|
||||||
|
state->current_instruction_table.NOTCOMPILED)
|
||||||
|
{
|
||||||
|
state->invalid_code[rdram_address1>>12] = 1;
|
||||||
|
}
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
invalidate_block(state, rdram_address1>>12);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (!state->invalid_code[rdram_address2>>12])
|
||||||
|
{
|
||||||
|
if (!state->blocks[rdram_address1>>12] ||
|
||||||
|
state->blocks[rdram_address2>>12]->block[(rdram_address2&0xFFF)/4].ops !=
|
||||||
|
state->current_instruction_table.NOTCOMPILED)
|
||||||
|
{
|
||||||
|
state->invalid_code[rdram_address2>>12] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i=0; i<(int)longueur; i++)
|
||||||
|
{
|
||||||
|
unsigned long rom_address = (((pi->regs[PI_CART_ADDR_REG]-0x10000000)&0x3FFFFFF)+i);
|
||||||
|
if (state->enable_trimming_mode)
|
||||||
|
bit_array_set(state->barray_rom, rom_address / 4);
|
||||||
|
((unsigned char*)pi->ri->rdram.dram)[(pi->regs[PI_DRAM_ADDR_REG]+i)^S8]=
|
||||||
|
pi->cart_rom.rom[rom_address^S8];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HACK: monitor PI DMA to trigger RDRAM size detection
|
||||||
|
* hack just before initial cart ROM loading. */
|
||||||
|
if (pi->regs[PI_CART_ADDR_REG] == 0x10001000)
|
||||||
|
{
|
||||||
|
force_detected_rdram_size_hack(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
pi->regs[PI_STATUS_REG] |= 3;
|
||||||
|
update_count(state);
|
||||||
|
add_interupt_event(state, PI_INT, state->g_delay_pi ? longueur/8 : 0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect_pi(struct pi_controller* pi,
|
||||||
|
struct r4300_core* r4300,
|
||||||
|
struct ri_controller* ri,
|
||||||
|
uint8_t* rom, size_t rom_size)
|
||||||
|
{
|
||||||
|
connect_cart_rom(&pi->cart_rom, rom, rom_size);
|
||||||
|
|
||||||
|
pi->r4300 = r4300;
|
||||||
|
pi->ri = ri;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_pi(struct pi_controller* pi)
|
||||||
|
{
|
||||||
|
memset(pi->regs, 0, PI_REGS_COUNT*sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_pi_regs(void* opaque, uint32_t address, uint32_t* value)
|
||||||
|
{
|
||||||
|
struct pi_controller* pi = (struct pi_controller*)opaque;
|
||||||
|
uint32_t reg = pi_reg(address);
|
||||||
|
|
||||||
|
*value = pi->regs[reg];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_pi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
|
||||||
|
{
|
||||||
|
struct pi_controller* pi = (struct pi_controller*)opaque;
|
||||||
|
uint32_t reg = pi_reg(address);
|
||||||
|
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case PI_RD_LEN_REG:
|
||||||
|
masked_write(&pi->regs[PI_RD_LEN_REG], value, mask);
|
||||||
|
dma_pi_read(pi->r4300->state, pi);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case PI_WR_LEN_REG:
|
||||||
|
masked_write(&pi->regs[PI_WR_LEN_REG], value, mask);
|
||||||
|
dma_pi_write(pi->r4300->state, pi);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case PI_STATUS_REG:
|
||||||
|
if (value & mask & 2)
|
||||||
|
clear_rcp_interrupt(pi->r4300, MI_INTR_PI);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case PI_BSD_DOM1_LAT_REG:
|
||||||
|
case PI_BSD_DOM1_PWD_REG:
|
||||||
|
case PI_BSD_DOM1_PGS_REG:
|
||||||
|
case PI_BSD_DOM1_RLS_REG:
|
||||||
|
case PI_BSD_DOM2_LAT_REG:
|
||||||
|
case PI_BSD_DOM2_PWD_REG:
|
||||||
|
case PI_BSD_DOM2_PGS_REG:
|
||||||
|
case PI_BSD_DOM2_RLS_REG:
|
||||||
|
masked_write(&pi->regs[reg], value & 0xff, mask);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
masked_write(&pi->regs[reg], value, mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pi_end_of_dma_event(struct pi_controller* pi)
|
||||||
|
{
|
||||||
|
pi->regs[PI_STATUS_REG] &= ~3;
|
||||||
|
raise_rcp_interrupt(pi->r4300, MI_INTR_PI);
|
||||||
|
}
|
81
Frameworks/lazyusf/lazyusf/pi/pi_controller.h
Normal file
81
Frameworks/lazyusf/lazyusf/pi/pi_controller.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - pi_controller.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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_PI_PI_CONTROLLER_H
|
||||||
|
#define M64P_PI_PI_CONTROLLER_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "cart_rom.h"
|
||||||
|
|
||||||
|
struct r4300_core;
|
||||||
|
struct ri_controller;
|
||||||
|
|
||||||
|
enum pi_registers
|
||||||
|
{
|
||||||
|
PI_DRAM_ADDR_REG,
|
||||||
|
PI_CART_ADDR_REG,
|
||||||
|
PI_RD_LEN_REG,
|
||||||
|
PI_WR_LEN_REG,
|
||||||
|
PI_STATUS_REG,
|
||||||
|
PI_BSD_DOM1_LAT_REG,
|
||||||
|
PI_BSD_DOM1_PWD_REG,
|
||||||
|
PI_BSD_DOM1_PGS_REG,
|
||||||
|
PI_BSD_DOM1_RLS_REG,
|
||||||
|
PI_BSD_DOM2_LAT_REG,
|
||||||
|
PI_BSD_DOM2_PWD_REG,
|
||||||
|
PI_BSD_DOM2_PGS_REG,
|
||||||
|
PI_BSD_DOM2_RLS_REG,
|
||||||
|
PI_REGS_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pi_controller
|
||||||
|
{
|
||||||
|
uint32_t regs[PI_REGS_COUNT];
|
||||||
|
|
||||||
|
struct cart_rom cart_rom;
|
||||||
|
|
||||||
|
struct r4300_core* r4300;
|
||||||
|
struct ri_controller* ri;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
static osal_inline uint32_t pi_reg(uint32_t address)
|
||||||
|
{
|
||||||
|
return (address & 0xffff) >> 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void connect_pi(struct pi_controller* pi,
|
||||||
|
struct r4300_core* r4300,
|
||||||
|
struct ri_controller* ri,
|
||||||
|
uint8_t* rom, size_t rom_size);
|
||||||
|
|
||||||
|
void init_pi(struct pi_controller* pi);
|
||||||
|
|
||||||
|
int read_pi_regs(void* opaque, uint32_t address, uint32_t* value);
|
||||||
|
int write_pi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
|
||||||
|
|
||||||
|
void pi_end_of_dma_event(struct pi_controller* pi);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,99 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include "usf.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
|
|
||||||
#include "usf_internal.h"
|
|
||||||
|
|
||||||
// Skeletal support so USFs that read the controller won't fail (bad practice, though)
|
|
||||||
|
|
||||||
void ProcessControllerCommand ( usf_state_t * state, int32_t Control, uint8_t * Command);
|
|
||||||
|
|
||||||
void PifRamRead (usf_state_t * state) {
|
|
||||||
int32_t Channel, CurPos;
|
|
||||||
|
|
||||||
Channel = 0;
|
|
||||||
CurPos = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
switch(state->PIF_Ram[CurPos]) {
|
|
||||||
case 0x00:
|
|
||||||
Channel += 1;
|
|
||||||
if (Channel > 6) { CurPos = 0x40; }
|
|
||||||
break;
|
|
||||||
case 0xFE: CurPos = 0x40; break;
|
|
||||||
case 0xFF: break;
|
|
||||||
case 0xB4: case 0x56: case 0xB8: break; /* ??? */
|
|
||||||
default:
|
|
||||||
if ((state->PIF_Ram[CurPos] & 0xC0) == 0) {
|
|
||||||
CurPos += state->PIF_Ram[CurPos] + (state->PIF_Ram[CurPos + 1] & 0x3F) + 1;
|
|
||||||
Channel += 1;
|
|
||||||
} else {
|
|
||||||
CurPos = 0x40;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CurPos += 1;
|
|
||||||
} while( CurPos < 0x40 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void PifRamWrite (usf_state_t * state) {
|
|
||||||
int Channel, CurPos;
|
|
||||||
|
|
||||||
Channel = 0;
|
|
||||||
|
|
||||||
for (CurPos = 0; CurPos < 0x40; CurPos++){
|
|
||||||
switch(state->PIF_Ram[CurPos]) {
|
|
||||||
case 0x00:
|
|
||||||
Channel += 1;
|
|
||||||
if (Channel > 6) { CurPos = 0x40; }
|
|
||||||
break;
|
|
||||||
case 0xFE: CurPos = 0x40; break;
|
|
||||||
case 0xFF: break;
|
|
||||||
case 0xB4: case 0x56: case 0xB8: break; /* ??? */
|
|
||||||
default:
|
|
||||||
if ((state->PIF_Ram[CurPos] & 0xC0) == 0) {
|
|
||||||
if (Channel < 4) {
|
|
||||||
ProcessControllerCommand(state,Channel,&state->PIF_Ram[CurPos]);
|
|
||||||
}
|
|
||||||
CurPos += state->PIF_Ram[CurPos] + (state->PIF_Ram[CurPos + 1] & 0x3F) + 1;
|
|
||||||
Channel += 1;
|
|
||||||
} else
|
|
||||||
CurPos = 0x40;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state->PIF_Ram[0x3F] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// always return failure
|
|
||||||
void ProcessControllerCommand ( usf_state_t * state, int32_t Control, uint8_t * Command) {
|
|
||||||
(void)state;
|
|
||||||
(void)Control;
|
|
||||||
Command[1] |= 0x80;
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* Project 64 - A Nintendo 64 emulator.
|
|
||||||
*
|
|
||||||
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
||||||
* Jabo (jabo@emulation64.com).
|
|
||||||
*
|
|
||||||
* pj64 homepage: www.pj64.net
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
||||||
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
||||||
* providing that this license information and copyright notice appear with
|
|
||||||
* all copies and any derived work.
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express or implied
|
|
||||||
* warranty. In no event shall the authors be held liable for any damages
|
|
||||||
* arising from the use of this software.
|
|
||||||
*
|
|
||||||
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
||||||
* seek permission of the copyright holders first. Commercial use includes
|
|
||||||
* charging money for Project64 or software derived from Project64.
|
|
||||||
*
|
|
||||||
* The copyright holders request that bug fixes and improvements to the code
|
|
||||||
* should be forwarded to them so if they want them.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
extern uint8_t *PIF_Ram;
|
|
||||||
|
|
||||||
void PifRamWrite ( usf_state_t * );
|
|
||||||
void PifRamRead ( usf_state_t * );
|
|
567
Frameworks/lazyusf/lazyusf/r4300/cached_interp.c
Normal file
567
Frameworks/lazyusf/lazyusf/r4300/cached_interp.c
Normal file
|
@ -0,0 +1,567 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - cached_interp.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 "cached_interp.h"
|
||||||
|
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
#include "main/main.h"
|
||||||
|
#include "memory/memory.h"
|
||||||
|
|
||||||
|
#include "r4300.h"
|
||||||
|
#include "cp0.h"
|
||||||
|
#include "cp1.h"
|
||||||
|
#include "ops.h"
|
||||||
|
#include "exception.h"
|
||||||
|
#include "interupt.h"
|
||||||
|
#include "macros.h"
|
||||||
|
#include "recomp.h"
|
||||||
|
#include "tlb.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// Cached interpreter functions (and fallback for dynarec).
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
#define UPDATE_DEBUGGER() do { } while(0)
|
||||||
|
|
||||||
|
#define PCADDR state->PC->addr
|
||||||
|
#define ADD_TO_PC(x) state->PC += x;
|
||||||
|
#define DECLARE_INSTRUCTION(name) static void osal_fastcall name(usf_state_t * state)
|
||||||
|
|
||||||
|
#define DECLARE_JUMP(name, destination, condition, link, likely, cop1) \
|
||||||
|
static void osal_fastcall name(usf_state_t * state) \
|
||||||
|
{ \
|
||||||
|
const int take_jump = (condition); \
|
||||||
|
const unsigned int jump_target = (destination); \
|
||||||
|
long long int *link_register = (link); \
|
||||||
|
if (cop1 && check_cop1_unusable(state)) return; \
|
||||||
|
if (link_register != &state->reg[0]) \
|
||||||
|
{ \
|
||||||
|
*link_register=state->PC->addr + 8; \
|
||||||
|
sign_extended(*link_register); \
|
||||||
|
} \
|
||||||
|
if (!likely || take_jump) \
|
||||||
|
{ \
|
||||||
|
state->PC++; \
|
||||||
|
state->delay_slot=1; \
|
||||||
|
UPDATE_DEBUGGER(); \
|
||||||
|
state->PC->ops(state); \
|
||||||
|
update_count(state); \
|
||||||
|
state->delay_slot=0; \
|
||||||
|
if (take_jump && !state->skip_jump) \
|
||||||
|
{ \
|
||||||
|
state->PC=state->actual->block+((jump_target-state->actual->start)>>2); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
state->PC += 2; \
|
||||||
|
update_count(state); \
|
||||||
|
} \
|
||||||
|
state->last_addr = state->PC->addr; \
|
||||||
|
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state); \
|
||||||
|
} \
|
||||||
|
static void osal_fastcall name##_OUT(usf_state_t * state) \
|
||||||
|
{ \
|
||||||
|
const int take_jump = (condition); \
|
||||||
|
const unsigned int jump_target = (destination); \
|
||||||
|
long long int *link_register = (link); \
|
||||||
|
if (cop1 && check_cop1_unusable(state)) return; \
|
||||||
|
if (link_register != &state->reg[0]) \
|
||||||
|
{ \
|
||||||
|
*link_register=state->PC->addr + 8; \
|
||||||
|
sign_extended(*link_register); \
|
||||||
|
} \
|
||||||
|
if (!likely || take_jump) \
|
||||||
|
{ \
|
||||||
|
state->PC++; \
|
||||||
|
state->delay_slot=1; \
|
||||||
|
UPDATE_DEBUGGER(); \
|
||||||
|
state->PC->ops(state); \
|
||||||
|
update_count(state); \
|
||||||
|
state->delay_slot=0; \
|
||||||
|
if (take_jump && !state->skip_jump) \
|
||||||
|
{ \
|
||||||
|
jump_to(jump_target); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
state->PC += 2; \
|
||||||
|
update_count(state); \
|
||||||
|
} \
|
||||||
|
state->last_addr = state->PC->addr; \
|
||||||
|
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state); \
|
||||||
|
} \
|
||||||
|
static void osal_fastcall name##_IDLE(usf_state_t * state) \
|
||||||
|
{ \
|
||||||
|
const int take_jump = (condition); \
|
||||||
|
int skip; \
|
||||||
|
if (cop1 && check_cop1_unusable(state)) return; \
|
||||||
|
if (take_jump) \
|
||||||
|
{ \
|
||||||
|
update_count(state); \
|
||||||
|
skip = state->next_interupt - state->g_cp0_regs[CP0_COUNT_REG]; \
|
||||||
|
if (skip > 3) state->g_cp0_regs[CP0_COUNT_REG] += (skip & 0xFFFFFFFC); \
|
||||||
|
else name(state); \
|
||||||
|
} \
|
||||||
|
else name(state); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_MEMORY() \
|
||||||
|
if (!state->invalid_code[state->address>>12]) \
|
||||||
|
if (state->blocks[state->address>>12]->block[(state->address&0xFFF)/4].ops != \
|
||||||
|
state->current_instruction_table.NOTCOMPILED) \
|
||||||
|
state->invalid_code[state->address>>12] = 1;
|
||||||
|
|
||||||
|
// two functions are defined from the macros above but never used
|
||||||
|
// these prototype declarations will prevent a warning
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
static void osal_fastcall JR_IDLE(usf_state_t *) __attribute__((used));
|
||||||
|
static void osal_fastcall JALR_IDLE(usf_state_t *) __attribute__((used));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "interpreter.def"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// Flow control 'fake' instructions
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
static void osal_fastcall FIN_BLOCK(usf_state_t * state)
|
||||||
|
{
|
||||||
|
if (!state->delay_slot)
|
||||||
|
{
|
||||||
|
jump_to((state->PC-1)->addr+4);
|
||||||
|
/*#ifdef DBG
|
||||||
|
if (g_DebuggerActive) update_debugger(PC->addr);
|
||||||
|
#endif
|
||||||
|
Used by dynarec only, check should be unnecessary
|
||||||
|
*/
|
||||||
|
state->PC->ops(state);
|
||||||
|
if (state->r4300emu == CORE_DYNAREC) dyna_jump(state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
precomp_block *blk = state->actual;
|
||||||
|
precomp_instr *inst = state->PC;
|
||||||
|
jump_to((state->PC-1)->addr+4);
|
||||||
|
|
||||||
|
/*#ifdef DBG
|
||||||
|
if (g_DebuggerActive) update_debugger(PC->addr);
|
||||||
|
#endif
|
||||||
|
Used by dynarec only, check should be unnecessary
|
||||||
|
*/
|
||||||
|
if (!state->skip_jump)
|
||||||
|
{
|
||||||
|
state->PC->ops(state);
|
||||||
|
state->actual = blk;
|
||||||
|
state->PC = inst+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
state->PC->ops(state);
|
||||||
|
|
||||||
|
if (state->r4300emu == CORE_DYNAREC) dyna_jump(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void osal_fastcall NOTCOMPILED(usf_state_t * state)
|
||||||
|
{
|
||||||
|
unsigned int *mem = fast_mem_access(state, state->blocks[state->PC->addr>>12]->start);
|
||||||
|
|
||||||
|
if (mem != NULL)
|
||||||
|
recompile_block(state, (int *)mem, state->blocks[state->PC->addr >> 12], state->PC->addr);
|
||||||
|
else
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "not compiled exception");
|
||||||
|
|
||||||
|
/*#ifdef DBG
|
||||||
|
if (g_DebuggerActive) update_debugger(PC->addr);
|
||||||
|
#endif
|
||||||
|
The preceeding update_debugger SHOULD be unnecessary since it should have been
|
||||||
|
called before NOTCOMPILED would have been executed
|
||||||
|
*/
|
||||||
|
state->PC->ops(state);
|
||||||
|
if (state->r4300emu == CORE_DYNAREC)
|
||||||
|
dyna_jump(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void osal_fastcall NOTCOMPILED2(usf_state_t * state)
|
||||||
|
{
|
||||||
|
NOTCOMPILED(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// Cached interpreter instruction table
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
const cpu_instruction_table cached_interpreter_table = {
|
||||||
|
LB,
|
||||||
|
LBU,
|
||||||
|
LH,
|
||||||
|
LHU,
|
||||||
|
LW,
|
||||||
|
LWL,
|
||||||
|
LWR,
|
||||||
|
SB,
|
||||||
|
SH,
|
||||||
|
SW,
|
||||||
|
SWL,
|
||||||
|
SWR,
|
||||||
|
|
||||||
|
LD,
|
||||||
|
LDL,
|
||||||
|
LDR,
|
||||||
|
LL,
|
||||||
|
LWU,
|
||||||
|
SC,
|
||||||
|
SD,
|
||||||
|
SDL,
|
||||||
|
SDR,
|
||||||
|
SYNC,
|
||||||
|
|
||||||
|
ADDI,
|
||||||
|
ADDIU,
|
||||||
|
SLTI,
|
||||||
|
SLTIU,
|
||||||
|
ANDI,
|
||||||
|
ORI,
|
||||||
|
XORI,
|
||||||
|
LUI,
|
||||||
|
|
||||||
|
DADDI,
|
||||||
|
DADDIU,
|
||||||
|
|
||||||
|
ADD,
|
||||||
|
ADDU,
|
||||||
|
SUB,
|
||||||
|
SUBU,
|
||||||
|
SLT,
|
||||||
|
SLTU,
|
||||||
|
AND,
|
||||||
|
OR,
|
||||||
|
XOR,
|
||||||
|
NOR,
|
||||||
|
|
||||||
|
DADD,
|
||||||
|
DADDU,
|
||||||
|
DSUB,
|
||||||
|
DSUBU,
|
||||||
|
|
||||||
|
MULT,
|
||||||
|
MULTU,
|
||||||
|
DIV,
|
||||||
|
DIVU,
|
||||||
|
MFHI,
|
||||||
|
MTHI,
|
||||||
|
MFLO,
|
||||||
|
MTLO,
|
||||||
|
|
||||||
|
DMULT,
|
||||||
|
DMULTU,
|
||||||
|
DDIV,
|
||||||
|
DDIVU,
|
||||||
|
|
||||||
|
J,
|
||||||
|
J_OUT,
|
||||||
|
J_IDLE,
|
||||||
|
JAL,
|
||||||
|
JAL_OUT,
|
||||||
|
JAL_IDLE,
|
||||||
|
// Use the _OUT versions of JR and JALR, since we don't know
|
||||||
|
// until runtime if they're going to jump inside or outside the block
|
||||||
|
JR_OUT,
|
||||||
|
JALR_OUT,
|
||||||
|
BEQ,
|
||||||
|
BEQ_OUT,
|
||||||
|
BEQ_IDLE,
|
||||||
|
BNE,
|
||||||
|
BNE_OUT,
|
||||||
|
BNE_IDLE,
|
||||||
|
BLEZ,
|
||||||
|
BLEZ_OUT,
|
||||||
|
BLEZ_IDLE,
|
||||||
|
BGTZ,
|
||||||
|
BGTZ_OUT,
|
||||||
|
BGTZ_IDLE,
|
||||||
|
BLTZ,
|
||||||
|
BLTZ_OUT,
|
||||||
|
BLTZ_IDLE,
|
||||||
|
BGEZ,
|
||||||
|
BGEZ_OUT,
|
||||||
|
BGEZ_IDLE,
|
||||||
|
BLTZAL,
|
||||||
|
BLTZAL_OUT,
|
||||||
|
BLTZAL_IDLE,
|
||||||
|
BGEZAL,
|
||||||
|
BGEZAL_OUT,
|
||||||
|
BGEZAL_IDLE,
|
||||||
|
|
||||||
|
BEQL,
|
||||||
|
BEQL_OUT,
|
||||||
|
BEQL_IDLE,
|
||||||
|
BNEL,
|
||||||
|
BNEL_OUT,
|
||||||
|
BNEL_IDLE,
|
||||||
|
BLEZL,
|
||||||
|
BLEZL_OUT,
|
||||||
|
BLEZL_IDLE,
|
||||||
|
BGTZL,
|
||||||
|
BGTZL_OUT,
|
||||||
|
BGTZL_IDLE,
|
||||||
|
BLTZL,
|
||||||
|
BLTZL_OUT,
|
||||||
|
BLTZL_IDLE,
|
||||||
|
BGEZL,
|
||||||
|
BGEZL_OUT,
|
||||||
|
BGEZL_IDLE,
|
||||||
|
BLTZALL,
|
||||||
|
BLTZALL_OUT,
|
||||||
|
BLTZALL_IDLE,
|
||||||
|
BGEZALL,
|
||||||
|
BGEZALL_OUT,
|
||||||
|
BGEZALL_IDLE,
|
||||||
|
BC1TL,
|
||||||
|
BC1TL_OUT,
|
||||||
|
BC1TL_IDLE,
|
||||||
|
BC1FL,
|
||||||
|
BC1FL_OUT,
|
||||||
|
BC1FL_IDLE,
|
||||||
|
|
||||||
|
SLL,
|
||||||
|
SRL,
|
||||||
|
SRA,
|
||||||
|
SLLV,
|
||||||
|
SRLV,
|
||||||
|
SRAV,
|
||||||
|
|
||||||
|
DSLL,
|
||||||
|
DSRL,
|
||||||
|
DSRA,
|
||||||
|
DSLLV,
|
||||||
|
DSRLV,
|
||||||
|
DSRAV,
|
||||||
|
DSLL32,
|
||||||
|
DSRL32,
|
||||||
|
DSRA32,
|
||||||
|
|
||||||
|
MTC0,
|
||||||
|
MFC0,
|
||||||
|
|
||||||
|
TLBR,
|
||||||
|
TLBWI,
|
||||||
|
TLBWR,
|
||||||
|
TLBP,
|
||||||
|
CACHE,
|
||||||
|
ERET,
|
||||||
|
|
||||||
|
LWC1,
|
||||||
|
SWC1,
|
||||||
|
MTC1,
|
||||||
|
MFC1,
|
||||||
|
CTC1,
|
||||||
|
CFC1,
|
||||||
|
BC1T,
|
||||||
|
BC1T_OUT,
|
||||||
|
BC1T_IDLE,
|
||||||
|
BC1F,
|
||||||
|
BC1F_OUT,
|
||||||
|
BC1F_IDLE,
|
||||||
|
|
||||||
|
DMFC1,
|
||||||
|
DMTC1,
|
||||||
|
LDC1,
|
||||||
|
SDC1,
|
||||||
|
|
||||||
|
CVT_S_D,
|
||||||
|
CVT_S_W,
|
||||||
|
CVT_S_L,
|
||||||
|
CVT_D_S,
|
||||||
|
CVT_D_W,
|
||||||
|
CVT_D_L,
|
||||||
|
CVT_W_S,
|
||||||
|
CVT_W_D,
|
||||||
|
CVT_L_S,
|
||||||
|
CVT_L_D,
|
||||||
|
|
||||||
|
ROUND_W_S,
|
||||||
|
ROUND_W_D,
|
||||||
|
ROUND_L_S,
|
||||||
|
ROUND_L_D,
|
||||||
|
|
||||||
|
TRUNC_W_S,
|
||||||
|
TRUNC_W_D,
|
||||||
|
TRUNC_L_S,
|
||||||
|
TRUNC_L_D,
|
||||||
|
|
||||||
|
CEIL_W_S,
|
||||||
|
CEIL_W_D,
|
||||||
|
CEIL_L_S,
|
||||||
|
CEIL_L_D,
|
||||||
|
|
||||||
|
FLOOR_W_S,
|
||||||
|
FLOOR_W_D,
|
||||||
|
FLOOR_L_S,
|
||||||
|
FLOOR_L_D,
|
||||||
|
|
||||||
|
ADD_S,
|
||||||
|
ADD_D,
|
||||||
|
|
||||||
|
SUB_S,
|
||||||
|
SUB_D,
|
||||||
|
|
||||||
|
MUL_S,
|
||||||
|
MUL_D,
|
||||||
|
|
||||||
|
DIV_S,
|
||||||
|
DIV_D,
|
||||||
|
|
||||||
|
ABS_S,
|
||||||
|
ABS_D,
|
||||||
|
|
||||||
|
MOV_S,
|
||||||
|
MOV_D,
|
||||||
|
|
||||||
|
NEG_S,
|
||||||
|
NEG_D,
|
||||||
|
|
||||||
|
SQRT_S,
|
||||||
|
SQRT_D,
|
||||||
|
|
||||||
|
C_F_S,
|
||||||
|
C_F_D,
|
||||||
|
C_UN_S,
|
||||||
|
C_UN_D,
|
||||||
|
C_EQ_S,
|
||||||
|
C_EQ_D,
|
||||||
|
C_UEQ_S,
|
||||||
|
C_UEQ_D,
|
||||||
|
C_OLT_S,
|
||||||
|
C_OLT_D,
|
||||||
|
C_ULT_S,
|
||||||
|
C_ULT_D,
|
||||||
|
C_OLE_S,
|
||||||
|
C_OLE_D,
|
||||||
|
C_ULE_S,
|
||||||
|
C_ULE_D,
|
||||||
|
C_SF_S,
|
||||||
|
C_SF_D,
|
||||||
|
C_NGLE_S,
|
||||||
|
C_NGLE_D,
|
||||||
|
C_SEQ_S,
|
||||||
|
C_SEQ_D,
|
||||||
|
C_NGL_S,
|
||||||
|
C_NGL_D,
|
||||||
|
C_LT_S,
|
||||||
|
C_LT_D,
|
||||||
|
C_NGE_S,
|
||||||
|
C_NGE_D,
|
||||||
|
C_LE_S,
|
||||||
|
C_LE_D,
|
||||||
|
C_NGT_S,
|
||||||
|
C_NGT_D,
|
||||||
|
|
||||||
|
SYSCALL,
|
||||||
|
BREAK,
|
||||||
|
|
||||||
|
TEQ,
|
||||||
|
|
||||||
|
NOP,
|
||||||
|
RESERVED,
|
||||||
|
NI,
|
||||||
|
|
||||||
|
FIN_BLOCK,
|
||||||
|
NOTCOMPILED,
|
||||||
|
NOTCOMPILED2
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int osal_fastcall update_invalid_addr(usf_state_t * state, unsigned int addr)
|
||||||
|
{
|
||||||
|
if (addr >= 0x80000000 && addr < 0xc0000000)
|
||||||
|
{
|
||||||
|
if (state->invalid_code[addr>>12]) state->invalid_code[(addr^0x20000000)>>12] = 1;
|
||||||
|
if (state->invalid_code[(addr^0x20000000)>>12]) state->invalid_code[addr>>12] = 1;
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int paddr = virtual_to_physical_address(state, addr, 2);
|
||||||
|
if (paddr)
|
||||||
|
{
|
||||||
|
unsigned int beg_paddr = paddr - (addr - (addr&~0xFFF));
|
||||||
|
update_invalid_addr(state, paddr);
|
||||||
|
if (state->invalid_code[(beg_paddr+0x000)>>12]) state->invalid_code[addr>>12] = 1;
|
||||||
|
if (state->invalid_code[(beg_paddr+0xFFC)>>12]) state->invalid_code[addr>>12] = 1;
|
||||||
|
if (state->invalid_code[addr>>12]) state->invalid_code[(beg_paddr+0x000)>>12] = 1;
|
||||||
|
if (state->invalid_code[addr>>12]) state->invalid_code[(beg_paddr+0xFFC)>>12] = 1;
|
||||||
|
}
|
||||||
|
return paddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define addr state->jump_to_address
|
||||||
|
void osal_fastcall jump_to_func(usf_state_t * state)
|
||||||
|
{
|
||||||
|
unsigned int paddr;
|
||||||
|
if (state->skip_jump) return;
|
||||||
|
paddr = update_invalid_addr(state, addr);
|
||||||
|
if (!paddr) return;
|
||||||
|
state->actual = state->blocks[addr>>12];
|
||||||
|
if (state->invalid_code[addr>>12])
|
||||||
|
{
|
||||||
|
if (!state->blocks[addr>>12])
|
||||||
|
{
|
||||||
|
state->blocks[addr>>12] = (precomp_block *) malloc(sizeof(precomp_block));
|
||||||
|
state->actual = state->blocks[addr>>12];
|
||||||
|
state->blocks[addr>>12]->code = NULL;
|
||||||
|
state->blocks[addr>>12]->block = NULL;
|
||||||
|
state->blocks[addr>>12]->jumps_table = NULL;
|
||||||
|
state->blocks[addr>>12]->riprel_table = NULL;
|
||||||
|
}
|
||||||
|
state->blocks[addr>>12]->start = addr & ~0xFFF;
|
||||||
|
state->blocks[addr>>12]->end = (addr & ~0xFFF) + 0x1000;
|
||||||
|
init_block(state, state->blocks[addr>>12]);
|
||||||
|
}
|
||||||
|
state->PC=state->actual->block+((addr-state->actual->start)>>2);
|
||||||
|
|
||||||
|
if (state->r4300emu == CORE_DYNAREC) dyna_jump(state);
|
||||||
|
}
|
||||||
|
#undef addr
|
||||||
|
|
||||||
|
void osal_fastcall init_blocks(usf_state_t * state)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; i<0x100000; i++)
|
||||||
|
{
|
||||||
|
state->invalid_code[i] = 1;
|
||||||
|
state->blocks[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void osal_fastcall free_blocks(usf_state_t * state)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; i<0x100000; i++)
|
||||||
|
{
|
||||||
|
if (state->blocks[i])
|
||||||
|
{
|
||||||
|
free_block(state, state->blocks[i]);
|
||||||
|
free(state->blocks[i]);
|
||||||
|
state->blocks[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
44
Frameworks/lazyusf/lazyusf/r4300/cached_interp.h
Normal file
44
Frameworks/lazyusf/lazyusf/r4300/cached_interp.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - cached_interp.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_CACHED_INTERP_H
|
||||||
|
#define M64P_R4300_CACHED_INTERP_H
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
#include "ops.h"
|
||||||
|
/* FIXME: use forward declaration for precomp_block */
|
||||||
|
#include "recomp.h"
|
||||||
|
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
extern const cpu_instruction_table cached_interpreter_table;
|
||||||
|
|
||||||
|
void osal_fastcall init_blocks(usf_state_t *);
|
||||||
|
void osal_fastcall free_blocks(usf_state_t *);
|
||||||
|
void osal_fastcall jump_to_func(usf_state_t *);
|
||||||
|
|
||||||
|
/* Jumps to the given address. This is for the cached interpreter / dynarec. */
|
||||||
|
#define jump_to(a) { state->jump_to_address = a; jump_to_func(state); }
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_CACHED_INTERP_H */
|
70
Frameworks/lazyusf/lazyusf/r4300/cp0.c
Normal file
70
Frameworks/lazyusf/lazyusf/r4300/cp0.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - cp0.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "r4300.h"
|
||||||
|
#include "cp0.h"
|
||||||
|
#include "exception.h"
|
||||||
|
|
||||||
|
#include "new_dynarec/new_dynarec.h"
|
||||||
|
|
||||||
|
#ifdef COMPARE_CORE
|
||||||
|
#include "api/debugger.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
#include "debugger/dbg_types.h"
|
||||||
|
#include "debugger/debugger.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* global functions */
|
||||||
|
int osal_fastcall check_cop1_unusable(usf_state_t * state)
|
||||||
|
{
|
||||||
|
if (!(state->g_cp0_regs[CP0_STATUS_REG] & 0x20000000))
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] = (11 << 2) | 0x10000000;
|
||||||
|
exception_general(state);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_count(usf_state_t * state)
|
||||||
|
{
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
if (r4300emu != CORE_DYNAREC)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
state->g_cp0_regs[CP0_COUNT_REG] += ((state->PC->addr - state->last_addr) >> 2) * state->count_per_op;
|
||||||
|
state->last_addr = state->PC->addr;
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*#ifdef DBG
|
||||||
|
if (g_DebuggerActive && !delay_slot) update_debugger(PC->addr);
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
61
Frameworks/lazyusf/lazyusf/r4300/cp0.h
Normal file
61
Frameworks/lazyusf/lazyusf/r4300/cp0.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - cp0.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_CP0_H
|
||||||
|
#define M64P_R4300_CP0_H
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CP0_INDEX_REG,
|
||||||
|
CP0_RANDOM_REG,
|
||||||
|
CP0_ENTRYLO0_REG,
|
||||||
|
CP0_ENTRYLO1_REG,
|
||||||
|
CP0_CONTEXT_REG,
|
||||||
|
CP0_PAGEMASK_REG,
|
||||||
|
CP0_WIRED_REG,
|
||||||
|
/* 7 is unused */
|
||||||
|
CP0_BADVADDR_REG = 8,
|
||||||
|
CP0_COUNT_REG,
|
||||||
|
CP0_ENTRYHI_REG,
|
||||||
|
CP0_COMPARE_REG,
|
||||||
|
CP0_STATUS_REG,
|
||||||
|
CP0_CAUSE_REG,
|
||||||
|
CP0_EPC_REG,
|
||||||
|
CP0_PREVID_REG,
|
||||||
|
CP0_CONFIG_REG,
|
||||||
|
CP0_LLADDR_REG,
|
||||||
|
CP0_WATCHLO_REG,
|
||||||
|
CP0_WATCHHI_REG,
|
||||||
|
CP0_XCONTEXT_REG,
|
||||||
|
/* 21 - 27 are unused */
|
||||||
|
CP0_TAGLO_REG = 28,
|
||||||
|
CP0_TAGHI_REG,
|
||||||
|
CP0_ERROREPC_REG,
|
||||||
|
/* 31 is unused */
|
||||||
|
CP0_REGS_COUNT = 32
|
||||||
|
};
|
||||||
|
|
||||||
|
int osal_fastcall check_cop1_unusable(usf_state_t *);
|
||||||
|
void update_count(usf_state_t *);
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_CP0_H */
|
||||||
|
|
110
Frameworks/lazyusf/lazyusf/r4300/cp1.c
Normal file
110
Frameworks/lazyusf/lazyusf/r4300/cp1.c
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - cp1.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 "usf/usf.h"
|
||||||
|
|
||||||
|
#include "new_dynarec/new_dynarec.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
/* Refer to Figure 6-2 on page 155 and explanation on page B-11
|
||||||
|
of MIPS R4000 Microprocessor User's Manual (Second Edition)
|
||||||
|
by Joe Heinrich.
|
||||||
|
*/
|
||||||
|
void shuffle_fpr_data(usf_state_t * state, int oldStatus, int newStatus)
|
||||||
|
{
|
||||||
|
#if defined(M64P_BIG_ENDIAN)
|
||||||
|
const int isBigEndian = 1;
|
||||||
|
#else
|
||||||
|
const int isBigEndian = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((newStatus & 0x04000000) != (oldStatus & 0x04000000))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int temp_fgr_32[32];
|
||||||
|
|
||||||
|
// pack or unpack the FGR register data
|
||||||
|
if (newStatus & 0x04000000)
|
||||||
|
{ // switching into 64-bit mode
|
||||||
|
// retrieve 32 FPR values from packed 32-bit FGR registers
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
temp_fgr_32[i] = *((int *) &state->reg_cop1_fgr_64[i>>1] + ((i & 1) ^ isBigEndian));
|
||||||
|
}
|
||||||
|
// unpack them into 32 64-bit registers, taking the high 32-bits from their temporary place in the upper 16 FGRs
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
int high32 = *((int *) &state->reg_cop1_fgr_64[(i>>1)+16] + (i & 1));
|
||||||
|
*((int *) &state->reg_cop1_fgr_64[i] + isBigEndian) = temp_fgr_32[i];
|
||||||
|
*((int *) &state->reg_cop1_fgr_64[i] + (isBigEndian^1)) = high32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // switching into 32-bit mode
|
||||||
|
// retrieve the high 32 bits from each 64-bit FGR register and store in temp array
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
temp_fgr_32[i] = *((int *) &state->reg_cop1_fgr_64[i] + (isBigEndian^1));
|
||||||
|
}
|
||||||
|
// take the low 32 bits from each register and pack them together into 64-bit pairs
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
unsigned int least32 = *((unsigned int *) &state->reg_cop1_fgr_64[i*2] + isBigEndian);
|
||||||
|
unsigned int most32 = *((unsigned int *) &state->reg_cop1_fgr_64[i*2+1] + isBigEndian);
|
||||||
|
state->reg_cop1_fgr_64[i] = ((unsigned long long) most32 << 32) | (unsigned long long) least32;
|
||||||
|
}
|
||||||
|
// store the high bits in the upper 16 FGRs, which wont be accessible in 32-bit mode
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
*((int *) &state->reg_cop1_fgr_64[(i>>1)+16] + (i & 1)) = temp_fgr_32[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_fpr_pointers(usf_state_t * state, int newStatus)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
#if defined(M64P_BIG_ENDIAN)
|
||||||
|
const int isBigEndian = 1;
|
||||||
|
#else
|
||||||
|
const int isBigEndian = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// update the FPR register pointers
|
||||||
|
if (newStatus & 0x04000000)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
state->reg_cop1_double[i] = (double*) &state->reg_cop1_fgr_64[i];
|
||||||
|
state->reg_cop1_simple[i] = ((float*) &state->reg_cop1_fgr_64[i]) + isBigEndian;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
state->reg_cop1_double[i] = (double*) &state->reg_cop1_fgr_64[i>>1];
|
||||||
|
state->reg_cop1_simple[i] = ((float*) &state->reg_cop1_fgr_64[i>>1]) + ((i & 1) ^ isBigEndian);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
Frameworks/lazyusf/lazyusf/r4300/cp1.h
Normal file
31
Frameworks/lazyusf/lazyusf/r4300/cp1.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - cp1.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_CP1_H
|
||||||
|
#define M64P_R4300_CP1_H
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
void shuffle_fpr_data(usf_state_t *, int oldStatus, int newStatus);
|
||||||
|
void set_fpr_pointers(usf_state_t *, int newStatus);
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_CP1_H */
|
||||||
|
|
1052
Frameworks/lazyusf/lazyusf/r4300/empty_dynarec.c
Normal file
1052
Frameworks/lazyusf/lazyusf/r4300/empty_dynarec.c
Normal file
File diff suppressed because it is too large
Load diff
149
Frameworks/lazyusf/lazyusf/r4300/exception.c
Normal file
149
Frameworks/lazyusf/lazyusf/r4300/exception.c
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - exception.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
#include "memory/memory.h"
|
||||||
|
|
||||||
|
#include "exception.h"
|
||||||
|
#include "r4300.h"
|
||||||
|
#include "cp0.h"
|
||||||
|
#include "recomph.h"
|
||||||
|
#include "tlb.h"
|
||||||
|
|
||||||
|
void TLB_refill_exception(usf_state_t * state, unsigned int address, int w)
|
||||||
|
{
|
||||||
|
int usual_handler = 0, i;
|
||||||
|
|
||||||
|
if (state->r4300emu != CORE_DYNAREC && w != 2) update_count(state);
|
||||||
|
if (w == 1) state->g_cp0_regs[CP0_CAUSE_REG] = (3 << 2);
|
||||||
|
else state->g_cp0_regs[CP0_CAUSE_REG] = (2 << 2);
|
||||||
|
state->g_cp0_regs[CP0_BADVADDR_REG] = address;
|
||||||
|
state->g_cp0_regs[CP0_CONTEXT_REG] = (state->g_cp0_regs[CP0_CONTEXT_REG] & 0xFF80000F) | ((address >> 9) & 0x007FFFF0);
|
||||||
|
state->g_cp0_regs[CP0_ENTRYHI_REG] = address & 0xFFFFE000;
|
||||||
|
if (state->g_cp0_regs[CP0_STATUS_REG] & 0x2) // Test de EXL
|
||||||
|
{
|
||||||
|
generic_jump_to(state, 0x80000180);
|
||||||
|
if(state->delay_slot==1 || state->delay_slot==3) state->g_cp0_regs[CP0_CAUSE_REG] |= 0x80000000;
|
||||||
|
else state->g_cp0_regs[CP0_CAUSE_REG] &= 0x7FFFFFFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
if (w!=2)
|
||||||
|
state->g_cp0_regs[CP0_EPC_REG] = state->PC->addr;
|
||||||
|
else
|
||||||
|
state->g_cp0_regs[CP0_EPC_REG] = address;
|
||||||
|
}
|
||||||
|
else state->g_cp0_regs[CP0_EPC_REG] = state->PC->addr;
|
||||||
|
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] &= ~0x80000000;
|
||||||
|
state->g_cp0_regs[CP0_STATUS_REG] |= 0x2; //EXL=1
|
||||||
|
|
||||||
|
if (address >= 0x80000000 && address < 0xc0000000)
|
||||||
|
usual_handler = 1;
|
||||||
|
for (i=0; i<32; i++)
|
||||||
|
{
|
||||||
|
if (/*state->tlb_e[i].v_even &&*/ address >= state->tlb_e[i].start_even &&
|
||||||
|
address <= state->tlb_e[i].end_even)
|
||||||
|
usual_handler = 1;
|
||||||
|
if (/*state->tlb_e[i].v_odd &&*/ address >= state->tlb_e[i].start_odd &&
|
||||||
|
address <= state->tlb_e[i].end_odd)
|
||||||
|
usual_handler = 1;
|
||||||
|
}
|
||||||
|
if (usual_handler)
|
||||||
|
{
|
||||||
|
generic_jump_to(state, 0x80000180);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
generic_jump_to(state, 0x80000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(state->delay_slot==1 || state->delay_slot==3)
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] |= 0x80000000;
|
||||||
|
state->g_cp0_regs[CP0_EPC_REG]-=4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] &= 0x7FFFFFFF;
|
||||||
|
}
|
||||||
|
if(w != 2) state->g_cp0_regs[CP0_EPC_REG]-=4;
|
||||||
|
|
||||||
|
state->last_addr = state->PC->addr;
|
||||||
|
|
||||||
|
if (state->r4300emu == CORE_DYNAREC)
|
||||||
|
{
|
||||||
|
dyna_jump(state);
|
||||||
|
if (!state->dyna_interp) state->delay_slot = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->r4300emu != CORE_DYNAREC || state->dyna_interp)
|
||||||
|
{
|
||||||
|
state->dyna_interp = 0;
|
||||||
|
if (state->delay_slot)
|
||||||
|
{
|
||||||
|
state->skip_jump = state->PC->addr;
|
||||||
|
state->next_interupt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void osal_fastcall exception_general(usf_state_t * state)
|
||||||
|
{
|
||||||
|
update_count(state);
|
||||||
|
state->g_cp0_regs[CP0_STATUS_REG] |= 2;
|
||||||
|
|
||||||
|
state->g_cp0_regs[CP0_EPC_REG] = state->PC->addr;
|
||||||
|
|
||||||
|
if(state->delay_slot==1 || state->delay_slot==3)
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] |= 0x80000000;
|
||||||
|
state->g_cp0_regs[CP0_EPC_REG]-=4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] &= 0x7FFFFFFF;
|
||||||
|
}
|
||||||
|
generic_jump_to(state, 0x80000180);
|
||||||
|
state->last_addr = state->PC->addr;
|
||||||
|
if (state->r4300emu == CORE_DYNAREC)
|
||||||
|
{
|
||||||
|
dyna_jump(state);
|
||||||
|
if (!state->dyna_interp) state->delay_slot = 0;
|
||||||
|
}
|
||||||
|
if (state->r4300emu != CORE_DYNAREC || state->dyna_interp)
|
||||||
|
{
|
||||||
|
state->dyna_interp = 0;
|
||||||
|
if (state->delay_slot)
|
||||||
|
{
|
||||||
|
state->skip_jump = state->PC->addr;
|
||||||
|
state->next_interupt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
31
Frameworks/lazyusf/lazyusf/r4300/exception.h
Normal file
31
Frameworks/lazyusf/lazyusf/r4300/exception.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - exception.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_EXCEPTION_H
|
||||||
|
#define M64P_R4300_EXCEPTION_H
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
void TLB_refill_exception(usf_state_t *, unsigned int addresse, int w);
|
||||||
|
void osal_fastcall exception_general(usf_state_t *);
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_EXCEPTION_H */
|
||||||
|
|
465
Frameworks/lazyusf/lazyusf/r4300/fpu.h
Normal file
465
Frameworks/lazyusf/lazyusf/r4300/fpu.h
Normal file
|
@ -0,0 +1,465 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - fpu.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2010 Ari64 *
|
||||||
|
* *
|
||||||
|
* 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_R4300_FPU_H
|
||||||
|
#define M64P_R4300_FPU_H
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "r4300.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define M64P_FPU_INLINE static __inline
|
||||||
|
#include <float.h>
|
||||||
|
typedef enum { FE_TONEAREST = 0, FE_TOWARDZERO, FE_UPWARD, FE_DOWNWARD } eRoundType;
|
||||||
|
static void fesetround(eRoundType RoundType)
|
||||||
|
{
|
||||||
|
static const unsigned int msRound[4] = { _RC_NEAR, _RC_CHOP, _RC_UP, _RC_DOWN };
|
||||||
|
unsigned int oldX87, oldSSE2;
|
||||||
|
__control87_2(msRound[RoundType], _MCW_RC, &oldX87, &oldSSE2);
|
||||||
|
}
|
||||||
|
static __inline double round(double x) { return floor(x + 0.5); }
|
||||||
|
static __inline float roundf(float x) { return (float) floor(x + 0.5); }
|
||||||
|
static __inline double trunc(double x) { return (double) (int) x; }
|
||||||
|
static __inline float truncf(float x) { return (float) (int) x; }
|
||||||
|
#define isnan _isnan
|
||||||
|
#else
|
||||||
|
#define M64P_FPU_INLINE static inline
|
||||||
|
#include <fenv.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void set_rounding(usf_state_t * state)
|
||||||
|
{
|
||||||
|
switch(state->rounding_mode) {
|
||||||
|
case 0x33F:
|
||||||
|
fesetround(FE_TONEAREST);
|
||||||
|
break;
|
||||||
|
case 0xF3F:
|
||||||
|
fesetround(FE_TOWARDZERO);
|
||||||
|
break;
|
||||||
|
case 0xB3F:
|
||||||
|
fesetround(FE_UPWARD);
|
||||||
|
break;
|
||||||
|
case 0x73F:
|
||||||
|
fesetround(FE_DOWNWARD);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void cvt_s_w(usf_state_t * state, int *source,float *dest)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*dest = (float) *source;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void cvt_d_w(usf_state_t * state, int *source,double *dest)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
*dest = (double) *source;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void cvt_s_l(usf_state_t * state, long long *source,float *dest)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*dest = (float) *source;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void cvt_d_l(usf_state_t * state, long long *source,double *dest)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*dest = (double) *source;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void cvt_d_s(usf_state_t * state, float *source,double *dest)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
*dest = (double) *source;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void cvt_s_d(usf_state_t * state, double *source,float *dest)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*dest = (float) *source;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void round_l_s(float *source,long long *dest)
|
||||||
|
{
|
||||||
|
*dest = (long long) roundf(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void round_w_s(float *source,int *dest)
|
||||||
|
{
|
||||||
|
*dest = (int) roundf(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void trunc_l_s(float *source,long long *dest)
|
||||||
|
{
|
||||||
|
*dest = (long long) truncf(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void trunc_w_s(float *source,int *dest)
|
||||||
|
{
|
||||||
|
*dest = (int) truncf(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void ceil_l_s(float *source,long long *dest)
|
||||||
|
{
|
||||||
|
*dest = (long long) ceilf(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void ceil_w_s(float *source,int *dest)
|
||||||
|
{
|
||||||
|
*dest = (int) ceilf(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void floor_l_s(float *source,long long *dest)
|
||||||
|
{
|
||||||
|
*dest = (long long) floorf(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void floor_w_s(float *source,int *dest)
|
||||||
|
{
|
||||||
|
*dest = (int) floorf(*source);
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void round_l_d(double *source,long long *dest)
|
||||||
|
{
|
||||||
|
*dest = (long long) round(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void round_w_d(double *source,int *dest)
|
||||||
|
{
|
||||||
|
*dest = (int) round(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void trunc_l_d(double *source,long long *dest)
|
||||||
|
{
|
||||||
|
*dest = (long long) trunc(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void trunc_w_d(double *source,int *dest)
|
||||||
|
{
|
||||||
|
*dest = (int) trunc(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void ceil_l_d(double *source,long long *dest)
|
||||||
|
{
|
||||||
|
*dest = (long long) ceil(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void ceil_w_d(double *source,int *dest)
|
||||||
|
{
|
||||||
|
*dest = (int) ceil(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void floor_l_d(double *source,long long *dest)
|
||||||
|
{
|
||||||
|
*dest = (long long) floor(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void floor_w_d(double *source,int *dest)
|
||||||
|
{
|
||||||
|
*dest = (int) floor(*source);
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void cvt_w_s(usf_state_t * state, float *source,int *dest)
|
||||||
|
{
|
||||||
|
switch(state->FCR31&3)
|
||||||
|
{
|
||||||
|
case 0: round_w_s(source,dest);return;
|
||||||
|
case 1: trunc_w_s(source,dest);return;
|
||||||
|
case 2: ceil_w_s(source,dest);return;
|
||||||
|
case 3: floor_w_s(source,dest);return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void cvt_w_d(usf_state_t * state, double *source,int *dest)
|
||||||
|
{
|
||||||
|
switch(state->FCR31&3)
|
||||||
|
{
|
||||||
|
case 0: round_w_d(source,dest);return;
|
||||||
|
case 1: trunc_w_d(source,dest);return;
|
||||||
|
case 2: ceil_w_d(source,dest);return;
|
||||||
|
case 3: floor_w_d(source,dest);return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void cvt_l_s(usf_state_t * state, float *source,long long *dest)
|
||||||
|
{
|
||||||
|
switch(state->FCR31&3)
|
||||||
|
{
|
||||||
|
case 0: round_l_s(source,dest);return;
|
||||||
|
case 1: trunc_l_s(source,dest);return;
|
||||||
|
case 2: ceil_l_s(source,dest);return;
|
||||||
|
case 3: floor_l_s(source,dest);return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void cvt_l_d(usf_state_t * state, double *source,long long *dest)
|
||||||
|
{
|
||||||
|
switch(state->FCR31&3)
|
||||||
|
{
|
||||||
|
case 0: round_l_d(source,dest);return;
|
||||||
|
case 1: trunc_l_d(source,dest);return;
|
||||||
|
case 2: ceil_l_d(source,dest);return;
|
||||||
|
case 3: floor_l_d(source,dest);return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_f_s(usf_state_t * state)
|
||||||
|
{
|
||||||
|
state->FCR31 &= ~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_un_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
state->FCR31=(isnan(*source) || isnan(*target)) ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_eq_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31&=~0x800000;return;}
|
||||||
|
state->FCR31 = *source==*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ueq_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31|=0x800000;return;}
|
||||||
|
state->FCR31 = *source==*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_olt_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31&=~0x800000;return;}
|
||||||
|
state->FCR31 = *source<*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ult_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31|=0x800000;return;}
|
||||||
|
state->FCR31 = *source<*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_ole_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31&=~0x800000;return;}
|
||||||
|
state->FCR31 = *source<=*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ule_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31|=0x800000;return;}
|
||||||
|
state->FCR31 = *source<=*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_sf_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31&=~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ngle_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31&=~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_seq_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source==*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ngl_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source==*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_lt_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source<*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_nge_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source<*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_le_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source<=*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ngt_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source<=*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_f_d(usf_state_t * state)
|
||||||
|
{
|
||||||
|
state->FCR31 &= ~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_un_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
state->FCR31=(isnan(*source) || isnan(*target)) ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_eq_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31&=~0x800000;return;}
|
||||||
|
state->FCR31 = *source==*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ueq_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31|=0x800000;return;}
|
||||||
|
state->FCR31 = *source==*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_olt_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31&=~0x800000;return;}
|
||||||
|
state->FCR31 = *source<*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ult_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31|=0x800000;return;}
|
||||||
|
state->FCR31 = *source<*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_ole_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31&=~0x800000;return;}
|
||||||
|
state->FCR31 = *source<=*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ule_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
if (isnan(*source) || isnan(*target)) {state->FCR31|=0x800000;return;}
|
||||||
|
state->FCR31 = *source<=*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_sf_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
(void)source; (void)target;
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31&=~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ngle_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31&=~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_seq_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source==*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ngl_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source==*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_lt_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source<*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_nge_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source<*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void c_le_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source<=*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void c_ngt_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
//if (isnan(*source) || isnan(*target)) // FIXME - exception
|
||||||
|
state->FCR31 = *source<=*target ? state->FCR31|0x800000 : state->FCR31&~0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
M64P_FPU_INLINE void add_s(usf_state_t * state, float *source1,float *source2,float *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=(*source1)+(*source2);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void sub_s(usf_state_t * state, float *source1,float *source2,float *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=(*source1)-(*source2);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void mul_s(usf_state_t * state, float *source1,float *source2,float *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=(*source1)*(*source2);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void div_s(usf_state_t * state, float *source1,float *source2,float *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=(*source1)/(*source2);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void sqrt_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=sqrtf(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void abs_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
*target=fabsf(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void mov_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
*target=*source;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void neg_s(usf_state_t * state, float *source,float *target)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
*target=-(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void add_d(usf_state_t * state, double *source1,double *source2,double *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=(*source1)+(*source2);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void sub_d(usf_state_t * state, double *source1,double *source2,double *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=(*source1)-(*source2);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void mul_d(usf_state_t * state, double *source1,double *source2,double *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=(*source1)*(*source2);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void div_d(usf_state_t * state, double *source1,double *source2,double *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=(*source1)/(*source2);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void sqrt_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
set_rounding(state);
|
||||||
|
*target=sqrt(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void abs_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
*target=fabs(*source);
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void mov_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
*target=*source;
|
||||||
|
}
|
||||||
|
M64P_FPU_INLINE void neg_d(usf_state_t * state, double *source,double *target)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
*target=-(*source);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_FPU_H */
|
105
Frameworks/lazyusf/lazyusf/r4300/instr_counters.c
Normal file
105
Frameworks/lazyusf/lazyusf/r4300/instr_counters.c
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - instr_counters.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#if defined(COUNT_INSTR)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
|
||||||
|
/* various constants */
|
||||||
|
static char instr_name[][10] =
|
||||||
|
{
|
||||||
|
"reserved", "NI", "J", "JAL", "BEQ", "BNE", "BLEZ", "BGTZ",
|
||||||
|
"ADDI", "ADDIU", "SLTI", "SLTIU", "ANDI", "ORI", "XORI", "LUI",
|
||||||
|
"BEQL", "BNEL", "BLEZL", "BGTZL", "DADDI", "DADDIU", "LDL", "LDR",
|
||||||
|
"LB", "LH", "LW", "LWL", "LBU", "LHU", "LWU", "LWR",
|
||||||
|
"SB", "SH", "SW", "SWL", "SWR", "SDL", "SDR", "LWC1",
|
||||||
|
"LDC1", "LD", "LL", "SWC1", "SDC1", "SD", "SC", "BLTZ",
|
||||||
|
"BGEZ", "BLTZL", "BGEZL", "BLTZAL", "BGEZAL", "BLTZALL", "BGEZALL", "SLL",
|
||||||
|
"SRL", "SRA", "SLLV", "SRLV", "SRAV", "JR", "JALR", "SYSCALL",
|
||||||
|
"MFHI", "MTHI", "MFLO", "MTLO", "DSLLV", "DSRLV", "DSRAV", "MULT",
|
||||||
|
"MULTU", "DIV", "DIVU", "DMULT", "DMULTU", "DDIV", "DDIVU", "ADD",
|
||||||
|
"ADDU", "SUB", "SUBU", "AND", "OR", "XOR", "NOR", "SLT",
|
||||||
|
"SLTU", "DADD", "DADDU", "DSUB", "DSUBU", "DSLL", "DSRL", "DSRA",
|
||||||
|
"TEQ", "DSLL32", "DSRL32", "DSRA32", "BC1F", "BC1T", "BC1FL", "BC1TL",
|
||||||
|
"TLBWI", "TLBP", "TLBR", "TLBWR", "ERET", "MFC0", "MTC0", "MFC1",
|
||||||
|
"DMFC1", "CFC1", "MTC1", "DMTC1", "CTC1", "f.CVT", "f.CMP", "f.ADD",
|
||||||
|
"f.SUB", "f.MUL", "f.DIV", "f.SQRT", "f.ABS", "f.MOV", "f.NEG", "f.ROUND",
|
||||||
|
"f.TRUNC", "f.CEIL", "f.FLOOR"
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned int instr_type[131] =
|
||||||
|
{
|
||||||
|
9, 10, 6, 6, 7, 7, 7, 7, 3, 3, 4, 4, 3, 4, 4, 0,
|
||||||
|
7, 7, 7, 7, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 6, 6, 10,
|
||||||
|
2, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3,
|
||||||
|
3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
8, 4, 4, 4, 7, 7, 7, 7, 10, 10, 10, 10, 8, 2, 2, 2,
|
||||||
|
2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5,
|
||||||
|
5, 5, 5
|
||||||
|
};
|
||||||
|
|
||||||
|
static char instr_typename[][20] =
|
||||||
|
{
|
||||||
|
"Load", "Store", "Data move/convert",
|
||||||
|
"32-bit math", "64-bit math", "Float Math",
|
||||||
|
"Jump", "Branch", "Exceptions",
|
||||||
|
"Reserved", "Other"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* global function */
|
||||||
|
void instr_counters_print(usf_state_t * state)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
unsigned int iTypeCount[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
unsigned int iTotal = 0;
|
||||||
|
char line[128], param[24];
|
||||||
|
DebugMessage(state, M64MSG_INFO, "Instruction counters:");
|
||||||
|
line[0] = 0;
|
||||||
|
for (i = 0; i < 131; i++)
|
||||||
|
{
|
||||||
|
sprintf(param, "%8s: %08i ", instr_name[i], state->instr_count[i]);
|
||||||
|
strcat(line, param);
|
||||||
|
if (i % 5 == 4)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_INFO, "%s", line);
|
||||||
|
line[0] = 0;
|
||||||
|
}
|
||||||
|
iTypeCount[instr_type[i]] += state->instr_count[i];
|
||||||
|
iTotal += state->instr_count[i];
|
||||||
|
}
|
||||||
|
DebugMessage(state, M64MSG_INFO, "Instruction type summary (total instructions = %i)", iTotal);
|
||||||
|
for (i = 0; i < 11; i++)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_INFO, "%20s: %04.1f%% (%i)", instr_typename[i], (float) iTypeCount[i] * 100.0 / iTotal, iTypeCount[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* COUNT_INSTR */
|
29
Frameworks/lazyusf/lazyusf/r4300/instr_counters.h
Normal file
29
Frameworks/lazyusf/lazyusf/r4300/instr_counters.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - instr_counters.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_INSTR_COUNTERS_H
|
||||||
|
#define M64P_R4300_INSTR_COUNTERS_H
|
||||||
|
|
||||||
|
#if defined(COUNT_INSTR)
|
||||||
|
void instr_counters_print(usf_state_t * state);
|
||||||
|
#endif /* COUNT_INSTR */
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_INSTR_COUNTERS_H */
|
79
Frameworks/lazyusf/lazyusf/r4300/interpreter.def
Normal file
79
Frameworks/lazyusf/lazyusf/r4300/interpreter.def
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - interpreter.def *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/* Before #including this file, the following macros should be defined:
|
||||||
|
*
|
||||||
|
* PCADDR: Program counter (memory address of the current instruction).
|
||||||
|
*
|
||||||
|
* ADD_TO_PC(x): Increment the program counter in 'x' instructions.
|
||||||
|
* This is only used for small changes to PC, so the new program counter
|
||||||
|
* is guaranteed to fall in the current cached interpreter or dynarec block.
|
||||||
|
*
|
||||||
|
* DECLARE_INSTRUCTION(name)
|
||||||
|
* Declares an instruction function which is not a jump.
|
||||||
|
* Followed by a block of code.
|
||||||
|
*
|
||||||
|
* DECLARE_JUMP(name, destination, condition, link, likely, cop1)
|
||||||
|
* name is the name of the jump or branch instruction.
|
||||||
|
* destination is the destination memory address of the jump.
|
||||||
|
* If condition is nonzero, the jump is taken.
|
||||||
|
* link is a pointer to a variable where (PC+8) is written unconditionally.
|
||||||
|
* To avoid linking, pass ®[0]
|
||||||
|
* If likely is nonzero, the delay slot is only executed if the jump is taken.
|
||||||
|
* If cop1 is nonzero, a COP1 unusable check will be done.
|
||||||
|
*
|
||||||
|
* CHECK_MEMORY(): A snippet to be run after a store instruction,
|
||||||
|
* to check if the store affected executable blocks.
|
||||||
|
* The memory address of the store is in the 'address' global.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(NI)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "NI() @ 0x%x", PCADDR);
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "opcode not implemented: %x:%x", PCADDR, *fast_mem_access(state, PCADDR));
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(RESERVED)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "reserved opcode: %x:%x", PCADDR, *fast_mem_access(state, PCADDR));
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// R4300
|
||||||
|
#include "interpreter_r4300.def"
|
||||||
|
|
||||||
|
// COP0
|
||||||
|
#include "interpreter_cop0.def"
|
||||||
|
|
||||||
|
// COP1
|
||||||
|
#include "interpreter_cop1.def"
|
||||||
|
|
||||||
|
// regimm
|
||||||
|
#include "interpreter_regimm.def"
|
||||||
|
|
||||||
|
// special
|
||||||
|
#include "interpreter_special.def"
|
||||||
|
|
||||||
|
// TLB
|
||||||
|
#include "interpreter_tlb.def"
|
||||||
|
|
||||||
|
|
137
Frameworks/lazyusf/lazyusf/r4300/interpreter_cop0.def
Normal file
137
Frameworks/lazyusf/lazyusf/r4300/interpreter_cop0.def
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - interpreter_cop0.def *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MFC0)
|
||||||
|
{
|
||||||
|
switch(rfs)
|
||||||
|
{
|
||||||
|
case CP0_RANDOM_REG:
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "MFC0 instruction reading un-implemented Random register");
|
||||||
|
state->stop=1;
|
||||||
|
case CP0_COUNT_REG:
|
||||||
|
update_count(state);
|
||||||
|
default:
|
||||||
|
rrt32 = state->g_cp0_regs[rfs];
|
||||||
|
sign_extended(rrt);
|
||||||
|
}
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MTC0)
|
||||||
|
{
|
||||||
|
switch(rfs)
|
||||||
|
{
|
||||||
|
case CP0_INDEX_REG:
|
||||||
|
state->g_cp0_regs[CP0_INDEX_REG] = (unsigned int) rrt & 0x8000003F;
|
||||||
|
if ((state->g_cp0_regs[CP0_INDEX_REG] & 0x3F) > 31)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "MTC0 instruction writing Index register with TLB index > 31");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CP0_RANDOM_REG:
|
||||||
|
break;
|
||||||
|
case CP0_ENTRYLO0_REG:
|
||||||
|
state->g_cp0_regs[CP0_ENTRYLO0_REG] = (unsigned int) rrt & 0x3FFFFFFF;
|
||||||
|
break;
|
||||||
|
case CP0_ENTRYLO1_REG:
|
||||||
|
state->g_cp0_regs[CP0_ENTRYLO1_REG] = (unsigned int) rrt & 0x3FFFFFFF;
|
||||||
|
break;
|
||||||
|
case CP0_CONTEXT_REG:
|
||||||
|
state->g_cp0_regs[CP0_CONTEXT_REG] = ((unsigned int) rrt & 0xFF800000)
|
||||||
|
| (state->g_cp0_regs[CP0_CONTEXT_REG] & 0x007FFFF0);
|
||||||
|
break;
|
||||||
|
case CP0_PAGEMASK_REG:
|
||||||
|
state->g_cp0_regs[CP0_PAGEMASK_REG] = (unsigned int) rrt & 0x01FFE000;
|
||||||
|
break;
|
||||||
|
case CP0_WIRED_REG:
|
||||||
|
state->g_cp0_regs[CP0_WIRED_REG] = (unsigned int) rrt;
|
||||||
|
state->g_cp0_regs[CP0_RANDOM_REG] = 31;
|
||||||
|
break;
|
||||||
|
case CP0_BADVADDR_REG:
|
||||||
|
break;
|
||||||
|
case CP0_COUNT_REG:
|
||||||
|
update_count(state);
|
||||||
|
state->interupt_unsafe_state = 1;
|
||||||
|
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state);
|
||||||
|
state->interupt_unsafe_state = 0;
|
||||||
|
translate_event_queue(state, (unsigned int) rrt & 0xFFFFFFFF);
|
||||||
|
state->g_cp0_regs[CP0_COUNT_REG] = (unsigned int) rrt & 0xFFFFFFFF;
|
||||||
|
break;
|
||||||
|
case CP0_ENTRYHI_REG:
|
||||||
|
state->g_cp0_regs[CP0_ENTRYHI_REG] = (unsigned int) rrt & 0xFFFFE0FF;
|
||||||
|
break;
|
||||||
|
case CP0_COMPARE_REG:
|
||||||
|
update_count(state);
|
||||||
|
remove_event(state, COMPARE_INT);
|
||||||
|
add_interupt_event_count(state, COMPARE_INT, (unsigned int)rrt);
|
||||||
|
state->g_cp0_regs[CP0_COMPARE_REG] = (unsigned int) rrt;
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] &= 0xFFFF7FFF; //Timer interupt is clear
|
||||||
|
break;
|
||||||
|
case CP0_STATUS_REG:
|
||||||
|
if((rrt & 0x04000000) != (state->g_cp0_regs[CP0_STATUS_REG] & 0x04000000))
|
||||||
|
{
|
||||||
|
shuffle_fpr_data(state, state->g_cp0_regs[CP0_STATUS_REG], (unsigned int) rrt);
|
||||||
|
set_fpr_pointers(state, (unsigned int) rrt);
|
||||||
|
}
|
||||||
|
state->g_cp0_regs[CP0_STATUS_REG] = (unsigned int) rrt;
|
||||||
|
update_count(state);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
check_interupt(state);
|
||||||
|
state->interupt_unsafe_state = 1;
|
||||||
|
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state);
|
||||||
|
state->interupt_unsafe_state = 0;
|
||||||
|
ADD_TO_PC(-1);
|
||||||
|
break;
|
||||||
|
case CP0_CAUSE_REG:
|
||||||
|
if (rrt!=0)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "MTC0 instruction trying to write Cause register with non-0 value");
|
||||||
|
state->stop = 1;
|
||||||
|
}
|
||||||
|
else state->g_cp0_regs[CP0_CAUSE_REG] = (unsigned int) rrt;
|
||||||
|
break;
|
||||||
|
case CP0_EPC_REG:
|
||||||
|
state->g_cp0_regs[CP0_EPC_REG] = (unsigned int) rrt;
|
||||||
|
break;
|
||||||
|
case CP0_PREVID_REG:
|
||||||
|
break;
|
||||||
|
case CP0_CONFIG_REG:
|
||||||
|
state->g_cp0_regs[CP0_CONFIG_REG] = (unsigned int) rrt;
|
||||||
|
break;
|
||||||
|
case CP0_WATCHLO_REG:
|
||||||
|
state->g_cp0_regs[CP0_WATCHLO_REG] = (unsigned int) rrt & 0xFFFFFFFF;
|
||||||
|
break;
|
||||||
|
case CP0_WATCHHI_REG:
|
||||||
|
state->g_cp0_regs[CP0_WATCHHI_REG] = (unsigned int) rrt & 0xFFFFFFFF;
|
||||||
|
break;
|
||||||
|
case CP0_TAGLO_REG:
|
||||||
|
state->g_cp0_regs[CP0_TAGLO_REG] = (unsigned int) rrt & 0x0FFFFFC0;
|
||||||
|
break;
|
||||||
|
case CP0_TAGHI_REG:
|
||||||
|
state->g_cp0_regs[CP0_TAGHI_REG] =0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Unknown MTC0 write: %d", rfs);
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
708
Frameworks/lazyusf/lazyusf/r4300/interpreter_cop1.def
Normal file
708
Frameworks/lazyusf/lazyusf/r4300/interpreter_cop1.def
Normal file
|
@ -0,0 +1,708 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - interpreter_cop1.def *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 "fpu.h"
|
||||||
|
|
||||||
|
DECLARE_JUMP(BC1F, PCADDR + (iimmediate+1)*4, (state->FCR31 & 0x800000)==0, &state->reg[0], 0, 1)
|
||||||
|
DECLARE_JUMP(BC1T, PCADDR + (iimmediate+1)*4, (state->FCR31 & 0x800000)!=0, &state->reg[0], 0, 1)
|
||||||
|
DECLARE_JUMP(BC1FL, PCADDR + (iimmediate+1)*4, (state->FCR31 & 0x800000)==0, &state->reg[0], 1, 1)
|
||||||
|
DECLARE_JUMP(BC1TL, PCADDR + (iimmediate+1)*4, (state->FCR31 & 0x800000)!=0, &state->reg[0], 1, 1)
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MFC1)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
rrt32 = *((int*)state->reg_cop1_simple[rfs]);
|
||||||
|
sign_extended(rrt);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DMFC1)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
rrt = *((long long*)state->reg_cop1_double[rfs]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CFC1)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (rfs==31)
|
||||||
|
{
|
||||||
|
rrt32 = state->FCR31;
|
||||||
|
sign_extended(rrt);
|
||||||
|
}
|
||||||
|
if (rfs==0)
|
||||||
|
{
|
||||||
|
rrt32 = state->FCR0;
|
||||||
|
sign_extended(rrt);
|
||||||
|
}
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MTC1)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
*((int*)state->reg_cop1_simple[rfs]) = rrt32;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DMTC1)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
*((long long*)state->reg_cop1_double[rfs]) = rrt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CTC1)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (rfs==31)
|
||||||
|
state->FCR31 = rrt32;
|
||||||
|
switch((state->FCR31 & 3))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state->rounding_mode = 0x33F; // Round to nearest, or to even if equidistant
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state->rounding_mode = 0xF3F; // Truncate (toward 0)
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state->rounding_mode = 0xB3F; // Round up (toward +infinity)
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state->rounding_mode = 0x73F; // Round down (toward -infinity)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//if ((state->FCR31 >> 7) & 0x1F) printf("FPU Exception enabled : %x\n",
|
||||||
|
// (int)((state->FCR31 >> 7) & 0x1F));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// COP1_D
|
||||||
|
DECLARE_INSTRUCTION(ADD_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
add_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SUB_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
sub_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MUL_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
mul_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DIV_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if((state->FCR31 & 0x400) && *state->reg_cop1_double[cfft] == 0)
|
||||||
|
{
|
||||||
|
//state->FCR31 |= 0x8020;
|
||||||
|
/*state->FCR31 |= 0x8000;
|
||||||
|
state->Cause = 15 << 2;
|
||||||
|
exception_general(state);*/
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "DIV_D by 0");
|
||||||
|
//return;
|
||||||
|
}
|
||||||
|
div_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SQRT_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
sqrt_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ABS_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
abs_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MOV_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
mov_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(NEG_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
neg_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ROUND_L_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
round_l_d(state->reg_cop1_double[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(TRUNC_L_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
trunc_l_d(state->reg_cop1_double[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CEIL_L_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
ceil_l_d(state->reg_cop1_double[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(FLOOR_L_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
floor_l_d(state->reg_cop1_double[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ROUND_W_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
round_w_d(state->reg_cop1_double[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(TRUNC_W_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
trunc_w_d(state->reg_cop1_double[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CEIL_W_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
ceil_w_d(state->reg_cop1_double[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(FLOOR_W_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
floor_w_d(state->reg_cop1_double[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CVT_S_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_s_d(state, state->reg_cop1_double[cffs], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CVT_W_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_w_d(state, state->reg_cop1_double[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CVT_L_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_l_d(state, state->reg_cop1_double[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_F_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_f_d(state);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_UN_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_un_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_EQ_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_eq_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_UEQ_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_ueq_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_OLT_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_olt_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_ULT_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_ult_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_OLE_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_ole_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_ULE_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_ule_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_SF_D)
|
||||||
|
{
|
||||||
|
if (isnan(*state->reg_cop1_double[cffs]) || isnan(*state->reg_cop1_double[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_sf_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_NGLE_D)
|
||||||
|
{
|
||||||
|
if (isnan(*state->reg_cop1_double[cffs]) || isnan(*state->reg_cop1_double[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_ngle_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_SEQ_D)
|
||||||
|
{
|
||||||
|
if (isnan(*state->reg_cop1_double[cffs]) || isnan(*state->reg_cop1_double[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_seq_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_NGL_D)
|
||||||
|
{
|
||||||
|
if (isnan(*state->reg_cop1_double[cffs]) || isnan(*state->reg_cop1_double[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_ngl_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_LT_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_double[cffs]) || isnan(*state->reg_cop1_double[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_lt_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_NGE_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_double[cffs]) || isnan(*state->reg_cop1_double[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_nge_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_LE_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_double[cffs]) || isnan(*state->reg_cop1_double[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_le_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_NGT_D)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_double[cffs]) || isnan(*state->reg_cop1_double[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_ngt_d(state, state->reg_cop1_double[cffs], state->reg_cop1_double[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// COP1_L
|
||||||
|
DECLARE_INSTRUCTION(CVT_S_L)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_s_l(state, (long long*)(state->reg_cop1_double[cffs]), state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CVT_D_L)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_d_l(state, (long long*)(state->reg_cop1_double[cffs]), state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// COP1_S
|
||||||
|
DECLARE_INSTRUCTION(ADD_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
add_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SUB_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
sub_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MUL_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
mul_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DIV_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if((state->FCR31 & 0x400) && *state->reg_cop1_simple[cfft] == 0)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "DIV_S by 0");
|
||||||
|
}
|
||||||
|
div_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SQRT_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
sqrt_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ABS_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
abs_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MOV_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
mov_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(NEG_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
neg_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ROUND_L_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
round_l_s(state->reg_cop1_simple[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(TRUNC_L_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
trunc_l_s(state->reg_cop1_simple[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CEIL_L_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
ceil_l_s(state->reg_cop1_simple[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(FLOOR_L_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
floor_l_s(state->reg_cop1_simple[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ROUND_W_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
round_w_s(state->reg_cop1_simple[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(TRUNC_W_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
trunc_w_s(state->reg_cop1_simple[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CEIL_W_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
ceil_w_s(state->reg_cop1_simple[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(FLOOR_W_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
floor_w_s(state->reg_cop1_simple[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CVT_D_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_d_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CVT_W_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_w_s(state, state->reg_cop1_simple[cffs], (int*)state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CVT_L_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_l_s(state, state->reg_cop1_simple[cffs], (long long*)(state->reg_cop1_double[cffd]));
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_F_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_f_s(state);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_UN_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_un_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_EQ_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_eq_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_UEQ_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_ueq_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_OLT_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_olt_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_ULT_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_ult_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_OLE_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_ole_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_ULE_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
c_ule_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_SF_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_simple[cffs]) || isnan(*state->reg_cop1_simple[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_sf_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_NGLE_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_simple[cffs]) || isnan(*state->reg_cop1_simple[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_ngle_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_SEQ_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_simple[cffs]) || isnan(*state->reg_cop1_simple[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_seq_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_NGL_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_simple[cffs]) || isnan(*state->reg_cop1_simple[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_ngl_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_LT_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_simple[cffs]) || isnan(*state->reg_cop1_simple[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_lt_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_NGE_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_simple[cffs]) || isnan(*state->reg_cop1_simple[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_nge_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_LE_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_simple[cffs]) || isnan(*state->reg_cop1_simple[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_le_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(C_NGT_S)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
if (isnan(*state->reg_cop1_simple[cffs]) || isnan(*state->reg_cop1_simple[cfft]))
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Invalid operation exception in C opcode");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
c_ngt_s(state, state->reg_cop1_simple[cffs], state->reg_cop1_simple[cfft]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// COP1_W
|
||||||
|
DECLARE_INSTRUCTION(CVT_S_W)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_s_w(state, (int*)state->reg_cop1_simple[cffs], state->reg_cop1_simple[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CVT_D_W)
|
||||||
|
{
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
cvt_d_w(state, (int*)state->reg_cop1_simple[cffs], state->reg_cop1_double[cffd]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
800
Frameworks/lazyusf/lazyusf/r4300/interpreter_r4300.def
Normal file
800
Frameworks/lazyusf/lazyusf/r4300/interpreter_r4300.def
Normal file
|
@ -0,0 +1,800 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - interpreter_r4300.def *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
DECLARE_JUMP(J, (jinst_index<<2) | ((PCADDR+4) & 0xF0000000), 1, &state->reg[0], 0, 0)
|
||||||
|
DECLARE_JUMP(JAL, (jinst_index<<2) | ((PCADDR+4) & 0xF0000000), 1, &state->reg[31], 0, 0)
|
||||||
|
DECLARE_JUMP(BEQ, PCADDR + (iimmediate+1)*4, irs == irt, &state->reg[0], 0, 0)
|
||||||
|
DECLARE_JUMP(BNE, PCADDR + (iimmediate+1)*4, irs != irt, &state->reg[0], 0, 0)
|
||||||
|
DECLARE_JUMP(BLEZ, PCADDR + (iimmediate+1)*4, irs <= 0, &state->reg[0], 0, 0)
|
||||||
|
DECLARE_JUMP(BGTZ, PCADDR + (iimmediate+1)*4, irs > 0, &state->reg[0], 0, 0)
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ADDI)
|
||||||
|
{
|
||||||
|
irt32 = irs32 + iimmediate;
|
||||||
|
sign_extended(irt);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ADDIU)
|
||||||
|
{
|
||||||
|
irt32 = irs32 + iimmediate;
|
||||||
|
sign_extended(irt);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SLTI)
|
||||||
|
{
|
||||||
|
if (irs < iimmediate) irt = 1;
|
||||||
|
else irt = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SLTIU)
|
||||||
|
{
|
||||||
|
if ((unsigned long long)irs < (unsigned long long)((long long)iimmediate))
|
||||||
|
irt = 1;
|
||||||
|
else irt = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ANDI)
|
||||||
|
{
|
||||||
|
irt = irs & (unsigned short)iimmediate;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ORI)
|
||||||
|
{
|
||||||
|
irt = irs | (unsigned short)iimmediate;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(XORI)
|
||||||
|
{
|
||||||
|
irt = irs ^ (unsigned short)iimmediate;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LUI)
|
||||||
|
{
|
||||||
|
irt32 = iimmediate << 16;
|
||||||
|
sign_extended(irt);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JUMP(BEQL, PCADDR + (iimmediate+1)*4, irs == irt, &state->reg[0], 1, 0)
|
||||||
|
DECLARE_JUMP(BNEL, PCADDR + (iimmediate+1)*4, irs != irt, &state->reg[0], 1, 0)
|
||||||
|
DECLARE_JUMP(BLEZL, PCADDR + (iimmediate+1)*4, irs <= 0, &state->reg[0], 1, 0)
|
||||||
|
DECLARE_JUMP(BGTZL, PCADDR + (iimmediate+1)*4, irs > 0, &state->reg[0], 1, 0)
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DADDI)
|
||||||
|
{
|
||||||
|
irt = irs + iimmediate;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DADDIU)
|
||||||
|
{
|
||||||
|
irt = irs + iimmediate;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODOXXX refactor the following functions to remove the
|
||||||
|
// lsaddr and lsrpt locals. this may lead to a small speedup too
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LDL)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
unsigned long long int word = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
switch ((lsaddr) & 7)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_dword_in_memory();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFF) | (word << 8);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFF) | (word << 16);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFF) | (word << 24);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFF) | (word << 32);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFLL) | (word << 40);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFFLL) | (word << 48);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFFFFLL) | (word << 56);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LDR)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
unsigned long long int word = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
switch ((lsaddr) & 7)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFFFF00LL) | (word >> 56);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFF0000LL) | (word >> 48);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFF000000LL) | (word >> 40);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFF00000000LL) | (word >> 32);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFF0000000000LL) | (word >> 24);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFF000000000000LL) | (word >> 16);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFF00000000000000LL) | (word >> 8);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_dword_in_memory();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LB)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_byte_in_memory();
|
||||||
|
if (state->address)
|
||||||
|
sign_extendedb(*lsrtp);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LH)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_hword_in_memory();
|
||||||
|
if (state->address)
|
||||||
|
sign_extendedh(*lsrtp);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LWL)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
unsigned long long int word = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
switch ((lsaddr) & 3)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_word_in_memory();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFF) | (word << 8);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFF) | (word << 16);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFF) | (word << 24);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(state->address)
|
||||||
|
sign_extended(*lsrtp);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LW)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_word_in_memory();
|
||||||
|
if (state->address)
|
||||||
|
sign_extended(*lsrtp);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LBU)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_byte_in_memory();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LHU)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_hword_in_memory();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LWR)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
unsigned long long int word = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
switch ((lsaddr) & 3)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFFFF00LL) | ((word >> 24) & 0xFF);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFFFF0000LL) | ((word >> 16) & 0xFFFF);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
*lsrtp = (*lsrtp & 0xFFFFFFFFFF000000LL) | ((word >> 8) & 0XFFFFFF);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
sign_extended(*lsrtp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LWU)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_word_in_memory();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SB)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->cpu_byte = (unsigned char)(*lsrtp & 0xFF);
|
||||||
|
write_byte_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SH)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->cpu_hword = (unsigned short)(*lsrtp & 0xFFFF);
|
||||||
|
write_hword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SWL)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
unsigned long long int old_word = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
switch ((lsaddr) & 3)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->cpu_word = (unsigned int)*lsrtp;
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_word = ((unsigned int)*lsrtp >> 8) | ((unsigned int) old_word & 0xFF000000);
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_word = ((unsigned int)*lsrtp >> 16) | ((unsigned int) old_word & 0xFFFF0000);
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->cpu_byte = (unsigned char)(*lsrtp >> 24);
|
||||||
|
write_byte_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SW)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->cpu_word = (unsigned int)(*lsrtp & 0xFFFFFFFF);
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SDL)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
unsigned long long int old_word = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
switch ((lsaddr) & 7)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->cpu_dword = *lsrtp;
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 8)|(old_word & 0xFF00000000000000LL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 16)|(old_word & 0xFFFF000000000000LL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 24)|(old_word & 0xFFFFFF0000000000LL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 32)|(old_word & 0xFFFFFFFF00000000LL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 40)|(old_word & 0xFFFFFFFFFF000000LL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 48)|(old_word & 0xFFFFFFFFFFFF0000LL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = ((unsigned long long)*lsrtp >> 56)|(old_word & 0xFFFFFFFFFFFFFF00LL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SDR)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
unsigned long long int old_word = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
switch ((lsaddr) & 7)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = (*lsrtp << 56) | (old_word & 0x00FFFFFFFFFFFFFFLL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = (*lsrtp << 48) | (old_word & 0x0000FFFFFFFFFFFFLL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = (*lsrtp << 40) | (old_word & 0x000000FFFFFFFFFFLL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = (*lsrtp << 32) | (old_word & 0x00000000FFFFFFFFLL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = (*lsrtp << 24) | (old_word & 0x0000000000FFFFFFLL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = (*lsrtp << 16) | (old_word & 0x000000000000FFFFLL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_dword_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_dword = (*lsrtp << 8) | (old_word & 0x00000000000000FFLL);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFF8;
|
||||||
|
state->cpu_dword = *lsrtp;
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SWR)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
unsigned long long int old_word = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
switch ((lsaddr) & 3)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_word = ((unsigned int)*lsrtp << 24) | ((unsigned int) old_word & 0x00FFFFFF);
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_word = ((unsigned int)*lsrtp << 16) | ((unsigned int) old_word & 0x0000FFFF);
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->rdword = &old_word;
|
||||||
|
read_word_in_memory();
|
||||||
|
if(state->address)
|
||||||
|
{
|
||||||
|
state->cpu_word = ((unsigned int)*lsrtp << 8) | ((unsigned int) old_word & 0x000000FF);
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state->address = ((unsigned int) lsaddr) & 0xFFFFFFFC;
|
||||||
|
state->cpu_word = (unsigned int)*lsrtp;
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(CACHE)
|
||||||
|
{
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LL)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_word_in_memory();
|
||||||
|
if (state->address)
|
||||||
|
{
|
||||||
|
sign_extended(*lsrtp);
|
||||||
|
state->llbit = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LWC1)
|
||||||
|
{
|
||||||
|
const unsigned char lslfft = lfft;
|
||||||
|
const unsigned int lslfaddr = (unsigned int)(lfoffset + state->reg[lfbase]);
|
||||||
|
unsigned long long int temp;
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lslfaddr;
|
||||||
|
state->rdword = &temp;
|
||||||
|
read_word_in_memory();
|
||||||
|
if (state->address)
|
||||||
|
*((int*)state->reg_cop1_simple[lslfft]) = (int) *state->rdword;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LDC1)
|
||||||
|
{
|
||||||
|
const unsigned char lslfft = lfft;
|
||||||
|
const unsigned int lslfaddr = (unsigned int)(lfoffset + state->reg[lfbase]);
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lslfaddr;
|
||||||
|
state->rdword = (unsigned long long *)state->reg_cop1_double[lslfft];
|
||||||
|
read_dword_in_memory();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(LD)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->rdword = (unsigned long long *) lsrtp;
|
||||||
|
read_dword_in_memory();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SC)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
if(state->llbit)
|
||||||
|
{
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->cpu_word = (unsigned int)(*lsrtp & 0xFFFFFFFF);
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
state->llbit = 0;
|
||||||
|
*lsrtp = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*lsrtp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SWC1)
|
||||||
|
{
|
||||||
|
const unsigned char lslfft = lfft;
|
||||||
|
const unsigned int lslfaddr = (unsigned int)(lfoffset + state->reg[lfbase]);
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lslfaddr;
|
||||||
|
state->cpu_word = *((int*)state->reg_cop1_simple[lslfft]);
|
||||||
|
write_word_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SDC1)
|
||||||
|
{
|
||||||
|
const unsigned char lslfft = lfft;
|
||||||
|
const unsigned int lslfaddr = (unsigned int)(lfoffset + state->reg[lfbase]);
|
||||||
|
if (check_cop1_unusable(state)) return;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lslfaddr;
|
||||||
|
state->cpu_dword = *((unsigned long long*)state->reg_cop1_double[lslfft]);
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SD)
|
||||||
|
{
|
||||||
|
const unsigned int lsaddr = (unsigned int)(iimmediate + irs32);
|
||||||
|
long long int *lsrtp = &irt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
state->address = (unsigned int) lsaddr;
|
||||||
|
state->cpu_dword = *lsrtp;
|
||||||
|
write_dword_in_memory();
|
||||||
|
CHECK_MEMORY();
|
||||||
|
}
|
29
Frameworks/lazyusf/lazyusf/r4300/interpreter_regimm.def
Normal file
29
Frameworks/lazyusf/lazyusf/r4300/interpreter_regimm.def
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - interpreter_regimm.def *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
DECLARE_JUMP(BLTZ, PCADDR + (iimmediate+1)*4, irs < 0, &state->reg[0], 0, 0)
|
||||||
|
DECLARE_JUMP(BGEZ, PCADDR + (iimmediate+1)*4, irs >= 0, &state->reg[0], 0, 0)
|
||||||
|
DECLARE_JUMP(BLTZL, PCADDR + (iimmediate+1)*4, irs < 0, &state->reg[0], 1, 0)
|
||||||
|
DECLARE_JUMP(BGEZL, PCADDR + (iimmediate+1)*4, irs >= 0, &state->reg[0], 1, 0)
|
||||||
|
DECLARE_JUMP(BLTZAL, PCADDR + (iimmediate+1)*4, irs < 0, &state->reg[31], 0, 0)
|
||||||
|
DECLARE_JUMP(BGEZAL, PCADDR + (iimmediate+1)*4, irs >= 0, &state->reg[31], 0, 0)
|
||||||
|
DECLARE_JUMP(BLTZALL, PCADDR + (iimmediate+1)*4, irs < 0, &state->reg[31], 1, 0)
|
||||||
|
DECLARE_JUMP(BGEZALL, PCADDR + (iimmediate+1)*4, irs >= 0, &state->reg[31], 1, 0)
|
408
Frameworks/lazyusf/lazyusf/r4300/interpreter_special.def
Normal file
408
Frameworks/lazyusf/lazyusf/r4300/interpreter_special.def
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - interpreter_special.def *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(NOP)
|
||||||
|
{
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SLL)
|
||||||
|
{
|
||||||
|
rrd32 = (unsigned int)(rrt32) << rsa;
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SRL)
|
||||||
|
{
|
||||||
|
rrd32 = (unsigned int)rrt32 >> rsa;
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SRA)
|
||||||
|
{
|
||||||
|
rrd32 = (signed int)rrt32 >> rsa;
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SLLV)
|
||||||
|
{
|
||||||
|
rrd32 = (unsigned int)(rrt32) << (rrs32&0x1F);
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SRLV)
|
||||||
|
{
|
||||||
|
rrd32 = (unsigned int)rrt32 >> (rrs32 & 0x1F);
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SRAV)
|
||||||
|
{
|
||||||
|
rrd32 = (signed int)rrt32 >> (rrs32 & 0x1F);
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_JUMP(JR, irs32, 1, &state->reg[0], 0, 0)
|
||||||
|
DECLARE_JUMP(JALR, irs32, 1, &rrd, 0, 0)
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SYSCALL)
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] = 8 << 2;
|
||||||
|
exception_general(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SYNC)
|
||||||
|
{
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MFHI)
|
||||||
|
{
|
||||||
|
rrd = state->hi;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MTHI)
|
||||||
|
{
|
||||||
|
state->hi = rrs;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MFLO)
|
||||||
|
{
|
||||||
|
rrd = state->lo;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MTLO)
|
||||||
|
{
|
||||||
|
state->lo = rrs;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSLLV)
|
||||||
|
{
|
||||||
|
rrd = rrt << (rrs32&0x3F);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSRLV)
|
||||||
|
{
|
||||||
|
rrd = (unsigned long long)rrt >> (rrs32 & 0x3F);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSRAV)
|
||||||
|
{
|
||||||
|
rrd = (long long)rrt >> (rrs32 & 0x3F);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MULT)
|
||||||
|
{
|
||||||
|
long long int temp;
|
||||||
|
temp = rrs * rrt;
|
||||||
|
state->hi = temp >> 32;
|
||||||
|
state->lo = temp;
|
||||||
|
sign_extended(state->lo);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(MULTU)
|
||||||
|
{
|
||||||
|
unsigned long long int temp;
|
||||||
|
temp = (unsigned int)rrs * (unsigned long long)((unsigned int)rrt);
|
||||||
|
state->hi = (long long)temp >> 32;
|
||||||
|
state->lo = temp;
|
||||||
|
sign_extended(state->lo);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DIV)
|
||||||
|
{
|
||||||
|
if (rrt32)
|
||||||
|
{
|
||||||
|
state->lo = rrs32 / rrt32;
|
||||||
|
state->hi = rrs32 % rrt32;
|
||||||
|
sign_extended(state->lo);
|
||||||
|
sign_extended(state->hi);
|
||||||
|
}
|
||||||
|
else DebugMessage(state, M64MSG_ERROR, "DIV: divide by 0");
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DIVU)
|
||||||
|
{
|
||||||
|
if (rrt32)
|
||||||
|
{
|
||||||
|
state->lo = (unsigned int)rrs32 / (unsigned int)rrt32;
|
||||||
|
state->hi = (unsigned int)rrs32 % (unsigned int)rrt32;
|
||||||
|
sign_extended(state->lo);
|
||||||
|
sign_extended(state->hi);
|
||||||
|
}
|
||||||
|
else DebugMessage(state, M64MSG_ERROR, "DIVU: divide by 0");
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DMULT)
|
||||||
|
{
|
||||||
|
unsigned long long int op1, op2, op3, op4;
|
||||||
|
unsigned long long int result1, result2, result3, result4;
|
||||||
|
unsigned long long int temp1, temp2, temp3, temp4;
|
||||||
|
int sign = 0;
|
||||||
|
|
||||||
|
if (rrs < 0)
|
||||||
|
{
|
||||||
|
op2 = -rrs;
|
||||||
|
sign = 1 - sign;
|
||||||
|
}
|
||||||
|
else op2 = rrs;
|
||||||
|
if (rrt < 0)
|
||||||
|
{
|
||||||
|
op4 = -rrt;
|
||||||
|
sign = 1 - sign;
|
||||||
|
}
|
||||||
|
else op4 = rrt;
|
||||||
|
|
||||||
|
op1 = op2 & 0xFFFFFFFF;
|
||||||
|
op2 = (op2 >> 32) & 0xFFFFFFFF;
|
||||||
|
op3 = op4 & 0xFFFFFFFF;
|
||||||
|
op4 = (op4 >> 32) & 0xFFFFFFFF;
|
||||||
|
|
||||||
|
temp1 = op1 * op3;
|
||||||
|
temp2 = (temp1 >> 32) + op1 * op4;
|
||||||
|
temp3 = op2 * op3;
|
||||||
|
temp4 = (temp3 >> 32) + op2 * op4;
|
||||||
|
|
||||||
|
result1 = temp1 & 0xFFFFFFFF;
|
||||||
|
result2 = temp2 + (temp3 & 0xFFFFFFFF);
|
||||||
|
result3 = (result2 >> 32) + temp4;
|
||||||
|
result4 = (result3 >> 32);
|
||||||
|
|
||||||
|
state->lo = result1 | (result2 << 32);
|
||||||
|
state->hi = (result3 & 0xFFFFFFFF) | (result4 << 32);
|
||||||
|
if (sign)
|
||||||
|
{
|
||||||
|
state->hi = ~state->hi;
|
||||||
|
if (!state->lo) state->hi++;
|
||||||
|
else state->lo = ~state->lo + 1;
|
||||||
|
}
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DMULTU)
|
||||||
|
{
|
||||||
|
unsigned long long int op1, op2, op3, op4;
|
||||||
|
unsigned long long int result1, result2, result3, result4;
|
||||||
|
unsigned long long int temp1, temp2, temp3, temp4;
|
||||||
|
|
||||||
|
op1 = rrs & 0xFFFFFFFF;
|
||||||
|
op2 = (rrs >> 32) & 0xFFFFFFFF;
|
||||||
|
op3 = rrt & 0xFFFFFFFF;
|
||||||
|
op4 = (rrt >> 32) & 0xFFFFFFFF;
|
||||||
|
|
||||||
|
temp1 = op1 * op3;
|
||||||
|
temp2 = (temp1 >> 32) + op1 * op4;
|
||||||
|
temp3 = op2 * op3;
|
||||||
|
temp4 = (temp3 >> 32) + op2 * op4;
|
||||||
|
|
||||||
|
result1 = temp1 & 0xFFFFFFFF;
|
||||||
|
result2 = temp2 + (temp3 & 0xFFFFFFFF);
|
||||||
|
result3 = (result2 >> 32) + temp4;
|
||||||
|
result4 = (result3 >> 32);
|
||||||
|
|
||||||
|
state->lo = result1 | (result2 << 32);
|
||||||
|
state->hi = (result3 & 0xFFFFFFFF) | (result4 << 32);
|
||||||
|
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DDIV)
|
||||||
|
{
|
||||||
|
if (rrt)
|
||||||
|
{
|
||||||
|
state->lo = (long long int)rrs / (long long int)rrt;
|
||||||
|
state->hi = (long long int)rrs % (long long int)rrt;
|
||||||
|
}
|
||||||
|
else DebugMessage(state, M64MSG_ERROR, "DDIV: divide by 0");
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DDIVU)
|
||||||
|
{
|
||||||
|
if (rrt)
|
||||||
|
{
|
||||||
|
state->lo = (unsigned long long int)rrs / (unsigned long long int)rrt;
|
||||||
|
state->hi = (unsigned long long int)rrs % (unsigned long long int)rrt;
|
||||||
|
}
|
||||||
|
else DebugMessage(state, M64MSG_ERROR, "DDIVU: divide by 0");
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ADD)
|
||||||
|
{
|
||||||
|
rrd32 = rrs32 + rrt32;
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ADDU)
|
||||||
|
{
|
||||||
|
rrd32 = rrs32 + rrt32;
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SUB)
|
||||||
|
{
|
||||||
|
rrd32 = rrs32 - rrt32;
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SUBU)
|
||||||
|
{
|
||||||
|
rrd32 = rrs32 - rrt32;
|
||||||
|
sign_extended(rrd);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(AND)
|
||||||
|
{
|
||||||
|
rrd = rrs & rrt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(OR)
|
||||||
|
{
|
||||||
|
rrd = rrs | rrt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(XOR)
|
||||||
|
{
|
||||||
|
rrd = rrs ^ rrt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(NOR)
|
||||||
|
{
|
||||||
|
rrd = ~(rrs | rrt);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SLT)
|
||||||
|
{
|
||||||
|
if (rrs < rrt) rrd = 1;
|
||||||
|
else rrd = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(SLTU)
|
||||||
|
{
|
||||||
|
if ((unsigned long long)rrs < (unsigned long long)rrt)
|
||||||
|
rrd = 1;
|
||||||
|
else rrd = 0;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DADD)
|
||||||
|
{
|
||||||
|
rrd = rrs + rrt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DADDU)
|
||||||
|
{
|
||||||
|
rrd = rrs + rrt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSUB)
|
||||||
|
{
|
||||||
|
rrd = rrs - rrt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSUBU)
|
||||||
|
{
|
||||||
|
rrd = rrs - rrt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(TEQ)
|
||||||
|
{
|
||||||
|
if (rrs == rrt)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "trap exception in TEQ");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSLL)
|
||||||
|
{
|
||||||
|
rrd = rrt << rsa;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSRL)
|
||||||
|
{
|
||||||
|
rrd = (unsigned long long)rrt >> rsa;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSRA)
|
||||||
|
{
|
||||||
|
rrd = rrt >> rsa;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSLL32)
|
||||||
|
{
|
||||||
|
rrd = rrt << (32+rsa);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSRL32)
|
||||||
|
{
|
||||||
|
rrd = (unsigned long long int)rrt >> (32+rsa);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(DSRA32)
|
||||||
|
{
|
||||||
|
rrd = (signed long long int)rrt >> (32+rsa);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Idle loop hack from 64th Note */
|
||||||
|
DECLARE_INSTRUCTION(BREAK)
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_COUNT_REG] = state->next_interupt;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
250
Frameworks/lazyusf/lazyusf/r4300/interpreter_tlb.def
Normal file
250
Frameworks/lazyusf/lazyusf/r4300/interpreter_tlb.def
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - interpreter_tlb.def *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 <zlib.h> // For adler32()
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(TLBR)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
index = state->g_cp0_regs[CP0_INDEX_REG] & 0x1F;
|
||||||
|
state->g_cp0_regs[CP0_PAGEMASK_REG] = state->tlb_e[index].mask << 13;
|
||||||
|
state->g_cp0_regs[CP0_ENTRYHI_REG] = ((state->tlb_e[index].vpn2 << 13) | state->tlb_e[index].asid);
|
||||||
|
state->g_cp0_regs[CP0_ENTRYLO0_REG] = (state->tlb_e[index].pfn_even << 6) | (state->tlb_e[index].c_even << 3)
|
||||||
|
| (state->tlb_e[index].d_even << 2) | (state->tlb_e[index].v_even << 1)
|
||||||
|
| state->tlb_e[index].g;
|
||||||
|
state->g_cp0_regs[CP0_ENTRYLO1_REG] = (state->tlb_e[index].pfn_odd << 6) | (state->tlb_e[index].c_odd << 3)
|
||||||
|
| (state->tlb_e[index].d_odd << 2) | (state->tlb_e[index].v_odd << 1)
|
||||||
|
| state->tlb_e[index].g;
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TLBWrite(usf_state_t * state, unsigned int idx)
|
||||||
|
{
|
||||||
|
if (state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
if (state->tlb_e[idx].v_even)
|
||||||
|
{
|
||||||
|
for (i=state->tlb_e[idx].start_even>>12; i<=state->tlb_e[idx].end_even>>12; i++)
|
||||||
|
{
|
||||||
|
if(!state->invalid_code[i] &&(state->invalid_code[state->tlb_LUT_r[i]>>12] ||
|
||||||
|
state->invalid_code[(state->tlb_LUT_r[i]>>12)+0x20000]))
|
||||||
|
state->invalid_code[i] = 1;
|
||||||
|
if (!state->invalid_code[i])
|
||||||
|
{
|
||||||
|
/*int j;
|
||||||
|
md5_state_t state;
|
||||||
|
md5_byte_t digest[16];
|
||||||
|
md5_init(&state);
|
||||||
|
md5_append(&state,
|
||||||
|
(const md5_byte_t*)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],
|
||||||
|
0x1000);
|
||||||
|
md5_finish(&state, digest);
|
||||||
|
for (j=0; j<16; j++) state->blocks[i]->md5[j] = digest[j];*/
|
||||||
|
|
||||||
|
state->blocks[i]->adler32 = adler32(0, (const unsigned char *)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4], 0x1000);
|
||||||
|
|
||||||
|
state->invalid_code[i] = 1;
|
||||||
|
}
|
||||||
|
else if (state->blocks[i])
|
||||||
|
{
|
||||||
|
/*int j;
|
||||||
|
for (j=0; j<16; j++) state->blocks[i]->md5[j] = 0;*/
|
||||||
|
state->blocks[i]->adler32 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state->tlb_e[idx].v_odd)
|
||||||
|
{
|
||||||
|
for (i=state->tlb_e[idx].start_odd>>12; i<=state->tlb_e[idx].end_odd>>12; i++)
|
||||||
|
{
|
||||||
|
if(!state->invalid_code[i] &&(state->invalid_code[state->tlb_LUT_r[i]>>12] ||
|
||||||
|
state->invalid_code[(state->tlb_LUT_r[i]>>12)+0x20000]))
|
||||||
|
state->invalid_code[i] = 1;
|
||||||
|
if (!state->invalid_code[i])
|
||||||
|
{
|
||||||
|
/*int j;
|
||||||
|
md5_state_t state;
|
||||||
|
md5_byte_t digest[16];
|
||||||
|
md5_init(&state);
|
||||||
|
md5_append(&state,
|
||||||
|
(const md5_byte_t*)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],
|
||||||
|
0x1000);
|
||||||
|
md5_finish(&state, digest);
|
||||||
|
for (j=0; j<16; j++) state->blocks[i]->md5[j] = digest[j];*/
|
||||||
|
|
||||||
|
state->blocks[i]->adler32 = adler32(0, (const unsigned char *)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4], 0x1000);
|
||||||
|
|
||||||
|
state->invalid_code[i] = 1;
|
||||||
|
}
|
||||||
|
else if (state->blocks[i])
|
||||||
|
{
|
||||||
|
/*int j;
|
||||||
|
for (j=0; j<16; j++) state->blocks[i]->md5[j] = 0;*/
|
||||||
|
state->blocks[i]->adler32 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tlb_unmap(state, &state->tlb_e[idx]);
|
||||||
|
|
||||||
|
state->tlb_e[idx].g = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & state->g_cp0_regs[CP0_ENTRYLO1_REG] & 1);
|
||||||
|
state->tlb_e[idx].pfn_even = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & 0x3FFFFFC0) >> 6;
|
||||||
|
state->tlb_e[idx].pfn_odd = (state->g_cp0_regs[CP0_ENTRYLO1_REG] & 0x3FFFFFC0) >> 6;
|
||||||
|
state->tlb_e[idx].c_even = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & 0x38) >> 3;
|
||||||
|
state->tlb_e[idx].c_odd = (state->g_cp0_regs[CP0_ENTRYLO1_REG] & 0x38) >> 3;
|
||||||
|
state->tlb_e[idx].d_even = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & 0x4) >> 2;
|
||||||
|
state->tlb_e[idx].d_odd = (state->g_cp0_regs[CP0_ENTRYLO1_REG] & 0x4) >> 2;
|
||||||
|
state->tlb_e[idx].v_even = (state->g_cp0_regs[CP0_ENTRYLO0_REG] & 0x2) >> 1;
|
||||||
|
state->tlb_e[idx].v_odd = (state->g_cp0_regs[CP0_ENTRYLO1_REG] & 0x2) >> 1;
|
||||||
|
state->tlb_e[idx].asid = (state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xFF);
|
||||||
|
state->tlb_e[idx].vpn2 = (state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xFFFFE000) >> 13;
|
||||||
|
//state->tlb_e[idx].r = (state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xC000000000000000LL) >> 62;
|
||||||
|
state->tlb_e[idx].mask = (state->g_cp0_regs[CP0_PAGEMASK_REG] & 0x1FFE000) >> 13;
|
||||||
|
|
||||||
|
state->tlb_e[idx].start_even = state->tlb_e[idx].vpn2 << 13;
|
||||||
|
state->tlb_e[idx].end_even = state->tlb_e[idx].start_even+
|
||||||
|
(state->tlb_e[idx].mask << 12) + 0xFFF;
|
||||||
|
state->tlb_e[idx].phys_even = state->tlb_e[idx].pfn_even << 12;
|
||||||
|
|
||||||
|
|
||||||
|
state->tlb_e[idx].start_odd = state->tlb_e[idx].end_even+1;
|
||||||
|
state->tlb_e[idx].end_odd = state->tlb_e[idx].start_odd+
|
||||||
|
(state->tlb_e[idx].mask << 12) + 0xFFF;
|
||||||
|
state->tlb_e[idx].phys_odd = state->tlb_e[idx].pfn_odd << 12;
|
||||||
|
|
||||||
|
tlb_map(state, &state->tlb_e[idx]);
|
||||||
|
|
||||||
|
if (state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
if (state->tlb_e[idx].v_even)
|
||||||
|
{
|
||||||
|
for (i=state->tlb_e[idx].start_even>>12; i<=state->tlb_e[idx].end_even>>12; i++)
|
||||||
|
{
|
||||||
|
/*if (state->blocks[i] && (state->blocks[i]->md5[0] || state->blocks[i]->md5[1] ||
|
||||||
|
state->blocks[i]->md5[2] || state->blocks[i]->md5[3]))
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
int equal = 1;
|
||||||
|
md5_state_t state;
|
||||||
|
md5_byte_t digest[16];
|
||||||
|
md5_init(&state);
|
||||||
|
md5_append(&state,
|
||||||
|
(const md5_byte_t*)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],
|
||||||
|
0x1000);
|
||||||
|
md5_finish(&state, digest);
|
||||||
|
for (j=0; j<16; j++)
|
||||||
|
if (digest[j] != state->blocks[i]->md5[j])
|
||||||
|
equal = 0;
|
||||||
|
if (equal) state->invalid_code[i] = 0;
|
||||||
|
}*/
|
||||||
|
if(state->blocks[i] && state->blocks[i]->adler32)
|
||||||
|
{
|
||||||
|
if(state->blocks[i]->adler32 == adler32(0,(const unsigned char *)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],0x1000))
|
||||||
|
state->invalid_code[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->tlb_e[idx].v_odd)
|
||||||
|
{
|
||||||
|
for (i=state->tlb_e[idx].start_odd>>12; i<=state->tlb_e[idx].end_odd>>12; i++)
|
||||||
|
{
|
||||||
|
/*if (state->blocks[i] && (state->blocks[i]->md5[0] || state->blocks[i]->md5[1] ||
|
||||||
|
state->blocks[i]->md5[2] || state->blocks[i]->md5[3]))
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
int equal = 1;
|
||||||
|
md5_state_t state;
|
||||||
|
md5_byte_t digest[16];
|
||||||
|
md5_init(&state);
|
||||||
|
md5_append(&state,
|
||||||
|
(const md5_byte_t*)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],
|
||||||
|
0x1000);
|
||||||
|
md5_finish(&state, digest);
|
||||||
|
for (j=0; j<16; j++)
|
||||||
|
if (digest[j] != state->blocks[i]->md5[j])
|
||||||
|
equal = 0;
|
||||||
|
if (equal) state->invalid_code[i] = 0;
|
||||||
|
}*/
|
||||||
|
if(state->blocks[i] && state->blocks[i]->adler32)
|
||||||
|
{
|
||||||
|
if(state->blocks[i]->adler32 == adler32(0,(const unsigned char *)&state->g_rdram[(state->tlb_LUT_r[i]&0x7FF000)/4],0x1000))
|
||||||
|
state->invalid_code[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(TLBWI)
|
||||||
|
{
|
||||||
|
TLBWrite(state, state->g_cp0_regs[CP0_INDEX_REG]&0x3F);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(TLBWR)
|
||||||
|
{
|
||||||
|
update_count(state);
|
||||||
|
state->g_cp0_regs[CP0_RANDOM_REG] = (state->g_cp0_regs[CP0_COUNT_REG]/2 % (32 - state->g_cp0_regs[CP0_WIRED_REG]))
|
||||||
|
+ state->g_cp0_regs[CP0_WIRED_REG];
|
||||||
|
TLBWrite(state, state->g_cp0_regs[CP0_RANDOM_REG]);
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(TLBP)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
state->g_cp0_regs[CP0_INDEX_REG] |= 0x80000000;
|
||||||
|
for (i=0; i<32; i++)
|
||||||
|
{
|
||||||
|
if (((state->tlb_e[i].vpn2 & (~state->tlb_e[i].mask)) ==
|
||||||
|
(((state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xFFFFE000) >> 13) & (~state->tlb_e[i].mask))) &&
|
||||||
|
((state->tlb_e[i].g) ||
|
||||||
|
(state->tlb_e[i].asid == (state->g_cp0_regs[CP0_ENTRYHI_REG] & 0xFF))))
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_INDEX_REG] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ADD_TO_PC(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_INSTRUCTION(ERET)
|
||||||
|
{
|
||||||
|
update_count(state);
|
||||||
|
if (state->g_cp0_regs[CP0_STATUS_REG] & 0x4)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "error in ERET");
|
||||||
|
state->stop=1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_STATUS_REG] &= ~0x2;
|
||||||
|
generic_jump_to(state, state->g_cp0_regs[CP0_EPC_REG]);
|
||||||
|
}
|
||||||
|
state->llbit = 0;
|
||||||
|
check_interupt(state);
|
||||||
|
state->last_addr = PCADDR;
|
||||||
|
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state);
|
||||||
|
}
|
601
Frameworks/lazyusf/lazyusf/r4300/interupt.c
Normal file
601
Frameworks/lazyusf/lazyusf/r4300/interupt.c
Normal file
|
@ -0,0 +1,601 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - interupt.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#define M64P_CORE_PROTOTYPES 1
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "interupt.h"
|
||||||
|
#include "cached_interp.h"
|
||||||
|
#include "cp0.h"
|
||||||
|
#include "exception.h"
|
||||||
|
#include "new_dynarec/new_dynarec.h"
|
||||||
|
#include "r4300.h"
|
||||||
|
#include "r4300_core.h"
|
||||||
|
#include "reset.h"
|
||||||
|
|
||||||
|
#include "ai/ai_controller.h"
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
#include "main/main.h"
|
||||||
|
#include "main/savestates.h"
|
||||||
|
#include "pi/pi_controller.h"
|
||||||
|
#include "rdp/rdp_core.h"
|
||||||
|
#include "rsp/rsp_core.h"
|
||||||
|
#include "si/si_controller.h"
|
||||||
|
#include "vi/vi_controller.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Pool of Single Linked List Nodes
|
||||||
|
**************************************************************************/
|
||||||
|
#ifndef INTERUPT_STRUCTS
|
||||||
|
#define INTERUPT_STRUCTS
|
||||||
|
#define POOL_CAPACITY 16
|
||||||
|
|
||||||
|
struct interrupt_event
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
unsigned int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct node
|
||||||
|
{
|
||||||
|
struct interrupt_event data;
|
||||||
|
struct node *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pool
|
||||||
|
{
|
||||||
|
struct node nodes[POOL_CAPACITY];
|
||||||
|
struct node* stack[POOL_CAPACITY];
|
||||||
|
size_t index;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct interrupt_queue
|
||||||
|
{
|
||||||
|
struct pool pool;
|
||||||
|
struct node* first;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct node* alloc_node(struct pool* p);
|
||||||
|
static void free_node(struct pool* p, struct node* node);
|
||||||
|
static void clear_pool(struct pool* p);
|
||||||
|
|
||||||
|
|
||||||
|
/* node allocation/deallocation on a given pool */
|
||||||
|
static struct node* alloc_node(struct pool* p)
|
||||||
|
{
|
||||||
|
/* return NULL if pool is too small */
|
||||||
|
if (p->index >= POOL_CAPACITY)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return p->stack[p->index++];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_node(struct pool* p, struct node* node)
|
||||||
|
{
|
||||||
|
if (p->index == 0 || node == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
p->stack[--p->index] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release all nodes */
|
||||||
|
static void clear_pool(struct pool* p)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < POOL_CAPACITY; ++i)
|
||||||
|
p->stack[i] = &p->nodes[i];
|
||||||
|
|
||||||
|
p->index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Interrupt Queue
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
static void clear_queue(usf_state_t * state)
|
||||||
|
{
|
||||||
|
state->q.first = NULL;
|
||||||
|
clear_pool(&state->q.pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int before_event(usf_state_t * state, unsigned int evt1, unsigned int evt2, int type2)
|
||||||
|
{
|
||||||
|
if(evt1 - state->g_cp0_regs[CP0_COUNT_REG] < 0x80000000)
|
||||||
|
{
|
||||||
|
if(evt2 - state->g_cp0_regs[CP0_COUNT_REG] < 0x80000000)
|
||||||
|
{
|
||||||
|
if((evt1 - state->g_cp0_regs[CP0_COUNT_REG]) < (evt2 - state->g_cp0_regs[CP0_COUNT_REG])) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if((state->g_cp0_regs[CP0_COUNT_REG] - evt2) < 0x10000000)
|
||||||
|
{
|
||||||
|
switch(type2)
|
||||||
|
{
|
||||||
|
case SPECIAL_INT:
|
||||||
|
if(state->SPECIAL_done) return 1;
|
||||||
|
else return 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_interupt_event(usf_state_t * state, int type, unsigned int delay)
|
||||||
|
{
|
||||||
|
add_interupt_event_count(state, type, state->g_cp0_regs[CP0_COUNT_REG] + delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_interupt_event_count(usf_state_t * state, int type, unsigned int count)
|
||||||
|
{
|
||||||
|
struct node* event;
|
||||||
|
struct node* e;
|
||||||
|
int special;
|
||||||
|
|
||||||
|
special = (type == SPECIAL_INT);
|
||||||
|
|
||||||
|
if(state->g_cp0_regs[CP0_COUNT_REG] > 0x80000000) state->SPECIAL_done = 0;
|
||||||
|
|
||||||
|
if (get_event(state, type)) {
|
||||||
|
DebugMessage(state, M64MSG_WARNING, "two events of type 0x%x in interrupt queue", type);
|
||||||
|
/* FIXME: hack-fix for freezing in Perfect Dark
|
||||||
|
* http://code.google.com/p/mupen64plus/issues/detail?id=553
|
||||||
|
* https://github.com/mupen64plus-ae/mupen64plus-ae/commit/802d8f81d46705d64694d7a34010dc5f35787c7d
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event = alloc_node(&state->q.pool);
|
||||||
|
if (event == NULL)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Failed to allocate node for new interrupt event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->data.count = count;
|
||||||
|
event->data.type = type;
|
||||||
|
|
||||||
|
if (state->q.first == NULL)
|
||||||
|
{
|
||||||
|
state->q.first = event;
|
||||||
|
event->next = NULL;
|
||||||
|
state->next_interupt = state->q.first->data.count;
|
||||||
|
}
|
||||||
|
else if (before_event(state, count, state->q.first->data.count, state->q.first->data.type) && !special)
|
||||||
|
{
|
||||||
|
event->next = state->q.first;
|
||||||
|
state->q.first = event;
|
||||||
|
state->next_interupt = state->q.first->data.count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(e = state->q.first;
|
||||||
|
e->next != NULL &&
|
||||||
|
(!before_event(state, count, e->next->data.count, e->next->data.type) || special);
|
||||||
|
e = e->next);
|
||||||
|
|
||||||
|
if (e->next == NULL)
|
||||||
|
{
|
||||||
|
e->next = event;
|
||||||
|
event->next = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!special)
|
||||||
|
for(; e->next != NULL && e->next->data.count == count; e = e->next);
|
||||||
|
|
||||||
|
event->next = e->next;
|
||||||
|
e->next = event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_interupt_event(usf_state_t * state)
|
||||||
|
{
|
||||||
|
struct node* e;
|
||||||
|
|
||||||
|
e = state->q.first;
|
||||||
|
state->q.first = e->next;
|
||||||
|
free_node(&state->q.pool, e);
|
||||||
|
|
||||||
|
state->next_interupt = (state->q.first != NULL
|
||||||
|
&& (state->q.first->data.count > state->g_cp0_regs[CP0_COUNT_REG]
|
||||||
|
|| (state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count) < 0x80000000))
|
||||||
|
? state->q.first->data.count
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int get_event(usf_state_t * state, int type)
|
||||||
|
{
|
||||||
|
struct node* e = state->q.first;
|
||||||
|
|
||||||
|
if (e == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (e->data.type == type)
|
||||||
|
return e->data.count;
|
||||||
|
|
||||||
|
for(; e->next != NULL && e->next->data.type != type; e = e->next);
|
||||||
|
|
||||||
|
return (e->next != NULL)
|
||||||
|
? e->next->data.count
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_next_event_type(usf_state_t * state)
|
||||||
|
{
|
||||||
|
return (state->q.first == NULL)
|
||||||
|
? 0
|
||||||
|
: state->q.first->data.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_event(usf_state_t * state, int type)
|
||||||
|
{
|
||||||
|
struct node* to_del;
|
||||||
|
struct node* e = state->q.first;
|
||||||
|
|
||||||
|
if (e == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (e->data.type == type)
|
||||||
|
{
|
||||||
|
state->q.first = e->next;
|
||||||
|
free_node(&state->q.pool, e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(; e->next != NULL && e->next->data.type != type; e = e->next);
|
||||||
|
|
||||||
|
if (e->next != NULL)
|
||||||
|
{
|
||||||
|
to_del = e->next;
|
||||||
|
e->next = to_del->next;
|
||||||
|
free_node(&state->q.pool, to_del);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void translate_event_queue(usf_state_t * state, unsigned int base)
|
||||||
|
{
|
||||||
|
struct node* e;
|
||||||
|
|
||||||
|
remove_event(state, COMPARE_INT);
|
||||||
|
remove_event(state, SPECIAL_INT);
|
||||||
|
|
||||||
|
for(e = state->q.first; e != NULL; e = e->next)
|
||||||
|
{
|
||||||
|
e->data.count = (e->data.count - state->g_cp0_regs[CP0_COUNT_REG]) + base;
|
||||||
|
}
|
||||||
|
add_interupt_event_count(state, COMPARE_INT, state->g_cp0_regs[CP0_COMPARE_REG]);
|
||||||
|
add_interupt_event_count(state, SPECIAL_INT, 0);
|
||||||
|
|
||||||
|
r4300_reset_checkpoint(state, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
int save_eventqueue_infos(usf_state_t * state, char *buf)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
struct node* e;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
for(e = state->q.first; e != NULL; e = e->next)
|
||||||
|
{
|
||||||
|
memcpy(buf + len , &e->data.type , 4);
|
||||||
|
memcpy(buf + len + 4, &e->data.count, 4);
|
||||||
|
len += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
*((unsigned int*)&buf[len]) = 0xFFFFFFFF;
|
||||||
|
return len+4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_eventqueue_infos(usf_state_t * state, char *buf)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
clear_queue(state);
|
||||||
|
while (*((unsigned int*)&buf[len]) != 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
int type = *((unsigned int*)&buf[len]);
|
||||||
|
unsigned int count = *((unsigned int*)&buf[len+4]);
|
||||||
|
add_interupt_event_count(state, type, count);
|
||||||
|
len += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_interupt(usf_state_t * state)
|
||||||
|
{
|
||||||
|
state->SPECIAL_done = 1;
|
||||||
|
|
||||||
|
state->g_vi.delay = state->g_vi.next_vi = 5000;
|
||||||
|
|
||||||
|
clear_queue(state);
|
||||||
|
add_interupt_event_count(state, VI_INT, state->g_vi.next_vi);
|
||||||
|
add_interupt_event_count(state, SPECIAL_INT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_interupt(usf_state_t * state)
|
||||||
|
{
|
||||||
|
struct node* event;
|
||||||
|
|
||||||
|
state->g_r4300.mi.regs[MI_INTR_REG] &= ~MI_INTR_AI;
|
||||||
|
state->g_r4300.mi.regs[MI_INTR_REG] |= state->g_r4300.mi.AudioIntrReg & MI_INTR_AI;
|
||||||
|
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
if (state->g_r4300.mi.regs[MI_INTR_REG])
|
||||||
|
fprintf(state->debug_log, "Interrupt %d - ", state->g_r4300.mi.regs[MI_INTR_REG]);
|
||||||
|
#endif
|
||||||
|
if (state->g_r4300.mi.regs[MI_INTR_REG] & state->g_r4300.mi.regs[MI_INTR_MASK_REG])
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
fprintf(state->debug_log, "triggered\n");
|
||||||
|
#endif
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] = (state->g_cp0_regs[CP0_CAUSE_REG] | 0x400) & 0xFFFFFF83;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
if (state->g_r4300.mi.regs[MI_INTR_REG])
|
||||||
|
fprintf(state->debug_log, "masked\n");
|
||||||
|
#endif
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] &= ~0x400;
|
||||||
|
}
|
||||||
|
if ((state->g_cp0_regs[CP0_STATUS_REG] & 7) != 1) return;
|
||||||
|
if (state->g_cp0_regs[CP0_STATUS_REG] & state->g_cp0_regs[CP0_CAUSE_REG] & 0xFF00)
|
||||||
|
{
|
||||||
|
event = alloc_node(&state->q.pool);
|
||||||
|
|
||||||
|
if (event == NULL)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Failed to allocate node for new interrupt event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event->data.count = state->next_interupt = state->g_cp0_regs[CP0_COUNT_REG];
|
||||||
|
event->data.type = CHECK_INT;
|
||||||
|
|
||||||
|
if (state->q.first == NULL)
|
||||||
|
{
|
||||||
|
state->q.first = event;
|
||||||
|
event->next = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event->next = state->q.first;
|
||||||
|
state->q.first = event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wrapped_exception_general(usf_state_t * state)
|
||||||
|
{
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
if (r4300emu == CORE_DYNAREC) {
|
||||||
|
state->g_cp0_regs[CP0_EPC_REG] = pcaddr;
|
||||||
|
state->pcaddr = 0x80000180;
|
||||||
|
state->g_cp0_regs[CP0_STATUS_REG] |= 2;
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] &= 0x7FFFFFFF;
|
||||||
|
state->pending_exception=1;
|
||||||
|
} else {
|
||||||
|
exception_general(state);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
exception_general(state);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void raise_maskable_interrupt(usf_state_t * state, uint32_t cause)
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] = (state->g_cp0_regs[CP0_CAUSE_REG] | cause) & 0xffffff83;
|
||||||
|
|
||||||
|
if (!(state->g_cp0_regs[CP0_STATUS_REG] & state->g_cp0_regs[CP0_CAUSE_REG] & 0xff00))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((state->g_cp0_regs[CP0_STATUS_REG] & 7) != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wrapped_exception_general(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void special_int_handler(usf_state_t * state)
|
||||||
|
{
|
||||||
|
if (state->g_cp0_regs[CP0_COUNT_REG] > 0x10000000)
|
||||||
|
return;
|
||||||
|
|
||||||
|
state->SPECIAL_done = 1;
|
||||||
|
remove_interupt_event(state);
|
||||||
|
add_interupt_event_count(state, SPECIAL_INT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compare_int_handler(usf_state_t * state)
|
||||||
|
{
|
||||||
|
remove_interupt_event(state);
|
||||||
|
state->g_cp0_regs[CP0_COUNT_REG]+=state->count_per_op;
|
||||||
|
add_interupt_event_count(state, COMPARE_INT, state->g_cp0_regs[CP0_COMPARE_REG]);
|
||||||
|
state->g_cp0_regs[CP0_COUNT_REG]-=state->count_per_op;
|
||||||
|
|
||||||
|
if (state->enablecompare)
|
||||||
|
raise_maskable_interrupt(state, 0x8000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hw2_int_handler(usf_state_t * state)
|
||||||
|
{
|
||||||
|
// Hardware Interrupt 2 -- remove interrupt event from queue
|
||||||
|
remove_interupt_event(state);
|
||||||
|
|
||||||
|
state->g_cp0_regs[CP0_STATUS_REG] = (state->g_cp0_regs[CP0_STATUS_REG] & ~0x00380000) | 0x1000;
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] = (state->g_cp0_regs[CP0_CAUSE_REG] | 0x1000) & 0xffffff83;
|
||||||
|
|
||||||
|
wrapped_exception_general(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nmi_int_handler(usf_state_t * state)
|
||||||
|
{
|
||||||
|
// Non Maskable Interrupt -- remove interrupt event from queue
|
||||||
|
remove_interupt_event(state);
|
||||||
|
// setup r4300 Status flags: reset TS and SR, set BEV, ERL, and SR
|
||||||
|
state->g_cp0_regs[CP0_STATUS_REG] = (state->g_cp0_regs[CP0_STATUS_REG] & ~0x00380000) | 0x00500004;
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] = 0x00000000;
|
||||||
|
// simulate the soft reset code which would run from the PIF ROM
|
||||||
|
r4300_reset_soft(state);
|
||||||
|
// clear all interrupts, reset interrupt counters back to 0
|
||||||
|
state->g_cp0_regs[CP0_COUNT_REG] = 0;
|
||||||
|
state->g_gs_vi_counter = 0;
|
||||||
|
init_interupt(state);
|
||||||
|
// clear the audio status register so that subsequent write_ai() calls will work properly
|
||||||
|
state->g_ai.regs[AI_STATUS_REG] = 0;
|
||||||
|
// set ErrorEPC with the last instruction address
|
||||||
|
state->g_cp0_regs[CP0_ERROREPC_REG] = state->PC->addr;
|
||||||
|
// reset the r4300 internal state
|
||||||
|
if (state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
// clear all the compiled instruction blocks and re-initialize
|
||||||
|
free_blocks(state);
|
||||||
|
init_blocks(state);
|
||||||
|
}
|
||||||
|
// adjust ErrorEPC if we were in a delay slot, and clear the delay_slot and dyna_interp flags
|
||||||
|
if(state->delay_slot==1 || state->delay_slot==3)
|
||||||
|
{
|
||||||
|
state->g_cp0_regs[CP0_ERROREPC_REG]-=4;
|
||||||
|
}
|
||||||
|
state->delay_slot = 0;
|
||||||
|
state->dyna_interp = 0;
|
||||||
|
// set next instruction address to reset vector
|
||||||
|
state->last_addr = 0xa4000040;
|
||||||
|
generic_jump_to(state, 0xa4000040);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void osal_fastcall gen_interupt(usf_state_t * state)
|
||||||
|
{
|
||||||
|
r4300_checkpoint(state);
|
||||||
|
|
||||||
|
if (state->stop == 1)
|
||||||
|
{
|
||||||
|
state->g_gs_vi_counter = 0; // debug
|
||||||
|
dyna_stop(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state->interupt_unsafe_state)
|
||||||
|
{
|
||||||
|
if (state->reset_hard_job)
|
||||||
|
{
|
||||||
|
reset_hard(state);
|
||||||
|
state->reset_hard_job = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->skip_jump)
|
||||||
|
{
|
||||||
|
unsigned int dest = state->skip_jump;
|
||||||
|
state->skip_jump = 0;
|
||||||
|
|
||||||
|
state->next_interupt = (state->q.first->data.count > state->g_cp0_regs[CP0_COUNT_REG]
|
||||||
|
|| (state->g_cp0_regs[CP0_COUNT_REG] - state->q.first->data.count) < 0x80000000)
|
||||||
|
? state->q.first->data.count
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
state->last_addr = dest;
|
||||||
|
generic_jump_to(state, dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(state->q.first->data.type)
|
||||||
|
{
|
||||||
|
case SPECIAL_INT:
|
||||||
|
special_int_handler(state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VI_INT:
|
||||||
|
remove_interupt_event(state);
|
||||||
|
vi_vertical_interrupt_event(&state->g_vi);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COMPARE_INT:
|
||||||
|
compare_int_handler(state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHECK_INT:
|
||||||
|
remove_interupt_event(state);
|
||||||
|
wrapped_exception_general(state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SI_INT:
|
||||||
|
remove_interupt_event(state);
|
||||||
|
si_end_of_dma_event(&state->g_si);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PI_INT:
|
||||||
|
remove_interupt_event(state);
|
||||||
|
pi_end_of_dma_event(&state->g_pi);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AI_INT:
|
||||||
|
remove_interupt_event(state);
|
||||||
|
ai_end_of_dma_event(&state->g_ai);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SP_INT:
|
||||||
|
remove_interupt_event(state);
|
||||||
|
rsp_interrupt_event(&state->g_sp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DP_INT:
|
||||||
|
remove_interupt_event(state);
|
||||||
|
rdp_interrupt_event(&state->g_dp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HW2_INT:
|
||||||
|
hw2_int_handler(state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NMI_INT:
|
||||||
|
nmi_int_handler(state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DebugMessage(state, M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", state->q.first->data.type);
|
||||||
|
remove_interupt_event(state);
|
||||||
|
wrapped_exception_general(state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
60
Frameworks/lazyusf/lazyusf/r4300/interupt.h
Normal file
60
Frameworks/lazyusf/lazyusf/r4300/interupt.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - interupt.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_INTERUPT_H
|
||||||
|
#define M64P_R4300_INTERUPT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
void init_interupt(usf_state_t *);
|
||||||
|
|
||||||
|
// set to avoid savestates/reset if state may be inconsistent
|
||||||
|
// (e.g. in the middle of an instruction)
|
||||||
|
void raise_maskable_interrupt(usf_state_t *, uint32_t cause);
|
||||||
|
|
||||||
|
void osal_fastcall gen_interupt(usf_state_t *);
|
||||||
|
void check_interupt(usf_state_t *);
|
||||||
|
|
||||||
|
void translate_event_queue(usf_state_t *, unsigned int base);
|
||||||
|
void remove_event(usf_state_t *, int type);
|
||||||
|
void add_interupt_event_count(usf_state_t *, int type, unsigned int count);
|
||||||
|
void add_interupt_event(usf_state_t *, int type, unsigned int delay);
|
||||||
|
unsigned int get_event(usf_state_t *, int type);
|
||||||
|
int get_next_event_type(usf_state_t *);
|
||||||
|
|
||||||
|
int save_eventqueue_infos(usf_state_t *, char *buf);
|
||||||
|
void load_eventqueue_infos(usf_state_t *, char *buf);
|
||||||
|
|
||||||
|
#define VI_INT 0x001
|
||||||
|
#define COMPARE_INT 0x002
|
||||||
|
#define CHECK_INT 0x004
|
||||||
|
#define SI_INT 0x008
|
||||||
|
#define PI_INT 0x010
|
||||||
|
#define SPECIAL_INT 0x020
|
||||||
|
#define AI_INT 0x040
|
||||||
|
#define SP_INT 0x080
|
||||||
|
#define DP_INT 0x100
|
||||||
|
#define HW2_INT 0x200
|
||||||
|
#define NMI_INT 0x400
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_INTERUPT_H */
|
63
Frameworks/lazyusf/lazyusf/r4300/macros.h
Normal file
63
Frameworks/lazyusf/lazyusf/r4300/macros.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - macros.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_MACROS_H
|
||||||
|
#define M64P_R4300_MACROS_H
|
||||||
|
|
||||||
|
#define sign_extended(a) a = (long long)((int)a)
|
||||||
|
#define sign_extendedb(a) a = (long long)((signed char)a)
|
||||||
|
#define sign_extendedh(a) a = (long long)((short)a)
|
||||||
|
|
||||||
|
#define rrt *state->PC->f.r.rt
|
||||||
|
#define rrd *state->PC->f.r.rd
|
||||||
|
#define rfs state->PC->f.r.nrd
|
||||||
|
#define rrs *state->PC->f.r.rs
|
||||||
|
#define rsa state->PC->f.r.sa
|
||||||
|
#define irt *state->PC->f.i.rt
|
||||||
|
#define ioffset state->PC->f.i.immediate
|
||||||
|
#define iimmediate state->PC->f.i.immediate
|
||||||
|
#define irs *state->PC->f.i.rs
|
||||||
|
#define ibase *state->PC->f.i.rs
|
||||||
|
#define jinst_index state->PC->f.j.inst_index
|
||||||
|
#define lfbase state->PC->f.lf.base
|
||||||
|
#define lfft state->PC->f.lf.ft
|
||||||
|
#define lfoffset state->PC->f.lf.offset
|
||||||
|
#define cfft state->PC->f.cf.ft
|
||||||
|
#define cffs state->PC->f.cf.fs
|
||||||
|
#define cffd state->PC->f.cf.fd
|
||||||
|
|
||||||
|
// 32 bits macros
|
||||||
|
#ifndef M64P_BIG_ENDIAN
|
||||||
|
#define rrt32 *((int*)state->PC->f.r.rt)
|
||||||
|
#define rrd32 *((int*)state->PC->f.r.rd)
|
||||||
|
#define rrs32 *((int*)state->PC->f.r.rs)
|
||||||
|
#define irs32 *((int*)state->PC->f.i.rs)
|
||||||
|
#define irt32 *((int*)state->PC->f.i.rt)
|
||||||
|
#else
|
||||||
|
#define rrt32 *((int*)state->PC->f.r.rt+1)
|
||||||
|
#define rrd32 *((int*)state->PC->f.r.rd+1)
|
||||||
|
#define rrs32 *((int*)state->PC->f.r.rs+1)
|
||||||
|
#define irs32 *((int*)state->PC->f.i.rs+1)
|
||||||
|
#define irt32 *((int*)state->PC->f.i.rt+1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_MACROS_H */
|
||||||
|
|
136
Frameworks/lazyusf/lazyusf/r4300/mi_controller.c
Normal file
136
Frameworks/lazyusf/lazyusf/r4300/mi_controller.c
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - mi_controller.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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 "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "mi_controller.h"
|
||||||
|
#include "r4300.h"
|
||||||
|
#include "r4300_core.h"
|
||||||
|
#include "cp0.h"
|
||||||
|
#include "interupt.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int update_mi_init_mode(uint32_t* mi_init_mode, uint32_t w)
|
||||||
|
{
|
||||||
|
int clear_dp = 0;
|
||||||
|
|
||||||
|
/* set init_length */
|
||||||
|
*mi_init_mode &= ~0x7f;
|
||||||
|
*mi_init_mode |= w & 0x7f;
|
||||||
|
/* clear / set init_mode */
|
||||||
|
if (w & 0x80) *mi_init_mode &= ~0x80;
|
||||||
|
if (w & 0x100) *mi_init_mode |= 0x80;
|
||||||
|
/* clear / set ebus test_mode */
|
||||||
|
if (w & 0x200) *mi_init_mode &= ~0x100;
|
||||||
|
if (w & 0x400) *mi_init_mode |= 0x100;
|
||||||
|
/* clear DP interrupt */
|
||||||
|
if (w & 0x800) clear_dp = 1;
|
||||||
|
/* clear / set RDRAM reg_mode */
|
||||||
|
if (w & 0x1000) *mi_init_mode &= ~0x200;
|
||||||
|
if (w & 0x2000) *mi_init_mode |= 0x200;
|
||||||
|
|
||||||
|
return clear_dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_mi_intr_mask(uint32_t* mi_intr_mask, uint32_t w)
|
||||||
|
{
|
||||||
|
if (w & 0x1) *mi_intr_mask &= ~0x1; // clear SP mask
|
||||||
|
if (w & 0x2) *mi_intr_mask |= 0x1; // set SP mask
|
||||||
|
if (w & 0x4) *mi_intr_mask &= ~0x2; // clear SI mask
|
||||||
|
if (w & 0x8) *mi_intr_mask |= 0x2; // set SI mask
|
||||||
|
if (w & 0x10) *mi_intr_mask &= ~0x4; // clear AI mask
|
||||||
|
if (w & 0x20) *mi_intr_mask |= 0x4; // set AI mask
|
||||||
|
if (w & 0x40) *mi_intr_mask &= ~0x8; // clear VI mask
|
||||||
|
if (w & 0x80) *mi_intr_mask |= 0x8; // set VI mask
|
||||||
|
if (w & 0x100) *mi_intr_mask &= ~0x10; // clear PI mask
|
||||||
|
if (w & 0x200) *mi_intr_mask |= 0x10; // set PI mask
|
||||||
|
if (w & 0x400) *mi_intr_mask &= ~0x20; // clear DP mask
|
||||||
|
if (w & 0x800) *mi_intr_mask |= 0x20; // set DP mask
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_mi(struct mi_controller* mi)
|
||||||
|
{
|
||||||
|
memset(mi->regs, 0, MI_REGS_COUNT*sizeof(uint32_t));
|
||||||
|
mi->regs[MI_VERSION_REG] = 0x02020102;
|
||||||
|
mi->AudioIntrReg = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_mi_regs(void* opaque, uint32_t address, uint32_t* value)
|
||||||
|
{
|
||||||
|
struct r4300_core* r4300 = (struct r4300_core*)opaque;
|
||||||
|
uint32_t reg = mi_reg(address);
|
||||||
|
|
||||||
|
*value = r4300->mi.regs[reg];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_mi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
|
||||||
|
{
|
||||||
|
struct r4300_core* r4300 = (struct r4300_core*)opaque;
|
||||||
|
uint32_t reg = mi_reg(address);
|
||||||
|
|
||||||
|
switch(reg)
|
||||||
|
{
|
||||||
|
case MI_INIT_MODE_REG:
|
||||||
|
if (update_mi_init_mode(&r4300->mi.regs[MI_INIT_MODE_REG], value & mask) != 0)
|
||||||
|
{
|
||||||
|
clear_rcp_interrupt(r4300, MI_INTR_DP);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MI_INTR_MASK_REG:
|
||||||
|
update_mi_intr_mask(&r4300->mi.regs[MI_INTR_MASK_REG], value & mask);
|
||||||
|
|
||||||
|
check_interupt(r4300->state);
|
||||||
|
update_count(r4300->state);
|
||||||
|
if (r4300->state->next_interupt <= r4300->state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(r4300->state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* interrupt execution is immediate (if not masked) */
|
||||||
|
void raise_rcp_interrupt(struct r4300_core* r4300, uint32_t mi_intr)
|
||||||
|
{
|
||||||
|
r4300->mi.regs[MI_INTR_REG] |= mi_intr;
|
||||||
|
|
||||||
|
if (r4300->mi.regs[MI_INTR_REG] & r4300->mi.regs[MI_INTR_MASK_REG])
|
||||||
|
raise_maskable_interrupt(r4300->state, 0x400);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* interrupt execution is scheduled (if not masked) */
|
||||||
|
void signal_rcp_interrupt(struct r4300_core* r4300, uint32_t mi_intr)
|
||||||
|
{
|
||||||
|
r4300->mi.regs[MI_INTR_REG] |= mi_intr;
|
||||||
|
check_interupt(r4300->state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_rcp_interrupt(struct r4300_core* r4300, uint32_t mi_intr)
|
||||||
|
{
|
||||||
|
r4300->mi.regs[MI_INTR_REG] &= ~mi_intr;
|
||||||
|
check_interupt(r4300->state);
|
||||||
|
}
|
||||||
|
|
71
Frameworks/lazyusf/lazyusf/r4300/mi_controller.h
Normal file
71
Frameworks/lazyusf/lazyusf/r4300/mi_controller.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - mi_controller.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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_R4300_MI_CONTROLLER_H
|
||||||
|
#define M64P_R4300_MI_CONTROLLER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct r4300_core;
|
||||||
|
|
||||||
|
enum mi_registers
|
||||||
|
{
|
||||||
|
MI_INIT_MODE_REG,
|
||||||
|
MI_VERSION_REG,
|
||||||
|
MI_INTR_REG,
|
||||||
|
MI_INTR_MASK_REG,
|
||||||
|
MI_REGS_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum mi_intr
|
||||||
|
{
|
||||||
|
MI_INTR_SP = 0x01,
|
||||||
|
MI_INTR_SI = 0x02,
|
||||||
|
MI_INTR_AI = 0x04,
|
||||||
|
MI_INTR_VI = 0x08,
|
||||||
|
MI_INTR_PI = 0x10,
|
||||||
|
MI_INTR_DP = 0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mi_controller
|
||||||
|
{
|
||||||
|
uint32_t regs[MI_REGS_COUNT];
|
||||||
|
uint32_t AudioIntrReg;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
static osal_inline uint32_t mi_reg(uint32_t address)
|
||||||
|
{
|
||||||
|
return (address & 0xffff) >> 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_mi(struct mi_controller* mi);
|
||||||
|
|
||||||
|
int read_mi_regs(void* opaque, uint32_t address, uint32_t* value);
|
||||||
|
int write_mi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask);
|
||||||
|
|
||||||
|
void raise_rcp_interrupt(struct r4300_core* r4300, uint32_t mi_intr);
|
||||||
|
void signal_rcp_interrupt(struct r4300_core* r4300, uint32_t mi_intr);
|
||||||
|
void clear_rcp_interrupt(struct r4300_core* r4300, uint32_t mi_intr);
|
||||||
|
|
||||||
|
#endif
|
4575
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/assem_arm.c
Normal file
4575
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/assem_arm.c
Normal file
File diff suppressed because it is too large
Load diff
48
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/assem_arm.h
Normal file
48
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/assem_arm.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef M64P_R4300_ASSEM_ARM_H
|
||||||
|
#define M64P_R4300_ASSEM_ARM_H
|
||||||
|
|
||||||
|
#define HOST_REGS 13
|
||||||
|
#define HOST_CCREG 10
|
||||||
|
#define HOST_BTREG 8
|
||||||
|
#define EXCLUDE_REG 11
|
||||||
|
|
||||||
|
#define HOST_IMM8 1
|
||||||
|
#define HAVE_CMOV_IMM 1
|
||||||
|
#define CORTEX_A8_BRANCH_PREDICTION_HACK 1
|
||||||
|
#define USE_MINI_HT 1
|
||||||
|
//#define REG_PREFETCH 1
|
||||||
|
#define HAVE_CONDITIONAL_CALL 1
|
||||||
|
#define RAM_OFFSET 1
|
||||||
|
|
||||||
|
/* ARM calling convention:
|
||||||
|
r0-r3, r12: caller-save
|
||||||
|
r4-r11: callee-save */
|
||||||
|
|
||||||
|
#define ARG1_REG 0
|
||||||
|
#define ARG2_REG 1
|
||||||
|
#define ARG3_REG 2
|
||||||
|
#define ARG4_REG 3
|
||||||
|
|
||||||
|
/* GCC register naming convention:
|
||||||
|
r10 = sl (base)
|
||||||
|
r11 = fp (frame pointer)
|
||||||
|
r12 = ip (scratch)
|
||||||
|
r13 = sp (stack pointer)
|
||||||
|
r14 = lr (link register)
|
||||||
|
r15 = pc (program counter) */
|
||||||
|
|
||||||
|
#define FP 11
|
||||||
|
#define LR 14
|
||||||
|
#define HOST_TEMPREG 14
|
||||||
|
|
||||||
|
// Note: FP is set to &dynarec_local when executing generated code.
|
||||||
|
// Thus the local variables are actually global and not on the stack.
|
||||||
|
|
||||||
|
extern char *invc_ptr;
|
||||||
|
extern char extra_memory[33554432];
|
||||||
|
|
||||||
|
#define BASE_ADDR ((int)(&extra_memory))
|
||||||
|
//#define TARGET_SIZE_2 24 // 2^24 = 16 megabytes
|
||||||
|
#define TARGET_SIZE_2 25 // 2^25 = 32 megabytes
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_ASSEM_ARM_H */
|
4436
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/assem_x86.c
Normal file
4436
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/assem_x86.c
Normal file
File diff suppressed because it is too large
Load diff
32
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/assem_x86.h
Normal file
32
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/assem_x86.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef M64P_R4300_ASSEM_X86_H
|
||||||
|
#define M64P_R4300_ASSEM_X86_H
|
||||||
|
|
||||||
|
#define HOST_REGS 8
|
||||||
|
#define HOST_CCREG 6
|
||||||
|
#define HOST_BTREG 5
|
||||||
|
#define EXCLUDE_REG 4
|
||||||
|
|
||||||
|
//#define IMM_PREFETCH 1
|
||||||
|
#define HOST_IMM_ADDR32 1
|
||||||
|
#define INVERTED_CARRY 1
|
||||||
|
#define DESTRUCTIVE_WRITEBACK 1
|
||||||
|
#define DESTRUCTIVE_SHIFT 1
|
||||||
|
|
||||||
|
#define USE_MINI_HT 1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
extern void *base_addr; // Code generator target address
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TARGET_SIZE_2 25 // 2^25 = 32 megabytes
|
||||||
|
#define JUMP_TABLE_SIZE 0 // Not needed for 32-bit x86
|
||||||
|
|
||||||
|
/* x86 calling convention:
|
||||||
|
caller-save: %eax %ecx %edx
|
||||||
|
callee-save: %ebp %ebx %esi %edi */
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_ASSEM_X86_H */
|
1227
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/linkage_arm.S
Normal file
1227
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/linkage_arm.S
Normal file
File diff suppressed because it is too large
Load diff
929
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/linkage_x86.S
Normal file
929
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/linkage_x86.S
Normal file
|
@ -0,0 +1,929 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - linkage_x86.s *
|
||||||
|
* Copyright (C) 2009-2011 Ari64 *
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
.file "linkage_x86.s"
|
||||||
|
.bss
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
.section .rodata
|
||||||
|
.text
|
||||||
|
.globl dyna_linker
|
||||||
|
.hidden dyna_linker
|
||||||
|
.type dyna_linker, @function
|
||||||
|
dyna_linker:
|
||||||
|
/* eax = virtual target address */
|
||||||
|
/* ebx = instruction to patch */
|
||||||
|
mov %eax, %edi
|
||||||
|
mov %eax, %ecx
|
||||||
|
shr $12, %edi
|
||||||
|
cmp $0xC0000000, %eax
|
||||||
|
cmovge tlb_LUT_r(,%edi,4), %ecx
|
||||||
|
test %ecx, %ecx
|
||||||
|
cmovz %eax, %ecx
|
||||||
|
xor $0x80000000, %ecx
|
||||||
|
mov $2047, %edx
|
||||||
|
shr $12, %ecx
|
||||||
|
and %ecx, %edx
|
||||||
|
or $2048, %edx
|
||||||
|
cmp %edx, %ecx
|
||||||
|
cmova %edx, %ecx
|
||||||
|
/* jump_in lookup */
|
||||||
|
mov jump_in(,%ecx,4), %edx
|
||||||
|
.A1:
|
||||||
|
test %edx, %edx
|
||||||
|
je .A3
|
||||||
|
mov (%edx), %edi
|
||||||
|
xor %eax, %edi
|
||||||
|
or 4(%edx), %edi
|
||||||
|
je .A2
|
||||||
|
movl 12(%edx), %edx
|
||||||
|
jmp .A1
|
||||||
|
.A2:
|
||||||
|
mov (%ebx), %edi
|
||||||
|
mov %esi, %ebp
|
||||||
|
lea 4(%ebx,%edi,1), %esi
|
||||||
|
mov %eax, %edi
|
||||||
|
pusha
|
||||||
|
call add_link
|
||||||
|
popa
|
||||||
|
mov 8(%edx), %edi
|
||||||
|
mov %ebp, %esi
|
||||||
|
lea -4(%edi), %edx
|
||||||
|
subl %ebx, %edx
|
||||||
|
movl %edx, (%ebx)
|
||||||
|
jmp *%edi
|
||||||
|
.A3:
|
||||||
|
/* hash_table lookup */
|
||||||
|
mov %eax, %edi
|
||||||
|
mov %eax, %edx
|
||||||
|
shr $16, %edi
|
||||||
|
shr $12, %edx
|
||||||
|
xor %eax, %edi
|
||||||
|
and $2047, %edx
|
||||||
|
movzwl %di, %edi
|
||||||
|
shl $4, %edi
|
||||||
|
cmp $2048, %ecx
|
||||||
|
cmovc %edx, %ecx
|
||||||
|
cmp hash_table(%edi), %eax
|
||||||
|
jne .A5
|
||||||
|
.A4:
|
||||||
|
mov hash_table+4(%edi), %edx
|
||||||
|
jmp *%edx
|
||||||
|
.A5:
|
||||||
|
cmp hash_table+8(%edi), %eax
|
||||||
|
lea 8(%edi), %edi
|
||||||
|
je .A4
|
||||||
|
/* jump_dirty lookup */
|
||||||
|
mov jump_dirty(,%ecx,4), %edx
|
||||||
|
.A6:
|
||||||
|
testl %edx, %edx
|
||||||
|
je .A8
|
||||||
|
mov (%edx), %ecx
|
||||||
|
xor %eax, %ecx
|
||||||
|
or 4(%edx), %ecx
|
||||||
|
je .A7
|
||||||
|
movl 12(%edx), %edx
|
||||||
|
jmp .A6
|
||||||
|
.A7:
|
||||||
|
mov 8(%edx), %edx
|
||||||
|
/* hash_table insert */
|
||||||
|
mov hash_table-8(%edi), %ebx
|
||||||
|
mov hash_table-4(%edi), %ecx
|
||||||
|
mov %eax, hash_table-8(%edi)
|
||||||
|
mov %edx, hash_table-4(%edi)
|
||||||
|
mov %ebx, hash_table(%edi)
|
||||||
|
mov %ecx, hash_table+4(%edi)
|
||||||
|
jmp *%edx
|
||||||
|
.A8:
|
||||||
|
mov %eax, %edi
|
||||||
|
pusha
|
||||||
|
call new_recompile_block
|
||||||
|
test %eax, %eax
|
||||||
|
popa
|
||||||
|
je dyna_linker
|
||||||
|
/* pagefault */
|
||||||
|
mov %eax, %ebx
|
||||||
|
mov $0x08, %ecx
|
||||||
|
.size dyna_linker, .-dyna_linker
|
||||||
|
|
||||||
|
.type exec_pagefault, @function
|
||||||
|
exec_pagefault:
|
||||||
|
/* eax = instruction pointer */
|
||||||
|
/* ebx = fault address */
|
||||||
|
/* ecx = cause */
|
||||||
|
mov g_cp0_regs+48, %edx
|
||||||
|
add $-12, %esp
|
||||||
|
mov g_cp0_regs+16, %edi
|
||||||
|
or $2, %edx
|
||||||
|
mov %ebx, g_cp0_regs+32 /* BadVAddr */
|
||||||
|
and $0xFF80000F, %edi
|
||||||
|
mov %edx, g_cp0_regs+48 /* Status */
|
||||||
|
mov %ecx, g_cp0_regs+52 /* Cause */
|
||||||
|
mov %eax, g_cp0_regs+56 /* EPC */
|
||||||
|
mov %ebx, %ecx
|
||||||
|
shr $9, %ebx
|
||||||
|
and $0xFFFFE000, %ecx
|
||||||
|
and $0x007FFFF0, %ebx
|
||||||
|
mov %ecx, g_cp0_regs+40 /* EntryHI */
|
||||||
|
or %ebx, %edi
|
||||||
|
mov %edi, g_cp0_regs+16 /* Context */
|
||||||
|
push $0x80000000
|
||||||
|
call get_addr_ht
|
||||||
|
add $16, %esp
|
||||||
|
jmp *%eax
|
||||||
|
.size exec_pagefault, .-exec_pagefault
|
||||||
|
|
||||||
|
/* Special dynamic linker for the case where a page fault
|
||||||
|
may occur in a branch delay slot */
|
||||||
|
.globl dyna_linker_ds
|
||||||
|
.hidden dyna_linker_ds
|
||||||
|
.type dyna_linker_ds, @function
|
||||||
|
dyna_linker_ds:
|
||||||
|
mov %eax, %edi
|
||||||
|
mov %eax, %ecx
|
||||||
|
shr $12, %edi
|
||||||
|
cmp $0xC0000000, %eax
|
||||||
|
cmovge tlb_LUT_r(,%edi,4), %ecx
|
||||||
|
test %ecx, %ecx
|
||||||
|
cmovz %eax, %ecx
|
||||||
|
xor $0x80000000, %ecx
|
||||||
|
mov $2047, %edx
|
||||||
|
shr $12, %ecx
|
||||||
|
and %ecx, %edx
|
||||||
|
or $2048, %edx
|
||||||
|
cmp %edx, %ecx
|
||||||
|
cmova %edx, %ecx
|
||||||
|
/* jump_in lookup */
|
||||||
|
mov jump_in(,%ecx,4), %edx
|
||||||
|
.B1:
|
||||||
|
test %edx, %edx
|
||||||
|
je .B3
|
||||||
|
mov (%edx), %edi
|
||||||
|
xor %eax, %edi
|
||||||
|
or 4(%edx), %edi
|
||||||
|
je .B2
|
||||||
|
movl 12(%edx), %edx
|
||||||
|
jmp .B1
|
||||||
|
.B2:
|
||||||
|
mov (%ebx), %edi
|
||||||
|
mov %esi, %ecx
|
||||||
|
lea 4(%ebx,%edi,1), %esi
|
||||||
|
mov %eax, %edi
|
||||||
|
pusha
|
||||||
|
call add_link
|
||||||
|
popa
|
||||||
|
mov 8(%edx), %edi
|
||||||
|
mov %ecx, %esi
|
||||||
|
lea -4(%edi), %edx
|
||||||
|
subl %ebx, %edx
|
||||||
|
movl %edx, (%ebx)
|
||||||
|
jmp *%edi
|
||||||
|
.B3:
|
||||||
|
/* hash_table lookup */
|
||||||
|
mov %eax, %edi
|
||||||
|
mov %eax, %edx
|
||||||
|
shr $16, %edi
|
||||||
|
shr $12, %edx
|
||||||
|
xor %eax, %edi
|
||||||
|
and $2047, %edx
|
||||||
|
movzwl %di, %edi
|
||||||
|
shl $4, %edi
|
||||||
|
cmp $2048, %ecx
|
||||||
|
cmovc %edx, %ecx
|
||||||
|
cmp hash_table(%edi), %eax
|
||||||
|
jne .B5
|
||||||
|
.B4:
|
||||||
|
mov hash_table+4(%edi), %edx
|
||||||
|
jmp *%edx
|
||||||
|
.B5:
|
||||||
|
cmp hash_table+8(%edi), %eax
|
||||||
|
lea 8(%edi), %edi
|
||||||
|
je .B4
|
||||||
|
/* jump_dirty lookup */
|
||||||
|
mov jump_dirty(,%ecx,4), %edx
|
||||||
|
.B6:
|
||||||
|
testl %edx, %edx
|
||||||
|
je .B8
|
||||||
|
mov (%edx), %ecx
|
||||||
|
xor %eax, %ecx
|
||||||
|
or 4(%edx), %ecx
|
||||||
|
je .B7
|
||||||
|
movl 12(%edx), %edx
|
||||||
|
jmp .B6
|
||||||
|
.B7:
|
||||||
|
mov 8(%edx), %edx
|
||||||
|
/* hash_table insert */
|
||||||
|
mov hash_table-8(%edi), %ebx
|
||||||
|
mov hash_table-4(%edi), %ecx
|
||||||
|
mov %eax, hash_table-8(%edi)
|
||||||
|
mov %edx, hash_table-4(%edi)
|
||||||
|
mov %ebx, hash_table(%edi)
|
||||||
|
mov %ecx, hash_table+4(%edi)
|
||||||
|
jmp *%edx
|
||||||
|
.B8:
|
||||||
|
mov %eax, %edi
|
||||||
|
and $0xFFFFFFF8, %edi
|
||||||
|
inc %edi
|
||||||
|
pusha
|
||||||
|
call new_recompile_block
|
||||||
|
test %eax, %eax
|
||||||
|
popa
|
||||||
|
je dyna_linker_ds
|
||||||
|
/* pagefault */
|
||||||
|
and $0xFFFFFFF8, %eax
|
||||||
|
mov $0x80000008, %ecx /* High bit set indicates pagefault in delay slot */
|
||||||
|
mov %eax, %ebx
|
||||||
|
sub $4, %eax
|
||||||
|
jmp exec_pagefault
|
||||||
|
.size dyna_linker_ds, .-dyna_linker_ds
|
||||||
|
|
||||||
|
.globl jump_vaddr_eax
|
||||||
|
.hidden jump_vaddr_eax
|
||||||
|
.type jump_vaddr_eax, @function
|
||||||
|
jump_vaddr_eax:
|
||||||
|
mov %eax, %edi
|
||||||
|
jmp jump_vaddr_edi
|
||||||
|
.size jump_vaddr_eax, .-jump_vaddr_eax
|
||||||
|
.globl jump_vaddr_ecx
|
||||||
|
.hidden jump_vaddr_ecx
|
||||||
|
.type jump_vaddr_ecx, @function
|
||||||
|
jump_vaddr_ecx:
|
||||||
|
mov %ecx, %edi
|
||||||
|
jmp jump_vaddr_edi
|
||||||
|
.size jump_vaddr_ecx, .-jump_vaddr_ecx
|
||||||
|
.globl jump_vaddr_edx
|
||||||
|
.hidden jump_vaddr_edx
|
||||||
|
.type jump_vaddr_edx, @function
|
||||||
|
jump_vaddr_edx:
|
||||||
|
mov %edx, %edi
|
||||||
|
jmp jump_vaddr_edi
|
||||||
|
.size jump_vaddr_edx, .-jump_vaddr_edx
|
||||||
|
.globl jump_vaddr_ebx
|
||||||
|
.hidden jump_vaddr_ebx
|
||||||
|
.type jump_vaddr_ebx, @function
|
||||||
|
jump_vaddr_ebx:
|
||||||
|
mov %ebx, %edi
|
||||||
|
jmp jump_vaddr_edi
|
||||||
|
.size jump_vaddr_ebx, .-jump_vaddr_ebx
|
||||||
|
.globl jump_vaddr_ebp
|
||||||
|
.hidden jump_vaddr_ebp
|
||||||
|
.type jump_vaddr_ebp, @function
|
||||||
|
jump_vaddr_ebp:
|
||||||
|
mov %ebp, %edi
|
||||||
|
.size jump_vaddr_ebp, .-jump_vaddr_ebp
|
||||||
|
.globl jump_vaddr_edi
|
||||||
|
.hidden jump_vaddr_edi
|
||||||
|
.type jump_vaddr_edi, @function
|
||||||
|
jump_vaddr_edi:
|
||||||
|
mov %edi, %eax
|
||||||
|
.size jump_vaddr_edi, .-jump_vaddr_edi
|
||||||
|
|
||||||
|
.type jump_vaddr, @function
|
||||||
|
jump_vaddr:
|
||||||
|
/* Check hash table */
|
||||||
|
shr $16, %eax
|
||||||
|
xor %edi, %eax
|
||||||
|
movzwl %ax, %eax
|
||||||
|
shl $4, %eax
|
||||||
|
cmp hash_table(%eax), %edi
|
||||||
|
jne .C2
|
||||||
|
.C1:
|
||||||
|
mov hash_table+4(%eax), %edi
|
||||||
|
jmp *%edi
|
||||||
|
.C2:
|
||||||
|
cmp hash_table+8(%eax), %edi
|
||||||
|
lea 8(%eax), %eax
|
||||||
|
je .C1
|
||||||
|
/* No hit on hash table, call compiler */
|
||||||
|
add $-12, %esp
|
||||||
|
push %edi
|
||||||
|
mov %esi, cycle_count /* CCREG */
|
||||||
|
call get_addr
|
||||||
|
mov cycle_count, %esi
|
||||||
|
add $16, %esp
|
||||||
|
jmp *%eax
|
||||||
|
.size jump_vaddr, .-jump_vaddr
|
||||||
|
|
||||||
|
.globl verify_code_ds
|
||||||
|
.hidden verify_code_ds
|
||||||
|
.type verify_code_ds, @function
|
||||||
|
verify_code_ds:
|
||||||
|
mov %ebp, branch_target
|
||||||
|
.size verify_code_ds, .-verify_code_ds
|
||||||
|
|
||||||
|
.globl verify_code_vm
|
||||||
|
.hidden verify_code_vm
|
||||||
|
.type verify_code_vm, @function
|
||||||
|
verify_code_vm:
|
||||||
|
/* eax = source (virtual address) */
|
||||||
|
/* ebx = target */
|
||||||
|
/* ecx = length */
|
||||||
|
cmp $0xC0000000, %eax
|
||||||
|
jl verify_code
|
||||||
|
mov %eax, %edx
|
||||||
|
lea -1(%eax,%ecx,1), %ebp
|
||||||
|
shr $12, %edx
|
||||||
|
shr $12, %ebp
|
||||||
|
mov memory_map(,%edx,4), %edi
|
||||||
|
test %edi, %edi
|
||||||
|
js .D5
|
||||||
|
lea (%eax,%edi,4), %eax
|
||||||
|
.D1:
|
||||||
|
xor memory_map(,%edx,4), %edi
|
||||||
|
shl $2, %edi
|
||||||
|
jne .D5
|
||||||
|
mov memory_map(,%edx,4), %edi
|
||||||
|
inc %edx
|
||||||
|
cmp %ebp, %edx
|
||||||
|
jbe .D1
|
||||||
|
.size verify_code_vm, .-verify_code_vm
|
||||||
|
|
||||||
|
.globl verify_code
|
||||||
|
.hidden verify_code
|
||||||
|
.type verify_code, @function
|
||||||
|
verify_code:
|
||||||
|
/* eax = source */
|
||||||
|
/* ebx = target */
|
||||||
|
/* ecx = length */
|
||||||
|
mov -4(%eax,%ecx,1), %edi
|
||||||
|
xor -4(%ebx,%ecx,1), %edi
|
||||||
|
jne .D5
|
||||||
|
mov %ecx, %edx
|
||||||
|
add $-4, %ecx
|
||||||
|
je .D3
|
||||||
|
test $4, %edx
|
||||||
|
cmove %edx, %ecx
|
||||||
|
mov %esi, cycle_count
|
||||||
|
.D2:
|
||||||
|
mov -4(%eax,%ecx,1), %edx
|
||||||
|
mov -4(%ebx,%ecx,1), %ebp
|
||||||
|
mov -8(%eax,%ecx,1), %esi
|
||||||
|
xor %edx, %ebp
|
||||||
|
mov -8(%ebx,%ecx,1), %edi
|
||||||
|
jne .D4
|
||||||
|
xor %esi, %edi
|
||||||
|
jne .D4
|
||||||
|
add $-8, %ecx
|
||||||
|
jne .D2
|
||||||
|
mov cycle_count, %esi
|
||||||
|
mov branch_target, %ebp
|
||||||
|
.D3:
|
||||||
|
ret
|
||||||
|
.D4:
|
||||||
|
mov cycle_count, %esi
|
||||||
|
.D5:
|
||||||
|
mov branch_target, %ebp
|
||||||
|
push %esi /* for stack alignment, unused */
|
||||||
|
push 8(%esp)
|
||||||
|
call get_addr
|
||||||
|
add $16, %esp /* pop stack */
|
||||||
|
jmp *%eax
|
||||||
|
.size verify_code, .-verify_code
|
||||||
|
|
||||||
|
.globl cc_interrupt
|
||||||
|
.hidden cc_interrupt
|
||||||
|
.type cc_interrupt, @function
|
||||||
|
cc_interrupt:
|
||||||
|
add last_count, %esi
|
||||||
|
add $-28, %esp /* Align stack */
|
||||||
|
mov %esi, g_cp0_regs+36 /* Count */
|
||||||
|
shr $19, %esi
|
||||||
|
movl $0, pending_exception
|
||||||
|
and $0x7f, %esi
|
||||||
|
cmpl $0, restore_candidate(,%esi,4)
|
||||||
|
jne .E4
|
||||||
|
.E1:
|
||||||
|
call gen_interupt
|
||||||
|
mov g_cp0_regs+36, %esi
|
||||||
|
mov next_interupt, %eax
|
||||||
|
mov pending_exception, %ebx
|
||||||
|
mov stop, %ecx
|
||||||
|
add $28, %esp
|
||||||
|
mov %eax, last_count
|
||||||
|
sub %eax, %esi
|
||||||
|
test %ecx, %ecx
|
||||||
|
jne .E3
|
||||||
|
test %ebx, %ebx
|
||||||
|
jne .E2
|
||||||
|
ret
|
||||||
|
.E2:
|
||||||
|
add $-8, %esp
|
||||||
|
mov pcaddr, %edi
|
||||||
|
mov %esi, cycle_count /* CCREG */
|
||||||
|
push %edi
|
||||||
|
call get_addr_ht
|
||||||
|
mov cycle_count, %esi
|
||||||
|
add $16, %esp
|
||||||
|
jmp *%eax
|
||||||
|
.E3:
|
||||||
|
add $16, %esp /* pop stack */
|
||||||
|
pop %edi /* restore edi */
|
||||||
|
pop %esi /* restore esi */
|
||||||
|
pop %ebx /* restore ebx */
|
||||||
|
pop %ebp /* restore ebp */
|
||||||
|
ret /* exit dynarec */
|
||||||
|
.E4:
|
||||||
|
/* Move 'dirty' blocks to the 'clean' list */
|
||||||
|
mov restore_candidate(,%esi,4), %ebx
|
||||||
|
mov %esi, %ebp
|
||||||
|
movl $0, restore_candidate(,%esi,4)
|
||||||
|
shl $5, %ebp
|
||||||
|
.E5:
|
||||||
|
shr $1, %ebx
|
||||||
|
jnc .E6
|
||||||
|
mov %ebp, (%esp)
|
||||||
|
call clean_blocks
|
||||||
|
.E6:
|
||||||
|
inc %ebp
|
||||||
|
test $31, %ebp
|
||||||
|
jne .E5
|
||||||
|
jmp .E1
|
||||||
|
.size cc_interrupt, .-cc_interrupt
|
||||||
|
|
||||||
|
.globl do_interrupt
|
||||||
|
.hidden do_interrupt
|
||||||
|
.type do_interrupt, @function
|
||||||
|
do_interrupt:
|
||||||
|
mov pcaddr, %edi
|
||||||
|
add $-12, %esp
|
||||||
|
push %edi
|
||||||
|
call get_addr_ht
|
||||||
|
add $16, %esp
|
||||||
|
mov g_cp0_regs+36, %esi
|
||||||
|
mov next_interupt, %ebx
|
||||||
|
mov %ebx, last_count
|
||||||
|
sub %ebx, %esi
|
||||||
|
add $2, %esi
|
||||||
|
jmp *%eax
|
||||||
|
.size do_interrupt, .-do_interrupt
|
||||||
|
|
||||||
|
.globl fp_exception
|
||||||
|
.hidden fp_exception
|
||||||
|
.type fp_exception, @function
|
||||||
|
fp_exception:
|
||||||
|
mov $0x1000002c, %edx
|
||||||
|
.E7:
|
||||||
|
mov g_cp0_regs+48, %ebx
|
||||||
|
add $-12, %esp
|
||||||
|
or $2, %ebx
|
||||||
|
mov %ebx, g_cp0_regs+48 /* Status */
|
||||||
|
mov %edx, g_cp0_regs+52 /* Cause */
|
||||||
|
mov %eax, g_cp0_regs+56 /* EPC */
|
||||||
|
push $0x80000180
|
||||||
|
call get_addr_ht
|
||||||
|
add $16, %esp
|
||||||
|
jmp *%eax
|
||||||
|
.size fp_exception, .-fp_exception
|
||||||
|
|
||||||
|
.globl fp_exception_ds
|
||||||
|
.hidden fp_exception_ds
|
||||||
|
.type fp_exception_ds, @function
|
||||||
|
fp_exception_ds:
|
||||||
|
mov $0x9000002c, %edx /* Set high bit if delay slot */
|
||||||
|
jmp .E7
|
||||||
|
.size fp_exception_ds, .-fp_exception_ds
|
||||||
|
|
||||||
|
.globl jump_syscall
|
||||||
|
.hidden jump_syscall
|
||||||
|
.type jump_syscall, @function
|
||||||
|
jump_syscall:
|
||||||
|
mov $0x20, %edx
|
||||||
|
mov g_cp0_regs+48, %ebx
|
||||||
|
add $-12, %esp
|
||||||
|
or $2, %ebx
|
||||||
|
mov %ebx, g_cp0_regs+48 /* Status */
|
||||||
|
mov %edx, g_cp0_regs+52 /* Cause */
|
||||||
|
mov %eax, g_cp0_regs+56 /* EPC */
|
||||||
|
push $0x80000180
|
||||||
|
call get_addr_ht
|
||||||
|
add $16, %esp
|
||||||
|
jmp *%eax
|
||||||
|
.size jump_syscall, .-jump_syscall
|
||||||
|
|
||||||
|
.globl jump_eret
|
||||||
|
.hidden jump_eret
|
||||||
|
.type jump_eret, @function
|
||||||
|
jump_eret:
|
||||||
|
mov g_cp0_regs+48, %ebx /* Status */
|
||||||
|
add last_count, %esi
|
||||||
|
and $0xFFFFFFFD, %ebx
|
||||||
|
mov %esi, g_cp0_regs+36 /* Count */
|
||||||
|
mov %ebx, g_cp0_regs+48 /* Status */
|
||||||
|
call check_interupt
|
||||||
|
mov next_interupt, %eax
|
||||||
|
mov g_cp0_regs+36, %esi
|
||||||
|
mov %eax, last_count
|
||||||
|
sub %eax, %esi
|
||||||
|
mov g_cp0_regs+56, %eax /* EPC */
|
||||||
|
jns .E11
|
||||||
|
.E8:
|
||||||
|
mov $248, %ebx
|
||||||
|
xor %edi, %edi
|
||||||
|
.E9:
|
||||||
|
mov reg(%ebx), %ecx
|
||||||
|
mov reg+4(%ebx), %edx
|
||||||
|
sar $31, %ecx
|
||||||
|
xor %ecx, %edx
|
||||||
|
neg %edx
|
||||||
|
adc %edi, %edi
|
||||||
|
sub $8, %ebx
|
||||||
|
jne .E9
|
||||||
|
mov hi(%ebx), %ecx
|
||||||
|
mov hi+4(%ebx), %edx
|
||||||
|
sar $31, %ecx
|
||||||
|
xor %ecx, %edx
|
||||||
|
jne .E10
|
||||||
|
mov lo(%ebx), %ecx
|
||||||
|
mov lo+4(%ebx), %edx
|
||||||
|
sar $31, %ecx
|
||||||
|
xor %ecx, %edx
|
||||||
|
.E10:
|
||||||
|
neg %edx
|
||||||
|
adc %edi, %edi
|
||||||
|
add $-8, %esp
|
||||||
|
push %edi
|
||||||
|
push %eax
|
||||||
|
mov %esi, cycle_count
|
||||||
|
call get_addr_32
|
||||||
|
mov cycle_count, %esi
|
||||||
|
add $16, %esp
|
||||||
|
jmp *%eax
|
||||||
|
.E11:
|
||||||
|
mov %eax, pcaddr
|
||||||
|
call cc_interrupt
|
||||||
|
mov pcaddr, %eax
|
||||||
|
jmp .E8
|
||||||
|
.size jump_eret, .-jump_eret
|
||||||
|
|
||||||
|
.globl new_dyna_start
|
||||||
|
.hidden new_dyna_start
|
||||||
|
.type new_dyna_start, @function
|
||||||
|
new_dyna_start:
|
||||||
|
push %ebp
|
||||||
|
push %ebx
|
||||||
|
push %esi
|
||||||
|
push %edi
|
||||||
|
add $-8, %esp /* align stack */
|
||||||
|
push $0xa4000040
|
||||||
|
call new_recompile_block
|
||||||
|
movl next_interupt, %edi
|
||||||
|
movl g_cp0_regs+36, %esi
|
||||||
|
movl %edi, last_count
|
||||||
|
subl %edi, %esi
|
||||||
|
jmp *base_addr
|
||||||
|
.size new_dyna_start, .-new_dyna_start
|
||||||
|
|
||||||
|
/* Note: Assumes %ebx, %ebp, %esi, %edi are callee-saved */
|
||||||
|
.globl invalidate_block_eax
|
||||||
|
.hidden invalidate_block_eax
|
||||||
|
.type invalidate_block_eax, @function
|
||||||
|
invalidate_block_eax:
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
push %eax
|
||||||
|
jmp invalidate_block_call
|
||||||
|
.size invalidate_block_eax, .-invalidate_block_eax
|
||||||
|
.globl invalidate_block_ecx
|
||||||
|
.hidden invalidate_block_ecx
|
||||||
|
.type invalidate_block_ecx, @function
|
||||||
|
invalidate_block_ecx:
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
push %ecx
|
||||||
|
jmp invalidate_block_call
|
||||||
|
.size invalidate_block_ecx, .-invalidate_block_ecx
|
||||||
|
.globl invalidate_block_edx
|
||||||
|
.hidden invalidate_block_edx
|
||||||
|
.type invalidate_block_edx, @function
|
||||||
|
invalidate_block_edx:
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
push %edx
|
||||||
|
jmp invalidate_block_call
|
||||||
|
.size invalidate_block_edx, .-invalidate_block_edx
|
||||||
|
.globl invalidate_block_ebx
|
||||||
|
.hidden invalidate_block_ebx
|
||||||
|
.type invalidate_block_ebx, @function
|
||||||
|
invalidate_block_ebx:
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
push %ebx
|
||||||
|
jmp invalidate_block_call
|
||||||
|
.size invalidate_block_ebx, .-invalidate_block_ebx
|
||||||
|
.globl invalidate_block_ebp
|
||||||
|
.hidden invalidate_block_ebp
|
||||||
|
.type invalidate_block_ebp, @function
|
||||||
|
invalidate_block_ebp:
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
push %ebp
|
||||||
|
jmp invalidate_block_call
|
||||||
|
.size invalidate_block_ebp, .-invalidate_block_ebp
|
||||||
|
.globl invalidate_block_esi
|
||||||
|
.hidden invalidate_block_esi
|
||||||
|
.type invalidate_block_esi, @function
|
||||||
|
invalidate_block_esi:
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
push %esi
|
||||||
|
jmp invalidate_block_call
|
||||||
|
.size invalidate_block_esi, .-invalidate_block_esi
|
||||||
|
.globl invalidate_block_edi
|
||||||
|
.hidden invalidate_block_edi
|
||||||
|
.type invalidate_block_edi, @function
|
||||||
|
invalidate_block_edi:
|
||||||
|
push %eax
|
||||||
|
push %ecx
|
||||||
|
push %edx
|
||||||
|
push %edi
|
||||||
|
.size invalidate_block_edi, .-invalidate_block_edi
|
||||||
|
|
||||||
|
.type invalidate_block_call, @function
|
||||||
|
invalidate_block_call:
|
||||||
|
call invalidate_block
|
||||||
|
pop %eax /* Throw away */
|
||||||
|
pop %edx
|
||||||
|
pop %ecx
|
||||||
|
pop %eax
|
||||||
|
ret
|
||||||
|
.size invalidate_block_call, .-invalidate_block_call
|
||||||
|
|
||||||
|
.globl write_rdram_new
|
||||||
|
.hidden write_rdram_new
|
||||||
|
.type write_rdram_new, @function
|
||||||
|
write_rdram_new:
|
||||||
|
mov address, %edi
|
||||||
|
mov cpu_word, %ecx
|
||||||
|
mov %ecx, g_rdram-0x80000000(%edi)
|
||||||
|
jmp .E12
|
||||||
|
.size write_rdram_new, .-write_rdram_new
|
||||||
|
|
||||||
|
.globl write_rdramb_new
|
||||||
|
.hidden write_rdramb_new
|
||||||
|
.type write_rdramb_new, @function
|
||||||
|
write_rdramb_new:
|
||||||
|
mov address, %edi
|
||||||
|
xor $3, %edi
|
||||||
|
movb cpu_byte, %cl
|
||||||
|
movb %cl, g_rdram-0x80000000(%edi)
|
||||||
|
jmp .E12
|
||||||
|
.size write_rdramb_new, .-write_rdramb_new
|
||||||
|
|
||||||
|
.globl write_rdramh_new
|
||||||
|
.hidden write_rdramh_new
|
||||||
|
.type write_rdramh_new, @function
|
||||||
|
write_rdramh_new:
|
||||||
|
mov address, %edi
|
||||||
|
xor $2, %edi
|
||||||
|
movw cpu_hword, %cx
|
||||||
|
movw %cx, g_rdram-0x80000000(%edi)
|
||||||
|
jmp .E12
|
||||||
|
.size write_rdramh_new, .-write_rdramh_new
|
||||||
|
|
||||||
|
.globl write_rdramd_new
|
||||||
|
.hidden write_rdramd_new
|
||||||
|
.type write_rdramd_new, @function
|
||||||
|
write_rdramd_new:
|
||||||
|
mov address, %edi
|
||||||
|
mov cpu_dword+4, %ecx
|
||||||
|
mov cpu_dword, %edx
|
||||||
|
mov %ecx, g_rdram-0x80000000(%edi)
|
||||||
|
mov %edx, g_rdram-0x80000000+4(%edi)
|
||||||
|
jmp .E12
|
||||||
|
.size write_rdramd_new, .-write_rdramd_new
|
||||||
|
|
||||||
|
.type do_invalidate, @function
|
||||||
|
do_invalidate:
|
||||||
|
mov address, %edi
|
||||||
|
mov %edi, %ebx /* Return ebx to caller */
|
||||||
|
.E12:
|
||||||
|
shr $12, %edi
|
||||||
|
cmpb $1, invalid_code(%edi)
|
||||||
|
je .E13
|
||||||
|
push %edi
|
||||||
|
call invalidate_block
|
||||||
|
pop %edi
|
||||||
|
.E13:
|
||||||
|
ret
|
||||||
|
.size do_invalidate, .-do_invalidate
|
||||||
|
|
||||||
|
.globl read_nomem_new
|
||||||
|
.hidden read_nomem_new
|
||||||
|
.type read_nomem_new, @function
|
||||||
|
read_nomem_new:
|
||||||
|
mov address, %edi
|
||||||
|
mov %edi, %ebx
|
||||||
|
shr $12, %edi
|
||||||
|
mov memory_map(,%edi,4),%edi
|
||||||
|
mov $0x8, %eax
|
||||||
|
test %edi, %edi
|
||||||
|
js tlb_exception
|
||||||
|
mov (%ebx,%edi,4), %ecx
|
||||||
|
mov %ecx, readmem_dword
|
||||||
|
ret
|
||||||
|
.size read_nomem_new, .-read_nomem_new
|
||||||
|
|
||||||
|
.globl read_nomemb_new
|
||||||
|
.hidden read_nomemb_new
|
||||||
|
.type read_nomemb_new, @function
|
||||||
|
read_nomemb_new:
|
||||||
|
mov address, %edi
|
||||||
|
mov %edi, %ebx
|
||||||
|
shr $12, %edi
|
||||||
|
mov memory_map(,%edi,4),%edi
|
||||||
|
mov $0x8, %eax
|
||||||
|
test %edi, %edi
|
||||||
|
js tlb_exception
|
||||||
|
xor $3, %ebx
|
||||||
|
movzbl (%ebx,%edi,4), %ecx
|
||||||
|
mov %ecx, readmem_dword
|
||||||
|
ret
|
||||||
|
.size read_nomemb_new, .-read_nomemb_new
|
||||||
|
|
||||||
|
.globl read_nomemh_new
|
||||||
|
.hidden read_nomemh_new
|
||||||
|
.type read_nomemh_new, @function
|
||||||
|
read_nomemh_new:
|
||||||
|
mov address, %edi
|
||||||
|
mov %edi, %ebx
|
||||||
|
shr $12, %edi
|
||||||
|
mov memory_map(,%edi,4),%edi
|
||||||
|
mov $0x8, %eax
|
||||||
|
test %edi, %edi
|
||||||
|
js tlb_exception
|
||||||
|
xor $2, %ebx
|
||||||
|
movzwl (%ebx,%edi,4), %ecx
|
||||||
|
mov %ecx, readmem_dword
|
||||||
|
ret
|
||||||
|
.size read_nomemh_new, .-read_nomemh_new
|
||||||
|
|
||||||
|
.globl read_nomemd_new
|
||||||
|
.hidden read_nomemd_new
|
||||||
|
.type read_nomemd_new, @function
|
||||||
|
read_nomemd_new:
|
||||||
|
mov address, %edi
|
||||||
|
mov %edi, %ebx
|
||||||
|
shr $12, %edi
|
||||||
|
mov memory_map(,%edi,4),%edi
|
||||||
|
mov $0x8, %eax
|
||||||
|
test %edi, %edi
|
||||||
|
js tlb_exception
|
||||||
|
mov 4(%ebx,%edi,4), %ecx
|
||||||
|
mov (%ebx,%edi,4), %edx
|
||||||
|
mov %ecx, readmem_dword
|
||||||
|
mov %edx, readmem_dword+4
|
||||||
|
ret
|
||||||
|
.size read_nomemd_new, .-read_nomemd_new
|
||||||
|
|
||||||
|
.globl write_nomem_new
|
||||||
|
.hidden write_nomem_new
|
||||||
|
.type write_nomem_new, @function
|
||||||
|
write_nomem_new:
|
||||||
|
call do_invalidate
|
||||||
|
mov memory_map(,%edi,4),%edi
|
||||||
|
mov cpu_word, %ecx
|
||||||
|
mov $0xc, %eax
|
||||||
|
shl $2, %edi
|
||||||
|
jc tlb_exception
|
||||||
|
mov %ecx, (%ebx,%edi)
|
||||||
|
ret
|
||||||
|
.size write_nomem_new, .-write_nomem_new
|
||||||
|
|
||||||
|
.globl write_nomemb_new
|
||||||
|
.hidden write_nomemb_new
|
||||||
|
.type write_nomemb_new, @function
|
||||||
|
write_nomemb_new:
|
||||||
|
call do_invalidate
|
||||||
|
mov memory_map(,%edi,4),%edi
|
||||||
|
movb cpu_byte, %cl
|
||||||
|
mov $0xc, %eax
|
||||||
|
shl $2, %edi
|
||||||
|
jc tlb_exception
|
||||||
|
xor $3, %ebx
|
||||||
|
movb %cl, (%ebx,%edi)
|
||||||
|
ret
|
||||||
|
.size write_nomemb_new, .-write_nomemb_new
|
||||||
|
|
||||||
|
.globl write_nomemh_new
|
||||||
|
.hidden write_nomemh_new
|
||||||
|
.type write_nomemh_new, @function
|
||||||
|
write_nomemh_new:
|
||||||
|
call do_invalidate
|
||||||
|
mov memory_map(,%edi,4),%edi
|
||||||
|
movw cpu_hword, %cx
|
||||||
|
mov $0xc, %eax
|
||||||
|
shl $2, %edi
|
||||||
|
jc tlb_exception
|
||||||
|
xor $2, %ebx
|
||||||
|
movw %cx, (%ebx,%edi)
|
||||||
|
ret
|
||||||
|
.size write_nomemh_new, .-write_nomemh_new
|
||||||
|
|
||||||
|
.globl write_nomemd_new
|
||||||
|
.hidden write_nomemd_new
|
||||||
|
.type write_nomemd_new, @function
|
||||||
|
write_nomemd_new:
|
||||||
|
call do_invalidate
|
||||||
|
mov memory_map(,%edi,4),%edi
|
||||||
|
mov cpu_dword+4, %edx
|
||||||
|
mov cpu_dword, %ecx
|
||||||
|
mov $0xc, %eax
|
||||||
|
shl $2, %edi
|
||||||
|
jc tlb_exception
|
||||||
|
mov %edx, (%ebx,%edi)
|
||||||
|
mov %ecx, 4(%ebx,%edi)
|
||||||
|
ret
|
||||||
|
.size write_nomemd_new, .-write_nomemd_new
|
||||||
|
|
||||||
|
.type tlb_exception, @function
|
||||||
|
tlb_exception:
|
||||||
|
/* eax = cause */
|
||||||
|
/* ebx = address */
|
||||||
|
/* ebp = instr addr + flags */
|
||||||
|
mov 0x24(%esp), %ebp
|
||||||
|
/* Debug:
|
||||||
|
push %ebp
|
||||||
|
push %ebx
|
||||||
|
push %eax
|
||||||
|
call tlb_debug
|
||||||
|
pop %eax
|
||||||
|
pop %ebx
|
||||||
|
pop %ebp
|
||||||
|
/* end debug */
|
||||||
|
mov g_cp0_regs+48, %esi
|
||||||
|
mov %ebp, %ecx
|
||||||
|
mov %ebp, %edx
|
||||||
|
mov %ebp, %edi
|
||||||
|
shl $31, %ebp
|
||||||
|
shr $12, %ecx
|
||||||
|
or %ebp, %eax
|
||||||
|
sar $29, %ebp
|
||||||
|
and $0xFFFFFFFC, %edx
|
||||||
|
mov memory_map(,%ecx,4), %ecx
|
||||||
|
or $2, %esi
|
||||||
|
mov (%edx, %ecx, 4), %ecx
|
||||||
|
add %ebp, %edx
|
||||||
|
mov %esi, g_cp0_regs+48 /* Status */
|
||||||
|
mov %eax, g_cp0_regs+52 /* Cause */
|
||||||
|
mov %edx, g_cp0_regs+56 /* EPC */
|
||||||
|
add $0x24, %esp
|
||||||
|
mov $0x6000022, %edx
|
||||||
|
mov %ecx, %ebp
|
||||||
|
movswl %cx, %eax
|
||||||
|
shr $26, %ecx
|
||||||
|
shr $21, %ebp
|
||||||
|
sub %eax, %ebx
|
||||||
|
and $0x1f, %ebp
|
||||||
|
ror %cl, %edx
|
||||||
|
mov g_cp0_regs+16, %esi
|
||||||
|
cmovc reg(,%ebp,8), %ebx
|
||||||
|
and $0xFF80000F, %esi
|
||||||
|
mov %ebx, reg(,%ebp,8)
|
||||||
|
add %ebx, %eax
|
||||||
|
sar $31, %ebx
|
||||||
|
mov %eax, g_cp0_regs+32 /* BadVAddr */
|
||||||
|
shr $9, %eax
|
||||||
|
test $2, %edi
|
||||||
|
cmove reg+4(,%ebp,8), %ebx
|
||||||
|
add $-12, %esp
|
||||||
|
and $0x007FFFF0, %eax
|
||||||
|
mov %ebx, reg+4(,%ebp,8)
|
||||||
|
push $0x80000180
|
||||||
|
or %eax, %esi
|
||||||
|
mov %esi, g_cp0_regs+16 /* Context */
|
||||||
|
call get_addr_ht
|
||||||
|
add $16, %esp
|
||||||
|
movl next_interupt, %edi
|
||||||
|
movl g_cp0_regs+36, %esi /* Count */
|
||||||
|
movl %edi, last_count
|
||||||
|
subl %edi, %esi
|
||||||
|
jmp *%eax
|
||||||
|
.size tlb_exception, .-tlb_exception
|
||||||
|
|
||||||
|
.globl breakpoint
|
||||||
|
.hidden breakpoint
|
||||||
|
.type breakpoint, @function
|
||||||
|
breakpoint:
|
||||||
|
.size breakpoint, .-breakpoint
|
873
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/linkage_x86.asm
Normal file
873
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/linkage_x86.asm
Normal file
|
@ -0,0 +1,873 @@
|
||||||
|
;Mupen64plus - linkage_x86.asm
|
||||||
|
;Copyright (C) 2009-2011 Ari64
|
||||||
|
;
|
||||||
|
;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.
|
||||||
|
|
||||||
|
%ifdef ELF_TYPE
|
||||||
|
%macro cglobal 1
|
||||||
|
global %1
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro cextern 1
|
||||||
|
extern %1
|
||||||
|
%endmacro
|
||||||
|
%else
|
||||||
|
%macro cglobal 1
|
||||||
|
global _%1
|
||||||
|
%define %1 _%1
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
%macro cextern 1
|
||||||
|
extern _%1
|
||||||
|
%define %1 _%1
|
||||||
|
%endmacro
|
||||||
|
%endif
|
||||||
|
|
||||||
|
cglobal dyna_linker
|
||||||
|
cglobal dyna_linker_ds
|
||||||
|
cglobal jump_vaddr_eax
|
||||||
|
cglobal jump_vaddr_ecx
|
||||||
|
cglobal jump_vaddr_edx
|
||||||
|
cglobal jump_vaddr_ebx
|
||||||
|
cglobal jump_vaddr_ebp
|
||||||
|
cglobal jump_vaddr_edi
|
||||||
|
cglobal verify_code_ds
|
||||||
|
cglobal verify_code_vm
|
||||||
|
cglobal verify_code
|
||||||
|
cglobal cc_interrupt
|
||||||
|
cglobal do_interrupt
|
||||||
|
cglobal fp_exception
|
||||||
|
cglobal fp_exception_ds
|
||||||
|
cglobal jump_syscall
|
||||||
|
cglobal jump_eret
|
||||||
|
cglobal new_dyna_start
|
||||||
|
cglobal invalidate_block_eax
|
||||||
|
cglobal invalidate_block_ecx
|
||||||
|
cglobal invalidate_block_edx
|
||||||
|
cglobal invalidate_block_ebx
|
||||||
|
cglobal invalidate_block_ebp
|
||||||
|
cglobal invalidate_block_esi
|
||||||
|
cglobal invalidate_block_edi
|
||||||
|
cglobal write_rdram_new
|
||||||
|
cglobal write_rdramb_new
|
||||||
|
cglobal write_rdramh_new
|
||||||
|
cglobal write_rdramd_new
|
||||||
|
cglobal read_nomem_new
|
||||||
|
cglobal read_nomemb_new
|
||||||
|
cglobal read_nomemh_new
|
||||||
|
cglobal read_nomemd_new
|
||||||
|
cglobal write_nomem_new
|
||||||
|
cglobal write_nomemb_new
|
||||||
|
cglobal write_nomemh_new
|
||||||
|
cglobal write_nomemd_new
|
||||||
|
cglobal breakpoint
|
||||||
|
|
||||||
|
cextern base_addr
|
||||||
|
cextern tlb_LUT_r
|
||||||
|
cextern jump_in
|
||||||
|
cextern add_link
|
||||||
|
cextern hash_table
|
||||||
|
cextern jump_dirty
|
||||||
|
cextern new_recompile_block
|
||||||
|
cextern g_cp0_regs
|
||||||
|
cextern get_addr_ht
|
||||||
|
cextern cycle_count
|
||||||
|
cextern get_addr
|
||||||
|
cextern branch_target
|
||||||
|
cextern memory_map
|
||||||
|
cextern pending_exception
|
||||||
|
cextern restore_candidate
|
||||||
|
cextern gen_interupt
|
||||||
|
cextern next_interupt
|
||||||
|
cextern stop
|
||||||
|
cextern last_count
|
||||||
|
cextern pcaddr
|
||||||
|
cextern clean_blocks
|
||||||
|
cextern reg
|
||||||
|
cextern hi
|
||||||
|
cextern lo
|
||||||
|
cextern invalidate_block
|
||||||
|
cextern address
|
||||||
|
cextern g_rdram
|
||||||
|
cextern cpu_byte
|
||||||
|
cextern cpu_hword
|
||||||
|
cextern cpu_word
|
||||||
|
cextern cpu_dword
|
||||||
|
cextern invalid_code
|
||||||
|
cextern readmem_dword
|
||||||
|
cextern check_interupt
|
||||||
|
cextern get_addr_32
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
align 4
|
||||||
|
|
||||||
|
section .rodata
|
||||||
|
section .text
|
||||||
|
|
||||||
|
dyna_linker:
|
||||||
|
;eax = virtual target address
|
||||||
|
;ebx = instruction to patch
|
||||||
|
mov edi, eax
|
||||||
|
mov ecx, eax
|
||||||
|
shr edi, 12
|
||||||
|
cmp eax, 0C0000000h
|
||||||
|
cmovge ecx, [tlb_LUT_r+edi*4]
|
||||||
|
test ecx, ecx
|
||||||
|
cmovz ecx, eax
|
||||||
|
xor ecx, 080000000h
|
||||||
|
mov edx, 2047
|
||||||
|
shr ecx, 12
|
||||||
|
and edx, ecx
|
||||||
|
or edx, 2048
|
||||||
|
cmp ecx, edx
|
||||||
|
cmova ecx, edx
|
||||||
|
;jump_in lookup
|
||||||
|
mov edx, [jump_in+ecx*4]
|
||||||
|
_A1:
|
||||||
|
test edx, edx
|
||||||
|
je _A3
|
||||||
|
mov edi, [edx]
|
||||||
|
xor edi, eax
|
||||||
|
or edi, [4+edx]
|
||||||
|
je _A2
|
||||||
|
mov edx, DWORD [12+edx]
|
||||||
|
jmp _A1
|
||||||
|
_A2:
|
||||||
|
mov edi, [ebx]
|
||||||
|
mov ebp, esi
|
||||||
|
lea esi, [4+ebx+edi*1]
|
||||||
|
mov edi, eax
|
||||||
|
pusha
|
||||||
|
call add_link
|
||||||
|
popa
|
||||||
|
mov edi, [8+edx]
|
||||||
|
mov esi, ebp
|
||||||
|
lea edx, [-4+edi]
|
||||||
|
sub edx, ebx
|
||||||
|
mov DWORD [ebx], edx
|
||||||
|
jmp edi
|
||||||
|
_A3:
|
||||||
|
;hash_table lookup
|
||||||
|
mov edi, eax
|
||||||
|
mov edx, eax
|
||||||
|
shr edi, 16
|
||||||
|
shr edx, 12
|
||||||
|
xor edi, eax
|
||||||
|
and edx, 2047
|
||||||
|
movzx edi, di
|
||||||
|
shl edi, 4
|
||||||
|
cmp ecx, 2048
|
||||||
|
cmovc ecx, edx
|
||||||
|
cmp eax, [hash_table+edi]
|
||||||
|
jne _A5
|
||||||
|
_A4:
|
||||||
|
mov edx, [hash_table+4+edi]
|
||||||
|
jmp edx
|
||||||
|
_A5:
|
||||||
|
cmp eax, [hash_table+8+edi]
|
||||||
|
lea edi, [8+edi]
|
||||||
|
je _A4
|
||||||
|
;jump_dirty lookup
|
||||||
|
mov edx, [jump_dirty+ecx*4]
|
||||||
|
_A6:
|
||||||
|
test edx, edx
|
||||||
|
je _A8
|
||||||
|
mov ecx, [edx]
|
||||||
|
xor ecx, eax
|
||||||
|
or ecx, [4+edx]
|
||||||
|
je _A7
|
||||||
|
mov edx, DWORD [12+edx]
|
||||||
|
jmp _A6
|
||||||
|
_A7:
|
||||||
|
mov edx, [8+edx]
|
||||||
|
;hash_table insert
|
||||||
|
mov ebx, [hash_table-8+edi]
|
||||||
|
mov ecx, [hash_table-4+edi]
|
||||||
|
mov [hash_table-8+edi], eax
|
||||||
|
mov [hash_table-4+edi], edx
|
||||||
|
mov [hash_table+edi], ebx
|
||||||
|
mov [hash_table+4+edi], ecx
|
||||||
|
jmp edx
|
||||||
|
_A8:
|
||||||
|
mov edi, eax
|
||||||
|
pusha
|
||||||
|
call new_recompile_block
|
||||||
|
test eax, eax
|
||||||
|
popa
|
||||||
|
je dyna_linker
|
||||||
|
;pagefault
|
||||||
|
mov ebx, eax
|
||||||
|
mov ecx, 008h
|
||||||
|
|
||||||
|
exec_pagefault:
|
||||||
|
;eax = instruction pointer
|
||||||
|
;ebx = fault address
|
||||||
|
;ecx = cause
|
||||||
|
mov edx, [g_cp0_regs+48]
|
||||||
|
add esp, -12
|
||||||
|
mov edi, [g_cp0_regs+16]
|
||||||
|
or edx, 2
|
||||||
|
mov [g_cp0_regs+32], ebx ;BadVAddr
|
||||||
|
and edi, 0FF80000Fh
|
||||||
|
mov [g_cp0_regs+48], edx ;Status
|
||||||
|
mov [g_cp0_regs+52], ecx ;Cause
|
||||||
|
mov [g_cp0_regs+56], eax ;EPC
|
||||||
|
mov ecx, ebx
|
||||||
|
shr ebx, 9
|
||||||
|
and ecx, 0FFFFE000h
|
||||||
|
and ebx, 0007FFFF0h
|
||||||
|
mov [g_cp0_regs+40], ecx ;EntryHI
|
||||||
|
or edi, ebx
|
||||||
|
mov [g_cp0_regs+16], edi ;Context
|
||||||
|
push 080000000h
|
||||||
|
call get_addr_ht
|
||||||
|
add esp, 16
|
||||||
|
jmp eax
|
||||||
|
|
||||||
|
;Special dynamic linker for the case where a page fault
|
||||||
|
;may occur in a branch delay slot
|
||||||
|
dyna_linker_ds:
|
||||||
|
mov edi, eax
|
||||||
|
mov ecx, eax
|
||||||
|
shr edi, 12
|
||||||
|
cmp eax, 0C0000000h
|
||||||
|
cmovge ecx, [tlb_LUT_r+edi*4]
|
||||||
|
test ecx, ecx
|
||||||
|
cmovz ecx, eax
|
||||||
|
xor ecx, 080000000h
|
||||||
|
mov edx, 2047
|
||||||
|
shr ecx, 12
|
||||||
|
and edx, ecx
|
||||||
|
or edx, 2048
|
||||||
|
cmp ecx, edx
|
||||||
|
cmova ecx, edx
|
||||||
|
;jump_in lookup
|
||||||
|
mov edx, [jump_in+ecx*4]
|
||||||
|
_B1:
|
||||||
|
test edx, edx
|
||||||
|
je _B3
|
||||||
|
mov edi, [edx]
|
||||||
|
xor edi, eax
|
||||||
|
or edi, [4+edx]
|
||||||
|
je _B2
|
||||||
|
mov edx, DWORD [12+edx]
|
||||||
|
jmp _B1
|
||||||
|
_B2:
|
||||||
|
mov edi, [ebx]
|
||||||
|
mov ecx, esi
|
||||||
|
lea esi, [4+ebx+edi*1]
|
||||||
|
mov edi, eax
|
||||||
|
pusha
|
||||||
|
call add_link
|
||||||
|
popa
|
||||||
|
mov edi, [8+edx]
|
||||||
|
mov esi, ecx
|
||||||
|
lea edx, [-4+edi]
|
||||||
|
sub edx, ebx
|
||||||
|
mov DWORD [ebx], edx
|
||||||
|
jmp edi
|
||||||
|
_B3:
|
||||||
|
;hash_table lookup
|
||||||
|
mov edi, eax
|
||||||
|
mov edx, eax
|
||||||
|
shr edi, 16
|
||||||
|
shr edx, 12
|
||||||
|
xor edi, eax
|
||||||
|
and edx, 2047
|
||||||
|
movzx edi, di
|
||||||
|
shl edi, 4
|
||||||
|
cmp ecx, 2048
|
||||||
|
cmovc ecx, edx
|
||||||
|
cmp eax, [hash_table+edi]
|
||||||
|
jne _B5
|
||||||
|
_B4:
|
||||||
|
mov edx, [hash_table+4+edi]
|
||||||
|
jmp edx
|
||||||
|
_B5:
|
||||||
|
cmp eax, [hash_table+8+edi]
|
||||||
|
lea edi, [8+edi]
|
||||||
|
je _B4
|
||||||
|
;jump_dirty lookup
|
||||||
|
mov edx, [jump_dirty+ecx*4]
|
||||||
|
_B6:
|
||||||
|
test edx, edx
|
||||||
|
je _B8
|
||||||
|
mov ecx, [edx]
|
||||||
|
xor ecx, eax
|
||||||
|
or ecx, [4+edx]
|
||||||
|
je _B7
|
||||||
|
mov edx, DWORD [12+edx]
|
||||||
|
jmp _B6
|
||||||
|
_B7:
|
||||||
|
mov edx, [8+edx]
|
||||||
|
;hash_table insert
|
||||||
|
mov ebx, [hash_table-8+edi]
|
||||||
|
mov ecx, [hash_table-4+edi]
|
||||||
|
mov [hash_table-8+edi], eax
|
||||||
|
mov [hash_table-4+edi], edx
|
||||||
|
mov [hash_table+edi], ebx
|
||||||
|
mov [hash_table+4+edi], ecx
|
||||||
|
jmp edx
|
||||||
|
_B8:
|
||||||
|
mov edi, eax
|
||||||
|
and edi, 0FFFFFFF8h
|
||||||
|
inc edi
|
||||||
|
pusha
|
||||||
|
call new_recompile_block
|
||||||
|
test eax, eax
|
||||||
|
popa
|
||||||
|
je dyna_linker_ds
|
||||||
|
;pagefault
|
||||||
|
and eax, 0FFFFFFF8h
|
||||||
|
mov ecx, 080000008h ;High bit set indicates pagefault in delay slot
|
||||||
|
mov ebx, eax
|
||||||
|
sub eax, 4
|
||||||
|
jmp exec_pagefault
|
||||||
|
|
||||||
|
jump_vaddr_eax:
|
||||||
|
mov edi, eax
|
||||||
|
jmp jump_vaddr_edi
|
||||||
|
|
||||||
|
jump_vaddr_ecx:
|
||||||
|
mov edi, ecx
|
||||||
|
jmp jump_vaddr_edi
|
||||||
|
|
||||||
|
jump_vaddr_edx:
|
||||||
|
mov edi, edx
|
||||||
|
jmp jump_vaddr_edi
|
||||||
|
|
||||||
|
jump_vaddr_ebx:
|
||||||
|
mov edi, ebx
|
||||||
|
jmp jump_vaddr_edi
|
||||||
|
|
||||||
|
jump_vaddr_ebp:
|
||||||
|
mov edi, ebp
|
||||||
|
|
||||||
|
jump_vaddr_edi:
|
||||||
|
mov eax, edi
|
||||||
|
|
||||||
|
jump_vaddr:
|
||||||
|
;Check hash table
|
||||||
|
shr eax, 16
|
||||||
|
xor eax, edi
|
||||||
|
movzx eax, ax
|
||||||
|
shl eax, 4
|
||||||
|
cmp edi, [hash_table+eax]
|
||||||
|
jne _C2
|
||||||
|
_C1:
|
||||||
|
mov edi, [hash_table+4+eax]
|
||||||
|
jmp edi
|
||||||
|
_C2:
|
||||||
|
cmp edi, [hash_table+8+eax]
|
||||||
|
lea eax, [8+eax]
|
||||||
|
je _C1
|
||||||
|
;No hit on hash table, call compiler
|
||||||
|
add esp, -12
|
||||||
|
push edi
|
||||||
|
mov [cycle_count], esi ;CCREG
|
||||||
|
call get_addr
|
||||||
|
mov esi, [cycle_count]
|
||||||
|
add esp, 16
|
||||||
|
jmp eax
|
||||||
|
|
||||||
|
verify_code_ds:
|
||||||
|
mov [branch_target], ebp
|
||||||
|
|
||||||
|
verify_code_vm:
|
||||||
|
;eax = source (virtual address)
|
||||||
|
;ebx = target
|
||||||
|
;ecx = length
|
||||||
|
cmp eax, 0C0000000h
|
||||||
|
jl verify_code
|
||||||
|
mov edx, eax
|
||||||
|
lea ebp, [-1+eax+ecx*1]
|
||||||
|
shr edx, 12
|
||||||
|
shr ebp, 12
|
||||||
|
mov edi, [memory_map+edx*4]
|
||||||
|
test edi, edi
|
||||||
|
js _D5
|
||||||
|
lea eax, [eax+edi*4]
|
||||||
|
_D1:
|
||||||
|
xor edi, [memory_map+edx*4]
|
||||||
|
shl edi, 2
|
||||||
|
jne _D5
|
||||||
|
mov edi, [memory_map+edx*4]
|
||||||
|
inc edx
|
||||||
|
cmp edx, ebp
|
||||||
|
jbe _D1
|
||||||
|
|
||||||
|
verify_code:
|
||||||
|
;eax = source
|
||||||
|
;ebx = target
|
||||||
|
;ecx = length
|
||||||
|
mov edi, [-4+eax+ecx*1]
|
||||||
|
xor edi, [-4+ebx+ecx*1]
|
||||||
|
jne _D5
|
||||||
|
mov edx, ecx
|
||||||
|
add ecx, -4
|
||||||
|
je _D3
|
||||||
|
test edx, 4
|
||||||
|
cmove ecx, edx
|
||||||
|
mov [cycle_count], esi
|
||||||
|
_D2:
|
||||||
|
mov edx, [-4+eax+ecx*1]
|
||||||
|
mov ebp, [-4+ebx+ecx*1]
|
||||||
|
mov esi, [-8+eax+ecx*1]
|
||||||
|
xor ebp, edx
|
||||||
|
mov edi, [-8+ebx+ecx*1]
|
||||||
|
jne _D4
|
||||||
|
xor edi, esi
|
||||||
|
jne _D4
|
||||||
|
add ecx, -8
|
||||||
|
jne _D2
|
||||||
|
mov esi, [cycle_count]
|
||||||
|
mov ebp, [branch_target]
|
||||||
|
_D3:
|
||||||
|
ret
|
||||||
|
_D4:
|
||||||
|
mov esi, [cycle_count]
|
||||||
|
_D5:
|
||||||
|
mov ebp, [branch_target]
|
||||||
|
push esi ;for stack alignment, unused
|
||||||
|
push DWORD [8+esp]
|
||||||
|
call get_addr
|
||||||
|
add esp, 16 ;pop stack
|
||||||
|
jmp eax
|
||||||
|
|
||||||
|
cc_interrupt:
|
||||||
|
add esi, [last_count]
|
||||||
|
add esp, -28 ;Align stack
|
||||||
|
mov [g_cp0_regs+36], esi ;Count
|
||||||
|
shr esi, 19
|
||||||
|
mov DWORD [pending_exception], 0
|
||||||
|
and esi, 07fh
|
||||||
|
cmp DWORD [restore_candidate+esi*4], 0
|
||||||
|
jne _E4
|
||||||
|
_E1:
|
||||||
|
call gen_interupt
|
||||||
|
mov esi, [g_cp0_regs+36]
|
||||||
|
mov eax, [next_interupt]
|
||||||
|
mov ebx, [pending_exception]
|
||||||
|
mov ecx, [stop]
|
||||||
|
add esp, 28
|
||||||
|
mov [last_count], eax
|
||||||
|
sub esi, eax
|
||||||
|
test ecx, ecx
|
||||||
|
jne _E3
|
||||||
|
test ebx, ebx
|
||||||
|
jne _E2
|
||||||
|
ret
|
||||||
|
_E2:
|
||||||
|
add esp, -8
|
||||||
|
mov edi, [pcaddr]
|
||||||
|
mov [cycle_count], esi ;CCREG
|
||||||
|
push edi
|
||||||
|
call get_addr_ht
|
||||||
|
mov esi, [cycle_count]
|
||||||
|
add esp, 16
|
||||||
|
jmp eax
|
||||||
|
_E3:
|
||||||
|
add esp, 16 ;pop stack
|
||||||
|
pop edi ;restore edi
|
||||||
|
pop esi ;restore esi
|
||||||
|
pop ebx ;restore ebx
|
||||||
|
pop ebp ;restore ebp
|
||||||
|
ret ;exit dynarec
|
||||||
|
_E4:
|
||||||
|
;Move 'dirty' blocks to the 'clean' list
|
||||||
|
mov ebx, [restore_candidate+esi*4]
|
||||||
|
mov ebp, esi
|
||||||
|
mov DWORD [restore_candidate+esi*4], 0
|
||||||
|
shl ebp, 5
|
||||||
|
_E5:
|
||||||
|
shr ebx, 1
|
||||||
|
jnc _E6
|
||||||
|
mov [esp], ebp
|
||||||
|
call clean_blocks
|
||||||
|
_E6:
|
||||||
|
inc ebp
|
||||||
|
test ebp, 31
|
||||||
|
jne _E5
|
||||||
|
jmp _E1
|
||||||
|
|
||||||
|
do_interrupt:
|
||||||
|
mov edi, [pcaddr]
|
||||||
|
add esp, -12
|
||||||
|
push edi
|
||||||
|
call get_addr_ht
|
||||||
|
add esp, 16
|
||||||
|
mov esi, [g_cp0_regs+36]
|
||||||
|
mov ebx, [next_interupt]
|
||||||
|
mov [last_count], ebx
|
||||||
|
sub esi, ebx
|
||||||
|
add esi, 2
|
||||||
|
jmp eax
|
||||||
|
|
||||||
|
fp_exception:
|
||||||
|
mov edx, 01000002ch
|
||||||
|
_E7:
|
||||||
|
mov ebx, [g_cp0_regs+48]
|
||||||
|
add esp, -12
|
||||||
|
or ebx, 2
|
||||||
|
mov [g_cp0_regs+48], ebx ;Status
|
||||||
|
mov [g_cp0_regs+52], edx ;Cause
|
||||||
|
mov [g_cp0_regs+56], eax ;EPC
|
||||||
|
push 080000180h
|
||||||
|
call get_addr_ht
|
||||||
|
add esp, 16
|
||||||
|
jmp eax
|
||||||
|
|
||||||
|
fp_exception_ds:
|
||||||
|
mov edx, 09000002ch ;Set high bit if delay slot
|
||||||
|
jmp _E7
|
||||||
|
|
||||||
|
jump_syscall:
|
||||||
|
mov edx, 020h
|
||||||
|
mov ebx, [g_cp0_regs+48]
|
||||||
|
add esp, -12
|
||||||
|
or ebx, 2
|
||||||
|
mov [g_cp0_regs+48], ebx ;Status
|
||||||
|
mov [g_cp0_regs+52], edx ;Cause
|
||||||
|
mov [g_cp0_regs+56], eax ;EPC
|
||||||
|
push 080000180h
|
||||||
|
call get_addr_ht
|
||||||
|
add esp, 16
|
||||||
|
jmp eax
|
||||||
|
|
||||||
|
jump_eret:
|
||||||
|
mov ebx, [g_cp0_regs+48] ;Status
|
||||||
|
add esi, [last_count]
|
||||||
|
and ebx, 0FFFFFFFDh
|
||||||
|
mov [g_cp0_regs+36], esi ;Count
|
||||||
|
mov [g_cp0_regs+48], ebx ;Status
|
||||||
|
call check_interupt
|
||||||
|
mov eax, [next_interupt]
|
||||||
|
mov esi, [g_cp0_regs+36]
|
||||||
|
mov [last_count], eax
|
||||||
|
sub esi, eax
|
||||||
|
mov eax, [g_cp0_regs+56] ;EPC
|
||||||
|
jns _E11
|
||||||
|
_E8:
|
||||||
|
mov ebx, 248
|
||||||
|
xor edi, edi
|
||||||
|
_E9:
|
||||||
|
mov ecx, [reg+ebx]
|
||||||
|
mov edx, [reg+4+ebx]
|
||||||
|
sar ecx, 31
|
||||||
|
xor edx, ecx
|
||||||
|
neg edx
|
||||||
|
adc edi, edi
|
||||||
|
sub ebx, 8
|
||||||
|
jne _E9
|
||||||
|
mov ecx, [hi+ebx]
|
||||||
|
mov edx, [hi+4+ebx]
|
||||||
|
sar ecx, 31
|
||||||
|
xor edx, ecx
|
||||||
|
jne _E10
|
||||||
|
mov ecx, [lo+ebx]
|
||||||
|
mov edx, [lo+4+ebx]
|
||||||
|
sar ecx, 31
|
||||||
|
xor edx, ecx
|
||||||
|
_E10:
|
||||||
|
neg edx
|
||||||
|
adc edi, edi
|
||||||
|
add esp, -8
|
||||||
|
push edi
|
||||||
|
push eax
|
||||||
|
mov [cycle_count], esi
|
||||||
|
call get_addr_32
|
||||||
|
mov esi, [cycle_count]
|
||||||
|
add esp, 16
|
||||||
|
jmp eax
|
||||||
|
_E11:
|
||||||
|
mov [pcaddr], eax
|
||||||
|
call cc_interrupt
|
||||||
|
mov eax, [pcaddr]
|
||||||
|
jmp _E8
|
||||||
|
|
||||||
|
new_dyna_start:
|
||||||
|
push ebp
|
||||||
|
push ebx
|
||||||
|
push esi
|
||||||
|
push edi
|
||||||
|
add esp, -8 ;align stack
|
||||||
|
push 0a4000040h
|
||||||
|
call new_recompile_block
|
||||||
|
mov edi, DWORD [next_interupt]
|
||||||
|
mov esi, DWORD [g_cp0_regs+36]
|
||||||
|
mov DWORD [last_count], edi
|
||||||
|
sub esi, edi
|
||||||
|
jmp DWORD [base_addr]
|
||||||
|
|
||||||
|
invalidate_block_eax:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
push eax
|
||||||
|
jmp invalidate_block_call
|
||||||
|
|
||||||
|
invalidate_block_ecx:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
push ecx
|
||||||
|
jmp invalidate_block_call
|
||||||
|
|
||||||
|
invalidate_block_edx:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
push edx
|
||||||
|
jmp invalidate_block_call
|
||||||
|
|
||||||
|
invalidate_block_ebx:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
push ebx
|
||||||
|
jmp invalidate_block_call
|
||||||
|
|
||||||
|
invalidate_block_ebp:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
push ebp
|
||||||
|
jmp invalidate_block_call
|
||||||
|
|
||||||
|
invalidate_block_esi:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
push esi
|
||||||
|
jmp invalidate_block_call
|
||||||
|
|
||||||
|
invalidate_block_edi:
|
||||||
|
push eax
|
||||||
|
push ecx
|
||||||
|
push edx
|
||||||
|
push edi
|
||||||
|
|
||||||
|
invalidate_block_call:
|
||||||
|
call invalidate_block
|
||||||
|
pop eax ;Throw away
|
||||||
|
pop edx
|
||||||
|
pop ecx
|
||||||
|
pop eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
write_rdram_new:
|
||||||
|
mov edi, [address]
|
||||||
|
mov ecx, [cpu_word]
|
||||||
|
mov [g_rdram-0x80000000+edi], ecx
|
||||||
|
jmp _E12
|
||||||
|
|
||||||
|
write_rdramb_new:
|
||||||
|
mov edi, [address]
|
||||||
|
xor edi, 3
|
||||||
|
mov cl, BYTE [cpu_byte]
|
||||||
|
mov BYTE [g_rdram-0x80000000+edi], cl
|
||||||
|
jmp _E12
|
||||||
|
|
||||||
|
write_rdramh_new:
|
||||||
|
mov edi, [address]
|
||||||
|
xor edi, 2
|
||||||
|
mov cx, WORD [cpu_hword]
|
||||||
|
mov WORD [g_rdram-0x80000000+edi], cx
|
||||||
|
jmp _E12
|
||||||
|
|
||||||
|
write_rdramd_new:
|
||||||
|
mov edi, [address]
|
||||||
|
mov ecx, [cpu_dword+4]
|
||||||
|
mov edx, [cpu_dword+0]
|
||||||
|
mov [g_rdram-0x80000000+edi], ecx
|
||||||
|
mov [g_rdram-0x80000000+4+edi], edx
|
||||||
|
jmp _E12
|
||||||
|
|
||||||
|
|
||||||
|
do_invalidate:
|
||||||
|
mov edi, [address]
|
||||||
|
mov ebx, edi ;Return ebx to caller
|
||||||
|
_E12:
|
||||||
|
shr edi, 12
|
||||||
|
cmp BYTE [invalid_code+edi], 1
|
||||||
|
je _E13
|
||||||
|
push edi
|
||||||
|
call invalidate_block
|
||||||
|
pop edi
|
||||||
|
_E13:
|
||||||
|
ret
|
||||||
|
|
||||||
|
read_nomem_new:
|
||||||
|
mov edi, [address]
|
||||||
|
mov ebx, edi
|
||||||
|
shr edi, 12
|
||||||
|
mov edi, [memory_map+edi*4]
|
||||||
|
mov eax, 08h
|
||||||
|
test edi, edi
|
||||||
|
js tlb_exception
|
||||||
|
mov ecx, [ebx+edi*4]
|
||||||
|
mov [readmem_dword], ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
read_nomemb_new:
|
||||||
|
mov edi, [address]
|
||||||
|
mov ebx, edi
|
||||||
|
shr edi, 12
|
||||||
|
mov edi, [memory_map+edi*4]
|
||||||
|
mov eax, 08h
|
||||||
|
test edi, edi
|
||||||
|
js tlb_exception
|
||||||
|
xor ebx, 3
|
||||||
|
movzx ecx, BYTE [ebx+edi*4]
|
||||||
|
mov [readmem_dword], ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
read_nomemh_new:
|
||||||
|
mov edi, [address]
|
||||||
|
mov ebx, edi
|
||||||
|
shr edi, 12
|
||||||
|
mov edi, [memory_map+edi*4]
|
||||||
|
mov eax, 08h
|
||||||
|
test edi, edi
|
||||||
|
js tlb_exception
|
||||||
|
xor ebx, 2
|
||||||
|
movzx ecx, WORD [ebx+edi*4]
|
||||||
|
mov [readmem_dword], ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
read_nomemd_new:
|
||||||
|
mov edi, [address]
|
||||||
|
mov ebx, edi
|
||||||
|
shr edi, 12
|
||||||
|
mov edi, [memory_map+edi*4]
|
||||||
|
mov eax, 08h
|
||||||
|
test edi, edi
|
||||||
|
js tlb_exception
|
||||||
|
mov ecx, [4+ebx+edi*4]
|
||||||
|
mov edx, [ebx+edi*4]
|
||||||
|
mov [readmem_dword], ecx
|
||||||
|
mov [readmem_dword+4], edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
write_nomem_new:
|
||||||
|
call do_invalidate
|
||||||
|
mov edi, [memory_map+edi*4]
|
||||||
|
mov ecx, [cpu_word]
|
||||||
|
mov eax, 0ch
|
||||||
|
shl edi, 2
|
||||||
|
jc tlb_exception
|
||||||
|
mov [ebx+edi], ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
write_nomemb_new:
|
||||||
|
call do_invalidate
|
||||||
|
mov edi, [memory_map+edi*4]
|
||||||
|
mov cl, BYTE [cpu_byte]
|
||||||
|
mov eax, 0ch
|
||||||
|
shl edi, 2
|
||||||
|
jc tlb_exception
|
||||||
|
xor ebx, 3
|
||||||
|
mov BYTE [ebx+edi], cl
|
||||||
|
ret
|
||||||
|
|
||||||
|
write_nomemh_new:
|
||||||
|
call do_invalidate
|
||||||
|
mov edi, [memory_map+edi*4]
|
||||||
|
mov cx, WORD [cpu_hword]
|
||||||
|
mov eax, 0ch
|
||||||
|
shl edi, 2
|
||||||
|
jc tlb_exception
|
||||||
|
xor ebx, 2
|
||||||
|
mov WORD [ebx+edi], cx
|
||||||
|
ret
|
||||||
|
|
||||||
|
write_nomemd_new:
|
||||||
|
call do_invalidate
|
||||||
|
mov edi, [memory_map+edi*4]
|
||||||
|
mov edx, [cpu_dword+4]
|
||||||
|
mov ecx, [cpu_dword+0]
|
||||||
|
mov eax, 0ch
|
||||||
|
shl edi, 2
|
||||||
|
jc tlb_exception
|
||||||
|
mov [ebx+edi], edx
|
||||||
|
mov [4+ebx+edi], ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
tlb_exception:
|
||||||
|
;eax = cause
|
||||||
|
;ebx = address
|
||||||
|
;ebp = instr addr + flags
|
||||||
|
mov ebp, [024h+esp]
|
||||||
|
;Debug:
|
||||||
|
;push ebp
|
||||||
|
;push ebx
|
||||||
|
;push eax
|
||||||
|
;call tlb_debug
|
||||||
|
;pop eax
|
||||||
|
;pop ebx
|
||||||
|
;pop ebp
|
||||||
|
;end debug
|
||||||
|
mov esi, [g_cp0_regs+48]
|
||||||
|
mov ecx, ebp
|
||||||
|
mov edx, ebp
|
||||||
|
mov edi, ebp
|
||||||
|
shl ebp, 31
|
||||||
|
shr ecx, 12
|
||||||
|
or eax, ebp
|
||||||
|
sar ebp, 29
|
||||||
|
and edx, 0FFFFFFFCh
|
||||||
|
mov ecx, [memory_map+ecx*4]
|
||||||
|
or esi, 2
|
||||||
|
mov ecx, [edx+ecx*4]
|
||||||
|
add edx, ebp
|
||||||
|
mov [g_cp0_regs+48], esi ;Status
|
||||||
|
mov [g_cp0_regs+52], eax ;Cause
|
||||||
|
mov [g_cp0_regs+56], edx ;EPC
|
||||||
|
add esp, 024h
|
||||||
|
mov edx, 06000022h
|
||||||
|
mov ebp, ecx
|
||||||
|
movsx eax, cx
|
||||||
|
shr ecx, 26
|
||||||
|
shr ebp, 21
|
||||||
|
sub ebx, eax
|
||||||
|
and ebp, 01fh
|
||||||
|
ror edx, cl
|
||||||
|
mov esi, [g_cp0_regs+16]
|
||||||
|
cmovc ebx, [reg+ebp*8]
|
||||||
|
and esi, 0FF80000Fh
|
||||||
|
mov [reg+ebp*8], ebx
|
||||||
|
add eax, ebx
|
||||||
|
sar ebx, 31
|
||||||
|
mov [g_cp0_regs+32], eax ;BadVAddr
|
||||||
|
shr eax, 9
|
||||||
|
test edi, 2
|
||||||
|
cmove ebx, [reg+4+ebp*8]
|
||||||
|
add esp, -12
|
||||||
|
and eax, 0007FFFF0h
|
||||||
|
mov [reg+4+ebp*8], ebx
|
||||||
|
push 080000180h
|
||||||
|
or esi, eax
|
||||||
|
mov [g_cp0_regs+16], esi ;Context
|
||||||
|
call get_addr_ht
|
||||||
|
add esp, 16
|
||||||
|
mov edi, DWORD [next_interupt]
|
||||||
|
mov esi, DWORD [g_cp0_regs+36] ;Count
|
||||||
|
mov DWORD [last_count], edi
|
||||||
|
sub esi, edi
|
||||||
|
jmp eax
|
||||||
|
|
||||||
|
breakpoint:
|
11143
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/new_dynarec.c
Normal file
11143
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/new_dynarec.c
Normal file
File diff suppressed because it is too large
Load diff
44
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/new_dynarec.h
Normal file
44
Frameworks/lazyusf/lazyusf/r4300/new_dynarec/new_dynarec.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - new_dynarec.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_NEW_DYNAREC_H
|
||||||
|
#define M64P_R4300_NEW_DYNAREC_H
|
||||||
|
|
||||||
|
#define NEW_DYNAREC_X86 1
|
||||||
|
#define NEW_DYNAREC_AMD64 2
|
||||||
|
#define NEW_DYNAREC_ARM 3
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
extern int pcaddr;
|
||||||
|
extern int pending_exception;
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void invalidate_all_pages(void);
|
||||||
|
void invalidate_block(unsigned int block);
|
||||||
|
void new_dynarec_init(void);
|
||||||
|
void new_dyna_start(void);
|
||||||
|
void new_dynarec_cleanup(void);
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_NEW_DYNAREC_H */
|
327
Frameworks/lazyusf/lazyusf/r4300/ops.h
Normal file
327
Frameworks/lazyusf/lazyusf/r4300/ops.h
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - ops.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_OPS_H
|
||||||
|
#define M64P_R4300_OPS_H
|
||||||
|
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
typedef struct _cpu_instruction_table
|
||||||
|
{
|
||||||
|
/* All jump/branch instructions (except JR and JALR) have three versions:
|
||||||
|
* - JUMPNAME() which for jumps inside the current block.
|
||||||
|
* - JUMPNAME_OUT() which jumps outside the current block.
|
||||||
|
* - JUMPNAME_IDLE() which does busy wait optimization.
|
||||||
|
*
|
||||||
|
* Busy wait optimization is used when a jump jumps to itself,
|
||||||
|
* and the instruction on the delay slot is a NOP.
|
||||||
|
* The program is waiting for the next interrupt, so we can just
|
||||||
|
* increase Count until the point where the next interrupt happens. */
|
||||||
|
|
||||||
|
// Load and store instructions
|
||||||
|
void (osal_fastcall *LB)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LBU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LH)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LHU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LW)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LWL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LWR)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SB)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SH)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SW)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SWL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SWR)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *LD)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LDL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LDR)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LWU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SC)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SD)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SDL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SDR)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SYNC)(usf_state_t *);
|
||||||
|
|
||||||
|
// Arithmetic instructions (ALU immediate)
|
||||||
|
void (osal_fastcall *ADDI)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ADDIU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SLTI)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SLTIU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ANDI)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ORI)(usf_state_t *);
|
||||||
|
void (osal_fastcall *XORI)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LUI)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *DADDI)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DADDIU)(usf_state_t *);
|
||||||
|
|
||||||
|
// Arithmetic instructions (3-operand)
|
||||||
|
void (osal_fastcall *ADD)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ADDU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SUB)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SUBU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SLT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SLTU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *AND)(usf_state_t *);
|
||||||
|
void (osal_fastcall *OR)(usf_state_t *);
|
||||||
|
void (osal_fastcall *XOR)(usf_state_t *);
|
||||||
|
void (osal_fastcall *NOR)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *DADD)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DADDU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSUB)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSUBU)(usf_state_t *);
|
||||||
|
|
||||||
|
// Multiply and divide instructions
|
||||||
|
void (osal_fastcall *MULT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MULTU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DIV)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DIVU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MFHI)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MTHI)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MFLO)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MTLO)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *DMULT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DMULTU)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DDIV)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DDIVU)(usf_state_t *);
|
||||||
|
|
||||||
|
// Jump and branch instructions
|
||||||
|
void (osal_fastcall *J)(usf_state_t *);
|
||||||
|
void (osal_fastcall *J_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *J_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *JAL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *JAL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *JAL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *JR)(usf_state_t *);
|
||||||
|
void (osal_fastcall *JALR)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BEQ)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BEQ_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BEQ_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BNE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BNE_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BNE_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLEZ)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLEZ_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLEZ_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGTZ)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGTZ_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGTZ_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZ)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZ_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZ_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZ)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZ_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZ_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZAL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZAL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZAL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZAL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZAL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZAL_IDLE)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *BEQL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BEQL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BEQL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BNEL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BNEL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BNEL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLEZL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLEZL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLEZL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGTZL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGTZL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGTZL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZALL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZALL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BLTZALL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZALL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZALL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BGEZALL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1TL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1TL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1TL_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1FL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1FL_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1FL_IDLE)(usf_state_t *);
|
||||||
|
|
||||||
|
// Shift instructions
|
||||||
|
void (osal_fastcall *SLL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SRL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SRA)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SLLV)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SRLV)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SRAV)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *DSLL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSRL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSRA)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSLLV)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSRLV)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSRAV)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSLL32)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSRL32)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DSRA32)(usf_state_t *);
|
||||||
|
|
||||||
|
// COP0 instructions
|
||||||
|
void (osal_fastcall *MTC0)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MFC0)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *TLBR)(usf_state_t *);
|
||||||
|
void (osal_fastcall *TLBWI)(usf_state_t *);
|
||||||
|
void (osal_fastcall *TLBWR)(usf_state_t *);
|
||||||
|
void (osal_fastcall *TLBP)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CACHE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ERET)(usf_state_t *);
|
||||||
|
|
||||||
|
// COP1 instructions
|
||||||
|
void (osal_fastcall *LWC1)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SWC1)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MTC1)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MFC1)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CTC1)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CFC1)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1T)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1T_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1T_IDLE)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1F)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1F_OUT)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BC1F_IDLE)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *DMFC1)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DMTC1)(usf_state_t *);
|
||||||
|
void (osal_fastcall *LDC1)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SDC1)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *CVT_S_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CVT_S_W)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CVT_S_L)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CVT_D_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CVT_D_W)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CVT_D_L)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CVT_W_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CVT_W_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CVT_L_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CVT_L_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *ROUND_W_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ROUND_W_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ROUND_L_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ROUND_L_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *TRUNC_W_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *TRUNC_W_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *TRUNC_L_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *TRUNC_L_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *CEIL_W_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CEIL_W_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CEIL_L_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *CEIL_L_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *FLOOR_W_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *FLOOR_W_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *FLOOR_L_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *FLOOR_L_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *ADD_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ADD_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *SUB_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SUB_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *MUL_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MUL_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *DIV_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *DIV_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *ABS_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *ABS_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *MOV_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *MOV_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *NEG_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *NEG_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *SQRT_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *SQRT_D)(usf_state_t *);
|
||||||
|
|
||||||
|
void (osal_fastcall *C_F_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_F_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_UN_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_UN_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_EQ_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_EQ_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_UEQ_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_UEQ_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_OLT_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_OLT_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_ULT_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_ULT_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_OLE_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_OLE_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_ULE_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_ULE_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_SF_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_SF_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_NGLE_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_NGLE_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_SEQ_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_SEQ_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_NGL_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_NGL_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_LT_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_LT_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_NGE_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_NGE_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_LE_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_LE_D)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_NGT_S)(usf_state_t *);
|
||||||
|
void (osal_fastcall *C_NGT_D)(usf_state_t *);
|
||||||
|
|
||||||
|
// Special instructions
|
||||||
|
void (osal_fastcall *SYSCALL)(usf_state_t *);
|
||||||
|
void (osal_fastcall *BREAK)(usf_state_t *);
|
||||||
|
|
||||||
|
// Exception instructions
|
||||||
|
void (osal_fastcall *TEQ)(usf_state_t *);
|
||||||
|
|
||||||
|
// Emulator helper functions
|
||||||
|
void (osal_fastcall *NOP)(usf_state_t *); // No operation (used to nullify R0 writes)
|
||||||
|
void (osal_fastcall *RESERVED)(usf_state_t *); // Reserved instruction handler
|
||||||
|
void (osal_fastcall *NI)(usf_state_t *); // Not implemented instruction handler
|
||||||
|
|
||||||
|
void (osal_fastcall *FIN_BLOCK)(usf_state_t *); // Handler for the end of a block
|
||||||
|
void (osal_fastcall *NOTCOMPILED)(usf_state_t *); // Handler for not yet compiled code
|
||||||
|
void (osal_fastcall *NOTCOMPILED2)(usf_state_t *); // TODOXXX
|
||||||
|
} cpu_instruction_table;
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_OPS_H_*/
|
746
Frameworks/lazyusf/lazyusf/r4300/pure_interp.c
Normal file
746
Frameworks/lazyusf/lazyusf/r4300/pure_interp.c
Normal file
|
@ -0,0 +1,746 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - pure_interp.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2015 Nebuleon <nebuleon.fumika@gmail.com> *
|
||||||
|
* *
|
||||||
|
* 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 <stdint.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
#include "memory/memory.h"
|
||||||
|
#include "main/main.h"
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
/* TLBWrite requires invalid_code and blocks from cached_interp.h, but only if
|
||||||
|
* (at run time) the active core is not the Pure Interpreter. */
|
||||||
|
#include "cached_interp.h"
|
||||||
|
#include "r4300.h"
|
||||||
|
#include "cp0.h"
|
||||||
|
#include "cp1.h"
|
||||||
|
#include "exception.h"
|
||||||
|
#include "interupt.h"
|
||||||
|
#include "tlb.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
static void InterpretOpcode(usf_state_t * state);
|
||||||
|
|
||||||
|
#define PCADDR state->interp_PC.addr
|
||||||
|
#define ADD_TO_PC(x) state->interp_PC.addr += x*4;
|
||||||
|
#define DECLARE_INSTRUCTION(name) static void name(usf_state_t * state, uint32_t op)
|
||||||
|
#define DECLARE_JUMP(name, destination, condition, link, likely, cop1) \
|
||||||
|
static void name(usf_state_t * state, uint32_t op) \
|
||||||
|
{ \
|
||||||
|
const int take_jump = (condition); \
|
||||||
|
const unsigned int jump_target = (destination); \
|
||||||
|
long long int *link_register = (link); \
|
||||||
|
if (cop1 && check_cop1_unusable(state)) return; \
|
||||||
|
if (link_register != &state->reg[0]) \
|
||||||
|
{ \
|
||||||
|
*link_register=state->interp_PC.addr + 8; \
|
||||||
|
sign_extended(*link_register); \
|
||||||
|
} \
|
||||||
|
if (!likely || take_jump) \
|
||||||
|
{ \
|
||||||
|
state->interp_PC.addr += 4; \
|
||||||
|
state->delay_slot=1; \
|
||||||
|
InterpretOpcode(state); \
|
||||||
|
update_count(state); \
|
||||||
|
state->delay_slot=0; \
|
||||||
|
if (take_jump && !state->skip_jump) \
|
||||||
|
{ \
|
||||||
|
state->interp_PC.addr = jump_target; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
state->interp_PC.addr += 8; \
|
||||||
|
update_count(state); \
|
||||||
|
} \
|
||||||
|
state->last_addr = state->interp_PC.addr; \
|
||||||
|
if (state->next_interupt <= state->g_cp0_regs[CP0_COUNT_REG]) gen_interupt(state); \
|
||||||
|
} \
|
||||||
|
static void name##_IDLE(usf_state_t * state, uint32_t op) \
|
||||||
|
{ \
|
||||||
|
const int take_jump = (condition); \
|
||||||
|
int skip; \
|
||||||
|
if (cop1 && check_cop1_unusable(state)) return; \
|
||||||
|
if (take_jump) \
|
||||||
|
{ \
|
||||||
|
update_count(state); \
|
||||||
|
skip = state->next_interupt - state->g_cp0_regs[CP0_COUNT_REG]; \
|
||||||
|
if (skip > 3) state->g_cp0_regs[CP0_COUNT_REG] += (skip & 0xFFFFFFFC); \
|
||||||
|
else name(state, op); \
|
||||||
|
} \
|
||||||
|
else name(state, op); \
|
||||||
|
}
|
||||||
|
#define CHECK_MEMORY()
|
||||||
|
|
||||||
|
#define RD_OF(op) (((op) >> 11) & 0x1F)
|
||||||
|
#define RS_OF(op) (((op) >> 21) & 0x1F)
|
||||||
|
#define RT_OF(op) (((op) >> 16) & 0x1F)
|
||||||
|
#define SA_OF(op) (((op) >> 6) & 0x1F)
|
||||||
|
#define IMM16S_OF(op) ((int16_t) (op))
|
||||||
|
#define IMM16U_OF(op) ((uint16_t) (op))
|
||||||
|
#define FD_OF(op) (((op) >> 6) & 0x1F)
|
||||||
|
#define FS_OF(op) (((op) >> 11) & 0x1F)
|
||||||
|
#define FT_OF(op) (((op) >> 16) & 0x1F)
|
||||||
|
#define JUMP_OF(op) ((op) & UINT32_C(0x3FFFFFF))
|
||||||
|
|
||||||
|
/* Determines whether a relative jump in a 16-bit immediate goes back to the
|
||||||
|
* same instruction without doing any work in its delay slot. The jump is
|
||||||
|
* relative to the instruction in the delay slot, so 1 instruction backwards
|
||||||
|
* (-1) goes back to the jump. */
|
||||||
|
#define IS_RELATIVE_IDLE_LOOP(op, addr) \
|
||||||
|
(IMM16S_OF(op) == -1 && *fast_mem_access(state, (addr) + 4) == 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
|
||||||
|
* in the same 256 MiB segment as the delay slot, so if the jump instruction
|
||||||
|
* is at the last address in its segment, it does not jump back to itself. */
|
||||||
|
#define IS_ABSOLUTE_IDLE_LOOP(op, addr) \
|
||||||
|
(JUMP_OF(op) == ((addr) & UINT32_C(0x0FFFFFFF)) >> 2 \
|
||||||
|
&& ((addr) & UINT32_C(0x0FFFFFFF)) != UINT32_C(0x0FFFFFFC) \
|
||||||
|
&& *fast_mem_access(state, (addr) + 4) == 0)
|
||||||
|
|
||||||
|
#define sign_extended(a) a = (int64_t) ((int32_t) (a))
|
||||||
|
#define sign_extendedb(a) a = (int64_t) ((int8_t) (a))
|
||||||
|
#define sign_extendedh(a) a = (int64_t) ((int16_t) (a))
|
||||||
|
|
||||||
|
/* These macros are like those in macros.h, but they parse opcode fields. */
|
||||||
|
#define rrt state->reg[RT_OF(op)]
|
||||||
|
#define rrd state->reg[RD_OF(op)]
|
||||||
|
#define rfs FS_OF(op)
|
||||||
|
#define rrs state->reg[RS_OF(op)]
|
||||||
|
#define rsa SA_OF(op)
|
||||||
|
#define irt state->reg[RT_OF(op)]
|
||||||
|
#define ioffset IMM16S_OF(op)
|
||||||
|
#define iimmediate IMM16S_OF(op)
|
||||||
|
#define irs state->reg[RS_OF(op)]
|
||||||
|
#define ibase state->reg[RS_OF(op)]
|
||||||
|
#define jinst_index JUMP_OF(op)
|
||||||
|
#define lfbase RS_OF(op)
|
||||||
|
#define lfft FT_OF(op)
|
||||||
|
#define lfoffset IMM16S_OF(op)
|
||||||
|
#define cfft FT_OF(op)
|
||||||
|
#define cffs FS_OF(op)
|
||||||
|
#define cffd FD_OF(op)
|
||||||
|
|
||||||
|
// 32 bits macros
|
||||||
|
#ifndef M64P_BIG_ENDIAN
|
||||||
|
#define rrt32 *((int32_t*) &state->reg[RT_OF(op)])
|
||||||
|
#define rrd32 *((int32_t*) &state->reg[RD_OF(op)])
|
||||||
|
#define rrs32 *((int32_t*) &state->reg[RS_OF(op)])
|
||||||
|
#define irs32 *((int32_t*) &state->reg[RS_OF(op)])
|
||||||
|
#define irt32 *((int32_t*) &state->reg[RT_OF(op)])
|
||||||
|
#else
|
||||||
|
#define rrt32 *((int32_t*) &state->reg[RT_OF(op)] + 1)
|
||||||
|
#define rrd32 *((int32_t*) &state->reg[RD_OF(op)] + 1)
|
||||||
|
#define rrs32 *((int32_t*) &state->reg[RS_OF(op)] + 1)
|
||||||
|
#define irs32 *((int32_t*) &state->reg[RS_OF(op)] + 1)
|
||||||
|
#define irt32 *((int32_t*) &state->reg[RT_OF(op)] + 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// two functions are defined from the macros above but never used
|
||||||
|
// these prototype declarations will prevent a warning
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
static void JR_IDLE(usf_state_t *, uint32_t) __attribute__((used));
|
||||||
|
static void JALR_IDLE(usf_state_t *, uint32_t) __attribute__((used));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "interpreter.def"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
#include "debugger/dbg_decoder.h"
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void InterpretOpcode(usf_state_t * state)
|
||||||
|
{
|
||||||
|
uint32_t op = *fast_mem_access(state, state->PC->addr);
|
||||||
|
#ifdef DEBUG_INFO
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
char instr[256];
|
||||||
|
char arguments[256];
|
||||||
|
r4300_decode_op(op, instr, arguments, state->PC->addr);
|
||||||
|
fprintf(state->debug_log, "%08x: %-16s %s\n", state->PC->addr, instr, arguments);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
switch ((op >> 26) & 0x3F) {
|
||||||
|
case 0: /* SPECIAL prefix */
|
||||||
|
switch (op & 0x3F) {
|
||||||
|
case 0: /* SPECIAL opcode 0: SLL */
|
||||||
|
if (RD_OF(op) != 0) SLL(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 2: /* SPECIAL opcode 2: SRL */
|
||||||
|
if (RD_OF(op) != 0) SRL(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 3: /* SPECIAL opcode 3: SRA */
|
||||||
|
if (RD_OF(op) != 0) SRA(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 4: /* SPECIAL opcode 4: SLLV */
|
||||||
|
if (RD_OF(op) != 0) SLLV(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 6: /* SPECIAL opcode 6: SRLV */
|
||||||
|
if (RD_OF(op) != 0) SRLV(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 7: /* SPECIAL opcode 7: SRAV */
|
||||||
|
if (RD_OF(op) != 0) SRAV(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 8: JR(state, op); break;
|
||||||
|
case 9: /* SPECIAL opcode 9: JALR */
|
||||||
|
/* Note: This can omit the check for Rd == 0 because the JALR
|
||||||
|
* function checks for link_register != ®[0]. If you're
|
||||||
|
* using this as a reference for a JIT, do check Rd == 0 in it. */
|
||||||
|
JALR(state, op);
|
||||||
|
break;
|
||||||
|
case 12: SYSCALL(state, op); break;
|
||||||
|
case 13: /* SPECIAL opcode 13: BREAK */
|
||||||
|
BREAK(state, op);
|
||||||
|
break;
|
||||||
|
case 15: SYNC(state, op); break;
|
||||||
|
case 16: /* SPECIAL opcode 16: MFHI */
|
||||||
|
if (RD_OF(op) != 0) MFHI(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 17: MTHI(state, op); break;
|
||||||
|
case 18: /* SPECIAL opcode 18: MFLO */
|
||||||
|
if (RD_OF(op) != 0) MFLO(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 19: MTLO(state, op); break;
|
||||||
|
case 20: /* SPECIAL opcode 20: DSLLV */
|
||||||
|
if (RD_OF(op) != 0) DSLLV(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 22: /* SPECIAL opcode 22: DSRLV */
|
||||||
|
if (RD_OF(op) != 0) DSRLV(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 23: /* SPECIAL opcode 23: DSRAV */
|
||||||
|
if (RD_OF(op) != 0) DSRAV(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 24: MULT(state, op); break;
|
||||||
|
case 25: MULTU(state, op); break;
|
||||||
|
case 26: DIV(state, op); break;
|
||||||
|
case 27: DIVU(state, op); break;
|
||||||
|
case 28: DMULT(state, op); break;
|
||||||
|
case 29: DMULTU(state, op); break;
|
||||||
|
case 30: DDIV(state, op); break;
|
||||||
|
case 31: DDIVU(state, op); break;
|
||||||
|
case 32: /* SPECIAL opcode 32: ADD */
|
||||||
|
if (RD_OF(op) != 0) ADD(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 33: /* SPECIAL opcode 33: ADDU */
|
||||||
|
if (RD_OF(op) != 0) ADDU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 34: /* SPECIAL opcode 34: SUB */
|
||||||
|
if (RD_OF(op) != 0) SUB(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 35: /* SPECIAL opcode 35: SUBU */
|
||||||
|
if (RD_OF(op) != 0) SUBU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 36: /* SPECIAL opcode 36: AND */
|
||||||
|
if (RD_OF(op) != 0) AND(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 37: /* SPECIAL opcode 37: OR */
|
||||||
|
if (RD_OF(op) != 0) OR(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 38: /* SPECIAL opcode 38: XOR */
|
||||||
|
if (RD_OF(op) != 0) XOR(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 39: /* SPECIAL opcode 39: NOR */
|
||||||
|
if (RD_OF(op) != 0) NOR(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 42: /* SPECIAL opcode 42: SLT */
|
||||||
|
if (RD_OF(op) != 0) SLT(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 43: /* SPECIAL opcode 43: SLTU */
|
||||||
|
if (RD_OF(op) != 0) SLTU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 44: /* SPECIAL opcode 44: DADD */
|
||||||
|
if (RD_OF(op) != 0) DADD(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 45: /* SPECIAL opcode 45: DADDU */
|
||||||
|
if (RD_OF(op) != 0) DADDU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 46: /* SPECIAL opcode 46: DSUB */
|
||||||
|
if (RD_OF(op) != 0) DSUB(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 47: /* SPECIAL opcode 47: DSUBU */
|
||||||
|
if (RD_OF(op) != 0) DSUBU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 48: /* SPECIAL opcode 48: TGE (Not implemented) */
|
||||||
|
case 49: /* SPECIAL opcode 49: TGEU (Not implemented) */
|
||||||
|
case 50: /* SPECIAL opcode 50: TLT (Not implemented) */
|
||||||
|
case 51: /* SPECIAL opcode 51: TLTU (Not implemented) */
|
||||||
|
NI(state, op);
|
||||||
|
break;
|
||||||
|
case 52: TEQ(state, op); break;
|
||||||
|
case 54: /* SPECIAL opcode 54: TNE (Not implemented) */
|
||||||
|
NI(state, op);
|
||||||
|
break;
|
||||||
|
case 56: /* SPECIAL opcode 56: DSLL */
|
||||||
|
if (RD_OF(op) != 0) DSLL(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 58: /* SPECIAL opcode 58: DSRL */
|
||||||
|
if (RD_OF(op) != 0) DSRL(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 59: /* SPECIAL opcode 59: DSRA */
|
||||||
|
if (RD_OF(op) != 0) DSRA(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 60: /* SPECIAL opcode 60: DSLL32 */
|
||||||
|
if (RD_OF(op) != 0) DSLL32(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 62: /* SPECIAL opcode 62: DSRL32 */
|
||||||
|
if (RD_OF(op) != 0) DSRL32(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 63: /* SPECIAL opcode 63: DSRA32 */
|
||||||
|
if (RD_OF(op) != 0) DSRA32(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
default: /* SPECIAL opcodes 1, 5, 10, 11, 14, 21, 40, 41, 53, 55, 57,
|
||||||
|
61: Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
} /* switch (op & 0x3F) for the SPECIAL prefix */
|
||||||
|
break;
|
||||||
|
case 1: /* REGIMM prefix */
|
||||||
|
switch ((op >> 16) & 0x1F) {
|
||||||
|
case 0: /* REGIMM opcode 0: BLTZ */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BLTZ_IDLE(state, op);
|
||||||
|
else BLTZ(state, op);
|
||||||
|
break;
|
||||||
|
case 1: /* REGIMM opcode 1: BGEZ */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BGEZ_IDLE(state, op);
|
||||||
|
else BGEZ(state, op);
|
||||||
|
break;
|
||||||
|
case 2: /* REGIMM opcode 2: BLTZL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BLTZL_IDLE(state, op);
|
||||||
|
else BLTZL(state, op);
|
||||||
|
break;
|
||||||
|
case 3: /* REGIMM opcode 3: BGEZL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BGEZL_IDLE(state, op);
|
||||||
|
else BGEZL(state, op);
|
||||||
|
break;
|
||||||
|
case 8: /* REGIMM opcode 8: TGEI (Not implemented) */
|
||||||
|
case 9: /* REGIMM opcode 9: TGEIU (Not implemented) */
|
||||||
|
case 10: /* REGIMM opcode 10: TLTI (Not implemented) */
|
||||||
|
case 11: /* REGIMM opcode 11: TLTIU (Not implemented) */
|
||||||
|
case 12: /* REGIMM opcode 12: TEQI (Not implemented) */
|
||||||
|
case 14: /* REGIMM opcode 14: TNEI (Not implemented) */
|
||||||
|
NI(state, op);
|
||||||
|
break;
|
||||||
|
case 16: /* REGIMM opcode 16: BLTZAL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BLTZAL_IDLE(state, op);
|
||||||
|
else BLTZAL(state, op);
|
||||||
|
break;
|
||||||
|
case 17: /* REGIMM opcode 17: BGEZAL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BGEZAL_IDLE(state, op);
|
||||||
|
else BGEZAL(state, op);
|
||||||
|
break;
|
||||||
|
case 18: /* REGIMM opcode 18: BLTZALL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BLTZALL_IDLE(state, op);
|
||||||
|
else BLTZALL(state, op);
|
||||||
|
break;
|
||||||
|
case 19: /* REGIMM opcode 19: BGEZALL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BGEZALL_IDLE(state, op);
|
||||||
|
else BGEZALL(state, op);
|
||||||
|
break;
|
||||||
|
default: /* REGIMM opcodes 4..7, 13, 15, 20..31:
|
||||||
|
Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
} /* switch ((op >> 16) & 0x1F) for the REGIMM prefix */
|
||||||
|
break;
|
||||||
|
case 2: /* Major opcode 2: J */
|
||||||
|
if (IS_ABSOLUTE_IDLE_LOOP(op, state->PC->addr)) J_IDLE(state, op);
|
||||||
|
else J(state, op);
|
||||||
|
break;
|
||||||
|
case 3: /* Major opcode 3: JAL */
|
||||||
|
if (IS_ABSOLUTE_IDLE_LOOP(op, state->PC->addr)) JAL_IDLE(state, op);
|
||||||
|
else JAL(state, op);
|
||||||
|
break;
|
||||||
|
case 4: /* Major opcode 4: BEQ */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BEQ_IDLE(state, op);
|
||||||
|
else BEQ(state, op);
|
||||||
|
break;
|
||||||
|
case 5: /* Major opcode 5: BNE */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BNE_IDLE(state, op);
|
||||||
|
else BNE(state, op);
|
||||||
|
break;
|
||||||
|
case 6: /* Major opcode 6: BLEZ */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BLEZ_IDLE(state, op);
|
||||||
|
else BLEZ(state, op);
|
||||||
|
break;
|
||||||
|
case 7: /* Major opcode 7: BGTZ */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BGTZ_IDLE(state, op);
|
||||||
|
else BGTZ(state, op);
|
||||||
|
break;
|
||||||
|
case 8: /* Major opcode 8: ADDI */
|
||||||
|
if (RT_OF(op) != 0) ADDI(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 9: /* Major opcode 9: ADDIU */
|
||||||
|
if (RT_OF(op) != 0) ADDIU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 10: /* Major opcode 10: SLTI */
|
||||||
|
if (RT_OF(op) != 0) SLTI(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 11: /* Major opcode 11: SLTIU */
|
||||||
|
if (RT_OF(op) != 0) SLTIU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 12: /* Major opcode 12: ANDI */
|
||||||
|
if (RT_OF(op) != 0) ANDI(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 13: /* Major opcode 13: ORI */
|
||||||
|
if (RT_OF(op) != 0) ORI(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 14: /* Major opcode 14: XORI */
|
||||||
|
if (RT_OF(op) != 0) XORI(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 15: /* Major opcode 15: LUI */
|
||||||
|
if (RT_OF(op) != 0) LUI(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 16: /* Coprocessor 0 prefix */
|
||||||
|
switch ((op >> 21) & 0x1F) {
|
||||||
|
case 0: /* Coprocessor 0 opcode 0: MFC0 */
|
||||||
|
if (RT_OF(op) != 0) MFC0(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 4: MTC0(state, op); break;
|
||||||
|
case 16: /* Coprocessor 0 opcode 16: TLB */
|
||||||
|
switch (op & 0x3F) {
|
||||||
|
case 1: TLBR(state, op); break;
|
||||||
|
case 2: TLBWI(state, op); break;
|
||||||
|
case 6: TLBWR(state, op); break;
|
||||||
|
case 8: TLBP(state, op); break;
|
||||||
|
case 24: ERET(state, op); break;
|
||||||
|
default: /* TLB sub-opcodes 0, 3..5, 7, 9..23, 25..63:
|
||||||
|
Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
} /* switch (op & 0x3F) for Coprocessor 0 TLB opcodes */
|
||||||
|
break;
|
||||||
|
default: /* Coprocessor 0 opcodes 1..3, 4..15, 17..31:
|
||||||
|
Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
} /* switch ((op >> 21) & 0x1F) for the Coprocessor 0 prefix */
|
||||||
|
break;
|
||||||
|
case 17: /* Coprocessor 1 prefix */
|
||||||
|
switch ((op >> 21) & 0x1F) {
|
||||||
|
case 0: /* Coprocessor 1 opcode 0: MFC1 */
|
||||||
|
if (RT_OF(op) != 0) MFC1(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 1: /* Coprocessor 1 opcode 1: DMFC1 */
|
||||||
|
if (RT_OF(op) != 0) DMFC1(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 2: /* Coprocessor 1 opcode 2: CFC1 */
|
||||||
|
if (RT_OF(op) != 0) CFC1(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 4: MTC1(state, op); break;
|
||||||
|
case 5: DMTC1(state, op); break;
|
||||||
|
case 6: CTC1(state, op); break;
|
||||||
|
case 8: /* Coprocessor 1 opcode 8: Branch on C1 condition... */
|
||||||
|
switch ((op >> 16) & 0x3) {
|
||||||
|
case 0: /* opcode 0: BC1F */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BC1F_IDLE(state, op);
|
||||||
|
else BC1F(state, op);
|
||||||
|
break;
|
||||||
|
case 1: /* opcode 1: BC1T */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BC1T_IDLE(state, op);
|
||||||
|
else BC1T(state, op);
|
||||||
|
break;
|
||||||
|
case 2: /* opcode 2: BC1FL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BC1FL_IDLE(state, op);
|
||||||
|
else BC1FL(state, op);
|
||||||
|
break;
|
||||||
|
case 3: /* opcode 3: BC1TL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BC1TL_IDLE(state, op);
|
||||||
|
else BC1TL(state, op);
|
||||||
|
break;
|
||||||
|
} /* switch ((op >> 16) & 0x3) for branches on C1 condition */
|
||||||
|
break;
|
||||||
|
case 16: /* Coprocessor 1 S-format opcodes */
|
||||||
|
switch (op & 0x3F) {
|
||||||
|
case 0: ADD_S(state, op); break;
|
||||||
|
case 1: SUB_S(state, op); break;
|
||||||
|
case 2: MUL_S(state, op); break;
|
||||||
|
case 3: DIV_S(state, op); break;
|
||||||
|
case 4: SQRT_S(state, op); break;
|
||||||
|
case 5: ABS_S(state, op); break;
|
||||||
|
case 6: MOV_S(state, op); break;
|
||||||
|
case 7: NEG_S(state, op); break;
|
||||||
|
case 8: ROUND_L_S(state, op); break;
|
||||||
|
case 9: TRUNC_L_S(state, op); break;
|
||||||
|
case 10: CEIL_L_S(state, op); break;
|
||||||
|
case 11: FLOOR_L_S(state, op); break;
|
||||||
|
case 12: ROUND_W_S(state, op); break;
|
||||||
|
case 13: TRUNC_W_S(state, op); break;
|
||||||
|
case 14: CEIL_W_S(state, op); break;
|
||||||
|
case 15: FLOOR_W_S(state, op); break;
|
||||||
|
case 33: CVT_D_S(state, op); break;
|
||||||
|
case 36: CVT_W_S(state, op); break;
|
||||||
|
case 37: CVT_L_S(state, op); break;
|
||||||
|
case 48: C_F_S(state, op); break;
|
||||||
|
case 49: C_UN_S(state, op); break;
|
||||||
|
case 50: C_EQ_S(state, op); break;
|
||||||
|
case 51: C_UEQ_S(state, op); break;
|
||||||
|
case 52: C_OLT_S(state, op); break;
|
||||||
|
case 53: C_ULT_S(state, op); break;
|
||||||
|
case 54: C_OLE_S(state, op); break;
|
||||||
|
case 55: C_ULE_S(state, op); break;
|
||||||
|
case 56: C_SF_S(state, op); break;
|
||||||
|
case 57: C_NGLE_S(state, op); break;
|
||||||
|
case 58: C_SEQ_S(state, op); break;
|
||||||
|
case 59: C_NGL_S(state, op); break;
|
||||||
|
case 60: C_LT_S(state, op); break;
|
||||||
|
case 61: C_NGE_S(state, op); break;
|
||||||
|
case 62: C_LE_S(state, op); break;
|
||||||
|
case 63: C_NGT_S(state, op); break;
|
||||||
|
default: /* Coprocessor 1 S-format opcodes 16..32, 34..35, 38..47:
|
||||||
|
Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
} /* switch (op & 0x3F) for Coprocessor 1 S-format opcodes */
|
||||||
|
break;
|
||||||
|
case 17: /* Coprocessor 1 D-format opcodes */
|
||||||
|
switch (op & 0x3F) {
|
||||||
|
case 0: ADD_D(state, op); break;
|
||||||
|
case 1: SUB_D(state, op); break;
|
||||||
|
case 2: MUL_D(state, op); break;
|
||||||
|
case 3: DIV_D(state, op); break;
|
||||||
|
case 4: SQRT_D(state, op); break;
|
||||||
|
case 5: ABS_D(state, op); break;
|
||||||
|
case 6: MOV_D(state, op); break;
|
||||||
|
case 7: NEG_D(state, op); break;
|
||||||
|
case 8: ROUND_L_D(state, op); break;
|
||||||
|
case 9: TRUNC_L_D(state, op); break;
|
||||||
|
case 10: CEIL_L_D(state, op); break;
|
||||||
|
case 11: FLOOR_L_D(state, op); break;
|
||||||
|
case 12: ROUND_W_D(state, op); break;
|
||||||
|
case 13: TRUNC_W_D(state, op); break;
|
||||||
|
case 14: CEIL_W_D(state, op); break;
|
||||||
|
case 15: FLOOR_W_D(state, op); break;
|
||||||
|
case 32: CVT_S_D(state, op); break;
|
||||||
|
case 36: CVT_W_D(state, op); break;
|
||||||
|
case 37: CVT_L_D(state, op); break;
|
||||||
|
case 48: C_F_D(state, op); break;
|
||||||
|
case 49: C_UN_D(state, op); break;
|
||||||
|
case 50: C_EQ_D(state, op); break;
|
||||||
|
case 51: C_UEQ_D(state, op); break;
|
||||||
|
case 52: C_OLT_D(state, op); break;
|
||||||
|
case 53: C_ULT_D(state, op); break;
|
||||||
|
case 54: C_OLE_D(state, op); break;
|
||||||
|
case 55: C_ULE_D(state, op); break;
|
||||||
|
case 56: C_SF_D(state, op); break;
|
||||||
|
case 57: C_NGLE_D(state, op); break;
|
||||||
|
case 58: C_SEQ_D(state, op); break;
|
||||||
|
case 59: C_NGL_D(state, op); break;
|
||||||
|
case 60: C_LT_D(state, op); break;
|
||||||
|
case 61: C_NGE_D(state, op); break;
|
||||||
|
case 62: C_LE_D(state, op); break;
|
||||||
|
case 63: C_NGT_D(state, op); break;
|
||||||
|
default: /* Coprocessor 1 D-format opcodes 16..31, 33..35, 38..47:
|
||||||
|
Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
} /* switch (op & 0x3F) for Coprocessor 1 D-format opcodes */
|
||||||
|
break;
|
||||||
|
case 20: /* Coprocessor 1 W-format opcodes */
|
||||||
|
switch (op & 0x3F) {
|
||||||
|
case 32: CVT_S_W(state, op); break;
|
||||||
|
case 33: CVT_D_W(state, op); break;
|
||||||
|
default: /* Coprocessor 1 W-format opcodes 0..31, 34..63:
|
||||||
|
Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 21: /* Coprocessor 1 L-format opcodes */
|
||||||
|
switch (op & 0x3F) {
|
||||||
|
case 32: CVT_S_L(state, op); break;
|
||||||
|
case 33: CVT_D_L(state, op); break;
|
||||||
|
default: /* Coprocessor 1 L-format opcodes 0..31, 34..63:
|
||||||
|
Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: /* Coprocessor 1 opcodes 3, 7, 9..15, 18..19, 22..31:
|
||||||
|
Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
} /* switch ((op >> 21) & 0x1F) for the Coprocessor 1 prefix */
|
||||||
|
break;
|
||||||
|
case 20: /* Major opcode 20: BEQL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BEQL_IDLE(state, op);
|
||||||
|
else BEQL(state, op);
|
||||||
|
break;
|
||||||
|
case 21: /* Major opcode 21: BNEL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BNEL_IDLE(state, op);
|
||||||
|
else BNEL(state, op);
|
||||||
|
break;
|
||||||
|
case 22: /* Major opcode 22: BLEZL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BLEZL_IDLE(state, op);
|
||||||
|
else BLEZL(state, op);
|
||||||
|
break;
|
||||||
|
case 23: /* Major opcode 23: BGTZL */
|
||||||
|
if (IS_RELATIVE_IDLE_LOOP(op, state->PC->addr)) BGTZL_IDLE(state, op);
|
||||||
|
else BGTZL(state, op);
|
||||||
|
break;
|
||||||
|
case 24: /* Major opcode 24: DADDI */
|
||||||
|
if (RT_OF(op) != 0) DADDI(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 25: /* Major opcode 25: DADDIU */
|
||||||
|
if (RT_OF(op) != 0) DADDIU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 26: /* Major opcode 26: LDL */
|
||||||
|
if (RT_OF(op) != 0) LDL(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 27: /* Major opcode 27: LDR */
|
||||||
|
if (RT_OF(op) != 0) LDR(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 32: /* Major opcode 32: LB */
|
||||||
|
if (RT_OF(op) != 0) LB(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 33: /* Major opcode 33: LH */
|
||||||
|
if (RT_OF(op) != 0) LH(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 34: /* Major opcode 34: LWL */
|
||||||
|
if (RT_OF(op) != 0) LWL(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 35: /* Major opcode 35: LW */
|
||||||
|
if (RT_OF(op) != 0) LW(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 36: /* Major opcode 36: LBU */
|
||||||
|
if (RT_OF(op) != 0) LBU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 37: /* Major opcode 37: LHU */
|
||||||
|
if (RT_OF(op) != 0) LHU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 38: /* Major opcode 38: LWR */
|
||||||
|
if (RT_OF(op) != 0) LWR(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 39: /* Major opcode 39: LWU */
|
||||||
|
if (RT_OF(op) != 0) LWU(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 40: SB(state, op); break;
|
||||||
|
case 41: SH(state, op); break;
|
||||||
|
case 42: SWL(state, op); break;
|
||||||
|
case 43: SW(state, op); break;
|
||||||
|
case 44: SDL(state, op); break;
|
||||||
|
case 45: SDR(state, op); break;
|
||||||
|
case 46: SWR(state, op); break;
|
||||||
|
case 47: CACHE(state, op); break;
|
||||||
|
case 48: /* Major opcode 48: LL */
|
||||||
|
if (RT_OF(op) != 0) LL(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 49: LWC1(state, op); break;
|
||||||
|
case 52: /* Major opcode 52: LLD (Not implemented) */
|
||||||
|
NI(state, op);
|
||||||
|
break;
|
||||||
|
case 53: LDC1(state, op); break;
|
||||||
|
case 55: /* Major opcode 55: LD */
|
||||||
|
if (RT_OF(op) != 0) LD(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 56: /* Major opcode 56: SC */
|
||||||
|
if (RT_OF(op) != 0) SC(state, op);
|
||||||
|
else NOP(state, 0);
|
||||||
|
break;
|
||||||
|
case 57: SWC1(state, op); break;
|
||||||
|
case 60: /* Major opcode 60: SCD (Not implemented) */
|
||||||
|
NI(state, op);
|
||||||
|
break;
|
||||||
|
case 61: SDC1(state, op); break;
|
||||||
|
case 63: SD(state, op); break;
|
||||||
|
default: /* Major opcodes 18..19, 28..31, 50..51, 54, 58..59, 62:
|
||||||
|
Reserved Instructions */
|
||||||
|
RESERVED(state, op);
|
||||||
|
break;
|
||||||
|
} /* switch ((op >> 26) & 0x3F) */
|
||||||
|
}
|
||||||
|
|
||||||
|
void pure_interpreter(usf_state_t * state)
|
||||||
|
{
|
||||||
|
state->stop = 0;
|
||||||
|
state->PC = &state->interp_PC;
|
||||||
|
|
||||||
|
while (!state->stop)
|
||||||
|
{
|
||||||
|
r4300_checkpoint(state);
|
||||||
|
InterpretOpcode(state);
|
||||||
|
}
|
||||||
|
}
|
27
Frameworks/lazyusf/lazyusf/r4300/pure_interp.h
Normal file
27
Frameworks/lazyusf/lazyusf/r4300/pure_interp.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - pure_interp.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_PURE_INTERP_H
|
||||||
|
#define M64P_R4300_PURE_INTERP_H
|
||||||
|
|
||||||
|
void pure_interpreter(usf_state_t *);
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_PURE_INTERP_H */
|
349
Frameworks/lazyusf/lazyusf/r4300/r4300.c
Normal file
349
Frameworks/lazyusf/lazyusf/r4300/r4300.c
Normal file
|
@ -0,0 +1,349 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - r4300.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "ai/ai_controller.h"
|
||||||
|
#include "api/m64p_types.h"
|
||||||
|
#include "api/callbacks.h"
|
||||||
|
#include "memory/memory.h"
|
||||||
|
#include "main/main.h"
|
||||||
|
#include "main/rom.h"
|
||||||
|
#include "pi/pi_controller.h"
|
||||||
|
#include "rsp/rsp_core.h"
|
||||||
|
#include "si/si_controller.h"
|
||||||
|
#include "vi/vi_controller.h"
|
||||||
|
|
||||||
|
#include "r4300.h"
|
||||||
|
#include "r4300_core.h"
|
||||||
|
#include "cached_interp.h"
|
||||||
|
#include "cp0.h"
|
||||||
|
#include "cp1.h"
|
||||||
|
#include "ops.h"
|
||||||
|
#include "interupt.h"
|
||||||
|
#include "pure_interp.h"
|
||||||
|
#include "recomp.h"
|
||||||
|
#include "recomph.h"
|
||||||
|
#include "tlb.h"
|
||||||
|
#include "new_dynarec/new_dynarec.h"
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
#include "debugger/dbg_types.h"
|
||||||
|
#include "debugger/debugger.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(COUNT_INSTR)
|
||||||
|
#include "instr_counters.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void generic_jump_to(usf_state_t * state, unsigned int address)
|
||||||
|
{
|
||||||
|
if (state->r4300emu == CORE_PURE_INTERPRETER)
|
||||||
|
state->interp_PC.addr = address;
|
||||||
|
else {
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
if (state->r4300emu == CORE_DYNAREC)
|
||||||
|
state->last_addr = pcaddr;
|
||||||
|
else
|
||||||
|
jump_to(address);
|
||||||
|
#else
|
||||||
|
jump_to(address);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this hard reset function simulates the boot-up state of the R4300 CPU */
|
||||||
|
void r4300_reset_hard(usf_state_t * state)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
// clear r4300 registers and TLB entries
|
||||||
|
for (i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
state->reg[i]=0;
|
||||||
|
state->g_cp0_regs[i]=0;
|
||||||
|
state->reg_cop1_fgr_64[i]=0;
|
||||||
|
|
||||||
|
// --------------tlb------------------------
|
||||||
|
state->tlb_e[i].mask=0;
|
||||||
|
state->tlb_e[i].vpn2=0;
|
||||||
|
state->tlb_e[i].g=0;
|
||||||
|
state->tlb_e[i].asid=0;
|
||||||
|
state->tlb_e[i].pfn_even=0;
|
||||||
|
state->tlb_e[i].c_even=0;
|
||||||
|
state->tlb_e[i].d_even=0;
|
||||||
|
state->tlb_e[i].v_even=0;
|
||||||
|
state->tlb_e[i].pfn_odd=0;
|
||||||
|
state->tlb_e[i].c_odd=0;
|
||||||
|
state->tlb_e[i].d_odd=0;
|
||||||
|
state->tlb_e[i].v_odd=0;
|
||||||
|
state->tlb_e[i].r=0;
|
||||||
|
//tlb_e[i].check_parity_mask=0x1000;
|
||||||
|
|
||||||
|
state->tlb_e[i].start_even=0;
|
||||||
|
state->tlb_e[i].end_even=0;
|
||||||
|
state->tlb_e[i].phys_even=0;
|
||||||
|
state->tlb_e[i].start_odd=0;
|
||||||
|
state->tlb_e[i].end_odd=0;
|
||||||
|
state->tlb_e[i].phys_odd=0;
|
||||||
|
}
|
||||||
|
for (i=0; i<0x100000; i++)
|
||||||
|
{
|
||||||
|
state->tlb_LUT_r[i] = 0;
|
||||||
|
state->tlb_LUT_w[i] = 0;
|
||||||
|
}
|
||||||
|
state->llbit=0;
|
||||||
|
state->hi=0;
|
||||||
|
state->lo=0;
|
||||||
|
state->FCR0=0x511;
|
||||||
|
state->FCR31=0;
|
||||||
|
|
||||||
|
// set COP0 registers
|
||||||
|
state->g_cp0_regs[CP0_RANDOM_REG] = 31;
|
||||||
|
state->g_cp0_regs[CP0_STATUS_REG]= 0x34000000;
|
||||||
|
set_fpr_pointers(state, state->g_cp0_regs[CP0_STATUS_REG]);
|
||||||
|
state->g_cp0_regs[CP0_CONFIG_REG]= 0x6e463;
|
||||||
|
state->g_cp0_regs[CP0_PREVID_REG] = 0xb00;
|
||||||
|
state->g_cp0_regs[CP0_COUNT_REG] = 0x5000;
|
||||||
|
state->g_cp0_regs[CP0_CAUSE_REG] = 0x5C;
|
||||||
|
state->g_cp0_regs[CP0_CONTEXT_REG] = 0x7FFFF0;
|
||||||
|
state->g_cp0_regs[CP0_EPC_REG] = 0xFFFFFFFF;
|
||||||
|
state->g_cp0_regs[CP0_BADVADDR_REG] = 0xFFFFFFFF;
|
||||||
|
state->g_cp0_regs[CP0_ERROREPC_REG] = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
state->rounding_mode = 0x33F;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int get_tv_type(usf_state_t * state)
|
||||||
|
{
|
||||||
|
switch(state->ROM_PARAMS.systemtype)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case SYSTEM_NTSC: return 1;
|
||||||
|
case SYSTEM_PAL: return 0;
|
||||||
|
case SYSTEM_MPAL: return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simulates end result of PIFBootROM execution */
|
||||||
|
void r4300_reset_soft(usf_state_t * state)
|
||||||
|
{
|
||||||
|
unsigned int rom_type = 0; /* 0:Cart, 1:DD */
|
||||||
|
unsigned int reset_type = 0; /* 0:ColdReset, 1:NMI */
|
||||||
|
unsigned int s7 = 0; /* ??? */
|
||||||
|
unsigned int tv_type = get_tv_type(state); /* 0:PAL, 1:NTSC, 2:MPAL */
|
||||||
|
uint32_t bsd_dom1_config = (state->g_rom && state->g_rom_size >= 4) ? *(uint32_t*)state->g_rom : 0;
|
||||||
|
|
||||||
|
state->g_cp0_regs[CP0_STATUS_REG] = 0x34000000;
|
||||||
|
state->g_cp0_regs[CP0_CONFIG_REG] = 0x0006e463;
|
||||||
|
|
||||||
|
state->g_sp.regs[SP_STATUS_REG] = 1;
|
||||||
|
state->g_sp.regs2[SP_PC_REG] = 0;
|
||||||
|
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_LAT_REG] = (bsd_dom1_config ) & 0xff;
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_PWD_REG] = (bsd_dom1_config >> 8) & 0xff;
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_PGS_REG] = (bsd_dom1_config >> 16) & 0x0f;
|
||||||
|
state->g_pi.regs[PI_BSD_DOM1_RLS_REG] = (bsd_dom1_config >> 20) & 0x03;
|
||||||
|
state->g_pi.regs[PI_STATUS_REG] = 0;
|
||||||
|
|
||||||
|
state->g_ai.regs[AI_DRAM_ADDR_REG] = 0;
|
||||||
|
state->g_ai.regs[AI_LEN_REG] = 0;
|
||||||
|
|
||||||
|
state->g_vi.regs[VI_V_INTR_REG] = 1023;
|
||||||
|
state->g_vi.regs[VI_CURRENT_REG] = 0;
|
||||||
|
state->g_vi.regs[VI_H_START_REG] = 0;
|
||||||
|
|
||||||
|
state->g_r4300.mi.regs[MI_INTR_REG] &= ~(MI_INTR_PI | MI_INTR_VI | MI_INTR_AI | MI_INTR_SP);
|
||||||
|
|
||||||
|
if (state->g_rom && state->g_rom_size >= 0xfc0)
|
||||||
|
memcpy((unsigned char*)state->g_sp.mem+0x40, state->g_rom+0x40, 0xfc0);
|
||||||
|
|
||||||
|
state->reg[19] = rom_type; /* s3 */
|
||||||
|
state->reg[20] = tv_type; /* s4 */
|
||||||
|
state->reg[21] = reset_type; /* s5 */
|
||||||
|
state->reg[22] = state->g_si.pif.cic.seed;/* s6 */
|
||||||
|
state->reg[23] = s7; /* s7 */
|
||||||
|
|
||||||
|
/* required by CIC x105 */
|
||||||
|
state->g_sp.mem[0x1000/4] = 0x3c0dbfc0;
|
||||||
|
state->g_sp.mem[0x1004/4] = 0x8da807fc;
|
||||||
|
state->g_sp.mem[0x1008/4] = 0x25ad07c0;
|
||||||
|
state->g_sp.mem[0x100c/4] = 0x31080080;
|
||||||
|
state->g_sp.mem[0x1010/4] = 0x5500fffc;
|
||||||
|
state->g_sp.mem[0x1014/4] = 0x3c0dbfc0;
|
||||||
|
state->g_sp.mem[0x1018/4] = 0x8da80024;
|
||||||
|
state->g_sp.mem[0x101c/4] = 0x3c0bb000;
|
||||||
|
|
||||||
|
/* required by CIC x105 */
|
||||||
|
state->reg[11] = 0xffffffffa4000040ULL; /* t3 */
|
||||||
|
state->reg[29] = 0xffffffffa4001ff0ULL; /* sp */
|
||||||
|
state->reg[31] = 0xffffffffa4001550ULL; /* ra */
|
||||||
|
|
||||||
|
/* ready to execute IPL3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(NO_ASM)
|
||||||
|
static void dynarec_setup_code()
|
||||||
|
{
|
||||||
|
usf_state_t * state;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
_asm
|
||||||
|
{
|
||||||
|
mov state, esi
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
asm volatile
|
||||||
|
#ifdef __x86_64__
|
||||||
|
(" mov %%r15, (%[state]) \n"
|
||||||
|
#else
|
||||||
|
(" mov %%esi, (%[state]) \n"
|
||||||
|
#endif
|
||||||
|
:
|
||||||
|
: [state]"r"(&state)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
// The dynarec jumps here after we call dyna_start and it prepares
|
||||||
|
// Here we need to prepare the initial code block and jump to it
|
||||||
|
jump_to(state->last_addr);
|
||||||
|
|
||||||
|
// Prevent segfault on failed jump_to
|
||||||
|
if (!state->actual || !state->actual->block || !state->actual->code)
|
||||||
|
dyna_stop(state);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void r4300_begin(usf_state_t * state)
|
||||||
|
{
|
||||||
|
state->current_instruction_table = cached_interpreter_table;
|
||||||
|
|
||||||
|
state->delay_slot=0;
|
||||||
|
state->stop = 0;
|
||||||
|
state->rompause = 0;
|
||||||
|
|
||||||
|
state->next_interupt = 624999;
|
||||||
|
init_interupt(state);
|
||||||
|
|
||||||
|
if (state->r4300emu == CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_INFO, "Starting R4300 emulator: Pure Interpreter");
|
||||||
|
state->r4300emu = CORE_PURE_INTERPRETER;
|
||||||
|
}
|
||||||
|
#if defined(DYNAREC)
|
||||||
|
else if (state->r4300emu >= 2)
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_INFO, "Starting R4300 emulator: Dynamic Recompiler");
|
||||||
|
state->r4300emu = CORE_DYNAREC;
|
||||||
|
init_blocks(state);
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
new_dynarec_init(state);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else /* if (r4300emu == CORE_INTERPRETER) */
|
||||||
|
{
|
||||||
|
DebugMessage(state, M64MSG_INFO, "Starting R4300 emulator: Cached Interpreter");
|
||||||
|
state->r4300emu = CORE_INTERPRETER;
|
||||||
|
init_blocks(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void r4300_reset_checkpoint(usf_state_t * state, unsigned int new_cp0_count)
|
||||||
|
{
|
||||||
|
unsigned int diff = state->g_cp0_regs[CP0_COUNT_REG] - state->g_timer_checkpoint;
|
||||||
|
state->g_timer_checkpoint = new_cp0_count - diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void r4300_checkpoint(usf_state_t * state)
|
||||||
|
{
|
||||||
|
if (state->g_cp0_regs[CP0_COUNT_REG] - state->g_timer_checkpoint >= state->count_per_op * 20000000)
|
||||||
|
{
|
||||||
|
if (state->last_sample_buffer_count == state->sample_buffer_count)
|
||||||
|
{
|
||||||
|
DebugMessage(state, 1, "Emulator appears to be stuck!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state->last_sample_buffer_count = state->sample_buffer_count;
|
||||||
|
state->g_timer_checkpoint = state->g_cp0_regs[CP0_COUNT_REG];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void r4300_execute(usf_state_t * state)
|
||||||
|
{
|
||||||
|
state->g_timer_checkpoint = state->g_cp0_regs[CP0_COUNT_REG];
|
||||||
|
state->last_sample_buffer_count = state->sample_buffer_count;
|
||||||
|
|
||||||
|
if (state->r4300emu == CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
pure_interpreter(state);
|
||||||
|
}
|
||||||
|
#if defined(DYNAREC)
|
||||||
|
else if (state->r4300emu == CORE_DYNAREC)
|
||||||
|
{
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
new_dyna_start(state);
|
||||||
|
#else
|
||||||
|
dyna_start(state, (void*)dynarec_setup_code);
|
||||||
|
state->PC++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else /* if (r4300emu == CORE_INTERPRETER) */
|
||||||
|
{
|
||||||
|
/* Prevent segfault on failed jump_to */
|
||||||
|
if (!state->actual->block)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (!state->stop)
|
||||||
|
{
|
||||||
|
r4300_checkpoint(state);
|
||||||
|
state->PC->ops(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void r4300_end(usf_state_t * state)
|
||||||
|
{
|
||||||
|
if (state->r4300emu == CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#if defined(DYNAREC)
|
||||||
|
else if (state->r4300emu == CORE_DYNAREC)
|
||||||
|
{
|
||||||
|
#ifdef NEW_DYNAREC
|
||||||
|
new_dynarec_cleanup(state);
|
||||||
|
#endif
|
||||||
|
free_blocks(state);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else /* if (r4300emu == CORE_INTERPRETER) */
|
||||||
|
{
|
||||||
|
free_blocks(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugMessage(state, M64MSG_INFO, "R4300 emulator finished.");
|
||||||
|
}
|
52
Frameworks/lazyusf/lazyusf/r4300/r4300.h
Normal file
52
Frameworks/lazyusf/lazyusf/r4300/r4300.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - r4300.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_R4300_H
|
||||||
|
#define M64P_R4300_R4300_H
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "ops.h"
|
||||||
|
#include "recomp.h"
|
||||||
|
|
||||||
|
#define COUNT_PER_OP_DEFAULT 2
|
||||||
|
|
||||||
|
void r4300_reset_hard(usf_state_t *);
|
||||||
|
void r4300_reset_soft(usf_state_t *);
|
||||||
|
|
||||||
|
void r4300_begin(usf_state_t *);
|
||||||
|
void r4300_execute(usf_state_t *);
|
||||||
|
void r4300_end(usf_state_t *);
|
||||||
|
|
||||||
|
void r4300_reset_checkpoint(usf_state_t *, unsigned int new_cp0_count);
|
||||||
|
void r4300_checkpoint(usf_state_t *);
|
||||||
|
|
||||||
|
/* Jump to the given address. This works for all r4300 emulator, but is slower.
|
||||||
|
* Use this for common code which can be executed from any r4300 emulator. */
|
||||||
|
void generic_jump_to(usf_state_t *, unsigned int address);
|
||||||
|
|
||||||
|
// r4300 emulators
|
||||||
|
#define CORE_PURE_INTERPRETER 0
|
||||||
|
#define CORE_INTERPRETER 1
|
||||||
|
#define CORE_DYNAREC 2
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_R4300_H */
|
||||||
|
|
35
Frameworks/lazyusf/lazyusf/r4300/r4300_core.c
Normal file
35
Frameworks/lazyusf/lazyusf/r4300/r4300_core.c
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - r4300_core.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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 "usf/usf.h"
|
||||||
|
|
||||||
|
#include "r4300_core.h"
|
||||||
|
|
||||||
|
void init_r4300(struct r4300_core* r4300)
|
||||||
|
{
|
||||||
|
init_mi(&r4300->mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void connect_r4300(struct r4300_core* r4300,
|
||||||
|
usf_state_t* state)
|
||||||
|
{
|
||||||
|
r4300->state = state;
|
||||||
|
}
|
39
Frameworks/lazyusf/lazyusf/r4300/r4300_core.h
Normal file
39
Frameworks/lazyusf/lazyusf/r4300/r4300_core.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - r4300_core.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2014 Bobby Smiles *
|
||||||
|
* *
|
||||||
|
* 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_R4300_R4300_CORE_H
|
||||||
|
#define M64P_R4300_R4300_CORE_H
|
||||||
|
|
||||||
|
#include "mi_controller.h"
|
||||||
|
|
||||||
|
struct r4300_core
|
||||||
|
{
|
||||||
|
struct mi_controller mi;
|
||||||
|
|
||||||
|
usf_state_t* state;
|
||||||
|
};
|
||||||
|
|
||||||
|
void init_r4300(struct r4300_core* r4300);
|
||||||
|
|
||||||
|
void connect_r4300(struct r4300_core* r4300,
|
||||||
|
usf_state_t* state);
|
||||||
|
|
||||||
|
#endif
|
2577
Frameworks/lazyusf/lazyusf/r4300/recomp.c
Normal file
2577
Frameworks/lazyusf/lazyusf/r4300/recomp.c
Normal file
File diff suppressed because it is too large
Load diff
114
Frameworks/lazyusf/lazyusf/r4300/recomp.h
Normal file
114
Frameworks/lazyusf/lazyusf/r4300/recomp.h
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - recomp.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_RECOMP_H
|
||||||
|
#define M64P_R4300_RECOMP_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "osal/preproc.h"
|
||||||
|
|
||||||
|
#ifndef PRECOMP_STRUCTS
|
||||||
|
#define PRECOMP_STRUCTS
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#include "x86_64/assemble_struct.h"
|
||||||
|
#else
|
||||||
|
#include "x86/assemble_struct.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _precomp_instr
|
||||||
|
{
|
||||||
|
void (osal_fastcall *ops)(usf_state_t * state);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
long long int *rs;
|
||||||
|
long long int *rt;
|
||||||
|
short immediate;
|
||||||
|
} i;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int inst_index;
|
||||||
|
} j;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
long long int *rs;
|
||||||
|
long long int *rt;
|
||||||
|
long long int *rd;
|
||||||
|
unsigned char sa;
|
||||||
|
unsigned char nrd;
|
||||||
|
} r;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned char base;
|
||||||
|
unsigned char ft;
|
||||||
|
short offset;
|
||||||
|
} lf;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned char ft;
|
||||||
|
unsigned char fs;
|
||||||
|
unsigned char fd;
|
||||||
|
} cf;
|
||||||
|
} f;
|
||||||
|
unsigned int addr; /* word-aligned instruction address in r4300 address space */
|
||||||
|
unsigned int local_addr; /* byte offset to start of corresponding x86_64 instructions, from start of code block */
|
||||||
|
reg_cache_struct reg_cache_infos;
|
||||||
|
} precomp_instr;
|
||||||
|
|
||||||
|
typedef struct _precomp_block
|
||||||
|
{
|
||||||
|
precomp_instr *block;
|
||||||
|
unsigned int start;
|
||||||
|
unsigned int end;
|
||||||
|
unsigned char *code;
|
||||||
|
unsigned int code_length;
|
||||||
|
unsigned int max_code_length;
|
||||||
|
void *jumps_table;
|
||||||
|
int jumps_number;
|
||||||
|
void *riprel_table;
|
||||||
|
int riprel_number;
|
||||||
|
//unsigned char md5[16];
|
||||||
|
unsigned int adler32;
|
||||||
|
} precomp_block;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void recompile_block(usf_state_t *, int *source, precomp_block *block, unsigned int func);
|
||||||
|
void init_block(usf_state_t *, precomp_block *block);
|
||||||
|
void free_block(usf_state_t *, precomp_block *block);
|
||||||
|
void recompile_opcode(usf_state_t *);
|
||||||
|
void dyna_jump(usf_state_t *);
|
||||||
|
void dyna_start(usf_state_t *, void *code);
|
||||||
|
void dyna_stop(usf_state_t *);
|
||||||
|
void *realloc_exec(usf_state_t *, void *ptr, size_t oldsize, size_t newsize);
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#include "x86_64/assemble.h"
|
||||||
|
#include "x86_64/regcache.h"
|
||||||
|
#else
|
||||||
|
#include "x86/assemble.h"
|
||||||
|
#include "x86/regcache.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_RECOMP_H */
|
||||||
|
|
294
Frameworks/lazyusf/lazyusf/r4300/recomph.h
Normal file
294
Frameworks/lazyusf/lazyusf/r4300/recomph.h
Normal file
|
@ -0,0 +1,294 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - recomph.h *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2002 Hacktarux *
|
||||||
|
* *
|
||||||
|
* 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_R4300_RECOMPH_H
|
||||||
|
#define M64P_R4300_RECOMPH_H
|
||||||
|
|
||||||
|
#include "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "recomp.h"
|
||||||
|
|
||||||
|
void passe2(usf_state_t *, precomp_instr *dest, int start, int end, precomp_block* block);
|
||||||
|
void init_assembler(usf_state_t *, void *block_jumps_table, int block_jumps_number, void *block_riprel_table, int block_riprel_number);
|
||||||
|
void free_assembler(usf_state_t *, void **block_jumps_table, int *block_jumps_number, void **block_riprel_table, int *block_riprel_number);
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
void gencallinterp(usf_state_t *, unsigned long long addr, int jump);
|
||||||
|
#else
|
||||||
|
void gencallinterp(usf_state_t *, unsigned long addr, int jump);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void genupdate_system(usf_state_t *, int type);
|
||||||
|
void genbnel(usf_state_t *);
|
||||||
|
void genblezl(usf_state_t *);
|
||||||
|
void genlw(usf_state_t *);
|
||||||
|
void genlbu(usf_state_t *);
|
||||||
|
void genlhu(usf_state_t *);
|
||||||
|
void gensb(usf_state_t *);
|
||||||
|
void gensh(usf_state_t *);
|
||||||
|
void gensw(usf_state_t *);
|
||||||
|
void gencache(usf_state_t *);
|
||||||
|
void genlwc1(usf_state_t *);
|
||||||
|
void genld(usf_state_t *);
|
||||||
|
void gensd(usf_state_t *);
|
||||||
|
void genbeq(usf_state_t *);
|
||||||
|
void genbne(usf_state_t *);
|
||||||
|
void genblez(usf_state_t *);
|
||||||
|
void genaddi(usf_state_t *);
|
||||||
|
void genaddiu(usf_state_t *);
|
||||||
|
void genslti(usf_state_t *);
|
||||||
|
void gensltiu(usf_state_t *);
|
||||||
|
void genandi(usf_state_t *);
|
||||||
|
void genori(usf_state_t *);
|
||||||
|
void genxori(usf_state_t *);
|
||||||
|
void genlui(usf_state_t *);
|
||||||
|
void genbeql(usf_state_t *);
|
||||||
|
void genmul_s(usf_state_t *);
|
||||||
|
void gendiv_s(usf_state_t *);
|
||||||
|
void gencvt_d_s(usf_state_t *);
|
||||||
|
void genadd_d(usf_state_t *);
|
||||||
|
void gentrunc_w_d(usf_state_t *);
|
||||||
|
void gencvt_s_w(usf_state_t *);
|
||||||
|
void genmfc1(usf_state_t *);
|
||||||
|
void gencfc1(usf_state_t *);
|
||||||
|
void genmtc1(usf_state_t *);
|
||||||
|
void genctc1(usf_state_t *);
|
||||||
|
void genj(usf_state_t *);
|
||||||
|
void genjal(usf_state_t *);
|
||||||
|
void genslt(usf_state_t *);
|
||||||
|
void gensltu(usf_state_t *);
|
||||||
|
void gendsll32(usf_state_t *);
|
||||||
|
void gendsra32(usf_state_t *);
|
||||||
|
void genbgez(usf_state_t *);
|
||||||
|
void genbgezl(usf_state_t *);
|
||||||
|
void genbgezal(usf_state_t *);
|
||||||
|
void gentlbwi(usf_state_t *);
|
||||||
|
void generet(usf_state_t *);
|
||||||
|
void genmfc0(usf_state_t *);
|
||||||
|
void genadd_s(usf_state_t *);
|
||||||
|
void genmult(usf_state_t *);
|
||||||
|
void genmultu(usf_state_t *);
|
||||||
|
void genmflo(usf_state_t *);
|
||||||
|
void genmtlo(usf_state_t *);
|
||||||
|
void gendiv(usf_state_t *);
|
||||||
|
void gendmultu(usf_state_t *);
|
||||||
|
void genddivu(usf_state_t *);
|
||||||
|
void genadd(usf_state_t *);
|
||||||
|
void genaddu(usf_state_t *);
|
||||||
|
void gensubu(usf_state_t *);
|
||||||
|
void genand(usf_state_t *);
|
||||||
|
void genor(usf_state_t *);
|
||||||
|
void genxor(usf_state_t *);
|
||||||
|
void genreserved(usf_state_t *);
|
||||||
|
void gennop(usf_state_t *);
|
||||||
|
void gensll(usf_state_t *);
|
||||||
|
void gensrl(usf_state_t *);
|
||||||
|
void gensra(usf_state_t *);
|
||||||
|
void gensllv(usf_state_t *);
|
||||||
|
void gensrlv(usf_state_t *);
|
||||||
|
void genjr(usf_state_t *);
|
||||||
|
void genni(usf_state_t *);
|
||||||
|
void genmfhi(usf_state_t *);
|
||||||
|
void genmthi(usf_state_t *);
|
||||||
|
void genmtc0(usf_state_t *);
|
||||||
|
void genbltz(usf_state_t *);
|
||||||
|
void genlwl(usf_state_t *);
|
||||||
|
void genswl(usf_state_t *);
|
||||||
|
void gentlbp(usf_state_t *);
|
||||||
|
void gentlbr(usf_state_t *);
|
||||||
|
void genswr(usf_state_t *);
|
||||||
|
void genlwr(usf_state_t *);
|
||||||
|
void gensrav(usf_state_t *);
|
||||||
|
void genbgtz(usf_state_t *);
|
||||||
|
void genlb(usf_state_t *);
|
||||||
|
void genswc1(usf_state_t *);
|
||||||
|
void genldc1(usf_state_t *);
|
||||||
|
void gencvt_d_w(usf_state_t *);
|
||||||
|
void genmul_d(usf_state_t *);
|
||||||
|
void gensub_d(usf_state_t *);
|
||||||
|
void gendiv_d(usf_state_t *);
|
||||||
|
void gencvt_s_d(usf_state_t *);
|
||||||
|
void genmov_s(usf_state_t *);
|
||||||
|
void genc_le_s(usf_state_t *);
|
||||||
|
void genbc1t(usf_state_t *);
|
||||||
|
void gentrunc_w_s(usf_state_t *);
|
||||||
|
void genbc1tl(usf_state_t *);
|
||||||
|
void genc_lt_s(usf_state_t *);
|
||||||
|
void genbc1fl(usf_state_t *);
|
||||||
|
void genneg_s(usf_state_t *);
|
||||||
|
void genc_le_d(usf_state_t *);
|
||||||
|
void genbgezal_idle(usf_state_t *);
|
||||||
|
void genj_idle(usf_state_t *);
|
||||||
|
void genbeq_idle(usf_state_t *);
|
||||||
|
void genlh(usf_state_t *);
|
||||||
|
void genmov_d(usf_state_t *);
|
||||||
|
void genc_lt_d(usf_state_t *);
|
||||||
|
void genbc1f(usf_state_t *);
|
||||||
|
void gennor(usf_state_t *);
|
||||||
|
void genneg_d(usf_state_t *);
|
||||||
|
void gensub(usf_state_t *);
|
||||||
|
void genblez_idle(usf_state_t *);
|
||||||
|
void gendivu(usf_state_t *);
|
||||||
|
void gencvt_w_s(usf_state_t *);
|
||||||
|
void genbltzl(usf_state_t *);
|
||||||
|
void gensdc1(usf_state_t *);
|
||||||
|
void genc_eq_s(usf_state_t *);
|
||||||
|
void genjalr(usf_state_t *);
|
||||||
|
void gensub_s(usf_state_t *);
|
||||||
|
void gensqrt_s(usf_state_t *);
|
||||||
|
void genc_eq_d(usf_state_t *);
|
||||||
|
void gencvt_w_d(usf_state_t *);
|
||||||
|
void genfin_block(usf_state_t *);
|
||||||
|
void genddiv(usf_state_t *);
|
||||||
|
void gendaddiu(usf_state_t *);
|
||||||
|
void genbgtzl(usf_state_t *);
|
||||||
|
void gendsrav(usf_state_t *);
|
||||||
|
void gendsllv(usf_state_t *);
|
||||||
|
void gencvt_s_l(usf_state_t *);
|
||||||
|
void gendmtc1(usf_state_t *);
|
||||||
|
void gendsrlv(usf_state_t *);
|
||||||
|
void gendsra(usf_state_t *);
|
||||||
|
void gendmult(usf_state_t *);
|
||||||
|
void gendsll(usf_state_t *);
|
||||||
|
void genabs_s(usf_state_t *);
|
||||||
|
void gensc(usf_state_t *);
|
||||||
|
void gennotcompiled(usf_state_t *);
|
||||||
|
void genjal_idle(usf_state_t *);
|
||||||
|
void genjal_out(usf_state_t *);
|
||||||
|
void genbeq_out(usf_state_t *);
|
||||||
|
void gensyscall(usf_state_t *);
|
||||||
|
void gensync(usf_state_t *);
|
||||||
|
void gendadd(usf_state_t *);
|
||||||
|
void gendaddu(usf_state_t *);
|
||||||
|
void gendsub(usf_state_t *);
|
||||||
|
void gendsubu(usf_state_t *);
|
||||||
|
void genteq(usf_state_t *);
|
||||||
|
void gendsrl(usf_state_t *);
|
||||||
|
void gendsrl32(usf_state_t *);
|
||||||
|
void genbltz_idle(usf_state_t *);
|
||||||
|
void genbltz_out(usf_state_t *);
|
||||||
|
void genbgez_idle(usf_state_t *);
|
||||||
|
void genbgez_out(usf_state_t *);
|
||||||
|
void genbltzl_idle(usf_state_t *);
|
||||||
|
void genbltzl_out(usf_state_t *);
|
||||||
|
void genbgezl_idle(usf_state_t *);
|
||||||
|
void genbgezl_out(usf_state_t *);
|
||||||
|
void genbltzal_idle(usf_state_t *);
|
||||||
|
void genbltzal_out(usf_state_t *);
|
||||||
|
void genbltzal(usf_state_t *);
|
||||||
|
void genbgezal_out(usf_state_t *);
|
||||||
|
void genbltzall_idle(usf_state_t *);
|
||||||
|
void genbltzall_out(usf_state_t *);
|
||||||
|
void genbltzall(usf_state_t *);
|
||||||
|
void genbgezall_idle(usf_state_t *);
|
||||||
|
void genbgezall_out(usf_state_t *);
|
||||||
|
void genbgezall(usf_state_t *);
|
||||||
|
void gentlbwr(usf_state_t *);
|
||||||
|
void genbc1f_idle(usf_state_t *);
|
||||||
|
void genbc1f_out(usf_state_t *);
|
||||||
|
void genbc1t_idle(usf_state_t *);
|
||||||
|
void genbc1t_out(usf_state_t *);
|
||||||
|
void genbc1fl_idle(usf_state_t *);
|
||||||
|
void genbc1fl_out(usf_state_t *);
|
||||||
|
void genbc1tl_idle(usf_state_t *);
|
||||||
|
void genbc1tl_out(usf_state_t *);
|
||||||
|
void genround_l_s(usf_state_t *);
|
||||||
|
void gentrunc_l_s(usf_state_t *);
|
||||||
|
void genceil_l_s(usf_state_t *);
|
||||||
|
void genfloor_l_s(usf_state_t *);
|
||||||
|
void genround_w_s(usf_state_t *);
|
||||||
|
void genceil_w_s(usf_state_t *);
|
||||||
|
void genfloor_w_s(usf_state_t *);
|
||||||
|
void gencvt_l_s(usf_state_t *);
|
||||||
|
void genc_f_s(usf_state_t *);
|
||||||
|
void genc_un_s(usf_state_t *);
|
||||||
|
void genc_ueq_s(usf_state_t *);
|
||||||
|
void genc_olt_s(usf_state_t *);
|
||||||
|
void genc_ult_s(usf_state_t *);
|
||||||
|
void genc_ole_s(usf_state_t *);
|
||||||
|
void genc_ule_s(usf_state_t *);
|
||||||
|
void genc_sf_s(usf_state_t *);
|
||||||
|
void genc_ngle_s(usf_state_t *);
|
||||||
|
void genc_seq_s(usf_state_t *);
|
||||||
|
void genc_ngl_s(usf_state_t *);
|
||||||
|
void genc_nge_s(usf_state_t *);
|
||||||
|
void genc_ngt_s(usf_state_t *);
|
||||||
|
void gensqrt_d(usf_state_t *);
|
||||||
|
void genabs_d(usf_state_t *);
|
||||||
|
void genround_l_d(usf_state_t *);
|
||||||
|
void gentrunc_l_d(usf_state_t *);
|
||||||
|
void genceil_l_d(usf_state_t *);
|
||||||
|
void genfloor_l_d(usf_state_t *);
|
||||||
|
void genround_w_d(usf_state_t *);
|
||||||
|
void genceil_w_d(usf_state_t *);
|
||||||
|
void genfloor_w_d(usf_state_t *);
|
||||||
|
void gencvt_l_d(usf_state_t *);
|
||||||
|
void genc_f_d(usf_state_t *);
|
||||||
|
void genc_un_d(usf_state_t *);
|
||||||
|
void genc_ueq_d(usf_state_t *);
|
||||||
|
void genc_olt_d(usf_state_t *);
|
||||||
|
void genc_ult_d(usf_state_t *);
|
||||||
|
void genc_ole_d(usf_state_t *);
|
||||||
|
void genc_ule_d(usf_state_t *);
|
||||||
|
void genc_sf_d(usf_state_t *);
|
||||||
|
void genc_ngle_d(usf_state_t *);
|
||||||
|
void genc_seq_d(usf_state_t *);
|
||||||
|
void genc_ngl_d(usf_state_t *);
|
||||||
|
void genc_nge_d(usf_state_t *);
|
||||||
|
void genc_ngt_d(usf_state_t *);
|
||||||
|
void gencvt_d_l(usf_state_t *);
|
||||||
|
void gendmfc1(usf_state_t *);
|
||||||
|
void genj_out(usf_state_t *);
|
||||||
|
void genbne_idle(usf_state_t *);
|
||||||
|
void genbne_out(usf_state_t *);
|
||||||
|
void genblez_out(usf_state_t *);
|
||||||
|
void genbgtz_idle(usf_state_t *);
|
||||||
|
void genbgtz_out(usf_state_t *);
|
||||||
|
void genbeql_idle(usf_state_t *);
|
||||||
|
void genbeql_out(usf_state_t *);
|
||||||
|
void genbnel_idle(usf_state_t *);
|
||||||
|
void genbnel_out(usf_state_t *);
|
||||||
|
void genblezl_idle(usf_state_t *);
|
||||||
|
void genblezl_out(usf_state_t *);
|
||||||
|
void genbgtzl_idle(usf_state_t *);
|
||||||
|
void genbgtzl_out(usf_state_t *);
|
||||||
|
void gendaddi(usf_state_t *);
|
||||||
|
void genldl(usf_state_t *);
|
||||||
|
void genldr(usf_state_t *);
|
||||||
|
void genlwu(usf_state_t *);
|
||||||
|
void gensdl(usf_state_t *);
|
||||||
|
void gensdr(usf_state_t *);
|
||||||
|
void genlink_subblock(usf_state_t *);
|
||||||
|
void gendelayslot(usf_state_t *);
|
||||||
|
void gencheck_interupt_reg(usf_state_t *);
|
||||||
|
void gentest(usf_state_t *);
|
||||||
|
void gentest_out(usf_state_t *);
|
||||||
|
void gentest_idle(usf_state_t *);
|
||||||
|
void gentestl(usf_state_t *);
|
||||||
|
void gentestl_out(usf_state_t *);
|
||||||
|
void gencheck_cop1_unusable(usf_state_t *);
|
||||||
|
void genll(usf_state_t *);
|
||||||
|
void genbreak(usf_state_t *);
|
||||||
|
|
||||||
|
#endif /* M64P_R4300_RECOMPH_H */
|
||||||
|
|
55
Frameworks/lazyusf/lazyusf/r4300/reset.c
Normal file
55
Frameworks/lazyusf/lazyusf/r4300/reset.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Mupen64plus - reset.c *
|
||||||
|
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
|
||||||
|
* Copyright (C) 2011 CasualJames *
|
||||||
|
* Copyright (C) 2008-2009 Richard Goedeken *
|
||||||
|
* Copyright (C) 2008 Ebenblues Nmn Okaygo Tillin9 *
|
||||||
|
* Hard reset based on code by hacktarux. *
|
||||||
|
* *
|
||||||
|
* 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 "usf/usf.h"
|
||||||
|
|
||||||
|
#include "usf/usf_internal.h"
|
||||||
|
|
||||||
|
#include "r4300/reset.h"
|
||||||
|
#include "r4300/r4300.h"
|
||||||
|
#include "r4300/interupt.h"
|
||||||
|
#include "memory/memory.h"
|
||||||
|
#include "r4300/cached_interp.h"
|
||||||
|
|
||||||
|
void reset_hard(usf_state_t * state)
|
||||||
|
{
|
||||||
|
init_memory(state, 0x800000);
|
||||||
|
r4300_reset_hard(state);
|
||||||
|
r4300_reset_soft(state);
|
||||||
|
state->last_addr = 0xa4000040;
|
||||||
|
state->next_interupt = 624999;
|
||||||
|
init_interupt(state);
|
||||||
|
if(state->r4300emu != CORE_PURE_INTERPRETER)
|
||||||
|
{
|
||||||
|
free_blocks(state);
|
||||||
|
init_blocks(state);
|
||||||
|
}
|
||||||
|
generic_jump_to(state, state->last_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_soft(usf_state_t * state)
|
||||||
|
{
|
||||||
|
add_interupt_event(state, HW2_INT, 0); /* Hardware 2 Interrupt immediately */
|
||||||
|
add_interupt_event(state, NMI_INT, 50000000); /* Non maskable Interrupt after 1/2 second */
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue