Gopher2600/disassembly/linear.go
steve c59a4a2dde o debugger
- RAM command now has CART option. displays any additional RAM the
	cartridge may have

o cartridge
    - implemented RAM() command. returns copy of RAM array
    - save/restore banks functions are now save/restore state and deal
	with cartridge RAM in addition to bank information

o debugger/memory
    - better error messages for peek and poke
2020-01-05 18:58:36 +00:00

45 lines
1.5 KiB
Go

package disassembly
import (
"gopher2600/hardware/cpu"
"gopher2600/hardware/cpu/result"
)
// linearDisassembly decodes every possible address in the cartridge. if the
// "execution" of the address succeeds it is stored in the linear table.
//
// compared to flowDisassembly, this form of disassembly takes into account
// areas of the cartridge that are unreachable when simply looking at where
// flow constructs take us. for instance, calling RTS with manually stacked
// return addresses are undetectable with flowDisassembly but linearDisassembly
// doesn't mind. self modifying code is still invisible.
//
// the downside of this method is that a lot of addresses in data segments will
// also be deemed to be valid instructions; so linear disassembly is no good
// for presenting the entire program.
func (dsm *Disassembly) linearDisassembly(mc *cpu.CPU) error {
for bank := 0; bank < len(dsm.linear); bank++ {
for address := dsm.Cart.Origin(); address <= dsm.Cart.Memtop(); address++ {
if err := dsm.Cart.SetBank(address, bank); err != nil {
return err
}
mc.PC.Load(address)
// deliberately ignoring errors
r, _ := mc.ExecuteInstruction(func(*result.Instruction) error { return nil })
// check validity of instruction result and add if it "executed"
// correctly
if r != nil && r.IsValid() == nil {
dsm.linear[bank][address&disasmMask] = Entry{
style: result.StyleBrief,
instruction: r.GetString(dsm.Symtable, result.StyleBrief),
instructionDefinition: r.Defn}
}
}
}
return nil
}