/****************************************************************************/ /* */ /* Sony Computer Entertainment CONFIDENTIAL */ /* (C) 1997 Sony Computer Entertainment Inc. All Rights Reserved */ /* */ /* VU simulator */ /* */ /****************************************************************************/ #include "vpe.h" #include "libvpe.h" #include #include unsigned long _ITOP; unsigned long _TOP; unsigned long _vpepc; int _is_dbg; int _is_verb; int _is_dump; int _pgpuif; FILE *_fp_gpu; int _GIF_SIM_OFF; int _GIF_BUSY; int _GIF_VUCALL; int _GIF_VUADDR; /****************************************************************************/ /* Some external declarations ... */ void GpuIfKick(VectorUnitState *state, int addr); void opcode_analyze(u_long *opcode); #define VF state->regs.VF #define VI state->regs.VI void initvpe(VectorUnitState *state) { /* [name] initvpe [desc] Initialize internal status of VU simulator. [args] void [return] void */ int i, j; _fp_gpu = stdout; VF[0][0] = 0.0; VF[0][1] = 0.5; VF[0][2] = -1.0; VF[0][3] = 1.0; VI[0] = 0; eflag = 0; jflag = 0; peflag = 0; sflag = 0; pc = _vpepc; jaddr = 0; bp = 0xffffffff; for (i = 0; i < 4; i++) { for (j = 0; j < 2; j++) { pipe[i][j].flag = 0; } } for (i = 0; i < 7; i++) { qpipe[i].flag = 0; } for (i = 0; i < 13; i++) { rqpipe[i].flag = 0; } ipipe[0].flag = 0; ipipe[1].flag = 0; apipe.flag = 0; Ipipe.flag = 0; spipe.no = 0; spipe.flag = 0; for (i = 1; i < 16; i++) { VI[i] = 0; } for (i = 1; i < 32; i++) { for (j = 0; j < 4; j++) { VF[i][j] = 0.0; } } /* EFU internal regstars */ VN[8] = 1.0; VN[9] = 1.0; /* S1 */ VN[10] = -0.166666567325592; /* S2 */ VN[11] = 0.008333025500178; /* S3 */ VN[12] = -0.000198074136279; /* S4 */ VN[13] = 0.000002601886990; /* S5 */ VN[14] = 0.999999344348907; /* T1 */ VN[15] = -0.333298563957214; /* T2 */ VN[16] = 0.199465364217758; /* T3 */ VN[17] = -0.139085337519646; /* T4 */ VN[18] = 0.096420042216778; /* T5 */ VN[19] = -0.055909886956215; /* T6 */ VN[20] = 0.021861229091883; /* T7 */ VN[21] = -0.004054057877511; /* T8 */ VN[22] = 0.7853981633974483; /* PI/4 */ VN[23] = 0.2499986842; /* E1 */ VN[24] = 0.0312575832; /* E2 */ VN[25] = 0.0025913712; /* E3 */ VN[26] = 0.0001715620; /* E4 */ VN[27] = 0.0000054302; /* E5 */ VN[28] = 0.0000006906; /* E6 */ _GIF_SIM_OFF = 0; _GIF_BUSY = 0; _GIF_VUCALL = 0; _GIF_VUADDR = 0; intr_mode = _is_dbg; ecount = 0; } int get_dest(u_long opcode) { /* [name] get_dest [desc.] get dest field of instruction. [args] opcode: instruction(32bits) [return] dest field value(4bits) */ return ((int) ((opcode >> 21) & 0xf)); } int get_ft(u_long opcode) { /* [name] get_ft [desc.] get ft field of instruction [args] opcode: instruction(32bits) [return] ft field value(5bits) */ return ((int) ((opcode >> 16) & 0x1f)); } int get_fs(u_long opcode) { /* [name] get_fs [desc.] get fs field of instruction [args] opcode: instruction(32bits) [return] fs field value(5bits) */ return ((int) ((opcode >> 11) & 0x1f)); } int get_fd(u_long opcode) { /* [name] get_fd [desc.] get fd field of instruction [args] opcode: instruction(32bits) [return] fd field value(5bits) */ return ((int) ((opcode >> 6) & 0x1f)); } int get_bc(u_long opcode) { /* [name] get_bc [desc.] get bc field of instruction [args] opcode: instruction(32bit) [return] bc field value(2bits); */ return ((int) (opcode & 0x3)); } int get_ic(u_long opcode) { /* [name] get_ic [desc.] get bit25 and bit26 in instruction [args] opcode: instruction(32bit) [return] bit 25 and bit26 value(2bits) */ return ((int) ((opcode >> 25) & 0x3)); } int get_fsf(u_long opcode) { /* [name] get_fsf [desc.] get fsf field of instruction [args] opcode: instruction(32bit) [return] fsf field value(2bits) */ return ((opcode >> 21) & 0x3); } int get_ftf(u_long opcode) { /* [name] get_ftf [desc.] get ftf field of instruction [args] opcode: instruction(32bit) [return] ftf field value(2bits) */ return ((opcode >> 23) & 0x3); } void statuscheck(float arg, u_long * status, int no) { /* [name] statuscheck [desc.] FMAC status decide when FMAC calculates. [args] arg: calculated value by FMAC. status: FMAC status pointer. no: FMAC number [return] void */ /* write status flag's value */ if (arg == 0.0) *status = *status | 1; if (arg < 0.0) *status = *status | 2; /* write MACflag's value */ switch (no) { case 0: if (arg == 0.0) *status |= 0x80000; if (arg < 0.0) *status |= 0x800000; break; case 1: if (arg == 0.0) *status |= 0x40000; if (arg < 0.0) *status |= 0x400000; break; case 2: if (arg == 0.0) *status |= 0x20000; if (arg < 0.0) *status |= 0x200000; break; case 3: if (arg == 0.0) *status |= 0x10000; if (arg < 0.0) *status |= 0x100000; break; } } int hazardcheck(int fs, int ft, int dest, int type) { /* [name] hazardcheck If destinatin registers in pipeline is same as source register, data hazard occured. [args] fs: If fs field assigns source register, set source register number in this argment. ft: If ft field assigns source register, set souce register number in this argment dest: specify which units calculate type: source register type 1: source register is ft field 2: source register is fs field 3: source registers are ft and fs field [return] 0: hazard not occured 1: hazard occured */ int i, j; for (i = 3; i >= 0; i--) { for (j = 0; j < 2; j++) { if (pipe[i][j].flag == 1) { if (type & 0x1) { if ((pipe[i][j].no == ft) && (pipe[i][j].mask | dest)) { sflag = 1; hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); return 1; } } if (type & 0x2) { if ((pipe[i][j].no == fs) && (pipe[i][j].mask | dest)) { sflag = 1; hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, fs); return 1; } } } if (pipe[i][j].flag == 6) { if (type & 0x1) { if ((pipe[i][j].no == ft) && (pipe[i][j].mask | dest)) { sflag = 1; hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); return 1; } } if (type & 0x2) { if ((pipe[i][j].no == fs) && (pipe[i][j].mask | dest)) { sflag = 1; hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, fs); return 1; } } } } } sflag = 0; return 0; } int hazardcheckVI(int fs, int ft, int type) { /* [name] hazardcheckVI [desc.] data hazarde check. (VI register) If destinatin registers in pipeline is same as source register, data hazard occured. [args] fs: If fs field assigns source register, set source register number in this argment. ft: If ft field assigns source register, set souce register number in this argment type: source register type 1: source register is ft field 2: source register is fs field 3: source registers are ft and fs field [return] 0: hazard not occured 1: hazard occured */ int i; for (i = 1; i >= 0; i--) { if (ipipe[i].flag == 1) { if (type & 0x1) { if (ipipe[i].no == ft) { hc_count++; if (verb_mode) printf("[data hazard %04d:VI%02d]\n", pc - 1, ft); sflag = 1; return 1; } } if (type & 0x2) { if (ipipe[i].no == fs) { hc_count++; if (verb_mode) printf("[data hazard %04d:VI%02d]\n", pc - 1, fs); sflag = 1; return 1; } } } } sflag = 0; return 0; } int hazardcheckFTF(int fs, int ft, int fsf, int ftf, int type) { /* [name] hazardcheckFTF [desc.] data hazarde check. (VF register) If destinatin registers in pipeline is same as source register, data hazard occured. [args] fs: If fs field assigns source register, set source register number in this argment. ft: If ft field assigns source register, set souce register number in this argment fsf: If fsf field assigns source register, set source register number in this argment. ftf: If ftf field assigns source register, set souce register number in this argment type: source register type 1: source register is ft field 2: source register is fs field 3: source registers are ft and fs field [return] 0: hazard not occured 1: hazard occured */ int i, j; for (i = 3; i >= 0; i--) { for (j = 0; j < 2; j++) { if (pipe[i][j].flag == 1) { if (type & 0x1) { if (pipe[i][j].no == ft) { switch (ftf) { case 0: if (pipe[i][j].mask & DEST_X) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); sflag = 1; return 1; } break; case 1: if (pipe[i][j].mask & DEST_Y) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); sflag = 1; return 1; } break; case 2: if (pipe[i][j].mask & DEST_Z) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); sflag = 1; return 1; } break; case 3: if (pipe[i][j].mask & DEST_W) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); sflag = 1; return 1; } break; } } } if (type & 0x2) { if (pipe[i][j].no == fs) { switch (fsf) { case 0: if (pipe[i][j].mask & DEST_X) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, fs); sflag = 1; return 1; } break; case 1: if (pipe[i][j].mask & DEST_Y) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, fs); sflag = 1; return 1; } break; case 2: if (pipe[i][j].mask & DEST_Z) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, fs); sflag = 1; return 1; } break; case 3: if (pipe[i][j].mask & DEST_W) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, fs); sflag = 1; return 1; } break; } } } } } } sflag = 0; return 0; } int hazardcheckBC(int fs, int ft, int dest, int bc, int type) { /* [name] hazardcheckBC [desc.] data hazarde check. (VF register) If destinatin registers in pipeline is same as source register, data hazard occured. [args] fs: If fs field assigns source register, set source register number in this argment. ft: If ft field assigns source register, set souce register number in this argment dest: specify which units calculate bc: specify which broadcast units type: source register type 1: source register is ft field 2: source register is fs field 3: source registers are ft and fs field [return] 0: hazard not occured 1: hazard occured */ int i, j; for (i = 3; i >= 0; i--) { for (j = 0; j < 2; j++) { if ((pipe[i][j].flag == 1) || (pipe[i][j].flag == 7)) { if (type & 0x1) { if (pipe[i][j].no == ft) { switch (bc) { case 0: if (pipe[i][j].mask & DEST_X) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); sflag = 1; return 1; } break; case 1: if (pipe[i][j].mask & DEST_Y) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); sflag = 1; return 1; } break; case 2: if (pipe[i][j].mask & DEST_Z) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); sflag = 1; return 1; } break; case 3: if (pipe[i][j].mask & DEST_W) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); sflag = 1; return 1; } break; } } } if (type & 0x2) { if ((pipe[i][j].no == fs) && (pipe[i][j].mask | dest)) { hc_count++; if (verb_mode) printf("[data hazard %04d:VF%02d]\n", pc - 1, ft); sflag = 1; return 1; } } } } } sflag = 0; return 0; } int hazardcheckQ(void) { /* [name] hazardcheckQ [desc.] resource hazarde check. (FDIV unit) If instruction use FDIV unit when FDIV is calculating, resource hazard occured. [args] void [return] 0: hazard not occured 1: hazard occured */ int i; for (i = 5; i >= 0; i--) { if (qpipe[i].flag == 1) { hc_count++; if (verb_mode) printf("[resource hazard %04d:FDIV]\n", pc - 1); sflag = 1; return 1; } } for (i = 11; i >= 0; i--) { if (rqpipe[i].flag == 1) { hc_count++; if (verb_mode) printf("[resource hazard %04d:FDIV]\n", pc - 1); sflag = 1; return 1; } } sflag = 0; return 0; } int hazardcheckP(void) { /* [name] hazardcheckP [desc.] resource hazarde check. (EFU) If instruction use EFU unit when EFU is calculating, resource hazard occured. [args] void [return] 0: hazard not occured 1: hazard occured */ if (spipe.no != 0) { hc_count++; if (verb_mode) printf("[resource hazard %04d:EFU]\n", pc - 1); sflag = 1; return 1; } sflag = 0; return 0; } int Lower_special(VectorUnitState *state, u_long iL) { /* [name] Lower_special [desc.] Micro Special OPCODE (Lower instruction) execute [args] iL: lower instruction(32bits) [return] 0: executed 1: stall ( hazard occured) */ double dval, ddval; float fval; u_long ival; switch ((iL >> 6) & 0x1f) { case 12: /* MOVE, MR32, ---, --- */ switch (get_bc(iL)) { case 0: /* MOVE */ if ((get_fs(iL) != 0) || (get_ft(iL) != 0)) { if (hazardcheck(get_fs(iL), 0, get_dest(iL), 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].no = get_ft(iL); pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "MOVE"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = VF[get_fs(iL)][0]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = VF[get_fs(iL)][1]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = VF[get_fs(iL)][2]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = VF[get_fs(iL)][3]; } break; case 1: /* MR32 */ if (hazardcheck(get_fs(iL), 0, get_dest(iL), 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].no = get_ft(iL); pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "MR32"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = VF[get_fs(iL)][1]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = VF[get_fs(iL)][2]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = VF[get_fs(iL)][3]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = VF[get_fs(iL)][0]; break; default: fprintf(stderr, "Undefined opcode(%08x)\n", iL); exit(1); } break; case 13: /* LQI, SQI, LQD, SQD */ switch (get_bc(iL)) { case 0: /* LQI */ if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].no = get_ft(iL); pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "LQI"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = *(float *) &state->MEM[VI[get_fs(iL)]][0]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = *(float *) &state->MEM[VI[get_fs(iL)]][1]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = *(float *) &state->MEM[VI[get_fs(iL)]][2]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = *(float *) &state->MEM[VI[get_fs(iL)]][3]; VI[get_fs(iL)] += 1; break; case 1: /* SQI */ /*printf("SQI\n"); printpipe(); printf("fs:%d ft:%d dest:%d)\n", get_fs(iL), get_ft(iL), get_dest(iL)); printf("hazardcheck(%d, %d, %d, %d)\n", 0, get_ft(iL), get_dest(iL), 1); */ //if (hazardcheck(0, get_ft(iL), get_dest(iL), 1) || //hazardcheckVI(get_fs(iL), 0, 2)) { if (hazardcheck(0, get_fs(iL), get_dest(iL), 1) || hazardcheckVI(get_ft(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 2; pipe[0][1].addr = VI[get_ft(iL)]; strcpy(pipe[0][1].code, "SQI"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = VF[get_fs(iL)][0]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = VF[get_fs(iL)][1]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = VF[get_fs(iL)][2]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = VF[get_fs(iL)][3]; VI[get_ft(iL)] += 1; break; case 2: /* LQD */ if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].no = get_ft(iL); pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "LQD"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = *(float *) &state->MEM[VI[get_fs(iL)] - 1][0]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = *(float *) &state->MEM[VI[get_fs(iL)] - 1][1]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = *(float *) &state->MEM[VI[get_fs(iL)] - 1][2]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = *(float *) &state->MEM[VI[get_fs(iL)] - 1][3]; VI[get_fs(iL)] -= 1; break; case 3: /* SQD */ if (hazardcheck(0, get_ft(iL), get_dest(iL), 1) || hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 2; pipe[0][1].addr = VI[get_ft(iL)] - 1; strcpy(pipe[0][1].code, "SQD"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = VF[get_fs(iL)][0]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = VF[get_fs(iL)][1]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = VF[get_fs(iL)][2]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = VF[get_fs(iL)][3]; VI[get_ft(iL)] -= 1; break; } break; case 14: /* DIV, SQRT, RSQRT, WAITQ */ switch (get_bc(iL)) { case 0: /* DIV */ if (hazardcheckFTF(get_fs(iL), get_ft(iL), get_fsf(iL), get_ftf(iL), 3) || hazardcheckQ()) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } qpipe[0].flag = 1; if(VF[get_ft(iL)][get_ftf(iL)] == 0){ *(u_long *)&qpipe[0].vf[0] = 0x7fffffff; if(VF[get_fs(iL)][get_fsf(iL)] == 0) qpipe[0].status |= 0x10; else qpipe[0].status |= 0x20; }else{ qpipe[0].vf[0] = VF[get_fs(iL)][get_fsf(iL)] / VF[get_ft(iL)][get_ftf(iL)]; qpipe[0].status = 0; } strcpy(qpipe[0].code, "DIV"); break; case 1: /* SQRT */ if (hazardcheckFTF(0, get_ft(iL), 0, get_ftf(iL), 1) || hazardcheckQ()) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } qpipe[0].flag = 1; dval = (double) VF[get_ft(iL)][get_ftf(iL)]; if(dval < 0){ dval = 0 - dval; qpipe[0].status |= 0x10; }else{ qpipe[0].status = 0; } ddval = sqrt(dval); qpipe[0].vf[0] = (float) ddval; strcpy(qpipe[0].code, "SQRT"); break; case 2: /* RSQRT */ if (hazardcheckFTF(0, get_ft(iL), 0, get_ftf(iL), 1) || hazardcheckQ()) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } rqpipe[0].flag = 1; dval = (double) (VF[get_ft(iL)][get_ftf(iL)]); if(dval < 0){ dval = 0 - dval; qpipe[0].status |= 0x10; } ddval = sqrt(dval); dval = (double) (VF[get_fs(iL)][get_fsf(iL)]); if(ddval < 0){ qpipe[0].status |= 0x20; *(u_long *)&rqpipe[0].vf[0] = 0x7fffffff; }else{ rqpipe[0].vf[0] = (float) (dval / ddval); } break; case 3: /* WAITQ */ if (hazardcheckQ()) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } break; } break; case 15: /* MTIR, MFIR, ILWR, ISWR */ switch (get_bc(iL)) { case 0: /* MTIR */ if (hazardcheck(get_fs(iL), 0, get_dest(iL), 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].no = get_ft(iL) + 32; pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "MTIR"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = VF[get_fs(iL)][0]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = VF[get_fs(iL)][1]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = VF[get_fs(iL)][2]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = VF[get_fs(iL)][3]; break; case 1: /* MFIR */ if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].no = get_ft(iL); pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "MFIR"); ival = VI[get_fs(iL)]; if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = *(float *) &ival; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = *(float *) &ival; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = *(float *) &ival; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = *(float *) &ival; break; case 2: /* ILWR */ if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].no = get_ft(iL) + 32; pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "ILWR"); if (get_dest(iL) & DEST_X) *(long *) &pipe[0][1].vf[0] = state->MEM[VI[get_fs(iL)]][0]; if (get_dest(iL) & DEST_Y) *(long *) &pipe[0][1].vf[1] = state->MEM[VI[get_fs(iL)]][1]; if (get_dest(iL) & DEST_Z) *(long *) &pipe[0][1].vf[2] = state->MEM[VI[get_fs(iL)]][2]; if (get_dest(iL) & DEST_W) *(long *) &pipe[0][1].vf[3] = state->MEM[VI[get_fs(iL)]][3]; break; case 3: /* ISWR */ if (hazardcheckVI(get_fs(iL), get_ft(iL), 3)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 2; pipe[0][1].addr = VI[get_fs(iL)]; strcpy(pipe[0][1].code, "ISWR"); if (get_dest(iL) & DEST_X) *(long *) &pipe[0][1].vf[0] = (VI[get_ft(iL)]) & 0xffff; if (get_dest(iL) & DEST_Y) *(long *) &pipe[0][1].vf[1] = (VI[get_ft(iL)]) & 0xffff; if (get_dest(iL) & DEST_Z) *(long *) &pipe[0][1].vf[2] = (VI[get_ft(iL)]) & 0xffff; if (get_dest(iL) & DEST_W) *(long *) &pipe[0][1].vf[3] = (VI[get_ft(iL)]) & 0xffff; break; } break; case 16: /* RNEXT, RGET, RINIT, RXOR */ switch (get_bc(iL)) { case 0: /* RNEXT */ pipe[0][1].no = get_ft(iL); pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "RNEXT"); ival = 0; if(((R >> 22) & 0x1) ^ ((R >> 4) & 0x1)) ival = 1; R = ((R << 1) + ival) & 0x007fffff; if (get_dest(iL) & DEST_X) *(u_long *)&pipe[0][1].vf[0] = 0x3f800000 | R; if (get_dest(iL) & DEST_Y) *(u_long *)&pipe[0][1].vf[1] = 0x3f800000 | R; if (get_dest(iL) & DEST_Z) *(u_long *)&pipe[0][1].vf[2] = 0x3f800000 | R; if (get_dest(iL) & DEST_W) *(u_long *)&pipe[0][1].vf[3] = 0x3f800000 | R; break; case 1: /* RGET */ pipe[0][1].no = get_ft(iL); pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "RGET"); if (get_dest(iL) & DEST_X) *(u_long *)&pipe[0][1].vf[0] = 0x3f800000 | R; if (get_dest(iL) & DEST_Y) *(u_long *)&pipe[0][1].vf[1] = 0x3f800000 | R; if (get_dest(iL) & DEST_Z) *(u_long *)&pipe[0][1].vf[2] = 0x3f800000 | R; if (get_dest(iL) & DEST_W) *(u_long *)&pipe[0][1].vf[3] = 0x3f800000 | R; break; case 2: /* RINIT */ if (hazardcheckFTF(get_fs(iL), 0, get_fsf(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } R = *(u_long *)&VF[get_fs(iL)][get_fsf(iL)] & 0x7fffff; break; case 3: /* RXOR */ if (hazardcheckFTF(get_fs(iL), 0, get_fsf(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } R = R ^ (*(u_long *)&VF[get_fs(iL)][get_fsf(iL)] & 0x7fffff); break; } break; case 25: /* MFP, ---, ---, --- */ switch (get_bc(iL)) { case 0: /* MFP */ pipe[0][1].no = get_ft(iL); pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 7; strcpy(pipe[0][1].code, "MFP"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = VN[4]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = VN[4]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = VN[4]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = VN[4]; break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08x)\n", iL); exit(1); break; } break; case 26: /* XITOP, XTOP */ switch (get_bc(iL)) { case 0: /* XTOP */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = (short) _TOP; strcpy(ipipe[0].code, "XTOP"); break; case 1: /* XITOP */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = (short) _ITOP; strcpy(ipipe[0].code, "XITOP"); break; } break; case 27: /* XGKICK */ GpuIfKick(state, VI[get_fs(iL)]); break; case 28: /* ESADD, ERSADD, ELENG, ERLENG */ switch (get_bc(iL)) { case 0: /* ESADD */ if (hazardcheckP() || hazardcheck(0, get_ft(iL), 0xe, 1)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][0]; VN[1] = VF[get_fs(iL)][1]; VN[2] = VF[get_fs(iL)][2]; spipe.vn = VN[0] * VN[0] + VN[1] * VN[1] + VN[2] * VN[2]; spipe.no = 9; break; case 1: /* ERSADD */ if (hazardcheckP() || hazardcheck(0, get_ft(iL), 0xe, 1)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][0]; VN[1] = VF[get_fs(iL)][1]; VN[2] = VF[get_fs(iL)][2]; VN[5] = VN[0] * VN[0] + VN[1] * VN[1] + VN[2] * VN[2]; spipe.vn = 1.0 / VN[5]; spipe.no = 16; break; case 2: /* ELENG */ if (hazardcheckP() || hazardcheck(0, get_ft(iL), 0xe, 1)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][0]; VN[1] = VF[get_fs(iL)][1]; VN[2] = VF[get_fs(iL)][2]; dval = (double) (VN[0] * VN[0] + VN[1] * VN[1] + VN[2] * VN[2]); spipe.vn = (float) sqrt(dval); spipe.no = 16; break; case 3: /* ERLENG */ if (hazardcheckP() || hazardcheck(0, get_ft(iL), 0xe, 1)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][0]; VN[1] = VF[get_fs(iL)][1]; VN[2] = VF[get_fs(iL)][2]; dval = (double) (VN[0] * VN[0] + VN[1] * VN[1] + VN[2] * VN[2]); spipe.vn = 1.0 / (float) sqrt(dval); spipe.no = 22; break; } break; case 29: /* EATANxy, EATANxz, ESUM, --- */ switch (get_bc(iL)) { case 0: /* EATANxy */ if (hazardcheckP() || hazardcheck(0, get_ft(iL), 0xc, 1)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][0]; VN[1] = VF[get_fs(iL)][1]; VN[5] = (VN[1] - VN[0]) / (VN[1] + VN[0]); fval = VN[5]; spipe.vn = VN[14] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[15] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[16] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[17] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[18] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[19] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[20] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[21] * fval; spipe.no = 52; break; case 1: /* EATANxz */ if (hazardcheckP() || hazardcheck(0, get_ft(iL), 0xa, 1)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][0]; VN[2] = VF[get_fs(iL)][2]; VN[5] = (VN[2] - VN[0]) / (VN[2] + VN[0]); fval = VN[5]; spipe.vn = VN[14] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[15] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[16] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[17] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[18] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[19] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[20] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[21] * fval; spipe.no = 52; break; case 2: /* ESUM */ if (hazardcheckP() || hazardcheck(0, get_ft(iL), 0xf, 1)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } spipe.vn = VF[get_fs(iL)][0] + VF[get_fs(iL)][1] + VF[get_fs(iL)][2] + VF[get_fs(iL)][3]; spipe.no = 10; break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08x)\n", iL); exit(1); break; } break; case 30: /* ESQRT, ERSQRT, ERCPR, WAITP */ switch (get_bc(iL)) { case 0: /* ESQRT */ if (hazardcheckP() || hazardcheckFTF(get_fs(iL), 0, get_fsf(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][get_fsf(iL)]; dval = (double) VN[0]; spipe.vn = (float) sqrt(dval); spipe.no = 10; break; case 1: /* ERSQRT */ if (hazardcheckP() || hazardcheckFTF(get_fs(iL), 0, get_fsf(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][get_fsf(iL)]; dval = (double) VN[0]; spipe.vn = 1.0 / (float) sqrt(dval); spipe.no = 16; break; case 2: /* ERCPR */ if (hazardcheckP() || hazardcheckFTF(get_fs(iL), 0, get_fsf(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][get_fsf(iL)]; spipe.vn = 1.0 / VN[0]; spipe.no = 10; break; case 3: /* WAITP */ if (hazardcheckP()) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } break; } break; case 31: /* ESIN, EATAN, EEXP, --- */ switch (get_bc(iL)) { case 0: /* SIN */ if (hazardcheckP() || hazardcheckFTF(get_fs(iL), 0, get_fsf(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][get_fsf(iL)]; fval = VN[0]; spipe.vn = VN[9] * fval; fval = fval * VN[0] * VN[0]; spipe.vn += VN[10] * fval; fval = fval * VN[0] * VN[0]; spipe.vn += VN[11] * fval; fval = fval * VN[0] * VN[0]; spipe.vn += VN[12] * fval; fval = fval * VN[0] * VN[0]; spipe.vn += VN[13] * fval; spipe.no = 27; break; case 1: /* EATAN */ if (hazardcheckP() || hazardcheckFTF(get_fs(iL), 0, get_fsf(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][get_fsf(iL)]; VN[5] = (VN[0] - 1.0) / (VN[0] + 1.0); fval = VN[5]; spipe.vn = VN[14] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[15] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[16] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[17] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[18] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[19] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[20] * fval; fval = fval * VN[5] * VN[5]; spipe.vn += VN[21] * fval; spipe.no = 52; break; case 2: /* EEXP */ if (hazardcheckP() || hazardcheckFTF(get_fs(iL), 0, get_fsf(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } VN[0] = VF[get_fs(iL)][get_fsf(iL)]; fval = 0.0 - VN[0]; VN[5] = fval; VN[6] = 1.0; VN[6] += VN[23] * VN[5]; VN[5] *= fval; VN[6] += VN[24] * VN[5]; VN[5] *= fval; VN[6] += VN[25] * VN[5]; VN[5] *= fval; VN[6] += VN[26] * VN[5]; VN[5] *= fval; VN[6] += VN[27] * VN[5]; VN[5] *= fval; VN[6] += VN[28] * VN[5]; fval = VN[6] * VN[6] * VN[6] * VN[6]; spipe.vn = 1.0 / fval; spipe.no = 42; break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08x)\n", iL); exit(1); break; } break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08x)\n", iL); exit(1); } return 0; } int Upper_special(VectorUnitState *state, u_long iH, u_long iL) { /* [name] Upper_special [desc.] Micro Special OPCODE (Upper instruction) execute [args] iH: Upper instruction(32bits) iL: lower instruction(32bits) [return] 0: executed 1: stall ( hazard occured) */ float w; double dval, dval2; long ix, iy, iz, iw; switch ((iH >> 6) & 0x1f) { /* bit42-38 */ case 0: /* ADDAx, ADDAy, ADDAz, ADDAw */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "ADDA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] + VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] + VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] + VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] + VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 1: /* SUBAx, SUBAy, SUBAz, SUBAw */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "SUBA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] - VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] - VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] - VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] - VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 2: /* MADDAx, MADDAy, MADDAz, MADDAw */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MADDA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] + VF[get_fs(iH)][0] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] + VF[get_fs(iH)][1] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] + VF[get_fs(iH)][2] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] + VF[get_fs(iH)][3] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 3: /* MSUBAx, MSUBAy, MSUBAz, MSUBAw */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MSUBA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] - VF[get_fs(iH)][0] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] - VF[get_fs(iH)][1] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] - VF[get_fs(iH)][2] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] - VF[get_fs(iH)][3] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 4: /* ITOF0, ITOF4, ITOF12, ITOF15 */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_ft(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; switch (get_bc(iH)) { case 0: /* ITOF0 */ strcpy(pipe[0][0].code, "ITOF0"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = *(long *) &VF[get_fs(iH)][0] / 1.0; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = *(long *) &VF[get_fs(iH)][1] / 1.0; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = *(long *) &VF[get_fs(iH)][2] / 1.0; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = *(long *) &VF[get_fs(iH)][3] / 1.0; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 1: /* ITOF4 */ strcpy(pipe[0][0].code, "ITOF4"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = *(long *) &VF[get_fs(iH)][0] / 16.0; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = *(long *) &VF[get_fs(iH)][1] / 16.0; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = *(long *) &VF[get_fs(iH)][2] / 16.0; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = *(long *) &VF[get_fs(iH)][3] / 16.0; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 2: /* ITOF12 */ strcpy(pipe[0][0].code, "ITOF12"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = *(long *)&VF[get_fs(iH)][0] / 4096.0; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = *(long *)&VF[get_fs(iH)][1] / 4096.0; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = *(long *)&VF[get_fs(iH)][2] / 4096.0; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = *(long *)&VF[get_fs(iH)][3] / 4096.0; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 3: /* ITOF15 */ strcpy(pipe[0][0].code, "ITOF15"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = *(long *) &VF[get_fs(iH)][0] / 32768.0; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = *(long *) &VF[get_fs(iH)][1] / 32768.0; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = *(long *) &VF[get_fs(iH)][2] / 32768.0; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = *(long *) &VF[get_fs(iH)][3] / 32768.0; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; } break; case 5: /* FTOI0, FTOI4, FTOI12, FTOI15 */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_ft(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; switch (get_bc(iH)) { case 0: /* FTOI0 */ strcpy(pipe[0][0].code, "FTOI0"); if (get_dest(iH) & DEST_X) { ix = VF[get_fs(iH)][0]; *(long *) &pipe[0][0].vf[0] = ix; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { iy = VF[get_fs(iH)][1]; *(long *) &pipe[0][0].vf[1] = iy; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { iz = VF[get_fs(iH)][2]; *(long *) &pipe[0][0].vf[2] = iz; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { iw = VF[get_fs(iH)][3]; *(long *) &pipe[0][0].vf[3] = iw; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 1: /* FTOI4 */ strcpy(pipe[0][0].code, "FTOI4"); if (get_dest(iH) & DEST_X) { ix = VF[get_fs(iH)][0] * 16; *(long *) &pipe[0][0].vf[0] = ix; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { iy = VF[get_fs(iH)][1] * 16; *(long *) &pipe[0][0].vf[1] = iy; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { iz = VF[get_fs(iH)][2] * 16; *(long *) &pipe[0][0].vf[2] = iz; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { iw = VF[get_fs(iH)][3] * 16; *(long *) &pipe[0][0].vf[3] = iw; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 2: /* FTOI12 */ strcpy(pipe[0][0].code, "FTOI12"); if (get_dest(iH) & DEST_X) { ix = VF[get_fs(iH)][0] * 4096; *(long *) &pipe[0][0].vf[0] = ix; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { iy = VF[get_fs(iH)][1] * 4096; *(long *) &pipe[0][0].vf[1] = iy; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { iz = VF[get_fs(iH)][2] * 4096; *(long *) &pipe[0][0].vf[2] = iz; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { iw = VF[get_fs(iH)][3] * 4096; *(long *) &pipe[0][0].vf[3] = iw; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 3: /* FTOI15 */ strcpy(pipe[0][0].code, "FTOI15"); if (get_dest(iH) & DEST_X) { ix = VF[get_fs(iH)][0] * 32768; *(long *) &pipe[0][0].vf[0] = ix; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { iy = VF[get_fs(iH)][1] * 32768; *(long *) &pipe[0][0].vf[1] = iy; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { iz = VF[get_fs(iH)][2] * 32768; *(long *) &pipe[0][0].vf[2] = iz; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { iw = VF[get_fs(iH)][3] * 32768; *(long *) &pipe[0][0].vf[3] = iw; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; } break; case 6: /* MULAx, MULAy, MULAz, MULAw */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MULA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 7: /* MULAq, ABS, MULAi, CLIP */ switch (get_bc(iH)) { case 0: /* MULAq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MULAq"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] * Q; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] * Q; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] * Q; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] * Q; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 1: /* ABS */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_ft(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "ABS"); if (get_dest(iH) & DEST_X) { if (VF[get_fs(iH)][0] > 0) { pipe[0][0].vf[0] = VF[get_fs(iH)][0]; } else { pipe[0][0].vf[0] = 0 - VF[get_fs(iH)][0]; } statuscheck(VF[get_ft(iH)][0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { if (VF[get_fs(iH)][1] > 0) { pipe[0][0].vf[1] = VF[get_fs(iH)][1]; } else { pipe[0][0].vf[1] = 0 - VF[get_fs(iH)][1]; } statuscheck(VF[get_ft(iH)][1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { if (VF[get_fs(iH)][2] > 0) { pipe[0][0].vf[2] = VF[get_fs(iH)][2]; } else { pipe[0][0].vf[2] = 0 - VF[get_fs(iH)][2]; } statuscheck(VF[get_ft(iH)][2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { if (VF[get_fs(iH)][3] > 0) { pipe[0][0].vf[3] = VF[get_fs(iH)][3]; } else { pipe[0][0].vf[3] = 0 - VF[get_fs(iH)][3]; } statuscheck(VF[get_ft(iH)][3], &pipe[0][0].status, 3); } break; case 2: /* MULAi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MULAi"); apipe.flag = 1; apipe.mask = get_dest(iH); if (iH & 0x80000000) { if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] * (*(float *) &iL); statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] * (*(float *) &iL); statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] * (*(float *) &iL); statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] * (*(float *) &iL); statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } else { if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] * I; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] * I; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] * I; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] * I; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } break; case 3: /* CLIP */ if (hazardcheck(get_fs(iH), 0, 0xf, 2)) return 1; pipe[0][0].flag = 5; pipe[0][0].status = 0; strcpy(pipe[0][0].code, "CLIP"); if (VF[get_ft(iH)][3] < 0) w = 0 - VF[get_ft(iH)][3]; else w = VF[get_ft(iH)][3]; if (VF[get_fs(iH)][0] > w) pipe[0][0].status |= 0x1; if (VF[get_fs(iH)][0] < (0 - w)) pipe[0][0].status |= 0x2; if (VF[get_fs(iH)][1] > w) pipe[0][0].status |= 0x4; if (VF[get_fs(iH)][1] < (0 - w)) pipe[0][0].status |= 0x8; if (VF[get_fs(iH)][2] > w) pipe[0][0].status |= 0x10; if (VF[get_fs(iH)][2] < (0 - w)) pipe[0][0].status |= 0x20; break; } break; case 8: /* ADDAq, MADDAq, ADDAi, MADDAi */ switch (get_bc(iH)) { case 0: /* ADDAq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "ADDAq"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] + Q; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] + Q; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] + Q; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] + Q; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 1: /* MADDAq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MADDAq"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] + VF[get_fs(iH)][0] * Q; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] + VF[get_fs(iH)][1] * Q; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] + VF[get_fs(iH)][2] * Q; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] + VF[get_fs(iH)][3] * Q; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 2: /* ADDAi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "ADDAi"); apipe.flag = 1; apipe.mask = get_dest(iH); if (iH & 0x80000000) { if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] + (*(float *) &iL); statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] + (*(float *) &iL); statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] + (*(float *) &iL); statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] + (*(float *) &iL); statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } else { if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] + I; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] + I; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] + I; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] + I; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } break; case 3: /* MADDAi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MADDAi"); apipe.flag = 1; apipe.mask = get_dest(iH); if (iH & 0x80000000) { if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] + VF[get_fs(iH)][0] * (*(float *) &iL); statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] + VF[get_fs(iH)][1] * (*(float *) &iL); statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] + VF[get_fs(iH)][2] * (*(float *) &iL); statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] + VF[get_fs(iH)][3] * (*(float *) &iL); statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } else { if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] + VF[get_fs(iH)][0] * I; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] + VF[get_fs(iH)][1] * I; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] + VF[get_fs(iH)][2] * I; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] + VF[get_fs(iH)][3] * I; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } break; } break; case 9: /* SUBAq, MSUBAq, SUBAi, MSUBAi */ switch (get_bc(iH)) { case 0: /* SUBAq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "SUBAq"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] - Q; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] - Q; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] - Q; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] - Q; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 1: /* MSUBAq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MSUBAq"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] - VF[get_fs(iH)][0] * Q; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] - VF[get_fs(iH)][1] * Q; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] - VF[get_fs(iH)][2] * Q; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] - VF[get_fs(iH)][3] * Q; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 2: /* SUBAi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "SUBAi"); apipe.flag = 1; apipe.mask = get_dest(iH); if (iH & 0x80000000) { if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] - (*(float *) &iL); statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] - (*(float *) &iL); statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] - (*(float *) &iL); statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] - (*(float *) &iL); statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } else { if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] - I; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] - I; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] - I; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] - I; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } break; case 3: /* MSUBAi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MSUBAi"); apipe.flag = 1; apipe.mask = get_dest(iH); if (iH & 0x80000000) { if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] - VF[get_fs(iH)][0] * (*(float *) &iL); statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] - VF[get_fs(iH)][1] * (*(float *) &iL); statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] - VF[get_fs(iH)][2] * (*(float *) &iL); statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] - VF[get_fs(iH)][3] * (*(float *) &iL); statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } else { if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] - VF[get_fs(iH)][0] * I; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] - VF[get_fs(iH)][1] * I; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] - VF[get_fs(iH)][2] * I; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] - VF[get_fs(iH)][3] * I; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } } break; } break; case 10: /* ADDA, MADDA, MULA, --- */ switch (get_bc(iH)) { case 0: /* ADDA */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "ADDA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] + VF[get_ft(iH)][0]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] + VF[get_ft(iH)][1]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] + VF[get_ft(iH)][2]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] + VF[get_ft(iH)][3]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 1: /* MADDA */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MADDA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] + VF[get_fs(iH)][0] * VF[get_ft(iH)][0]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] + VF[get_fs(iH)][1] * VF[get_ft(iH)][1]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] + VF[get_fs(iH)][2] * VF[get_ft(iH)][2]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] + VF[get_fs(iH)][3] * VF[get_ft(iH)][3]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 2: /* MULA */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MULA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] * VF[get_ft(iH)][0]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] * VF[get_ft(iH)][1]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] * VF[get_ft(iH)][2]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] * VF[get_ft(iH)][3]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 3: fprintf(stderr, "Undefined opcode(UpperOp:%08x)\n", iH); break; } break; case 11: /* SUBA, MSUBA, OPMULA, NOP */ switch (get_bc(iH)) { case 0: /* SUBA */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "SUBA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = VF[get_fs(iH)][0] - VF[get_ft(iH)][0]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = VF[get_fs(iH)][1] - VF[get_ft(iH)][1]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = VF[get_fs(iH)][2] - VF[get_ft(iH)][2]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = VF[get_fs(iH)][3] - VF[get_ft(iH)][3]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 1: /* MSUBA */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].flag = 4; strcpy(pipe[0][0].code, "MSUBA"); apipe.flag = 1; apipe.mask = get_dest(iH); if (get_dest(iH) & DEST_X) { apipe.acc[0] = ACC[0] - VF[get_fs(iH)][0] * VF[get_ft(iH)][0]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { apipe.acc[1] = ACC[1] - VF[get_fs(iH)][1] * VF[get_ft(iH)][1]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { apipe.acc[2] = ACC[2] - VF[get_fs(iH)][2] * VF[get_ft(iH)][2]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { apipe.acc[3] = ACC[3] - VF[get_fs(iH)][3] * VF[get_ft(iH)][3]; statuscheck(apipe.acc[3], &pipe[0][0].status, 3); } break; case 2: /* OPMULA */ if (hazardcheck(get_fs(iH), get_ft(iH), 0xe, 3)) return 1; pipe[0][0].flag = 4; apipe.flag = 1; apipe.mask = get_dest(iH); strcpy(pipe[0][0].code, "OPMULA"); apipe.acc[0] = VF[get_fs(iH)][1] * VF[get_ft(iH)][2]; statuscheck(apipe.acc[0], &pipe[0][0].status, 0); apipe.acc[1] = VF[get_fs(iH)][2] * VF[get_ft(iH)][0]; statuscheck(apipe.acc[1], &pipe[0][0].status, 1); apipe.acc[2] = VF[get_fs(iH)][0] * VF[get_ft(iH)][1]; statuscheck(apipe.acc[2], &pipe[0][0].status, 2); break; case 3: /* NOP */ break; } break; default: fprintf(stderr, "Undefined opcode(%08x)\n", iH); exit(1); } return 0; } int exec_inst(VectorUnitState *state) { /* [name] exec_inst [desc.] execute instruction ( second stage of pipeline) [args] void [return] 0: finished 1: stall (hazard occured) 2: executed */ double dval; float fval; u_long iH, iL; long imm12, imm11, imm15, imm5, imm24; if (peflag == -1) return 0; if (peflag == 1) peflag = -1; if (instbuf[0] & 0x40000000) eflag = 1; iH = instbuf[0]; iL = instbuf[1]; pipe[0][0].status = 0; pipe[0][1].status = 0; qpipe[0].status = 0; rqpipe[0].status = 0; if (iH & 0x80000000) { Ipipe.flag = 1; Ipipe.val = *(float *) &iL; /* pipe[0][1].flag = 3; pipe[0][1].vf[0] = *(float *)&iL; */ } /* UpperOp execute */ switch ((iH >> 2) & 0xf) { /* bit37-34 */ case 0: /* ADDx,y,z,w */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "ADD"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] + VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] + VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] + VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] + VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 0); } break; case 1: /* SUBx,y,z,w */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "SUB"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] - VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] - VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] - VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] - VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 2: /* MADDx,y,z,w */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MADD"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = ACC[0] + VF[get_fs(iH)][0] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = ACC[1] + VF[get_fs(iH)][1] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = ACC[2] + VF[get_fs(iH)][2] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = ACC[3] + VF[get_fs(iH)][3] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 3: /* MSUBx,y,z,w */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MSUB"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = ACC[0] - VF[get_fs(iH)][0] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = ACC[1] - VF[get_fs(iH)][1] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = ACC[2] - VF[get_fs(iH)][2] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = ACC[3] - VF[get_fs(iH)][3] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 4: /* MAXx,y,z,w */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MAX"); if (get_dest(iH) & DEST_X) { if (VF[get_fs(iH)][0] > VF[get_ft(iH)][get_bc(iH)]) pipe[0][0].vf[0] = VF[get_fs(iH)][0]; else pipe[0][0].vf[0] = VF[get_ft(iH)][get_bc(iH)]; } if (get_dest(iH) & DEST_Y) { if (VF[get_fs(iH)][1] > VF[get_ft(iH)][get_bc(iH)]) pipe[0][0].vf[1] = VF[get_fs(iH)][1]; else pipe[0][0].vf[1] = VF[get_ft(iH)][get_bc(iH)]; } if (get_dest(iH) & DEST_Z) { if (VF[get_fs(iH)][2] > VF[get_ft(iH)][get_bc(iH)]) pipe[0][0].vf[2] = VF[get_fs(iH)][2]; else pipe[0][0].vf[2] = VF[get_ft(iH)][get_bc(iH)]; } if (get_dest(iH) & DEST_W) { if (VF[get_fs(iH)][3] > VF[get_ft(iH)][get_bc(iH)]) pipe[0][0].vf[3] = VF[get_fs(iH)][3]; else pipe[0][0].vf[3] = VF[get_ft(iH)][get_bc(iH)]; } break; case 5: /* MINIx,y,z,w */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MINI"); if (get_dest(iH) & DEST_X) { if (VF[get_fs(iH)][0] < VF[get_ft(iH)][get_bc(iH)]) pipe[0][0].vf[0] = VF[get_fs(iH)][0]; else pipe[0][0].vf[0] = VF[get_ft(iH)][get_bc(iH)]; } if (get_dest(iH) & DEST_Y) { if (VF[get_fs(iH)][1] < VF[get_ft(iH)][get_bc(iH)]) pipe[0][0].vf[1] = VF[get_fs(iH)][1]; else pipe[0][0].vf[1] = VF[get_ft(iH)][get_bc(iH)]; } if (get_dest(iH) & DEST_Z) { if (VF[get_fs(iH)][2] < VF[get_ft(iH)][get_bc(iH)]) pipe[0][0].vf[2] = VF[get_fs(iH)][2]; else pipe[0][0].vf[2] = VF[get_ft(iH)][get_bc(iH)]; } if (get_dest(iH) & DEST_W) { if (VF[get_fs(iH)][3] < VF[get_ft(iH)][get_bc(iH)]) pipe[0][0].vf[3] = VF[get_fs(iH)][3]; else pipe[0][0].vf[3] = VF[get_ft(iH)][get_bc(iH)]; } break; case 6: /* MULx,y,z,w */ if (hazardcheckBC(get_fs(iH), get_ft(iH), get_dest(iH), get_bc(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MUL"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] * VF[get_ft(iH)][get_bc(iH)]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 7: /* MULq, MAXi, MULi, MINIi */ switch (get_bc(iH)) { case 0: /* MULq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MULq"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] * Q; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] * Q; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] * Q; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] * Q; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 1: /* MAXi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MAXi"); fval = I; if (get_dest(iH) & DEST_X) { if (VF[get_fs(iH)][0] > fval) { pipe[0][0].vf[0] = VF[get_fs(iH)][0]; } else { pipe[0][0].vf[0] = fval; } } if (get_dest(iH) & DEST_Y) { if (VF[get_fs(iH)][1] > fval) { pipe[0][0].vf[1] = VF[get_fs(iH)][1]; } else { pipe[0][0].vf[1] = fval; } } if (get_dest(iH) & DEST_Z) { if (VF[get_fs(iH)][2] > fval) { pipe[0][0].vf[2] = VF[get_fs(iH)][2]; } else { pipe[0][0].vf[2] = fval; } } if (get_dest(iH) & DEST_W) { if (VF[get_fs(iH)][3] > fval) { pipe[0][0].vf[3] = VF[get_fs(iH)][3]; } else { pipe[0][0].vf[3] = fval; } } break; case 2: /* MULi */ /* if(iH & 0x80000000){ if(hazardcheckI()) return 1; } */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MULi"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] * I; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] * I; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] * I; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] * I; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 3: /* MINIi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MINIi"); fval = I; if (get_dest(iH) & DEST_X) { if (VF[get_fs(iH)][0] < fval) { pipe[0][0].vf[0] = VF[get_fs(iH)][0]; } else { pipe[0][0].vf[0] = fval; } } if (get_dest(iH) & DEST_Y) { if (VF[get_fs(iH)][1] < fval) { pipe[0][0].vf[1] = VF[get_fs(iH)][1]; } else { pipe[0][0].vf[1] = fval; } } if (get_dest(iH) & DEST_Z) { if (VF[get_fs(iH)][2] < fval) { pipe[0][0].vf[2] = VF[get_fs(iH)][2]; } else { pipe[0][0].vf[2] = fval; } } if (get_dest(iH) & DEST_W) { if (VF[get_fs(iH)][3] < fval) { pipe[0][0].vf[3] = VF[get_fs(iH)][3]; } else { pipe[0][0].vf[3] = fval; } } break; } break; case 8: /* ADDq, MADDq, ADDi, MADDi */ switch (get_bc(iH)) { case 0: /* ADDq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "ADDq"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] + Q; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] + Q; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] + Q; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] + Q; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 1: /* MADDq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MADDq"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = ACC[0] + VF[get_fs(iH)][0] * Q; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = ACC[1] + VF[get_fs(iH)][1] * Q; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = ACC[2] + VF[get_fs(iH)][2] * Q; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = ACC[3] + VF[get_fs(iH)][3] * Q; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 2: /* ADDi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "ADDi"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] + I; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] + I; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] + I; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] + I; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 3: /* MADDi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MADDi"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = ACC[0] + VF[get_fs(iH)][0] * I; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = ACC[1] + VF[get_fs(iH)][1] * I; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = ACC[2] + VF[get_fs(iH)][2] * I; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = ACC[3] + VF[get_fs(iH)][3] * I; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; } break; case 9: /* SUBq, MSUBq, SUBi, MSUBi */ switch (get_bc(iH)) { case 0: /* SUBq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "SUBq"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] - Q; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] - Q; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] - Q; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] - Q; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 1: /* MSUBq */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MSUBq"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = ACC[0] - VF[get_fs(iH)][0] * Q; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = ACC[1] - VF[get_fs(iH)][1] * Q; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = ACC[2] - VF[get_fs(iH)][2] * Q; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = ACC[3] - VF[get_fs(iH)][3] * Q; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 2: /* SUBi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "SUBi"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] - I; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] - I; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] - I; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] - I; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 3: /* MSUBi */ if (hazardcheck(get_fs(iH), 0, get_dest(iH), 2)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MSUBi"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = ACC[0] - VF[get_fs(iH)][0] * I; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = ACC[1] - VF[get_fs(iH)][1] * I; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = ACC[2] - VF[get_fs(iH)][2] * I; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = ACC[3] - VF[get_fs(iH)][3] * I; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; } break; case 10: /* ADD, MADD, MUL, MAX */ switch (get_bc(iH)) { case 0: /* ADD */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "ADD"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] + VF[get_ft(iH)][0]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] + VF[get_ft(iH)][1]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] + VF[get_ft(iH)][2]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] + VF[get_ft(iH)][3]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 1: /* MADD */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MADD"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = ACC[0] + VF[get_fs(iH)][0] * VF[get_ft(iH)][0]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = ACC[1] + VF[get_fs(iH)][1] * VF[get_ft(iH)][1]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = ACC[2] + VF[get_fs(iH)][2] * VF[get_ft(iH)][2]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = ACC[3] + VF[get_fs(iH)][3] * VF[get_ft(iH)][3]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 2: /* MUL */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MUL"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] * VF[get_ft(iH)][0]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] * VF[get_ft(iH)][1]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] * VF[get_ft(iH)][2]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] * VF[get_ft(iH)][3]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 3: /* MAX */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MAX"); if (get_dest(iH) & DEST_X) { if (VF[get_fs(iH)][0] > VF[get_ft(iH)][0]) { pipe[0][0].vf[0] = VF[get_fs(iH)][0]; } else { pipe[0][0].vf[0] = VF[get_ft(iH)][0]; } } if (get_dest(iH) & DEST_Y) { if (VF[get_fs(iH)][1] > VF[get_ft(iH)][1]) { pipe[0][0].vf[1] = VF[get_fs(iH)][1]; } else { pipe[0][0].vf[1] = VF[get_ft(iH)][1]; } } if (get_dest(iH) & DEST_Z) { if (VF[get_fs(iH)][2] > VF[get_ft(iH)][2]) { pipe[0][0].vf[2] = VF[get_fs(iH)][2]; } else { pipe[0][0].vf[2] = VF[get_ft(iH)][2]; } } if (get_dest(iH) & DEST_W) { if (VF[get_fs(iH)][3] > VF[get_ft(iH)][3]) { pipe[0][0].vf[3] = VF[get_fs(iH)][3]; } else { pipe[0][0].vf[3] = VF[get_ft(iH)][3]; } } break; } break; case 11: /* SUB, MSUB, OPMSUB, MINI */ switch (get_bc(iH)) { case 0: /* SUB */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "SUB"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = VF[get_fs(iH)][0] - VF[get_ft(iH)][0]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = VF[get_fs(iH)][1] - VF[get_ft(iH)][1]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = VF[get_fs(iH)][2] - VF[get_ft(iH)][2]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = VF[get_fs(iH)][3] - VF[get_ft(iH)][3]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 1: /* MSUB */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "MSUB"); if (get_dest(iH) & DEST_X) { pipe[0][0].vf[0] = ACC[0] - VF[get_fs(iH)][0] * VF[get_ft(iH)][0]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); } if (get_dest(iH) & DEST_Y) { pipe[0][0].vf[1] = ACC[1] - VF[get_fs(iH)][1] * VF[get_ft(iH)][1]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); } if (get_dest(iH) & DEST_Z) { pipe[0][0].vf[2] = ACC[2] - VF[get_fs(iH)][2] * VF[get_ft(iH)][2]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); } if (get_dest(iH) & DEST_W) { pipe[0][0].vf[3] = ACC[3] - VF[get_fs(iH)][3] * VF[get_ft(iH)][3]; statuscheck(pipe[0][0].vf[3], &pipe[0][0].status, 3); } break; case 2: /* OPMSUB */ if (hazardcheck(get_fs(iH), get_ft(iH), 0xe, 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = 0xe; pipe[0][0].flag = 1; strcpy(pipe[0][0].code, "OPMSUB"); pipe[0][0].vf[0] = ACC[0] - VF[get_fs(iH)][1] * VF[get_ft(iH)][2]; statuscheck(pipe[0][0].vf[0], &pipe[0][0].status, 0); pipe[0][0].vf[1] = ACC[1] - VF[get_fs(iH)][2] * VF[get_ft(iH)][0]; statuscheck(pipe[0][0].vf[1], &pipe[0][0].status, 1); pipe[0][0].vf[2] = ACC[2] - VF[get_fs(iH)][0] * VF[get_ft(iH)][1]; statuscheck(pipe[0][0].vf[2], &pipe[0][0].status, 2); break; case 3: /* MINI */ if (hazardcheck(get_fs(iH), get_ft(iH), get_dest(iH), 3)) return 1; pipe[0][0].no = get_fd(iH); pipe[0][0].mask = get_dest(iH); pipe[0][0].flag = 1; if (get_dest(iH) & DEST_X) { if (VF[get_fs(iH)][0] < VF[get_ft(iH)][0]) { pipe[0][0].vf[0] = VF[get_fs(iH)][0]; } else { pipe[0][0].vf[0] = VF[get_ft(iH)][0]; } } if (get_dest(iH) & DEST_Y) { if (VF[get_fs(iH)][1] < VF[get_ft(iH)][1]) { pipe[0][0].vf[1] = VF[get_fs(iH)][1]; } else { pipe[0][0].vf[1] = VF[get_ft(iH)][1]; } } if (get_dest(iH) & DEST_Z) { if (VF[get_fs(iH)][2] < VF[get_ft(iH)][2]) { pipe[0][0].vf[2] = VF[get_fs(iH)][2]; } else { pipe[0][0].vf[2] = VF[get_ft(iH)][2]; } } if (get_dest(iH) & DEST_W) { if (VF[get_fs(iH)][3] < VF[get_ft(iH)][3]) { pipe[0][0].vf[3] = VF[get_fs(iH)][3]; } else { pipe[0][0].vf[3] = VF[get_ft(iH)][3]; } } break; } break; case 15: if (Upper_special(state, iH, iL)) return 1; break; default: fprintf(stderr, "Undefined opcode(%08x)\n", iH); exit(1); } if (iH & 0x80000000) return 1; if (iH & 0x04000000) { /* DEBUG PRINT */ if (dpr_mode) printf("\"%08lx\"\n", iL); return 1; } /* LowerOp execute */ switch ((iL >> 27) & 0x1f) { case 0: /* LQ, SQ, ---, --- */ if (iL & 0x00000400) imm11 = (iL & 0x07ff) | 0xfffff800; else imm11 = iL & 0x07ff; switch (get_ic(iL)) { case 0: /* LQ */ if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].no = get_ft(iL); pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "LQ"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = *(float *) &state->MEM[imm11 + VI[get_fs(iL)]][0]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = *(float *) &state->MEM[imm11 + VI[get_fs(iL)]][1]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = *(float *) &state->MEM[imm11 + VI[get_fs(iL)]][2]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = *(float *) &state->MEM[imm11 + VI[get_fs(iL)]][3]; break; case 1: /* SQ */ if (hazardcheck(0, get_ft(iL), get_dest(iL), 1) || hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 2; pipe[0][1].addr = imm11 + VI[get_ft(iL)]; strcpy(pipe[0][1].code, "SQ"); if (get_dest(iL) & DEST_X) pipe[0][1].vf[0] = VF[get_fs(iL)][0]; if (get_dest(iL) & DEST_Y) pipe[0][1].vf[1] = VF[get_fs(iL)][1]; if (get_dest(iL) & DEST_Z) pipe[0][1].vf[2] = VF[get_fs(iL)][2]; if (get_dest(iL) & DEST_W) pipe[0][1].vf[3] = VF[get_fs(iL)][3]; break; default: fprintf(stderr, "Undefined opcode(%08lx)\n", iL); exit(1); } break; case 1: /* ILW, ISW, ---, --- */ if (iL & 0x00000400) imm11 = (iL & 0x07ff) | 0xfffff800; else imm11 = iL & 0x07ff; switch (get_ic(iL)) { case 0: /* ILW */ if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].no = get_ft(iL) + 32; pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 1; strcpy(pipe[0][1].code, "ILW"); if (get_dest(iL) & DEST_X) *(long *) &pipe[0][1].vf[0] = state->MEM[imm11 + VI[get_fs(iL)]][0]; if (get_dest(iL) & DEST_Y) *(long *) &pipe[0][1].vf[1] = state->MEM[imm11 + VI[get_fs(iL)]][1]; if (get_dest(iL) & DEST_Z) *(long *) &pipe[0][1].vf[2] = state->MEM[imm11 + VI[get_fs(iL)]][2]; if (get_dest(iL) & DEST_W) *(long *) &pipe[0][1].vf[3] = state->MEM[imm11 + VI[get_fs(iL)]][3]; break; case 1: /* ISW */ if (hazardcheckVI(get_fs(iL), get_ft(iL), 3)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } pipe[0][1].mask = get_dest(iL); pipe[0][1].flag = 2; pipe[0][1].addr = imm11 + VI[get_fs(iL)]; strcpy(pipe[0][1].code, "ISW"); if (get_dest(iL) & DEST_X) *(long *) &pipe[0][1].vf[0] = (VI[get_ft(iL)]) & 0xffff; if (get_dest(iL) & DEST_Y) *(long *) &pipe[0][1].vf[1] = (VI[get_ft(iL)]) & 0xffff; if (get_dest(iL) & DEST_Z) *(long *) &pipe[0][1].vf[2] = (VI[get_ft(iL)]) & 0xffff; if (get_dest(iL) & DEST_W) *(long *) &pipe[0][1].vf[3] = (VI[get_ft(iL)]) & 0xffff; break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08lx)\n", iL); exit(1); } break; case 2: /* IADDIU, ISUBIU, ---, --- */ if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } imm15 = ((iL >> 10) & 0x7800) | (iL & 0x7ff); switch (get_ic(iL)) { case 0: /* IADDIU */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = VI[get_fs(iL)] + imm15; strcpy(ipipe[0].code, "IADDIU"); break; case 1: /* ISUBIU */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = VI[get_fs(iL)] - imm15; strcpy(ipipe[0].code, "ISUBIU"); break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08lx)\n", iL); exit(1); } break; case 3: fprintf(stderr, "Undefined opcode(LowerOp:%08lx)\n", iL); exit(1); break; case 4: /* FCEQ, FCSET, FCAND, FCOR */ imm24 = iL & 0x00ffffff; switch (get_ic(iL)) { case 0: /* FCEQ */ ipipe[0].no = 1; ipipe[0].flag = 1; if(clipflag == imm24) ipipe[0].vi = 1; else ipipe[0].vi = 0; strcpy(ipipe[0].code, "FCEQ"); break; case 1: /* FCSET */ pipe[0][1].flag = 5; pipe[0][1].status = imm24; strcpy(pipe[0][1].code, "FCSET"); break; case 2: /* FCAND */ ipipe[0].no = 1; ipipe[0].flag = 1; if(clipflag & imm24) ipipe[0].vi = 1; else ipipe[0].vi = 0; strcpy(ipipe[0].code, "FCAND"); break; case 3: /* FCOR */ ipipe[0].no = 1; ipipe[0].flag = 1; if((clipflag | imm24) == 0x00ffffff) ipipe[0].vi = 1; else ipipe[0].vi = 0; strcpy(ipipe[0].code, "FCOR"); break; } break; case 5: /* FSEQ, FSSET, FSAND, FSOR */ imm12 = ((iL >> 10) & 0x0800) | (iL & 0x7ff); switch (get_ic(iL)) { case 0: /* FSEQ */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; if(statusflag == imm12) ipipe[0].vi = 1; else ipipe[0].vi = 0; strcpy(ipipe[0].code, "FSEQ"); break; case 1: /* FSSET */ pipe[0][1].flag = 4; pipe[0][1].status = imm12 & 0xfc0; strcpy(pipe[0][1].code, "FSSET"); break; case 2: /* FSAND */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = statusflag & imm12; strcpy(ipipe[0].code, "FSAND"); break; case 3: /* FSOR */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = statusflag | imm12; strcpy(ipipe[0].code, "FSOR"); break; } break; case 6: /* FMEQ, NULL, FMAND, FMOR */ switch (get_ic(iL)) { case 0: /* FMEQ */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; if ((short) MACflag == VI[get_fs(iL)]) ipipe[0].vi = 1; else ipipe[0].vi = 0; strcpy(ipipe[0].code, "FMEQ"); break; case 2: /* FMAND */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = (MACflag & 0xffff) & VI[get_fs(iL)]; strcpy(ipipe[0].code, "FMAND"); break; case 3: /* FMOR */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = (MACflag & 0xffff) | VI[get_fs(iL)]; strcpy(ipipe[0].code, "FMOR"); break; } break; case 7: /* FCGET, ---, ---, --- */ switch (get_ic(iL)) { case 0: /* FCGET */ ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = clipflag & 0x0fff; strcpy(ipipe[0].code, "FCGET"); break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08lx)\n", iL); exit(1); } break; case 8: /* B, BAL, ---, --- */ if (iL & 0x00000400) imm11 = (iL & 0x07ff) | 0xfffff800; else imm11 = iL & 0x07ff; switch (get_ic(iL)) { case 0: /* B */ jaddr = pc + imm11; jflag = 1; break; case 1: /* BAL */ jaddr = pc + imm11; jflag = 1; ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = pc + 1; strcpy(ipipe[0].code, "BAL"); break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08lx)\n", iL); exit(1); } break; case 9: /* JR, JALR, ---, --- */ if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } switch (get_ic(iL)) { case 0: /* JR */ jaddr = VI[get_fs(iL)]; jflag = 1; break; case 1: /* JALR */ jaddr = VI[get_fs(iL)]; jflag = 1; ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = pc + 1; strcpy(ipipe[0].code, "JAL"); break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08lx)\n", iL); exit(1); } break; case 10: /* IBEQ, IBNE, NULL, NULL */ if (iL & 0x00000400) imm11 = (iL & 0x07ff) | 0xfffff800; else imm11 = iL & 0x07ff; if (hazardcheckVI(get_fs(iL), get_ft(iL), 3)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } switch (get_ic(iL)) { case 0: /* IBEQ */ if (VI[get_ft(iL)] == VI[get_fs(iL)]) { jaddr = pc + imm11; jflag = 1; } break; case 1: /* IBNE */ if (VI[get_ft(iL)] != VI[get_fs(iL)]) { jaddr = pc + imm11; jflag = 1; } break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08lx)\n", iL); exit(1); } break; case 11: /* IBLTZ, IBGTZ, IBLEZ, IBGEZ */ if (iL & 0x00000400) imm11 = (iL & 0x07ff) | 0xfffff800; else imm11 = iL & 0x07ff; if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } switch (get_ic(iL)) { case 0: /* IBLTZ */ if (VI[get_fs(iL)] < 0) { jaddr = pc + imm11; jflag = 1; } break; case 1: /* IBGTZ */ if (VI[get_fs(iL)] > 0) { jaddr = pc + imm11; jflag = 1; } break; case 2: /* IBLEZ */ if (VI[get_fs(iL)] <= 0) { jaddr = pc + imm11; jflag = 1; } break; case 3: /* IBGEZ */ if (VI[get_fs(iL)] >= 0) { jaddr = pc + imm11; jflag = 1; } break; } break; case 16: switch ((iL >> 2) & 0xf) { case 12: /* IADD, ISUB, IADDI, --- */ switch (get_bc(iL)) { case 0: /* IADD */ if (hazardcheckVI(get_fs(iL), get_ft(iL), 3)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } ipipe[0].no = get_fd(iL); ipipe[0].flag = 1; ipipe[0].vi = VI[get_fs(iL)] + VI[get_ft(iL)]; strcpy(ipipe[0].code, "IADD"); break; case 1: /* ISUB */ if (hazardcheckVI(get_fs(iL), get_ft(iL), 3)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } ipipe[0].no = get_fd(iL); ipipe[0].flag = 1; ipipe[0].vi = VI[get_fs(iL)] - VI[get_ft(iL)]; strcpy(ipipe[0].code, "ISUB"); break; case 2: /* IADDI */ if (hazardcheckVI(get_fs(iL), 0, 2)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } if (iL & 0x00000400) imm5 = ((iL >> 6) & 0x1f) | 0xffffffe0; else imm5 = (iL >> 6) & 0x1f; ipipe[0].no = get_ft(iL); ipipe[0].flag = 1; ipipe[0].vi = VI[get_fs(iL)] + imm5; strcpy(ipipe[0].code, "IADDI"); break; default: fprintf(stderr, "Undefined opcode(LowerOp:%08lx)\n", iL); exit(1); } break; case 13: /* IAND, IOR */ switch (get_bc(iL)) { case 0: /* IAND */ if (hazardcheckVI(get_fs(iL), get_ft(iL), 3)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } ipipe[0].no = get_fd(iL); ipipe[0].flag = 1; ipipe[0].vi = VI[get_fs(iL)] & VI[get_ft(iL)]; strcpy(ipipe[0].code, "IAND"); break; case 1: /* IOR */ if (hazardcheckVI(get_fs(iL), get_ft(iL), 3)) { pipe[0][0].flag = 0; apipe.flag = 0; return 1; } ipipe[0].no = get_fd(iL); ipipe[0].flag = 1; ipipe[0].vi = VI[get_fs(iL)] | VI[get_ft(iL)]; strcpy(ipipe[0].code, "IOR"); break; } break; case 15: if (Lower_special(state, iL)) return 1; break; default: fprintf(stderr, "Undefined opcode(%08lx)\n", iL); exit(1); } break; default: fprintf(stderr, "Undefined opcode(%08lx)\n", iL); exit(1); } return 2; } int fetch_inst(VectorUnitState *state) { /* [name] fetch_inst [desc.] instruction fetchs on Micro memory [args] void [return] 0: finished 1: fetched */ if (eflag != -1) { if (sflag != 1) { opc = pc; instbuf[0] = state->uMEM[pc][0]; instbuf[1] = state->uMEM[pc][1]; /* ihc */ printf("%04d: ", pc); opcode_analyze(instbuf); putchar('\n'); /* -=ihc=- */ if (jflag == 1) { pc = jaddr; jflag = 0; } else if (eflag == 1) { eflag = -1; peflag = 1; } else { pc++; } } return 1; } return 0; } /* move pipeline stage */ int move_pipe(VectorUnitState *state) { /* [name] move_pipe [desc.] move value to next pipeline stage. [args] void [return] 0: no value exist in all pipeline stage 1: some values exist in pipeline stage */ int i, j, move = 0; if (apipe.flag != 0) { if (apipe.mask & DEST_X) { ACC[0] = apipe.acc[0]; } if (apipe.mask & DEST_Y) { ACC[1] = apipe.acc[1]; } if (apipe.mask & DEST_Z) { ACC[2] = apipe.acc[2]; } if (apipe.mask & DEST_W) { ACC[3] = apipe.acc[3]; } apipe.flag = 0; } if (ipipe[0].flag != 0) { ipipe[0].flag = 0; VI[ipipe[0].no] = ipipe[0].vi; } if (ipipe[0].flag != 0) { ipipe[1].no = ipipe[0].no; ipipe[1].flag = ipipe[0].flag; ipipe[0].flag = 0; ipipe[1].vi = ipipe[0].vi; strcpy(ipipe[1].code, ipipe[0].code); move = 1; } if (pipe[3][0].flag != 0) { switch (pipe[3][0].flag) { case 1:/* move to VF-reg */ if (pipe[3][0].mask & DEST_X) { VF[pipe[3][0].no][0] = pipe[3][0].vf[0]; } if (pipe[3][0].mask & DEST_Y) { VF[pipe[3][0].no][1] = pipe[3][0].vf[1]; } if (pipe[3][0].mask & DEST_Z) { VF[pipe[3][0].no][2] = pipe[3][0].vf[2]; } if (pipe[3][0].mask & DEST_W) { VF[pipe[3][0].no][3] = pipe[3][0].vf[3]; } statusflag = (statusflag & 0x00000ff0) | ((pipe[3][0].status & 0x0f) << 6) | (pipe[3][0].status & 0x0f); MACflag = (pipe[3][0].status >> 16) & 0xffff; break; case 2:/* store from VF-reg */ if (pipe[3][0].mask & DEST_X) { state->MEM[pipe[3][0].addr][0] = pipe[3][0].vf[0]; } if (pipe[3][0].mask & DEST_Y) { state->MEM[pipe[3][0].addr][1] = pipe[3][0].vf[1]; } if (pipe[3][0].mask & DEST_Z) { state->MEM[pipe[3][0].addr][2] = pipe[3][0].vf[2]; } if (pipe[3][0].mask & DEST_W) { state->MEM[pipe[3][0].addr][3] = pipe[3][0].vf[3]; } break; case 3:/* move to I-reg */ I = pipe[3][0].vf[0]; break; case 4:/* status only */ statusflag = (statusflag & 0x00000ff0) | ((pipe[3][0].status & 0x0f) << 6) | (pipe[3][0].status & 0x0f); MACflag = (pipe[3][0].status >> 16) & 0xffff; case 5: clipflag = (clipflag << 6) & 0x00ffffc0 | (pipe[3][0].status & 0x3f); break; } pipe[3][0].flag = 0; } if (qpipe[6].flag != 0) { qpipe[6].flag = 0; Q = qpipe[6].vf[0]; statusflag = (statusflag & 0xfcf) | (qpipe[6].status << 6) | qpipe[6].status; } for (i = 5; i >= 0; i--) { if (qpipe[i].flag != 0) { qpipe[i + 1].vf[0] = qpipe[i].vf[0]; qpipe[i + 1].flag = qpipe[i].flag; qpipe[i + 1].status = qpipe[i].status; qpipe[i].flag = 0; strcpy(qpipe[i + 1].code, qpipe[i].code); move = 1; } } if (rqpipe[12].flag != 0) { rqpipe[12].flag = 0; Q = rqpipe[12].vf[0]; statusflag = (statusflag & 0xfcf) | (rqpipe[12].status << 6) | rqpipe[12].status; } for (i = 11; i >= 0; i--) { if (rqpipe[i].flag != 0) { rqpipe[i + 1].vf[0] = rqpipe[i].vf[0]; rqpipe[i + 1].flag = rqpipe[i].flag; rqpipe[i + 1].status = rqpipe[i].status; rqpipe[i].flag = 0; move = 1; } } if (pipe[3][1].flag != 0) { switch (pipe[3][1].flag) { case 1: if (pipe[3][1].no > 31) { if (pipe[3][1].mask & DEST_X) { VI[(pipe[3][1].no) & 0x1f] = *(long *) &pipe[3][1].vf[0] & 0xffff; } if (pipe[3][1].mask & DEST_Y) { VI[(pipe[3][1].no) & 0x1f] = *(long *) &pipe[3][1].vf[1] & 0xffff; } if (pipe[3][1].mask & DEST_Z) { VI[(pipe[3][1].no) & 0x1f] = *(long *) &pipe[3][1].vf[2] & 0xffff; } if (pipe[3][1].mask & DEST_W) { VI[(pipe[3][1].no) & 0x1f] = *(long *) &pipe[3][1].vf[3] & 0xffff; } } else { if (pipe[3][1].mask & DEST_X) { VF[pipe[3][1].no][0] = pipe[3][1].vf[0]; } if (pipe[3][1].mask & DEST_Y) { VF[pipe[3][1].no][1] = pipe[3][1].vf[1]; } if (pipe[3][1].mask & DEST_Z) { VF[pipe[3][1].no][2] = pipe[3][1].vf[2]; } if (pipe[3][1].mask & DEST_W) { VF[pipe[3][1].no][3] = pipe[3][1].vf[3]; } } break; case 2: if (strcmp(pipe[3][1].code, "ISW") == 0) { if (pipe[3][1].mask & DEST_X) { state->MEM[pipe[3][1].addr][0] = (*(long *) &pipe[3][1].vf[0]) & 0xffff; } if (pipe[3][1].mask & DEST_Y) { state->MEM[pipe[3][1].addr][1] = (*(long *) &pipe[3][1].vf[1]) & 0xffff; } if (pipe[3][1].mask & DEST_Z) { state->MEM[pipe[3][1].addr][2] = (*(long *) &pipe[3][1].vf[2]) & 0xffff; } if (pipe[3][1].mask & DEST_W) { state->MEM[pipe[3][1].addr][3] = (*(long *) &pipe[3][1].vf[3]) & 0xffff; } } else { if (pipe[3][1].mask & DEST_X) { state->MEM[pipe[3][1].addr][0] = *(long *) &pipe[3][1].vf[0]; } if (pipe[3][1].mask & DEST_Y) { state->MEM[pipe[3][1].addr][1] = *(long *) &pipe[3][1].vf[1]; } if (pipe[3][1].mask & DEST_Z) { state->MEM[pipe[3][1].addr][2] = *(long *) &pipe[3][1].vf[2]; } if (pipe[3][1].mask & DEST_W) { state->MEM[pipe[3][1].addr][3] = *(long *) &pipe[3][1].vf[3]; } } break; case 3:/* move to I-reg */ I = pipe[3][1].vf[0]; break; case 4: statusflag = pipe[3][1].status; break; case 5: clipflag = pipe[3][1].status; break; case 6: if (pipe[3][1].mask & DEST_X) { VN[0] = pipe[3][1].vf[0]; } if (pipe[3][1].mask & DEST_Y) { VN[1] = pipe[3][1].vf[1]; } if (pipe[3][1].mask & DEST_Z) { VN[2] = pipe[3][1].vf[2]; } if (pipe[3][1].mask & DEST_W) { VN[3] = pipe[3][1].vf[3]; } break; case 7: if (pipe[3][1].mask & DEST_X) { VF[pipe[3][1].no][0] = pipe[3][1].vf[0]; } if (pipe[3][1].mask & DEST_Y) { VF[pipe[3][1].no][1] = pipe[3][1].vf[1]; } if (pipe[3][1].mask & DEST_Z) { VF[pipe[3][1].no][2] = pipe[3][1].vf[2]; } if (pipe[3][1].mask & DEST_W) { VF[pipe[3][1].no][3] = pipe[3][1].vf[3]; } break; } pipe[3][1].flag = 0; } for (i = 2; i >= 0; i--) { if (pipe[i][0].flag != 0) { move = 1; pipe[i + 1][0].flag = pipe[i][0].flag; pipe[i][0].flag = 0; for (j = 0; j < 4; j++) { pipe[i + 1][0].vf[j] = pipe[i][0].vf[j]; } pipe[i + 1][0].no = pipe[i][0].no; pipe[i + 1][0].mask = pipe[i][0].mask; pipe[i + 1][0].addr = pipe[i][0].addr; pipe[i + 1][0].status = pipe[i][0].status; pipe[i][0].status = 0; strcpy(pipe[i + 1][0].code, pipe[i][0].code); } if (pipe[i][1].flag != 0) { move = 1; pipe[i + 1][1].flag = pipe[i][1].flag; pipe[i][1].flag = 0; for (j = 0; j < 4; j++) { pipe[i + 1][1].vf[j] = pipe[i][1].vf[j]; } pipe[i + 1][1].no = pipe[i][1].no; pipe[i + 1][1].mask = pipe[i][1].mask; pipe[i + 1][1].addr = pipe[i][1].addr; pipe[i + 1][1].status = pipe[i][1].status; pipe[i][1].status = 0; strcpy(pipe[i + 1][1].code, pipe[i][1].code); } } if (spipe.no != 0) { if (spipe.no == 1) { spipe.no = 0; if (spipe.flag == 1) { VN[0] = spipe.vn; } else { VN[4] = spipe.vn; } spipe.flag = 0; } else { spipe.no--; } } if (Ipipe.flag) { I = Ipipe.val; Ipipe.flag = 0; } return move; } void printpipe(void) { /* [name] printpipe [desc.] print out pipeline status to stdout. (for debug mode) [args] void [return] void */ int i; for (i = 0; i < 4; i++) { switch (pipe[i][0].flag) { case 0:/* not charged */ printf("Up:%d(nocharge)\n", i); break; case 1:/* move to reg */ printf("Up:%d(%s) -> VF%02d\n", i, pipe[i][0].code, pipe[i][0].no); if (pipe[i][0].mask & DEST_W) printf("<%f>", pipe[i][0].vf[3]); else printf("<--->"); if (pipe[i][0].mask & DEST_Z) printf("<%f>", pipe[i][0].vf[2]); else printf("<--->"); if (pipe[i][0].mask & DEST_Y) printf("<%f>", pipe[i][0].vf[1]); else printf("<--->"); if (pipe[i][0].mask & DEST_X) printf("<%f>\n", pipe[i][0].vf[0]); else printf("<--->\n"); break; case 2:/* store from reg */ printf("Up:%d(%s) -> 0x%x\n", i, pipe[i][0].code, pipe[i][0].addr); break; case 4:/* only status */ printf("Up:%d(%s) -> status <0x%08x>\n", i, pipe[i][0].code, pipe[i][0].status); break; case 5:/* only clip */ printf("Up:%d(%s) -> clip <0x%04x>\n", i, pipe[i][0].code, pipe[i][0].status); break; } } for (i = 0; i < 4; i++) { switch (pipe[i][1].flag) { case 1:/* move to reg */ if (pipe[i][1].no > 31) { printf("Lo:%d(%s) -> VI%02d", i, pipe[i][1].code, pipe[i][1].no - 32); if (pipe[i][1].mask & DEST_X) printf(" <%f>\n", pipe[i][1].vf[0]); if (pipe[i][1].mask & DEST_Y) printf(" <%f>\n", pipe[i][1].vf[1]); if (pipe[i][1].mask & DEST_Z) printf(" <%f>\n", pipe[i][1].vf[2]); if (pipe[i][1].mask & DEST_W) printf(" <%f>\n", pipe[i][1].vf[3]); } else { printf("Lo:%d(%s) -> VF%02d\n", i, pipe[i][1].code, pipe[i][1].no); if (pipe[i][1].mask & DEST_W) printf("<%f>", pipe[i][1].vf[3]); else printf("<--->"); if (pipe[i][1].mask & DEST_Z) printf("<%f>", pipe[i][1].vf[2]); else printf("<--->"); if (pipe[i][1].mask & DEST_Y) printf("<%f>", pipe[i][1].vf[1]); else printf("<--->"); if (pipe[i][1].mask & DEST_X) printf("<%f>\n", pipe[i][1].vf[0]); else printf("<--->\n"); } break; case 2:/* store from reg */ printf("Lo:%d(%s) -> 0x%x\n", i, pipe[i][1].code, pipe[i][1].addr); if (pipe[i][1].mask & DEST_W) printf("<%f>", pipe[i][1].vf[3]); else printf("<--->"); if (pipe[i][1].mask & DEST_Z) printf("<%f>", pipe[i][1].vf[2]); else printf("<--->"); if (pipe[i][1].mask & DEST_Y) printf("<%f>", pipe[i][1].vf[1]); else printf("<--->"); if (pipe[i][1].mask & DEST_X) printf("<%f>\n", pipe[i][1].vf[0]); else printf("<--->\n"); break; case 3:/* move to I-reg */ printf("Lo:%d(LOI) -> I <%f>\n", i, pipe[i][1].vf[0]); case 4:/* only status */ printf("Lo:%d(%s) -> status <0x%08x>\n", i, pipe[i][1].code, pipe[i][1].status); break; case 5:/* only clip */ printf("Lo:%d(%s) -> clip <0x%04x>\n", i, pipe[i][1].code, pipe[i][1].status); break; case 6:/* move to EFU */ printf("EFU:%d(MFP)\n", i); if (pipe[i][1].mask & DEST_W) printf("<%f>", pipe[i][1].vf[3]); else printf("<--->"); if (pipe[i][1].mask & DEST_Z) printf("<%f>", pipe[i][1].vf[2]); else printf("<--->"); if (pipe[i][1].mask & DEST_Y) printf("<%f>", pipe[i][1].vf[1]); else printf("<--->"); if (pipe[i][1].mask & DEST_X) printf("<%f>\n", pipe[i][1].vf[0]); else printf("<--->\n"); break; case 7:/* move from EFU */ printf("EFU:%d(MFP->VF%02d)", i, pipe[i][1].no); if (pipe[i][1].mask & DEST_W) printf("<%f>", pipe[i][1].vf[3]); if (pipe[i][1].mask & DEST_Z) printf("<%f>", pipe[i][1].vf[2]); if (pipe[i][1].mask & DEST_Y) printf("<%f>", pipe[i][1].vf[1]); if (pipe[i][1].mask & DEST_X) printf("<%f>", pipe[i][1].vf[0]); printf("\n"); break; } } for (i = 0; i < 2; i++) { if (ipipe[i].flag) { printf("Lo:%d(%s) -> VI%02d <%d>\n", i, ipipe[i].code, ipipe[i].no, ipipe[i].vi); } } if (spipe.no != 0) { printf("EFU(%d): <%f>\n", spipe.no, spipe.vn); } for (i = 0; i < 7; i++) { if (qpipe[i].flag) { printf("q_pipe(%d)<%s> -> %f\n", 6 - i, qpipe[i].code, qpipe[i].vf[0]); } } } void printlist(VectorUnitState *state, char *buf) { /* [name] printlist [desc.] print out instruction list to stdout (for debug mode) [args] buf: input data from debug mode command line [return] void */ char dmy[32]; int no, i; u_long inst[2]; if (index(buf, ' ') != (char *) NULL) { sscanf(buf, "%s %d", dmy, &no); } else { no = opc; } for (i = 0; i < 10; i++) { inst[0] = state->uMEM[no + i][0]; inst[1] = state->uMEM[no + i][1]; printf("%04d: ", no + i); opcode_analyze(inst); putchar('\n'); } } void printreg(VectorUnitState *state, char *buf) { /* [name] printreg [desc.] print out register values(float or int) to stdout [args] buf: input data from debug mode command line [return] void */ int i; char dmy[32]; if (buf[1] == 'F') { if(buf[2] == 0){ for(i = 0; i < 32; i++){ printf("VF%02d <%f> <%f> <%f> <%f>\n", i, VF[i][3], VF[i][2], VF[i][1], VF[i][0]); } }else{ sscanf(buf, "VF%d", &i); printf("VF%02d <%f> <%f> <%f> <%f>\n", i, VF[i][3], VF[i][2], VF[i][1], VF[i][0]); } } else { if (buf[1] == 'I') { if (buf[2] == 0){ for(i = 0; i < 16; i++){ printf("VI%02d <%d>\n", i, VI[i]); } }else{ sscanf(buf, "VI%d", &i); printf("VI%02d <%d>\n", i, VI[i]); } } } } void printregI(VectorUnitState *state, char *buf) { /* [name] printreg [desc.] print out register values(hex) to stdout [args] buf: input data from debug mode command line [return] void */ int i; char dmy[32]; if (buf[1] == 'f') { if(buf[2] == 0) { for(i = 0; i < 32; i++){ printf("VF%02d <%08lx> <%08lx> <%08lx> <%08lx>\n", i, *(u_long *) & (VF[i][3]), *(u_long *) & (VF[i][2]), *(u_long *) & (VF[i][1]), *(u_long *) & (VF[i][0])); } }else{ sscanf(buf, "vf%d", &i); printf("VF%02d <%08lx> <%08lx> <%08lx> <%08lx>\n", i, *(u_long *) & (VF[i][3]), *(u_long *) & (VF[i][2]), *(u_long *) & (VF[i][1]), *(u_long *) & (VF[i][0])); } } else { if (buf[1] == 'i') { if (buf[2] == 0){ for(i = 0; i < 16; i++){ printf("VI%02d <%x>\n", i, VI[i]); } }else{ sscanf(buf, "vi%d", &i); printf("VI%02d <%x>\n", i, VI[i]); } } } } void setVFreg(VectorUnitState *state, char *buf) { /* [name] setVFreg [desc.] set value to VF regster (for debug mode) [args] buf: input data from debug mode command line [return] void */ int no; float val0, val1, val2, val3; sscanf(buf, "F%d %f %f %f %f\n", &no, &val0, &val1, &val2, &val3); if ((no <= 0) || (no > 31)) { printf("cannot set value VF%02d\n", no); } else { VF[no][0] = val3; VF[no][1] = val2; VF[no][2] = val1; VF[no][3] = val0; printf("VF%02d <%f> <%f> <%f> <%f>\n", no, VF[no][3], VF[no][2], VF[no][1], VF[no][0]); } } void setVIreg(VectorUnitState *state, char *buf) { /* [name] setVIreg [desc.] set value to VI regster (for debug mode) [args] buf: input data from debug mode command line [return] void */ int no, val; sscanf(buf, "I%d %d\n", &no, &val); if ((no <= 0) || (no > 24)) { printf("cannot set value VI%02d\n", no); } else { VI[no] = val; printf("VI%02d <%d>\n", no, VI[no]); } } void interactive(VectorUnitState *state) { /* [name] interactive [desc.] debug mode monitor [args] void [return] void */ int stat = 1; char buf[128]; char dmy[32]; int addr; printf("%04d: ", opc); opcode_analyze(instbuf); putchar('\n'); while (stat) { printf(">", opc); gets(buf); switch (buf[0]) { case 'b': /* breakpoint */ sscanf(buf, "%s %d", dmy, &bp); break; case 'p': /* pipe */ printpipe(); break; case 'r': /* run */ sscanf(buf, "%s %d", dmy, &pc); intr_mode = 1; stat = 0; break; case 'e': /* end count */ sscanf(buf, "%s %d", dmy, &ecount); intr_mode = 4; stat = 0; break; case 'd': /* dump state->MEM by hex */ sscanf(buf, "%s %d", dmy, &addr); printf("%04d %08lx %08lx %08lx %08lx\n", addr, state->MEM[addr][3], state->MEM[addr][2], state->MEM[addr][1], state->MEM[addr][0]); break; case 'D': /* dump state->MEM by float */ sscanf(buf, "%s %d", dmy, &addr); printf("%04d %f %f %f %f\n", addr, *(float *) &state->MEM[addr][3], *(float *) &state->MEM[addr][2], *(float *) &state->MEM[addr][1], *(float *) &state->MEM[addr][0]); break; case 'l': /* list */ printlist(state, buf); break; case 's': /* step */ intr_mode = 2; stat = 0; break; case 'c': /* continue */ intr_mode = 3; stat = 0; break; case 'i': /* print I */ printf("I : %f\n", I); break; case 'V': /* print reg */ printreg(state, buf); break; case 'v': /* print reg */ printregI(state, buf); break; case 'F': /* set val to VF reg */ setVFreg(state, buf); break; case 'I': /* set val to VI reg */ setVIreg(state, buf); break; case 'Q': /* print Q */ printf("Q : %f\n", Q); break; case 'P': /* print P */ printf("P : %f\n", VN[4]); break; case 'R': /* print R */ printf("R : 0x%08lx\n", R); break; case 'A': /* print ACC */ printf("ACC:<%f> <%f> <%f> <%f>\n", ACC[0], ACC[1], ACC[2], ACC[3]); break; case 'M': /* print MAC flag */ printf("MAC:<%04lx>\n", MACflag); break; case 'S': /* print status flag */ printf("status:<%03lx>\n", statusflag); break; case 'C': /* print clip flag */ printf("clip:<%03lx>\n", clipflag); break; case 'h': /* help */ printf("COMMAND LIST\n"); printf("r[un]\n"); printf("b[reakpoint] \n"); printf("c[ontinue]\n"); printf("s[tep]\n"); printf("l[ist] \n"); printf("p[ipe]\n"); printf("VF(float)\n"); printf("vf(hex)\n"); printf("VI\n"); printf("F \n"); printf("I \n"); printf("Q\n"); printf("P\n"); printf("R\n"); printf("M[ac flag]\n"); printf("S[tatus flag]\n"); printf("C[lip flag]\n"); printf("d[ump state->MEM(hex)] \n"); printf("D[ump state->MEM(float)] \n"); printf("e[nd count] \n"); printf("h[elp]\n"); break; default: break; } } } void simvpe(VectorUnitState *state) { /* [name] simvpe [desc.] VU simulation main routine. Need to set below variables and call initvpe, befor call this routine. _ITOP, _TOP, _vpepc, _is_dbg, _is_verb, _isdump, _pgpuif [args] void [return] void */ int stat = 1; eflag = 0; jflag = 0; peflag = 0; sflag = 0; verb_mode = _is_verb; dpr_mode = _is_dump; pc = _vpepc; if ((intr_mode > 0) && (intr_mode < 3)) { printf("simvpe interactive mode\n"); bp = _vpepc + 1; } if ((intr_mode == 4) && (ecount == 0)){ bp = _vpepc + 1; } fetch_inst(state); while (stat) { stat = 0; all_count++; if (((intr_mode == 1) && (pc == bp)) || ((intr_mode == 3) && (pc == bp)) || ((intr_mode == 4) && (pc == bp)) || (intr_mode == 2)) { interactive(state); } if (exec_inst(state)) stat += 1; if (fetch_inst(state)) stat += 2; if (move_pipe(state)) stat += 8; } _vpepc = pc + 1; ecount--; if (verb_mode) { printf("\n>> all cycles = %d cycle\n", all_count); printf(">> all hazard stall cycles = %d cycle\n", hc_count); } } void LoadVUMem(VectorUnitState *state, int dst_addr, u_long * src_addr, int qsize) { /* [name] LoadVUMem [desc.] Set values to VU memory [args] dst_addr: destination address of VU memory to set values. (The byte order of destination values is big endian.) src_addr: source address of values to set. (The byte order of source values is little endian) qsize: count of values to set ( quad ward ) [return] void */ int i; u_long eldata[4]; for (i = 0; i < qsize; i++) { /* convert little endian to bigendian. */ eldata[3] = src_addr[0] << 24 | ((src_addr[0] << 8) & 0xff0000) | ((src_addr[0] >> 8) & 0xff00) | ((src_addr[0] >> 24) & 0xff); eldata[2] = src_addr[1] << 24 | ((src_addr[1] << 8) & 0xff0000) | ((src_addr[1] >> 8) & 0xff00) | ((src_addr[1] >> 24) & 0xff); eldata[1] = src_addr[2] << 24 | ((src_addr[2] << 8) & 0xff0000) | ((src_addr[2] >> 8) & 0xff00) | ((src_addr[2] >> 24) & 0xff); eldata[0] = src_addr[3] << 24 | ((src_addr[3] << 8) & 0xff0000) | ((src_addr[3] >> 8) & 0xff00) | ((src_addr[3] >> 24) & 0xff); state->MEM[dst_addr + i][0] = eldata[0]; state->MEM[dst_addr + i][1] = eldata[1]; state->MEM[dst_addr + i][2] = eldata[2]; state->MEM[dst_addr + i][3] = eldata[3]; src_addr += 4; } } void LoadMMem(VectorUnitState *state, int dst_addr, u_long * src_addr, int dwsize) { /* [name] LoadMMem [desc.] Set instructions to Micro memory [args] dst_addr: destination address of Micro memory to set instructions (The byte order of destination values is big endian.) src_addr: source address of instructions to set (The byte order of source values is little endian.) dwsize: count of values to set ( double ward ) [return] void */ int i; u_long elop[2]; for (i = 0; i < dwsize; i++) { /* convert little endian to big endian. */ elop[1] = src_addr[0] << 24 | ((src_addr[0] << 8) & 0xff0000) | ((src_addr[0] >> 8) & 0xff00) | ((src_addr[0] >> 24) & 0xff); elop[0] = src_addr[1] << 24 | ((src_addr[1] << 8) & 0xff0000) | ((src_addr[1] >> 8) & 0xff00) | ((src_addr[1] >> 24) & 0xff); state->uMEM[dst_addr + i][0] = elop[0]; state->uMEM[dst_addr + i][1] = elop[1]; src_addr += 2; } } void StoreVUMem(VectorUnitState *state, int src_addr, u_long * dst_addr, int qsize) { /* [name] StoreVUMem [desc.] Get values from VU memory [args] src_addr: source address of VU memory to get values (The byte order of source values is big endian.) dst_addr: destination address of values to get (The byte order of destination values is little endian.) qsize: count of values to get (quad ward) [return] void */ int i; u_long data[4]; for (i = 0; i < qsize; i++) { data[3] = state->MEM[src_addr + i][0]; data[2] = state->MEM[src_addr + i][1]; data[1] = state->MEM[src_addr + i][2]; data[0] = state->MEM[src_addr + i][3]; /* convert big endian to little endian. */ dst_addr[3] = data[3] << 24 | ((data[3] << 8) & 0xff0000) | ((data[3] >> 8) & 0xff00) | ((data[3] >> 24) & 0xff); dst_addr[2] = data[2] << 24 | ((data[2] << 8) & 0xff0000) | ((data[2] >> 8) & 0xff00) | ((data[2] >> 24) & 0xff); dst_addr[1] = data[1] << 24 | ((data[1] << 8) & 0xff0000) | ((data[1] >> 8) & 0xff00) | ((data[1] >> 24) & 0xff); dst_addr[0] = data[0] << 24 | ((data[0] << 8) & 0xff0000) | ((data[0] >> 8) & 0xff00) | ((data[0] >> 24) & 0xff); dst_addr += 4; } } void StoreMMem(VectorUnitState *state, int src_addr, u_long * dst_addr, int dwsize) { /* [name] StoreMMem [desc.] Get instructions from Micro memory [args] src_addr: source address of Micro memory to get instructions (The byte order of source values is big endian.) dst_addr: destination address of instructions to get (The byte order of destination values is little endian.) qsize: count of instructions to get (quad ward) [return] void */ int i; u_long data[2]; for (i = 0; i < dwsize; i++) { data[1] = state->uMEM[src_addr + i][0]; data[0] = state->uMEM[src_addr + i][1]; /* convert big endian to little endian. */ dst_addr[1] = data[1] << 24 | ((data[1] << 8) & 0xff0000) | ((data[1] >> 8) & 0xff00) | ((data[1] >> 24) & 0xff); dst_addr[0] = data[0] << 24 | ((data[0] << 8) & 0xff0000) | ((data[0] >> 8) & 0xff00) | ((data[0] >> 24) & 0xff); dst_addr += 2; } } void vpecallms_init(VectorUnitState *state) { /* [name] vpecallms_init [desc.] Initialize internal status of VU simulator when start to execute a Micro program. This routine doesn't use with simvpe(). This routine use with vpecallms_cycle() and initvpe(). [args] void [return] void */ eflag = 0; jflag = 0; peflag = 0; sflag = 0; intr_mode = _is_dbg; verb_mode = _is_verb; dpr_mode = _is_dump; pc = _vpepc; } void vpecallms_cycle(VectorUnitState* state) { /* [name] vpecallms_cycle [desc.] VU simulator execute 1cycle. [args] void [return] !0: VU is busy 0: VU is idle */ int stat = 0; if (fetch_inst(state)) stat = 1; if (exec_inst(state)) stat = 2; if (move_pipe(state)) stat = 4; _vpepc = pc + 1; if (stat) { state->regs.VPE_STAT.vbs = 1; } else { state->regs.VPE_STAT.vbs = 0; } } #if 0 void simvpe2(VectorUnitState *state) { /* [name] simvpe2 [desc.] VU simulate same as simvpe(). ( sample routine ) [args] void [return] void */ vpecallms_init(state); while (vpecallms_cycle(state)); } #endif /*--------------------------------------------------------------------------*/ /****************************************************************************/ /* */ /* Sony Computer Entertainment CONFIDENTIAL */ /* (C) 1997 Sony Computer Entertainment Inc. All Rights Reserved */ /* */ /* Experimental disassembler */ /* */ /****************************************************************************/ #include void p_bc(u_long opcode) { switch(opcode&0x3){ case 0: putchar('x'); break; case 1: putchar('y'); break; case 2: putchar('z'); break; case 3: putchar('w'); break; } } void p_dest(u_long opcode) { switch((opcode >> 21) & 0xf){ case 1: printf("w"); break; case 2: printf("z"); break; case 3: printf("wz"); break; case 4: printf("y"); break; case 5: printf("yw"); break; case 6: printf("yz"); break; case 7: printf("yzw"); break; case 8: printf("x"); break; case 9: printf("xw"); break; case 10: printf("xz"); break; case 11: printf("xzw"); break; case 12: printf("xy"); break; case 13: printf("xyw"); break; case 14: printf("xyz"); break; case 15: printf("xyzw"); break; } } void bc_reg(u_long opcode) { putchar('/'); p_dest(opcode); printf(" VF%02d", (opcode >> 6) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_bc(opcode); } void par_reg3(u_long opcode) { printf(" VF%02d", (opcode >> 6) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); } void par_reg_ds(u_long opcode) { printf(" VF%02d", (opcode >> 6) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); } void mul_q(u_long opcode) { switch(opcode & 0x3){ case 0: printf("MULq/"); p_dest(opcode); par_reg_ds(opcode); printf(", Q"); break; case 1: printf("MAXi/"); p_dest(opcode); par_reg_ds(opcode); printf(", I"); break; case 2: printf("MULi/"); p_dest(opcode); par_reg_ds(opcode); printf(", I"); break; case 3: printf("MINIi/"); p_dest(opcode); par_reg_ds(opcode); printf(", I"); break; } } void add_q(u_long opcode) { switch(opcode & 0x3){ case 0: printf("ADDq/"); p_dest(opcode); par_reg_ds(opcode); printf(", Q"); break; case 1: printf("MADDq/"); p_dest(opcode); par_reg_ds(opcode); printf(", Q"); break; case 2: printf("ADDi/"); p_dest(opcode); par_reg_ds(opcode); printf(", I"); break; case 3: printf("MADDi/"); p_dest(opcode); par_reg_ds(opcode); printf(", I"); break; } } void sub_q(u_long opcode) { switch(opcode & 0x3){ case 0: printf("SUBq/"); p_dest(opcode); par_reg_ds(opcode); printf(", Q"); break; case 1: printf("MSUBq/"); p_dest(opcode); par_reg_ds(opcode); printf(", Q"); break; case 2: printf("SUBi/"); p_dest(opcode); par_reg_ds(opcode); printf(", I"); break; case 3: printf("MSUBi/"); p_dest(opcode); par_reg_ds(opcode); printf(", I"); break; } } void add(u_long opcode) { switch(opcode & 0x3){ case 0: printf("ADD/"); p_dest(opcode); par_reg3(opcode); break; case 1: printf("MADD/"); p_dest(opcode); par_reg3(opcode); break; case 2: printf("MUL/"); p_dest(opcode); par_reg3(opcode); break; case 3: printf("MAX/"); p_dest(opcode); par_reg3(opcode); break; } } void sub(u_long opcode) { switch(opcode & 0x3){ case 0: printf("SUB/"); p_dest(opcode); par_reg3(opcode); break; case 1: printf("MSUB/"); p_dest(opcode); par_reg3(opcode); break; case 2: printf("OPMSUB/xyz, VF%02dxyz", (opcode >> 6) & 0x1f); printf(", VF%02dxyz, VF%02dxyz", (opcode >> 11) & 0x1f, (opcode >> 16) & 0x1f); break; case 3: printf("MINI/"); p_dest(opcode); par_reg3(opcode); break; } } void bc_acc(u_long opcode) { putchar('/'); p_dest(opcode); printf(" ACC"); p_dest(opcode); printf(", VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_bc(opcode); } void itof(u_long opcode) { switch(opcode & 0x3){ case 0: printf("0/"); break; case 1: printf("4/"); break; case 2: printf("12/"); break; case 3: printf("15/"); break; } p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); } void par_reg_s(u_long opcode) { printf(" ACC"); p_dest(opcode); printf(", VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); } void mula_q(u_long opcode) { switch(opcode & 0x3){ case 0: printf("MULAq/"); p_dest(opcode); par_reg_s(opcode); printf(", Q"); break; case 1: printf("ABS/"); p_dest(opcode); printf(" VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); break; case 2: printf("MULAi/"); p_dest(opcode); par_reg_s(opcode); printf(", I"); break; case 3: printf("CLIPw/xyz"); printf(" VF%02dxyz", (opcode >> 11) & 0x1f); printf(", VF%02dw", (opcode >> 16) & 0x1f); break; } } void adda_q(u_long opcode) { switch(opcode & 0x3){ case 0: printf("ADDAq/"); p_dest(opcode); par_reg_s(opcode); printf(", Q"); break; case 1: printf("MADDAq/"); p_dest(opcode); par_reg_s(opcode); printf(", Q"); break; case 2: printf("ADDAi/"); p_dest(opcode); par_reg_s(opcode); printf(", I"); break; case 3: printf("MADDAi/"); p_dest(opcode); par_reg_s(opcode); printf(", I"); break; } } void suba_q(u_long opcode) { switch(opcode & 0x3){ case 0: printf("SUBAq/"); p_dest(opcode); par_reg_s(opcode); printf(", Q"); break; case 1: printf("MSUBAq/"); p_dest(opcode); par_reg_s(opcode); printf(", Q"); break; case 2: printf("SUBAi/"); p_dest(opcode); par_reg_s(opcode); printf(", I"); break; case 3: printf("MSUBAi/"); p_dest(opcode); par_reg_s(opcode); printf(", I"); break; } } void adda(u_long opcode) { switch(opcode & 0x3){ case 0: printf("ADDA/"); p_dest(opcode); par_reg_s(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); break; case 1: printf("MADDA/"); p_dest(opcode); par_reg_s(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); break; case 2: printf("MULA/"); p_dest(opcode); par_reg_s(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); break; case 3: printf("Undefined opcode(%08lx)", opcode); break; } } void suba(u_long opcode) { switch(opcode & 0x3){ case 0: printf("SUBA/"); p_dest(opcode); par_reg_s(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); break; case 1: printf("MSUBA/"); p_dest(opcode); par_reg_s(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); break; case 2: printf("OPMULA/xyz ACCxyz, VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); break; case 3: printf("NOP"); break; } } void special(u_long opcode) { switch((opcode >> 6) & 0xf) { /* bit41-38 */ case 0: printf("ADDA"); p_bc(opcode); bc_acc(opcode); break; case 1: printf("SUBA"); p_bc(opcode); bc_acc(opcode); break; case 2: printf("MADDA"); p_bc(opcode); bc_acc(opcode); break; case 3: printf("MSUBA"); p_bc(opcode); bc_acc(opcode); break; case 4: printf("ITOF"); itof(opcode); break; case 5: printf("FTOI"); itof(opcode); break; case 6: printf("MULA"); p_bc(opcode); bc_acc(opcode); break; case 7: mula_q(opcode); break; case 8: adda_q(opcode); break; case 9: suba_q(opcode); break; case 10: adda(opcode); break; case 11: suba(opcode); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void quad_load(u_long opcode) { switch((opcode >> 25) & 0x3){ case 0: printf("LQ/"); p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", %d(VI%02d)", opcode & 0x7ff, (opcode >> 11) & 0x1f); break; case 1: printf("SQ/"); p_dest(opcode); printf(" VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); printf(", %d(VI%02d)", opcode & 0x7ff, (opcode >> 16) & 0x1f); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void int_load(u_long opcode) { switch((opcode >> 25) & 0x3){ case 0: printf("ILW/"); p_dest(opcode); printf(" VI%02d", (opcode >> 16) & 0x1f); printf(", %d(VI%02d)", opcode & 0x7ff, (opcode >> 11) & 0x1f); break; case 1: printf("ISW/"); p_dest(opcode); printf(" VI%02d", (opcode >> 16) & 0x1f); printf(", %d(VI%02d)", opcode & 0x7ff, (opcode >> 11) & 0x1f); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void int_br(u_long opcode) { switch((opcode >> 25) & 0x3){ case 0: printf("IBEQ"); printf(" VI%02d, VI%02d, 0x%x", (opcode >> 16) & 0x1f, (opcode >> 11) & 0x1f, opcode & 0x7ff); break; case 1: printf("IBNE"); printf(" VI%02d, VI%02d, 0x%x", (opcode >> 16) & 0x1f, (opcode >> 11) & 0x1f, opcode & 0x7ff); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void cond_int_br(u_long opcode) { switch((opcode >> 25) & 0x3){ case 0: printf("IBLTZ"); printf(" VI%02d, 0x%x", (opcode >> 11) & 0x1f, opcode & 0x7ff); break; case 1: printf("IBGTZ"); printf(" VI%02d, 0x%x", (opcode >> 11) & 0x1f, opcode & 0x7ff); break; case 2: printf("IBLEZ"); printf(" VI%02d, 0x%x", (opcode >> 11) & 0x1f, opcode & 0x7ff); break; case 3: printf("IBGEZ"); printf(" VI%02d, 0x%x", (opcode >> 11) & 0x1f, opcode & 0x7ff); break; } } void br(u_long opcode) { switch((opcode >> 25) & 0x3){ case 0: printf("B 0x%x", opcode & 0x7ff); break; case 1: printf("BAL VI%02d, 0x%x", (opcode >> 16) & 0x1f, opcode & 0x7ff); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void jr(u_long opcode) { switch((opcode >> 25) & 0x3){ case 0: printf("JR VI%02d", (opcode >> 11) & 0x1f); break; case 1: printf("JALR VI%02d, VI%02d", (opcode >> 16) & 0x1f, (opcode >> 11) & 0x1f); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void uint_add(u_long opcode) { u_int imm; switch((opcode >> 25) & 0x3){ case 0: printf("IADDIU"); imm = ((opcode >> 10) & 0x7800) | (opcode & 0x7ff); printf(" VI%02d, VI%02d, %d", (opcode >> 16) & 0x1f, (opcode >> 11) & 0x1f, imm); break; case 1: printf("ISUBIU"); imm = ((opcode >> 10) & 0x7800) | (opcode & 0x7ff); printf(" VI%02d, VI%02d, %d", (opcode >> 16) & 0x1f, (opcode >> 11) & 0x1f, imm); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void fceq(u_long opcode) { switch((opcode >> 25) & 0x3){ case 0: printf("FCEQ 0x%x", opcode & 0x00ffffff); break; case 1: printf("FCSET 0x%x", opcode & 0x00ffffff); break; case 2: printf("FCAND 0x%x", opcode & 0x00ffffff); break; case 3: printf("FCOR 0x%x", opcode & 0x00ffffff); break; } } void fseq(u_long opcode) { u_long imm12; imm12 = ((opcode & 0x00200000) >> 10) | (opcode & 0x7ff); switch((opcode >> 25) & 0x3){ case 0: printf("FSEQ VI%02d, 0x%x", (opcode >> 16) & 0x1f, imm12); break; case 1: printf("FSSET 0x%x", imm12); break; case 2: printf("FSAND VI%02d, 0x%x", (opcode >> 16) & 0x1f, imm12); break; case 3: printf("FSOR VI%02d, 0x%x", (opcode >> 16) & 0x1f, imm12); break; } } void fcget(u_long opcode) { switch((opcode >> 25) & 0x3){ case 0: printf("FCGET VI%02d", (opcode >> 16) & 0x1f); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void fmand(u_long opcode) { switch((opcode >> 25) & 0x3){ case 0: printf("FMEQ VI%02d, VI%02d", (opcode >> 11) & 0x1f, (opcode >> 16) & 0x1f); break; case 2: printf("FMAND VI%02d, VI%02d", (opcode >> 11) & 0x1f, (opcode >> 16) & 0x1f); break; case 3: printf("FMOR VI%02d, VI%02d", (opcode >> 11) & 0x1f, (opcode >> 16) & 0x1f); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void iand(u_long opcode) { int imm5; switch(opcode & 0x3){ case 0: printf("IAND VI%02d, VI%02d, VI%02d", (opcode >> 6) & 0x1f, (opcode >> 11) & 0x1f, (opcode >> 16) & 0x1f); break; case 1: printf("IOR VI%02d, VI%02d, VI%02d", (opcode >> 6) & 0x1f, (opcode >> 11) & 0x1f, (opcode >> 16) & 0x1f); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void iadd(u_long opcode) { int imm5; switch(opcode & 0x3){ case 0: printf("IADD VI%02d, VI%02d, VI%02d", (opcode >> 6) & 0x1f, (opcode >> 11) & 0x1f, (opcode >> 16) & 0x1f); break; case 1: printf("ISUB VI%02d, VI%02d, VI%02d", (opcode >> 6) & 0x1f, (opcode >> 11) & 0x1f, (opcode >> 16) & 0x1f); break; case 2: if(opcode & 0x0400){ imm5 = ((opcode >> 6) & 0x1f) | 0xffffffe0; }else imm5 = ((opcode >> 6) & 0x1f); printf("IADDI VI%02d, VI%02d, %d", (opcode >> 16) & 0x1f, (opcode >> 11) & 0x1f, imm5); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void move(u_long opcode) { switch(opcode & 0x3){ case 0: if(((opcode >> 11 & 0x1f) == 0) && ((opcode >> 16) & 0x1f) == 0){ printf("NOP"); }else{ printf("MOVE/"); p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); } break; case 1: printf("MR32/"); p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void pinc_load(u_long opcode) { switch(opcode & 0x3){ case 0: printf("LQI/"); p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", VI%02d", (opcode >> 11) & 0x1f); break; case 1: printf("SQI/"); p_dest(opcode); printf(" VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); printf(", VI%02d", (opcode >> 16) & 0x1f); break; case 2: printf("LQD/"); p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", VI%02d", (opcode >> 11) & 0x1f); break; case 3: printf("SQD/"); p_dest(opcode); printf(" VF%02d", (opcode >> 11) & 0x1f); p_dest(opcode); printf(", VI%02d", (opcode >> 16) & 0x1f); break; } } void p_ftf(u_long ftf) { switch(ftf){ case 0: putchar('x'); break; case 1: putchar('y'); break; case 2: putchar('z'); break; case 3: putchar('w'); break; } } void mftir(u_long opcode) { switch(opcode & 0x3){ case 0: printf("MTIR/"); p_dest(opcode); printf(" VI%02d, VF%02d", (opcode >> 16) & 0x1f, (opcode >> 11) & 0x1f); p_dest(opcode); break; case 1: printf("MFIR/"); p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", VI%02d", (opcode >> 11) & 0x1f); break; case 2: printf("ILWR/"); p_dest(opcode); printf(" VI%02d, VI%02d", (opcode >> 16) & 0x1f, (opcode >> 11) & 0x1f); break; case 3: printf("ISWR/"); p_dest(opcode); printf(" VI%02d, VI%02d", (opcode >> 16) & 0x1f, (opcode >> 11) & 0x1f); break; } } void div(u_long opcode) { switch(opcode & 0x3){ case 0: printf("DIV Q, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); printf(", VF%02d", (opcode >> 16) & 0x1f); p_ftf((opcode >> 23) & 0x3); break; case 1: printf("SQRT Q, VF%02d", (opcode >> 16) & 0x1f); p_ftf((opcode >> 21) & 0x3); break; case 2: printf("RSQRT Q, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); printf(", VF%02d", (opcode >> 16) & 0x1f); p_ftf((opcode >> 23) & 0x3); break; case 3: printf("WAITQ"); break; } } void esadd_ersadd(u_long opcode) { switch(opcode & 0x3){ case 0: printf("ESADD"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); break; case 1: printf("ERSADD"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); break; case 2: printf("ELENG"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); break; case 3: printf("ERLENG"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); break; } } void esrsqrt(u_long opcode) { switch(opcode & 0x3){ case 0: printf("ESQRT"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); break; case 1: printf("ERSQRT"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); break; case 2: printf("ERCPR"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); break; case 3: printf("WAITP");break; } } void eatanxyz(u_long opcode) { switch(opcode & 0x3){ case 0: printf("EATANxy"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); break; case 1: printf("EATANxz"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); break; case 2: printf("ESUM"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); break; } } void esinatan(u_long opcode) { switch(opcode & 0x3){ case 0: printf("ESIN"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); break; case 1: printf("EATAN"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); break; case 2: printf("EEXP"); printf(" P, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); break; } } void mfp(u_long opcode) { switch(opcode & 0x3){ case 0: printf("MFP/"); p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", P"); break; } } void xgkick(u_long opcode) { printf("XGKICK VI%02d", (opcode >> 11) &0x1f); } void xitop(u_long opcode) { switch(opcode & 0x3){ case 0: printf("XTOP VI%02d", (opcode >> 16) & 0x1f); break; case 1: printf("XITOP VI%02d", (opcode >> 16) & 0x1f); break; } } void rand(u_long opcode) { switch(opcode & 0x3){ case 0: printf("RNEXT/"); p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", R"); break; case 1: printf("RGET/"); p_dest(opcode); printf(" VF%02d", (opcode >> 16) & 0x1f); p_dest(opcode); printf(", R"); break; case 2: printf("RINIT R, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); break; case 3: printf("RXOR R, VF%02d", (opcode >> 11) & 0x1f); p_ftf((opcode >> 21) & 0x3); break; } } void Special_Low(u_long opcode) { switch((opcode >> 6) & 0x1f){ case 12: move(opcode); break; case 13: pinc_load(opcode); break; case 14: div(opcode); break; case 15: mftir(opcode); break; case 16: rand(opcode); break; case 25: mfp(opcode); break; case 26: xitop(opcode); break; case 27: xgkick(opcode); break; case 28: esadd_ersadd(opcode); break; case 29: eatanxyz(opcode); break; case 30: esrsqrt(opcode); break; case 31: esinatan(opcode); break; default: printf("Undefined opcode(%08lx)", opcode); break; } } void maj_spcial(u_long opcode) { if(((opcode >> 2) & 0xf) == 12){ iadd(opcode); }else if(((opcode >> 2) & 0xf) == 13){ iand(opcode); }else if(((opcode >> 2) & 0xf) == 15){ Special_Low(opcode); }else{ printf("Undefined opcode(%08lx)", opcode); } } void opcode_analyze(u_long *opcode) { /* UpperOp */ switch((opcode[0] >> 2) & 0xf){ /* bit37-34 */ case 0: printf("ADD"); p_bc(opcode[0]); bc_reg(opcode[0]); break; case 1: printf("SUB"); p_bc(opcode[0]); bc_reg(opcode[0]); break; case 2: printf("MADD"); p_bc(opcode[0]); bc_reg(opcode[0]); break; case 3: printf("MSUB"); p_bc(opcode[0]); bc_reg(opcode[0]); break; case 4: printf("MAX"); p_bc(opcode[0]); bc_reg(opcode[0]); break; case 5: printf("MINI"); p_bc(opcode[0]); bc_reg(opcode[0]); break; case 6: printf("MUL"); p_bc(opcode[0]); bc_reg(opcode[0]); break; case 7: mul_q(opcode[0]); break; case 8: add_q(opcode[0]); break; case 9: sub_q(opcode[0]); break; case 10: add(opcode[0]); break; case 11: sub(opcode[0]); break; case 15: special(opcode[0]); break; default: printf("Undefined opcode(%08lx)", opcode[0]); break; } printf(" | "); /* LowerOp */ if(opcode[0]&0x80000000){ printf("LOI %f", *(float *)&opcode[1]); }else if(opcode[0]&0x40000000){ printf("END"); }else if(opcode[0]&0x04000000){ printf("PRT %08lx", opcode[1]); }else{ switch((opcode[1] >> 27) & 0x1f){ case 0: quad_load(opcode[1]); break; case 1: int_load(opcode[1]); break; case 2: uint_add(opcode[1]); break; case 4: fceq(opcode[1]); break; case 5: fseq(opcode[1]); break; case 6: fmand(opcode[1]); break; case 7: fcget(opcode[1]); break; case 8: br(opcode[1]); break; case 9: jr(opcode[1]); break; case 10: int_br(opcode[1]); break; case 11: cond_int_br(opcode[1]); break; case 16: maj_spcial(opcode[1]); break; default: printf("Undefined opcode(%08lx)", opcode[1]); break; } } } #if 0 void main(int argc, char **argv) { FILE *fpr; char rfilename[64]; u_long opcode[2]; u_long elop[2]; int count = 0; if(argc < 2){ fprintf(stderr, "Usage: dpppasm filename\n"); exit(1); } strcpy(rfilename, argv[1]); if((fpr = fopen(rfilename, "r")) == NULL){ fprintf(stderr, "can not open %s\n", rfilename); exit(1); } while(fread(&elop[0], 4, 2, fpr) != 0){ opcode[0] = (elop[1] << 24 ) | ((elop[1] << 8) & 0xff0000) | ((elop[1] >> 8) & 0xff00) | ((elop[1] >> 24) & 0xff); opcode[1] = (elop[0] << 24 ) | ((elop[0] << 8) & 0xff0000) | ((elop[0] >> 8) & 0xff00) | ((elop[0] >> 24) & 0xff); printf("%04d: ", count++); opcode_analyze(opcode); putchar('\n'); } fclose(fpr); } #endif /****************************************************************************/ /* */ /* Sony Computer Entertainment CONFIDENTIAL */ /* (C) 1997 Sony Computer Entertainment Inc. All Rights Reserved */ /* */ /* Psuedo GPUIF simulator (handle only PATH1) */ /* */ /****************************************************************************/ #define PRIM 0x00 #define RGBAQ 0x01 #define ST 0x02 #define UV 0x03 #define XYZF2 0x04 #define XYZ2 0x05 #define TEX0_1 0x06 #define TEX0_2 0x07 #define CLAMP_1 0x08 #define CLAMP_2 0x09 #define XYZF 0x0a #define XYZF3 0x0c #define XYZ3 0x0d #define A_D 0x0e #define GPUNOP 0x0f #define NOOUT 0 #define PRTGPUIF 1 #define PRTGPU 2 #define PRTGPI 3 extern int _GIF_SIM_OFF; extern int _GIF_BUSY; extern int _GIF_VUCALL; extern int _GIF_VUADDR; static u_long stQ; extern int _pgpuif; extern FILE *_fp_gpu; void GPU2_Put_gpu(int addr, u_long reg1, u_long reg0) { float xx, yy; fprintf(_fp_gpu,"%02x %08lx %08lx\n", addr, reg1, reg0); } void GPU2_Put_gpi(int addr, u_long reg1, u_long reg0) { float xx, yy; int ctxt, fst, aa1, abe, fge, tme, iip, prim; switch(addr){ case PRIM: fprintf(_fp_gpu, "PRIM PRIM=%d ", (reg0 & 0x7)); if(reg0 & 0x200) fprintf(_fp_gpu, "CTXT=1 "); if(reg0 & 0x100) fprintf(_fp_gpu, "FST=1 "); if(reg0 & 0x80) fprintf(_fp_gpu, "AA1=1 "); if(reg0 & 0x40) fprintf(_fp_gpu, "ABE=1 "); if(reg0 & 0x20) fprintf(_fp_gpu, "FGE=1 "); if(reg0 & 0x10) fprintf(_fp_gpu, "TME=1 "); if(reg0 & 0x8) fprintf(_fp_gpu, "IIP=1 "); fprintf(_fp_gpu, "\n"); break; case RGBAQ: xx = *(float *)®1; fprintf(_fp_gpu, "RGBAQ %d %d %d %d %e\n", reg0&0xff, (reg0>>8)&0xff, (reg0>>16)&0xff, (reg0>>24)&0xff, xx); break; case ST: xx = *(float *)®0; yy = *(float *)®1; fprintf(_fp_gpu, "ST %e %e\n", xx, yy); break; case UV: xx = (float)(reg0 & 0xffff)/16.0; yy = (float)((reg0 >> 16) & 0xffff)/16.0; fprintf(_fp_gpu, "UV %f %f\n", xx, yy); break; case XYZF2: xx = (float)(reg0&0xffff)/16.0; yy = (float)((reg0 >> 16)&0xffff)/16.0; fprintf(_fp_gpu, "XYZF2 %f %f %d %d\n", xx, yy, reg1&0xffffff, (reg1>>24)&0xff); break; case XYZ2: xx = (float)(reg0&0xffff)/16.0; yy = (float)((reg0 >> 16)&0xffff)/16.0; fprintf(_fp_gpu, "XYZ2 %f %f %d \n", xx, yy, reg1); break; case XYZF: xx = (float)(reg0&0xffff)/16.0; yy = (float)((reg0 >> 16)&0xffff)/16.0; fprintf(_fp_gpu, "XYZF %f %f %d %d\n", xx, yy, reg1&0xffffff, (reg1>>24)&0xff); break; case XYZF3: xx = (float)(reg0&0xffff)/16.0; yy = (float)((reg0 >> 16)&0xffff)/16.0; fprintf(_fp_gpu, "XYZF3 %f %f %d %d\n", xx, yy, reg1&0xffffff, (reg1>>24)&0xff); break; case XYZ3: xx = (float)(reg0&0xffff)/16.0; yy = (float)((reg0 >> 16)&0xffff)/16.0; fprintf(_fp_gpu, "XYZ3 %f %f %d\n", xx, yy, reg1); break; case A_D: fprintf(_fp_gpu, "!%02x %08lx %08lx\n", addr, reg1, reg0); break; case GPUNOP: break; default: fprintf(_fp_gpu, "!%02x %08lx %08lx\n", addr, reg1, reg0); break; } } void to_gpu(VectorUnitState *state, int regno, int addr) { u_long reg0, reg1; switch(regno){ case RGBAQ: reg0 = (state->MEM[addr][0] & 0xff) | ((state->MEM[addr][1] & 0xff) << 8) | ((state->MEM[addr][2] & 0xff) << 16) | ((state->MEM[addr][3] & 0xff) << 24); switch(_pgpuif){ case NOOUT: break; case PRTGPUIF: break; case PRTGPU: GPU2_Put_gpu(RGBAQ, stQ, reg0); break; case PRTGPI: GPU2_Put_gpi(RGBAQ, stQ, reg0); break; } break; case UV: reg0 = (state->MEM[addr][0] & 0xffff) | ((state->MEM[addr][1] & 0xffff) << 16); switch(_pgpuif){ case NOOUT: break; case PRTGPUIF: break; case PRTGPU: GPU2_Put_gpu(UV, 0, reg0); break; case PRTGPI: GPU2_Put_gpi(UV, 0, reg0); break; } break; case XYZF2: case XYZF3: reg0 = (state->MEM[addr][0] & 0xffff) | ((state->MEM[addr][1] & 0xffff) << 16); reg1 = ((state->MEM[addr][2]>>4) & 0xffffff) | (((state->MEM[addr][3]>>4) & 0xff) << 24); switch(_pgpuif){ case NOOUT: break; case PRTGPUIF: break; case PRTGPU: if(state->MEM[addr][3] & 0x8000) GPU2_Put_gpu(XYZF3, reg1, reg0); else GPU2_Put_gpu(XYZF2, reg1, reg0); break; case PRTGPI: if(state->MEM[addr][3] & 0x8000) GPU2_Put_gpi(XYZF3, reg1, reg0); else GPU2_Put_gpi(XYZF2, reg1, reg0); break; } break; case ST: stQ = state->MEM[addr][2]; case PRIM: case TEX0_1: case TEX0_2: case CLAMP_1: case CLAMP_2: switch(_pgpuif){ case NOOUT: break; case PRTGPUIF: break; case PRTGPU: GPU2_Put_gpu(regno, state->MEM[addr][1], state->MEM[addr][0]); break; case PRTGPI: GPU2_Put_gpi(regno, state->MEM[addr][1], state->MEM[addr][0]); break; } break; case A_D: switch(_pgpuif){ case NOOUT: break; case PRTGPUIF: break; case PRTGPU: GPU2_Put_gpu(state->MEM[addr][2] & 0xff, state->MEM[addr][1], state->MEM[addr][0]); break; case PRTGPI: GPU2_Put_gpi(state->MEM[addr][2] & 0xff, state->MEM[addr][1], state->MEM[addr][0]); break; } break; } } void GpuIfKick(VectorUnitState *state, int addr) { int nreg, flg, prim, pre, nloop; int regs[16], i, j; u_long tag0; if(_GIF_SIM_OFF){ if(_GIF_BUSY){ sflag = 1; hc_count++; pipe[0][0].flag = 0; apipe.flag = 0; }else{ _GIF_VUCALL = 1; _GIF_VUADDR = addr; _GIF_BUSY = 1; sflag = 0; } }else{ tag0 = state->MEM[addr][0]; nreg = (state->MEM[addr][1] >> 28) & 0xf; flg = (state->MEM[addr][1] >> 26) & 0x3; prim = (state->MEM[addr][1] >> 15) & 0x7ff; pre = (state->MEM[addr][1] >> 14) & 0x1; nloop = state->MEM[addr][0] & 0x7fff; do { tag0 = state->MEM[addr][0]; nreg = (state->MEM[addr][1] >> 28) & 0xf; flg = (state->MEM[addr][1] >> 26) & 0x3; prim = (state->MEM[addr][1] >> 15) & 0x7ff; pre = (state->MEM[addr][1] >> 14) & 0x1; nloop = state->MEM[addr][0] & 0x7fff; if(nreg == 0) nreg = 16; if(flg != 0){ fprintf(stderr, "GIF: not support FLG(%d)<%d>\n", flg, addr); return; } for(i = 0; i < 8; i++) regs[i] = (state->MEM[addr][2] >> (i * 4)) & 0xf; for(i = 8; i < 16; i++) regs[i] = (state->MEM[addr][3] >> ((i - 8) * 4)) & 0xf; if(pre){ switch(_pgpuif){ case NOOUT: case PRTGPUIF: break; case PRTGPU: GPU2_Put_gpu(PRIM, 0, (u_long)prim); break; case PRTGPI: GPU2_Put_gpi(PRIM, 0, (u_long)prim); break; } } if(_pgpuif == PRTGPUIF) fprintf(_fp_gpu, "%08lx %08lx %08lx %08lx\n", state->MEM[addr][3], state->MEM[addr][2], state->MEM[addr][1], state->MEM[addr][0]); addr++; for(i = 0; i < nloop; i++){ for(j = 0; j < nreg; j++){ if(_pgpuif == PRTGPUIF){ fprintf(_fp_gpu, "%08lx %08lx %08lx %08lx\n", state->MEM[addr][3], state->MEM[addr][2], state->MEM[addr][1], state->MEM[addr][0]); }else{ to_gpu(state, regs[j], addr); } addr++; } } }while((tag0 & 0x8000) == 0); } }