1
0
mirror of https://github.com/ksherlock/x65.git synced 2024-06-02 03:41:28 +00:00

Added type of sections

- x65 now has a type for each section
This commit is contained in:
Carl-Henrik Skårstedt 2015-11-06 22:48:50 -08:00
parent 97dc0ad5e6
commit 5030d0be15
3 changed files with 153 additions and 34 deletions

View File

@ -23,6 +23,17 @@ There are no hard limits on binary size so if the address exceeds $ffff it will
There is a sublime package for coding/building in Sublime Text 3 in the *sublime* subfolder.
## Features
* **Code**
* **Linking**
* **Comments**
* **Labels**
* **Directives**
* **Macros**
* **Expressions**
* **List File with Cycle Count**
## Prerequisite
x65.cpp requires struse.h which is a single file text parsing library that can be retrieved from https://github.com/Sakrac/struse.
@ -65,16 +76,6 @@ x65 filename.s code.prg [options]
* -vice (file.vs): export a vice symbol file
* -endm: macro and rept end with endm/endr or endmacro/endrepeat instead of scoped ('{' - '}')
## Features
* **Code**
* **Linking**
* **Comments**
* **Labels**
* **Directives**
* **Macros**
* **Expressions**
### Code
Code is any valid mnemonic/opcode and addressing mode. At the moment only one opcode per line is assembled.
@ -686,6 +687,63 @@ Define byte triplets (like **DA** but three bytes instead of 2)
Define values of four bytes.
## List File
This is a typical list file. Columns from left to right are:
* Address
* Bytes (up to 4) generated by this line
* Instruction (disassembled)
* Cycles for this instruction, + indicates this instruction can be an extra cycle due to condition or for 65816 multiple extra cycles.
* Source code that generated this line
For scope lines ('{' - '}') the sum of the cycles within the scope is added up as are the additional cycles.
```
c>1 Sin {
$0000 a2 03 ldx #$03 2 ldx #3
c>2 {
$0002 b5 e8 lda $e8,x 4 lda SinP.Ang,x
$0004 95 ec sta $ec,x 4 sta SinP.R,x ; result starts with x
$0006 95 e4 sta $e4,x 4 sta SinP.W0,x
$0008 95 f4 sta $f4,x 4 sta Mul824.A,x
$000a 95 f0 sta $f0,x 4 sta Mul824.B,x
$000c ca dex 2 dex
$000d 10 f3 bpl $0002 2+ bpl !
c<2 = 24 + 1 }
; x^2, copy to W1
$000f a9 e0 lda #$e0 2 lda #SinP.W1
$0011 20 00 00 jsr $0000 6 jsr Multiply824S_Copy
; iterate value
$0014 a0 00 ldy #$00 2 ldy #0
.SinIterate
c>2 {
; W0 *= W1
$0016 a2 03 ldx #$03 2 ldx #3
c>3 {
$0018 b5 e4 lda $e4,x 4 lda SinP.W0,x ; x^(1+2n)
$001a 95 f4 sta $f4,x 4 sta Mul824.A,x
$001c b5 e0 lda $e0,x 4 lda SinP.W1,x ; x^2
$001e 95 f0 sta $f0,x 4 sta Mul824.B,x
$0020 ca dex 2 dex
$0021 10 f5 bpl $0018 2+ bpl !
c<3 = 20 + 1 }
$0023 a9 e4 lda #$e4 2 lda #SinP.W0 ; Copy to W0
$0025 20 00 00 jsr $0000 6 jsr Multiply824S_Copy
$0028 a2 e4 ldx #$e4 2 ldx #SinP.W0 ; Copy W0 to A
$002a a9 f4 lda #$f4 2 lda #Mul824.A
$002c 20 00 00 jsr $0000 6 jsr Cpy824Z
$002f a2 00 ldx #$00 2 ldx #0
c>3 {
$0031 b9 00 00 lda $0000,y 4+ lda SinInvPermute,y
$0034 95 f0 sta $f0,x 4 sta Mul824.B,x
$0036 c8 iny 2 iny
$0037 e8 inx 2 inx
$0038 e0 04 cpx #$04 2 cpx #4
$003a d0 f5 bne $0031 2+ bne !
c<3 = 16 + 2 }
```
## <a name="expressions">Expression syntax
Expressions contain values, such as labels or raw numbers and operators including +, -, \*, /, & (and), | (or), ^ (eor), << (shift left), >> (shift right) similar to how expressions work in C. Parenthesis are supported for managing order of operations where C style precedence needs to be overridden. In addition there are some special characters supported:
@ -833,6 +891,7 @@ Fish food! Assembler has all important features and switching to make a 6502 pro
* irp (indefinite repeat)
**FIXED**
* Added section types, should cover most intuitive formats (seg.type; segment name; segment "name": type; etc. etc.)
* Changed the data for relocs to better match Apple II GS OMF format which also changes the object file format.
* Added a disassembler (disassembler/x65dsasm.s)
* % evaluates to the current end of scope instead of whatever scope ends first

View File

@ -42,6 +42,14 @@
//
//
enum SectionType : char {
ST_UNDEFINED, // not set
ST_CODE, // default type
ST_DATA, // data section (matters for GS/OS OMF)
ST_BSS, // uninitialized data section
ST_ZEROPAGE // ununitialized data section in zero page / direct page
};
struct ObjFileHeader {
short id; // 'x6'
short sections;
@ -69,7 +77,8 @@ struct ObjFileSection {
int output_size; // assembled binary size
int align_address;
short relocs;
short flags;
SectionType type;
char flags;
};
struct ObjFileReloc {
@ -161,6 +170,14 @@ static const char *reloc_type[] = {
static const char *late_type[] = {
"LABEL", "ABS_REF", "ABS_L_REF", "ABS_4_REF",
"BRANCH", "BRANCH_16", "BYTE" };
static const char *section_type[] = {
"UNDEFINED", // not set
"CODE", // default type
"DATA", // data section (matters for GS/OS OMF)
"BSS", // uninitialized data section
"ZEROPAGE" // ununitialized data section in zero page / direct page
};
static const int section_type_str = sizeof(section_type) / sizeof(section_type[0]);
void ReadObjectFile(const char *file, unsigned int show = SHOW_DEFAULT)
@ -187,28 +204,29 @@ void ReadObjectFile(const char *file, unsigned int show = SHOW_DEFAULT)
for (int si = 0; si < hdr.sections; si++) {
struct ObjFileSection &s = aSect[si];
short f = s.flags;
const char *tstr = s.type > 0 && s.type < section_type_str ? section_type[s.type] : "error";
if (f & (1 << ObjFileSection::OFS_MERGED)) {
printf("Section %d: " STRREF_FMT "(Merged)\n",
printf("Section %d: \"" STRREF_FMT "\": (Merged)\n",
reloc_idx, STRREF_ARG(PoolStr(s.name, str_orig)));
} else if (f & (1 << ObjFileSection::OFS_DUMMY)) {
if (f&(1 << ObjFileSection::OFS_FIXED)) {
printf("Section %d: " STRREF_FMT "(Dummy, fixed at $%04x)\n",
reloc_idx, STRREF_ARG(PoolStr(s.name, str_orig)), s.start_address);
printf("Section %d: \"" STRREF_FMT "\": (Dummy [%s], fixed at $%04x)\n",
reloc_idx, STRREF_ARG(PoolStr(s.name, str_orig)), tstr, s.start_address);
} else {
printf("Section %d: " STRREF_FMT "(Dummy, relative)\n",
reloc_idx, STRREF_ARG(PoolStr(s.name, str_orig)));
printf("Section %d: \"" STRREF_FMT "\": (Dummy [%s], relative)\n",
reloc_idx, STRREF_ARG(PoolStr(s.name, str_orig)), tstr);
}
} else {
if (f&(1 << ObjFileSection::OFS_FIXED)) {
printf("Section %d: " STRREF_FMT "(Fixed $%04x, $%x bytes)\n",
reloc_idx, STRREF_ARG(PoolStr(s.name, str_orig)), s.start_address, s.output_size);
printf("Section %d: \"" STRREF_FMT "\": (Fixed [%s] $%04x, $%x bytes)\n",
reloc_idx, STRREF_ARG(PoolStr(s.name, str_orig)), tstr, s.start_address, s.output_size);
} else {
printf("Section %d: " STRREF_FMT "(Relative, $%x bytes, align to $%x)\n",
reloc_idx, STRREF_ARG(PoolStr(s.name, str_orig)), s.output_size, s.align_address);
printf("Section %d: \"" STRREF_FMT "\": (Relative [%s], $%x bytes, align to $%x)\n",
reloc_idx, STRREF_ARG(PoolStr(s.name, str_orig)), tstr, s.output_size, s.align_address);
}
strref export_append = PoolStr(s.exp_app, str_orig);
if (export_append)
printf(" Export as: " STRREF_FMT "\n", STRREF_ARG(export_append));
printf(" Export as: \"" STRREF_FMT "\"\n", STRREF_ARG(export_append));
}
reloc_idx++;
}
@ -270,7 +288,7 @@ void ReadObjectFile(const char *file, unsigned int show = SHOW_DEFAULT)
}
if (show & SHOW_CODE_RANGE)
printf("Code block: $%x - $%x (%d bytes)\n", (size_t)code_start, size, size - hdr.bindata);
printf("Code block: $%x - $%x (%d bytes)\n", (int)code_start, (int)size, (int)(size - hdr.bindata));
// restore previous section
} else

66
x65.cpp
View File

@ -1125,6 +1125,14 @@ struct ListLine {
};
typedef std::vector<struct ListLine> Listing;
enum SectionType : char {
ST_UNDEFINED, // not set
ST_CODE, // default type
ST_DATA, // data section (matters for GS/OS OMF)
ST_BSS, // uninitialized data section
ST_ZEROPAGE // ununitialized data section in zero page / direct page
};
// start of data section support
// Default is a relative section
// Whenever org or dum with address is encountered => new section
@ -1155,10 +1163,11 @@ typedef struct Section {
bool address_assigned; // address is absolute if assigned
bool dummySection; // true if section does not generate data, only labels
SectionType type; // distinguishing section type for relocatable output
void reset() { // explicitly cleaning up sections, not called from Section destructor
name.clear(); export_append.clear();
start_address = address = load_address = 0x0;
start_address = address = load_address = 0x0; type = ST_CODE;
address_assigned = false; output = nullptr; curr = nullptr;
dummySection = false; output_capacity = 0; merged_offset = -1; merged_section = -1;
align_address = 1; if (pRelocs) delete pRelocs;
@ -1746,22 +1755,52 @@ void Asm::SetSection(strref name, int address)
current_section = &allSections[allSections.size()-1];
}
void Asm::SetSection(strref name)
void Asm::SetSection(strref line)
{
if (link_all_section)
LinkAllToSection();
if (allSections.size()==allSections.capacity())
allSections.reserve(allSections.size() + 16);
SectionType type = ST_UNDEFINED;
// SEG.U etc.
if (line.get_first() == '.') {
++line;
switch (strref::tolower(line.get_first())) {
case 'u': type = ST_BSS; break;
case 'z': type = ST_ZEROPAGE; break;
case 'd': type = ST_DATA; break;
case 'c': type = ST_CODE; break;
}
}
line.trim_whitespace();
int align = 1;
strref align_str = name.after(',');
align_str.trim_whitespace();
if (align_str.get_first()=='$') {
++align_str;
align = align_str.ahextoui();
} else
align = align_str.atoi();
Section newSection(name.before_or_full(','));
strref name;
while (strref arg = line.split_token_any_trim(",:")) {
if (arg.get_first() == '$') { ++arg; align = arg.ahextoui(); }
else if (arg.is_number()) align = arg.atoi();
else if (arg.get_first() == '"') name = (arg + 1).before_or_full('"');
else if (!name) name = arg;
else if (arg.same_str("code")) type = ST_CODE;
else if (arg.same_str("data")) type = ST_DATA;
else if (arg.same_str("bss")) type = ST_BSS;
else if (arg.same_str("zp") || arg.same_str("dp") ||
arg.same_str("zeropage") || arg.same_str("direct")) type = ST_ZEROPAGE;
}
if (type == ST_UNDEFINED) {
if (name.find("code") >= 0) type = ST_CODE;
else if (name.find("data") >= 0) type = ST_DATA;
else if (name.find("bss") >= 0) type = ST_BSS;
else if (name.find("zp") >= 0 || name.find("zeropage") >= 0 || name.find("direct") >= 0)
type = ST_ZEROPAGE;
else type = ST_CODE;
}
Section newSection(name);
newSection.align_address = align;
newSection.type = type;
allSections.push_back(newSection);
current_section = &allSections[allSections.size()-1];
}
@ -4049,7 +4088,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
return Directive_LOAD(line);
case AD_SECTION:
SetSection(line.get_trimmed_ws());
SetSection(line);
break;
case AD_LINK:
@ -5360,7 +5399,8 @@ struct ObjFileSection {
int output_size; // assembled binary size
int align_address;
short relocs;
short flags;
SectionType type;
char flags;
};
struct ObjFileReloc {
@ -5490,6 +5530,7 @@ StatusCode Asm::WriteObjectFile(strref filename)
s.align_address = si->align_address;
s.relocs = si->pRelocs ? (short)(si->pRelocs->size()) : 0;
s.start_address = si->start_address;
s.type = si->type;
s.flags =
(si->IsDummySection() ? (1 << ObjFileSection::OFS_DUMMY) : 0) |
(si->IsMergedSection() ? (1 << ObjFileSection::OFS_MERGED) : 0) |
@ -5659,6 +5700,7 @@ StatusCode Asm::ReadObjectFile(strref filename)
CurrSection().export_append = aSect[si].exp_app.offs>=0 ? strref(str_pool + aSect[si].name.offs) : strref();
CurrSection().align_address = aSect[si].align_address;
CurrSection().address = CurrSection().start_address + aSect[si].output_size;
CurrSection().type = aSect[si].type;
if (aSect[si].output_size) {
CurrSection().output = (unsigned char*)malloc(aSect[si].output_size);
memcpy(CurrSection().output, bin_data, aSect[si].output_size);