// SwatInsAnal.bcpl - Routines for analyzing Alto instructions
// Copyright Xerox Corporation 1979, 1981, 1982
// Last modified March 21, 1982 2:10 PM by Boggs
// All you have to do is...07/25/73 (alb)
get "Swat.decl"
external
[
// outgoing procedures
SymbolicInst; EffAddr; BuildSI
// incoming procedures
VMFetch; ReportFail; AddrToSym
Ws; PutTemplate; Puts; Zero
// incoming statics
dsp; xmFlag
]
structure OP: // instruction fields
[
[
alu bit 1
acSrc bit 2
acDest bit 2
aluFn bit 3
shift bit 2
carry bit 2
noLoad bit 1
skip bit 3
] =
[
f1 bit 3
f2 bit 2 = ac bit 2
indir bit 1
index bit 2
disp bit 8
]
]
structure SI: // Simulated Instruction
[
instr word // simulating instruction
doItRtn word // 0: default, 1: jmp, 2: bri
simRtn word // simulation routine dispatch (small integer)
disp word // sign extended displacement
eaReg word // 0, or -> trapAdd, trapAC2, or AC3
indir word // number of times to indirect (0-2)
]
compileif size SI/16 ne 6 then
[ Error("Change lenSI declaration in Swat.decl") ]
manifest
[
// SI.sim values -- *** known to SwatResident.asm ***
simMRIALU = 0 // Memory Reference and Arithmetic Logical instrs
simJmp = 1
simJsr = 2
simDirs = 3
simBRI = 4
// SI.doIt values -- *** known to SwatResident.asm ***
doItDefault = 0
doItJmp = 1
doItBRI = 2
]
//----------------------------------------------------------------------------
let EffAddr(instr, addr, returnIfNoEA; numargs na) = valof
//----------------------------------------------------------------------------
[
let disp = Displacement(instr)
test (instr & 177400B) eq 64400B //JSRII
ifso resultis VMFetch(VMFetch(disp+addr))
ifnot test (instr & 177400B) eq 65000B //JSRIS
ifso resultis VMFetch(VMFetch(disp+VMFetch(userAC2)))
ifnot
[
if instr<<OP.f1 gr 2 test na ge 3 & returnIfNoEA
ifso resultis -1
ifnot ReportFail("Instruction has no effective address")
let ea = disp + selecton instr<<OP.index into
[
case 0: 0
case 1: addr
case 2: VMFetch(userAC2)
case 3: VMFetch(userAC3)
]
if instr<<OP.indir eq 1 then ea = VMFetch(ea)
resultis ea
]
]
//----------------------------------------------------------------------------
and BuildSI(si, instr) be
//----------------------------------------------------------------------------
// Builds an SI structure at si to simulate the execution of instr
[
Zero(si, lenSI)
si>>SI.instr = 401b //jmp .+1
si>>SI.doItRtn = doItDefault
si>>SI.disp = Displacement(instr)
si>>SI.eaReg = selecton instr<<OP.index into
[
case 0: 0
case 1: userPC
case 2: userAC2
case 3: userAC3
]
switchon instr<<OP.f1 into
[
case 0: // jmp, jsr, isz, dsz
[
switchon instr<<OP.f2 into
[
case 0: // jmp
[
si>>SI.simRtn = simJmp
endcase
]
case 1: // jsr
[
si>>SI.simRtn = simJsr
endcase
]
case 2: // isz
case 3: // dsz
[
si>>SI.simRtn = simMRIALU
si>>SI.instr = (instr & 74000b) + 2405b //op @.+5
endcase
]
]
si>>SI.indir = instr<<OP.indir
endcase
]
case 1: // lda
case 2: // sta
[
si>>SI.simRtn = simMRIALU
si>>SI.instr = (instr & 74000b) + 2405b //op @.+5
si>>SI.indir = instr<<OP.indir
endcase
]
case 4 to 7: // alu
[
si>>SI.simRtn = simMRIALU
si>>SI.instr = instr
endcase
]
// BuildSI (cont'd)
case 3: // special Alto instructions
[
let i = instr & 77400b
test i eq 64400b % i eq 65000b // jsrii, jsris
ifso
[
si>>SI.simRtn = simJsr
si>>SI.indir = 2
]
ifnot switchon instr into
[
case 61000b: // dir
[
si>>SI.doItRtn = doItJmp
endcase
]
case 61001b: // eir
[
si>>SI.doItRtn = doItBRI
endcase
]
case 61002b: // bri
[
si>>SI.simRtn = simBRI
si>>SI.doItRtn = doItBRI
endcase
]
case 61013b: // dirs
[
si>>SI.simRtn = simDirs
si>>SI.doItRtn = doItJmp
endcase
]
default: // simMRIALU works for the rest of them
[
si>>SI.simRtn = simMRIALU
// don't re-execute traps
unless i eq 77400b do si>>SI.instr = instr
if xmFlag & ((instr & xJmpInstMask) eq xJmp0) then
ReportFail("I Can't simulate xJmp instructions")
endcase
]
]
endcase
]
]
]
//----------------------------------------------------------------------------
and SymbolicInst(instr, addr) be
//----------------------------------------------------------------------------
// Print instr as an Alto instruction assuming it resides at addr.
[
PutTemplate(dsp, "$6UO ", instr)
test instr<<OP.alu eq 1
ifso
[
Ws(selecton instr<<OP.aluFn into
[
case 0:"com"
case 1:"neg"
case 2:"mov"
case 3:"inc"
case 4:"adc"
case 5:"sub"
case 6:"add"
case 7:"and"
])
Ws(selecton instr<<OP.carry into
[
case 0:""
case 1:"z"
case 2:"o"
case 3:"c"
])
Ws(selecton instr<<OP.shift into
[
case 0:""
case 1:"l"
case 2:"r"
case 3:"s"
])
if instr<<OP.noLoad ne 0 then Puts(dsp, $#)
PutTemplate(dsp, " $O $O ", instr<<OP.acSrc, instr<<OP.acDest)
Ws(selecton instr<<OP.skip into
[
case 0:""
case 1:"skp"
case 2:"szc"
case 3:"snc"
case 4:"szr"
case 5:"snr"
case 6:"sez"
case 7:"sbn"
])
// SymbolicInst (Cont'd)
test instr<<OP.skip eq 0
ifso if instr<<OP.acSrc eq instr<<OP.acDest then
PutTemplate(dsp, selecton instr & 103777b into //ignore ACs
[
case 102520b: "; AC$O ← 1"
case 102000b: "; AC$O ← -1"
case 102400b: "; AC$O ← 0"
default: ""
], instr<<OP.acSrc)
ifnot PutTemplate(dsp, selecton instr & 103767b into //ignore ACs,nl
[
case 102023b: "$S$O uls AC$O"
case 102423b: "$S$O ule AC$O"
case 102422b: "$S$O ugr AC$O"
case 102022b: "$S$O uge AC$O"
case 102102b: case 102122b: "$S$O ls AC$O"
case 102502b: case 102522b: "$S$O le AC$O"
case 102503b: case 102523b: "$S$O gr AC$O"
case 102103b: case 102123b: "$S$O ge AC$O"
case 102405b: "$S$O ne AC$O"
case 102404b: "$S$O eq AC$O"
case 101103b: "$S$O ls 0"
case 100502b: "$S$O le 0"
case 100503b: "$S$O gr 0"
case 101102b: "$S$O ge 0"
case 101005b: "$S$O ne 0"
case 101004b: "$S$O eq 0"
case 100005b: "$S$O ne -1"
case 100004b: "$S$O eq -1"
case 101202b: "$S$O even"
case 101203b: "$S$O odd"
default: ""
], "; Skip if AC", instr<<OP.acSrc, instr<<OP.acDest)
]
// SymbolicInst (Cont'd)
ifnot switchon instr<<OP.f1 into
[
case 0:
[
Ws(selecton instr<<OP.f2 into
[
case 0:"jmp "
case 1:"jsr "
case 2:"isz "
case 3:"dsz "
])
PrintAddress(instr, addr)
endcase
]
case 1:
[
PutTemplate(dsp, "lda $O ", instr<<OP.ac)
PrintAddress(instr, addr)
endcase
]
case 2:
[
PutTemplate(dsp, "sta $O ", instr<<OP.ac)
PrintAddress(instr, addr)
endcase
]
case 3:
[
Ws(selecton instr into
[
case 61000b: "dir"
case 61001b: "eir"
case 61002b: "bri"
case 61003b: "rclk"
case 61004b: "sio"
case 61005b: "blt"
case 61006b: "blks"
case 61007b: "sit"
case 61010b: "jmpram"
case 61011b: "rdram"
case 61012b: "wrtram"
case 61013b: "dirs"
case 61014b: "vers"
case 61015b: "dread"
case 61016b: "dwrite"
case 61017b: "dexch"
case 61020b: "mul"
case 61021b: "div"
case 61022b: "diagnose1"
case 61023b: "diagnose2"
case 61024b: "bitblt"
case 61025b: "xmlda"
case 61026b: "xmsta"
case 61037b: "setdefaultdisk"
case 61040b: "doradoin"
case 61041b: "doradoout"
case 61042b: "doradohalt"
case 61043b: "setpchist"
case 64034b: "xjmp0"
case 64035b: "xjmp1"
case 64036b: "xjmp2"
case 64037b: "xjmp3"
default: ""
])
switchon instr & 77400b into
[
case 60000b: [ PutTemplate(dsp, "cycle $O", instr&17B); endcase ]
case 64400b: [ Ws("jsrii"); PrintAddress(instr, addr); endcase ]
case 65000b: [ Ws("jsris"); PrintAddress(instr, addr); endcase ]
case 67000b: [ PutTemplate(dsp, "convert $P", SignedDisp, instr) ]
]
endcase
]
]
]
//----------------------------------------------------------------------------
and PrintAddress(instr, addr) be
//----------------------------------------------------------------------------
// Prints jump and memory reference addresses
[
if instr<<OP.indir eq 1 then Puts(dsp, $@)
switchon instr<<OP.index into
[
case 0: // page zero
[
PutTemplate(dsp, "$O", instr<<OP.disp)
endcase
]
case 1: // pc relative
[
PutTemplate(dsp, ".$P", SignedDisp, instr)
endcase
]
case 2: // ac2 relative
case 3: // ac3 relative
[
PutTemplate(dsp, "$O,$O", Displacement(instr), instr<<OP.index)
endcase
]
]
let effAdd = EffAddr(instr, addr)
PutTemplate(dsp, " -> $P: $UO", AddrToSym, effAdd, VMFetch(effAdd))
]
//----------------------------------------------------------------------------
and Displacement(instr) = (instr<<OP.index eq 0? instr<<OP.disp,
(instr<<OP.disp + (instr<<OP.disp ge 200b? 177400b, 0)))
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
and SignedDisp(stream, instr) be
//----------------------------------------------------------------------------
[
let disp = Displacement(instr)
PutTemplate(stream, "$S$O", (disp ge 0? "+", ""), disp)
]