From: Ian Carmichael Date: Wed, 28 Jan 1998 02:04:32 +0000 (+0000) Subject: * Very, very early support for vu1 based on sce code. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8ae6b5cd79abca4e12987dc7dd46e20418712d5c;p=binutils-gdb.git * Very, very early support for vu1 based on sce code. * Modified Files: * ChangeLog Makefile.in hardware.c vu1.c vu1.h * Added Files: * libvpe.c libvpe.h vpe.h vu.h --- diff --git a/sim/txvu/ChangeLog b/sim/txvu/ChangeLog index 8b192eb43a5..c053a248e72 100644 --- a/sim/txvu/ChangeLog +++ b/sim/txvu/ChangeLog @@ -1,15 +1,19 @@ +Tue Jan 27 18:24:01 1998 Ian Carmichael + + * Very, very early support for vu1 based on sce code. + Thu Jan 22 15:44:46 1998 Ian Carmichael - * Incorporate GPR_SET from mips/sim-main.h + * Incorporate GPR_SET from mips/sim-main.h. Fri Jan 16 14:25:54 1998 Ian Carmichael - * Devices now get decode() call + * Devices now get decode() call. Fri Jan 16 14:25:54 1998 Ian Carmichael - * Initial Device Support + * Initial Device Support. Thu Jan 15 10:25:54 1998 Ian Carmichael - * ChangeLog created + * ChangeLog created. diff --git a/sim/txvu/Makefile.in b/sim/txvu/Makefile.in index 4871dc8a7cb..08145118b68 100644 --- a/sim/txvu/Makefile.in +++ b/sim/txvu/Makefile.in @@ -37,6 +37,7 @@ SIM_OBJS = \ dma.o \ vu0.o \ vu1.o \ + libvpe.o \ pke.o \ sim-hload.o \ sim-engine.o \ @@ -59,6 +60,8 @@ SIM_EXTRA_CFLAGS = \ -I$(srcdir)/../../newlib/libc/sys/idt \ $(SIM_@sim_gen@_CFLAGS) +SIM_EXTRA_CCFLAGS = $(SIM_EXTRA_CFLAGS) + SIM_EXTRA_CLEAN = clean-igen clean-m16 clean-extra SIM_EXTRA_ALL = $(SIM_@sim_gen@_ALL) diff --git a/sim/txvu/hardware.c b/sim/txvu/hardware.c index 6460847dc7c..443396adf3d 100644 --- a/sim/txvu/hardware.c +++ b/sim/txvu/hardware.c @@ -18,6 +18,6 @@ register_devices(SIM_DESC sd) dma_attach(sd); pke0_attach(sd); vu0_attach(sd); - vu1_attach(sd); + vu1_init(sd); pke1_attach(sd); } diff --git a/sim/txvu/libvpe.c b/sim/txvu/libvpe.c new file mode 100644 index 00000000000..99f6b5268cd --- /dev/null +++ b/sim/txvu/libvpe.c @@ -0,0 +1,5877 @@ +/****************************************************************************/ +/* */ +/* 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); + } + +} diff --git a/sim/txvu/libvpe.h b/sim/txvu/libvpe.h new file mode 100644 index 00000000000..9e6bb23d63d --- /dev/null +++ b/sim/txvu/libvpe.h @@ -0,0 +1,35 @@ +/****************************************************************************/ +/* */ +/* Sony Computer Entertainment CONFIDENTIAL */ +/* (C) 1997 Sony Computer Entertainment Inc. All Rights Reserved */ +/* */ +/* VPE1 simulator (part of VU1) global variables */ +/* */ +/****************************************************************************/ + +#ifndef LIBVPE_H_ +#define LIBVPE_H_ + +extern unsigned long _ITOP; +extern unsigned long _TOP; +extern unsigned long _vpepc; +extern int _is_dbg; +extern int _is_verb; +extern int _is_dump; +extern int _pgpuif; +extern FILE *_fp_gpu; + +extern int _GIF_SIM_OFF; +extern int _GIF_BUSY; +extern int _GIF_VUCALL; +extern int _GIF_VUADDR; + +#include "vu.h" + +void initvpe(VectorUnitState *state); + +void vpecallms_init(VectorUnitState *state); +void vpecallms_cycle(VectorUnitState* state); + + +#endif diff --git a/sim/txvu/vpe.h b/sim/txvu/vpe.h new file mode 100644 index 00000000000..8895e993833 --- /dev/null +++ b/sim/txvu/vpe.h @@ -0,0 +1,114 @@ +/****************************************************************************/ +/* */ +/* Sony Computer Entertainment CONFIDENTIAL */ +/* (C) 1997 Sony Computer Entertainment Inc. All Rights Reserved */ +/* */ +/* VU simulator global definitions */ +/* */ +/****************************************************************************/ + +#include +#include +#include +#include + +typedef struct { + int no; /* destination register number VF:0-31 VI:32-47*/ + int mask; /* specify which units calculate */ + float vf[4]; /* calculated value */ + int flag; /*0: empty in this pipeline stage, + 1: write value to reg, + 2: store value from reg, + 3: write value to I-reg ( not used ), + 4: write only status to statusflag, + 5: write only clip value to clipflag, + 6: move value from EFU reg */ + u_long status; /* calculation unit status */ + u_long addr; /* store address ( store operation )*/ + char code[32]; /* instruction */ +} PIPELINE; /* pipeline stage specification for FMAC, Ld/St, RANDU, FDIV */ + +typedef struct { + int no; /* destination register number VI:0-15 */ + short vi; /* calculated value */ + int flag; /* 0: empty in this pipeline stage, + 1: write value to reg */ + char code[32]; /* instruction */ +} IPIPELINE; /* pipeline stage specification for IALU */ + +typedef struct { + int flag; /* 0: empty in this pipeline stage, + 1: write value to I-reg */ + float val; /* calculated value */ +} LOIPIPELINE; /* pipeline stage specification for I bit */ + +typedef struct { + int mask; /* specify which units calculate */ + float acc[4]; /* calculated value */ + int flag; /* 0: empty in this pipeline stage, + 1: write value to ACC */ +} APIPELINE; /* accumulator pipeline stage specification */ + +typedef struct { + int no; /* left stage count of pipeline */ + float vn; /* calculated value */ + int flag; /* 0: move to VN[4] + 1: move to VN[0] (not used)*/ +} SUPIPELINE; + +u_long instbuf[2]; /* instruction buffer. instbuf[0]:Upper, instbuf[1]:Lower*/ +u_long pc, opc; /* pc is next PC, opc is executed PC. see fetch_inst() */ +u_long jaddr; /* branch address */ + +float VF[32][4]; /* VF registers */ + /* VF[?][0] = x, VF[?][1] = y, VF[?][2] = z, VF[?][3] = w */ +short VI[16]; /* VI registers */ +float ACC[4]; /* accumulator registers */ +float Q; /* FDIV register */ +float I; /* I register */ +u_long R; /* RANDU register */ +float VN[32]; /* EFU registers */ +u_long MACflag; +u_long statusflag; +u_long clipflag; + +u_long MEM[4096][4]; /* VU (data) memory */ +u_long uMEM[1024][2]; /* Micro (instruction) memory */ + +PIPELINE pipe[4][2]; /* FMAC, Ld/St, RANDU piepline */ +PIPELINE qpipe[7]; /* FDIV(DIV,DQRT) pipeline */ +PIPELINE rqpipe[13]; /*FDIV(RSQRT) pipeline */ +IPIPELINE ipipe[2]; /* IALU pipeline */ +APIPELINE apipe; /* ACC pipeline stage */ +SUPIPELINE spipe; /* EFU pipeline stage */ +LOIPIPELINE Ipipe; /* I-bit pipeline stage */ + +int eflag, jflag, peflag, sflag; + /* eflag: E-bit detect flag + 0: not detect, 1: detect, -1: fetch stage terminate + jflag: branch detect flag + 0: not detect, 1: detect + peflag: end delay slot execute flag + 0: not execute, 1: execute, -1: finished ececution + sflag: data hazard stall flag + 0: not stall, 1: stall */ +u_long bp; /* break point address */ +u_long ecount; /* end counter */ +int intr_mode; /* interactive mode enable */ +int verb_mode; /* verbose mode enable */ +int dpr_mode; /* PRT (debug print) instruction enable */ +u_long all_count; /* amount of executed cycles */ +u_long hc_count; /* amount of hazard stall cycles */ + +extern int _GIF_SIM_OFF; /* internal GPUIF simulator disable */ +extern int _GIF_BUSY; /* external GPUIF simulator is BUSY flag, + this flag uses when _GIF_SIM_OFF = 1 */ +extern int _GIF_VUCALL; /* XGKICK instruction detect flag, + this flag uses when _GIF_SIM_OFF = 1 */ +extern int _GIF_VUADDR; /* appointed address by XGKICK instruction, + this flag uses when _GIF_SIM_OFF = 1 */ + +#define DEST_X 0x8 +#define DEST_Y 0x4 +#define DEST_Z 0x2 +#define DEST_W 0x1 diff --git a/sim/txvu/vu.h b/sim/txvu/vu.h new file mode 100644 index 00000000000..b983d88d87a --- /dev/null +++ b/sim/txvu/vu.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#ifndef VU_H_ +#define VU_H_ + +#include "sim-main.h" +#include + +typedef u_long MEM_Entry_Type[4]; +typedef u_long uMEM_Entry_Type[2]; + +typedef enum { VU_READY, VU_RUN, VU_BREAK } RunState; + +/* See VU Specifications (Ver. 2.10), p7-11 */ +typedef struct { + u_long vbs : 1; /* busy 0: Idle, 1: Busy */ + u_long vds : 1; /* D bit stop 0: No D bit stop, 1: D bit stop */ + u_long vts : 1; /* T bit stop 0: No T bit stop, 1: T bit stop*/ + u_long vfs : 1; /* ForceBreak stop 0: no ForceBreak stop, 1: ForceBreak stop*/ + u_long vgw : 1; /* XGKICK wait 0: Do not wait, 1: Wait */ + u_long div : 1; /* DIV busy 0: Idle, 1: Busy*/ + u_long efu : 1; /* EF busy 0: Idle, 1: Busy */ + u_long reserved_2:25; +} VpeStat; + +typedef struct { + float VF[32][4]; + short VI[16]; + u_long MST; + u_long MMC; + u_long MCP; + u_long MR; + u_long MI; + u_long MQ; + u_long MP; + u_long MTPC; + VpeStat VPE_STAT; +} VectorUnitRegs; + +typedef struct { + MEM_Entry_Type *MEM; /* VU (data) memory */ + uMEM_Entry_Type *uMEM; /* Micro (instruction) memory */ + VectorUnitRegs regs; + RunState runState; +} VectorUnitState; + +#endif diff --git a/sim/txvu/vu1.c b/sim/txvu/vu1.c index d2335685386..08231abed21 100644 --- a/sim/txvu/vu1.c +++ b/sim/txvu/vu1.c @@ -6,34 +6,69 @@ #include "device.h" #include "vu1.h" +#include "libvpe.h" +#include "vu.h" -static char vu1_mem0_buffer[VU1_MEM0_SIZE]; -static char vu1_mem1_buffer[VU1_MEM1_SIZE]; +VectorUnitState vu1_state; + +static char vu1_umem_buffer[VU1_MEM0_SIZE]; +static char vu1_mem_buffer[VU1_MEM1_SIZE]; + +void init_vu1(); +void init_vu(VectorUnitState *state, char* umem_buffer, char* mem_buffer); void vu1_issue() { + if (vu1_state.runState == VU_RUN) + vpecallms_cycle(&vu1_state); } int -vu1_io_read_buffer(device *me, - void *dest, - int space, - address_word addr, - unsigned nr_bytes, - sim_cpu *processor, - sim_cia cia) +vu1_io_read_register_window(device *me, + void *dest, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) { - printf("%s: Read!\n", me->name); + /* Slow and crappy hack ... */ + + int i; + + char source_buffer[VU1_REGISTER_WINDOW_SIZE]; + char* src; + + memcpy(source_buffer, &vu1_state.regs.VF[0][0], 0x200); /* copy VF registers */ + for (i = 0; i<16; i++ ) { + *(short*)&source_buffer[0x200 + i*16] = vu1_state.regs.VI[i]; + } + *(u_long*)&source_buffer[VU1_MST - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MST; + *(u_long*)&source_buffer[VU1_MMC - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MMC; + *(u_long*)&source_buffer[VU1_MCP - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MCP; + *(u_long*)&source_buffer[VU1_MR - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MR; + *(u_long*)&source_buffer[VU1_MI - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MI; + *(u_long*)&source_buffer[VU1_MQ - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MQ; + *(u_long*)&source_buffer[VU1_MP - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MP; + *(u_long*)&source_buffer[VU1_MTPC - VU1_REGISTER_WINDOW_START] = vu1_state.regs.MTPC; + *(VpeStat*)&source_buffer[VPE1_STAT - VU1_REGISTER_WINDOW_START] = vu1_state.regs.VPE_STAT; -printf(" vu1_mem0[0] = %d\n", *(int*)&vu1_mem0_buffer[0]); -printf(" vu1_mem1[0] = %d\n", *(int*)&vu1_mem1_buffer[0]); + printf("%s: Read: %x, %d, dest: %x, space: %d, %x!\n", me->name, addr, nr_bytes, dest, space, vu1_state.regs.VPE_STAT); + printf(" vu1_state.regs.VPE_STAT = %x\n", vu1_state.regs.VPE_STAT); + if (addr + nr_bytes > VU1_REGISTER_WINDOW_END) { + fprintf(stderr, "Error: Read past end of vu1 register window!!!\n"); + exit(1); + } + + src = &source_buffer[0] + (addr - VU1_REGISTER_WINDOW_START); + memcpy(dest, src, nr_bytes); return nr_bytes; } int -vu1_io_write_buffer(device *me, +vu1_io_write_register_window(device *me, const void *source, int space, address_word addr, @@ -41,20 +76,54 @@ vu1_io_write_buffer(device *me, sim_cpu *processor, sim_cia cia) { - printf("%s: Write!\n", me->name); + char *dest; + + if (addr == VPE1_STAT && nr_bytes == 4) { + /* Magic to switch VU to run state, until other methods are available. */ + vu1_state.runState = VU_RUN; + vu1_state.regs.VPE_STAT.vbs = 1; +printf("Magic start run...\n"); +printf("%x,%x,%x,%x\n", &vu1_state.regs.VF[0][0], &vu1_state.regs.VPE_STAT, + ((char*)&vu1_state.regs.VPE_STAT) - ((char*)&vu1_state.regs.VF[0][0]), + ((char*)&vu1_state.regs.VPE_STAT) - ((char*)&vu1_state.regs.VF[0][0]) + VU1_REGISTER_WINDOW_START + ); + +printf("%x,%x,%x,%x\n", &vu1_state.regs.VF[0][0], &vu1_state.regs.VI[0], + ((char*)&vu1_state.regs.VI[0]) - ((char*)&vu1_state.regs.VF[0][0]), + ((char*)&vu1_state.regs.VI[0]) - ((char*)&vu1_state.regs.VF[0][0]) + VU1_REGISTER_WINDOW_START + ); +printf("%x,%x,%x,%x\n", &vu1_state.regs.VF[0][0], &vu1_state.regs.MST, + ((char*)&vu1_state.regs.MST) - ((char*)&vu1_state.regs.VF[0][0]), + ((char*)&vu1_state.regs.MST) - ((char*)&vu1_state.regs.VF[0][0]) + VU1_REGISTER_WINDOW_START + ); + return nr_bytes; + } + + printf("%s: Write: %x, %d, source: %x, space: %d!\n", me->name, addr, nr_bytes, source, space); + + if (addr + nr_bytes > VU1_REGISTER_WINDOW_END) { + fprintf(stderr, "Error: Read past end of vu1 register window!!!\n"); + exit(1); + } + + dest = ((char*) (&vu1_state.regs)) + (addr - VU1_REGISTER_WINDOW_START); + + memcpy(dest, source, nr_bytes); + return nr_bytes; } device vu1_device = { "vu1", - &vu1_io_read_buffer, - &vu1_io_write_buffer + &vu1_io_read_register_window, + &vu1_io_write_register_window }; void -vu1_attach(SIM_DESC sd) +vu1_init(SIM_DESC sd) { + sim_core_attach (sd, NULL, 0 /*level*/, @@ -75,7 +144,7 @@ vu1_attach(SIM_DESC sd) VU1_MEM0_SIZE /*nr_bytes*/, 0 /*modulo*/, 0 /*device*/, - &vu1_mem0_buffer /*buffer*/); + &vu1_umem_buffer /*buffer*/); sim_core_attach (sd, NULL, @@ -86,5 +155,169 @@ vu1_attach(SIM_DESC sd) VU1_MEM1_SIZE /*nr_bytes*/, 0 /*modulo*/, 0 /*device*/, - &vu1_mem1_buffer /*buffer*/); + &vu1_mem_buffer /*buffer*/); + + init_vu1(); + /*initvpe();*/ + vpecallms_init(&vu1_state); +} + +/****************************************************************************/ +/* */ +/* Sony Computer Entertainment CONFIDENTIAL */ +/* (C) 1997 Sony Computer Entertainment Inc. All Rights Reserved */ +/* */ +/* VPE1 simulator */ +/* */ +/****************************************************************************/ + +#include +#include +#include +#include "libvpe.h" + +char ifilename[64] = "vu.bin"; +char ofilename[64] = ""; +char pfilename[64] = ""; + +void abend2(char *fmt, char* p) { + fprintf(stderr, fmt, p); + exit(1); +} + +void getoption(); + +void init_vu1() { + init_vu(&vu1_state, &vu1_umem_buffer[0], &vu1_mem_buffer[0]); +} + +void init_vu(VectorUnitState *state, char* umem_buffer, char* mem_buffer) +{ + FILE *fp; + int i, j; + u_long data[4]; + + /* set up memory buffers */ + state->uMEM = (uMEM_Entry_Type *) umem_buffer; + state->MEM = (MEM_Entry_Type*) mem_buffer; + + /* set up run state */ + state->runState = VU_READY; + + /* read option */ + getoption(); + + /* read instruction file (mandatory) */ + if (*ifilename) { + if((fp = fopen(ifilename, "r")) == NULL) + abend2("%s: can not open\n", ifilename); + + for (i = 0; fread(&data[0], 4, 1, fp) != 0; i++) { + fread(&data[1], 4, 1, fp); + LoadMMem(state, i, data, 1); + } + fclose(fp); + } + + /* PKE dirven simvpe */ + if (*pfilename) { + /* initpke(pfilename); */ + initvpe(&vu1_state); + /* while (simpke() != -1) + simvpe(); */ + } + + /* conventional simvpe */ + else { + initvpe(&vu1_state); + /*simvpe();*/ + } + + /* write result memory image (optional) */ + if (*ofilename) { + if((fp = fopen(ofilename, "w")) == NULL) + abend2("%s: can not open\n", ofilename); + + for(i = 0; i < 2048; i++){ + StoreVUMem(i, data, 1); + for(j = 0; j < 4; j++) + fwrite(&data[j], 4, 1, fp); + } + fclose(fp); + } +} + +static void Usage(void) +{ + fprintf(stderr, "Usage: simvpe [options]\n"); + fprintf(stderr, "\t\t-i instruction-file\n"); + fprintf(stderr, "\t\t-o output-memory-file\n"); + fprintf(stderr, "\t\t-t PKE-file (text type)\n"); + fprintf(stderr, "\t\t-s start-address [default = 0]\n"); + fprintf(stderr, "\t\t-d [interactive mode enable: default desable]\n"); + fprintf(stderr, "\t\t-v [statistics mode enable: default desable]\n"); + fprintf(stderr, "\t\t-p [debug print mode enable: default desable]\n"); +} + +void getoption() +{ + int startline = 0; + int count = 1; + + _is_dbg = 1; + _vpepc = 0; + _is_verb = 0; + _is_dump = 0; + _pgpuif = 2; + _ITOP = 20; + _TOP = 10; + +#if 0 + while(argc - count){ + if(argv[count][0] == '-'){ + switch(argv[count][1]){ + case 'i': + strcpy(ifilename, argv[count+1]); + count += 2; + break; + case 'o': + strcpy(ofilename, argv[count+1]); + count += 2; + break; + case 't': + strcpy(pfilename, argv[count+1]); + count += 2; + break; + case 's': + sscanf(argv[count+1], "%d", &startline); + _vpepc = startline; + count += 2; + break; + case 'd': + _is_dbg = 1; + count += 1; + break; + case 'v': + _is_verb = 1; + count += 1; + break; + case 'p': + _is_dump = 1; + count += 1; + break; + case 'h': + case '?': + Usage(); + exit(1); + break; + default: + Usage(); + exit(1); + } + }else{ + Usage(); + exit(1); + } + } +#endif } diff --git a/sim/txvu/vu1.h b/sim/txvu/vu1.h index 393c84a7ec8..6150b09ea61 100644 --- a/sim/txvu/vu1.h +++ b/sim/txvu/vu1.h @@ -26,11 +26,17 @@ void vu1_issue(); /* ... */ #define VU1_VI15 0x110072f0 -/* ... */ - -#define VPE1_STAT 0x11007370 - -#define VU1_REGISTER_WINDOW_END 0x11007380 +#define VU1_MST 0x11007300 +#define VU1_MMC 0x11007310 +#define VU1_MCP 0x11007320 +#define VU1_MR 0x11007330 +#define VU1_MI 0x11007340 +#define VU1_MQ 0x11007350 +#define VU1_MP 0x11007360 +#define VU1_MTPC 0x110073a0 +#define VPE1_STAT 0x110073d0 + +#define VU1_REGISTER_WINDOW_END 0x110073e0 #define VU1_REGISTER_WINDOW_SIZE (VU1_REGISTER_WINDOW_END - VU1_REGISTER_WINDOW_START)