disassembles raw binaries

This commit is contained in:
Sean 2020-02-21 16:57:11 -07:00
parent 86d4c4fe3a
commit d8e52ee98d
No known key found for this signature in database
GPG Key ID: B111C910D99B42B8
16 changed files with 16205 additions and 14436 deletions

View File

@ -1,18 +1,15 @@
CC=clang CC=clang
CFLAGS=-Wall CFLAGS=-Wall
all: 2mg omf regs all: 2mg regs
2mg: 2mg.o 2mg: 2mg.o
$(CC) $(CFLAGS) -o $@ -largp $^ $(CC) $(CFLAGS) -o $@ -largp $^
omf: omf.o parser.o regs: src/iigs.h
$(CC) $(CFLAGS) -o $@ -largp $^ $(MAKE) -C src
regs: regs.o map.o scan.o parser.o disasm.o iigs.o src/iigs.h: iigs.dat
$(CC) $(CFLAGS) -o $@ -largp $^
iigs.c: iigs.dat
xxd -i $< $@ xxd -i $< $@
iigs.dat: docmaker/docmaker iigs iigs.dat: docmaker/docmaker iigs
@ -25,4 +22,6 @@ docmaker/docmaker:
$(CC) -c $(CFLAGS) -o $@ $< $(CC) -c $(CFLAGS) -o $@ $<
clean: clean:
rm -f *.o 2mg omg regs rm -f *.o 2mg regs
$(MAKE) -C docmaker clean
$(MAKE) -C src clean

14314
iigs.c

File diff suppressed because it is too large Load Diff

BIN
iigs.dat

Binary file not shown.

789
iigs/addresses.txt Normal file
View File

@ -0,0 +1,789 @@
EnterBASIC() {
-4, $03d0
}
ReconnectDOS() {
-4, $03d2
}
CowSound() {
-4, $03d9
}
ReconnectIO() {
-4, $03ea
}
ControlResetVector() {
-4, $03f2
}
AmpersandVector() {
-4, $03f5
}
ControlYVector() {
-4, $03f8
}
KBD() {
-4, $c000
}
W80STOREON() {
-4, $c001
}
RDMAINRAM() {
-4, $c002
}
RDCARDRAM() {
-4, $c003
}
WRMAINRAM() {
-4, $c004
}
WRCARDRAM() {
-4, $c005
}
SETSLOTCXROM() {
-4, $c006
}
SETINTCXROM() {
-4, $c007
}
SETSTDZP() {
-4, $c008
}
SETALTZP() {
-4, $c009
}
SETINTC3ROM() {
-4, $c00a
}
SETSLOTC3ROM() {
-4, $c00b
}
CLR80VID() {
-4, $c00c
}
SET80VID() {
-4, $c00d
}
CLRALTCHAR() {
-4, $c00e
}
SETALTCHAR() {
-4, $c00f
}
KBDSTRB() {
-4, $c010
}
RDLCBNK2() {
-4, $c011
}
RDLCRAM() {
-4, $c012
}
RDRAMRD() {
-4, $c013
}
RDRAMWRT() {
-4, $c014
}
RDCXROM() {
-4, $c015
}
RDALTZP() {
-4, $c016
}
RDC3ROM() {
-4, $c017
}
RD80STORE() {
-4, $c018
}
RDVBL() {
-4, $c019
}
RDTEXT() {
-4, $c01a
}
RDMIXED() {
-4, $c01b
}
RDPAGE2() {
-4, $c01c
}
RDHIRES() {
-4, $c01d
}
RDALTCHAR() {
-4, $c01e
}
RD80VID() {
-4, $c01f
}
TAPEOUT() {
-4, $c020
}
MONOCOLOR() {
-4, $c021
}
TBCOLOR() {
-4, $c022
}
VGCINT() {
-4, $c023
}
MOUSEDATA() {
-4, $c024
}
KEYMODREG() {
-4, $c025
}
DATAREG() {
-4, $c026
}
KMSTATUS() {
-4, $c027
}
ROMBANK() {
-4, $c028
}
NEWVIDEO() {
-4, $c029
}
LANGSEL() {
-4, $c02b
}
CHARROM() {
-4, $c02c
}
SLTROMSEL() {
-4, $c02d
}
VERTCNT() {
-4, $c02e
}
HORIZCNT() {
-4, $c02f
}
SPKR() {
-4, $c030
}
DISKREG() {
-4, $c031
}
SCANINT() {
-4, $c032
}
CLOCKDATA() {
-4, $c033
}
CLOCKCTL() {
-4, $c034
}
SHADOW() {
-4, $c035
}
CYAREG() {
-4, $c036
}
DMAREG() {
-4, $c037
}
SCCBREG() {
-4, $c038
}
SCCAREG() {
-4, $c039
}
SCCBDATA() {
-4, $c03a
}
SCCADATA() {
-4, $c03b
}
SOUNDCTL() {
-4, $c03c
}
SOUNDDATA() {
-4, $c03d
}
SOUNDADRL() {
-4, $c03e
}
SOUNDADRH() {
-4, $c03f
}
STROBE() {
-4, $c040
}
INTEN() {
-4, $c041
}
MMDELTAX() {
-4, $c044
}
MMDELTAY() {
-4, $c045
}
DIAGTYPE() {
-4, $c046
}
CLRVBLINT() {
-4, $c047
}
CLRXYINT() {
-4, $c048
}
TXTCLR() {
-4, $c050
}
TXTSET() {
-4, $c051
}
MIXCLR() {
-4, $c052
}
MIXSET() {
-4, $c053
}
TXTPAGE1() {
-4, $c054
}
TXTPAGE2() {
-4, $c055
}
LORES() {
-4, $c056
}
HIRES() {
-4, $c057
}
CLRAN0() {
-4, $c058
}
SETAN0() {
-4, $c059
}
CLRAN1() {
-4, $c05a
}
SETAN1() {
-4, $c05b
}
CLRAN2() {
-4, $c05c
}
SETAN2() {
-4, $c05d
}
DHIRESON() {
-4, $c05e
}
DHIRESOFF() {
-4, $c05f
}
TAPEIN() {
-4, $c060
}
RDBTN0() {
-4, $c061
}
RDBTN1() {
-4, $c062
}
RDBTN2() {
-4, $c063
}
PADDL0() {
-4, $c064
}
PADDL1() {
-4, $c065
}
PADDL2() {
-4, $c066
}
PADDL3() {
-4, $c067
}
STATEREG() {
-4, $c068
}
TESTREG() {
-4, $c069
}
CLTRM() {
-4, $c06e
}
ENTM() {
-4, $c06f
}
PTRIG() {
-4, $c070
}
BANKSEL() {
-4, $c073
}
IOUDISON() {
-4, $c07e
}
IOUDISOFF() {
-4, $c07f
}
ROMIN() {
-4, $c081
}
LCBANK2() {
-4, $c083
}
LCBANK1() {
-4, $c08b
}
PH0_off() {
-4, $c0e0
}
PH0_on() {
-4, $c0e1
}
PH1_off() {
-4, $c0e2
}
PH1_on() {
-4, $c0e3
}
PH2_off() {
-4, $c0e4
}
PH2_on() {
-4, $c0e5
}
PH3_off() {
-4, $c0e6
}
PH3_on() {
-4, $c0e7
}
Motor_off() {
-4, $c0e8
}
Motor_on() {
-4, $c0e9
}
Drive_1() {
-4, $c0ea
}
Drive_2() {
-4, $c0eb
}
Q6_off() {
-4, $c0ec
}
Q6_on() {
-4, $c0ed
}
Q7_off() {
-4, $c0ee
}
Q7_on() {
-4, $c0ef
}
AUXMOVE() {
-4, $c311
}
XFER() {
-4, $c314
}
CLRROM() {
-4, $cfff
}
NEW() {
-4, $e5ad
}
RESUME() {
-4, $f317
}
HGR() {
-4, $f3de
}
PLOT() {
-4, $f800
}
PLOT1() {
-4, $f80e
}
HLINE() {
-4, $f819
}
VLINE() {
-4, $f828
}
CLRSCR() {
-4, $f832
}
CLRTOP() {
-4, $f836
}
GBASCALC() {
-4, $f847
}
NXTCOL() {
-4, $f85f
}
SETCOL() {
-4, $f864
}
SCRN() {
-4, $f871
}
INSDS1() {
-4, $f88c
}
INSDS2() {
-4, $f88e
}
GET816LEN() {
-4, $f890
}
INSTDSP() {
-4, $f8d0
}
PRNTYX() {
-4, $f940
}
PRNTAX() {
-4, $f941
}
PRNTX() {
-4, $f944
}
PRBLNK() {
-4, $f948
}
PRBL2() {
-4, $f94a
}
PCADJ() {
-4, $f953
}
TEXT2COPY() {
-4, $f962
}
OLDIRQ() {
-4, $fa40
}
BREAK() {
-4, $fa4c
}
OLDBRK() {
-4, $fa59
}
RESET() {
-4, $fa62
}
PWRUP() {
-4, $faa6
}
SLOOP() {
-4, $faba
}
REGDSP() {
-4, $fad7
}
RTBL() {
-4, $fb19
}
PREAD() {
-4, $fb1e
}
PREAD4() {
-4, $fb21
}
INIT() {
-4, $fb2f
}
SETTXT() {
-4, $fb39
}
SETGR() {
-4, $fb40
}
SETWND() {
-4, $fb4b
}
SETWND2() {
-4, $fb51
}
TABV() {
-4, $fb5b
}
APPLEII() {
-4, $fb60
}
SETPWRC() {
-4, $fb6f
}
VIDWAIT() {
-4, $fb78
}
KBDWAIT() {
-4, $fb88
}
VERSION() {
-4, $fbb3
}
ZIDBYTE2() {
-4, $fbbf
}
ZIDBYTE() {
-4, $fbc0
}
BASCALC() {
-4, $fbc1
}
BELL1() {
-4, $fbdd
}
BELL12() {
-4, $fbe2
}
BELL2() {
-4, $fbe4
}
STORADV() {
-4, $fbf0
}
ADVANCE() {
-4, $fbf4
}
VIDOUT() {
-4, $fbfd
}
BS() {
-4, $fc10
}
UP() {
-4, $fc1a
}
VTAB() {
-4, $fc22
}
VTABZ() {
-4, $fc24
}
ESC() {
-4, $fc2c
}
CLREOP() {
-4, $fc42
}
HOME() {
-4, $fc58
}
CR() {
-4, $fc62
}
LF() {
-4, $fc66
}
SCROLL() {
-4, $fc70
}
CLREOL() {
-4, $fc9c
}
CLREOLZ() {
-4, $fc9e
}
WAIT() {
-4, $fca8
}
NXTA4() {
-4, $fcb4
}
NXTA1() {
-4, $fcba
}
HEADR() {
-4, $fcc9
}
RDKEY() {
-4, $fd0c
}
FD10() {
-4, $fd10
}
RDKEY1() {
-4, $fd18
}
KEYIN() {
-4, $fd1b
}
RDCHAR() {
-4, $fd35
}
GETLNZ() {
-4, $fd67
}
GETLN() {
-4, $fd6a
}
GETLN0() {
-4, $fd6c
}
GETLN1() {
-4, $fd6f
}
CROUT1() {
-4, $fd8b
}
CROUT() {
-4, $fd6e
}
PRA1() {
-4, $fd92
}
PRBYTE() {
-4, $fdda
}
PRHEX() {
-4, $fde3
}
COUT() {
-4, $fded
}
COUT1() {
-4, $fdf0
}
COUTZ() {
-4, $fdf6
}
IDROUTINE() {
-4, $fe1f
}
MOVE() {
-4, $fe2c
}
LIST() {
-4, $fe5e
}
INVERSE() {
-4, $fe80
}
NORMAL() {
-4, $fe84
}
SETKBD() {
-4, $fe89
}
INPORT() {
-4, $fe8b
}
SETVID() {
-4, $fe93
}
OUTPORT() {
-4, $fe95
}
GO() {
-4, $feb6
}
WRITE() {
-4, $fecd
}
READ() {
-4, $fefd
}
PRERR() {
-4, $ff2d
}
BELL() {
-4, $ff3a
}
RESTORE() {
-4, $ff3f
}
RSTR1() {
-4, $ff44
}
SAVE() {
-4, $ff4a
}
SAV1() {
-4, $ff4c
}
IORTS() {
-4, $ff58
}
OLDRST() {
-4, $ff59
}
MON() {
-4, $ff65
}
MONZ() {
-4, $ff69
}
MONZ2() {
-4, $ff6c
}
MONZ4() {
-4, $ff70
}
DIG() {
-4, $ff8a
}
GETNUM() {
-4, $ffa7
}
NXTCHR() {
-4, $ffad
}
TOSUB() {
-4, $ffbe
}
ZMODE() {
-4, $ffc7
}
StdText() {
-4, $e01e04
}
StdLine() {
-4, $e01e08
}
StdRect() {
-4, $e01e0c
}
StdRRect() {
-4, $e01e10
}
StdOval() {
-4, $e01e14
}
StdArc() {
-4, $e01e18
}
StdPoly() {
-4, $e01e1c
}
StdRgn() {
-4, $e01e20
}
StdPixels() {
-4, $e01e24
}
StdComment() {
-4, $e01e28
}
StdTxMeas() {
-4, $e01e2c
}
StdTxBnds() {
-4, $e01e30
}
StdGetPic() {
-4, $e01e34
}
StdPutPic() {
-4, $e01e38
}
ShieldCursor() {
-4, $e01e98
}
UnshieldCursor() {
-4, $e01e9c
}

View File

@ -1,19 +1,19 @@
OBJS = main.o omf.o handle.o map.o disasm.o api.o scanner.o OBJS = main.o omf.o handle.o map.o disasm.o api.o scanner.o
CXX = clang++ CXX = clang++
CXXFLAGS = -Wall -std=c++11 CXXFLAGS = -g -Wall -std=c++11
UNAME := $(shell uname) UNAME := $(shell uname)
ifeq ($(UNAME), Darwin) ifeq ($(UNAME), Darwin)
LDFLAGS = -largp LDFLAGS = -largp
endif endif
all: regs all: ../regs
regs: $(OBJS) ../regs: $(OBJS)
$(CXX) $(CXXFLAGS) $(LIBS) -o $@ $(LDFLAGS) $^ $(CXX) $(CXXFLAGS) $(LIBS) -o $@ $(LDFLAGS) $^
%.o: %.cc %.o: %.cc
$(CXX) -c $(CXXFLAGS) -o $@ $< $(CXX) -c $(CXXFLAGS) -o $@ $<
clean: clean:
rm -f regs $(OBJS) rm -f ../regs $(OBJS)

View File

@ -196,6 +196,6 @@ void API::setFunction(Handle h, std::shared_ptr<symbol::Symbol> s) {
setRef(h, f->returnType); setRef(h, f->returnType);
auto numSig = h->r32(); auto numSig = h->r32();
for (uint32_t i = 0; i < numSig; i++) { for (uint32_t i = 0; i < numSig; i++) {
f->signature.push_back(h->r32()); f->signature.push_back(static_cast<int32_t>(h->r32()));
} }
} }

View File

@ -46,7 +46,7 @@ struct Argument {
struct Function : public Symbol { struct Function : public Symbol {
std::vector<Argument> arguments; std::vector<Argument> arguments;
std::shared_ptr<Ref> returnType; std::shared_ptr<Ref> returnType;
std::vector<uint32_t> signature; std::vector<int32_t> signature;
}; };
struct Field { struct Field {

View File

@ -43,7 +43,7 @@ bool Disassembler::disassemble(std::vector<Segment> segments,
std::cerr << "Failed to open '" << fname << "' for writing" << std::endl; std::cerr << "Failed to open '" << fname << "' for writing" << std::endl;
return false; return false;
} }
f << "Section $" << hex(segment.segnum, Value) << " " f << "Segment " << hex(segment.segnum, 2) << " "
<< segment.name << std::endl; << segment.name << std::endl;
if (!scanner.disassemble(f, segment.mapped, if (!scanner.disassemble(f, segment.mapped,
segment.mapped + segment.length, segment.mapped + segment.length,
@ -80,7 +80,7 @@ std::shared_ptr<Inst> Disassembler::decodeInst(Handle f, Entry *entry) {
break; break;
case IMM: case IMM:
inst->oper = f->r8(); inst->oper = f->r8();
inst->operType = Opr::Imm; inst->operType = Opr::Imm8;
if (opcode == 0xe2) { if (opcode == 0xe2) {
entry->flags |= inst->oper & IsFlags; entry->flags |= inst->oper & IsFlags;
} else if (opcode == 0xc2) { } else if (opcode == 0xc2) {
@ -96,22 +96,24 @@ std::shared_ptr<Inst> Disassembler::decodeInst(Handle f, Entry *entry) {
case IMMM: case IMMM:
if (entry->flags & (IsEmu | IsM8)) { if (entry->flags & (IsEmu | IsM8)) {
inst->oper = f->r8(); inst->oper = f->r8();
inst->operType = Opr::Imm8;
} else { } else {
inst->oper = f->r16(); inst->oper = f->r16();
inst->operType = Opr::Imm16;
} }
inst->operType = Opr::Imm;
break; break;
case IMMX: case IMMX:
if (entry->flags & (IsEmu | IsX8)) { if (entry->flags & (IsEmu | IsX8)) {
inst->oper = f->r8(); inst->oper = f->r8();
inst->operType = Opr::Imm8;
} else { } else {
inst->oper = f->r16(); inst->oper = f->r16();
inst->operType = Opr::Imm16;
} }
inst->operType = Opr::Imm;
break; break;
case IMMS: case IMMS:
inst->oper = f->r16(); inst->oper = f->r16();
inst->operType = Opr::Imm; inst->operType = Opr::Imm16;
break; break;
case ABS: case ABS:
inst->oper = f->r16(); inst->oper = f->r16();
@ -260,75 +262,83 @@ std::string Disassembler::printInst(std::shared_ptr<Inst> inst) {
switch (inst->operType) { switch (inst->operType) {
case Opr::None: case Opr::None:
break; break;
case Opr::Imm: case Opr::Imm8:
args = "#" + hex(inst->oper, Value); args = "#" + hex(inst->oper, 2);
break;
case Opr::Imm16:
args = "#" + hex(inst->oper, 4);
break; break;
case Opr::Abs: case Opr::Abs:
args = hex(inst->oper, Address); args = hex(inst->oper, 6);
break; break;
case Opr::AbsB: case Opr::AbsB:
args = "B:" + hex(inst->oper, Value); args = "B:" + hex(inst->oper, 4);
comment += lookup(inst->oper);
break; break;
case Opr::AbsD: case Opr::AbsD:
args = "D:" + hex(inst->oper, Value); args = "D:" + hex(inst->oper, 2);
break; break;
case Opr::AbsX: case Opr::AbsX:
args = hex(inst->oper, Address) + ", x"; args = hex(inst->oper, 6) + ", x";
break; break;
case Opr::AbsXB: case Opr::AbsXB:
args = "B:" + hex(inst->oper, Value) + ", x"; args = "B:" + hex(inst->oper, 4) + ", x";
comment += lookup(inst->oper);
break; break;
case Opr::AbsXD: case Opr::AbsXD:
args = "D:" + hex(inst->oper, Value) + ", x"; args = "D:" + hex(inst->oper, 2) + ", x";
break; break;
case Opr::AbsY: case Opr::AbsY:
args = hex(inst->oper, Address) + ", y"; args = hex(inst->oper, 6) + ", y";
break; break;
case Opr::AbsYB: case Opr::AbsYB:
args = "B:" + hex(inst->oper, Value) + ", y"; args = "B:" + hex(inst->oper, 4) + ", y";
comment += lookup(inst->oper);
break; break;
case Opr::AbsYD: case Opr::AbsYD:
args = "D:" + hex(inst->oper, Value) + ", y"; args = "D:" + hex(inst->oper, 2) + ", y";
break; break;
case Opr::AbsS: case Opr::AbsS:
args = hex(inst->oper, Value) + ", s"; args = hex(inst->oper, 2) + ", s";
break; break;
case Opr::Ind: case Opr::Ind:
args = "(" + hex(inst->oper, Address) + ")"; args = "(" + hex(inst->oper, 6) + ")";
break; break;
case Opr::IndB: case Opr::IndB:
args = "(B:" + hex(inst->oper, Value) + ")"; args = "(B:" + hex(inst->oper, 4) + ")";
comment += lookup(inst->oper);
break; break;
case Opr::IndD: case Opr::IndD:
args = "(D:" + hex(inst->oper, Value) + ")"; args = "(D:" + hex(inst->oper, 2) + ")";
break; break;
case Opr::IndX: case Opr::IndX:
args = "(" + hex(inst->oper, Address) + ", x)"; args = "(" + hex(inst->oper, 6) + ", x)";
break; break;
case Opr::IndXB: case Opr::IndXB:
args = "(B:" + hex(inst->oper, Value) + ", x)"; args = "(B:" + hex(inst->oper, 4) + ", x)";
comment += lookup(inst->oper);
break; break;
case Opr::IndY: case Opr::IndY:
args = "(" + hex(inst->oper, Address) + "), y"; args = "(" + hex(inst->oper, 6) + "), y";
break; break;
case Opr::IndL: case Opr::IndL:
args = "[" + hex(inst->oper, Address) + "]"; args = "[" + hex(inst->oper, 6) + "]";
break; break;
case Opr::IndLY: case Opr::IndLY:
args = "[" + hex(inst->oper, Address) + "], y"; args = "[" + hex(inst->oper, 6) + "], y";
break; break;
case Opr::IndS: case Opr::IndS:
args = "(" + hex(inst->oper, Value) + ", s), y"; args = "(" + hex(inst->oper, 2) + ", s), y";
break; break;
case Opr::Bank: case Opr::Bank:
args = hex(inst->oper >> 8, Value) + ", " + hex(inst->oper & 0xff, Value); args = hex(inst->oper >> 8, 2) + ", " + hex(inst->oper & 0xff, 2);
break; break;
} }
if (inst->flags & IsEmuChanged) { if (inst->flags & IsEmuChanged) {
if (inst->flags & IsEmu) { if (inst->flags & IsEmu) {
comment = " 8-bit mode"; comment += " 8-bit mode";
} else { } else {
comment = " 16-bit mode"; comment += " 16-bit mode";
} }
} }
if (inst->flags & IsM8Changed) { if (inst->flags & IsM8Changed) {
@ -345,7 +355,11 @@ std::string Disassembler::printInst(std::shared_ptr<Inst> inst) {
comment += " x.w"; comment += " x.w";
} }
} }
std::string r = args; std::string r = inst->name;
while (r.length() < 8) {
r += " ";
}
r += args;
if (!comment.empty()) { if (!comment.empty()) {
while (r.length() < 20) { while (r.length() < 20) {
r += " "; r += " ";
@ -355,42 +369,28 @@ std::string Disassembler::printInst(std::shared_ptr<Inst> inst) {
return r; return r;
} }
std::string Disassembler::hex(uint32_t val, HexType type) { std::string Disassembler::lookup(uint32_t val) {
std::string ret; return symbols[val];
int width = 0; }
if (type == HexType::Address) {
ret = symbols[val]; std::string Disassembler::hex(uint32_t val, int width) {
} static const char *digits = "0123456789abcdef";
if (ret.empty()) { std::string ret;
if ((val & ~0xff) == ~0xff) { if (width == 6) {
ret += "$-"; ret = symbols[val];
val = ~val + 1; if (!ret.empty()) {
width = 2; return ret;
} else if ((val & ~0xff) == 0) { }
ret += "$"; ret = "$00/0000";
width = 2; for (size_t i = 0, j = 5 << 2; i < 6; i++, j -= 4) {
} else if ((val & ~0xffff) == ~0xffff) { ret[i < 2 ? i + 1 : i + 2] = digits[(val >> j) & 0xf];
ret += "$-"; }
val = ~val + 1; return ret;
width = 4; }
} else if ((val & ~0xffff) == 0) { ret = "$";
ret += "$"; std::string h(width, '0');
width = 4; for (int i = 0, j = (width - 1) << 2; i < width; i++, j -= 4) {
} else if (val & 0x80000000) { h[i] = digits[(val >> j) & 0xf];
ret += "$-"; }
width = 8; return ret + h;
} else {
ret += "$";
width = 8;
}
for (int i = 0; i < width; i++) {
uint8_t ch = val >> (width - (i + 1)) * 4;
if (ch < 10) {
ret += static_cast<char>(ch + '0');
} else {
ret += static_cast<char>(ch - 10 + 'a');
}
}
}
return ret;
} }

View File

@ -26,14 +26,10 @@ enum InsType : uint16_t {
Invalid = 0xff, Invalid = 0xff,
}; };
enum HexType {
Value = 0x01,
Address = 0x02,
};
enum class Opr { enum class Opr {
None = 0, Imm, Abs, AbsB, AbsD, AbsX, AbsXB, AbsXD, AbsY, AbsYB, AbsYD, AbsS, None = 0, Imm8, Imm16, Abs, AbsB, AbsD, AbsX, AbsXB, AbsXD,
Ind, IndB, IndD, IndX, IndXB, IndY, IndL, IndLY, IndS, Bank, AbsY, AbsYB, AbsYD, AbsS, Ind, IndB, IndD, IndX, IndXB,
IndY, IndL, IndLY, IndS, Bank,
}; };
struct Inst { struct Inst {
@ -56,7 +52,8 @@ class Disassembler {
std::string printInst(std::shared_ptr<Inst> inst); std::string printInst(std::shared_ptr<Inst> inst);
std::shared_ptr<Inst> decodeInst(Handle f, Entry *entry); std::shared_ptr<Inst> decodeInst(Handle f, Entry *entry);
bool valid(uint32_t address); bool valid(uint32_t address);
std::string hex(uint32_t value, HexType type); std::string hex(uint32_t value, int width);
std::string lookup(uint32_t value);
std::map<uint32_t, std::string> symbols; std::map<uint32_t, std::string> symbols;
std::shared_ptr<Fingerprints> fingerprints; std::shared_ptr<Fingerprints> fingerprints;

View File

@ -60,8 +60,8 @@ uint32_t TheHandle::r32() {
uint32_t TheHandle::r24() { uint32_t TheHandle::r24() {
uint32_t r = *pos++; uint32_t r = *pos++;
r |= *pos << 8; r |= *pos++ << 8;
r |= *pos << 16; r |= *pos++ << 16;
return r; return r;
} }

15204
src/iigs.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
#include "disasm.h" #include "disasm.h"
#include "omf.h" #include "omf.h"
#include "api.h" #include "api.h"
#include "../iigs.c" #include "iigs.h"
const char *argp_program_version = "regs 0.2"; const char *argp_program_version = "regs 0.2";
const char *argp_program_bug_address = "sean@seancode.com"; const char *argp_program_bug_address = "sean@seancode.com";
@ -105,27 +105,31 @@ static struct argp argp = { options, parse_opt, args_doc, doc };
int main(int argc, char **argv) { int main(int argc, char **argv) {
struct arguments arguments; struct arguments arguments;
arguments.filename = ""; arguments.filename = "";
arguments.org = 0x300; arguments.org = 0;
arguments.flags = 0; arguments.flags = 0;
argp_parse(&argp, argc, argv, 0, 0, &arguments); argp_parse(&argp, argc, argv, 0, 0, &arguments);
// load map if it exists // load map if it exists
Map map(arguments.filename); Map map(arguments.filename, arguments.org);
OMF omf; OMF omf;
if (!omf.load(arguments.filename, arguments.org)) { if (!omf.load(arguments.filename, map.org)) {
std::cerr << "Failed to load " << arguments.filename << std::endl; std::cerr << "Failed to load " << arguments.filename << std::endl;
return -1; return -1;
} }
auto segments = omf.get(); auto segments = omf.get();
if (map.needsEntry()) { if (map.needsEntry()) {
for (auto &s : segments) { for (auto &s : segments) {
if ((s.kind & 0x1f) == 0) { // code if ((s.kind & 0x1f) == 0) { // first code
map.addEntry(s.mapped + s.entry, arguments.flags); map.addEntry(s.mapped + s.entry, arguments.flags);
break; break;
} }
} }
} }
// note that we save the map here.. before we add a bunch of symbols
// from the api
map.save();
API api(iigs_dat, iigs_dat_len); API api(iigs_dat, iigs_dat_len);
auto prints = std::make_shared<Fingerprints>(); auto prints = std::make_shared<Fingerprints>();
@ -159,6 +163,8 @@ int main(int argc, char **argv) {
sig7[3] = f->signature[2]; sig7[3] = f->signature[2];
prints->add(sig5, f->name, f->signature[1]); prints->add(sig5, f->name, f->signature[1]);
prints->add(sig7, f->name, f->signature[1]); prints->add(sig7, f->name, f->signature[1]);
} else if (f->signature[0] == -4) { // symbol
map.addSymbol(f->signature[1], f->name);
} }
} }
} }

View File

@ -3,8 +3,16 @@
#include <string> #include <string>
#include <fstream> #include <fstream>
Map::Map(const char *filename) { struct Field {
std::string mapname = filename; uint32_t org;
std::string flags;
bool isEntry;
bool isOrg;
std::string symbol;
};
Map::Map(const char *filename, uint32_t org) : org(org) {
mapname = filename;
mapname += ".regs"; mapname += ".regs";
File file(mapname); File file(mapname);
if (!file.is_open()) { if (!file.is_open()) {
@ -13,23 +21,18 @@ Map::Map(const char *filename) {
while (!file.eof()) { while (!file.eof()) {
uint32_t ofs = file.hex(); uint32_t ofs = file.hex();
if (!ofs) { if (file.check('!')) {
return; if (!this->org) { // commandline overrides
this->org = ofs;
}
} }
if (file.check(':')) { if (file.check(':')) {
Entry entry; Entry entry;
entry.org = ofs; entry.org = ofs;
entry.flags = 0; entry.flags = 0;
uint8_t ch; uint8_t ch;
while ((ch = file.oneOf("oemx")) != 0) { while ((ch = file.oneOf("emx")) != 0) {
switch (ch) { switch (ch) {
case 'o':
if (this->org) {
file.error("Duplicate org address");
return;
}
this->org = ofs;
break;
case 'e': case 'e':
entry.flags |= IsEmu; entry.flags |= IsEmu;
break; break;
@ -49,6 +52,55 @@ Map::Map(const char *filename) {
} }
} }
static bool compareFields(const Field &a, const Field &b) {
return a.org < b.org;
}
void Map::save() {
std::map<uint32_t, Field> fields;
fields[this->org].isOrg = true;
for (auto & entryPoint : entryPoints) {
auto org = entryPoint.org;
fields[org].isEntry = true;
if (entryPoint.flags & IsEmu) {
fields[org].flags += 'e';
}
if (entryPoint.flags & IsM8) {
fields[org].flags += 'm';
}
if (entryPoint.flags & IsX8) {
fields[org].flags += 'x';
}
}
for (auto sym : symbols) {
fields[sym.first].symbol = sym.second;
}
std::vector<Field> outFields;
for (auto field : fields) {
field.second.org = field.first;
outFields.push_back(field.second);
}
std::sort(outFields.begin(), outFields.end(), compareFields);
std::ofstream f(mapname, std::ios::out | std::ios::binary | std::ios::trunc);
for (auto field : outFields) {
f << toAddress(field.org);
if (field.isOrg) {
f << "!";
}
if (field.isEntry) {
f << ":";
}
if (!field.flags.empty()) {
f << field.flags;
}
if (!field.symbol.empty()) {
f << "<" << field.symbol << ">";
}
f << std::endl;
}
f.close();
}
bool Map::needsEntry() { bool Map::needsEntry() {
return entryPoints.size() == 0; return entryPoints.size() == 0;
} }
@ -68,6 +120,10 @@ void Map::addEntry(uint32_t entry, uint32_t flags) {
entryPoints.push_back(e); entryPoints.push_back(e);
} }
void Map::addSymbol(uint32_t ofs, std::string name) {
symbols[ofs] = name;
}
File::File(const std::string &filename) { File::File(const std::string &filename) {
data = p = nullptr; data = p = nullptr;
std::ifstream f(filename, std::ios::in | std::ios::binary | std::ios::ate); std::ifstream f(filename, std::ios::in | std::ios::binary | std::ios::ate);
@ -99,7 +155,7 @@ void File::ws() {
bool File::eof() { bool File::eof() {
ws(); ws();
return p < end; return p >= end;
} }
uint32_t File::hex() { uint32_t File::hex() {
@ -130,6 +186,7 @@ uint32_t File::hex() {
bool File::check(uint8_t ch) { bool File::check(uint8_t ch) {
ws(); ws();
if (p < end && ch == *p) { if (p < end && ch == *p) {
p++;
return true; return true;
} }
return false; return false;
@ -155,3 +212,12 @@ std::string File::until(uint8_t ch) {
p++; // skip ending character p++; // skip ending character
return r; return r;
} }
std::string Map::toAddress(uint32_t value) {
static const char *digits = "0123456789abcdef";
std::string ret="$00/0000";
for (size_t i = 0, j = 5 << 2; i < 6; i++, j -= 4) {
ret[i < 2 ? i + 1 : i + 2] = digits[(value >> j) & 0xf];
}
return ret;
}

View File

@ -31,14 +31,18 @@ struct Entry {
class Map { class Map {
public: public:
Map(const char *filename); Map(const char *filename, uint32_t org);
void save();
bool needsEntry(); bool needsEntry();
std::vector<Entry> getEntries(); std::vector<Entry> getEntries();
std::map<uint32_t, std::string> getSymbols(); std::map<uint32_t, std::string> getSymbols();
void addEntry(uint32_t entry, uint32_t flags); void addEntry(uint32_t entry, uint32_t flags);
void addSymbol(uint32_t org, std::string name);
uint32_t org; uint32_t org;
private: private:
std::string mapname;
std::vector<Entry> entryPoints; std::vector<Entry> entryPoints;
std::map<uint32_t, std::string> symbols; std::map<uint32_t, std::string> symbols;
std::string toAddress(uint32_t val);
}; };

View File

@ -30,6 +30,7 @@ bool OMF::load(const char *filename, uint32_t org) {
seg.entry = 0; seg.entry = 0;
seg.mapped = org; seg.mapped = org;
seg.data = handle; seg.data = handle;
seg.length = seg.bytecnt;
segments.push_back(seg); segments.push_back(seg);
} else { } else {
if (!loadSegments()) { if (!loadSegments()) {

View File

@ -69,9 +69,9 @@ bool Scanner::trace(const Entry &start,
} }
map[addr] = inst; map[addr] = inst;
if (inst->type == Jump || inst->type == Branch || inst->type == Call) { if (inst->type == Jump || inst->type == Branch || inst->type == Call) {
if (inst->operType == Opr::Imm || inst->operType == Opr::Abs) { if (inst->operType == Opr::Abs) {
if (valid(inst->oper) && labels.find(inst->oper) == labels.end()) { if (valid(inst->oper) && labels.find(inst->oper) == labels.end()) {
workList.push({state.flags, inst->oper}); workList.push({inst->oper, state.flags});
labels[inst->oper] = inst->oper; labels[inst->oper] = inst->oper;
} }
} }
@ -118,7 +118,7 @@ bool Scanner::basicBlocks() {
block->length = branch->first - block->address; block->length = branch->first - block->address;
if (b->type != Return && b->type != Invalid) { if (b->type != Return && b->type != Invalid) {
// branch has a destination // branch has a destination
if (b->operType == Opr::Imm || b->operType == Opr::Abs) { if (b->operType == Opr::Abs) {
if (valid(b->oper)) { if (valid(b->oper)) {
auto next = getBlock(b->oper); auto next = getBlock(b->oper);
next->preds.push_back(block); next->preds.push_back(block);
@ -171,8 +171,8 @@ bool Scanner::disassemble(std::ostream &f, uint32_t from, uint32_t to,
auto count = 0; auto count = 0;
std::string preds; std::string preds;
for (auto pred : b->preds) { for (auto pred : b->preds) {
if (pred->address + pred->length != b->address && count++ < 4) { if (pred->address + pred->length != b->address && count++ < 7) {
preds += (pred->address < b->address) ? u8"\u2b9d" : u8"\u2b9f"; preds += (pred->address < b->address) ? u8"\u2b06 " : u8"\u2b07 ";
preds += hex(pred->address + pred->length - pred->branchLen, 6); preds += hex(pred->address + pred->length - pred->branchLen, 6);
} }
} }
@ -205,20 +205,30 @@ void Scanner::dumpHex(std::ostream &f, uint32_t from, uint32_t to) {
for (int i = 0; i < len; i += 16) { for (int i = 0; i < len; i += 16) {
f << hex(from, 6) << ": "; f << hex(from, 6) << ": ";
std::string ascii; std::string ascii;
int skip = from & 0xf;
int j = 0; int j = 0;
for (; j < 16 && !ptr->eof(); j++) { for (; j < skip; j++) {
uint8_t ch = ptr->r8(); if (j == 8) {
f << hex(ch, 2) << " ";
ascii += isprint(ch) ? static_cast<char>(ch) : '.';
if (j == 7) {
f << " "; f << " ";
ascii += " "; ascii += " ";
} }
f << " ";
ascii += " ";
}
for (; j < 16 && !ptr->eof(); j++) {
if (j == 8) {
f << " ";
ascii += " ";
}
uint8_t ch = ptr->r8();
f << hex(ch, 2) << " ";
ascii += isprint(ch) ? static_cast<char>(ch) : '.';
from++;
} }
for (; j < 16; j++) { for (; j < 16; j++) {
f << " "; f << " ";
} }
f << "|" << ascii << std::endl; f << "| " << ascii << std::endl;
} }
} }
} }
@ -259,6 +269,13 @@ std::shared_ptr<Block> Scanner::getBlock(uint32_t address) {
std::string Scanner::hex(uint32_t value, size_t len) { std::string Scanner::hex(uint32_t value, size_t len) {
static const char *digits = "0123456789abcdef"; static const char *digits = "0123456789abcdef";
if (len == 6) {
std::string ret="00/0000";
for (size_t i = 0, j = 5 << 2; i < 6; i++, j -= 4) {
ret[i < 2 ? i : i + 1] = digits[(value >> j) & 0xf];
}
return ret;
}
std::string ret(len, '0'); std::string ret(len, '0');
for (size_t i = 0, j = (len - 1) << 2; i < len; i++, j -= 4) { for (size_t i = 0, j = (len - 1) << 2; i < len; i++, j -= 4) {
ret[i] = digits[(value >> j) & 0xf]; ret[i] = digits[(value >> j) & 0xf];