+void gteNULL(struct psxCP2Regs *regs) {
+ psxRegisters *regs_ = (psxRegisters *)((u8 *)regs - offsetof(psxRegisters, CP2));
+ psxNULLne(regs_);
+}
+
+OP(psxSPECIAL) {
+ psxSPC[_Funct_](regs_, code);
+}
+
+OP(psxCOP0) {
+ u32 rs = _Rs_;
+ if (rs & 0x10) {
+ u32 op2 = code & 0x1f;
+ switch (op2) {
+ case 0x01:
+ case 0x02:
+ case 0x06:
+ case 0x08: psxNULL(regs_, code); break;
+ case 0x10: psxRFE(regs_, code); break;
+ default: psxNULLne(regs_); break;
+ }
+ return;
+ }
+ switch (rs) {
+ case 0x00: psxMFC0(regs_, code); break;
+ case 0x04: psxMTC0(regs_, code); break;
+ case 0x02: // CFC
+ case 0x06: psxNULL(regs_, code); break; // CTC -> exception
+ case 0x08:
+ case 0x0c: log_unhandled("BC0 %08x @%08x\n", code, regs_->pc - 4);
+ default: psxNULLne(regs_); break;
+ }
+}
+
+OP(psxCOP1) {
+ // ??? what actually happens here?
+ log_unhandled("COP1 %08x @%08x\n", code, regs_->pc - 4);
+}
+
+OP(psxCOP2) {
+ u32 rt = _Rt_, rd = _Rd_, rs = _Rs_;
+ if (rs & 0x10) {
+ psxCP2[_Funct_](®s_->CP2);
+ return;
+ }
+ switch (rs) {
+ case 0x00: doLoad(regs_, rt, MFC2(®s_->CP2, rd)); break; // MFC2
+ case 0x02: doLoad(regs_, rt, regs_->CP2C.r[rd]); break; // CFC2
+ case 0x04: MTC2(®s_->CP2, regs_->GPR.r[rt], rd); break; // MTC2
+ case 0x06: CTC2(®s_->CP2, regs_->GPR.r[rt], rd); break; // CTC2
+ case 0x08:
+ case 0x0c: log_unhandled("BC2 %08x @%08x\n", code, regs_->pc - 4);
+ default: psxNULLne(regs_); break;
+ }
+}
+
+OP(psxCOP2_stall) {
+ u32 f = _Funct_;
+ gteCheckStall(f);
+ psxCOP2(regs_, code);
+}
+
+OP(gteLWC2) {
+ MTC2(®s_->CP2, psxMemRead32(_oB_), _Rt_);
+}
+
+OP(gteLWC2_stall) {
+ gteCheckStall(0);
+ gteLWC2(regs_, code);
+}
+
+OP(gteLWC2e_stall) {
+ gteCheckStall(0);
+ if (checkLD(regs_, _oB_, 3))
+ MTC2(®s_->CP2, psxMemRead32(_oB_), _Rt_);
+}
+
+OP(gteSWC2) {
+ psxMemWrite32(_oB_, MFC2(®s_->CP2, _Rt_));
+}
+
+OP(gteSWC2_stall) {
+ gteCheckStall(0);
+ gteSWC2(regs_, code);
+}
+
+OP(gteSWC2e_stall) {
+ gteCheckStall(0);
+ if (checkST(regs_, _oB_, 3))
+ gteSWC2(regs_, code);
+}
+
+OP(psxCOP3) {
+ // ??? what actually happens here?
+ log_unhandled("COP3 %08x @%08x\n", code, regs_->pc - 4);