Sfoglia il codice sorgente

fixed 68 disassembler for INLINE instructions

Keelan Lightfoot 1 anno fa
parent
commit
85f1a31bbf
3 ha cambiato i file con 123 aggiunte e 117 eliminazioni
  1. 1
    1
      LICENSE.txt
  2. 2
    0
      go.mod
  3. 120
    116
      main.go

+ 1
- 1
LICENSE.txt Vedi File

@@ -1,4 +1,4 @@
1
-Copyright 2023 Keelan Lightfoot
1
+Copyright © 2023 Keelan Lightfoot
2 2
 
3 3
 Permission is hereby granted, free of charge, to any person obtaining a copy of
4 4
 this software and associated documentation files (the “Software”), to deal in

+ 2
- 0
go.mod Vedi File

@@ -1,3 +1,5 @@
1 1
 module code.beefchicken.com/keelan/disasm4000sx
2 2
 
3 3
 go 1.20
4
+
5
+require code.beefchicken.com/keelan/68kdisasm v1.0.0

+ 120
- 116
main.go Vedi File

@@ -5,13 +5,15 @@ import (
5 5
 	"math"
6 6
 	"os"
7 7
 	//	"sort"
8
-	"strings"
9
-	//"code.beefchicken.com/68kdisasm"
8
+	"code.beefchicken.com/keelan/68kdisasm"
10 9
 	"encoding/json"
11 10
 	"path/filepath"
11
+	"strings"
12 12
 )
13 13
 
14
-//var externs = make([]int, 0)
14
+const (
15
+	bytesPerDisassemblyLine = 9
16
+)
15 17
 
16 18
 type romInfo struct {
17 19
 	Roms []struct {
@@ -39,6 +41,10 @@ type output struct {
39 41
 	mnemonic string
40 42
 	operands string
41 43
 	comment  string
44
+
45
+	// these are used for "INLINE" only
46
+	startPC uint32
47
+	endPC   uint32
42 48
 }
43 49
 
44 50
 type call struct {
@@ -52,46 +58,50 @@ type call struct {
52 58
 func main() {
53 59
 
54 60
 	if len(os.Args) < 2 {
55
-		fmt.Printf("Usage: %s <path to rom directory>\n", os.Args[0])
56
-		os.Exit(1)
61
+		die("Usage: %s <path to rom directory>\n", os.Args[0])
57 62
 	}
63
+
58 64
 	romDir := os.Args[1]
59
-	romMapFilename := filepath.Join(romDir, "map.json")
60
-	info := &romInfo{}
61 65
 
66
+	romMapFilename := filepath.Join(romDir, "map.json")
62 67
 	b, _ := os.ReadFile(romMapFilename)
63 68
 
64 69
 	fmt.Printf("Loading ROM info from '%s'...\n", romMapFilename)
70
+
71
+	info := &romInfo{}
65 72
 	err := json.Unmarshal(b, &info)
66 73
 	if err != nil {
67
-		fmt.Printf("unable to load rom map from '%s': %v\n", romMapFilename, err)
68
-		os.Exit(1)
74
+		die("Unable to load rom map from '%s': %v\n", romMapFilename, err)
69 75
 	}
70 76
 
71 77
 	d := NewDisassembler()
72 78
 
73 79
 	for _, rom := range info.Roms {
80
+
74 81
 		var start, end uint32
75 82
 		var checksum int
76 83
 
77 84
 		_, err := fmt.Sscanf(rom.Start, "0x%X", &start)
78 85
 		if err != nil {
79
-			fmt.Printf("Unable to parse start address '%s' for rom '%s'!\n", rom.Start, rom.File)
80
-			os.Exit(1)
86
+			die("Unable to parse start address '%s' for rom '%s'!\n", rom.Start, rom.File)
81 87
 		}
88
+
82 89
 		_, err = fmt.Sscanf(rom.End, "0x%X", &end)
83 90
 		if err != nil {
84
-			fmt.Printf("Unable to parse end address '%s' for rom '%s'!\n", rom.End, rom.File)
85
-			os.Exit(1)
91
+			die("Unable to parse end address '%s' for rom '%s'!\n", rom.End, rom.File)
86 92
 		}
93
+
87 94
 		_, err = fmt.Sscanf(rom.Checksum, "0x%X", &checksum)
88 95
 		if err != nil {
89
-			fmt.Printf("Unable to checksum '%s' for rom '%s'!\n", rom.Checksum, rom.File)
90
-			os.Exit(1)
96
+			die("Unable to checksum '%s' for rom '%s'!\n", rom.Checksum, rom.File)
91 97
 		}
98
+
92 99
 		file := filepath.Join(romDir, rom.File)
100
+
93 101
 		fmt.Printf("Loading '%s' (0x%06X-0x%06X)...\n", file, start, end)
102
+
94 103
 		d.AddRom(file, start, end, checksum)
104
+
95 105
 	}
96 106
 
97 107
 	for _, label := range info.Labels {
@@ -99,17 +109,16 @@ func main() {
99 109
 		var address uint32
100 110
 		_, err := fmt.Sscanf(label.Address, "0x%X", &address)
101 111
 		if err != nil {
102
-			fmt.Printf("Unable to parse address '%s' for label '%s!\n", label.Address, label.Label)
103
-			os.Exit(1)
112
+			die("Unable to parse address '%s' for label '%s!\n", label.Address, label.Label)
104 113
 		}
105 114
 		fmt.Printf("Adding label %s = 0x%06X\n", label.Label, address)
106 115
 		d.AddLabel(address, label.Label)
107 116
 
108 117
 	}
109 118
 
110
-	// look for the two kinds of header functions and queue
119
+	// look for the three kinds of header functions and queue
111 120
 	// the vm code up for disassembly
112
-	queue := []uint32{} //0xe6d // 0xa0435 <- week // 0x00001631 <- WRNO FIX // 0x0009324d
121
+	queue := []uint32{}
113 122
 	for _, block := range d.roms {
114 123
 		for i := block.start; i <= block.end-3; i++ {
115 124
 			inst := d.read32(i)
@@ -138,6 +147,11 @@ func main() {
138 147
 
139 148
 }
140 149
 
150
+func die(format string, a ...any) {
151
+	fmt.Printf(format, a...)
152
+	os.Exit(1)
153
+}
154
+
141 155
 type disassembler struct {
142 156
 	pc        uint32
143 157
 	labels    map[uint32]string
@@ -176,6 +190,9 @@ func addx(x, y uint16, xf *uint16) uint16 {
176 190
 
177 191
 func (d *disassembler) AddRom(file string, start uint32, end uint32, checksum int) error {
178 192
 
193
+	// grow memory
194
+	// yes this is inefficient with firmware that has sparse allocation, but for the 4000SX
195
+	// it works fine.
179 196
 	if len(d.prog) < int(end)+1 {
180 197
 		newProg := make([]byte, end+1)
181 198
 		copy(newProg, d.prog)
@@ -187,26 +204,26 @@ func (d *disassembler) AddRom(file string, start uint32, end uint32, checksum in
187 204
 		return err
188 205
 	}
189 206
 
190
-	var cs uint16 = 0
191
-	var cs2 uint16 = 0
192
-
193
-	var xf uint16
207
+	var softCS, hardCS, xflag uint16
194 208
 
195 209
 	for i := 0; i < len(b); i++ {
196 210
 		d.prog[int(start)+i*2] = b[i]
197 211
 		if i < len(b)-4 {
198
-			cs = addx(uint16(b[i]), cs, &xf)
212
+			softCS = addx(uint16(b[i]), softCS, &xflag)
199 213
 		}
200
-		cs2 += uint16(b[i])
214
+		hardCS += uint16(b[i])
201 215
 	}
202
-	cs = ^cs
216
+	softCS = ^softCS
203 217
 
204 218
 	internalStoredChecksum := uint16(b[len(b)-1])<<8 + uint16(b[len(b)-2])
205 219
 
206
-	fmt.Printf("%s INTERNAL CHECKSUM: GOT 0x%04X EXPECTED 0x%04X\n", file, cs, internalStoredChecksum)
207
-	fmt.Printf("%s EXTERNAL CHECKSUM: GOT 0x%04X EXPECTED 0x%04X\n", file, cs2, checksum)
220
+	// the 'soft' checksum is the one the receiver checks on boot
221
+	fmt.Printf("%s Soft Checksum: got 0x%04X expected 0x%04X\n", file, softCS, internalStoredChecksum)
208 222
 
209
-	// check if we've already loaded the pair for this rom
223
+	// the 'hard' checksum is the one printed on the label on the EPROM
224
+	fmt.Printf("%s Hard Checksum: got 0x%04X expected 0x%04X\n", file, hardCS, checksum)
225
+
226
+	// check if we've already loaded the partner for this rom
210 227
 	var block *memBlock
211 228
 	for _, rom := range d.roms {
212 229
 		if start&0xFFFFFFFE == rom.start&0xFFFFFFFE {
@@ -230,10 +247,12 @@ func (d *disassembler) AddRom(file string, start uint32, end uint32, checksum in
230 247
 		d.roms = append(d.roms, block)
231 248
 	}
232 249
 
250
+	// highfile/lowfile isn't actually used for anything, but I might want it
251
+	// in the future, so I'm leaving it here.
233 252
 	if start%2 == 0 {
234
-		block.lowFile = file
235
-	} else {
236 253
 		block.highFile = file
254
+	} else {
255
+		block.lowFile = file
237 256
 	}
238 257
 
239 258
 	return nil
@@ -251,10 +270,6 @@ func (d *disassembler) read32(addr uint32) uint32 {
251 270
 	return uint32(d.prog[addr])<<24 | uint32(d.prog[addr+1])<<16 | uint32(d.prog[addr+2])<<8 | uint32(d.prog[addr+3])
252 271
 }
253 272
 
254
-func (d *disassembler) readFloat64(addr uint32) float64 {
255
-	return math.Float64frombits(d.read64(addr))
256
-}
257
-
258 273
 func (d *disassembler) read64(addr uint32) uint64 {
259 274
 	var ret uint64
260 275
 
@@ -270,6 +285,10 @@ func (d *disassembler) read64(addr uint32) uint64 {
270 285
 	return ret
271 286
 }
272 287
 
288
+func (d *disassembler) readFloat64(addr uint32) float64 {
289
+	return math.Float64frombits(d.read64(addr))
290
+}
291
+
273 292
 func (d *disassembler) disassemble(start uint32, dests map[uint32][]call, silent bool) ([]call, error) {
274 293
 
275 294
 	externs := make([]call, 0)
@@ -368,7 +387,7 @@ func (d *disassembler) disassemble(start uint32, dests map[uint32][]call, silent
368 387
 
369 388
 		}
370 389
 
371
-		fmt.Printf("\n%6s  %-14s  %-8s\t%-20s%s\n\n", "; addr", "bytes", "opcode", "operands", "comment")
390
+		fmt.Printf("\n%6s  %-*s%-8s\t%-20s%s\n\n", "; addr", bytesPerDisassemblyLine*3+2, "bytes", "opcode", "operands", "comment")
372 391
 
373 392
 	}
374 393
 
@@ -405,32 +424,24 @@ func (d *disassembler) disassemble(start uint32, dests map[uint32][]call, silent
405 424
 			if d.pc%2 != 0 {
406 425
 				d.pc++
407 426
 			}
408
-			//startPC := d.pc
409
-			machineCodeBytes := make([]byte, 0)
427
+
428
+			startPC := d.pc
429
+
430
+			// find end of program
410 431
 			for {
411
-				machineCodeBytes = append(machineCodeBytes, d.prog[d.pc])
412 432
 				if d.read16(d.pc) == 0x4e75 {
413
-					machineCodeBytes = append(machineCodeBytes, d.prog[d.pc+1])
414 433
 					d.pc += 2
415 434
 					break
416 435
 				}
417
-				d.pc++
436
+				d.pc += 2
418 437
 			}
419 438
 
420
-			// 	bus := disasm.NewAddressBus(d.prog)
421
-			// 			doneBytes := 0
422
-			//
423
-			// 			for {
424
-			// 				s, n := disasm.Disassemble(disasm.M68K_CPU_TYPE_68000, int32(startPC+doneBytes), bus)
425
-			// 				fmt.Println(s)
426
-			// 				doneBytes+=int(n)
427
-			// 				if doneBytes == len(machineCodeBytes) {
428
-			// 					break
429
-			// 				}
430
-			// 			}
431
-
432
-			//fmt.Printf("%d % 02X\n",len(machineCodeBytes),machineCodeBytes)
433
-			o.operands = fmt.Sprintf("%d Bytes", len(machineCodeBytes)) //d.getOpr32())
439
+			machineCodeBytes := d.prog[startPC:d.pc]
440
+
441
+			o.startPC = startPC
442
+			o.endPC = d.pc
443
+
444
+			o.operands = fmt.Sprintf("%d Bytes", len(machineCodeBytes))
434 445
 		} else if inst == 0x03 {
435 446
 			op := d.getOpr8()
436 447
 			if op <= 0x30 {
@@ -492,35 +503,6 @@ func (d *disassembler) disassemble(start uint32, dests map[uint32][]call, silent
492 503
 			err = fmt.Errorf("bad instruction")
493 504
 		}
494 505
 
495
-		//	var hex string
496
-
497
-		// if !silent {
498
-		// 			if d.pc-instPC < 6 {
499
-		// 				hex = fmt.Sprintf("% 02X", d.prog[instPC:d.pc])
500
-		// 			} else {
501
-		// 				hex = fmt.Sprintf("% 02X...", d.prog[instPC:instPC+4])
502
-		// 			}
503
-		// 			fmt.Printf("%06X  % -14s  ", instPC, hex)
504
-		// 		}
505
-		//
506
-		// 		if err != nil {
507
-		// 			break
508
-		// 		}
509
-		//
510
-		// 		if !silent {
511
-		// 			var comment string
512
-		// 			if o.comment != "" {
513
-		// 				comment = "; " + o.comment
514
-		// 			}
515
-		// 			fmt.Printf("%-8s\t%-20s%s\n", o.mnemonic, o.operands, comment)
516
-		// 		}
517
-
518
-		if err == nil {
519
-			if !silent {
520
-				d.printInstr(instPC, o)
521
-			}
522
-		}
523
-
524 506
 		if err != nil {
525 507
 			if !silent {
526 508
 				fmt.Printf("Disassembly failed at $%06X\n", instPC)
@@ -528,6 +510,10 @@ func (d *disassembler) disassemble(start uint32, dests map[uint32][]call, silent
528 510
 			break
529 511
 		}
530 512
 
513
+		if !silent {
514
+			d.printInstr(instPC, o)
515
+		}
516
+
531 517
 		if o.mnemonic == "RETURN" {
532 518
 			break
533 519
 		}
@@ -550,49 +536,41 @@ func (d *disassembler) disassemble(start uint32, dests map[uint32][]call, silent
550 536
 
551 537
 func (d *disassembler) printInstr(instPC uint32, o output) {
552 538
 
553
-	// var hex, comment string
554
-	// 		if o.comment != "" {
555
-	// 			comment = "; " + o.comment
556
-	// 		}
557
-	//
558
-	// 		if d.pc-instPC < 6 {
559
-	// 			hex = fmt.Sprintf("% 02X", d.prog[instPC:d.pc])
560
-	// 		} else {
561
-	// 			hex = fmt.Sprintf("% 02X...", d.prog[instPC:instPC+4])
562
-	// 		}
563
-	// 		fmt.Printf("%06X  % -14s  ", instPC, hex)
564
-	//
565
-	//
566
-	// 		fmt.Printf("%-8s\t%-20s%s\n", o.mnemonic, o.operands, comment)
567
-
568
-	var hex, comment string
569
-	if o.comment != "" {
570
-		comment = "; " + o.comment
539
+	if o.mnemonic == "INLINE" {
540
+		d.disassemble68k(instPC, o.startPC, d.prog[o.startPC:o.endPC])
541
+		return
571 542
 	}
572 543
 
573
-	if d.pc-instPC < 6 {
574
-		hex = fmt.Sprintf("% 02X", d.prog[instPC:d.pc])
575
-		fmt.Printf("%06X  % -14s  %-8s\t%-20s%s\n", instPC, hex, o.mnemonic, o.operands, comment)
544
+	d.printy(instPC, d.pc, o.mnemonic, o.operands, o.comment)
545
+
546
+}
547
+
548
+func (d *disassembler) printy(startPC, endPC uint32, mnemonic, operands, comment string) {
549
+	if comment != "" {
550
+		comment = "; " + comment
551
+	}
552
+	bytePadding := bytesPerDisassemblyLine*3 + 2
553
+	if endPC-startPC <= bytesPerDisassemblyLine {
554
+		hex := fmt.Sprintf("% 02X", d.prog[startPC:endPC])
555
+		fmt.Printf("%06X  % -*s%-8s\t%-20s%s\n", startPC, bytePadding, hex, mnemonic, operands, comment)
576 556
 	} else {
577
-		for i := instPC; i < d.pc; i += 5 {
578
-			if i == instPC {
579
-				hex = fmt.Sprintf("% 02X", d.prog[i:i+5])
580
-				fmt.Printf("%06X  % -14s  %-8s\t%-20s%s\n", i, hex, o.mnemonic, o.operands, comment)
557
+		for i := startPC; i < endPC; i += bytesPerDisassemblyLine {
558
+			if i == startPC {
559
+				hex := fmt.Sprintf("% 02X", d.prog[i:i+bytesPerDisassemblyLine])
560
+				fmt.Printf("%06X  % -*s%-8s\t%-20s%s\n", i, bytePadding, hex, mnemonic, operands, comment)
581 561
 			} else {
582
-				endAddr := i + 5
583
-				if endAddr > d.pc {
584
-					endAddr = d.pc
562
+				endAddr := i + bytesPerDisassemblyLine
563
+				if endAddr > endPC {
564
+					endAddr = endPC
585 565
 				}
586
-				hex = fmt.Sprintf("% 02X", d.prog[i:endAddr])
587
-				//fmt.Printf("%06X  % -14s  %-8s\n", i, hex, "")
588
-				fmt.Printf("%6s  % -14s  %-8s\n", "", hex, "")
566
+				hex := fmt.Sprintf("% 02X", d.prog[i:endAddr])
567
+				fmt.Printf("%6s  % -*s%-8s\n", "", bytePadding, hex, "")
589 568
 
590 569
 			}
591 570
 
592 571
 		}
593 572
 
594 573
 	}
595
-
596 574
 }
597 575
 
598 576
 func (d *disassembler) getOpr6() byte {
@@ -855,3 +833,29 @@ func (d *disassembler) handle2090(instAddr uint32, inst byte, externs []call) (o
855 833
 	}
856 834
 	return o, externs, nil
857 835
 }
836
+
837
+func (d *disassembler) disassemble68k(instPC, startPC uint32, machineCodeBytes []byte) {
838
+	bus := disasm.NewAddressBus(d.prog)
839
+	doneBytes := uint32(0)
840
+
841
+	operand := ""
842
+
843
+	if startPC-instPC > 1 {
844
+		operand = "PAD"
845
+	}
846
+	d.printy(instPC, startPC, "INLINE", operand, "")
847
+
848
+	for {
849
+		startPC := uint32(startPC + doneBytes)
850
+		s, n := disasm.Disassemble(disasm.M68K_CPU_TYPE_68000, int32(startPC), bus)
851
+		endPC := startPC + uint32(n)
852
+
853
+		d.printy(startPC, endPC, "  "+s, "", "")
854
+
855
+		doneBytes += uint32(n)
856
+		if doneBytes == uint32(len(machineCodeBytes)) {
857
+			break
858
+		}
859
+	}
860
+
861
+}