X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fmips%2Finterp.c;h=a8788d7393926152a8aa0622b78cac8381a585d7;hb=c0a4c3ba170e91bf93d16e0a6340980f6d62901a;hp=1ab0f11f4283e5a65fef99e0e54a22d18cf34c07;hpb=64ed8b6a8ca5f7eb48f3e19662e3c0d949cfd7dd;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/mips/interp.c b/sim/mips/interp.c index 1ab0f11f42..a8788d7393 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -44,6 +44,7 @@ code on the hardware. #include "sky-vpe.h" #include "sky-libvpe.h" #include "sky-pke.h" +#include "idecode.h" #endif /* end-sanitize-sky */ @@ -671,31 +672,31 @@ sim_store_register (sd,rn,memory,length) if( rn < NUM_VU_REGS ) { if (rn < NUM_VU_INTEGER_REGS) - return write_vu_int_reg (&(vu0_device.state->regs), rn, memory); + return write_vu_int_reg (&(vu0_device.regs), rn, memory); else if (rn >= FIRST_VEC_REG) { rn -= FIRST_VEC_REG; - return write_vu_vec_reg (&(vu0_device.state->regs), rn>>2, rn&3, + return write_vu_vec_reg (&(vu0_device.regs), rn>>2, rn&3, memory); } else switch (rn - NUM_VU_INTEGER_REGS) { case 0: - return write_vu_special_reg (vu0_device.state, VU_REG_CIA, + return write_vu_special_reg (&vu0_device, VU_REG_CIA, memory); case 1: - return write_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MR, + return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MR, memory); case 2: /* VU0 has no P register */ return 4; case 3: - return write_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MI, + return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MI, memory); case 4: - return write_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MQ, + return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ, memory); default: - return write_vu_acc_reg (&(vu0_device.state->regs), + return write_vu_acc_reg (&(vu0_device.regs), rn - (NUM_VU_INTEGER_REGS + 5), memory); } @@ -706,32 +707,32 @@ sim_store_register (sd,rn,memory,length) if (rn < NUM_VU_REGS) { if (rn < NUM_VU_INTEGER_REGS) - return write_vu_int_reg (&(vu1_device.state->regs), rn, memory); + return write_vu_int_reg (&(vu1_device.regs), rn, memory); else if (rn >= FIRST_VEC_REG) { rn -= FIRST_VEC_REG; - return write_vu_vec_reg (&(vu1_device.state->regs), + return write_vu_vec_reg (&(vu1_device.regs), rn >> 2, rn & 3, memory); } else switch (rn - NUM_VU_INTEGER_REGS) { case 0: - return write_vu_special_reg (vu1_device.state, VU_REG_CIA, + return write_vu_special_reg (&vu1_device, VU_REG_CIA, memory); case 1: - return write_vu_misc_reg (&(vu1_device.state->regs), VU_REG_MR, + return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MR, memory); case 2: - return write_vu_misc_reg (&(vu1_device.state->regs), VU_REG_MP, + return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MP, memory); case 3: - return write_vu_misc_reg (&(vu1_device.state->regs), VU_REG_MI, + return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MI, memory); case 4: - return write_vu_misc_reg (&(vu1_device.state->regs), VU_REG_MQ, + return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MQ, memory); default: - return write_vu_acc_reg (&(vu1_device.state->regs), + return write_vu_acc_reg (&(vu1_device.regs), rn - (NUM_VU_INTEGER_REGS + 5), memory); } @@ -846,31 +847,31 @@ sim_fetch_register (sd,rn,memory,length) if (rn < NUM_VU_REGS) { if (rn < NUM_VU_INTEGER_REGS) - return read_vu_int_reg (&(vu0_device.state->regs), rn, memory); + return read_vu_int_reg (&(vu0_device.regs), rn, memory); else if (rn >= FIRST_VEC_REG) { rn -= FIRST_VEC_REG; - return read_vu_vec_reg (&(vu0_device.state->regs), rn>>2, rn & 3, + return read_vu_vec_reg (&(vu0_device.regs), rn>>2, rn & 3, memory); } else switch (rn - NUM_VU_INTEGER_REGS) { case 0: - return read_vu_special_reg(vu0_device.state, VU_REG_CIA, memory); + return read_vu_special_reg(&vu0_device, VU_REG_CIA, memory); case 1: - return read_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MR, + return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MR, memory); case 2: /* VU0 has no P register */ *((int *) memory) = 0; return 4; case 3: - return read_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MI, + return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MI, memory); case 4: - return read_vu_misc_reg (&(vu0_device.state->regs), VU_REG_MQ, + return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ, memory); default: - return read_vu_acc_reg (&(vu0_device.state->regs), + return read_vu_acc_reg (&(vu0_device.regs), rn - (NUM_VU_INTEGER_REGS + 5), memory); } @@ -881,31 +882,31 @@ sim_fetch_register (sd,rn,memory,length) if (rn < NUM_VU_REGS) { if (rn < NUM_VU_INTEGER_REGS) - return read_vu_int_reg (&(vu1_device.state->regs), rn, memory); + return read_vu_int_reg (&(vu1_device.regs), rn, memory); else if (rn >= FIRST_VEC_REG) { rn -= FIRST_VEC_REG; - return read_vu_vec_reg (&(vu1_device.state->regs), + return read_vu_vec_reg (&(vu1_device.regs), rn >> 2, rn & 3, memory); } else switch (rn - NUM_VU_INTEGER_REGS) { case 0: - return read_vu_special_reg(vu1_device.state, VU_REG_CIA, memory); + return read_vu_special_reg(&vu1_device, VU_REG_CIA, memory); case 1: - return read_vu_misc_reg (&(vu1_device.state->regs), + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MR, memory); case 2: - return read_vu_misc_reg (&(vu1_device.state->regs), + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MP, memory); case 3: - return read_vu_misc_reg (&(vu1_device.state->regs), + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MI, memory); case 4: - return read_vu_misc_reg (&(vu1_device.state->regs), + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MQ, memory); default: - return read_vu_acc_reg (&(vu1_device.state->regs), + return read_vu_acc_reg (&(vu1_device.regs), rn - (NUM_VU_INTEGER_REGS + 5), memory); } @@ -2970,9 +2971,22 @@ cop_lq (SIM_DESC sd, switch (coproc_num) { case 2: - /* XXX COP2 */ - break; - + { + unsigned_16 xyzw; + + while(vu0_busy()) + vu0_issue(sd); + + memcpy(& xyzw, & memword, sizeof(xyzw)); + xyzw = H2T_16(xyzw); + /* one word at a time, argh! */ + write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 0, A4_16(& xyzw, 3)); + write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 1, A4_16(& xyzw, 2)); + write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 2, A4_16(& xyzw, 1)); + write_vu_vec_reg(&(vu0_device.regs), coproc_reg, 3, A4_16(& xyzw, 0)); + } + break; + default: sim_io_printf(sd,"COP_LQ(%d,%d,??) at PC = 0x%s : TODO (architecture specific)\n", coproc_num,coproc_reg,pr_addr(cia)); @@ -3058,9 +3072,22 @@ cop_sq (SIM_DESC sd, switch (coproc_num) { case 2: - /* XXX COP2 */ - break; + { + unsigned_16 xyzw; + while(vu0_busy()) + vu0_issue(sd); + + /* one word at a time, argh! */ + read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 0, A4_16(& xyzw, 3)); + read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 1, A4_16(& xyzw, 2)); + read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 2, A4_16(& xyzw, 1)); + read_vu_vec_reg(&(vu0_device.regs), coproc_reg, 3, A4_16(& xyzw, 0)); + xyzw = T2H_16(xyzw); + return xyzw; + } + break; + default: sim_io_printf(sd,"COP_SQ(%d,%d) at PC = 0x%s : TODO (architecture specific)\n", coproc_num,coproc_reg,pr_addr(cia)); @@ -3213,7 +3240,7 @@ decode_coproc (SIM_DESC sd, } break; - case 2: /* undefined co-processor */ + case 2: /* co-processor 2 */ { int handle = 0; @@ -3223,12 +3250,14 @@ decode_coproc (SIM_DESC sd, int i_25_21 = (instruction >> 21) & 0x1f; int i_20_16 = (instruction >> 16) & 0x1f; + int i_20_6 = (instruction >> 6) & 0x7fff; int i_15_11 = (instruction >> 11) & 0x1f; int i_15_0 = instruction & 0xffff; int i_10_1 = (instruction >> 1) & 0x3ff; + int i_10_0 = instruction & 0x7ff; + int i_10_6 = (instruction >> 6) & 0x1f; 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; @@ -3272,101 +3301,138 @@ decode_coproc (SIM_DESC sd, { 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 */ + /* POLICY: never busy in macro mode */ + while(vu0_busy() && interlock) + vu0_issue(sd); - /* always check data hazard */ - while(vu0_macro_hazard_check(id)) - vu0_issue(sd); - } - else if(vu0_busy_in_micro_mode() && interlock) + /* perform VU register address */ + if(i_25_21 == 0x01) /* QMFC2 */ { - while(vu0_busy_in_micro_mode()) - vu0_issue(sd); + unsigned_16 xyzw; + /* one word at a time, argh! */ + read_vu_vec_reg(&(vu0_device.regs), id, 0, A4_16(& xyzw, 3)); + read_vu_vec_reg(&(vu0_device.regs), id, 1, A4_16(& xyzw, 2)); + read_vu_vec_reg(&(vu0_device.regs), id, 2, A4_16(& xyzw, 1)); + read_vu_vec_reg(&(vu0_device.regs), id, 3, A4_16(& xyzw, 0)); + xyzw = T2H_16(xyzw); + memcpy(& GPR[rt], & xyzw, sizeof(xyzw)); } - - /* 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); + { + unsigned_4 data; + /* enum + int calculation, argh! */ + id = VU_REG_MST + 16 * id; + read_vu_misc_reg(&(vu0_device.regs), id, & data); + GPR[rt] = EXTEND32(T2H_4(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 */ + /* POLICY: never busy in macro mode */ + if(vu0_busy() && interlock) { - /* interlock bit invalid here */ - if(interlock) - ; /* XXX: warning */ - - /* always check data hazard */ - while(vu0_macro_hazard_check(id)) + while(! vu0_micro_interlock_released()) vu0_issue(sd); } - else if(vu0_busy_in_micro_mode()) + + /* perform VU register address */ + if(i_25_21 == 0x05) /* QMTC2 */ { - if(interlock) - { - while(! vu0_micro_interlock_released()) - vu0_issue(sd); - } + unsigned_16 xyzw; + memcpy(& xyzw, & GPR[rt], sizeof(xyzw)); + xyzw = H2T_16(xyzw); + /* one word at a time, argh! */ + write_vu_vec_reg(&(vu0_device.regs), id, 0, A4_16(& xyzw, 3)); + write_vu_vec_reg(&(vu0_device.regs), id, 1, A4_16(& xyzw, 2)); + write_vu_vec_reg(&(vu0_device.regs), id, 2, A4_16(& xyzw, 1)); + write_vu_vec_reg(&(vu0_device.regs), id, 3, A4_16(& xyzw, 0)); } - - /* 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); + { + unsigned_4 data = H2T_4(GPR[rt]); + /* enum + int calculation, argh! */ + id = VU_REG_MST + 16 * id; + write_vu_misc_reg(&(vu0_device.regs), id, & data); + } + } + else if(i_10_0 == 0x3bf) /* VWAITQ */ + { + while(vu0_q_busy()) + vu0_issue(sd); + } + else if(i_5_0 == 0x38) /* VCALLMS */ + { + unsigned_4 data = H2T_2(i_20_6); + + while(vu0_busy()) + vu0_issue(sd); + + /* write to reserved CIA register to get VU0 moving */ + write_vu_special_reg(& vu0_device, VU_REG_CIA, & data); + + ASSERT(vu0_busy()); + } + else if(i_5_0 == 0x39) /* VCALLMSR */ + { + unsigned_4 data; + + while(vu0_busy()) + vu0_issue(sd); + + read_vu_special_reg(& vu0_device, VU_REG_CMSAR0, & data); + /* write to reserved CIA register to get VU0 moving */ + write_vu_special_reg(& vu0_device, VU_REG_CIA, & data); - data = GPR[rt]; - sim_core_write_aligned_4(cpu, cia, write_map, vu_cr_addr, data); + ASSERT(vu0_busy()); } - else if( 0 /* XXX: ... upper ... */) + /* handle all remaining UPPER VU instructions in one block */ + else if((i_5_0 < 0x30) || /* VADDx .. VMINI */ + (i_5_0 >= 0x3c && i_10_6 < 0x0c)) /* VADDAx .. VNOP */ { unsigned_4 vu_upper, vu_lower; vu_upper = 0x00000000 | /* bits 31 .. 25 */ - instruction & 0x01ffffff; /* bits 24 .. 0 */ + (instruction & 0x01ffffff); /* bits 24 .. 0 */ vu_lower = 0x8000033c; /* NOP */ - while(vu0_busy_in_micro_mode()) + /* POLICY: never busy in macro mode */ + while(vu0_busy()) vu0_issue(sd); vu0_macro_issue(vu_upper, vu_lower); + + /* POLICY: wait for completion of macro-instruction */ + while(vu0_busy()) + vu0_issue(sd); } - else if( 0 /* XXX: ... lower ... */) - { + /* handle all remaining LOWER VU instructions in one block */ + else if((i_5_0 >= 0x30 && i_5_0 <= 0x35) || /* VIADD .. VIOR */ + (i_5_0 >= 0x3c && i_10_6 >= 0x0c)) /* VMOVE .. VRXOR */ + { /* N.B.: VWAITQ already covered by prior case */ unsigned_4 vu_upper, vu_lower; - vu_upper = 0x000002ff; /* NOP */ + vu_upper = 0x000002ff; /* NOP/NOP */ vu_lower = - 0x10000000 | /* bits 31 .. 25 */ - instruction & 0x01ffffff; /* bits 24 .. 0 */ + 0x80000000 | /* bits 31 .. 25 */ + (instruction & 0x01ffffff); /* bits 24 .. 0 */ - while(vu0_busy_in_micro_mode()) + /* POLICY: never busy in macro mode */ + while(vu0_busy()) vu0_issue(sd); vu0_macro_issue(vu_upper, vu_lower); + + /* POLICY: wait for completion of macro-instruction */ + while(vu0_busy()) + vu0_issue(sd); } - /* XXX */ - /* ... other COP2 instructions ... */ + /* ... no other COP2 instructions ... */ else { SignalException(ReservedInstruction, instruction); @@ -3381,7 +3447,7 @@ decode_coproc (SIM_DESC sd, if(! handle) { - sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n", + sim_io_eprintf(sd, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n", instruction,pr_addr(cia)); } }