Commit a987b367 authored by George Hotz's avatar George Hotz

merge branch delay with next instruction

parent c2cb5b6a
......@@ -25,10 +25,6 @@ contract MIPS {
uint32 constant public REG_HI = REG_OFFSET + 0x21*4;
uint32 constant public REG_LO = REG_OFFSET + 0x22*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 BRK_START = 0x40000000;
......@@ -105,31 +101,17 @@ contract MIPS {
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) {
// instruction fetch
uint32 pc = ReadMemory(stateHash, REG_PC);
if (pc == 0x5ead0000) {
return stateHash;
}
return stepPC(stateHash, pc, pc+4);
}
uint32 nextPC;
if (pc & PC_PEND == 0) {
nextPC = pc + 4;
} else {
pc = pc & PC_MASK;
nextPC = ReadMemory(stateHash, REG_PENDPC);
}
// will revert if any required input state is missing
function stepPC(bytes32 stateHash, uint32 pc, uint32 nextPC) internal returns (bytes32) {
// instruction fetch
uint32 insn = ReadMemory(stateHash, pc);
uint32 opcode = insn >> 26; // 6-bits
......@@ -137,8 +119,12 @@ contract MIPS {
// j-type j/jal
if (opcode == 2 || opcode == 3) {
return branchDelay(stateHash, nextPC,
SE(insn&0x03FFFFFF, 26) << 2, opcode == 3);
stateHash = stepPC(stateHash, nextPC,
SE(insn&0x03FFFFFF, 26) << 2);
if (opcode == 3) {
stateHash = WriteMemory(stateHash, REG_LR, pc+8);
}
return stateHash;
}
// register fetch
......@@ -204,11 +190,11 @@ contract MIPS {
}
if (shouldBranch) {
return branchDelay(stateHash, nextPC,
pc + 4 + (SE(insn&0xFFFF, 16)<<2), false);
return stepPC(stateHash, nextPC,
pc + 4 + (SE(insn&0xFFFF, 16)<<2));
} else {
// branch not taken
return branchDelay(stateHash, nextPC, nextPC+4, false);
return stepPC(stateHash, nextPC, nextPC+4);
}
}
......@@ -219,7 +205,11 @@ contract MIPS {
if (opcode == 0 && func >= 8 && func < 0x1c) {
if (func == 8 || func == 9) {
// 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
......
......@@ -27,6 +27,7 @@ func TestCompare(t *testing.T) {
steps := 10000000
//steps := 1165
//steps := 1180
//steps := 24
cevm := make(chan []uint32, 1)
cuni := make(chan []uint32, 1)
......@@ -51,6 +52,7 @@ func TestCompare(t *testing.T) {
done.Unlock()
})
mismatch := false
for i := 0; i < steps; i++ {
x, y := <-cevm, <-cuni
if x[0] == 0x5ead0000 && y[0] == 0x5ead0000 {
......@@ -63,15 +65,17 @@ func TestCompare(t *testing.T) {
for j := 0; j < len(x); j++ {
if x[j] != y[j] {
fmt.Println(i, "mismatch at", j, "cevm", x, "cuni", y)
break
mismatch = true
}
}
if mismatch {
break
}
}
// final ram check
done.Lock()
time.Sleep(100 * time.Millisecond)
mismatch := false
for k, v := range ram {
if uniram[k] != v {
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 {
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)) {
pc, _ := mu.RegRead(uc.MIPS_REG_PC)
//fmt.Printf("%d uni %x\n", step, pc)
WriteRam(ram, 0xc0000080, uint32(pc))
FixBranchDelay(ram)
addr := uint32(0xc0000000)
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)) {
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_lo, _ := mu.RegRead(uc.MIPS_REG_LO)
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