mirror of
https://github.com/ksherlock/wdc-utils.git
synced 2024-06-26 15:29:34 +00:00
Compare commits
72 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a455e48a2b | ||
|
65d373be25 | ||
|
42347e4d40 | ||
|
3ab26264f6 | ||
|
9430f99270 | ||
|
32495371de | ||
|
8ff374eced | ||
|
b9ce1e2d3f | ||
|
ec6619c8c7 | ||
|
2364cae06a | ||
|
9fa57d0a12 | ||
|
ae182abaa4 | ||
|
66cf463cbf | ||
|
e7720a69bb | ||
|
d66de57273 | ||
|
ab5961c1a9 | ||
|
d3df7b2c47 | ||
|
885fcc7958 | ||
|
db1d452f53 | ||
|
236dc538b0 | ||
|
8147da2cfc | ||
|
5f9d1a900d | ||
|
348b97669b | ||
|
606747cba3 | ||
|
4f833d83a6 | ||
|
285763c318 | ||
|
7c07cbcd17 | ||
|
1e810db107 | ||
|
13389be323 | ||
|
2f2809dcb2 | ||
|
b9092401f6 | ||
|
b18467a641 | ||
|
7f3ccd84c8 | ||
|
ebd67dc0cc | ||
|
97787b30e4 | ||
|
e81e47d4c8 | ||
|
e43ace0d1c | ||
|
06a3c5b5ae | ||
|
4e51bd6c51 | ||
|
466c90a34e | ||
|
253a3ccc49 | ||
|
e9383cfcdc | ||
|
b29b208b06 | ||
|
dd0a369ac1 | ||
|
e693ad8ef3 | ||
|
91d7f60bff | ||
|
47130d0e67 | ||
|
bcb2ba03ef | ||
|
18c9ede89f | ||
|
c08c84c593 | ||
|
adafabd419 | ||
|
6aa7418561 | ||
|
ef838227d2 | ||
|
7e09ecd5f2 | ||
|
eed6958275 | ||
|
03f24ec829 | ||
|
6b99d138a2 | ||
|
5db92377d6 | ||
|
8ba832d9a9 | ||
|
e4e6febf7d | ||
|
d5105336dd | ||
|
ac071f1d9a | ||
|
7c71a97550 | ||
|
6aa54979a9 | ||
|
add8545906 | ||
|
25e6e61989 | ||
|
6d1e684f8d | ||
|
61c3b82aaf | ||
|
4317d2929b | ||
|
2ff8267af3 | ||
|
ff09d63678 | ||
|
11bce44253 |
17
.github/workflows/make.yml
vendored
Normal file
17
.github/workflows/make.yml
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
name: Make
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [macos-latest, ubuntu-latest]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- name: make
|
||||||
|
run: make all
|
32
.github/workflows/msys2.yml
vendored
Normal file
32
.github/workflows/msys2.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
name: MSYS2 build
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
msys: [MSYS, MINGW32, MINGW64]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Setup MSYS2
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
path-type: strict
|
||||||
|
msystem: ${{ matrix.msys }}
|
||||||
|
install: make gcc mingw32/mingw-w64-i686-gcc mingw64/mingw-w64-x86_64-gcc
|
||||||
|
|
||||||
|
# Runs a single command using the runners shell
|
||||||
|
- name: Make ${{ matrix.msys }}
|
||||||
|
run: msys2 -c 'make'
|
||||||
|
|
||||||
|
- name: Artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: binaries - ${{ matrix.msys }}
|
||||||
|
path: "*.exe"
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "afp"]
|
||||||
|
path = afp
|
||||||
|
url = https://github.com/ksherlock/afp
|
29
.travis.yml
29
.travis.yml
|
@ -1,27 +1,12 @@
|
||||||
language: generic
|
dist: bionic
|
||||||
os: osx
|
language: cpp
|
||||||
matrix:
|
os:
|
||||||
include:
|
- osx
|
||||||
- os: linux
|
- linux
|
||||||
env: COMPILER_NAME=gcc CXX=g++-5 CC=gcc-5
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- g++-5
|
|
||||||
sources: &sources
|
|
||||||
- llvm-toolchain-precise-3.8
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
- os: linux
|
|
||||||
env: COMPILER_NAME=clang CXX=clang++-3.8 CC=clang-3.8
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- clang-3.8
|
|
||||||
sources: *sources
|
|
||||||
|
|
||||||
script: make all
|
|
||||||
|
|
||||||
compiler:
|
compiler:
|
||||||
- clang
|
- clang
|
||||||
- gcc
|
- gcc
|
||||||
|
|
||||||
|
script: make all
|
||||||
|
|
||||||
|
|
26
Makefile
26
Makefile
|
@ -1,12 +1,19 @@
|
||||||
LINK.o = $(LINK.cc)
|
LINK.o = $(LINK.cc)
|
||||||
CXXFLAGS = -std=c++14 -g -Wall -Wno-sign-compare
|
CXXFLAGS = -std=c++14 -g -Wall -Wno-sign-compare
|
||||||
CCFLAGS = -g
|
CCFLAGS = -g
|
||||||
|
|
||||||
DUMP_OBJS = dumpobj.o disassembler.o zrdz_disassembler.o
|
DUMP_OBJS = dumpobj.o disassembler.o zrdz_disassembler.o
|
||||||
LINK_OBJS = link.o expression.o omf.o set_file_type.o
|
LINK_OBJS = link.o expression.o omf.o set_file_type.o afp/libafp.a
|
||||||
|
|
||||||
|
# static link if using mingw32 or mingw64 to make redistribution easier.
|
||||||
|
# also add mingw directory.
|
||||||
|
ifeq ($(MSYSTEM),MINGW32)
|
||||||
|
DUMP_OBJS += mingw/err.o
|
||||||
|
LINK_OBJS += mingw/err.o
|
||||||
|
CPPFLAGS += -I mingw/
|
||||||
|
LDLIBS += -static
|
||||||
|
endif
|
||||||
|
|
||||||
#UNAME_S := $(shell uname -s)
|
|
||||||
#ifeq ($(UNAME_S),MINGW64_NT-10.0)
|
|
||||||
ifeq ($(MSYSTEM),MINGW64)
|
ifeq ($(MSYSTEM),MINGW64)
|
||||||
DUMP_OBJS += mingw/err.o
|
DUMP_OBJS += mingw/err.o
|
||||||
LINK_OBJS += mingw/err.o
|
LINK_OBJS += mingw/err.o
|
||||||
|
@ -24,6 +31,9 @@ wdclink : $(LINK_OBJS)
|
||||||
$(LINK.o) $^ $(LDLIBS) -o $@
|
$(LINK.o) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
|
|
||||||
|
subdirs :
|
||||||
|
$(MAKE) -C afp
|
||||||
|
|
||||||
disassembler.o : disassembler.cpp disassembler.h
|
disassembler.o : disassembler.cpp disassembler.h
|
||||||
zrdz_disassembler.o : zrdz_disassembler.cpp zrdz_disassembler.h disassembler.h
|
zrdz_disassembler.o : zrdz_disassembler.cpp zrdz_disassembler.h disassembler.h
|
||||||
dumpobj.o : dumpobj.cpp zrdz_disassembler.h disassembler.h
|
dumpobj.o : dumpobj.cpp zrdz_disassembler.h disassembler.h
|
||||||
|
@ -31,9 +41,15 @@ omf.o : omf.cpp omf.h
|
||||||
expression.o : expression.cpp expression.h
|
expression.o : expression.cpp expression.h
|
||||||
mingw/err.o : mingw/err.c mingw/err.h
|
mingw/err.o : mingw/err.c mingw/err.h
|
||||||
|
|
||||||
|
set_file_type.o : CPPFLAGS += -I afp/include
|
||||||
|
set_file_type.o : set_file_type.cpp
|
||||||
|
|
||||||
|
afp/libafp.a : subdirs
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(RM) wdcdumpobj $(DUMP_OBJS) $(LINK_OBJS)
|
$(RM) wdcdumpobj wdclink $(DUMP_OBJS) $(LINK_OBJS)
|
||||||
|
$(MAKE) -C afp clean
|
||||||
|
|
||||||
|
|
||||||
.PHONY: variables
|
.PHONY: variables
|
||||||
|
|
1
afp
Submodule
1
afp
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit bf4399146d7402a390cad78102d4169e2a41ac04
|
435
disassembler.cpp
435
disassembler.cpp
|
@ -1,7 +1,11 @@
|
||||||
|
#define _XOPEN_SOURCE
|
||||||
|
|
||||||
#include "disassembler.h"
|
#include "disassembler.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
static constexpr const char opcodes[] =
|
static constexpr const char opcodes[] =
|
||||||
"brkoracoporatsboraaslora"
|
"brkoracoporatsboraaslora"
|
||||||
|
@ -49,6 +53,7 @@ static constexpr const int mDPI = 0x7000;
|
||||||
static constexpr const int mDPIL = 0x8000;
|
static constexpr const int mDPIL = 0x8000;
|
||||||
static constexpr const int mRelative = 0x9000;
|
static constexpr const int mRelative = 0x9000;
|
||||||
static constexpr const int mBlockMove = 0xa000;
|
static constexpr const int mBlockMove = 0xa000;
|
||||||
|
static constexpr const int mImpliedA = 0xb000; // inc a, dec a, etc.
|
||||||
|
|
||||||
static constexpr const int m_S = 0x0100;
|
static constexpr const int m_S = 0x0100;
|
||||||
static constexpr const int m_X = 0x0200;
|
static constexpr const int m_X = 0x0200;
|
||||||
|
@ -69,7 +74,7 @@ static constexpr const int modes[] =
|
||||||
1 | mDPIL, // 07 ora [dp]
|
1 | mDPIL, // 07 ora [dp]
|
||||||
0 | mImplied, // 08 php
|
0 | mImplied, // 08 php
|
||||||
1 | mImmediate | m_M, // 09 ora #imm
|
1 | mImmediate | m_M, // 09 ora #imm
|
||||||
0 | mImplied, // 0a asl a
|
0 | mImpliedA, // 0a asl a
|
||||||
0 | mImplied, // 0b phd
|
0 | mImplied, // 0b phd
|
||||||
2 | mAbsolute, // 0c tsb |abs
|
2 | mAbsolute, // 0c tsb |abs
|
||||||
2 | mAbsolute, // 0d ora |abs
|
2 | mAbsolute, // 0d ora |abs
|
||||||
|
@ -86,7 +91,7 @@ static constexpr const int modes[] =
|
||||||
1 | mDPIL | m_Y, // 17 ora [dp],y
|
1 | mDPIL | m_Y, // 17 ora [dp],y
|
||||||
0 | mImplied, // 18 clc
|
0 | mImplied, // 18 clc
|
||||||
2 | mAbsolute | m_Y, // 19 ora |abs,y
|
2 | mAbsolute | m_Y, // 19 ora |abs,y
|
||||||
0 | mImplied, // 1a inc a
|
0 | mImpliedA, // 1a inc a
|
||||||
0 | mImplied, // 1b tcs
|
0 | mImplied, // 1b tcs
|
||||||
2 | mAbsolute, // 1c trb |abs
|
2 | mAbsolute, // 1c trb |abs
|
||||||
2 | mAbsolute | m_X, // 1d ora |abs,x
|
2 | mAbsolute | m_X, // 1d ora |abs,x
|
||||||
|
@ -103,7 +108,7 @@ static constexpr const int modes[] =
|
||||||
1 | mDPIL, // 27 and [dp]
|
1 | mDPIL, // 27 and [dp]
|
||||||
0 | mImplied, // 28 plp
|
0 | mImplied, // 28 plp
|
||||||
1 | mImmediate | m_M, // 29 and #imm
|
1 | mImmediate | m_M, // 29 and #imm
|
||||||
0 | mImplied, // 2a rol a
|
0 | mImpliedA, // 2a rol a
|
||||||
0 | mImplied, // 2b pld
|
0 | mImplied, // 2b pld
|
||||||
2 | mAbsolute, // 2c bit |abs
|
2 | mAbsolute, // 2c bit |abs
|
||||||
2 | mAbsolute, // 2d and |abs
|
2 | mAbsolute, // 2d and |abs
|
||||||
|
@ -120,7 +125,7 @@ static constexpr const int modes[] =
|
||||||
1 | mDPIL | m_Y, // 37 and [dp],y
|
1 | mDPIL | m_Y, // 37 and [dp],y
|
||||||
0 | mImplied, // 38 sec
|
0 | mImplied, // 38 sec
|
||||||
2 | mAbsolute | m_Y, // 39 and |abs,y
|
2 | mAbsolute | m_Y, // 39 and |abs,y
|
||||||
0 | mImplied, // 3a dec a
|
0 | mImpliedA, // 3a dec a
|
||||||
0 | mImplied, // 3b tsc
|
0 | mImplied, // 3b tsc
|
||||||
2 | mAbsolute | m_X, // 3c bits |abs,x
|
2 | mAbsolute | m_X, // 3c bits |abs,x
|
||||||
2 | mAbsolute | m_X, // 3d and |abs,x
|
2 | mAbsolute | m_X, // 3d and |abs,x
|
||||||
|
@ -137,7 +142,7 @@ static constexpr const int modes[] =
|
||||||
1 | mDPIL, // 47 eor [dp]
|
1 | mDPIL, // 47 eor [dp]
|
||||||
0 | mImplied, // 48 pha
|
0 | mImplied, // 48 pha
|
||||||
1 | mImmediate | m_M, // 49 eor #imm
|
1 | mImmediate | m_M, // 49 eor #imm
|
||||||
0 | mImplied, // 4a lsr a
|
0 | mImpliedA, // 4a lsr a
|
||||||
0 | mImplied, // 4b phk
|
0 | mImplied, // 4b phk
|
||||||
2 | mAbsolute, // 4c jmp |abs
|
2 | mAbsolute, // 4c jmp |abs
|
||||||
2 | mAbsolute, // 4d eor |abs
|
2 | mAbsolute, // 4d eor |abs
|
||||||
|
@ -318,7 +323,7 @@ static constexpr const int modes[] =
|
||||||
1 | mDPI | m_Y, // f1 sbc (dp),y
|
1 | mDPI | m_Y, // f1 sbc (dp),y
|
||||||
1 | mDPI, // f2 sbc (dp)
|
1 | mDPI, // f2 sbc (dp)
|
||||||
1 | mDPI | m_S | m_Y, // f3 sbc ,s,y
|
1 | mDPI | m_S | m_Y, // f3 sbc ,s,y
|
||||||
2 | mImmediate, // f4 pea |abs --> pea #imm
|
2 | mAbsolute, // f4 pea |abs --> pea #imm
|
||||||
1 | mDP | m_X, // f5 sbc dp,x
|
1 | mDP | m_X, // f5 sbc dp,x
|
||||||
1 | mDP | m_X, // f6 inc dp,x
|
1 | mDP | m_X, // f6 inc dp,x
|
||||||
1 | mDPIL | m_Y, // f7 sbc [dp],y
|
1 | mDPIL | m_Y, // f7 sbc [dp],y
|
||||||
|
@ -333,6 +338,38 @@ static constexpr const int modes[] =
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool branchlike(uint8_t op) {
|
||||||
|
|
||||||
|
switch(op) {
|
||||||
|
case 0x10: // bpl
|
||||||
|
//case 0x20: // jsr
|
||||||
|
//case 0x22: // jsl
|
||||||
|
case 0x30: // bmi
|
||||||
|
case 0x40: // rti
|
||||||
|
case 0x4c: // jmp
|
||||||
|
case 0x50: // bvc
|
||||||
|
case 0x5c: // jml
|
||||||
|
case 0x60: // rts
|
||||||
|
case 0x6b: // rtl
|
||||||
|
case 0x6c: // jmp
|
||||||
|
case 0x70: // bvs
|
||||||
|
case 0x7c: // jmp
|
||||||
|
case 0x80: // bra
|
||||||
|
case 0x82: // brl
|
||||||
|
case 0x90: // bcc
|
||||||
|
case 0xb0: // bcs
|
||||||
|
case 0xd0: // bne
|
||||||
|
case 0xdc: // jml
|
||||||
|
case 0xf0: // beq
|
||||||
|
//case 0xfc: // jsr
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
constexpr const int kOpcodeTab = 20;
|
constexpr const int kOpcodeTab = 20;
|
||||||
constexpr const int kOperandTab = 30;
|
constexpr const int kOperandTab = 30;
|
||||||
constexpr const int kCommentTab = 80;
|
constexpr const int kCommentTab = 80;
|
||||||
|
@ -368,6 +405,15 @@ std::string disassembler::to_x(uint32_t x, unsigned bytes, char prefix) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int disassembler::operand_size(uint8_t op, bool m, bool x) {
|
||||||
|
unsigned mode = modes[op];
|
||||||
|
unsigned size = mode & 0x0f;
|
||||||
|
if ((mode & m_I) && x) size++;
|
||||||
|
if ((mode & m_M) && m) size++;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void disassembler::emit(const std::string &label) {
|
void disassembler::emit(const std::string &label) {
|
||||||
fputs(label.c_str(), stdout);
|
fputs(label.c_str(), stdout);
|
||||||
|
@ -378,13 +424,8 @@ void disassembler::emit(const std::string &label, const std::string &opcode) {
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
tmp = label;
|
tmp = label;
|
||||||
|
|
||||||
int column = tmp.length();
|
|
||||||
|
|
||||||
if (!opcode.empty()) {
|
if (!opcode.empty()) {
|
||||||
do {
|
indent_to(tmp, kOpcodeTab);
|
||||||
tmp.push_back(' ');
|
|
||||||
column++;
|
|
||||||
} while (column < kOpcodeTab);
|
|
||||||
tmp += opcode;
|
tmp += opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,22 +440,14 @@ void disassembler::emit(const std::string &label, const std::string &opcode, con
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
tmp = label;
|
tmp = label;
|
||||||
|
|
||||||
int column = tmp.length();
|
|
||||||
|
|
||||||
if (!opcode.empty()) {
|
if (!opcode.empty()) {
|
||||||
do {
|
indent_to(tmp, kOpcodeTab);
|
||||||
tmp.push_back(' ');
|
|
||||||
column++;
|
|
||||||
} while (column < kOpcodeTab);
|
|
||||||
tmp += opcode;
|
tmp += opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
column = tmp.length();
|
|
||||||
if (!operand.empty()) {
|
if (!operand.empty()) {
|
||||||
do {
|
indent_to(tmp, kOperandTab);
|
||||||
tmp.push_back(' ');
|
|
||||||
column++;
|
|
||||||
} while (column < kOperandTab);
|
|
||||||
tmp += operand;
|
tmp += operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,6 +456,33 @@ void disassembler::emit(const std::string &label, const std::string &opcode, con
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void disassembler::emit(const std::string &label, const std::string &opcode, const std::string &operand, const std::string &comment) {
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
tmp = label;
|
||||||
|
|
||||||
|
if (!opcode.empty()) {
|
||||||
|
indent_to(tmp, kOpcodeTab);
|
||||||
|
tmp += opcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!operand.empty()) {
|
||||||
|
indent_to(tmp, kOperandTab);
|
||||||
|
tmp += operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!comment.empty()) {
|
||||||
|
indent_to(tmp, kCommentTab);
|
||||||
|
tmp += "; ";
|
||||||
|
tmp += comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp.push_back('\n');
|
||||||
|
fputs(tmp.c_str(), stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void disassembler::reset() {
|
void disassembler::reset() {
|
||||||
|
@ -431,7 +491,36 @@ void disassembler::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<std::string, std::string>
|
||||||
|
disassembler::format_data(unsigned size, const uint8_t *data) {
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < size; ++i) {
|
||||||
|
if (i > 0) tmp += ", ";
|
||||||
|
tmp += to_x(data[i], 2, '$');
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair("db", tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::string, std::string>
|
||||||
|
disassembler::format_data(unsigned size, const std::string &data) {
|
||||||
|
|
||||||
|
switch(size) {
|
||||||
|
case 1: return std::make_pair("db", data);
|
||||||
|
case 2: return std::make_pair("dw", data);
|
||||||
|
case 3: return std::make_pair("da", data);
|
||||||
|
case 4: return std::make_pair("dl", data);
|
||||||
|
|
||||||
|
default: {
|
||||||
|
std::string tmp;
|
||||||
|
tmp = std::to_string(size) + " bytes";
|
||||||
|
return std::make_pair(tmp, data);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void disassembler::dump() {
|
void disassembler::dump() {
|
||||||
|
|
||||||
|
@ -440,15 +529,12 @@ void disassembler::dump() {
|
||||||
if (!_st) return;
|
if (!_st) return;
|
||||||
|
|
||||||
|
|
||||||
|
auto p = format_data(_st, _bytes);
|
||||||
|
|
||||||
indent_to(line, kOpcodeTab);
|
indent_to(line, kOpcodeTab);
|
||||||
line += "db";
|
line += p.first;
|
||||||
indent_to(line, kOperandTab);
|
indent_to(line, kOperandTab);
|
||||||
|
line += p.second;
|
||||||
|
|
||||||
for (unsigned i = 0; i < _st; ++i) {
|
|
||||||
if (i > 0) line += ", ";
|
|
||||||
line += to_x(_bytes[i], 2, '$');
|
|
||||||
}
|
|
||||||
|
|
||||||
hexdump(line);
|
hexdump(line);
|
||||||
line.push_back('\n');
|
line.push_back('\n');
|
||||||
|
@ -458,28 +544,23 @@ void disassembler::dump() {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void disassembler::dump(const std::string &expr, unsigned size) {
|
void disassembler::dump(const std::string &expr, unsigned size, uint32_t value) {
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
if (_st) dump();
|
if (_st) dump();
|
||||||
|
|
||||||
for (_st = 0; _st < size; ++_st) _bytes[_st] = 0;
|
for (_st = 0; _st < size; ++_st) {
|
||||||
|
_bytes[_st] = value & 0xff;
|
||||||
|
value >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto p = format_data(size, expr);
|
||||||
|
|
||||||
indent_to(line, kOpcodeTab);
|
indent_to(line, kOpcodeTab);
|
||||||
|
line += p.first;
|
||||||
switch(size) {
|
|
||||||
case 1: line += "db"; break;
|
|
||||||
case 2: line += "dw"; break;
|
|
||||||
case 3: line += "da"; break;
|
|
||||||
case 4: line += "dl"; break;
|
|
||||||
default:
|
|
||||||
line += std::to_string(size);
|
|
||||||
line += " bytes";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
indent_to(line, kOperandTab);
|
indent_to(line, kOperandTab);
|
||||||
line += expr;
|
line += p.second;
|
||||||
|
|
||||||
hexdump(line);
|
hexdump(line);
|
||||||
line.push_back('\n');
|
line.push_back('\n');
|
||||||
|
@ -512,7 +593,7 @@ void disassembler::space(unsigned size) {
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
indent_to(line, kOpcodeTab);
|
indent_to(line, kOpcodeTab);
|
||||||
line += "ds";
|
line += ds();
|
||||||
indent_to(line, kOperandTab);
|
indent_to(line, kOperandTab);
|
||||||
|
|
||||||
|
|
||||||
|
@ -544,21 +625,28 @@ void disassembler::space(unsigned size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void disassembler::operator()(const std::string &expr, unsigned size) {
|
void disassembler::operator()(const std::string &expr, unsigned size, uint32_t value) {
|
||||||
|
|
||||||
// todo -- what if label within size?
|
if (_st == 0 || !_code)
|
||||||
check_labels();
|
check_labels();
|
||||||
|
|
||||||
if (!_code) {
|
if (!_code) {
|
||||||
dump(expr, size);
|
dump(expr, size, value);
|
||||||
|
if (_inline_data) {
|
||||||
|
_inline_data -= size;
|
||||||
|
if (_inline_data <= 0) _code = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_st != 1 || size != _size) {
|
if (_st != 1 || size != _size) {
|
||||||
dump(expr, size);
|
dump(expr, size, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for(int i = 0; i < size; ++i) _bytes[_st++] = 0;
|
for (int i = 0; i < size; ++i) {
|
||||||
|
_bytes[_st++] = value & 0xff;
|
||||||
|
value >>= 8;
|
||||||
|
}
|
||||||
print(expr);
|
print(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,10 +654,18 @@ void disassembler::operator()(const std::string &expr, unsigned size) {
|
||||||
|
|
||||||
void disassembler::operator()(uint8_t byte) {
|
void disassembler::operator()(uint8_t byte) {
|
||||||
|
|
||||||
check_labels();
|
if (_st == 0 || !_code)
|
||||||
|
check_labels();
|
||||||
|
|
||||||
if (!_code) {
|
if (!_code) {
|
||||||
_bytes[_st++] = byte;
|
_bytes[_st++] = byte;
|
||||||
|
|
||||||
|
if (_inline_data && --_inline_data <= 0) {
|
||||||
|
dump();
|
||||||
|
_code = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_st == 4) dump();
|
if (_st == 4) dump();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -578,12 +674,24 @@ void disassembler::operator()(uint8_t byte) {
|
||||||
if (_st == 1) {
|
if (_st == 1) {
|
||||||
_op = byte;
|
_op = byte;
|
||||||
_mode = modes[_op];
|
_mode = modes[_op];
|
||||||
|
|
||||||
|
// bit hack
|
||||||
|
if (_traits & bit_hacks && _op == 0x2c) {
|
||||||
|
if (_next_label == _pc + 1) {
|
||||||
|
dump();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_traits & pea_immediate && _op == 0xf4) _mode = 2 | mImmediate;
|
||||||
_size = _mode & 0x0f;
|
_size = _mode & 0x0f;
|
||||||
if (_mode & _flags & m_I) _size++;
|
if (_mode & _flags & m_I) _size++;
|
||||||
if (_mode & _flags & m_M) _size++;
|
if (_mode & _flags & m_M) _size++;
|
||||||
|
|
||||||
if (!_size) {
|
if (!_size) {
|
||||||
print();
|
print();
|
||||||
|
|
||||||
|
if (branchlike(byte)) fputs("\n", stdout);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -591,42 +699,38 @@ void disassembler::operator()(uint8_t byte) {
|
||||||
_arg = _arg + (byte << shift);
|
_arg = _arg + (byte << shift);
|
||||||
if (_st <= _size) return;
|
if (_st <= _size) return;
|
||||||
|
|
||||||
switch(_op) {
|
uint8_t op = _op;
|
||||||
case 0xc2: // REP
|
uint32_t arg = _arg;
|
||||||
_flags |= (_arg & 0x30);
|
|
||||||
break;
|
if (_traits & track_rep_sep) {
|
||||||
case 0xe2: // SEP
|
switch(_op) {
|
||||||
_flags &= ~(_arg & 0x30);
|
case 0xc2: // REP
|
||||||
break;
|
_flags |= (_arg & 0x30);
|
||||||
|
break;
|
||||||
|
case 0xe2: // SEP
|
||||||
|
_flags &= ~(_arg & 0x30);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// all done... now print it.
|
// all done... now print it.
|
||||||
print();
|
print();
|
||||||
}
|
|
||||||
|
|
||||||
|
if (branchlike(op)) fputs("\n", stdout);
|
||||||
|
|
||||||
|
// todo -- subscribe to before/after events...
|
||||||
void disassembler::print_prefix() {
|
switch(op) {
|
||||||
|
case 0xc2:
|
||||||
switch(_mode & 0xf000) {
|
case 0xe2:
|
||||||
case mImmediate: printf("\t#"); break;
|
case 0x22:
|
||||||
case mDP: printf("\t<"); break;
|
case 0x5c:
|
||||||
case mDPI: printf("\t(<"); break;
|
case 0xdc:
|
||||||
case mDPIL: printf("\t[<"); break;
|
event(op, arg);
|
||||||
case mAbsoluteIL: printf("\t["); break;
|
|
||||||
|
|
||||||
case mRelative:
|
|
||||||
case mBlockMove:
|
|
||||||
printf("\t"); break;
|
|
||||||
|
|
||||||
// cop, brk are treated as absolute.
|
|
||||||
case mAbsolute:
|
|
||||||
if (_size == 1) printf("\t");
|
|
||||||
else printf("\t|");
|
|
||||||
break;
|
break;
|
||||||
case mAbsoluteLong: printf("\t>"); break;
|
|
||||||
case mAbsoluteI: printf("\t("); break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -692,36 +796,6 @@ std::string disassembler::suffix() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void disassembler::print_suffix() {
|
|
||||||
|
|
||||||
switch(_mode & 0x0f00) {
|
|
||||||
case m_X: printf(",x"); break;
|
|
||||||
case m_Y: if (!(_mode & (mDPI|mDPIL))) printf(",y"); break;
|
|
||||||
case m_S:
|
|
||||||
case m_S | m_Y:
|
|
||||||
printf(",s"); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(_mode & 0xf000) {
|
|
||||||
case mAbsoluteI:
|
|
||||||
case mDPI:
|
|
||||||
printf(")"); break;
|
|
||||||
case mAbsoluteIL:
|
|
||||||
case mDPIL:
|
|
||||||
printf("]"); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// (xxx,s),y
|
|
||||||
// (xxx),y
|
|
||||||
// [xxx],y
|
|
||||||
switch(_mode & 0x0f00) {
|
|
||||||
case m_Y: if (_mode & (mDPI|mDPIL)) printf(",y"); break;
|
|
||||||
case m_S | m_Y:
|
|
||||||
printf(",y"); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void disassembler::hexdump(std::string &line) {
|
void disassembler::hexdump(std::string &line) {
|
||||||
// print pc and hexdump...
|
// print pc and hexdump...
|
||||||
|
@ -743,33 +817,16 @@ void disassembler::hexdump(std::string &line) {
|
||||||
line += " ";
|
line += " ";
|
||||||
for (i = 0; i < _st; ++i) {
|
for (i = 0; i < _st; ++i) {
|
||||||
uint8_t c = _bytes[i];
|
uint8_t c = _bytes[i];
|
||||||
|
// msb flag?
|
||||||
|
if (_traits & msb_hexdump) c &= 0x7f;
|
||||||
if (isprint(c) && isascii(c)) line += c;
|
if (isprint(c) && isascii(c)) line += c;
|
||||||
else line += '.';
|
else line += '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string disassembler::label_for_address(uint32_t address) { return ""; }
|
||||||
void disassembler::hexdump() {
|
std::string disassembler::label_for_zp(uint32_t address) { return ""; }
|
||||||
// print pc and hexdump...
|
|
||||||
int i;
|
|
||||||
printf("%04x:", _pc);
|
|
||||||
for (i = 0; i < _st; ++i) {
|
|
||||||
printf(" %02x", _bytes[i]);
|
|
||||||
}
|
|
||||||
for ( ; i < 4; ++i) {
|
|
||||||
printf(" ");
|
|
||||||
}
|
|
||||||
printf(" ");
|
|
||||||
for (i = 0; i < _st; ++i) {
|
|
||||||
uint8_t c = _bytes[i];
|
|
||||||
if (isprint(c) && isascii(c)) putc(c, stdout);
|
|
||||||
else putc('.', stdout);
|
|
||||||
}
|
|
||||||
for ( ; i < 4; ++i) {
|
|
||||||
printf(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void disassembler::print() {
|
void disassembler::print() {
|
||||||
|
|
||||||
|
@ -785,8 +842,11 @@ void disassembler::print() {
|
||||||
if ((_size == 1) && (_arg & 0x80))
|
if ((_size == 1) && (_arg & 0x80))
|
||||||
pc += 0xff00;
|
pc += 0xff00;
|
||||||
pc &= 0xffff;
|
pc &= 0xffff;
|
||||||
tmp = to_x(pc, 4, '$');
|
|
||||||
|
|
||||||
// it would be really fancy if it checked for a label name @pc...
|
// it would be really fancy if it checked for a label name @pc...
|
||||||
|
tmp = label_for_address(pc);
|
||||||
|
if (tmp.empty()) tmp = to_x(pc, 4, '$');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case mBlockMove: {
|
case mBlockMove: {
|
||||||
|
@ -796,10 +856,25 @@ void disassembler::print() {
|
||||||
+ to_x((_arg >> 0) & 0xff, 2, '$');
|
+ to_x((_arg >> 0) & 0xff, 2, '$');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
case mDP:
|
||||||
|
case mDPI:
|
||||||
|
case mDPIL:
|
||||||
|
tmp = label_for_zp(_arg);
|
||||||
|
if (tmp.empty()) tmp = to_x(_arg, _size * 2, '$');
|
||||||
|
break;
|
||||||
|
|
||||||
|
//case mImmediate:
|
||||||
|
case mAbsolute:
|
||||||
|
case mAbsoluteI:
|
||||||
|
case mAbsoluteIL:
|
||||||
|
case mAbsoluteLong:
|
||||||
|
tmp = label_for_address(_arg);
|
||||||
|
if (tmp.empty()) tmp = to_x(_arg, _size * 2, '$');
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
tmp = to_x(_arg, _size * 2, '$');
|
tmp = to_x(_arg, _size * 2, '$');
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
print(tmp);
|
print(tmp);
|
||||||
return;
|
return;
|
||||||
|
@ -808,9 +883,17 @@ void disassembler::print() {
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
indent_to(line, kOpcodeTab);
|
indent_to(line, kOpcodeTab);
|
||||||
line.append(&opcodes[_op * 3], 3);
|
line.append(&opcodes[_op * 3], 3);
|
||||||
|
|
||||||
|
if (_mode == mImpliedA && (_traits & explicit_implied_a)) {
|
||||||
|
indent_to(line, kOperandTab);
|
||||||
|
line.append("a");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
hexdump(line);
|
hexdump(line);
|
||||||
line.push_back('\n');
|
line.push_back('\n');
|
||||||
|
@ -842,3 +925,89 @@ void disassembler::print(const std::string &expr) {
|
||||||
_pc += _size + 1;
|
_pc += _size + 1;
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
const std::vector<uint32_t> &analyzer::finish() {
|
||||||
|
std::sort(_labels.begin(), _labels.end());
|
||||||
|
auto end = std::unique(_labels.begin(), _labels.end());
|
||||||
|
_labels.erase(end, _labels.end());
|
||||||
|
return _labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void analyzer::operator()(uint8_t byte) {
|
||||||
|
|
||||||
|
|
||||||
|
if (!_code) {
|
||||||
|
|
||||||
|
if (_inline_data && --_inline_data <= 0) {
|
||||||
|
_code = true;
|
||||||
|
reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_st++;
|
||||||
|
if (_st == 1) {
|
||||||
|
_op = byte;
|
||||||
|
_mode = modes[_op];
|
||||||
|
|
||||||
|
_size = _mode & 0x0f;
|
||||||
|
if (_mode & _flags & m_I) _size++;
|
||||||
|
if (_mode & _flags & m_M) _size++;
|
||||||
|
|
||||||
|
if (!_size) { reset(); }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned shift = (_st - 2) * 8;
|
||||||
|
_arg = _arg + (byte << shift);
|
||||||
|
if (_st <= _size) return;
|
||||||
|
|
||||||
|
|
||||||
|
// all done... now process it
|
||||||
|
process();
|
||||||
|
}
|
||||||
|
|
||||||
|
void analyzer::reset() {
|
||||||
|
_pc += _st;
|
||||||
|
_arg = 0;
|
||||||
|
_st = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void analyzer::process() {
|
||||||
|
|
||||||
|
if (_traits & disassembler::track_rep_sep) {
|
||||||
|
switch(_op) {
|
||||||
|
case 0xc2: // REP
|
||||||
|
_flags |= (_arg & 0x30);
|
||||||
|
break;
|
||||||
|
case 0xe2: // SEP
|
||||||
|
_flags &= ~(_arg & 0x30);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (_mode & 0xf000) {
|
||||||
|
case mRelative: {
|
||||||
|
|
||||||
|
uint32_t pc = _pc + 1 + _size + _arg;
|
||||||
|
|
||||||
|
if ((_size == 1) && (_arg & 0x80))
|
||||||
|
pc += 0xff00;
|
||||||
|
pc &= 0xffff;
|
||||||
|
|
||||||
|
_labels.push_back(pc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case mAbsolute:
|
||||||
|
case mAbsoluteI:
|
||||||
|
case mAbsoluteLong: {
|
||||||
|
_labels.push_back(_arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
118
disassembler.h
118
disassembler.h
|
@ -3,21 +3,46 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// disassembler traits
|
||||||
|
|
||||||
class disassembler {
|
class disassembler {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum {
|
||||||
|
|
||||||
|
// pea #xxxx vs pea |xxxx
|
||||||
|
pea_immediate = 1,
|
||||||
|
// jml [|xxxx] vs jml [xxxx]
|
||||||
|
jml_indirect_modifier = 2,
|
||||||
|
// asl vs asl a
|
||||||
|
explicit_implied_a = 4,
|
||||||
|
// and & 07f hexdump
|
||||||
|
msb_hexdump = 8,
|
||||||
|
track_rep_sep = 16,
|
||||||
|
bit_hacks = 32,
|
||||||
|
|
||||||
|
orca = jml_indirect_modifier | explicit_implied_a,
|
||||||
|
mpw = jml_indirect_modifier | explicit_implied_a,
|
||||||
|
wdc = pea_immediate,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
disassembler() = default;
|
disassembler() = default;
|
||||||
|
disassembler(unsigned traits) : _traits(traits)
|
||||||
|
{}
|
||||||
virtual ~disassembler();
|
virtual ~disassembler();
|
||||||
|
|
||||||
void operator()(uint8_t byte);
|
void operator()(uint8_t byte);
|
||||||
void operator()(const std::string &expr, unsigned size);
|
void operator()(const std::string &expr, unsigned size, uint32_t value = 0);
|
||||||
|
|
||||||
template<class Iter>
|
template<class Iter>
|
||||||
void operator()(Iter begin, Iter end) { while (begin != end) code(*begin++); }
|
void operator()(Iter begin, Iter end) { while (begin != end) (*this)(*begin++); }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void operator()(const T &t) { code(std::begin(t), std::end(t)); }
|
void operator()(const T &t) { (*this)(std::begin(t), std::end(t)); }
|
||||||
|
|
||||||
void space(unsigned bytes);
|
void space(unsigned bytes);
|
||||||
|
|
||||||
|
@ -52,30 +77,49 @@ class disassembler {
|
||||||
static void emit(const std::string &label);
|
static void emit(const std::string &label);
|
||||||
static void emit(const std::string &label, const std::string &opcode);
|
static void emit(const std::string &label, const std::string &opcode);
|
||||||
static void emit(const std::string &label, const std::string &opcode, const std::string &operand);
|
static void emit(const std::string &label, const std::string &opcode, const std::string &operand);
|
||||||
|
static void emit(const std::string &label, const std::string &opcode, const std::string &operand, const std::string &comment);
|
||||||
|
|
||||||
|
static int operand_size(uint8_t op, bool m = true, bool x = true);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
|
virtual std::pair<std::string, std::string> format_data(unsigned size, const uint8_t *data);
|
||||||
|
virtual std::pair<std::string, std::string> format_data(unsigned size, const std::string &);
|
||||||
|
|
||||||
|
virtual std::string label_for_address(uint32_t address);
|
||||||
|
virtual std::string label_for_zp(uint32_t address);
|
||||||
|
|
||||||
|
|
||||||
|
virtual std::string ds() const { return "ds"; }
|
||||||
|
|
||||||
|
|
||||||
|
void set_inline_data(int count) {
|
||||||
|
flush();
|
||||||
|
_code = count ? false : true;
|
||||||
|
_inline_data = count;
|
||||||
|
}
|
||||||
|
|
||||||
virtual int32_t next_label(int32_t pc) {
|
virtual int32_t next_label(int32_t pc) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void event(uint8_t opcode, uint32_t operand) {}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
void dump(const std::string &expr, unsigned size);
|
void dump(const std::string &expr, unsigned size, uint32_t value = 0);
|
||||||
|
|
||||||
void print();
|
void print();
|
||||||
void print(const std::string &expr);
|
void print(const std::string &expr);
|
||||||
|
|
||||||
void print_prefix();
|
|
||||||
void print_suffix();
|
|
||||||
|
|
||||||
std::string prefix();
|
std::string prefix();
|
||||||
std::string suffix();
|
std::string suffix();
|
||||||
|
|
||||||
void hexdump();
|
|
||||||
void hexdump(std::string &);
|
void hexdump(std::string &);
|
||||||
|
|
||||||
unsigned _st = 0;
|
unsigned _st = 0;
|
||||||
|
@ -88,9 +132,65 @@ class disassembler {
|
||||||
unsigned _arg = 0;
|
unsigned _arg = 0;
|
||||||
|
|
||||||
bool _code = true;
|
bool _code = true;
|
||||||
|
int _inline_data = 0;
|
||||||
int32_t _next_label = -1;
|
int32_t _next_label = -1;
|
||||||
|
|
||||||
|
unsigned _traits = 0;
|
||||||
|
|
||||||
void check_labels();
|
void check_labels();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class analyzer {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
analyzer(unsigned traits = 0) : _traits(traits)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void set_pc(uint32_t pc) { _pc = pc; }
|
||||||
|
uint32_t pc() const { return _pc; }
|
||||||
|
|
||||||
|
|
||||||
|
bool m() const { return _flags & 0x20; }
|
||||||
|
bool x() const { return _flags & 0x10; }
|
||||||
|
|
||||||
|
void set_m(bool x) {
|
||||||
|
if (x) _flags |= 0x20;
|
||||||
|
else _flags &= ~0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_x(bool x) {
|
||||||
|
if (x) _flags |= 0x10;
|
||||||
|
else _flags &= ~0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void operator()(uint8_t x);
|
||||||
|
void operator()(uint32_t x, unsigned size);
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector<uint32_t> &finish();
|
||||||
|
|
||||||
|
bool state() const { return _st == 0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
void process();
|
||||||
|
|
||||||
|
unsigned _traits = 0;
|
||||||
|
int _inline_data = 0;
|
||||||
|
bool _code = true;
|
||||||
|
unsigned _st = 0;
|
||||||
|
uint8_t _op = 0;
|
||||||
|
unsigned _size = 0;
|
||||||
|
unsigned _flags = 0x30;
|
||||||
|
unsigned _pc = 0;
|
||||||
|
unsigned _arg = 0;
|
||||||
|
unsigned _mode = 0;
|
||||||
|
|
||||||
|
std::vector<uint32_t> _labels;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
78
dumpobj.cpp
78
dumpobj.cpp
|
@ -16,6 +16,8 @@
|
||||||
#include "obj816.h"
|
#include "obj816.h"
|
||||||
#include "zrdz_disassembler.h"
|
#include "zrdz_disassembler.h"
|
||||||
|
|
||||||
|
#include "endian.h"
|
||||||
|
|
||||||
#ifndef O_BINARY
|
#ifndef O_BINARY
|
||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,18 +30,12 @@
|
||||||
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool _S = false;
|
bool S = false;
|
||||||
bool _g = false;
|
bool g = false;
|
||||||
bool _n = false;
|
bool n = false;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
|
|
||||||
enum class endian {
|
|
||||||
little = __ORDER_LITTLE_ENDIAN__,
|
|
||||||
big = __ORDER_BIG_ENDIAN__,
|
|
||||||
native = __BYTE_ORDER__
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void swap_if(T &t, std::false_type) {}
|
void swap_if(T &t, std::false_type) {}
|
||||||
|
@ -239,6 +235,9 @@ bool dump_obj(const char *name, int fd)
|
||||||
ok = read(fd, symbol_data.data(), h.h_symsize);
|
ok = read(fd, symbol_data.data(), h.h_symsize);
|
||||||
if (ok != h.h_symsize) errx(EX_DATAERR, "%s symbols truncated", name);
|
if (ok != h.h_symsize) errx(EX_DATAERR, "%s symbols truncated", name);
|
||||||
|
|
||||||
|
if (h.h_optsize) lseek(fd, h.h_optsize, SEEK_CUR);
|
||||||
|
|
||||||
|
|
||||||
zrdz_disassembler d(read_sections(section_data), read_symbols(symbol_data));
|
zrdz_disassembler d(read_sections(section_data), read_symbols(symbol_data));
|
||||||
|
|
||||||
uint8_t op = REC_END;
|
uint8_t op = REC_END;
|
||||||
|
@ -288,7 +287,7 @@ bool dump_obj(const char *name, int fd)
|
||||||
|
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
if (flags._n) {
|
if (flags.n) {
|
||||||
name = d.section_name(section) + "+" + d.to_x(offset, 4, '$');
|
name = d.section_name(section) + "+" + d.to_x(offset, 4, '$');
|
||||||
} else {
|
} else {
|
||||||
name = d.location_name(section, offset);
|
name = d.location_name(section, offset);
|
||||||
|
@ -311,7 +310,7 @@ bool dump_obj(const char *name, int fd)
|
||||||
case OP_NOT:
|
case OP_NOT:
|
||||||
case OP_NEG:
|
case OP_NEG:
|
||||||
case OP_FLP: {
|
case OP_FLP: {
|
||||||
static const char *ops[] = {
|
static const std::string ops[] = {
|
||||||
".NOT.", "-", "\\"
|
".NOT.", "-", "\\"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -323,12 +322,24 @@ bool dump_obj(const char *name, int fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// binary operators
|
// binary operators
|
||||||
case OP_SHR:
|
case OP_EXP:
|
||||||
|
case OP_MUL:
|
||||||
|
case OP_DIV:
|
||||||
|
case OP_MOD:
|
||||||
|
case OP_SHR:
|
||||||
case OP_SHL:
|
case OP_SHL:
|
||||||
case OP_ADD:
|
case OP_ADD:
|
||||||
case OP_SUB: {
|
case OP_SUB:
|
||||||
static const char *ops[] = {
|
case OP_AND:
|
||||||
"**", "*", "/", ".MOD.", ">>", "<<", "+", "-", "&", "|", "^", "=", ">", "<"
|
case OP_OR:
|
||||||
|
case OP_XOR:
|
||||||
|
case OP_EQ:
|
||||||
|
case OP_GT:
|
||||||
|
case OP_LT:
|
||||||
|
case OP_UGT:
|
||||||
|
case OP_ULT: {
|
||||||
|
static const std::string ops[] = {
|
||||||
|
"**", "*", "/", ".MOD.", ">>", "<<", "+", "-", "&", "|", "^", "=", ">", "<", ".UGT.", ".ULT."
|
||||||
|
|
||||||
};
|
};
|
||||||
if (stack.size() < 2) errx(EX_DATAERR, "%s : stack underflow error", name);
|
if (stack.size() < 2) errx(EX_DATAERR, "%s : stack underflow error", name);
|
||||||
|
@ -538,7 +549,7 @@ bool dump_obj(const char *name, int fd)
|
||||||
|
|
||||||
|
|
||||||
unsigned f = 0;
|
unsigned f = 0;
|
||||||
if (flags._S) f |= 0x01;
|
if (flags.S) f |= 0x01;
|
||||||
d.back_matter(f);
|
d.back_matter(f);
|
||||||
|
|
||||||
if (iter != data.end() || op != REC_END) errx(EX_DATAERR, "%s records ended early", name);
|
if (iter != data.end() || op != REC_END) errx(EX_DATAERR, "%s records ended early", name);
|
||||||
|
@ -572,43 +583,48 @@ void dump_lib(const char *name, int fd)
|
||||||
assert(h.l_version == 1);
|
assert(h.l_version == 1);
|
||||||
assert(h.l_filtyp == 2);
|
assert(h.l_filtyp == 2);
|
||||||
|
|
||||||
printf("modstart : $%04x\n", h.l_modstart);
|
printf("; library %s\n\n", name);
|
||||||
printf("number symbols: $%04x\n", h.l_numsyms);
|
/*
|
||||||
printf("number files : $%04x\n", h.l_numfiles);
|
printf("; modstart : $%04x\n", h.l_modstart);
|
||||||
|
printf("; number symbols: $%04x\n", h.l_numsyms);
|
||||||
|
printf("; number files : $%04x\n", h.l_numfiles);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
*/
|
||||||
|
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
long count = h.l_modstart - sizeof(h);
|
long count = h.l_modstart - sizeof(h);
|
||||||
if (count < 0) errx(EX_DATAERR, "%s", name);
|
if (count < 0) errx(EX_DATAERR, "%s", name);
|
||||||
data.reserve(count);
|
data.resize(count);
|
||||||
ok = read(fd, data.data(), count);
|
ok = read(fd, data.data(), count);
|
||||||
if (ok != count) errx(EX_DATAERR, "%s truncated", name);
|
if (ok != count) errx(EX_DATAERR, "%s truncated", name);
|
||||||
|
|
||||||
|
|
||||||
// files
|
// files
|
||||||
|
printf("; files:\n");
|
||||||
auto iter = data.begin();
|
auto iter = data.begin();
|
||||||
for (int i = 0; i < h.l_numfiles; ++i) {
|
for (int i = 0; i < h.l_numfiles; ++i) {
|
||||||
uint16_t file_number = read_16(iter);
|
uint16_t file_number = read_16(iter);
|
||||||
std::string s = read_pstring(iter);
|
std::string s = read_pstring(iter);
|
||||||
printf("$%02x %s\n", file_number, s.c_str());
|
printf("; $%02x %s\n", file_number, s.c_str());
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
// symbols
|
// symbols
|
||||||
|
printf("; symbols:\n");
|
||||||
auto name_iter = iter + h.l_numsyms * 8;
|
auto name_iter = iter + h.l_numsyms * 8;
|
||||||
for (int i = 0; i < h.l_numsyms; ++i) {
|
for (int i = 0; i < h.l_numsyms; ++i) {
|
||||||
uint16_t name_offset = read_16(iter);
|
uint16_t name_offset = read_16(iter);
|
||||||
uint16_t file_number = read_16(iter);
|
uint16_t file_number = read_16(iter);
|
||||||
uint32_t offset = read_32(iter);
|
uint32_t offset = read_32(iter);
|
||||||
std::string name = read_pstring(name_iter);
|
auto tmp = name_iter + name_offset;
|
||||||
|
std::string name = read_pstring(tmp);
|
||||||
|
|
||||||
printf("symbol : $%04x %s\n", i, name.c_str());
|
printf("; $%04x %s\n", i, name.c_str());
|
||||||
//printf("name offset: %02x\n", name_offset);
|
//printf("name offset: %02x\n", name_offset);
|
||||||
printf("file_number : $%02x\n", file_number);
|
//printf("file_number : $%02x\n", file_number);
|
||||||
printf("module offset: $%04x\n", offset);
|
//printf("module offset: $%04x\n", offset);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump(const char *name) {
|
void dump(const char *name) {
|
||||||
|
@ -645,9 +661,9 @@ int main(int argc, char **argv) {
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt(argc, argv, "Sgn")) != -1) {
|
while ((c = getopt(argc, argv, "Sgn")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'S': flags._S = true; break;
|
case 'S': flags.S = true; break;
|
||||||
case 'g': flags._g = true; break;
|
case 'g': flags.g = true; break;
|
||||||
case 'n': flags._n = true; break;
|
case 'n': flags.n = true; break;
|
||||||
default: exit(EX_USAGE); break;
|
default: exit(EX_USAGE); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
endian.h
Normal file
16
endian.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef endian_h
|
||||||
|
#define endian_h
|
||||||
|
|
||||||
|
enum class endian {
|
||||||
|
#ifdef _WIN32
|
||||||
|
little = 1234,
|
||||||
|
big = 4321,
|
||||||
|
native = little
|
||||||
|
#else
|
||||||
|
little = __ORDER_LITTLE_ENDIAN__,
|
||||||
|
big = __ORDER_BIG_ENDIAN__,
|
||||||
|
native = __BYTE_ORDER__
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -2,6 +2,9 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "obj816.h"
|
#include "obj816.h"
|
||||||
|
|
||||||
|
#include <sysexits.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
/* a ** b */
|
/* a ** b */
|
||||||
uint32_t power(uint32_t a, uint32_t b) {
|
uint32_t power(uint32_t a, uint32_t b) {
|
||||||
|
|
||||||
|
@ -21,6 +24,8 @@ bool unary_op(unsigned op, std::vector<expr> &v) {
|
||||||
case OP_NOT: a.value = !a.value; break;
|
case OP_NOT: a.value = !a.value; break;
|
||||||
case OP_NEG: a.value = -a.value; break;
|
case OP_NEG: a.value = -a.value; break;
|
||||||
case OP_FLP: a.value = ~a.value; break;
|
case OP_FLP: a.value = ~a.value; break;
|
||||||
|
default:
|
||||||
|
errx(EX_SOFTWARE, "Unsupported unary op %02x", a.tag);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +59,8 @@ bool binary_op(unsigned op, std::vector<expr> &v) {
|
||||||
case OP_LT: value = (int32_t)a.value < (int32_t)b.value; break;
|
case OP_LT: value = (int32_t)a.value < (int32_t)b.value; break;
|
||||||
case OP_UGT: value = a.value > b.value; break;
|
case OP_UGT: value = a.value > b.value; break;
|
||||||
case OP_ULT: value = a.value < b.value; break;
|
case OP_ULT: value = a.value < b.value; break;
|
||||||
|
default:
|
||||||
|
errx(EX_SOFTWARE, "Unsupported binary op %02x", a.tag);
|
||||||
}
|
}
|
||||||
v.pop_back();
|
v.pop_back();
|
||||||
v.back().value = value;
|
v.back().value = value;
|
||||||
|
@ -86,8 +93,16 @@ bool binary_op(unsigned op, std::vector<expr> &v) {
|
||||||
// optimization... regardless of where it's located, shifting > 24 bits will result in 0...
|
// optimization... regardless of where it's located, shifting > 24 bits will result in 0...
|
||||||
if (a.tag == OP_LOC && b.tag == OP_VAL) {
|
if (a.tag == OP_LOC && b.tag == OP_VAL) {
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case OP_ADD: a.value += b.value; return true;
|
case OP_ADD: {
|
||||||
case OP_SUB: a.value -= b.value; return true;
|
a.value += b.value;
|
||||||
|
v.pop_back();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case OP_SUB: {
|
||||||
|
a.value -= b.value;
|
||||||
|
v.pop_back();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
obj816.h
4
obj816.h
|
@ -19,7 +19,7 @@ typedef struct Mod_head {
|
||||||
uint16_t h_optsize; /* sizeof options section */
|
uint16_t h_optsize; /* sizeof options section */
|
||||||
uint8_t h_tot_secs; /* total number of sections in module */
|
uint8_t h_tot_secs; /* total number of sections in module */
|
||||||
uint8_t h_num_secs; /* number of sections referenced */
|
uint8_t h_num_secs; /* number of sections referenced */
|
||||||
uint16_t h_num_syms; /* number of symbols */
|
uint16_t h_num_syms; /* number of symbols */
|
||||||
} Mod_head;
|
} Mod_head;
|
||||||
|
|
||||||
typedef struct Lib_head {
|
typedef struct Lib_head {
|
||||||
|
@ -30,7 +30,7 @@ typedef struct Lib_head {
|
||||||
uint32_t l_modstart; /* offset of modules start */
|
uint32_t l_modstart; /* offset of modules start */
|
||||||
uint32_t l_numsyms; /* number of symbol entries */
|
uint32_t l_numsyms; /* number of symbol entries */
|
||||||
uint32_t l_symsize; /* sizeof symbol section */
|
uint32_t l_symsize; /* sizeof symbol section */
|
||||||
uint32_t l_numfiles; /* number of files */
|
uint32_t l_numfiles; /* number of files */
|
||||||
} Lib_head;
|
} Lib_head;
|
||||||
|
|
||||||
#define MOD_CONVERT "lwbblslsbbw"
|
#define MOD_CONVERT "lwbblslsbbw"
|
||||||
|
|
495
omf.cpp
495
omf.cpp
|
@ -3,17 +3,32 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <sysexits.h>
|
#include <sysexits.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "optional.h"
|
||||||
|
|
||||||
#ifndef O_BINARY
|
#ifndef O_BINARY
|
||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum class endian {
|
||||||
|
#ifdef _WIN32
|
||||||
|
little = 0,
|
||||||
|
big = 1,
|
||||||
|
native = little
|
||||||
|
#else
|
||||||
|
little = __ORDER_LITTLE_ENDIAN__,
|
||||||
|
big = __ORDER_BIG_ENDIAN__,
|
||||||
|
native = __BYTE_ORDER__
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct omf_header {
|
struct omf_header {
|
||||||
uint32_t bytecount = 0;
|
uint32_t bytecount = 0;
|
||||||
|
@ -60,6 +75,90 @@ struct omf_express_header {
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
static_assert(sizeof(omf_header) == 44, "OMF Header not packed");
|
||||||
|
static_assert(sizeof(omf_express_header) == 48, "OMF Express Header not packed");
|
||||||
|
|
||||||
|
|
||||||
|
static void swap(uint8_t &x) {}
|
||||||
|
static void swap(uint16_t &x) {
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
x = __builtin_bswap16(x);
|
||||||
|
#else
|
||||||
|
x = (x >> 8) | (x << 8);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static void swap(uint32_t &x) {
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
x = __builtin_bswap32(x);
|
||||||
|
#else
|
||||||
|
x = ((x & 0xff000000) >> 24) |
|
||||||
|
((x & 0x00ff0000) >> 8) |
|
||||||
|
((x & 0x0000ff00) << 8) |
|
||||||
|
((x & 0x000000ff) << 24);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void to_little(struct omf_header &h) {
|
||||||
|
if (endian::native != endian::little) {
|
||||||
|
swap(h.bytecount);
|
||||||
|
swap(h.reserved_space);
|
||||||
|
swap(h.length);
|
||||||
|
swap(h.unused1);
|
||||||
|
swap(h.lablen);
|
||||||
|
swap(h.numlen);
|
||||||
|
swap(h.version);
|
||||||
|
swap(h.banksize);
|
||||||
|
swap(h.kind);
|
||||||
|
swap(h.unused2);
|
||||||
|
swap(h.org);
|
||||||
|
swap(h.alignment);
|
||||||
|
swap(h.numsex);
|
||||||
|
swap(h.unused3);
|
||||||
|
swap(h.segnum);
|
||||||
|
swap(h.entry);
|
||||||
|
swap(h.dispname);
|
||||||
|
swap(h.dispdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void to_little(struct omf_express_header &h) {
|
||||||
|
if (endian::native != endian::little) {
|
||||||
|
swap(h.lconst_mark);
|
||||||
|
swap(h.lconst_size);
|
||||||
|
swap(h.reloc_mark);
|
||||||
|
swap(h.reloc_size);
|
||||||
|
swap(h.unused1);
|
||||||
|
swap(h.lablen);
|
||||||
|
swap(h.numlen);
|
||||||
|
swap(h.version);
|
||||||
|
swap(h.banksize);
|
||||||
|
swap(h.kind);
|
||||||
|
swap(h.unused2);
|
||||||
|
swap(h.org);
|
||||||
|
swap(h.alignment);
|
||||||
|
swap(h.numsex);
|
||||||
|
swap(h.unused3);
|
||||||
|
swap(h.segnum);
|
||||||
|
swap(h.entry);
|
||||||
|
swap(h.dispname);
|
||||||
|
swap(h.dispdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void to_v1(struct omf_header &h) {
|
||||||
|
|
||||||
|
// KIND op value used as-is, no translation.
|
||||||
|
|
||||||
|
h.version = 1;
|
||||||
|
// byte count -> block count
|
||||||
|
h.bytecount = (h.bytecount + 511) >> 9;
|
||||||
|
h.unused1 = h.kind;
|
||||||
|
h.kind = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void push(std::vector<uint8_t> &v, uint8_t x) {
|
void push(std::vector<uint8_t> &v, uint8_t x) {
|
||||||
v.push_back(x);
|
v.push_back(x);
|
||||||
}
|
}
|
||||||
|
@ -83,11 +182,302 @@ void push(std::vector<uint8_t> &v, uint32_t x) {
|
||||||
void push(std::vector<uint8_t> &v, const std::string &s) {
|
void push(std::vector<uint8_t> &v, const std::string &s) {
|
||||||
uint8_t count = std::min((int)s.size(), 255);
|
uint8_t count = std::min((int)s.size(), 255);
|
||||||
push(v, count);
|
push(v, count);
|
||||||
v.insert(v.end(), s.begin(), s.end());
|
v.insert(v.end(), s.begin(), s.begin() + count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(std::vector<uint8_t> &v, const std::string &s, size_t count) {
|
||||||
|
std::string tmp(s, 0, count);
|
||||||
|
tmp.resize(count, ' ');
|
||||||
|
v.insert(v.end(), tmp.begin(), tmp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
class super_helper {
|
||||||
|
|
||||||
|
std::vector<uint8_t> _data;
|
||||||
|
uint32_t _page = 0;
|
||||||
|
int _count = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
super_helper() = default;
|
||||||
|
|
||||||
|
|
||||||
|
void append(uint32_t pc) {
|
||||||
|
unsigned offset = pc & 0xff;
|
||||||
|
unsigned page = pc >> 8;
|
||||||
|
assert(page >= _page);
|
||||||
|
|
||||||
|
if (page != _page) {
|
||||||
|
unsigned skip = page - _page;
|
||||||
|
if (_count) --skip;
|
||||||
|
if (skip) {
|
||||||
|
|
||||||
|
while (skip >= 0x80) {
|
||||||
|
_data.push_back(0xff);
|
||||||
|
skip -= 0x7f;
|
||||||
|
}
|
||||||
|
if (skip)
|
||||||
|
_data.push_back(0x80 | skip);
|
||||||
|
}
|
||||||
|
_page = page;
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_count) {
|
||||||
|
_data.push_back(0); // count-1 place holder.
|
||||||
|
} else {
|
||||||
|
_data[_data.size() - _count - 1] = _count; // count is count - 1 at this point,
|
||||||
|
}
|
||||||
|
|
||||||
|
_data.push_back(offset);
|
||||||
|
++_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
_data.clear();
|
||||||
|
_page = 0;
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<uint8_t> &data() {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SUPER_RELOC2,
|
||||||
|
SUPER_RELOC3,
|
||||||
|
SUPER_INTERSEG1,
|
||||||
|
SUPER_INTERSEG2,
|
||||||
|
SUPER_INTERSEG3,
|
||||||
|
SUPER_INTERSEG4,
|
||||||
|
SUPER_INTERSEG5,
|
||||||
|
SUPER_INTERSEG6,
|
||||||
|
SUPER_INTERSEG7,
|
||||||
|
SUPER_INTERSEG8,
|
||||||
|
SUPER_INTERSEG9,
|
||||||
|
SUPER_INTERSEG10,
|
||||||
|
SUPER_INTERSEG11,
|
||||||
|
SUPER_INTERSEG12,
|
||||||
|
SUPER_INTERSEG13,
|
||||||
|
SUPER_INTERSEG14,
|
||||||
|
SUPER_INTERSEG15,
|
||||||
|
SUPER_INTERSEG16,
|
||||||
|
SUPER_INTERSEG17,
|
||||||
|
SUPER_INTERSEG18,
|
||||||
|
SUPER_INTERSEG19,
|
||||||
|
SUPER_INTERSEG20,
|
||||||
|
SUPER_INTERSEG21,
|
||||||
|
SUPER_INTERSEG22,
|
||||||
|
SUPER_INTERSEG23,
|
||||||
|
SUPER_INTERSEG24,
|
||||||
|
SUPER_INTERSEG25,
|
||||||
|
SUPER_INTERSEG26,
|
||||||
|
SUPER_INTERSEG27,
|
||||||
|
SUPER_INTERSEG28,
|
||||||
|
SUPER_INTERSEG29,
|
||||||
|
SUPER_INTERSEG30,
|
||||||
|
SUPER_INTERSEG31,
|
||||||
|
SUPER_INTERSEG32,
|
||||||
|
SUPER_INTERSEG33,
|
||||||
|
SUPER_INTERSEG34,
|
||||||
|
SUPER_INTERSEG35,
|
||||||
|
SUPER_INTERSEG36,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t add_relocs(std::vector<uint8_t> &data, size_t data_offset, omf::segment &seg, bool compress, bool super) {
|
||||||
|
|
||||||
|
std::array< optional<super_helper>, 38 > ss;
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t reloc_size = 0;
|
||||||
|
|
||||||
|
for (auto &r : seg.relocs) {
|
||||||
|
|
||||||
|
if (compress && r.can_compress()) {
|
||||||
|
|
||||||
|
if (super) {
|
||||||
|
if (r.shift == 0 && r.size == 2) {
|
||||||
|
constexpr int n = SUPER_RELOC2;
|
||||||
|
|
||||||
|
auto &sr = ss[n];
|
||||||
|
if (!sr) sr.emplace();
|
||||||
|
sr->append(r.offset);
|
||||||
|
|
||||||
|
uint32_t value = r.value;
|
||||||
|
for (int i = 0; i < 2; ++i, value >>= 8)
|
||||||
|
data[data_offset + r.offset + i] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sreloc 3 is for 3 bytes. however 4 bytes is also ok since
|
||||||
|
// it's 24-bit address space.
|
||||||
|
if (r.shift == 0 && (r.size == 2 || r.size == 3))
|
||||||
|
{
|
||||||
|
constexpr int n = SUPER_RELOC3;
|
||||||
|
|
||||||
|
auto &sr = ss[n];
|
||||||
|
if (!sr) sr.emplace();
|
||||||
|
sr->append(r.offset);
|
||||||
|
|
||||||
|
uint32_t value = r.value;
|
||||||
|
for (int i = 0; i < 3; ++i, value >>= 8)
|
||||||
|
data[data_offset + r.offset + i] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if size == 2 && shift == -16, -> SUPER INTERSEG
|
||||||
|
if (seg.segnum <= 12 && r.shift == 0xf0 && r.size == 2) {
|
||||||
|
|
||||||
|
int n = SUPER_INTERSEG24 + seg.segnum;
|
||||||
|
auto &sr = ss[n];
|
||||||
|
if (!sr) sr.emplace();
|
||||||
|
sr->append(r.offset);
|
||||||
|
|
||||||
|
uint32_t value = r.value;
|
||||||
|
for (int i = 0; i < 2; ++i, value >>= 8)
|
||||||
|
data[data_offset + r.offset + i] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push(data, (uint8_t)omf::cRELOC);
|
||||||
|
push(data, (uint8_t)r.size);
|
||||||
|
push(data, (uint8_t)r.shift);
|
||||||
|
push(data, (uint16_t)r.offset);
|
||||||
|
push(data, (uint16_t)r.value);
|
||||||
|
reloc_size += 7;
|
||||||
|
} else {
|
||||||
|
push(data, (uint8_t)omf::RELOC);
|
||||||
|
push(data, (uint8_t)r.size);
|
||||||
|
push(data, (uint8_t)r.shift);
|
||||||
|
push(data, (uint32_t)r.offset);
|
||||||
|
push(data, (uint32_t)r.value);
|
||||||
|
reloc_size += 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &r : seg.intersegs) {
|
||||||
|
if (compress && r.can_compress()) {
|
||||||
|
|
||||||
|
if (super) {
|
||||||
|
|
||||||
|
if (r.shift == 0 && r.size == 3) {
|
||||||
|
constexpr int n = SUPER_INTERSEG1;
|
||||||
|
auto &sr = ss[n];
|
||||||
|
if (!sr) sr.emplace();
|
||||||
|
sr->append(r.offset);
|
||||||
|
|
||||||
|
uint32_t value = r.segment_offset;
|
||||||
|
|
||||||
|
data[data_offset + r.offset + 0] = value; value >>= 8;
|
||||||
|
data[data_offset + r.offset + 1] = value; value >>= 8;
|
||||||
|
data[data_offset + r.offset + 2] = r.segment;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (r.shift == 0 && r.size == 2 && r.segment <= 12) {
|
||||||
|
|
||||||
|
int n = SUPER_INTERSEG12 + r.segment;
|
||||||
|
auto &sr = ss[n];
|
||||||
|
if (!sr) sr.emplace();
|
||||||
|
sr->append(r.offset);
|
||||||
|
|
||||||
|
uint32_t value = r.segment_offset;
|
||||||
|
for (int i = 0; i < 2; ++i, value >>= 8)
|
||||||
|
data[data_offset + r.offset + i] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r.shift == 0xf0 && r.size == 2 && r.segment <= 12) {
|
||||||
|
|
||||||
|
int n = SUPER_INTERSEG24 + r.segment;
|
||||||
|
auto &sr = ss[n];
|
||||||
|
if (!sr) sr.emplace();
|
||||||
|
sr->append(r.offset);
|
||||||
|
|
||||||
|
uint32_t value = r.segment_offset;
|
||||||
|
for (int i = 0; i < 2; ++i, value >>= 8)
|
||||||
|
data[data_offset + r.offset + i] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
push(data, (uint8_t)omf::cINTERSEG);
|
||||||
|
push(data, (uint8_t)r.size);
|
||||||
|
push(data, (uint8_t)r.shift);
|
||||||
|
push(data, (uint16_t)r.offset);
|
||||||
|
push(data, (uint8_t)r.segment);
|
||||||
|
push(data, (uint16_t)r.segment_offset);
|
||||||
|
reloc_size += 8;
|
||||||
|
} else {
|
||||||
|
push(data, (uint8_t)omf::INTERSEG);
|
||||||
|
push(data, (uint8_t)r.size);
|
||||||
|
push(data, (uint8_t)r.shift);
|
||||||
|
push(data, (uint32_t)r.offset);
|
||||||
|
push(data, (uint16_t)r.file);
|
||||||
|
push(data, (uint16_t)r.segment);
|
||||||
|
push(data, (uint32_t)r.segment_offset);
|
||||||
|
reloc_size += 15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < ss.size(); ++i) {
|
||||||
|
auto &s = ss[i];
|
||||||
|
if (!s) continue;
|
||||||
|
|
||||||
|
auto tmp = s->data();
|
||||||
|
if (tmp.empty()) continue;
|
||||||
|
|
||||||
|
reloc_size += tmp.size() + 6;
|
||||||
|
data.push_back(omf::SUPER);
|
||||||
|
push(data, ((uint32_t)tmp.size() + 1));
|
||||||
|
data.push_back(i);
|
||||||
|
|
||||||
|
data.insert(data.end(), tmp.begin(), tmp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
return reloc_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_bin(const std::string &path, omf::segment &segment, uint32_t org) {
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
err(EX_CANTCREAT, "Unable to open %s", path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &data = segment.data;
|
||||||
|
|
||||||
|
for (auto &r : segment.relocs) {
|
||||||
|
|
||||||
|
uint32_t value = r.value + org;
|
||||||
|
value >>= -(int8_t)r.shift;
|
||||||
|
|
||||||
|
unsigned offset = r.offset;
|
||||||
|
unsigned size = r.size;
|
||||||
|
while (size--) {
|
||||||
|
data[offset++] = value & 0xff;
|
||||||
|
value >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ok = write(fd, data.data(), data.size());
|
||||||
|
if (ok < 0) {
|
||||||
|
close(fd);
|
||||||
|
err(EX_OSERR, "write %s", path.c_str());
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::string &path) {
|
void save_omf(const std::string &path, std::vector<omf::segment> &segments, unsigned flags) {
|
||||||
|
|
||||||
// expressload doesn't support links to other files.
|
// expressload doesn't support links to other files.
|
||||||
// fortunately, we don't either.
|
// fortunately, we don't either.
|
||||||
|
@ -95,6 +485,17 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||||
std::vector<uint8_t> expr_headers;
|
std::vector<uint8_t> expr_headers;
|
||||||
std::vector<unsigned> expr_offsets;
|
std::vector<unsigned> expr_offsets;
|
||||||
|
|
||||||
|
|
||||||
|
bool compress = !(flags & OMF_NO_COMPRESS);
|
||||||
|
bool super = !(flags & OMF_NO_SUPER);
|
||||||
|
bool expressload = !(flags & OMF_NO_EXPRESS);
|
||||||
|
bool v1 = flags & OMF_V1;
|
||||||
|
|
||||||
|
if (v1) {
|
||||||
|
expressload = false;
|
||||||
|
super = false;
|
||||||
|
}
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
|
fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -127,15 +528,26 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||||
|
|
||||||
for (auto &s : segments) {
|
for (auto &s : segments) {
|
||||||
omf_header h;
|
omf_header h;
|
||||||
h.length = s.data.size();
|
h.length = s.data.size() + s.reserved_space;
|
||||||
h.kind = s.kind;
|
h.kind = s.kind;
|
||||||
h.banksize = s.data.size() > 0xffff ? 0x0000 : 0x010000;
|
h.banksize = s.data.size() > 0xffff ? 0x0000 : 0x010000;
|
||||||
h.segnum = s.segnum;
|
h.segnum = s.segnum;
|
||||||
|
h.alignment = s.alignment;
|
||||||
|
h.reserved_space = s.reserved_space;
|
||||||
|
|
||||||
|
uint32_t reserved_space = 0;
|
||||||
|
if (expressload) {
|
||||||
|
std::swap(reserved_space, h.reserved_space);
|
||||||
|
}
|
||||||
|
|
||||||
|
// length field INCLUDES reserved space. Express expand reserved space.
|
||||||
|
|
||||||
|
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
// push segname and load name onto data.
|
// push segname and load name onto data.
|
||||||
data.insert(data.end(), 10, ' ');
|
// data.insert(data.end(), 10, ' ');
|
||||||
|
push(data, s.loadname, 10);
|
||||||
push(data, s.segname);
|
push(data, s.segname);
|
||||||
|
|
||||||
h.dispname = sizeof(omf_header);
|
h.dispname = sizeof(omf_header);
|
||||||
|
@ -144,68 +556,31 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||||
|
|
||||||
|
|
||||||
uint32_t lconst_offset = offset + sizeof(omf_header) + data.size() + 5;
|
uint32_t lconst_offset = offset + sizeof(omf_header) + data.size() + 5;
|
||||||
uint32_t lconst_size = h.length;
|
uint32_t lconst_size = s.data.size() + reserved_space;
|
||||||
|
|
||||||
|
|
||||||
//lconst record
|
//lconst record
|
||||||
push(data, (uint8_t)0xf2);
|
push(data, (uint8_t)omf::LCONST);
|
||||||
push(data, (uint32_t)h.length);
|
push(data, (uint32_t)lconst_size);
|
||||||
|
|
||||||
|
size_t data_offset = data.size();
|
||||||
|
|
||||||
data.insert(data.end(), s.data.begin(), s.data.end());
|
data.insert(data.end(), s.data.begin(), s.data.end());
|
||||||
|
|
||||||
|
if (reserved_space) {
|
||||||
|
data.insert(data.end(), reserved_space, 0);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t reloc_offset = offset + sizeof(omf_header) + data.size();
|
uint32_t reloc_offset = offset + sizeof(omf_header) + data.size();
|
||||||
uint32_t reloc_size = 0;
|
uint32_t reloc_size = 0;
|
||||||
|
|
||||||
// should interseg/reloc records be sorted?
|
reloc_size = add_relocs(data, data_offset, s, compress, super);
|
||||||
// todo -- compress into super records.
|
|
||||||
for (const auto &r : s.relocs) {
|
|
||||||
if (r.can_compress()) {
|
|
||||||
push(data, (uint8_t)0xf5);
|
|
||||||
push(data, (uint8_t)r.size);
|
|
||||||
push(data, (uint8_t)r.shift);
|
|
||||||
push(data, (uint16_t)r.offset);
|
|
||||||
push(data, (uint16_t)r.value);
|
|
||||||
reloc_size += 7;
|
|
||||||
} else {
|
|
||||||
push(data, (uint8_t)0xe5);
|
|
||||||
push(data, (uint8_t)r.size);
|
|
||||||
push(data, (uint8_t)r.shift);
|
|
||||||
push(data, (uint32_t)r.offset);
|
|
||||||
push(data, (uint32_t)r.value);
|
|
||||||
reloc_size += 11;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &r : s.intersegs) {
|
|
||||||
if (r.can_compress()) {
|
|
||||||
push(data, (uint8_t)0xf6);
|
|
||||||
push(data, (uint8_t)r.size);
|
|
||||||
push(data, (uint8_t)r.shift);
|
|
||||||
push(data, (uint16_t)r.offset);
|
|
||||||
push(data, (uint8_t)r.segment);
|
|
||||||
push(data, (uint16_t)r.segment_offset);
|
|
||||||
reloc_size += 8;
|
|
||||||
} else {
|
|
||||||
push(data, (uint8_t)0xe3);
|
|
||||||
push(data, (uint8_t)r.size);
|
|
||||||
push(data, (uint8_t)r.shift);
|
|
||||||
push(data, (uint32_t)r.offset);
|
|
||||||
push(data, (uint16_t)r.file);
|
|
||||||
push(data, (uint16_t)r.segment);
|
|
||||||
push(data, (uint32_t)r.segment_offset);
|
|
||||||
reloc_size += 15;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// end-of-record
|
// end-of-record
|
||||||
push(data, (uint8_t)0x00);
|
push(data, (uint8_t)omf::END);
|
||||||
|
|
||||||
h.bytecount = data.size() + sizeof(omf_header);
|
h.bytecount = data.size() + sizeof(omf_header);
|
||||||
|
|
||||||
// todo -- byteswap to little-endian!
|
|
||||||
offset += write(fd, &h, sizeof(h));
|
|
||||||
offset += write(fd, data.data(), data.size());
|
|
||||||
|
|
||||||
if (expressload) {
|
if (expressload) {
|
||||||
|
|
||||||
expr_offsets.emplace_back(expr_headers.size());
|
expr_offsets.emplace_back(expr_headers.size());
|
||||||
|
@ -239,6 +614,17 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||||
push(expr_headers, s.segname);
|
push(expr_headers, s.segname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v1) to_v1(h);
|
||||||
|
to_little(h);
|
||||||
|
|
||||||
|
offset += write(fd, &h, sizeof(h));
|
||||||
|
offset += write(fd, data.data(), data.size());
|
||||||
|
|
||||||
|
// version 1 needs 512-byte padding for all but final segment.
|
||||||
|
if (v1 && &s != &segments.back()) {
|
||||||
|
static uint8_t zero[512];
|
||||||
|
offset += write(fd, zero, 512 - (offset & 511) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expressload) {
|
if (expressload) {
|
||||||
|
@ -278,6 +664,7 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||||
|
|
||||||
h.bytecount = data.size() + sizeof(omf_header);
|
h.bytecount = data.size() + sizeof(omf_header);
|
||||||
|
|
||||||
|
to_little(h);
|
||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
write(fd, &h, sizeof(h));
|
write(fd, &h, sizeof(h));
|
||||||
write(fd, data.data(), data.size());
|
write(fd, data.data(), data.size());
|
||||||
|
@ -285,4 +672,4 @@ void save_omf(std::vector<omf::segment> &segments, bool expressload, const std::
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
43
omf.h
43
omf.h
|
@ -5,8 +5,36 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
namespace omf {
|
namespace omf {
|
||||||
|
|
||||||
|
enum opcode : uint8_t {
|
||||||
|
END = 0x00,
|
||||||
|
// 0x01-0xdf CONST
|
||||||
|
ALIGN = 0xe0,
|
||||||
|
ORG = 0xe1,
|
||||||
|
RELOC = 0xe2,
|
||||||
|
INTERSEG = 0xe3,
|
||||||
|
USING = 0xe4,
|
||||||
|
STRONG = 0xe5,
|
||||||
|
GLOBAL = 0xe6,
|
||||||
|
GEQU = 0xe7,
|
||||||
|
MEM = 0xe8,
|
||||||
|
EXPR = 0xeb,
|
||||||
|
ZEXPR = 0xec,
|
||||||
|
BEXPR = 0xed,
|
||||||
|
RELEXPR = 0xee,
|
||||||
|
LOCAL = 0xef,
|
||||||
|
EQU = 0xf0,
|
||||||
|
DS = 0xf1,
|
||||||
|
LCONST = 0xf2,
|
||||||
|
LEXPR = 0xf3,
|
||||||
|
ENTRY = 0xf4,
|
||||||
|
cRELOC = 0xf5,
|
||||||
|
cINTERSEG = 0xf6,
|
||||||
|
SUPER = 0xf7,
|
||||||
|
};
|
||||||
|
|
||||||
struct reloc {
|
struct reloc {
|
||||||
uint8_t size = 0;
|
uint8_t size = 0;
|
||||||
uint8_t shift = 0;
|
uint8_t shift = 0;
|
||||||
|
@ -37,6 +65,8 @@ namespace omf {
|
||||||
|
|
||||||
uint16_t segnum = 0;
|
uint16_t segnum = 0;
|
||||||
uint16_t kind = 0;
|
uint16_t kind = 0;
|
||||||
|
uint32_t alignment = 0;
|
||||||
|
uint32_t reserved_space = 0;
|
||||||
|
|
||||||
std::string loadname;
|
std::string loadname;
|
||||||
std::string segname;
|
std::string segname;
|
||||||
|
@ -49,4 +79,17 @@ namespace omf {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
// flags
|
||||||
|
OMF_V1 = 1,
|
||||||
|
OMF_V2 = 0,
|
||||||
|
OMF_NO_SUPER = 2,
|
||||||
|
OMF_NO_COMPRESS = 4,
|
||||||
|
OMF_NO_EXPRESS = 8
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void save_omf(const std::string &path, std::vector<omf::segment> &segments, unsigned flags);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
10
optional.h
10
optional.h
|
@ -56,6 +56,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~optional() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template< class U = T >
|
template< class U = T >
|
||||||
optional& operator=( U&& value ) {
|
optional& operator=( U&& value ) {
|
||||||
|
@ -82,9 +86,11 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< class... Args >
|
||||||
~optional() {
|
void emplace( Args&&... args ) {
|
||||||
reset();
|
reset();
|
||||||
|
new(std::addressof(_data)) T(std::forward<Args>(args)...);
|
||||||
|
_engaged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
AS = wdc816as
|
AS = wdc816as
|
||||||
|
CC = wdc816cc
|
||||||
ASFLAGS = -L
|
ASFLAGS = -L
|
||||||
|
CCFLAGS = -LT -ML -I../include
|
||||||
|
|
||||||
all: instructions.obj hello1.obj hello2.obj hello3.obj labels.obj ref_only.obj
|
all: instructions.obj hello1.obj hello2.obj hello3.obj labels.obj ref_only.obj
|
||||||
|
|
||||||
|
%.obj : %.c
|
||||||
|
$(CC) $(CCFLAGS) $< -o $@
|
||||||
|
|
||||||
|
|
||||||
%.obj : %.asm
|
%.obj : %.asm
|
||||||
$(AS) $(ASFLAGS) $< -o $@
|
$(AS) $(ASFLAGS) $< -o $@
|
||||||
|
|
29
samples/hello4.asm
Normal file
29
samples/hello4.asm
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
;
|
||||||
|
; 2-segment, 2 module code.
|
||||||
|
; with intersegment linkage.
|
||||||
|
|
||||||
|
include 'hello.macros'
|
||||||
|
|
||||||
|
macdelim {
|
||||||
|
|
||||||
|
module code
|
||||||
|
CODE
|
||||||
|
extern text
|
||||||
|
pea #^text
|
||||||
|
pea #text
|
||||||
|
_WriteLine
|
||||||
|
|
||||||
|
rtl
|
||||||
|
ends
|
||||||
|
endmod
|
||||||
|
|
||||||
|
module data
|
||||||
|
XDATA SECTION
|
||||||
|
public text
|
||||||
|
text
|
||||||
|
pstr {'hello, world'}
|
||||||
|
ends
|
||||||
|
endmod
|
||||||
|
|
||||||
|
|
50
samples/hello4.lst
Normal file
50
samples/hello4.lst
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
Thu Jan 12 2017 12:17 Page 1
|
||||||
|
|
||||||
|
|
||||||
|
***************************************
|
||||||
|
** WDC 65C816 Macro Assembler **
|
||||||
|
** **
|
||||||
|
** Version 3.49.1- Feb 6 2006 **
|
||||||
|
***************************************
|
||||||
|
|
||||||
|
1
|
||||||
|
2 ;
|
||||||
|
3 ; 2-segment, 2 module code.
|
||||||
|
4 ; with intersegment linkage.
|
||||||
|
5
|
||||||
|
6 include 'hello.macros'
|
||||||
|
7
|
||||||
|
8 macdelim {
|
||||||
|
9
|
||||||
|
10 module code
|
||||||
|
11 CODE
|
||||||
|
12 extern text
|
||||||
|
13 00:0000: F4 xx xx pea #^text
|
||||||
|
14 00:0003: F4 xx xx pea #text
|
||||||
|
15 _WriteLine
|
||||||
|
+ 15 00:0006: A2 0C 1A ldx #$1a0c
|
||||||
|
+ 15 00:0009: 22 00 00 E1 jsl $e10000
|
||||||
|
16
|
||||||
|
17 00:000D: 6B rtl
|
||||||
|
18 ends
|
||||||
|
19 endmod
|
||||||
|
20
|
||||||
|
21 module data
|
||||||
|
22 XDATA SECTION
|
||||||
|
23 public text
|
||||||
|
24 text
|
||||||
|
25 pstr {'hello, world'}
|
||||||
|
+ 25 00:0000: 0C db end0001-start0001
|
||||||
|
+ 25 start0001
|
||||||
|
+ 25 00:0001: 68 65 6C 6C db 'hello, world'
|
||||||
|
00:0005: 6F 2C 20 77
|
||||||
|
00:0009: 6F 72 6C 64
|
||||||
|
+ 25 end0001
|
||||||
|
26 00:000D: ends
|
||||||
|
27 endmod
|
||||||
|
28
|
||||||
|
29
|
||||||
|
|
||||||
|
|
||||||
|
Lines assembled: 59
|
||||||
|
Errors: 0
|
BIN
samples/hello4.obj
Normal file
BIN
samples/hello4.obj
Normal file
Binary file not shown.
37
samples/relative.asm
Normal file
37
samples/relative.asm
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
; test relative expressions.
|
||||||
|
|
||||||
|
module code1
|
||||||
|
globals on
|
||||||
|
externs on
|
||||||
|
branchb
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
endmod
|
||||||
|
|
||||||
|
module code2
|
||||||
|
globals on
|
||||||
|
externs on
|
||||||
|
jmp branchb
|
||||||
|
bra branchb
|
||||||
|
brl branchb
|
||||||
|
per branchb
|
||||||
|
;
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
;
|
||||||
|
jmp branchf
|
||||||
|
bra branchf
|
||||||
|
brl branchf
|
||||||
|
per branchf
|
||||||
|
|
||||||
|
endmod
|
||||||
|
|
||||||
|
module code3
|
||||||
|
globals on
|
||||||
|
externs on
|
||||||
|
branchf
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
rtl
|
||||||
|
endmod
|
50
samples/relative.lst
Normal file
50
samples/relative.lst
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
Thu Jan 12 2017 12:24 Page 1
|
||||||
|
|
||||||
|
|
||||||
|
***************************************
|
||||||
|
** WDC 65C816 Macro Assembler **
|
||||||
|
** **
|
||||||
|
** Version 3.49.1- Feb 6 2006 **
|
||||||
|
***************************************
|
||||||
|
|
||||||
|
1 ; test relative expressions.
|
||||||
|
2
|
||||||
|
3 module code1
|
||||||
|
4 globals on
|
||||||
|
5 externs on
|
||||||
|
6 branchb
|
||||||
|
7 00:0000: EA nop
|
||||||
|
8 00:0001: EA nop
|
||||||
|
9 endmod
|
||||||
|
10
|
||||||
|
11 module code2
|
||||||
|
12 globals on
|
||||||
|
13 externs on
|
||||||
|
14 00:0000: 4C xx xx jmp branchb
|
||||||
|
15 00:0003: 80 xx bra branchb
|
||||||
|
16 00:0005: 82 xx xx brl branchb
|
||||||
|
17 00:0008: 62 xx xx per branchb
|
||||||
|
18 ;
|
||||||
|
19 00:000B: EA nop
|
||||||
|
20 00:000C: EA nop
|
||||||
|
21 ;
|
||||||
|
22 00:000D: 4C xx xx jmp branchf
|
||||||
|
23 00:0010: 80 xx bra branchf
|
||||||
|
24 00:0012: 82 xx xx brl branchf
|
||||||
|
25 00:0015: 62 xx xx per branchf
|
||||||
|
26
|
||||||
|
27 endmod
|
||||||
|
28
|
||||||
|
29 module code3
|
||||||
|
30 globals on
|
||||||
|
31 externs on
|
||||||
|
32 branchf
|
||||||
|
33 00:0000: EA nop
|
||||||
|
34 00:0001: EA nop
|
||||||
|
35 00:0002: EA nop
|
||||||
|
36 00:0003: 6B rtl
|
||||||
|
37 endmod
|
||||||
|
|
||||||
|
|
||||||
|
Lines assembled: 37
|
||||||
|
Errors: 0
|
BIN
samples/relative.obj
Normal file
BIN
samples/relative.obj
Normal file
Binary file not shown.
109
samples/stdio_test.c
Normal file
109
samples/stdio_test.c
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
#asm
|
||||||
|
phk
|
||||||
|
plb
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
fputs("hello, world\n", stdout);
|
||||||
|
|
||||||
|
fp = fopen("file.txt", "wb");
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// these stubs are not provided in the library but could call gs/os.
|
||||||
|
|
||||||
|
int open(const char *name, int mode) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int close(int fd) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t read(int fd, void *buffer, size_t count) {
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
unsigned pCount;
|
||||||
|
unsigned refNum;
|
||||||
|
void *dataBuffer;
|
||||||
|
unsigned long requestCount;
|
||||||
|
unsigned long transferCount;
|
||||||
|
unsigned cachePriority;
|
||||||
|
} dcb;
|
||||||
|
|
||||||
|
|
||||||
|
unsigned tool_error = 0x0043;
|
||||||
|
|
||||||
|
dcb.pCount = 4;
|
||||||
|
dcb.refNum = fd+1;
|
||||||
|
dcb.dataBuffer = buffer;
|
||||||
|
dcb.requestCount = count;
|
||||||
|
#asm
|
||||||
|
pea #^%%dcb
|
||||||
|
pea #%%dcb
|
||||||
|
pea #$2012
|
||||||
|
jsl $e100b0
|
||||||
|
sta %%tool_error;
|
||||||
|
#endasm
|
||||||
|
if (tool_error) return -1;
|
||||||
|
return dcb.transferCount;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t write(int fd, void *buffer, size_t count) {
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
unsigned pCount;
|
||||||
|
unsigned refNum;
|
||||||
|
void *dataBuffer;
|
||||||
|
unsigned long requestCount;
|
||||||
|
unsigned long transferCount;
|
||||||
|
unsigned cachePriority;
|
||||||
|
} dcb;
|
||||||
|
|
||||||
|
|
||||||
|
unsigned tool_error = 0x0043;
|
||||||
|
|
||||||
|
dcb.pCount = 4;
|
||||||
|
dcb.refNum = fd+1;
|
||||||
|
dcb.dataBuffer = buffer;
|
||||||
|
dcb.requestCount = count;
|
||||||
|
#asm
|
||||||
|
pea #^%%dcb
|
||||||
|
pea #%%dcb
|
||||||
|
pea #$2013
|
||||||
|
jsl $e100b0
|
||||||
|
sta %%tool_error;
|
||||||
|
#endasm
|
||||||
|
if (tool_error) return -1;
|
||||||
|
return dcb.transferCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
long lseek(int fd, long offset, int whence) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int creat(const char *name, int mode) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unlink(const char *name) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int isatty(int fd) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma section udata=heap
|
||||||
|
char __heap[8192];
|
||||||
|
void *heap_start = (void *)__heap;
|
||||||
|
void *heap_end = (void *)&__heap[8092];
|
563
samples/stdio_test.lst
Normal file
563
samples/stdio_test.lst
Normal file
|
@ -0,0 +1,563 @@
|
||||||
|
Tue Jan 17 2017 23:30 Page 1
|
||||||
|
|
||||||
|
|
||||||
|
***************************************
|
||||||
|
** WDC 65C816 Macro Assembler **
|
||||||
|
** **
|
||||||
|
** Version 3.49.1- Feb 6 2006 **
|
||||||
|
***************************************
|
||||||
|
|
||||||
|
1 ;:ts=8
|
||||||
|
2 00000001 R0 equ 1
|
||||||
|
3 00000005 R1 equ 5
|
||||||
|
4 00000009 R2 equ 9
|
||||||
|
5 0000000D R3 equ 13
|
||||||
|
6 ;#include <stdio.h>
|
||||||
|
7 ;#include <fcntl.h>
|
||||||
|
8 ;
|
||||||
|
9 ;
|
||||||
|
10 ;void main(void) {
|
||||||
|
11 code
|
||||||
|
12 xdef ~~main
|
||||||
|
13 func
|
||||||
|
14 ~~main:
|
||||||
|
15 longa on
|
||||||
|
16 longi on
|
||||||
|
17 00:0000: 3B tsc
|
||||||
|
18 00:0001: 38 sec
|
||||||
|
19 00:0002: E9 08 00 sbc #L2
|
||||||
|
20 00:0005: 1B tcs
|
||||||
|
21 00:0006: 0B phd
|
||||||
|
22 00:0007: 5B tcd
|
||||||
|
23 ; FILE *fp;
|
||||||
|
24 ;
|
||||||
|
25 ; #asm
|
||||||
|
26 00000000 fp_1 set 0
|
||||||
|
27 ; phk
|
||||||
|
28 ; plb
|
||||||
|
29 ; #endasm
|
||||||
|
30 asmstart
|
||||||
|
31 00:0008: 4B phk
|
||||||
|
32 00:0009: AB plb
|
||||||
|
33 asmend
|
||||||
|
34 ;
|
||||||
|
35 ; fputs("hello, world\n", stdout);
|
||||||
|
36 00:000A: A9 xx xx lda #<~~_iob+20
|
||||||
|
37 00:000D: 85 01 sta <R0
|
||||||
|
38 xref _BEG_DATA
|
||||||
|
39 00:000F: A9 xx xx lda #_BEG_DATA>>16
|
||||||
|
40 00:0012: 85 03 sta <R0+2
|
||||||
|
41 00:0014: D4 03 pei <R0+2
|
||||||
|
42 00:0016: D4 01 pei <R0
|
||||||
|
43 00:0018: F4 xx xx pea #^L1
|
||||||
|
44 00:001B: F4 xx xx pea #<L1
|
||||||
|
45 00:001E: 22 xx xx xx jsl ~~fputs
|
||||||
|
46 ;
|
||||||
|
47 ; fp = fopen("file.txt", "wb");
|
||||||
|
48 00:0022: F4 xx xx pea #^L1+23
|
||||||
|
49 00:0025: F4 xx xx pea #<L1+23
|
||||||
|
50 00:0028: F4 xx xx pea #^L1+14
|
||||||
|
51 00:002B: F4 xx xx pea #<L1+14
|
||||||
|
52 00:002E: 22 xx xx xx jsl ~~fopen
|
||||||
|
Tue Jan 17 2017 23:30 Page 2
|
||||||
|
|
||||||
|
|
||||||
|
53 00:0032: 85 05 sta <L3+fp_1
|
||||||
|
54 00:0034: 86 07 stx <L3+fp_1+2
|
||||||
|
55 ; fclose(fp);
|
||||||
|
56 00:0036: D4 07 pei <L3+fp_1+2
|
||||||
|
57 00:0038: D4 05 pei <L3+fp_1
|
||||||
|
58 00:003A: 22 xx xx xx jsl ~~fclose
|
||||||
|
59 ;}
|
||||||
|
60 L4:
|
||||||
|
61 00:003E: 2B pld
|
||||||
|
62 00:003F: 3B tsc
|
||||||
|
63 00:0040: 18 clc
|
||||||
|
64 00:0041: 69 08 00 adc #L2
|
||||||
|
65 00:0044: 1B tcs
|
||||||
|
66 00:0045: 6B rtl
|
||||||
|
67 00000008 L2 equ 8
|
||||||
|
68 00000005 L3 equ 5
|
||||||
|
69 ends
|
||||||
|
70 efunc
|
||||||
|
71 data
|
||||||
|
72 L1:
|
||||||
|
73 00:0000: 68 65 6C 6C db $68,$65,$6C,$6C,$6F,$2C,$20,$77,$6F,$72,
|
||||||
|
$6C,$64,$0A,$00,$66
|
||||||
|
00:0004: 6F 2C 20 77
|
||||||
|
00:0008: 6F 72 6C 64
|
||||||
|
00:000C: 0A 00 66
|
||||||
|
74 00:000F: 69 6C 65 2E db $69,$6C,$65,$2E,$74,$78,$74,$00,$77,$62,
|
||||||
|
$00
|
||||||
|
00:0013: 74 78 74 00
|
||||||
|
00:0017: 77 62 00
|
||||||
|
75 00:001A: ends
|
||||||
|
76 ;
|
||||||
|
77 ;// these stubs are not provided in the library bu
|
||||||
|
t could call gs/os.
|
||||||
|
78 ;
|
||||||
|
79 ;int open(const char *name, int mode) {
|
||||||
|
80 code
|
||||||
|
81 xdef ~~open
|
||||||
|
82 func
|
||||||
|
83 ~~open:
|
||||||
|
84 longa on
|
||||||
|
85 longi on
|
||||||
|
86 00:0046: 3B tsc
|
||||||
|
87 00:0047: 38 sec
|
||||||
|
88 00:0048: E9 00 00 sbc #L6
|
||||||
|
89 00:004B: 1B tcs
|
||||||
|
90 00:004C: 0B phd
|
||||||
|
91 00:004D: 5B tcd
|
||||||
|
92 00000004 name_0 set 4
|
||||||
|
93 00000008 mode_0 set 8
|
||||||
|
94 ; return -1;
|
||||||
|
95 00:004E: A9 FF FF lda #$ffff
|
||||||
|
96 L8:
|
||||||
|
97 00:0051: A8 tay
|
||||||
|
98 00:0052: A5 02 lda <L6+2
|
||||||
|
99 00:0054: 85 08 sta <L6+2+6
|
||||||
|
100 00:0056: A5 01 lda <L6+1
|
||||||
|
101 00:0058: 85 07 sta <L6+1+6
|
||||||
|
102 00:005A: 2B pld
|
||||||
|
Tue Jan 17 2017 23:30 Page 3
|
||||||
|
|
||||||
|
|
||||||
|
103 00:005B: 3B tsc
|
||||||
|
104 00:005C: 18 clc
|
||||||
|
105 00:005D: 69 06 00 adc #L6+6
|
||||||
|
106 00:0060: 1B tcs
|
||||||
|
107 00:0061: 98 tya
|
||||||
|
108 00:0062: 6B rtl
|
||||||
|
109 ;}
|
||||||
|
110 00000000 L6 equ 0
|
||||||
|
111 00000001 L7 equ 1
|
||||||
|
112 ends
|
||||||
|
113 efunc
|
||||||
|
114 ;
|
||||||
|
115 ;int close(int fd) {
|
||||||
|
116 code
|
||||||
|
117 xdef ~~close
|
||||||
|
118 func
|
||||||
|
119 ~~close:
|
||||||
|
120 longa on
|
||||||
|
121 longi on
|
||||||
|
122 00:0063: 3B tsc
|
||||||
|
123 00:0064: 38 sec
|
||||||
|
124 00:0065: E9 00 00 sbc #L9
|
||||||
|
125 00:0068: 1B tcs
|
||||||
|
126 00:0069: 0B phd
|
||||||
|
127 00:006A: 5B tcd
|
||||||
|
128 00000004 fd_0 set 4
|
||||||
|
129 ; return -1;
|
||||||
|
130 00:006B: A9 FF FF lda #$ffff
|
||||||
|
131 L11:
|
||||||
|
132 00:006E: A8 tay
|
||||||
|
133 00:006F: A5 02 lda <L9+2
|
||||||
|
134 00:0071: 85 04 sta <L9+2+2
|
||||||
|
135 00:0073: A5 01 lda <L9+1
|
||||||
|
136 00:0075: 85 03 sta <L9+1+2
|
||||||
|
137 00:0077: 2B pld
|
||||||
|
138 00:0078: 3B tsc
|
||||||
|
139 00:0079: 18 clc
|
||||||
|
140 00:007A: 69 02 00 adc #L9+2
|
||||||
|
141 00:007D: 1B tcs
|
||||||
|
142 00:007E: 98 tya
|
||||||
|
143 00:007F: 6B rtl
|
||||||
|
144 ;}
|
||||||
|
145 00000000 L9 equ 0
|
||||||
|
146 00000001 L10 equ 1
|
||||||
|
147 ends
|
||||||
|
148 efunc
|
||||||
|
149 ;
|
||||||
|
150 ;
|
||||||
|
151 ;size_t read(int fd, void *buffer, size_t count) {
|
||||||
|
152 code
|
||||||
|
153 xdef ~~read
|
||||||
|
154 func
|
||||||
|
155 ~~read:
|
||||||
|
156 longa on
|
||||||
|
157 longi on
|
||||||
|
158 00:0080: 3B tsc
|
||||||
|
159 00:0081: 38 sec
|
||||||
|
160 00:0082: E9 02 00 sbc #L12
|
||||||
|
Tue Jan 17 2017 23:30 Page 4
|
||||||
|
|
||||||
|
|
||||||
|
161 00:0085: 1B tcs
|
||||||
|
162 00:0086: 0B phd
|
||||||
|
163 00:0087: 5B tcd
|
||||||
|
164 00000004 fd_0 set 4
|
||||||
|
165 00000006 buffer_0 set 6
|
||||||
|
166 0000000A count_0 set 10
|
||||||
|
167 ;
|
||||||
|
168 ;static struct {
|
||||||
|
169 ; unsigned pCount;
|
||||||
|
170 ; unsigned refNum;
|
||||||
|
171 ; void *dataBuffer;
|
||||||
|
172 ; unsigned long requestCount;
|
||||||
|
173 ; unsigned long transferCount;
|
||||||
|
174 ; unsigned cachePriority;
|
||||||
|
175 ;} dcb;
|
||||||
|
176 udata
|
||||||
|
177 L10001:
|
||||||
|
178 00:0000: ds 18
|
||||||
|
179 00:0012: ends
|
||||||
|
180 ;
|
||||||
|
181 ;
|
||||||
|
182 ; unsigned tool_error = 0x0043;
|
||||||
|
183 ;
|
||||||
|
184 ; dcb.pCount = 4;
|
||||||
|
185 00000000 tool_error_1 set 0
|
||||||
|
186 00:0088: A9 43 00 lda #$43
|
||||||
|
187 00:008B: 85 01 sta <L13+tool_error_1
|
||||||
|
188 00:008D: A9 04 00 lda #$4
|
||||||
|
189 00:0090: 8D xx xx sta |L10001
|
||||||
|
190 ; dcb.refNum = fd+1;
|
||||||
|
191 00:0093: A5 06 lda <L12+fd_0
|
||||||
|
192 00:0095: 1A ina
|
||||||
|
193 00:0096: 8D xx xx sta |L10001+2
|
||||||
|
194 ; dcb.dataBuffer = buffer;
|
||||||
|
195 00:0099: A5 08 lda <L12+buffer_0
|
||||||
|
196 00:009B: 8D xx xx sta |L10001+4
|
||||||
|
197 00:009E: A5 0A lda <L12+buffer_0+2
|
||||||
|
198 00:00A0: 8D xx xx sta |L10001+4+2
|
||||||
|
199 ; dcb.requestCount = count;
|
||||||
|
200 00:00A3: A5 0C lda <L12+count_0
|
||||||
|
201 00:00A5: 8D xx xx sta |L10001+8
|
||||||
|
202 00:00A8: 9C xx xx stz |L10001+8+2
|
||||||
|
203 ; #asm
|
||||||
|
204 ; pea #^%%dcb
|
||||||
|
205 ; pea #%%dcb
|
||||||
|
206 ; pea #$2012
|
||||||
|
207 ; jsl $e100b0
|
||||||
|
208 ; sta %%tool_error;
|
||||||
|
209 ; #endasm
|
||||||
|
210 asmstart
|
||||||
|
211 00:00AB: F4 xx xx pea #^L10001
|
||||||
|
212 00:00AE: F4 xx xx pea #L10001
|
||||||
|
213 00:00B1: F4 12 20 pea #$2012
|
||||||
|
214 00:00B4: 22 B0 00 E1 jsl $e100b0
|
||||||
|
215 00:00B8: 85 01 sta <L13+tool_error_1;
|
||||||
|
216 asmend
|
||||||
|
217 ; if (tool_error) return -1;
|
||||||
|
218 00:00BA: A5 01 lda <L13+tool_error_1
|
||||||
|
Tue Jan 17 2017 23:30 Page 5
|
||||||
|
|
||||||
|
|
||||||
|
219 00:00BC: D0 03 bne L14
|
||||||
|
220 00:00BE: 82 15 00 brl L10002
|
||||||
|
221 L14:
|
||||||
|
222 00:00C1: A9 FF FF lda #$ffff
|
||||||
|
223 L15:
|
||||||
|
224 00:00C4: A8 tay
|
||||||
|
225 00:00C5: A5 04 lda <L12+2
|
||||||
|
226 00:00C7: 85 0C sta <L12+2+8
|
||||||
|
227 00:00C9: A5 03 lda <L12+1
|
||||||
|
228 00:00CB: 85 0B sta <L12+1+8
|
||||||
|
229 00:00CD: 2B pld
|
||||||
|
230 00:00CE: 3B tsc
|
||||||
|
231 00:00CF: 18 clc
|
||||||
|
232 00:00D0: 69 0A 00 adc #L12+8
|
||||||
|
233 00:00D3: 1B tcs
|
||||||
|
234 00:00D4: 98 tya
|
||||||
|
235 00:00D5: 6B rtl
|
||||||
|
236 ; return dcb.transferCount;
|
||||||
|
237 L10002:
|
||||||
|
238 00:00D6: AD xx xx lda |L10001+12
|
||||||
|
239 00:00D9: 82 E8 FF brl L15
|
||||||
|
240 ;
|
||||||
|
241 ;}
|
||||||
|
242 00000002 L12 equ 2
|
||||||
|
243 00000001 L13 equ 1
|
||||||
|
244 ends
|
||||||
|
245 efunc
|
||||||
|
246 ;
|
||||||
|
247 ;size_t write(int fd, void *buffer, size_t count)
|
||||||
|
{
|
||||||
|
248 code
|
||||||
|
249 xdef ~~write
|
||||||
|
250 func
|
||||||
|
251 ~~write:
|
||||||
|
252 longa on
|
||||||
|
253 longi on
|
||||||
|
254 00:00DC: 3B tsc
|
||||||
|
255 00:00DD: 38 sec
|
||||||
|
256 00:00DE: E9 02 00 sbc #L16
|
||||||
|
257 00:00E1: 1B tcs
|
||||||
|
258 00:00E2: 0B phd
|
||||||
|
259 00:00E3: 5B tcd
|
||||||
|
260 00000004 fd_0 set 4
|
||||||
|
261 00000006 buffer_0 set 6
|
||||||
|
262 0000000A count_0 set 10
|
||||||
|
263 ;
|
||||||
|
264 ;static struct {
|
||||||
|
265 ; unsigned pCount;
|
||||||
|
266 ; unsigned refNum;
|
||||||
|
267 ; void *dataBuffer;
|
||||||
|
268 ; unsigned long requestCount;
|
||||||
|
269 ; unsigned long transferCount;
|
||||||
|
270 ; unsigned cachePriority;
|
||||||
|
271 ;} dcb;
|
||||||
|
272 udata
|
||||||
|
273 L10003:
|
||||||
|
274 00:0012: ds 18
|
||||||
|
275 00:0024: ends
|
||||||
|
Tue Jan 17 2017 23:30 Page 6
|
||||||
|
|
||||||
|
|
||||||
|
276 ;
|
||||||
|
277 ;
|
||||||
|
278 ; unsigned tool_error = 0x0043;
|
||||||
|
279 ;
|
||||||
|
280 ; dcb.pCount = 4;
|
||||||
|
281 00000000 tool_error_1 set 0
|
||||||
|
282 00:00E4: A9 43 00 lda #$43
|
||||||
|
283 00:00E7: 85 01 sta <L17+tool_error_1
|
||||||
|
284 00:00E9: A9 04 00 lda #$4
|
||||||
|
285 00:00EC: 8D xx xx sta |L10003
|
||||||
|
286 ; dcb.refNum = fd+1;
|
||||||
|
287 00:00EF: A5 06 lda <L16+fd_0
|
||||||
|
288 00:00F1: 1A ina
|
||||||
|
289 00:00F2: 8D xx xx sta |L10003+2
|
||||||
|
290 ; dcb.dataBuffer = buffer;
|
||||||
|
291 00:00F5: A5 08 lda <L16+buffer_0
|
||||||
|
292 00:00F7: 8D xx xx sta |L10003+4
|
||||||
|
293 00:00FA: A5 0A lda <L16+buffer_0+2
|
||||||
|
294 00:00FC: 8D xx xx sta |L10003+4+2
|
||||||
|
295 ; dcb.requestCount = count;
|
||||||
|
296 00:00FF: A5 0C lda <L16+count_0
|
||||||
|
297 00:0101: 8D xx xx sta |L10003+8
|
||||||
|
298 00:0104: 9C xx xx stz |L10003+8+2
|
||||||
|
299 ; #asm
|
||||||
|
300 ; pea #^%%dcb
|
||||||
|
301 ; pea #%%dcb
|
||||||
|
302 ; pea #$2013
|
||||||
|
303 ; jsl $e100b0
|
||||||
|
304 ; sta %%tool_error;
|
||||||
|
305 ; #endasm
|
||||||
|
306 asmstart
|
||||||
|
307 00:0107: F4 xx xx pea #^L10003
|
||||||
|
308 00:010A: F4 xx xx pea #L10003
|
||||||
|
309 00:010D: F4 13 20 pea #$2013
|
||||||
|
310 00:0110: 22 B0 00 E1 jsl $e100b0
|
||||||
|
311 00:0114: 85 01 sta <L17+tool_error_1;
|
||||||
|
312 asmend
|
||||||
|
313 ; if (tool_error) return -1;
|
||||||
|
314 00:0116: A5 01 lda <L17+tool_error_1
|
||||||
|
315 00:0118: D0 03 bne L18
|
||||||
|
316 00:011A: 82 15 00 brl L10004
|
||||||
|
317 L18:
|
||||||
|
318 00:011D: A9 FF FF lda #$ffff
|
||||||
|
319 L19:
|
||||||
|
320 00:0120: A8 tay
|
||||||
|
321 00:0121: A5 04 lda <L16+2
|
||||||
|
322 00:0123: 85 0C sta <L16+2+8
|
||||||
|
323 00:0125: A5 03 lda <L16+1
|
||||||
|
324 00:0127: 85 0B sta <L16+1+8
|
||||||
|
325 00:0129: 2B pld
|
||||||
|
326 00:012A: 3B tsc
|
||||||
|
327 00:012B: 18 clc
|
||||||
|
328 00:012C: 69 0A 00 adc #L16+8
|
||||||
|
329 00:012F: 1B tcs
|
||||||
|
330 00:0130: 98 tya
|
||||||
|
331 00:0131: 6B rtl
|
||||||
|
332 ; return dcb.transferCount;
|
||||||
|
333 L10004:
|
||||||
|
Tue Jan 17 2017 23:30 Page 7
|
||||||
|
|
||||||
|
|
||||||
|
334 00:0132: AD xx xx lda |L10003+12
|
||||||
|
335 00:0135: 82 E8 FF brl L19
|
||||||
|
336 ;}
|
||||||
|
337 00000002 L16 equ 2
|
||||||
|
338 00000001 L17 equ 1
|
||||||
|
339 ends
|
||||||
|
340 efunc
|
||||||
|
341 ;
|
||||||
|
342 ;long lseek(int fd, long offset, int whence) {
|
||||||
|
343 code
|
||||||
|
344 xdef ~~lseek
|
||||||
|
345 func
|
||||||
|
346 ~~lseek:
|
||||||
|
347 longa on
|
||||||
|
348 longi on
|
||||||
|
349 00:0138: 3B tsc
|
||||||
|
350 00:0139: 38 sec
|
||||||
|
351 00:013A: E9 00 00 sbc #L20
|
||||||
|
352 00:013D: 1B tcs
|
||||||
|
353 00:013E: 0B phd
|
||||||
|
354 00:013F: 5B tcd
|
||||||
|
355 00000004 fd_0 set 4
|
||||||
|
356 00000006 offset_0 set 6
|
||||||
|
357 0000000A whence_0 set 10
|
||||||
|
358 ; return -1;
|
||||||
|
359 00:0140: A9 FF FF lda #$ffff
|
||||||
|
360 00:0143: AA tax
|
||||||
|
361 00:0144: A9 FF FF lda #$ffff
|
||||||
|
362 L22:
|
||||||
|
363 00:0147: A8 tay
|
||||||
|
364 00:0148: A5 02 lda <L20+2
|
||||||
|
365 00:014A: 85 0A sta <L20+2+8
|
||||||
|
366 00:014C: A5 01 lda <L20+1
|
||||||
|
367 00:014E: 85 09 sta <L20+1+8
|
||||||
|
368 00:0150: 2B pld
|
||||||
|
369 00:0151: 3B tsc
|
||||||
|
370 00:0152: 18 clc
|
||||||
|
371 00:0153: 69 08 00 adc #L20+8
|
||||||
|
372 00:0156: 1B tcs
|
||||||
|
373 00:0157: 98 tya
|
||||||
|
374 00:0158: 6B rtl
|
||||||
|
375 ;}
|
||||||
|
376 00000000 L20 equ 0
|
||||||
|
377 00000001 L21 equ 1
|
||||||
|
378 ends
|
||||||
|
379 efunc
|
||||||
|
380 ;
|
||||||
|
381 ;int creat(const char *name, int mode) {
|
||||||
|
382 code
|
||||||
|
383 xdef ~~creat
|
||||||
|
384 func
|
||||||
|
385 ~~creat:
|
||||||
|
386 longa on
|
||||||
|
387 longi on
|
||||||
|
388 00:0159: 3B tsc
|
||||||
|
389 00:015A: 38 sec
|
||||||
|
390 00:015B: E9 00 00 sbc #L23
|
||||||
|
391 00:015E: 1B tcs
|
||||||
|
Tue Jan 17 2017 23:30 Page 8
|
||||||
|
|
||||||
|
|
||||||
|
392 00:015F: 0B phd
|
||||||
|
393 00:0160: 5B tcd
|
||||||
|
394 00000004 name_0 set 4
|
||||||
|
395 00000008 mode_0 set 8
|
||||||
|
396 ; return -1;
|
||||||
|
397 00:0161: A9 FF FF lda #$ffff
|
||||||
|
398 L25:
|
||||||
|
399 00:0164: A8 tay
|
||||||
|
400 00:0165: A5 02 lda <L23+2
|
||||||
|
401 00:0167: 85 08 sta <L23+2+6
|
||||||
|
402 00:0169: A5 01 lda <L23+1
|
||||||
|
403 00:016B: 85 07 sta <L23+1+6
|
||||||
|
404 00:016D: 2B pld
|
||||||
|
405 00:016E: 3B tsc
|
||||||
|
406 00:016F: 18 clc
|
||||||
|
407 00:0170: 69 06 00 adc #L23+6
|
||||||
|
408 00:0173: 1B tcs
|
||||||
|
409 00:0174: 98 tya
|
||||||
|
410 00:0175: 6B rtl
|
||||||
|
411 ;}
|
||||||
|
412 00000000 L23 equ 0
|
||||||
|
413 00000001 L24 equ 1
|
||||||
|
414 ends
|
||||||
|
415 efunc
|
||||||
|
416 ;
|
||||||
|
417 ;int unlink(const char *name) {
|
||||||
|
418 code
|
||||||
|
419 xdef ~~unlink
|
||||||
|
420 func
|
||||||
|
421 ~~unlink:
|
||||||
|
422 longa on
|
||||||
|
423 longi on
|
||||||
|
424 00:0176: 3B tsc
|
||||||
|
425 00:0177: 38 sec
|
||||||
|
426 00:0178: E9 00 00 sbc #L26
|
||||||
|
427 00:017B: 1B tcs
|
||||||
|
428 00:017C: 0B phd
|
||||||
|
429 00:017D: 5B tcd
|
||||||
|
430 00000004 name_0 set 4
|
||||||
|
431 ; return -1;
|
||||||
|
432 00:017E: A9 FF FF lda #$ffff
|
||||||
|
433 L28:
|
||||||
|
434 00:0181: A8 tay
|
||||||
|
435 00:0182: A5 02 lda <L26+2
|
||||||
|
436 00:0184: 85 06 sta <L26+2+4
|
||||||
|
437 00:0186: A5 01 lda <L26+1
|
||||||
|
438 00:0188: 85 05 sta <L26+1+4
|
||||||
|
439 00:018A: 2B pld
|
||||||
|
440 00:018B: 3B tsc
|
||||||
|
441 00:018C: 18 clc
|
||||||
|
442 00:018D: 69 04 00 adc #L26+4
|
||||||
|
443 00:0190: 1B tcs
|
||||||
|
444 00:0191: 98 tya
|
||||||
|
445 00:0192: 6B rtl
|
||||||
|
446 ;}
|
||||||
|
447 00000000 L26 equ 0
|
||||||
|
448 00000001 L27 equ 1
|
||||||
|
449 ends
|
||||||
|
Tue Jan 17 2017 23:30 Page 9
|
||||||
|
|
||||||
|
|
||||||
|
450 efunc
|
||||||
|
451 ;
|
||||||
|
452 ;int isatty(int fd) {
|
||||||
|
453 code
|
||||||
|
454 xdef ~~isatty
|
||||||
|
455 func
|
||||||
|
456 ~~isatty:
|
||||||
|
457 longa on
|
||||||
|
458 longi on
|
||||||
|
459 00:0193: 3B tsc
|
||||||
|
460 00:0194: 38 sec
|
||||||
|
461 00:0195: E9 00 00 sbc #L29
|
||||||
|
462 00:0198: 1B tcs
|
||||||
|
463 00:0199: 0B phd
|
||||||
|
464 00:019A: 5B tcd
|
||||||
|
465 00000004 fd_0 set 4
|
||||||
|
466 ; return -1;
|
||||||
|
467 00:019B: A9 FF FF lda #$ffff
|
||||||
|
468 L31:
|
||||||
|
469 00:019E: A8 tay
|
||||||
|
470 00:019F: A5 02 lda <L29+2
|
||||||
|
471 00:01A1: 85 04 sta <L29+2+2
|
||||||
|
472 00:01A3: A5 01 lda <L29+1
|
||||||
|
473 00:01A5: 85 03 sta <L29+1+2
|
||||||
|
474 00:01A7: 2B pld
|
||||||
|
475 00:01A8: 3B tsc
|
||||||
|
476 00:01A9: 18 clc
|
||||||
|
477 00:01AA: 69 02 00 adc #L29+2
|
||||||
|
478 00:01AD: 1B tcs
|
||||||
|
479 00:01AE: 98 tya
|
||||||
|
480 00:01AF: 6B rtl
|
||||||
|
481 ;}
|
||||||
|
482 00000000 L29 equ 0
|
||||||
|
483 00000001 L30 equ 1
|
||||||
|
484 ends
|
||||||
|
485 efunc
|
||||||
|
486 ;
|
||||||
|
487 ;
|
||||||
|
488 ;#pragma section udata=heap
|
||||||
|
489 heap section
|
||||||
|
490 00:0000: ends
|
||||||
|
491 ;char __heap[8192];
|
||||||
|
492 ;void *heap_start = (void *)__heap;
|
||||||
|
493 data
|
||||||
|
494 xdef ~~heap_start
|
||||||
|
495 ~~heap_start:
|
||||||
|
496 00:001A: xx xx xx xx dl ~~__heap
|
||||||
|
497 00:001E: ends
|
||||||
|
498 ;void *heap_end = (void *)&__heap[8092];
|
||||||
|
499 data
|
||||||
|
500 xdef ~~heap_end
|
||||||
|
501 ~~heap_end:
|
||||||
|
502 00:001E: xx xx xx xx dl ~~__heap+8092
|
||||||
|
503 00:0022: ends
|
||||||
|
504 ;
|
||||||
|
505 xref ~~fputs
|
||||||
|
506 xref ~~fopen
|
||||||
|
507 xref ~~fclose
|
||||||
|
Tue Jan 17 2017 23:30 Page 10
|
||||||
|
|
||||||
|
|
||||||
|
508 heap
|
||||||
|
509 xdef ~~__heap
|
||||||
|
510 ~~__heap
|
||||||
|
511 00:0000: ds 8192
|
||||||
|
512 00:2000: ends
|
||||||
|
513 xref ~~_iob
|
||||||
|
514 end
|
||||||
|
|
||||||
|
|
||||||
|
Lines assembled: 514
|
||||||
|
Errors: 0
|
BIN
samples/stdio_test.obj
Normal file
BIN
samples/stdio_test.obj
Normal file
Binary file not shown.
|
@ -1,276 +1,20 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <system_error>
|
||||||
|
#include <afp/finder_info.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type) {
|
||||||
#include <sys/xattr.h>
|
|
||||||
|
|
||||||
#elif defined(__linux__)
|
afp::finder_info fi;
|
||||||
#include <sys/xattr.h>
|
std::error_code ec;
|
||||||
#define XATTR_FINDERINFO_NAME "user.com.apple.FinderInfo"
|
|
||||||
|
|
||||||
#elif defined(__FreeBSD__)
|
if (!fi.open(path, afp::finder_info::read_write, ec))
|
||||||
#include <sys/types.h>
|
return -1;
|
||||||
#include <sys/extattr.h>
|
|
||||||
|
|
||||||
#elif defined(_AIX)
|
fi.set_prodos_file_type(file_type, aux_type);
|
||||||
#include <sys/ea.h>
|
if (!fi.write(ec))
|
||||||
|
return -1;
|
||||||
|
|
||||||
#elif defined(__sun)
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
#else
|
|
||||||
#error "set_file_type: unsupported OS."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef XATTR_FINDERINFO_NAME
|
|
||||||
#define XATTR_FINDERINFO_NAME "com.apple.FinderInfo"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* extended attributes functions.
|
|
||||||
*/
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
ssize_t size_xattr(int fd, const char *xattr) {
|
|
||||||
return fgetxattr(fd, xattr, NULL, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t read_xattr(int fd, const char *xattr, void *buffer, size_t size) {
|
|
||||||
return fgetxattr(fd, xattr, buffer, size, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t write_xattr(int fd, const char *xattr, const void *buffer, size_t size) {
|
|
||||||
if (fsetxattr(fd, xattr, buffer, size, 0, 0) < 0) return -1;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int remove_xattr(int fd, const char *xattr) {
|
|
||||||
return fremovexattr(fd, xattr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__linux__)
|
|
||||||
ssize_t size_xattr(int fd, const char *xattr) {
|
|
||||||
return fgetxattr(fd, xattr, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t read_xattr(int fd, const char *xattr, void *buffer, size_t size) {
|
|
||||||
return fgetxattr(fd, xattr, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t write_xattr(int fd, const char *xattr, const void *buffer, size_t size) {
|
|
||||||
if (fsetxattr(fd, xattr, buffer, size, 0) < 0) return -1;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int remove_xattr(int fd, const char *xattr) {
|
|
||||||
return fremovexattr(fd, xattr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__FreeBSD__)
|
|
||||||
ssize_t size_xattr(int fd, const char *xattr) {
|
|
||||||
return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, xattr, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t read_xattr(int fd, const char *xattr, void *buffer, size_t size) {
|
|
||||||
return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, xattr, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t write_xattr(int fd, const char *xattr, const void *buffer, size_t size) {
|
|
||||||
return extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, xattr, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int remove_xattr(int fd, const char *xattr) {
|
|
||||||
return extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, xattr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(_AIX)
|
|
||||||
ssize_t size_xattr(int fd, const char *xattr) {
|
|
||||||
/*
|
|
||||||
struct stat64x st;
|
|
||||||
if (fstatea(fd, xattr, &st) < 0) return -1;
|
|
||||||
return st.st_size;
|
|
||||||
*/
|
|
||||||
return fgetea(fd, xattr, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t read_xattr(int fd, const char *xattr, void *buffer, size_t size) {
|
|
||||||
return fgetea(fd, xattr, buffer, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t write_xattr(int fd, const char *xattr, const void *buffer, size_t size) {
|
|
||||||
if (fsetea(fd, xattr, buffer, size, 0) < 0) return -1;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int remove_xattr(int fd, const char *xattr) {
|
|
||||||
return fremoveea(fd, xattr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static int file_type_to_finder_info(uint8_t *buffer, uint16_t file_type, uint32_t aux_type) {
|
|
||||||
if (file_type > 0xff || aux_type > 0xffff) return -1;
|
|
||||||
|
|
||||||
if (!file_type && aux_type == 0x0000) {
|
|
||||||
memcpy(buffer, "BINApdos", 8);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_type == 0x04 && aux_type == 0x0000) {
|
|
||||||
memcpy(buffer, "TEXTpdos", 8);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_type == 0xff && aux_type == 0x0000) {
|
|
||||||
memcpy(buffer, "PSYSpdos", 8);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_type == 0xb3 && aux_type == 0x0000) {
|
|
||||||
memcpy(buffer, "PS16pdos", 8);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_type == 0xd7 && aux_type == 0x0000) {
|
|
||||||
memcpy(buffer, "MIDIpdos", 8);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (file_type == 0xd8 && aux_type == 0x0000) {
|
|
||||||
memcpy(buffer, "AIFFpdos", 8);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (file_type == 0xd8 && aux_type == 0x0001) {
|
|
||||||
memcpy(buffer, "AIFCpdos", 8);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (file_type == 0xe0 && aux_type == 0x0005) {
|
|
||||||
memcpy(buffer, "dImgdCpy", 8);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
memcpy(buffer, "p pdos", 8);
|
|
||||||
buffer[1] = (file_type) & 0xff;
|
|
||||||
buffer[2] = (aux_type >> 8) & 0xff;
|
|
||||||
buffer[3] = (aux_type) & 0xff;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 2)
|
|
||||||
struct AFP_Info {
|
|
||||||
uint32_t magic;
|
|
||||||
uint32_t version;
|
|
||||||
uint32_t file_id;
|
|
||||||
uint32_t backup_date;
|
|
||||||
uint8_t finder_info[32];
|
|
||||||
uint16_t prodos_file_type;
|
|
||||||
uint32_t prodos_aux_type;
|
|
||||||
uint8_t reserved[6];
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
static void afp_init(struct AFP_Info *info, uint16_t file_type, uint32_t aux_type) {
|
|
||||||
//static_assert(sizeof(AFP_Info) == 60, "Incorrect AFP_Info size");
|
|
||||||
memset(info, 0, sizeof(*info));
|
|
||||||
info->magic = 0x00504641;
|
|
||||||
info->version = 0x00010000;
|
|
||||||
info->prodos_file_type = file_type;
|
|
||||||
info->prodos_aux_type = aux_type;
|
|
||||||
if (file_type || aux_type)
|
|
||||||
file_type_to_finder_info(info->finder_info, file_type, aux_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool afp_verify(struct AFP_Info *info) {
|
|
||||||
if (!info) return false;
|
|
||||||
|
|
||||||
if (info->magic != 0x00504641) return false;
|
|
||||||
if (info->version != 0x00010000) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type) {
|
|
||||||
AFP_Info info;
|
|
||||||
int ok;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
ok = stat(path.c_str(), &st);
|
|
||||||
if (ok == 0 && ! S_ISDIR(st.st_mode)) {
|
|
||||||
|
|
||||||
std::string xpath(path);
|
|
||||||
xpath.append(":AFP_AfpInfo");
|
|
||||||
|
|
||||||
int fd = open(xpath.c_str(), O_RDWR | O_CREAT | O_BINARY, 0666);
|
|
||||||
if (fd < 0) return -1;
|
|
||||||
|
|
||||||
ok = read(fd, &info, sizeof(info));
|
|
||||||
if (ok < sizeof(info) || !afp_verify(&info)) {
|
|
||||||
afp_init(&info, file_type, aux_type);
|
|
||||||
} else {
|
|
||||||
info.prodos_file_type = file_type;
|
|
||||||
info.prodos_aux_type = aux_type;
|
|
||||||
file_type_to_finder_info(info.finder_info, file_type, aux_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
|
||||||
ok = write(fd, &info, sizeof(info));
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
}
|
|
||||||
if (ok > 0) ok = 0;
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type) {
|
|
||||||
|
|
||||||
|
|
||||||
int fd;
|
|
||||||
int ok;
|
|
||||||
struct stat st;
|
|
||||||
fd = open(path.c_str(), O_RDONLY);
|
|
||||||
if (fd < 0) return -1;
|
|
||||||
|
|
||||||
ok = fstat(fd, &st);
|
|
||||||
if (ok == 0 && !S_ISDIR(st.st_mode)) {
|
|
||||||
uint8_t buffer[32];
|
|
||||||
memset(buffer, 0, sizeof(buffer));
|
|
||||||
|
|
||||||
#if defined(__sun)
|
|
||||||
int xfd = attropen(path, XATTR_RESOURCEFORK_NAME, O_RDWR | O_CREAT, 0666);
|
|
||||||
if (xfd < 0) {
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ok = read(xfd, buffer, 32);
|
|
||||||
file_type_to_finder_info(buffer, file_type, aux_type);
|
|
||||||
lseek(xfd, 0, SEEK_SET);
|
|
||||||
ok = write(xfd, buffer, 32);
|
|
||||||
close(xfd);
|
|
||||||
#else
|
|
||||||
|
|
||||||
ok = read_xattr(fd, XATTR_FINDERINFO_NAME, buffer, 32);
|
|
||||||
file_type_to_finder_info(buffer, file_type, aux_type);
|
|
||||||
ok = write_xattr(fd, XATTR_FINDERINFO_NAME, buffer, 32);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
if (ok > 0) ok = 0;
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
static constexpr const int equ_type = (ST_EQU << 4) | S_ABS;
|
static constexpr const int equ_type = (ST_EQU << 4) | S_ABS;
|
||||||
|
|
||||||
zrdz_disassembler::zrdz_disassembler(std::vector<section> &§ions, std::vector<symbol> &&symbols) :
|
zrdz_disassembler::zrdz_disassembler(std::vector<section> &§ions, std::vector<symbol> &&symbols) :
|
||||||
_symbols(std::move(symbols))
|
disassembler(wdc), _symbols(std::move(symbols))
|
||||||
{
|
{
|
||||||
|
|
||||||
// do not sort _symbols ... order matters for lookup by entry number.
|
// do not sort _symbols ... order matters for lookup by entry number.
|
||||||
|
@ -91,10 +91,10 @@ void zrdz_disassembler::front_matter(const std::string &module) {
|
||||||
if ((e.flags & SEC_REF_ONLY) == 0) continue;
|
if ((e.flags & SEC_REF_ONLY) == 0) continue;
|
||||||
if (e.size == 0 && e.symbols.empty()) continue;
|
if (e.size == 0 && e.symbols.empty()) continue;
|
||||||
|
|
||||||
e.processed = true;
|
|
||||||
print_section(e);
|
print_section(e);
|
||||||
print_globals(e.number);
|
print_globals(e.number);
|
||||||
print_equs(e.number);
|
print_equs(e.number);
|
||||||
|
e.processed = true;
|
||||||
|
|
||||||
if (e.org) emit("", ".org", to_x(e.org, 4, '$'));
|
if (e.org) emit("", ".org", to_x(e.org, 4, '$'));
|
||||||
uint32_t pc = e.org;
|
uint32_t pc = e.org;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user