mirror of
https://github.com/google0101-ryan/Emotional.git
synced 2024-05-11 00:55:29 -04:00
Got first character on serial
This commit is contained in:
parent
911cea1f32
commit
7013869f15
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3,4 +3,5 @@
|
|||
A WIP PlayStation 2 emulator
|
||||
|
||||
Currently implemented:
|
||||
|
||||
Some Emotion Engine opcodes
|
|
@ -30,4 +30,6 @@ Bus::Bus(std::string fileName, bool& s)
|
|||
|
||||
s = true;
|
||||
printf("[emu/Bus]: %s: Bus initialized\n", __FUNCTION__);
|
||||
|
||||
console.open("log.txt");
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <bits/stdint-uintn.h>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
class Bus
|
||||
{
|
||||
|
@ -10,6 +11,8 @@ private:
|
|||
uint8_t bios[0x400000];
|
||||
uint8_t scratchpad[0x4000];
|
||||
|
||||
std::ofstream console;
|
||||
|
||||
uint32_t Translate(uint32_t addr)
|
||||
{
|
||||
if (addr <= 0x7FFFFFFF)
|
||||
|
@ -35,6 +38,14 @@ public:
|
|||
|
||||
if (addr >= 0x1FC00000 && addr < 0x21C00000)
|
||||
return *(T*)&bios[addr - 0x1FC00000];
|
||||
if (addr >= 0x70000000 && addr < 0x70004000)
|
||||
return *(T*)&scratchpad[addr - 0x70000000];
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case 0x1000f130: // SIO status
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("[emu/Bus]: %s: Failed to read from address 0x%08x\n", __FUNCTION__, addr);
|
||||
exit(1);
|
||||
|
@ -53,10 +64,17 @@ public:
|
|||
|
||||
switch (addr)
|
||||
{
|
||||
// misc SIO settings
|
||||
case 0x1000f100:
|
||||
case 0x1000f120:
|
||||
case 0x1000f140:
|
||||
case 0x1000f150:
|
||||
case 0x1000f500:
|
||||
return;
|
||||
case 0x1000f180:
|
||||
console << (char)data;
|
||||
console.flush();
|
||||
return;
|
||||
}
|
||||
|
||||
printf("[emu/Bus]: %s: Write to unknown addr 0x%08x\n", __FUNCTION__, addr);
|
||||
|
|
|
@ -13,12 +13,20 @@ EmotionEngine::EmotionEngine(Bus* bus)
|
|||
next_pc = pc + 4;
|
||||
|
||||
cop0_regs[15] = 0x2E20;
|
||||
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
icache[i].tag[0] = 1 << 31;
|
||||
icache[i].tag[1] = 1 << 31;
|
||||
icache[i].lfu[0] = false;
|
||||
icache[i].lfu[1] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EmotionEngine::Clock()
|
||||
{
|
||||
Opcode instr;
|
||||
instr.full = Read32Instr(pc);
|
||||
instr.full = Read32(pc, true);
|
||||
|
||||
AdvancePC();
|
||||
|
||||
|
@ -37,6 +45,9 @@ void EmotionEngine::Clock()
|
|||
case 0x00:
|
||||
sll(instr);
|
||||
break;
|
||||
case 0x03:
|
||||
sra(instr);
|
||||
break;
|
||||
case 0x08:
|
||||
jr(instr);
|
||||
break;
|
||||
|
@ -46,9 +57,15 @@ void EmotionEngine::Clock()
|
|||
case 0x0F:
|
||||
printf("sync\n");
|
||||
break;
|
||||
case 0x12:
|
||||
mflo(instr);
|
||||
break;
|
||||
case 0x18:
|
||||
mult(instr);
|
||||
break;
|
||||
case 0x1B:
|
||||
divu(instr);
|
||||
break;
|
||||
case 0x25:
|
||||
op_or(instr);
|
||||
break;
|
||||
|
@ -62,9 +79,26 @@ void EmotionEngine::Clock()
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x01:
|
||||
{
|
||||
switch (instr.i_type.rt)
|
||||
{
|
||||
case 0x00:
|
||||
bltz(instr);
|
||||
break;
|
||||
default:
|
||||
printf("[emu/CPU]: %s: Unknown regimm instruction 0x%08x (0x%02x)\n", __FUNCTION__, instr.full, instr.i_type.rt);
|
||||
Application::Exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
j(instr);
|
||||
break;
|
||||
case 0x03:
|
||||
jal(instr);
|
||||
break;
|
||||
case 0x04:
|
||||
beq(instr);
|
||||
break;
|
||||
|
@ -77,6 +111,9 @@ void EmotionEngine::Clock()
|
|||
case 0x0A:
|
||||
slti(instr);
|
||||
break;
|
||||
case 0x0B:
|
||||
sltiu(instr);
|
||||
break;
|
||||
case 0x0C:
|
||||
andi(instr);
|
||||
break;
|
||||
|
@ -106,9 +143,33 @@ void EmotionEngine::Clock()
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 0x14:
|
||||
beql(instr);
|
||||
break;
|
||||
case 0x15:
|
||||
bnel(instr);
|
||||
break;
|
||||
case 0x20:
|
||||
lb(instr);
|
||||
break;
|
||||
case 0x23:
|
||||
lw(instr);
|
||||
break;
|
||||
case 0x24:
|
||||
lbu(instr);
|
||||
break;
|
||||
case 0x28:
|
||||
sb(instr);
|
||||
break;
|
||||
case 0x2B:
|
||||
sw(instr);
|
||||
break;
|
||||
case 0x37:
|
||||
ld(instr);
|
||||
break;
|
||||
case 0x39:
|
||||
swc1(instr);
|
||||
break;
|
||||
case 0x3f:
|
||||
sd(instr);
|
||||
break;
|
||||
|
@ -124,4 +185,5 @@ void EmotionEngine::Dump()
|
|||
{
|
||||
for (int i = 0; i < 32; i++)
|
||||
printf("[emu/CPU]: %s: %s\t->\t%s\n", __FUNCTION__, Reg(i), print_128(regs[i]));
|
||||
printf("[emu/CPU]: %s: pc\t->\t0x%08x\n", __FUNCTION__, pc-4);
|
||||
}
|
|
@ -15,6 +15,15 @@ private:
|
|||
uint32_t pc, next_pc;
|
||||
uint64_t hi, lo;
|
||||
|
||||
struct COP1
|
||||
{
|
||||
union
|
||||
{
|
||||
float f[32] = {0.0f};
|
||||
uint32_t i[32];
|
||||
};
|
||||
} cop1;
|
||||
|
||||
struct CacheTag
|
||||
{
|
||||
bool valid = false;
|
||||
|
@ -23,47 +32,68 @@ private:
|
|||
uint32_t page = 0;
|
||||
};
|
||||
|
||||
struct Cache
|
||||
struct ICacheLine
|
||||
{
|
||||
CacheTag tag[2];
|
||||
uint8_t data[2][64] = {0};
|
||||
} icache[128], dcache[64];
|
||||
bool lfu[2];
|
||||
uint32_t tag[2];
|
||||
uint8_t data[2][64];
|
||||
};
|
||||
|
||||
ICacheLine icache[128];
|
||||
|
||||
bool isCacheEnabled = false;
|
||||
|
||||
uint32_t Read32Instr(uint32_t addr)
|
||||
uint32_t Read32(uint32_t addr, bool isInstr = false)
|
||||
{
|
||||
if (!bus->IsCacheable(addr) || !isCacheEnabled)
|
||||
if (!bus->IsCacheable(addr) || !isCacheEnabled || !isInstr)
|
||||
return bus->read<uint32_t>(addr);
|
||||
|
||||
uint32_t page = (addr >> 14);
|
||||
uint32_t index = (addr >> 5) & 8;
|
||||
uint32_t offset = addr & 0x3F;
|
||||
int index = (addr >> 6) & 0x7F;
|
||||
uint16_t tag = addr >> 13;
|
||||
int off = addr & 0x3F;
|
||||
|
||||
Cache& line = icache[index];
|
||||
ICacheLine& line = icache[index];
|
||||
|
||||
for (int way = 0; way < 2; way++)
|
||||
if (line.tag[0] != tag)
|
||||
{
|
||||
if (line.tag[way].page == page && line.tag[way].valid)
|
||||
if (line.tag[1] != tag)
|
||||
{
|
||||
return *((uint32_t*)&line.data[way][offset]);
|
||||
printf("Cache miss for addr 0x%08x\n", addr);
|
||||
if (line.tag[0] & (1 << 31))
|
||||
{
|
||||
line.lfu[0] ^= true;
|
||||
line.tag[0] = tag;
|
||||
for (int i = 0; i < 64; i++)
|
||||
line.data[0][i] = bus->read<uint8_t>((addr & 0xFFFFFFC0) + i);
|
||||
return *(uint32_t*)&line.data[0][off];
|
||||
}
|
||||
else if (line.tag[1] & (1 << 31))
|
||||
{
|
||||
line.lfu[1] ^= true;
|
||||
line.tag[1] = tag;
|
||||
for (int i = 0; i < 64; i++)
|
||||
line.data[1][i] = bus->read<uint8_t>((addr & 0xFFFFFFC0) + i);
|
||||
return *(uint32_t*)&line.data[1][off];
|
||||
}
|
||||
else
|
||||
{
|
||||
int replace = line.lfu[0] ^ line.lfu[1];
|
||||
line.lfu[replace] ^= true;
|
||||
line.lfu[replace] = tag;
|
||||
for (int i = 0; i < 64; i++)
|
||||
line.data[replace][i] = bus->read<uint8_t>((addr & 0xFFFFFFC0) + i);
|
||||
return *(uint32_t*)&line.data[replace][off];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return *(uint32_t*)&line.data[1][off];
|
||||
}
|
||||
}
|
||||
|
||||
// Welp, cache miss
|
||||
printf("[emu/CPU]: Cache miss for address 0x%08x\n", addr);
|
||||
|
||||
int replace = 0;
|
||||
if (!line.tag[0].valid && line.tag[1].valid)
|
||||
replace = 0;
|
||||
else if (line.tag[0].valid && !line.tag[1].valid)
|
||||
replace = 1;
|
||||
else
|
||||
replace = line.tag[0].lrf ^ line.tag[1].lrf;
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
line.data[replace][i] = bus->read<uint8_t>((page << 14) + i);
|
||||
return *(uint32_t*)&line.data[replace][offset];
|
||||
{
|
||||
return *(uint32_t*)&line.data[0][off];
|
||||
}
|
||||
}
|
||||
|
||||
void Write32(uint32_t addr, uint32_t data)
|
||||
|
@ -74,43 +104,7 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t page = (addr >> 13);
|
||||
uint32_t index = (addr >> 5) & 0b1111111;
|
||||
uint32_t offset = addr & 0x3F;
|
||||
|
||||
Cache& line = dcache[index];
|
||||
|
||||
for (int way = 0; way < 2; way++)
|
||||
{
|
||||
if (line.tag[way].page == page && line.tag[way].valid)
|
||||
{
|
||||
*((uint32_t*)&line.data[way][offset]) = data;
|
||||
line.tag[way].dirty = true; // We mark as dirty to flush back to main memory on eviction
|
||||
}
|
||||
}
|
||||
|
||||
printf("[emu/CPU]: Cache miss for address 0x%08x\n", addr);
|
||||
|
||||
int replace = 0;
|
||||
if (!line.tag[0].valid && line.tag[1].valid)
|
||||
replace = 0;
|
||||
else if (line.tag[0].valid && !line.tag[1].valid)
|
||||
replace = 1;
|
||||
else
|
||||
replace = line.tag[0].lrf ^ line.tag[1].lrf;
|
||||
|
||||
if (line.tag[replace].dirty)
|
||||
{
|
||||
for (int i = 0; i < 64; i++)
|
||||
bus->write((page << 13) + i, line.data[replace][i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
line.data[replace][i] = bus->read<uint8_t>((page << 13) + i);
|
||||
}
|
||||
*(uint32_t*)&line.data[replace][offset] = data;
|
||||
line.tag[replace].dirty = true;
|
||||
}
|
||||
|
||||
void Write64(uint32_t addr, uint64_t data)
|
||||
|
@ -120,66 +114,43 @@ private:
|
|||
bus->write(addr, data);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t page = (addr >> 13);
|
||||
uint32_t index = (addr >> 5) & 0b1111111;
|
||||
uint32_t offset = addr & 0x3F;
|
||||
|
||||
Cache& line = dcache[index];
|
||||
|
||||
for (int way = 0; way < 2; way++)
|
||||
{
|
||||
if (line.tag[way].page == page && line.tag[way].valid)
|
||||
{
|
||||
*((uint64_t*)&line.data[way][offset]) = data;
|
||||
line.tag[way].dirty = true; // We mark as dirty to flush back to main memory on eviction
|
||||
}
|
||||
}
|
||||
|
||||
printf("[emu/CPU]: Cache miss for address 0x%08x\n", addr);
|
||||
|
||||
int replace = 0;
|
||||
if (!line.tag[0].valid && line.tag[1].valid)
|
||||
replace = 0;
|
||||
else if (line.tag[0].valid && !line.tag[1].valid)
|
||||
replace = 1;
|
||||
else
|
||||
replace = line.tag[0].lrf ^ line.tag[1].lrf;
|
||||
|
||||
if (line.tag[replace].dirty)
|
||||
{
|
||||
for (int i = 0; i < 64; i++)
|
||||
bus->write((page << 13) + i, line.data[replace][i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
line.data[replace][i] = bus->read<uint8_t>((page << 13) + i);
|
||||
}
|
||||
*(uint64_t*)&line.data[replace][offset] = data;
|
||||
line.tag[replace].dirty = true;
|
||||
}
|
||||
|
||||
void j(Opcode i); // 0x03
|
||||
void j(Opcode i); // 0x02
|
||||
void jal(Opcode i); // 0x03
|
||||
void beq(Opcode i); // 0x04
|
||||
void bne(Opcode i); // 0x05
|
||||
void addiu(Opcode i); // 0x09
|
||||
void slti(Opcode i); // 0x0A
|
||||
void sltiu(Opcode i); // 0x0B
|
||||
void andi(Opcode i); // 0x0C
|
||||
void ori(Opcode i); // 0x0D
|
||||
void lui(Opcode i); // 0x0F
|
||||
void mfc0(Opcode i); // 0x10 0x00
|
||||
void mtc0(Opcode i); // 0x10 0x04
|
||||
void beql(Opcode i); // 0x14
|
||||
void bnel(Opcode i); // 0x15
|
||||
void lb(Opcode i); // 0x20
|
||||
void lw(Opcode i); // 0x23
|
||||
void lbu(Opcode i); // 0x24
|
||||
void sb(Opcode i); // 0x28
|
||||
void sw(Opcode i); // 0x2B
|
||||
void ld(Opcode i); // 0x37
|
||||
void swc1(Opcode i); // 0x39
|
||||
void sd(Opcode i); // 0x3f
|
||||
|
||||
void sll(Opcode i); // 0x00
|
||||
void sra(Opcode i); // 0x03
|
||||
void jr(Opcode i); // 0x08
|
||||
void jalr(Opcode i); // 0x09
|
||||
void mflo(Opcode i); // 0x12
|
||||
void mult(Opcode i); // 0x18
|
||||
void divu(Opcode i); // 0x1B
|
||||
void op_or(Opcode i); // 0x25
|
||||
void daddu(Opcode i); // 0x2d
|
||||
|
||||
void bltz(Opcode i); // 0x00
|
||||
|
||||
void AdvancePC()
|
||||
{
|
||||
pc = next_pc;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <cstdio>
|
||||
#include <emu/cpu/EmotionEngine.h>
|
||||
|
||||
|
||||
void EmotionEngine::j(Opcode i)
|
||||
{
|
||||
uint32_t target = (i.j_type.target << 2);
|
||||
|
@ -11,6 +12,14 @@ void EmotionEngine::j(Opcode i)
|
|||
printf("j 0x%08x\n", next_pc);
|
||||
}
|
||||
|
||||
void EmotionEngine::jal(Opcode i)
|
||||
{
|
||||
uint32_t target = (i.j_type.target << 2);
|
||||
regs[31].u64[0] = next_pc;
|
||||
next_pc = (pc & 0xF0000000) | target;
|
||||
printf("jal 0x%08x\n", next_pc);
|
||||
}
|
||||
|
||||
void EmotionEngine::beq(Opcode i)
|
||||
{
|
||||
int32_t imm = (int32_t)((uint32_t)i.i_type.imm << 2);
|
||||
|
@ -41,38 +50,44 @@ void EmotionEngine::addiu(Opcode i)
|
|||
int rs = i.i_type.rs;
|
||||
int32_t imm = (int16_t)(uint32_t)i.i_type.imm;
|
||||
|
||||
regs[rt].u32[0] = (uint32_t)((int32_t)regs[rt].u32[0] + imm);
|
||||
regs[rt].u64[0] = (uint32_t)((int32_t)regs[rt].u32[0] + imm);
|
||||
|
||||
printf("addiu %s, %s, %d\n", Reg(rt), Reg(rs), imm);
|
||||
}
|
||||
|
||||
void EmotionEngine::slti(Opcode i)
|
||||
{
|
||||
regs[i.i_type.rt].u32[0] = (int32_t)regs[i.i_type.rs].u32[0] < (int32_t)(uint32_t)i.i_type.imm;
|
||||
regs[i.i_type.rt].u64[0] = (int32_t)regs[i.i_type.rs].u32[0] < (int32_t)(uint32_t)i.i_type.imm;
|
||||
printf("slti %s, %s, 0x%04x\n", Reg(i.i_type.rt), Reg(i.i_type.rs), i.i_type.imm);
|
||||
}
|
||||
|
||||
void EmotionEngine::sltiu(Opcode i)
|
||||
{
|
||||
regs[i.i_type.rt].u64[0] = regs[i.i_type.rs].u32[0] < (uint32_t)i.i_type.imm;
|
||||
printf("sltiu %s, %s, 0x%04x\n", Reg(i.i_type.rt), Reg(i.i_type.rs), i.i_type.imm);
|
||||
}
|
||||
|
||||
void EmotionEngine::andi(Opcode i)
|
||||
{
|
||||
regs[i.i_type.rt].u32[0] = regs[i.i_type.rs].u32[0] & (uint32_t)(int32_t)i.i_type.imm;
|
||||
regs[i.i_type.rt].u64[0] = regs[i.i_type.rs].u32[0] & (uint32_t)(int32_t)i.i_type.imm;
|
||||
printf("andi %s, %s, 0x%08x\n", Reg(i.i_type.rt), Reg(i.i_type.rs), i.i_type.imm);
|
||||
}
|
||||
|
||||
void EmotionEngine::ori(Opcode i)
|
||||
{
|
||||
regs[i.i_type.rt].u32[0] = regs[i.i_type.rs].u32[0] | (uint32_t)(int32_t)i.i_type.imm;
|
||||
regs[i.i_type.rt].u64[0] = regs[i.i_type.rs].u32[0] | (uint32_t)(int32_t)i.i_type.imm;
|
||||
printf("ori %s, %s, 0x%08x\n", Reg(i.i_type.rt), Reg(i.i_type.rs), i.i_type.imm);
|
||||
}
|
||||
|
||||
void EmotionEngine::lui(Opcode i)
|
||||
{
|
||||
regs[i.i_type.rt].u32[0] = (int32_t)((uint32_t)i.i_type.imm << 16);
|
||||
regs[i.i_type.rt].u64[0] = ((uint32_t)i.i_type.imm << 16);
|
||||
printf("lui %s, 0x%08x\n", Reg(i.i_type.rt), regs[i.i_type.rt].u32[0]);
|
||||
}
|
||||
|
||||
void EmotionEngine::mfc0(Opcode i)
|
||||
{
|
||||
regs[i.r_type.rt].u32[0] = cop0_regs[i.r_type.rd];
|
||||
regs[i.r_type.rt].u64[0] = cop0_regs[i.r_type.rd];
|
||||
printf("mfc0 %s, r%d\n", Reg(i.r_type.rt), i.r_type.rd);
|
||||
}
|
||||
|
||||
|
@ -82,6 +97,89 @@ void EmotionEngine::mtc0(Opcode i)
|
|||
printf("mtc0 %s, r%d\n", Reg(i.r_type.rt), i.r_type.rd);
|
||||
}
|
||||
|
||||
void EmotionEngine::beql(Opcode i)
|
||||
{
|
||||
int32_t imm = (int32_t)((uint32_t)i.i_type.imm << 2);
|
||||
|
||||
printf("beql %s, %s, 0x%08x\n", Reg(i.i_type.rs), Reg(i.i_type.rt), next_pc + imm);
|
||||
|
||||
if ((int32_t)regs[i.i_type.rs].u32[0] == (int32_t)regs[i.i_type.rt].u32[0])
|
||||
{
|
||||
next_pc = pc + imm;
|
||||
}
|
||||
else
|
||||
AdvancePC(); // Skip delay slot
|
||||
}
|
||||
|
||||
void EmotionEngine::bnel(Opcode i)
|
||||
{
|
||||
int32_t imm = (int32_t)((uint32_t)i.i_type.imm << 2);
|
||||
|
||||
bool taken = false;
|
||||
|
||||
if ((int32_t)regs[i.i_type.rs].u32[0] != (int32_t)regs[i.i_type.rt].u32[0])
|
||||
{
|
||||
next_pc = pc + imm;
|
||||
taken = true;
|
||||
}
|
||||
else
|
||||
AdvancePC(); // Skip delay slot
|
||||
|
||||
printf("bnel %s, %s, 0x%08x (%s)\n", Reg(i.i_type.rs), Reg(i.i_type.rt), pc + imm, taken ? "taken" : "");
|
||||
}
|
||||
|
||||
void EmotionEngine::lb(Opcode i)
|
||||
{
|
||||
int base = i.i_type.rs;
|
||||
int rt = i.i_type.rt;
|
||||
int16_t off = (int16_t)i.i_type.imm;
|
||||
|
||||
uint32_t addr = regs[base].u32[0] + off;
|
||||
|
||||
regs[rt].u64[0] = (int64_t)((uint8_t)(Read32(addr) & 0xFF));
|
||||
|
||||
printf("lb %s, %d(%s)\n", Reg(rt), off, Reg(base));
|
||||
}
|
||||
|
||||
void EmotionEngine::lw(Opcode i)
|
||||
{
|
||||
int base = i.i_type.rs;
|
||||
int rt = i.i_type.rt;
|
||||
int16_t off = (int16_t)i.i_type.imm;
|
||||
|
||||
uint32_t addr = regs[base].u32[0] + off;
|
||||
|
||||
regs[rt].u32[0] = bus->read<uint32_t>(addr);
|
||||
|
||||
printf("lw %s, %d(%s)\n", Reg(rt), off, Reg(base));
|
||||
}
|
||||
|
||||
void EmotionEngine::lbu(Opcode i)
|
||||
{
|
||||
int base = i.i_type.rs;
|
||||
int rt = i.i_type.rt;
|
||||
int16_t off = (int16_t)i.i_type.imm;
|
||||
|
||||
uint32_t addr = regs[base].u32[0] + off;
|
||||
|
||||
regs[rt].u64[0] = Read32(addr) & 0xFF;
|
||||
|
||||
printf("lbu %s, %d(%s)\n", Reg(rt), off, Reg(base));
|
||||
}
|
||||
|
||||
void EmotionEngine::sb(Opcode i)
|
||||
{
|
||||
int base = i.i_type.rs;
|
||||
int rt = i.i_type.rt;
|
||||
int16_t off = (int16_t)i.i_type.imm;
|
||||
|
||||
uint32_t addr = regs[base].u32[0] + off;
|
||||
|
||||
bus->write<uint8_t>(addr, regs[rt].u32[0] & 0xFF);
|
||||
|
||||
printf("sb %s, %d(%s)\n", Reg(rt), off, Reg(base));
|
||||
}
|
||||
|
||||
void EmotionEngine::sw(Opcode i)
|
||||
{
|
||||
int base = i.i_type.rs;
|
||||
|
@ -95,6 +193,32 @@ void EmotionEngine::sw(Opcode i)
|
|||
printf("sw %s, %d(%s)\n", Reg(rt), off, Reg(base));
|
||||
}
|
||||
|
||||
void EmotionEngine::ld(Opcode i)
|
||||
{
|
||||
int base = i.i_type.rs;
|
||||
int rt = i.i_type.rt;
|
||||
int16_t off = (int16_t)i.i_type.imm;
|
||||
|
||||
uint32_t addr = regs[base].u32[0] + off;
|
||||
|
||||
regs[rt].u64[0] = bus->read<uint64_t>(addr);
|
||||
|
||||
printf("ld %s, %d(%s)\n", Reg(rt), off, Reg(base));
|
||||
}
|
||||
|
||||
void EmotionEngine::swc1(Opcode i)
|
||||
{
|
||||
int base = i.i_type.rs;
|
||||
int rt = i.i_type.rt;
|
||||
int16_t off = (int16_t)i.i_type.imm;
|
||||
|
||||
uint32_t addr = regs[base].u32[0] + off;
|
||||
|
||||
Write32(addr, cop1.i[rt]);
|
||||
|
||||
printf("swc1 f%d, %d(%s)\n", rt, off, Reg(base));
|
||||
}
|
||||
|
||||
void EmotionEngine::sd(Opcode i)
|
||||
{
|
||||
int base = i.i_type.rs;
|
||||
|
@ -122,22 +246,43 @@ void EmotionEngine::sll(Opcode i)
|
|||
int rt = i.r_type.rt;
|
||||
int sa = i.r_type.sa;
|
||||
|
||||
regs[rd].u32[0] = regs[rt].u32[0] << sa;
|
||||
regs[rd].u64[0] = regs[rt].u32[0] << sa;
|
||||
|
||||
printf("sll %s, %s, %d\n", Reg(rd), Reg(rt), sa);
|
||||
}
|
||||
|
||||
void EmotionEngine::sra(Opcode i)
|
||||
{
|
||||
int rd = i.r_type.rd;
|
||||
int rt = i.r_type.rt;
|
||||
int sa = i.r_type.sa;
|
||||
|
||||
int32_t reg = (int32_t)regs[rt].u32[0];
|
||||
regs[rd].u64[0] = reg >> sa;
|
||||
|
||||
printf("sra %s, %s, %d\n", Reg(rd), Reg(rt), sa);
|
||||
}
|
||||
|
||||
void EmotionEngine::jalr(Opcode i)
|
||||
{
|
||||
int rs = i.r_type.rs;
|
||||
int rd = i.r_type.rd;
|
||||
|
||||
regs[rd].u32[0] = next_pc;
|
||||
regs[rd].u64[0] = next_pc;
|
||||
next_pc = regs[rs].u32[0];
|
||||
|
||||
printf("jalr %s, %s\n", Reg(rs), Reg(rd));
|
||||
}
|
||||
|
||||
void EmotionEngine::mflo(Opcode i)
|
||||
{
|
||||
int rd = i.r_type.rd;
|
||||
|
||||
regs[rd].u64[0] = lo;
|
||||
|
||||
printf("mflo %s\n", Reg(rd));
|
||||
}
|
||||
|
||||
void EmotionEngine::mult(Opcode i)
|
||||
{
|
||||
int rs = i.r_type.rs;
|
||||
|
@ -148,10 +293,29 @@ void EmotionEngine::mult(Opcode i)
|
|||
int64_t reg2 = (int64_t)regs[rt].u32[0];
|
||||
int64_t result = reg1 * reg2;
|
||||
|
||||
regs[rd].u32[0] = lo = (int32_t)(result & 0xFFFFFFFF);
|
||||
regs[rd].u64[0] = lo = (int32_t)(result & 0xFFFFFFFF);
|
||||
hi = (int32_t)(result >> 32);
|
||||
|
||||
printf("mult %s, %s, %s\n", Reg(rd), Reg(rs), Reg(rt));
|
||||
printf("mult %s, %s, %s (0x%08x, 0x%08x)\n", Reg(rd), Reg(rs), Reg(rt), hi, lo);
|
||||
}
|
||||
|
||||
void EmotionEngine::divu(Opcode i)
|
||||
{
|
||||
int rs = i.r_type.rs;
|
||||
int rt = i.r_type.rt;
|
||||
|
||||
if (regs[rt].u32[0] == 0)
|
||||
{
|
||||
hi = (int32_t)regs[rs].u32[0];
|
||||
lo = (int32_t)0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
hi = (int32_t)(regs[rs].u32[0] % regs[rt].u32[0]);
|
||||
lo = (int32_t)(regs[rs].u32[0] / regs[rt].u32[0]);
|
||||
}
|
||||
|
||||
printf("divu %s (0x%08x), %s (0x%08x) (0x%08x, 0x%08x)\n", Reg(rs), regs[rs].u32[0], Reg(rt), regs[rt].u32[0], hi, lo);
|
||||
}
|
||||
|
||||
void EmotionEngine::op_or(Opcode i)
|
||||
|
@ -160,7 +324,7 @@ void EmotionEngine::op_or(Opcode i)
|
|||
int rs = i.r_type.rs;
|
||||
int rt = i.r_type.rt;
|
||||
|
||||
regs[rd].u32[0] = regs[rt].u32[0] | regs[rs].u32[0];
|
||||
regs[rd].u64[0] = regs[rt].u32[0] | regs[rs].u32[0];
|
||||
|
||||
printf("or %s, %s, %s\n", Reg(rd), Reg(rt), Reg(rs));
|
||||
}
|
||||
|
@ -177,4 +341,19 @@ void EmotionEngine::daddu(Opcode i)
|
|||
regs[rd].u64[0] = reg1 + reg2;
|
||||
|
||||
printf("daddu %s, %s, %s\n", Reg(rd), Reg(rs), Reg(rt));
|
||||
}
|
||||
|
||||
void EmotionEngine::bltz(Opcode i)
|
||||
{
|
||||
int rs = i.i_type.rs;
|
||||
|
||||
int32_t val = (int32_t)regs[rs].u32[0];
|
||||
int32_t off = (int32_t)(i.i_type.imm << 2);
|
||||
|
||||
printf("bltz %s, 0x%08x\n", Reg(rs), pc + off);
|
||||
|
||||
if (val < 0)
|
||||
{
|
||||
next_pc = pc + off;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue