+ {
+ int handle = 0;
+
+ /* start-sanitize-sky */
+#ifdef TARGET_SKY
+ /* On the R5900, this refers to a "VU" vector co-processor. */
+
+ int i_25_21 = (instruction >> 21) & 0x1f;
+ int i_20_16 = (instruction >> 16) & 0x1f;
+ int i_15_11 = (instruction >> 11) & 0x1f;
+ int i_15_0 = instruction & 0xffff;
+ int i_10_1 = (instruction >> 1) & 0x3ff;
+ int i_5_0 = instruction & 0x03f;
+ int interlock = instruction & 0x01;
+ int co = (instruction >> 25) & 0x01;
+ /* setup for semantic.c-like actions below */
+ typedef unsigned_4 instruction_word;
+ int CIA = cia;
+ int NIA = cia + 4;
+ sim_cpu* CPU_ = cpu;
+
+ handle = 1;
+
+ /* test COP2 usability */
+ if(! (SR & status_CU2))
+ {
+ SignalException(CoProcessorUnusable,instruction);
+ /* NOTREACHED */
+ }
+
+ /* classify & execute basic COP2 instructions */
+ if(i_25_21 == 0x08 && i_20_16 == 0x00) /* BC2F */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+ }
+ else if(i_25_21 == 0x08 && i_20_16==0x02) /* BC2FL */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+ else NULLIFY_NEXT_INSTRUCTION();
+ }
+ else if(i_25_21 == 0x08 && i_20_16 == 0x01) /* BC2T */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+ }
+ else if(i_25_21 == 0x08 && i_20_16 == 0x03) /* BC2TL */
+ {
+ address_word offset = EXTEND16(i_15_0) << 2;
+ if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
+ else NULLIFY_NEXT_INSTRUCTION();
+ }
+ else if((i_25_21 == 0x02 && i_10_1 == 0x000) || /* CFC2 */
+ (i_25_21 == 0x01)) /* QMFC2 */
+ {
+ int rt = i_20_16;
+ int id = i_15_11;
+ address_word vu_cr_addr; /* VU control register address */
+ unsigned_4 data;
+
+ /* interlock checking */
+ if(vu0_busy_in_macro_mode()) /* busy in macro mode */
+ {
+ /* interlock bit invalid here */
+ if(interlock)
+ ; /* XXX: warning */
+
+ /* always check data hazard */
+ while(vu0_macro_hazard_check(id))
+ vu0_issue(sd);
+ }
+ else if(vu0_busy_in_micro_mode() && interlock)
+ {
+ while(vu0_busy_in_micro_mode())
+ vu0_issue(sd);
+ }
+
+ /* compute VU register address */
+ if(i_25_21 == 0x01) /* QMFC2 */
+ vu_cr_addr = VU0_REGISTER_WINDOW_START + (id * 16);
+ else /* CFC2 */
+ vu_cr_addr = VU0_MST + (id * 16);
+
+ /* read or write word */
+ data = sim_core_read_aligned_4(cpu, cia, read_map, vu_cr_addr);
+ GPR[rt] = EXTEND64(data);
+ }
+ else if((i_25_21 == 0x06 && i_10_1 == 0x000) || /* CTC2 */
+ (i_25_21 == 0x05)) /* QMTC2 */
+ {
+ int rt = i_20_16;
+ int id = i_15_11;
+ address_word vu_cr_addr; /* VU control register address */
+ unsigned_4 data;
+
+ /* interlock checking */
+ if(vu0_busy_in_macro_mode()) /* busy in macro mode */
+ {
+ /* interlock bit invalid here */
+ if(interlock)
+ ; /* XXX: warning */
+
+ /* always check data hazard */
+ while(vu0_macro_hazard_check(id))
+ vu0_issue(sd);
+ }
+ else if(vu0_busy_in_micro_mode())
+ {
+ if(interlock)
+ {
+ while(! vu0_micro_interlock_released())
+ vu0_issue(sd);
+ }
+ }
+
+ /* compute VU register address */
+ if(i_25_21 == 0x05) /* QMTC2 */
+ vu_cr_addr = VU0_REGISTER_WINDOW_START + (id * 16);
+ else /* CTC2 */
+ vu_cr_addr = VU0_MST + (id * 16);
+
+ data = GPR[rt];
+ sim_core_write_aligned_4(cpu, cia, write_map, vu_cr_addr, data);
+ }
+ else if( 0 /* XXX: ... upper ... */)
+ {
+ unsigned_4 vu_upper, vu_lower;
+ vu_upper =
+ 0x00000000 | /* bits 31 .. 25 */
+ instruction & 0x01ffffff; /* bits 24 .. 0 */
+ vu_lower = 0x8000033c; /* NOP */
+
+ while(vu0_busy_in_micro_mode())
+ vu0_issue(sd);
+
+ vu0_macro_issue(vu_upper, vu_lower);
+ }
+ else if( 0 /* XXX: ... lower ... */)
+ {
+ unsigned_4 vu_upper, vu_lower;
+ vu_upper = 0x000002ff; /* NOP */
+ vu_lower =
+ 0x10000000 | /* bits 31 .. 25 */
+ instruction & 0x01ffffff; /* bits 24 .. 0 */
+
+ while(vu0_busy_in_micro_mode())
+ vu0_issue(sd);
+
+ vu0_macro_issue(vu_upper, vu_lower);
+ }
+ /* XXX */
+ /* ... other COP2 instructions ... */
+ else
+ {
+ SignalException(ReservedInstruction, instruction);
+ /* NOTREACHED */
+ }
+
+ /* cleanup for semantic.c-like actions above */
+ PC = NIA;
+
+#endif /* TARGET_SKY */
+ /* end-sanitize-sky */
+
+ if(! handle)
+ {
+ sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
+ instruction,pr_addr(cia));
+ }
+ }
+ break;
+