psxsdk/libpsx/src/cop.c

112 lines
2.8 KiB
C

#include <psx.h>
unsigned int get_cop_register(unsigned char cop_num,
unsigned char register_num)
{
// Workaround for MIPS' simplicistic instruction set...
unsigned int instr[] =
{0x40020000, // cfc $v0, 0
0x03E00008, // jr $ra
0x00000000, // nop
0x00000000}; // nop
int (*rawFunc)() = (void*)instr;
// Write coprocessor register number inside instruction
instr[0] |= ( (cop_num & 3) << 26 ) | ( (register_num & 31) << 11 );
// Execute modified instruction
return rawFunc();
}
unsigned int get_cop_ctrl_register(unsigned char cop_num,
unsigned char register_num)
{
// Workaround for MIPS' simplicistic instruction set...
unsigned int instr[] =
{0x40420000, // mfc $v0, 0
0x03E00008, // jr $ra
0x00000000, // nop
0x00000000}; // nop
int (*rawFunc)() = (void*)instr;
// Write coprocessor register number inside instruction
instr[0] |= ( (cop_num & 3) << 26 ) | ( (register_num & 31) << 11 );
// Execute modified instruction
return rawFunc();
}
unsigned int get_cop0_register(unsigned char register_num)
{
return get_cop_register(0, register_num);
}
void set_cop_register(unsigned char cop_num,
unsigned char register_num,
unsigned int value)
{
// Workaround for MIPS' simplicistic instruction set...
unsigned int instr[] =
{0x40840000, // mtc $a0, 0
0x03E00008, // jr $ra
0x00000000, // nop
0x00000000}; // nop
void (*rawFunc)(int value) = (void*)instr;
// Write coprocessor register number inside instruction
instr[0] |= ( (cop_num & 3) << 26 ) | ( (register_num & 31) << 11 );
// Execute modified instruction
rawFunc(value);
}
void set_cop_ctrl_register(unsigned char cop_num,
unsigned char register_num,
unsigned int value)
{
// Workaround for MIPS' simplicistic instruction set...
unsigned int instr[] =
{0x40C40000, // ctc $a0, 0
0x03E00008, // jr $ra
0x00000000, // nop
0x00000000}; // nop
void (*rawFunc)(int value) = (void*)instr;
// Write coprocessor register number inside instruction
instr[0] |= ( (cop_num & 3) << 26 ) | ( (register_num & 31) << 11 );
// Execute modified instruction
rawFunc(value);
}
void set_cop0_register(unsigned char register_num,
unsigned int value)
{
set_cop_register(0, register_num, value);
}
void run_cop_instruction(unsigned char cop_num,
unsigned int operation)
{
// Workaround for MIPS' simplicistic instruction set...
unsigned int instr[] =
{0x42000000, // cop 0
0x03E00008, // jr $ra
0x00000000, // nop
0x00000000}; // nop
void (*rawFunc)(void) = (void*)instr;
// Write coprocessor register number inside instruction
instr[0] |= ( (cop_num & 3) << 26 ) | (operation & 0x1ffffff);
// Execute modified instruction
rawFunc();
}