Commit a987b367 authored by George Hotz's avatar George Hotz

merge branch delay with next instruction

parent c2cb5b6a
...@@ -25,10 +25,6 @@ contract MIPS { ...@@ -25,10 +25,6 @@ contract MIPS {
uint32 constant public REG_HI = REG_OFFSET + 0x21*4; uint32 constant public REG_HI = REG_OFFSET + 0x21*4;
uint32 constant public REG_LO = REG_OFFSET + 0x22*4; uint32 constant public REG_LO = REG_OFFSET + 0x22*4;
uint32 constant public REG_HEAP = REG_OFFSET + 0x23*4; uint32 constant public REG_HEAP = REG_OFFSET + 0x23*4;
uint32 constant public REG_PENDPC = REG_OFFSET + 0x24*4;
uint32 constant public PC_PEND = 0x80000000;
uint32 constant public PC_MASK = 0x7FFFFFFF;
uint32 constant public HEAP_START = 0x20000000; uint32 constant public HEAP_START = 0x20000000;
uint32 constant public BRK_START = 0x40000000; uint32 constant public BRK_START = 0x40000000;
...@@ -105,31 +101,17 @@ contract MIPS { ...@@ -105,31 +101,17 @@ contract MIPS {
return (stateHash, exit); return (stateHash, exit);
} }
function branchDelay(bytes32 stateHash, uint32 pc, uint32 nextPC, bool link) internal returns (bytes32) {
if (link) {
stateHash = WriteMemory(stateHash, REG_LR, pc+4);
}
stateHash = WriteMemory(stateHash, REG_PENDPC, nextPC);
stateHash = WriteMemory(stateHash, REG_PC, PC_PEND | pc);
return stateHash;
}
// will revert if any required input state is missing
function Step(bytes32 stateHash) public returns (bytes32) { function Step(bytes32 stateHash) public returns (bytes32) {
// instruction fetch
uint32 pc = ReadMemory(stateHash, REG_PC); uint32 pc = ReadMemory(stateHash, REG_PC);
if (pc == 0x5ead0000) { if (pc == 0x5ead0000) {
return stateHash; return stateHash;
} }
return stepPC(stateHash, pc, pc+4);
}
uint32 nextPC; // will revert if any required input state is missing
if (pc & PC_PEND == 0) { function stepPC(bytes32 stateHash, uint32 pc, uint32 nextPC) internal returns (bytes32) {
nextPC = pc + 4; // instruction fetch
} else {
pc = pc & PC_MASK;
nextPC = ReadMemory(stateHash, REG_PENDPC);
}
uint32 insn = ReadMemory(stateHash, pc); uint32 insn = ReadMemory(stateHash, pc);
uint32 opcode = insn >> 26; // 6-bits uint32 opcode = insn >> 26; // 6-bits
...@@ -137,8 +119,12 @@ contract MIPS { ...@@ -137,8 +119,12 @@ contract MIPS {
// j-type j/jal // j-type j/jal
if (opcode == 2 || opcode == 3) { if (opcode == 2 || opcode == 3) {
return branchDelay(stateHash, nextPC, stateHash = stepPC(stateHash, nextPC,
SE(insn&0x03FFFFFF, 26) << 2, opcode == 3); SE(insn&0x03FFFFFF, 26) << 2);
if (opcode == 3) {
stateHash = WriteMemory(stateHash, REG_LR, pc+8);
}
return stateHash;
} }
// register fetch // register fetch
...@@ -204,11 +190,11 @@ contract MIPS { ...@@ -204,11 +190,11 @@ contract MIPS {
} }
if (shouldBranch) { if (shouldBranch) {
return branchDelay(stateHash, nextPC, return stepPC(stateHash, nextPC,
pc + 4 + (SE(insn&0xFFFF, 16)<<2), false); pc + 4 + (SE(insn&0xFFFF, 16)<<2));
} else { } else {
// branch not taken // branch not taken
return branchDelay(stateHash, nextPC, nextPC+4, false); return stepPC(stateHash, nextPC, nextPC+4);
} }
} }
...@@ -219,7 +205,11 @@ contract MIPS { ...@@ -219,7 +205,11 @@ contract MIPS {
if (opcode == 0 && func >= 8 && func < 0x1c) { if (opcode == 0 && func >= 8 && func < 0x1c) {
if (func == 8 || func == 9) { if (func == 8 || func == 9) {
// jr/jalr // jr/jalr
return branchDelay(stateHash, nextPC, rs, func == 9); stateHash = stepPC(stateHash, nextPC, rs);
if (func == 9) {
stateHash = WriteMemory(stateHash, REG_LR, pc+8);
}
return stateHash;
} }
// handle movz and movn when they don't write back // handle movz and movn when they don't write back
......
...@@ -27,6 +27,7 @@ func TestCompare(t *testing.T) { ...@@ -27,6 +27,7 @@ func TestCompare(t *testing.T) {
steps := 10000000 steps := 10000000
//steps := 1165 //steps := 1165
//steps := 1180 //steps := 1180
//steps := 24
cevm := make(chan []uint32, 1) cevm := make(chan []uint32, 1)
cuni := make(chan []uint32, 1) cuni := make(chan []uint32, 1)
...@@ -51,6 +52,7 @@ func TestCompare(t *testing.T) { ...@@ -51,6 +52,7 @@ func TestCompare(t *testing.T) {
done.Unlock() done.Unlock()
}) })
mismatch := false
for i := 0; i < steps; i++ { for i := 0; i < steps; i++ {
x, y := <-cevm, <-cuni x, y := <-cevm, <-cuni
if x[0] == 0x5ead0000 && y[0] == 0x5ead0000 { if x[0] == 0x5ead0000 && y[0] == 0x5ead0000 {
...@@ -63,15 +65,17 @@ func TestCompare(t *testing.T) { ...@@ -63,15 +65,17 @@ func TestCompare(t *testing.T) {
for j := 0; j < len(x); j++ { for j := 0; j < len(x); j++ {
if x[j] != y[j] { if x[j] != y[j] {
fmt.Println(i, "mismatch at", j, "cevm", x, "cuni", y) fmt.Println(i, "mismatch at", j, "cevm", x, "cuni", y)
break mismatch = true
} }
} }
if mismatch {
break
}
} }
// final ram check // final ram check
done.Lock() done.Lock()
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
mismatch := false
for k, v := range ram { for k, v := range ram {
if uniram[k] != v { if uniram[k] != v {
fmt.Printf("ram mismatch at %x, evm %x != uni %x\n", k, v, uniram[k]) fmt.Printf("ram mismatch at %x, evm %x != uni %x\n", k, v, uniram[k])
......
...@@ -58,73 +58,10 @@ func SE(dat uint32, idx uint32) uint32 { ...@@ -58,73 +58,10 @@ func SE(dat uint32, idx uint32) uint32 {
return ret return ret
} }
// UGH: is there a better way?
// I don't see a better way to get this out
func FixBranchDelay(ram map[uint32](uint32)) {
pc := ram[REG_PC] & 0x7FFFFFFF
insn := ram[pc-4]
opcode := insn >> 26
mfunc := insn & 0x3f
//fmt.Println(opcode)
//fmt.Printf("%d %x: %x\n", steps, pc-4, insn)
//fmt.Println(pc, opcode, mfunc)
// FIX SC
/*if opcode == 0x38 {
rt := ram[REG_OFFSET+((insn>>14)&0x7C)]
rs := ram[REG_OFFSET+((insn>>19)&0x7C)]
SignExtImm := SE(insn&0xFFFF, 16)
rs += SignExtImm
fmt.Printf("SC @ steps %d writing %x at %x\n", steps, rt, rs)
WriteRam(ram, rs, rt)
}*/
if opcode == 2 || opcode == 3 {
WriteRam(ram, REG_PENDPC, SE(insn&0x03FFFFFF, 26)<<2)
WriteRam(ram, REG_PC, ram[REG_PC]|0x80000000)
return
}
rs := ram[REG_OFFSET+((insn>>19)&0x7C)]
if (opcode >= 4 && opcode < 8) || opcode == 1 {
shouldBranch := false
if opcode == 4 || opcode == 5 {
rt := ram[REG_OFFSET+((insn>>14)&0x7C)]
shouldBranch = (rs == rt && opcode == 4) || (rs != rt && opcode == 5)
} else if opcode == 6 {
shouldBranch = int32(rs) <= 0
} else if opcode == 7 {
shouldBranch = int32(rs) > 0
} else if opcode == 1 {
rtv := ((insn >> 16) & 0x1F)
if rtv == 0 {
shouldBranch = int32(rs) < 0
} else if rtv == 1 {
shouldBranch = int32(rs) >= 0
}
}
WriteRam(ram, REG_PC, ram[REG_PC]|0x80000000)
if shouldBranch {
WriteRam(ram, REG_PENDPC, pc+(SE(insn&0xFFFF, 16)<<2))
} else {
WriteRam(ram, REG_PENDPC, pc+4)
}
}
if opcode == 0 && (mfunc == 8 || mfunc == 9) {
WriteRam(ram, REG_PC, ram[REG_PC]|0x80000000)
WriteRam(ram, REG_PENDPC, rs)
}
}
/*func rawAccess(p unsafe.Pointer, len int) []byte {
return (*(*[8440]byte)(p))[:len]
}*/
func SyncRegs(mu uc.Unicorn, ram map[uint32](uint32)) { func SyncRegs(mu uc.Unicorn, ram map[uint32](uint32)) {
pc, _ := mu.RegRead(uc.MIPS_REG_PC) pc, _ := mu.RegRead(uc.MIPS_REG_PC)
//fmt.Printf("%d uni %x\n", step, pc) //fmt.Printf("%d uni %x\n", step, pc)
WriteRam(ram, 0xc0000080, uint32(pc)) WriteRam(ram, 0xc0000080, uint32(pc))
FixBranchDelay(ram)
addr := uint32(0xc0000000) addr := uint32(0xc0000000)
for i := uc.MIPS_REG_ZERO; i < uc.MIPS_REG_ZERO+32; i++ { for i := uc.MIPS_REG_ZERO; i < uc.MIPS_REG_ZERO+32; i++ {
...@@ -133,28 +70,6 @@ func SyncRegs(mu uc.Unicorn, ram map[uint32](uint32)) { ...@@ -133,28 +70,6 @@ func SyncRegs(mu uc.Unicorn, ram map[uint32](uint32)) {
addr += 4 addr += 4
} }
/*ctx, _ := mu.ContextSave(nil)
ptr := rawAccess(unsafe.Pointer(*ctx), 8440)
fmt.Println(ctx)*/
// TODO: this is broken
/*for i := 0; i < 1000; i++ {
tst, _ := mu.RegRead(i)
if tst == uint64(0x3b9ac9ff) {
fmt.Println("LOW HIT", i)
}
if tst == uint64(0xc4653600) {
fmt.Println("HI HIT", i)
}
}*/
/*hflags, _ := mu.RegRead(uc.MIPS_REG_W1)
pendpc, _ := mu.RegRead(uc.MIPS_REG_W0)
fmt.Println(pendpc, hflags)
if pendpc != 0 && pc != pendpc {
WriteRam(ram, REG_PC, uint32(pc)|0x80000000)
WriteRam(ram, REG_PENDPC, uint32(pendpc))
}*/
reg_hi, _ := mu.RegRead(uc.MIPS_REG_HI) reg_hi, _ := mu.RegRead(uc.MIPS_REG_HI)
reg_lo, _ := mu.RegRead(uc.MIPS_REG_LO) reg_lo, _ := mu.RegRead(uc.MIPS_REG_LO)
WriteRam(ram, REG_OFFSET+0x21*4, uint32(reg_hi)) WriteRam(ram, REG_OFFSET+0x21*4, uint32(reg_hi))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment