diff options
| author | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-01-31 10:32:23 +0100 |
|---|---|---|
| committer | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-01-31 10:32:23 +0100 |
| commit | 7c24e9a9b02b04dcaf9507acb94091ea70a2c02d (patch) | |
| tree | c28d0748652ad4b4222309e46e6cfc82c0906220 /libpsx/src/cop.c | |
| parent | a2b7b6bb1cc2f4a3258b7b2dbc92399d151f864d (diff) | |
Imported pristine psxsdk-20190410 from official repo
Diffstat (limited to 'libpsx/src/cop.c')
| -rw-r--r-- | libpsx/src/cop.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/libpsx/src/cop.c b/libpsx/src/cop.c new file mode 100644 index 0000000..04b49f5 --- /dev/null +++ b/libpsx/src/cop.c @@ -0,0 +1,111 @@ +#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(); +} + |
