Skip to content
Snippets Groups Projects
Commit 787df2b4 authored by Geo Ster's avatar Geo Ster
Browse files

VU0: Add basic ADD/SUB/MUL instructions

* The bios uses them to initialize the VU0 registers. For now I don't
check for overflow but I think it's going to become necessary in the
near future.
parent 71aab146
No related branches found
No related tags found
No related merge requests found
......@@ -20,7 +20,7 @@ namespace vu
case 0b101100:
return op_vsub(vu_instr);
case 0b110000:
return op_viadd(vu_instr);
case 0b111100 ... 0b111111:
return special2(instr);
default:
......@@ -37,6 +37,10 @@ namespace vu
VUInstr vu_instr = { .value = instr.value };
switch (opcode)
{
case 0b0000100: op_vsuba(vu_instr); break;
case 0b0001000: op_vmadda(vu_instr); break;
case 0b0001100: op_vmsuba(vu_instr); break;
case 0b0010000: op_vitof0(vu_instr); break;
case 0b0111111: op_viswr(vu_instr); break;
case 0b0110101: op_vsqi(vu_instr); break;
default:
......@@ -157,4 +161,63 @@ namespace vu
fmt::print("[VU0] VIADD VI[{}] = VI[{}] ({:#x}) + VI[{}] ({:#x})\n", id, is, regs.vi[is], it, regs.vi[it]);
regs.vi[id] = regs.vi[is] + regs.vi[it];
}
void VU0::op_vsuba(VUInstr instr)
{
uint16_t fs = instr.fs;
uint16_t ft = instr.ft;
fmt::print("[VU0] VSUBA Writing VF[{}] - VF[{}] (", fs, ft);
for (int i = 0; i < 4; i++)
{
/* If the component is set in the dest mask */
if (instr.dest & (1 << i))
{
fmt::print("{}, ", "XYZW"[i]);
acc.fword[i] = regs.vf[fs].fword[i] - regs.vf[ft].fword[i];
}
}
fmt::print("\b\b)\n");
}
void VU0::op_vmadda(VUInstr instr)
{
uint16_t fs = instr.fs;
uint16_t ft = instr.ft;
fmt::print("[VU0] VMADDA Writing VF[{}] * VF[{}] (", fs, ft);
for (int i = 0; i < 4; i++)
{
/* If the component is set in the dest mask */
if (instr.dest & (1 << i))
{
fmt::print("{}, ", "XYZW"[i]);
acc.fword[i] += regs.vf[fs].fword[i] * regs.vf[ft].fword[i];
}
}
fmt::print("\b\b)\n");
}
void VU0::op_vmsuba(VUInstr instr)
{
uint16_t fs = instr.fs;
uint16_t ft = instr.ft;
fmt::print("[VU0] VMSUBA Writing VF[{}] - VF[{}] (", fs, ft);
for (int i = 0; i < 4; i++)
{
/* If the component is set in the dest mask */
if (instr.dest & (1 << i))
{
fmt::print("{}, ", "XYZW"[i]);
acc.fword[i] -= regs.vf[fs].fword[i] * regs.vf[ft].fword[i];
}
}
fmt::print("\b\b)\n");
}
void VU0::op_vitof0(VUInstr instr)
{
}
}
\ No newline at end of file
......@@ -11,10 +11,13 @@ using uint128_t = unsigned __int128;
namespace vu
{
union VF
union Vector
{
/* The unsigned part is used to preserve bit data */
uint128_t qword;
uint32_t word[4];
/* Float part is used for float operations */
float fword[4];
struct { float x, y, z, w; };
};
......@@ -22,7 +25,7 @@ namespace vu
{
uint32_t vi[16];
uint32_t control[16];
VF vf[32];
Vector vf[32];
};
union VUInstr
......@@ -47,12 +50,6 @@ namespace vu
uint32_t ft : 5;
uint32_t : 11;
};
VUInstr operator=(uint32_t i)
{
VUInstr v = { .value = i };
return v;
}
};
struct VU0
......@@ -73,10 +70,15 @@ namespace vu
void op_vsub(VUInstr instr);
void op_vsqi(VUInstr instr);
void op_viadd(VUInstr instr);
void op_vsuba(VUInstr instr);
void op_vmadda(VUInstr instr);
void op_vmsuba(VUInstr instr);
void op_vitof0(VUInstr instr);
private:
ee::EmotionEngine* cpu;
Registers regs = {};
Vector acc;
uint8_t data[4 * 1024] = {};
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment