Simpler approach for Applecorn trace, no reentrancy

This commit is contained in:
Ivan Izaguirre 2021-07-24 19:41:53 +02:00
parent 612adbc11f
commit 3b56312d9c
1 changed files with 36 additions and 43 deletions

View File

@ -2,7 +2,6 @@ package izapple2
import ( import (
"fmt" "fmt"
"strings"
) )
/* /*
@ -19,19 +18,20 @@ type traceApplecorn struct {
a *Apple2 a *Apple2
skipConsole bool skipConsole bool
osbyteNames [256]string osbyteNames [256]string
calls []mosCallData call mosCallData
lastDepth int lastDepth int
wasInKernel bool
} }
type mosCallData struct { type mosCallData struct {
caller uint16
api uint16 api uint16
a, x, y uint8 a, x, y uint8
skipLog bool
} }
const ( const (
applecornMosVec uint16 = 0xffb9 // Start of the MOS entry points applecornKernelStart uint16 = 0xc000 // Code above this is out of BBC territory
applecornNoCaller uint16 = 0xffff applecornNoCaller uint16 = 0xffff
) )
func newTraceApplecorn(a *Apple2, skipConsole bool) *traceApplecorn { func newTraceApplecorn(a *Apple2, skipConsole bool) *traceApplecorn {
@ -48,16 +48,17 @@ func newTraceApplecorn(a *Apple2, skipConsole bool) *traceApplecorn {
t.osbyteNames[0x85] = "top user mem for mode" t.osbyteNames[0x85] = "top user mem for mode"
t.osbyteNames[0x86] = "read cursor pos" t.osbyteNames[0x86] = "read cursor pos"
t.osbyteNames[0xDA] = "clear VDU queue" t.osbyteNames[0xDA] = "clear VDU queue"
t.calls = make([]mosCallData, 0)
return &t return &t
} }
func (t *traceApplecorn) inspect() { func (t *traceApplecorn) inspect() {
pc, sp := t.a.cpu.GetPCAndSP() pc, _ := t.a.cpu.GetPCAndSP()
if pc >= 0xd000 /*applecornMosVec*/ { inKernel := pc >= applecornKernelStart
regA, regX, regY := t.a.cpu.GetAXY()
s := "" if !t.wasInKernel && inKernel {
regA, regX, regY, _ := t.a.cpu.GetAXYP()
s := "UNKNOWN"
skip := false skip := false
// Page 2 vectors // Page 2 vectors
@ -123,17 +124,15 @@ func (t *traceApplecorn) inspect() {
case 0xffe0: case 0xffe0:
s = fmt.Sprintf("OSRDCH()") s = fmt.Sprintf("OSRDCH()")
skip = t.skipConsole skip = t.skipConsole
/* case 0xffe3: // This fallbacks to OSWRCH
case 0xffe3: // This fallbacks to OSWRCH s = "OSASCI(?)"
s = "OSASCI(?)" skip = t.skipConsole
skip = t.skipConsole case 0xffe7: // This fallbacks to OSWRCH
case 0xffe7: // This fallbacks to OSWRCH s = fmt.Sprintf("OSNEWL()")
s = fmt.Sprintf("OSNEWL()") skip = t.skipConsole
skip = t.skipConsole case 0xffec: // This fallbacks to OSWRCH
case 0xffec: // This fallbacks to OSWRCH skip = t.skipConsole
skip = t.skipConsole s = fmt.Sprintf("OSNECR()")
s = fmt.Sprintf("OSNECR()")
*/
case 0xffee: case 0xffee:
ch := "" ch := ""
if regA >= 0x20 && regA < 0x7f { if regA >= 0x20 && regA < 0x7f {
@ -153,48 +152,42 @@ func (t *traceApplecorn) inspect() {
} }
case 0xfff4: case 0xfff4:
s = fmt.Sprintf("OSBYTE('%s';A=%02x,X=%02x,Y=%02x)", t.osbyteNames[regA], regA, regX, regY) s = fmt.Sprintf("OSBYTE('%s';A=%02x,X=%02x,Y=%02x)", t.osbyteNames[regA], regA, regX, regY)
//if regA == 0xda {
// t.a.cpu.Reset()
//}
case 0xfff7: case 0xfff7:
s = "OSCLI(?)" s = "OSCLI(?)"
} }
if !skip && s != "" { t.call.api = pc
caller := t.a.mmu.peekWord(0x100+uint16(sp+1)) + 1 t.call.a = regA
t.calls = append(t.calls, mosCallData{caller, pc, regA, regX, regY}) t.call.x = regX
if len(t.calls) > t.lastDepth { t.call.y = regY
// Reentrant call, first of block t.call.skipLog = skip
fmt.Println() if !skip {
}
if len(t.calls) > 1 {
// Reentrant call
fmt.Printf("%s", strings.Repeat(" ", len(t.calls)))
}
fmt.Printf("BBC MOS call to $%04x %s ", pc, s) fmt.Printf("BBC MOS call to $%04x %s ", pc, s)
t.lastDepth = len(t.calls)
} }
} }
if len(t.calls) > 0 && pc == t.calls[len(t.calls)-1].caller { if t.wasInKernel && !inKernel && !t.call.skipLog {
// Returning from the call // Returning from the call
regA, regX, regY := t.a.cpu.GetAXY() regA, regX, regY, _ := t.a.cpu.GetAXYP()
call := t.calls[len(t.calls)-1]
s := "" s := ""
switch call.api { switch t.call.api {
case 0xfff1: // OSWORD case 0xfff1: // OSWORD
cbAddress := uint16(call.x) + uint16(call.y)<<8 cbAddress := uint16(t.call.x) + uint16(t.call.y)<<8
switch call.a { switch t.call.a {
case 0: // Read line from input case 0: // Read line from input
lineAddress := t.a.mmu.peekWord(cbAddress) lineAddress := t.a.mmu.peekWord(cbAddress)
line := t.getString(lineAddress, regY) line := t.getString(lineAddress, regY)
s = fmt.Sprintf(",line='%s'", line) s = fmt.Sprintf(",line='%s'", line)
t.a.cpu.SetTrace(true)
} }
} }
fmt.Printf("=> (A=%02x,X=%02x,Y=%02x%s)\n", regA, regX, regY, s) fmt.Printf("=> (A=%02x,X=%02x,Y=%02x%s)\n", regA, regX, regY, s)
t.calls = t.calls[:len(t.calls)-1]
} }
t.wasInKernel = inKernel
} }
func (t *traceApplecorn) getString(address uint16, length uint8) string { func (t *traceApplecorn) getString(address uint16, length uint8) string {