123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861 |
- package main
-
- import (
- "fmt"
- "math"
- "os"
- // "sort"
- "code.beefchicken.com/keelan/68kdisasm"
- "encoding/json"
- "path/filepath"
- "strings"
- )
-
- const (
- bytesPerDisassemblyLine = 9
- )
-
- type romInfo struct {
- Roms []struct {
- File string `json:"file"`
- Start string `json:"start"`
- End string `json:"end"`
- Version string `json:"version"`
- Device string `json:"device"`
- Checksum string `json:"checksum"`
- } `json:"roms"`
- Labels []struct {
- Address string `json:"address"`
- Label string `json:"label"`
- } `json:"labels"`
- }
-
- type memBlock struct {
- lowFile string
- highFile string
- start uint32
- end uint32
- }
-
- type output struct {
- mnemonic string
- operands string
- comment string
-
- // these are used for "INLINE" only
- startPC uint32
- endPC uint32
- }
-
- type call struct {
- function uint32
- instrAddr uint32
- computedAddr uint32
- targetAddr uint32
- native bool
- }
-
- func main() {
-
- if len(os.Args) < 2 {
- die("Usage: %s <path to rom directory>\n", os.Args[0])
- }
-
- romDir := os.Args[1]
-
- romMapFilename := filepath.Join(romDir, "map.json")
- b, _ := os.ReadFile(romMapFilename)
-
- fmt.Printf("Loading ROM info from '%s'...\n", romMapFilename)
-
- info := &romInfo{}
- err := json.Unmarshal(b, &info)
- if err != nil {
- die("Unable to load rom map from '%s': %v\n", romMapFilename, err)
- }
-
- d := NewDisassembler()
-
- for _, rom := range info.Roms {
-
- var start, end uint32
- var checksum int
-
- _, err := fmt.Sscanf(rom.Start, "0x%X", &start)
- if err != nil {
- die("Unable to parse start address '%s' for rom '%s'!\n", rom.Start, rom.File)
- }
-
- _, err = fmt.Sscanf(rom.End, "0x%X", &end)
- if err != nil {
- die("Unable to parse end address '%s' for rom '%s'!\n", rom.End, rom.File)
- }
-
- _, err = fmt.Sscanf(rom.Checksum, "0x%X", &checksum)
- if err != nil {
- die("Unable to checksum '%s' for rom '%s'!\n", rom.Checksum, rom.File)
- }
-
- file := filepath.Join(romDir, rom.File)
-
- fmt.Printf("Loading '%s' (0x%06X-0x%06X)...\n", file, start, end)
-
- d.AddRom(file, start, end, checksum)
-
- }
-
- for _, label := range info.Labels {
-
- var address uint32
- _, err := fmt.Sscanf(label.Address, "0x%X", &address)
- if err != nil {
- die("Unable to parse address '%s' for label '%s!\n", label.Address, label.Label)
- }
- fmt.Printf("Adding label %s = 0x%06X\n", label.Label, address)
- d.AddLabel(address, label.Label)
-
- }
-
- // look for the three kinds of header functions and queue
- // the vm code up for disassembly
- queue := []uint32{}
- for _, block := range d.roms {
- for i := block.start; i <= block.end-3; i++ {
- inst := d.read32(i)
- if inst == 0x4EB82144 || inst == 0x4EB82164 || inst == 0x4EB82102 {
- queue = append(queue, i)
- }
- }
- }
-
- dests := make(map[uint32][]call)
-
- // first pass to gather all of the JSR.68Ks
- for _, addr := range queue {
- externs, _ := d.disassemble(addr, nil, true)
- for _, c := range externs {
- if !c.native {
- dests[c.targetAddr] = append(dests[c.targetAddr], c)
- }
- }
- }
-
- // disassemble with output
- for _, vpc := range queue {
- d.disassemble(vpc, dests, false)
- }
-
- }
-
- func die(format string, a ...any) {
- fmt.Printf(format, a...)
- os.Exit(1)
- }
-
- type disassembler struct {
- pc uint32
- labels map[uint32]string
- roms []*memBlock
- prog []byte
- caseStmts map[uint32]caseStmt
- }
-
- type caseStmt struct {
- switchAddr uint32
- keys []byte
- }
-
- func NewDisassembler() *disassembler {
- return &disassembler{
- labels: make(map[uint32]string),
- roms: make([]*memBlock, 0),
- prog: make([]byte, 0),
- caseStmts: make(map[uint32]caseStmt),
- }
- }
-
- func (d *disassembler) AddLabel(addr uint32, l string) {
- d.labels[addr] = l
- }
-
- func addx(x, y uint16, xf *uint16) uint16 {
- t := x + y + *xf
- if int(t) < int(x)+int(y)+int(*xf) {
- *xf = 1
- } else {
- *xf = 0
- }
- return t
- }
-
- func (d *disassembler) AddRom(file string, start uint32, end uint32, checksum int) error {
-
- // grow memory
- // yes this is inefficient with firmware that has sparse allocation, but for the 4000SX
- // it works fine.
- if len(d.prog) < int(end)+1 {
- newProg := make([]byte, end+1)
- copy(newProg, d.prog)
- d.prog = newProg
- }
-
- b, err := os.ReadFile(file)
- if err != nil {
- return err
- }
-
- var softCS, hardCS, xflag uint16
-
- for i := 0; i < len(b); i++ {
- d.prog[int(start)+i*2] = b[i]
- if i < len(b)-4 {
- softCS = addx(uint16(b[i]), softCS, &xflag)
- }
- hardCS += uint16(b[i])
- }
- softCS = ^softCS
-
- internalStoredChecksum := uint16(b[len(b)-1])<<8 + uint16(b[len(b)-2])
-
- // the 'soft' checksum is the one the receiver checks on boot
- fmt.Printf("%s Soft Checksum: got 0x%04X expected 0x%04X\n", file, softCS, internalStoredChecksum)
-
- // the 'hard' checksum is the one printed on the label on the EPROM
- fmt.Printf("%s Hard Checksum: got 0x%04X expected 0x%04X\n", file, hardCS, checksum)
-
- // check if we've already loaded the partner for this rom
- var block *memBlock
- for _, rom := range d.roms {
- if start&0xFFFFFFFE == rom.start&0xFFFFFFFE {
- block = rom
- if start < block.start {
- block.start = start
- }
- if end > block.end {
- block.end = end
- }
- break
- }
- }
-
- if block == nil {
- // this is the first ROM of this pair, so create the block
- block = &memBlock{
- start: start,
- end: end,
- }
- d.roms = append(d.roms, block)
- }
-
- // highfile/lowfile isn't actually used for anything, but I might want it
- // in the future, so I'm leaving it here.
- if start%2 == 0 {
- block.highFile = file
- } else {
- block.lowFile = file
- }
-
- return nil
- }
-
- func (d *disassembler) read8(addr uint32) byte {
- return d.prog[addr]
- }
-
- func (d *disassembler) read16(addr uint32) uint16 {
- return uint16(d.prog[addr])<<8 | uint16(d.prog[addr+1])
- }
-
- func (d *disassembler) read32(addr uint32) uint32 {
- return uint32(d.prog[addr])<<24 | uint32(d.prog[addr+1])<<16 | uint32(d.prog[addr+2])<<8 | uint32(d.prog[addr+3])
- }
-
- func (d *disassembler) read64(addr uint32) uint64 {
- var ret uint64
-
- ret |= uint64(d.prog[addr]) << 56
- ret |= uint64(d.prog[addr+1]) << 48
- ret |= uint64(d.prog[addr+2]) << 40
- ret |= uint64(d.prog[addr+3]) << 32
- ret |= uint64(d.prog[addr+4]) << 24
- ret |= uint64(d.prog[addr+5]) << 16
- ret |= uint64(d.prog[addr+6]) << 8
- ret |= uint64(d.prog[addr+7])
-
- return ret
- }
-
- func (d *disassembler) readFloat64(addr uint32) float64 {
- return math.Float64frombits(d.read64(addr))
- }
-
- func (d *disassembler) disassemble(start uint32, dests map[uint32][]call, silent bool) ([]call, error) {
-
- externs := make([]call, 0)
-
- signature := d.read32(start)
-
- var headerInfo string
-
- // 13fff = no branch
- // 14000 = branch
- // 14001 = branch
-
- if signature == 0x4EB82102 {
- if !silent {
- stackMax := 0x17fff
- vsp := stackMax + 1 - int(d.read16(start+4))
- if vsp < 0x14000 {
- vsp -= 0xc000
- }
-
- headerInfo = fmt.Sprintf("; A0 = $%06X; (A0) = $%04X; A6 = $%06X\n\n", 0x4000, vsp, vsp)
-
- // A0 = A6
- }
- d.pc = start + 6
- } else if signature == 0x4EB82144 {
- if !silent {
- a6 := 0
- a1 := a6 + int(d.read16(start+4)) - 1
- a0 := 0x4000 + (int(d.read8(start+6)) << 2)
-
- //(a0) = a1
- if a1 >= 0 {
- headerInfo = fmt.Sprintf("; A0 = $%06X; (A0) = SP + $%X\n\n", a0, a1)
- } else {
- headerInfo = fmt.Sprintf("; A0 = $%06X; (A0) = SP - $%X\n\n", a0, -a1)
- }
- }
- d.pc = start + 7
- } else if signature == 0x4EB82164 {
-
- // movea.l (SP)+,A5
- // move.w (A5)+,D0w
- // move.w (A5)+,D1w
- // moveq #0x0,D2
- // move.b (A5)+,D2b
- // lsl.w #0x2,D2w
- // movea.w #0x4000,A0
- // adda.w D2w,A0
- // move.l (A0),-(SP)=>DAT_00004000
- // move.w A0w,-(SP)=>local_2
- // movea.l A6,A1
- // adda.w D0w,A1
- // subq.l #0x1,A1
- // move.l A1,(A0)=>DAT_00004000
- // movea.l A6,A0
- // suba.w D1w,A6
- // tst.w D0w
- // beq.b LAB_00002196
- // movea.l A6,A1
- // lsr.w #0x1,D0w
- // subq.w #0x1,D0w
- // LAB_00002190
- // move.w (A0)+,(A1)+
- // dbf D0w,LAB_00002190
- // LAB_00002196
- // bra.w FUN_00002000
-
- if !silent {
- d0 := uint32(d.read16(start + 4))
- a6 := uint32(0)
- a1 := a6 + d0 - 1
- d1 := uint32(d.read16(start + 6))
- a0 := 0x4000 + (int(d.read8(start+8)) << 2)
-
- headerInfo = fmt.Sprintf("; P0 = $%04X; P1 = $%04X; P2 = $%02X\n", d.read16(start+4), d.read16(start+6), d.read8(start+8))
-
- if d0 > 0 {
- d0 = (d0 << 1) - 1
- }
-
- if a1 >= 0 {
- headerInfo += fmt.Sprintf("; A0 = $%06X; (A0) = A6 + $%X; D1 = $%06X\n\n", a0, a1, d1)
- } else {
- headerInfo += fmt.Sprintf("; A0 = $%06X; (A0) = A6 - $%X; D1 = $%06X\n\n", a0, -a1, d1)
- }
- }
- d.pc = start + 9
- }
-
- if !silent {
-
- fmt.Printf("\n; ---------------- Begin %04X Function $%06X ---------------- \n\n%s", signature&0xFFFF, start, headerInfo)
- for _, dest := range dests[start] {
- fmt.Printf("; called from $%06X:$%06X\n", dest.function, dest.instrAddr)
-
- }
-
- fmt.Printf("\n%6s %-*s%-8s\t%-20s%s\n\n", "; addr", bytesPerDisassemblyLine*3+2, "bytes", "opcode", "operands", "comment")
-
- }
-
- var err error
-
- for {
-
- instPC := d.pc
- inst := d.prog[d.pc]
- d.pc++
- o := output{}
-
- if cs, ok := d.caseStmts[instPC]; ok {
- if len(cs.keys) > 0 {
- o.mnemonic = fmt.Sprintf("CASE")
- o.comment = fmt.Sprintf("SWITCH $%06X", cs.switchAddr)
- keysStr := make([]string, len(cs.keys))
- for i, v := range cs.keys {
- keysStr[i] = fmt.Sprintf("$%02X", v)
- }
- o.operands = strings.Join(keysStr, ", ")
-
- d.pc += 1 + uint32(len(cs.keys))
- } else {
- o.mnemonic = fmt.Sprintf("DEFAULT")
- o.comment = fmt.Sprintf("SWITCH $%06X", cs.switchAddr)
- }
- delete(d.caseStmts, instPC)
- } else if inst == 0x01 {
- o.mnemonic = "NOP"
- } else if inst == 0x02 {
- o.mnemonic = "INLINE"
-
- if d.pc%2 != 0 {
- d.pc++
- }
-
- startPC := d.pc
-
- // find end of program
- for {
- if d.read16(d.pc) == 0x4e75 {
- d.pc += 2
- break
- }
- d.pc += 2
- }
-
- machineCodeBytes := d.prog[startPC:d.pc]
-
- o.startPC = startPC
- o.endPC = d.pc
-
- o.operands = fmt.Sprintf("%d Bytes", len(machineCodeBytes))
- } else if inst == 0x03 {
- op := d.getOpr8()
- if op <= 0x30 {
- o, externs, err = d.handle2090(d.pc-2, op, externs)
- } else {
- err = fmt.Errorf("bad 0x03 instruction")
- }
- } else if inst >= 0x04 && inst <= 0x07 {
- o.mnemonic = "PUSH.10"
- o.operands = fmt.Sprintf("$%03X", d.getOpr10())
- } else if inst >= 0x08 && inst <= 0x0F {
- o.mnemonic = fmt.Sprintf("?_$%02X", inst)
- op1 := d.getOpr16()
- op2 := d.getOpr16()
-
- if inst&(1<<2) == 0 && d.prog[d.pc] == 0 {
- d.pc++
- o.operands = fmt.Sprintf("$%04X, $%04X, $0", op1, op2)
- } else {
- o.operands = fmt.Sprintf("$%04X, $%04X", op1, op2)
- }
-
- } else if inst >= 0x10 && inst <= 0x17 {
- o.mnemonic = "BR"
- jd := int(d.getSignedOpr11())
- o.operands = fmt.Sprintf("$%03X", jd)
- o.comment = fmt.Sprintf("=> $%06X", uint32(int(d.pc)+jd))
- } else if inst >= 0x18 && inst <= 0x1F {
- o.mnemonic = "BRZ"
- jd := int(d.getSignedOpr11())
- o.operands = fmt.Sprintf("$%03X", jd)
- o.comment = fmt.Sprintf("=> $%06X", uint32(int(d.pc)+jd))
- } else if inst >= 0x20 && inst <= 0x3F {
- o, externs, err = d.handle2090(d.pc-1, inst-0x20, externs)
- } else if inst >= 0x40 && inst <= 0x7f {
- o.mnemonic = "PUSH.6"
- o.operands = fmt.Sprintf("$%02X", d.getOpr6())
- } else if inst >= 0x80 && inst <= 0xFF {
- w := []string{"B", "W", "L", "F"}[inst&0x03]
-
- if (inst & 0x10) == 0 {
- o.mnemonic = fmt.Sprintf("READ.%s", w)
- } else {
- o.mnemonic = fmt.Sprintf("WRITE.%s", w)
- }
-
- if inst >= 0xc0 {
- o.operands = fmt.Sprintf("$%04X", d.getOpr16())
- } else {
- o.operands = fmt.Sprintf("$%02X", d.getOpr8())
- }
-
- if (inst & 0x10) == 0 {
- if d.prog[d.pc] == 0 {
- d.pc++
- }
- }
- } else {
- err = fmt.Errorf("bad instruction")
- }
-
- if err != nil {
- if !silent {
- fmt.Printf("Disassembly failed at $%06X\n", instPC)
- }
- break
- }
-
- if !silent {
- d.printInstr(instPC, o)
- }
-
- if o.mnemonic == "RETURN" {
- break
- }
-
- }
- for i := range externs {
- externs[i].function = start
- }
-
- if !silent {
- if err != nil {
- fmt.Printf("\n; ---------------- Disassemly Terminated: %v ---------------- \n", err)
-
- } else {
- fmt.Printf("\n; ---------------- End Function $%06X ---------------- \n\n\n", start)
- }
- }
- return externs, err
- }
-
- func (d *disassembler) printInstr(instPC uint32, o output) {
-
- if o.mnemonic == "INLINE" {
- d.disassemble68k(instPC, o.startPC, d.prog[o.startPC:o.endPC])
- return
- }
-
- d.printy(instPC, d.pc, o.mnemonic, o.operands, o.comment)
-
- }
-
- func (d *disassembler) printy(startPC, endPC uint32, mnemonic, operands, comment string) {
- if comment != "" {
- comment = "; " + comment
- }
- bytePadding := bytesPerDisassemblyLine*3 + 2
- if endPC-startPC <= bytesPerDisassemblyLine {
- hex := fmt.Sprintf("% 02X", d.prog[startPC:endPC])
- fmt.Printf("%06X % -*s%-8s\t%-20s%s\n", startPC, bytePadding, hex, mnemonic, operands, comment)
- } else {
- for i := startPC; i < endPC; i += bytesPerDisassemblyLine {
- if i == startPC {
- hex := fmt.Sprintf("% 02X", d.prog[i:i+bytesPerDisassemblyLine])
- fmt.Printf("%06X % -*s%-8s\t%-20s%s\n", i, bytePadding, hex, mnemonic, operands, comment)
- } else {
- endAddr := i + bytesPerDisassemblyLine
- if endAddr > endPC {
- endAddr = endPC
- }
- hex := fmt.Sprintf("% 02X", d.prog[i:endAddr])
- fmt.Printf("%6s % -*s%-8s\n", "", bytePadding, hex, "")
-
- }
-
- }
-
- }
- }
-
- func (d *disassembler) getOpr6() byte {
- return d.prog[d.pc-1] & 0x3F
- }
-
- func (d *disassembler) getOpr8() byte {
- v := d.prog[d.pc]
- d.pc += 1
- return v
- }
-
- func (d *disassembler) getOpr10() uint16 {
- v := uint16(d.prog[d.pc-1]&0x03)<<8 | uint16(d.prog[d.pc])
- d.pc += 1
- return v
- }
-
- func (d *disassembler) getOpr11() uint16 {
- v := uint16(d.prog[d.pc-1]&0x07)<<8 | uint16(d.prog[d.pc])
- d.pc += 1
- return v
- }
-
- func (d *disassembler) getSignedOpr11() int16 {
- v := uint16(d.prog[d.pc-1]&0x07)<<8 | uint16(d.prog[d.pc])
- d.pc += 1
- if v&0x0400 != 0 {
- return int16(v | 0xF800)
- }
- return int16(v)
- }
-
- func (d *disassembler) getOpr16() uint16 {
- v := uint16(d.prog[d.pc])<<8 | uint16(d.prog[d.pc+1])
- d.pc += 2
- return v
- }
-
- func (d *disassembler) getOpr32() uint32 {
- v := uint32(d.prog[d.pc])<<24 | uint32(d.prog[d.pc+1])<<16 | uint32(d.prog[d.pc+2])<<8 | uint32(d.prog[d.pc+3])
- d.pc += 4
- return v
- }
-
- func (d *disassembler) getOpr64() uint64 {
- v := uint64(d.prog[d.pc]) << 56
- v |= uint64(d.prog[d.pc+1]) << 48
- v |= uint64(d.prog[d.pc+2]) << 40
- v |= uint64(d.prog[d.pc+3]) << 32
- v |= uint64(d.prog[d.pc+4]) << 24
- v |= uint64(d.prog[d.pc+5]) << 16
- v |= uint64(d.prog[d.pc+6]) << 8
- v |= uint64(d.prog[d.pc+7])
- d.pc += 8
- return v
- }
-
- func (d *disassembler) handle2090(instAddr uint32, inst byte, externs []call) (output, []call, error) {
- o := output{}
- switch inst {
- case 0x00:
- o.mnemonic = "ADD.F"
- case 0x01:
- o.mnemonic = "SUB.F"
- case 0x02:
- o.mnemonic = "MUL.F"
- case 0x03:
- o.mnemonic = "DIV.F"
- case 0x04:
- o.mnemonic = "GT.F"
- case 0x05:
- o.mnemonic = "GTE.F"
- case 0x06:
- o.mnemonic = "EQ.F"
- case 0x07:
- o.mnemonic = "ADD.L"
- case 0x08:
- o.mnemonic = "SUB.L"
- case 0x09:
- o.mnemonic = "MUL.L"
- case 0x0A:
- o.mnemonic = "EQ.L"
- case 0x0B:
- o.mnemonic = "NEQ.L"
- case 0x0C:
- o.mnemonic = "AND.L"
- case 0x0D:
- o.mnemonic = "OR.L"
- case 0x0E:
- o.mnemonic = "NOT.L"
- case 0x0F:
- o.mnemonic = "MOD.L"
- case 0x10:
- o.mnemonic = "BSR.68K"
- off := int(d.getOpr16())
- o.operands = fmt.Sprintf("$%04X", off)
-
- c := call{
- instrAddr: instAddr,
- computedAddr: uint32(int(d.pc) - off),
- }
-
- var targetAddrStr string
-
- if d.read16(c.computedAddr) == 0x4EF9 {
- c.targetAddr = d.read32(c.computedAddr + 2)
- targetAddrStr = fmt.Sprintf(" => $%06X", c.targetAddr)
- } else {
- c.targetAddr = c.computedAddr
- }
-
- label := d.labels[c.targetAddr]
- if label != "" {
- label = fmt.Sprintf(" (%s)", label)
- }
-
- var native string
- if d.read32(c.targetAddr) != 0x4EB82144 && d.read32(c.targetAddr) != 0x4EB82164 {
- native = " (NATIVE)"
- c.native = true
- }
-
- o.comment = fmt.Sprintf("=> $%06X%s%s%s", c.computedAddr, targetAddrStr, label, native)
-
- externs = append(externs, c)
- case 0x11:
- o.mnemonic = "SUBSP.B"
- o.operands = fmt.Sprintf("$%02X", d.getOpr8())
- case 0x12:
- o.mnemonic = "ADDSP.B"
- o.operands = fmt.Sprintf("$%02X", d.getOpr8())
- case 0x13:
- o.mnemonic = "_2300"
- case 0x14:
- o.mnemonic = "RETURN"
- case 0x15:
- o.mnemonic = "SWITCH"
- switchAddr := d.pc - 1
- tpc := d.pc
- for d.prog[tpc] != 0 {
- caseAddr := tpc
- op := d.read16(tpc)
- tpc += 2
- numKey := int(op & 0xF000 >> 12)
- recLen := int(op & 0xfff)
- keys := make([]byte, numKey)
- for i := 0; i < numKey; i++ {
- keys[i] = d.read8(tpc + uint32(i))
- }
- d.caseStmts[caseAddr] = caseStmt{
- switchAddr: switchAddr,
- keys: keys,
- }
- tpc += uint32(recLen)
- }
- d.caseStmts[tpc] = caseStmt{
- switchAddr: switchAddr,
- }
- case 0x16:
- o.mnemonic = "_2362"
- op := d.getOpr16() & 0xfff
- a0 := 0x4000 + ((op & 0x0C00) >> 8)
-
- o.comment = fmt.Sprintf("A0 = $%06X; (A0) = A6 + $%X\n\n", a0, 0)
-
- o.operands = fmt.Sprintf("$%04X", op)
- case 0x17:
- o.mnemonic = "_23d2"
- op := d.getOpr16() & 0xfff
- op2 := d.getOpr16()
- o.operands = fmt.Sprintf("$%04X, $%04X", op, op2)
- case 0x18:
- op := d.getOpr16()
- o.mnemonic = []string{"BLS.B", "BLS.W", "BLS.L", "BLS.W"}[op&0xc000>>14]
- o.operands = fmt.Sprintf("$%04X", op&0x3fff)
- o.comment = fmt.Sprintf("=> $%06X", int(d.pc)+int(op&0x3fff))
-
- case 0x19:
- o.mnemonic = "_23fc"
- op := d.getOpr16()
- op2 := d.getOpr16()
- o.operands = fmt.Sprintf("$%04X, $%04X", op, op2)
- case 0x1A:
- op := d.getOpr16()
- o.mnemonic = []string{"BGT.B", "BGT.W", "BGT.L", "BGT.W"}[op&0xc000>>14]
- o.operands = fmt.Sprintf("$%04X", op&0x3fff)
- o.comment = fmt.Sprintf("=> $%06X", int(d.pc)+int(op&0x3fff))
- case 0x1B:
- o.mnemonic = "PUSH.F"
- v := d.getOpr64()
- fv := math.Float64frombits(v)
- o.operands = fmt.Sprintf("$%016X", v)
- o.comment = fmt.Sprintf("float = %f", fv)
- case 0x1C:
- o.mnemonic = "PUSH.W"
- op := int(d.getOpr16())
- o.operands = fmt.Sprintf("$%04X", op)
- case 0x1D:
- o.mnemonic = "PUSH.L"
- op := int(d.getOpr32())
- o.operands = fmt.Sprintf("$%08X", op)
- case 0x1E:
- o.mnemonic = "PUSH.W"
- o.operands = "$0000"
- case 0x1F:
- o.mnemonic = "DISP"
- strlen := uint32(d.getOpr8())
- str := d.prog[d.pc : d.pc+strlen]
- o.operands = fmt.Sprintf(`"%s"`, string(str))
- d.pc += strlen
- case 0x20:
- o.mnemonic = "NEG.W"
- case 0x21:
- o.mnemonic = "LT.F"
- case 0x22:
- o.mnemonic = "LTE.F"
- case 0x23:
- o.mnemonic = "NEQ.F"
- case 0x24:
- o.mnemonic = "DIV.L"
- case 0x25:
- o.mnemonic = "LT.L"
- case 0x26:
- o.mnemonic = "GT.L"
- case 0x27:
- o.mnemonic = "LTE.L"
- case 0x28:
- o.mnemonic = "GTE.L"
- case 0x29:
- o.mnemonic = "FLOAT2LONG"
- case 0x2A:
- o.mnemonic = "LONG2FLOAT"
- case 0x2B:
- o.mnemonic = "COMPARE"
- op := d.getOpr16()
- o.operands = fmt.Sprintf("$%04X", op)
- case 0x2C:
- o.mnemonic = "NOTCOMPARE"
- op := d.getOpr16()
- o.operands = fmt.Sprintf("$%04X", op)
- case 0x2D:
- o.mnemonic = "SUBSP.W"
- op := d.getOpr16()
- o.operands = fmt.Sprintf("$%04X", op)
- case 0x2E:
- o.mnemonic = "ADDSP.W"
- op := d.getOpr16()
- o.operands = fmt.Sprintf("$%04X", op)
- case 0x2F:
- o.mnemonic = "XORL.L"
- case 0x30:
- o.mnemonic = "TRAP1"
- strlen := uint32(d.getOpr8())
- str := d.prog[d.pc : d.pc+strlen]
- o.operands = fmt.Sprintf("\"%s\"", string(str))
- d.pc += strlen
- default:
- return o, externs, fmt.Errorf("unrecognized 2090 instruction $%02X", inst)
- }
- return o, externs, nil
- }
-
- func (d *disassembler) disassemble68k(instPC, startPC uint32, machineCodeBytes []byte) {
- bus := disasm.NewAddressBus(d.prog)
- doneBytes := uint32(0)
-
- operand := ""
-
- if startPC-instPC > 1 {
- operand = "PAD"
- }
- d.printy(instPC, startPC, "INLINE", operand, "")
-
- for {
- startPC := uint32(startPC + doneBytes)
- s, n := disasm.Disassemble(disasm.M68K_CPU_TYPE_68000, int32(startPC), bus)
- endPC := startPC + uint32(n)
-
- d.printy(startPC, endPC, " "+s, "", "")
-
- doneBytes += uint32(n)
- if doneBytes == uint32(len(machineCodeBytes)) {
- break
- }
- }
-
- }
|