mirror of
https://github.com/ksherlock/x65.git
synced 2025-08-11 14:25:26 +00:00
Alias opcodes
- Added aliases to opcodes - Fixed XCode warnings - Revisited outdated comments - Fixed CPU / PROCESSOR keyword giving an error even if the argument was valid - Rearranged switch statements to be in a more logical order
This commit is contained in:
18
README.md
18
README.md
@@ -105,7 +105,7 @@ Would yield 3 bytes where the address of a label can be calculated by taking the
|
|||||||
|
|
||||||
### <a name="labels">Labels
|
### <a name="labels">Labels
|
||||||
|
|
||||||
Labels come in two flavors: **Addresses** (PC based) or **Values** (Evaluated from an expression). An address label is simply placed somewhere in code and a value label is follwed by '**=**' and an expression. All labels are rewritable so it is fine to do things like NumInstance = NumInstance+1. Value assignments can be prefixed with '.const' or '.label' but is not required to be prefixed by anything.
|
Labels come in two flavors: **Addresses** (PC based) or **Values** (Evaluated from an expression). An address label is simply placed somewhere in code and a value label is followed by '**=**' and an expression. All labels are rewritable so it is fine to do things like NumInstance = NumInstance+1. Value assignments can be prefixed with '.const' or '.label' but is not required to be prefixed by anything, the CONST keyword should cause an error if the label is modified in the same source file.
|
||||||
|
|
||||||
*Local labels* exist inbetween *global labels* and gets discarded whenever a new global label is added. The syntax for local labels are one of: prefix with period, at-sign, exclamation mark or suffix with $, as in: **.local** or **!local** or **@local** or **local$**. Both value labels and address labels can be local labels.
|
*Local labels* exist inbetween *global labels* and gets discarded whenever a new global label is added. The syntax for local labels are one of: prefix with period, at-sign, exclamation mark or suffix with $, as in: **.local** or **!local** or **@local** or **local$**. Both value labels and address labels can be local labels.
|
||||||
|
|
||||||
@@ -485,7 +485,7 @@ Adds a folder to search for INCLUDE, INCBIN, etc. files in
|
|||||||
|
|
||||||
The accumulator and index register mode will be reset to 8 bits if the CPU is switched to something other than 65816.
|
The accumulator and index register mode will be reset to 8 bits if the CPU is switched to something other than 65816.
|
||||||
|
|
||||||
An alternative method is to add .b/.w to immediat mode instructions that support 16 bit modes such as:
|
An alternative method is to add .b/.w to immediate mode instructions that support 16 bit modes such as:
|
||||||
|
|
||||||
```
|
```
|
||||||
ora.b #$21
|
ora.b #$21
|
||||||
@@ -586,15 +586,15 @@ SAV causes Merlin to save the result it has generated so far, which is somewhat
|
|||||||
|
|
||||||
## <a name="expressions">Expression syntax
|
## <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 overrided. In addition there are some special characters supported:
|
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:
|
||||||
|
|
||||||
* \*: Current address (PC). This conflicts with the use of \* as multiply so multiply will be interpreted only after a value or right parenthesis
|
* \*: Current address (PC). This conflicts with the use of \* as multiply so multiply will be interpreted only after a value or right parenthesis
|
||||||
* <: If less than is not follwed by another '<' in an expression this evaluates to the low byte of a value (and $ff)
|
* <: If less than is not followed by another '<' in an expression this evaluates to the low byte of a value (and $ff)
|
||||||
* >: If greater than is not followed by another '>' in an expression this evaluates to the high byte of a value (>>8)
|
* >: If greater than is not followed by another '>' in an expression this evaluates to the high byte of a value (>>8)
|
||||||
* ^: Inbetween two values '^' is an eor operation, as a prefix to values it extracts the bank byte (v>>24).
|
* ^: Inbetween two values '^' is an eor operation, as a prefix to values it extracts the bank byte (v>>24).
|
||||||
* !: Start of scope (use like an address label in expression)
|
* !: Start of scope (use like an address label in expression)
|
||||||
* %: First address after scope (use like an address label in expression)
|
* %: First address after scope (use like an address label in expression)
|
||||||
* $: Preceeds hexadecimal value
|
* $: Precedes hexadecimal value
|
||||||
* %: If immediately followed by '0' or '1' this is a binary value and not scope closure address
|
* %: If immediately followed by '0' or '1' this is a binary value and not scope closure address
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@@ -637,10 +637,10 @@ Alternative syntax for macros:
|
|||||||
To support the syntax of other assemblers macro parameters can also be defined through space separated arguments:
|
To support the syntax of other assemblers macro parameters can also be defined through space separated arguments:
|
||||||
|
|
||||||
```
|
```
|
||||||
macro loop_end op lbl {
|
macro loop_end op lbl {
|
||||||
op
|
op
|
||||||
bne lbl
|
bne lbl
|
||||||
}
|
}
|
||||||
|
|
||||||
ldx #4
|
ldx #4
|
||||||
{
|
{
|
||||||
|
300
x65.cpp
300
x65.cpp
@@ -458,9 +458,9 @@ struct mnem opcodes_6502[] = {
|
|||||||
{ "nop", AMM_NON, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea } }
|
{ "nop", AMM_NON, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea } }
|
||||||
};
|
};
|
||||||
|
|
||||||
char* aliases_6502[] = {
|
const char* aliases_6502[] = {
|
||||||
"bcc", "blt",
|
"bcc", "blt",
|
||||||
"bvs", "bge",
|
"bcs", "bge",
|
||||||
nullptr, nullptr
|
nullptr, nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -559,9 +559,9 @@ struct mnem opcodes_65C02[] = {
|
|||||||
{ "bbs7", AMC_BBR, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0xff } },
|
{ "bbs7", AMC_BBR, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0xff } },
|
||||||
};
|
};
|
||||||
|
|
||||||
char* aliases_65C02[] = {
|
const char* aliases_65C02[] = {
|
||||||
"bcc", "blt",
|
"bcc", "blt",
|
||||||
"bvs", "bge",
|
"bcs", "bge",
|
||||||
nullptr, nullptr
|
nullptr, nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -674,9 +674,9 @@ struct mnem opcodes_65816[] = {
|
|||||||
{ "xce", AMM_NON, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
{ "xce", AMM_NON, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
char* aliases_65816[] = {
|
const char* aliases_65816[] = {
|
||||||
"bcc", "blt",
|
"bcc", "blt",
|
||||||
"bvs", "bge",
|
"bcs", "bge",
|
||||||
"tcs", "tas",
|
"tcs", "tas",
|
||||||
"tsc", "tsa",
|
"tsc", "tsa",
|
||||||
"xba", "swa",
|
"xba", "swa",
|
||||||
@@ -685,7 +685,6 @@ char* aliases_65816[] = {
|
|||||||
nullptr, nullptr
|
nullptr, nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const int num_opcodes_65816 = sizeof(opcodes_65816) / sizeof(opcodes_65816[0]);
|
static const int num_opcodes_65816 = sizeof(opcodes_65816) / sizeof(opcodes_65816[0]);
|
||||||
|
|
||||||
|
|
||||||
@@ -721,8 +720,8 @@ enum CPUIndex {
|
|||||||
struct CPUDetails {
|
struct CPUDetails {
|
||||||
mnem *opcodes;
|
mnem *opcodes;
|
||||||
int num_opcodes;
|
int num_opcodes;
|
||||||
char* name;
|
const char* name;
|
||||||
char** aliases;
|
const char** aliases;
|
||||||
} aCPUs[] = {
|
} aCPUs[] = {
|
||||||
{ opcodes_6502, num_opcodes_6502, "6502", aliases_6502 },
|
{ opcodes_6502, num_opcodes_6502, "6502", aliases_6502 },
|
||||||
{ opcodes_65C02, num_opcodes_65C02-18, "65C02", aliases_65C02 },
|
{ opcodes_65C02, num_opcodes_65C02-18, "65C02", aliases_65C02 },
|
||||||
@@ -959,7 +958,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// relocs are cheaper than full expressions and work with
|
// relocs are cheaper than full expressions and work with
|
||||||
// local labels for relative sections which could otherwise
|
// local labels for relative sections which would otherwise
|
||||||
// be out of scope at link time.
|
// be out of scope at link time.
|
||||||
|
|
||||||
struct Reloc {
|
struct Reloc {
|
||||||
@@ -992,7 +991,7 @@ struct ListLine {
|
|||||||
typedef std::vector<struct ListLine> Listing;
|
typedef std::vector<struct ListLine> Listing;
|
||||||
|
|
||||||
// start of data section support
|
// start of data section support
|
||||||
// Default is a fixed address section at $1000
|
// Default is a relative section
|
||||||
// Whenever org or dum with address is encountered => new section
|
// Whenever org or dum with address is encountered => new section
|
||||||
// If org is fixed and < $200 then it is a dummy section Otherwise clear dummy section
|
// If org is fixed and < $200 then it is a dummy section Otherwise clear dummy section
|
||||||
typedef struct Section {
|
typedef struct Section {
|
||||||
@@ -1052,8 +1051,7 @@ typedef struct Section {
|
|||||||
void AddReloc(int base, int offset, int section, Reloc::Type type = Reloc::WORD);
|
void AddReloc(int base, int offset, int section, Reloc::Type type = Reloc::WORD);
|
||||||
|
|
||||||
Section() : pRelocs(nullptr), pListing(nullptr) { reset(); }
|
Section() : pRelocs(nullptr), pListing(nullptr) { reset(); }
|
||||||
Section(strref _name, int _address) : pRelocs(nullptr), pListing(nullptr)
|
Section(strref _name, int _address) : pRelocs(nullptr), pListing(nullptr) {
|
||||||
{
|
|
||||||
reset(); name = _name; start_address = load_address = address = _address;
|
reset(); name = _name; start_address = load_address = address = _address;
|
||||||
address_assigned = true;
|
address_assigned = true;
|
||||||
}
|
}
|
||||||
@@ -1063,7 +1061,7 @@ typedef struct Section {
|
|||||||
}
|
}
|
||||||
~Section() { }
|
~Section() { }
|
||||||
|
|
||||||
// Appending data to a section
|
// Append data to a section
|
||||||
void CheckOutputCapacity(unsigned int addSize);
|
void CheckOutputCapacity(unsigned int addSize);
|
||||||
void AddByte(int b);
|
void AddByte(int b);
|
||||||
void AddWord(int w);
|
void AddWord(int w);
|
||||||
@@ -1222,16 +1220,15 @@ public:
|
|||||||
pairArray<unsigned int, Macro> macros;
|
pairArray<unsigned int, Macro> macros;
|
||||||
pairArray<unsigned int, LabelPool> labelPools;
|
pairArray<unsigned int, LabelPool> labelPools;
|
||||||
pairArray<unsigned int, LabelStruct> labelStructs;
|
pairArray<unsigned int, LabelStruct> labelStructs;
|
||||||
// labels matching xdef names will be marked as external
|
pairArray<unsigned int, strref> xdefs; // labels matching xdef names will be marked as external
|
||||||
pairArray<unsigned int, strref> xdefs;
|
|
||||||
|
|
||||||
std::vector<LateEval> lateEval;
|
std::vector<LateEval> lateEval;
|
||||||
std::vector<LocalLabelRecord> localLabels;
|
std::vector<LocalLabelRecord> localLabels;
|
||||||
std::vector<char*> loadedData; // free when assembler is completed
|
std::vector<char*> loadedData; // free when assembler is completed
|
||||||
std::vector<MemberOffset> structMembers; // labelStructs refer to sets of structMembers
|
std::vector<MemberOffset> structMembers; // labelStructs refer to sets of structMembers
|
||||||
std::vector<strref> includePaths;
|
std::vector<strref> includePaths;
|
||||||
std::vector<Section> allSections;
|
std::vector<Section> allSections;
|
||||||
std::vector<ExtLabels> externals; // external labels organized by object file
|
std::vector<ExtLabels> externals; // external labels organized by object file
|
||||||
MapSymbolArray map;
|
MapSymbolArray map;
|
||||||
|
|
||||||
// CPU target
|
// CPU target
|
||||||
@@ -1279,7 +1276,7 @@ public:
|
|||||||
// Generate assembler listing if requested
|
// Generate assembler listing if requested
|
||||||
bool List(strref filename);
|
bool List(strref filename);
|
||||||
|
|
||||||
// Generate source for all valid instructions
|
// Generate source for all valid instructions and addressing modes for current CPU
|
||||||
bool AllOpcodes(strref filename);
|
bool AllOpcodes(strref filename);
|
||||||
|
|
||||||
// Clean up memory allocations, reset assembler state
|
// Clean up memory allocations, reset assembler state
|
||||||
@@ -1413,7 +1410,8 @@ void Asm::Cleanup() {
|
|||||||
for (std::vector<ExtLabels>::iterator exti = externals.begin(); exti !=externals.end(); ++exti)
|
for (std::vector<ExtLabels>::iterator exti = externals.begin(); exti !=externals.end(); ++exti)
|
||||||
exti->labels.clear();
|
exti->labels.clear();
|
||||||
externals.clear();
|
externals.clear();
|
||||||
SetSection(strref("default")); // this section is relocatable but is assigned address $1000 if exporting without directives
|
// this section is relocatable but is assigned address $1000 if exporting without directives
|
||||||
|
SetSection(strref("default"));
|
||||||
current_section = &allSections[0];
|
current_section = &allSections[0];
|
||||||
syntax = SYNTAX_SANE;
|
syntax = SYNTAX_SANE;
|
||||||
scope_depth = 0;
|
scope_depth = 0;
|
||||||
@@ -1434,7 +1432,7 @@ int sortHashLookup(const void *A, const void *B) {
|
|||||||
return _A->op_hash > _B->op_hash ? 1 : -1;
|
return _A->op_hash > _B->op_hash ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BuildInstructionTable(OPLookup *pInstr, int maxInstructions, struct mnem *opcodes, int count)
|
int BuildInstructionTable(OPLookup *pInstr, int maxInstructions, struct mnem *opcodes, int count, const char **aliases)
|
||||||
{
|
{
|
||||||
// create an instruction table (mnemonic hash lookup)
|
// create an instruction table (mnemonic hash lookup)
|
||||||
int numInstructions = 0;
|
int numInstructions = 0;
|
||||||
@@ -1445,6 +1443,23 @@ int BuildInstructionTable(OPLookup *pInstr, int maxInstructions, struct mnem *op
|
|||||||
op.type = OT_MNEMONIC;
|
op.type = OT_MNEMONIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add instruction aliases
|
||||||
|
if (aliases) {
|
||||||
|
while (*aliases) {
|
||||||
|
strref orig(*aliases++);
|
||||||
|
strref alias(*aliases++);
|
||||||
|
for (int o=0; o<count; o++) {
|
||||||
|
if (orig.same_str_case(opcodes[o].instr)) {
|
||||||
|
OPLookup &op = pInstr[numInstructions++];
|
||||||
|
op.op_hash = alias.fnv1a_lower();
|
||||||
|
op.index = o;
|
||||||
|
op.type = OT_MNEMONIC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// add assembler directives
|
// add assembler directives
|
||||||
for (int d = 0; d<nDirectiveNames; d++) {
|
for (int d = 0; d<nDirectiveNames; d++) {
|
||||||
OPLookup &op_hash = pInstr[numInstructions++];
|
OPLookup &op_hash = pInstr[numInstructions++];
|
||||||
@@ -1452,7 +1467,7 @@ int BuildInstructionTable(OPLookup *pInstr, int maxInstructions, struct mnem *op
|
|||||||
op_hash.index = (unsigned char)aDirectiveNames[d].directive;
|
op_hash.index = (unsigned char)aDirectiveNames[d].directive;
|
||||||
op_hash.type = OT_DIRECTIVE;
|
op_hash.type = OT_DIRECTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort table by hash for binary search lookup
|
// sort table by hash for binary search lookup
|
||||||
qsort(pInstr, numInstructions, sizeof(OPLookup), sortHashLookup);
|
qsort(pInstr, numInstructions, sizeof(OPLookup), sortHashLookup);
|
||||||
return numInstructions;
|
return numInstructions;
|
||||||
@@ -1465,7 +1480,7 @@ void Asm::SetCPU(CPUIndex CPU) {
|
|||||||
list_cpu = cpu;
|
list_cpu = cpu;
|
||||||
opcode_table = aCPUs[CPU].opcodes;
|
opcode_table = aCPUs[CPU].opcodes;
|
||||||
opcode_count = aCPUs[CPU].num_opcodes;
|
opcode_count = aCPUs[CPU].num_opcodes;
|
||||||
num_instructions = BuildInstructionTable(aInstructions, MAX_OPCODES_DIRECTIVES, opcode_table, opcode_count);
|
num_instructions = BuildInstructionTable(aInstructions, MAX_OPCODES_DIRECTIVES, opcode_table, opcode_count, aCPUs[CPU].aliases);
|
||||||
if (CPU != CPU_65816) {
|
if (CPU != CPU_65816) {
|
||||||
accumulator_16bit = false;
|
accumulator_16bit = false;
|
||||||
index_reg_16bit = false;
|
index_reg_16bit = false;
|
||||||
@@ -1477,8 +1492,8 @@ char* Asm::LoadText(strref filename, size_t &size) {
|
|||||||
strown<512> file(filename);
|
strown<512> file(filename);
|
||||||
std::vector<strref>::iterator i = includePaths.begin();
|
std::vector<strref>::iterator i = includePaths.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (FILE *f = fopen(file.c_str(), "rb")) {
|
if (FILE *f = fopen(file.c_str(), "rb")) { // rb is intended here since OS
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END); // eol conversion can do ugly things
|
||||||
size_t _size = ftell(f);
|
size_t _size = ftell(f);
|
||||||
fseek(f, 0, SEEK_SET);
|
fseek(f, 0, SEEK_SET);
|
||||||
if (char *buf = (char*)calloc(_size, 1)) {
|
if (char *buf = (char*)calloc(_size, 1)) {
|
||||||
@@ -1533,6 +1548,7 @@ char* Asm::LoadBinary(strref filename, size_t &size) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new section with a fixed address
|
||||||
void Asm::SetSection(strref name, int address)
|
void Asm::SetSection(strref name, int address)
|
||||||
{
|
{
|
||||||
if (name) {
|
if (name) {
|
||||||
@@ -1645,7 +1661,8 @@ unsigned char* Asm::BuildExport(strref append, int &file_size, int &addr)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
if (has_relative_section) {
|
if (has_relative_section) {
|
||||||
if (!has_fixed_section) {
|
if (!has_fixed_section) {
|
||||||
SetSection(strref(), 0x1000);
|
start_address = 0x1000;
|
||||||
|
SetSection(strref(), start_address);
|
||||||
CurrSection().export_append = append;
|
CurrSection().export_append = append;
|
||||||
last_fixed_section = SectionId();
|
last_fixed_section = SectionId();
|
||||||
}
|
}
|
||||||
@@ -1941,11 +1958,13 @@ void Asm::CheckOutputCapacity(unsigned int addSize) {
|
|||||||
// add a custom macro
|
// add a custom macro
|
||||||
StatusCode Asm::AddMacro(strref macro, strref source_name, strref source_file, strref &left)
|
StatusCode Asm::AddMacro(strref macro, strref source_name, strref source_file, strref &left)
|
||||||
{ //
|
{ //
|
||||||
// Non-merlin macro types:
|
// Recommended macro syntax:
|
||||||
// macro name(optional params) { actual macro }
|
// macro name(optional params) { actual macro }
|
||||||
|
//
|
||||||
|
// -endm option macro syntax:
|
||||||
// macro name arg\nactual macro\nendmacro
|
// macro name arg\nactual macro\nendmacro
|
||||||
//
|
//
|
||||||
// Merlin macro:
|
// Merlin macro syntax: (TODO: ignore arguments and use ]1, ]2, etc.)
|
||||||
// name mac arg1 arg2\nactual macro\n[<<<]/[EOM]
|
// name mac arg1 arg2\nactual macro\n[<<<]/[EOM]
|
||||||
//
|
//
|
||||||
strref name;
|
strref name;
|
||||||
@@ -2499,7 +2518,7 @@ StatusCode Asm::EvalExpression(strref expression, const struct EvalContext &etx,
|
|||||||
case EVOP_SUB: // -
|
case EVOP_SUB: // -
|
||||||
if (ri==1)
|
if (ri==1)
|
||||||
values[ri-1] = -values[ri-1];
|
values[ri-1] = -values[ri-1];
|
||||||
else {
|
else if (ri>1) {
|
||||||
ri--;
|
ri--;
|
||||||
for (int i = 0; i<num_sections; i++)
|
for (int i = 0; i<num_sections; i++)
|
||||||
section_counts[i][ri-1] -= section_counts[i][ri];
|
section_counts[i][ri-1] -= section_counts[i][ri];
|
||||||
@@ -2669,21 +2688,6 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
|
|||||||
}
|
}
|
||||||
bool resolved = true;
|
bool resolved = true;
|
||||||
switch (i->type) {
|
switch (i->type) {
|
||||||
case LateEval::LET_BRANCH:
|
|
||||||
value -= i->address+1;
|
|
||||||
if (value<-128 || value>127) {
|
|
||||||
i = lateEval.erase(i);
|
|
||||||
return ERROR_BRANCH_OUT_OF_RANGE;
|
|
||||||
} if (trg >= allSections[sec].size())
|
|
||||||
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
|
||||||
allSections[sec].SetByte(trg, value);
|
|
||||||
break;
|
|
||||||
case LateEval::LET_BRANCH_16:
|
|
||||||
value -= i->address+2;
|
|
||||||
if (trg >= allSections[sec].size())
|
|
||||||
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
|
||||||
allSections[sec].SetWord(trg, value);
|
|
||||||
break;
|
|
||||||
case LateEval::LET_BYTE:
|
case LateEval::LET_BYTE:
|
||||||
if (ret==STATUS_RELATIVE_SECTION) {
|
if (ret==STATUS_RELATIVE_SECTION) {
|
||||||
if (i->section<0)
|
if (i->section<0)
|
||||||
@@ -2698,6 +2702,7 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
|
|||||||
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
||||||
allSections[sec].SetByte(trg, value);
|
allSections[sec].SetByte(trg, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LateEval::LET_ABS_REF:
|
case LateEval::LET_ABS_REF:
|
||||||
if (ret==STATUS_RELATIVE_SECTION) {
|
if (ret==STATUS_RELATIVE_SECTION) {
|
||||||
if (i->section<0)
|
if (i->section<0)
|
||||||
@@ -2711,6 +2716,7 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
|
|||||||
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
||||||
allSections[sec].SetWord(trg, value);
|
allSections[sec].SetWord(trg, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LateEval::LET_ABS_L_REF:
|
case LateEval::LET_ABS_L_REF:
|
||||||
if (ret==STATUS_RELATIVE_SECTION) {
|
if (ret==STATUS_RELATIVE_SECTION) {
|
||||||
if (i->section<0)
|
if (i->section<0)
|
||||||
@@ -2724,6 +2730,24 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
|
|||||||
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
||||||
allSections[sec].SetTriple(trg, value);
|
allSections[sec].SetTriple(trg, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LateEval::LET_BRANCH:
|
||||||
|
value -= i->address+1;
|
||||||
|
if (value<-128 || value>127) {
|
||||||
|
i = lateEval.erase(i);
|
||||||
|
return ERROR_BRANCH_OUT_OF_RANGE;
|
||||||
|
} if (trg >= allSections[sec].size())
|
||||||
|
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
||||||
|
allSections[sec].SetByte(trg, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LateEval::LET_BRANCH_16:
|
||||||
|
value -= i->address+2;
|
||||||
|
if (trg >= allSections[sec].size())
|
||||||
|
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
|
||||||
|
allSections[sec].SetWord(trg, value);
|
||||||
|
break;
|
||||||
|
|
||||||
case LateEval::LET_LABEL: {
|
case LateEval::LET_LABEL: {
|
||||||
Label *label = GetLabel(i->label, i->file_ref);
|
Label *label = GetLabel(i->label, i->file_ref);
|
||||||
if (!label)
|
if (!label)
|
||||||
@@ -3300,6 +3324,7 @@ int LookupOpCodeIndex(unsigned int hash, OPLookup *lookup, int count)
|
|||||||
return -1; // index not found
|
return -1; // index not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encountered a REPT or LUP
|
||||||
StatusCode Asm::Directive_Rept(strref line, strref source_file)
|
StatusCode Asm::Directive_Rept(strref line, strref source_file)
|
||||||
{
|
{
|
||||||
SourceContext &ctx = contextStack.curr();
|
SourceContext &ctx = contextStack.curr();
|
||||||
@@ -3370,8 +3395,9 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
case AD_CPU:
|
case AD_CPU:
|
||||||
for (int c = 0; c < nCPUs; c++) {
|
for (int c = 0; c < nCPUs; c++) {
|
||||||
if (line.same_str(aCPUs[c].name)) {
|
if (line.same_str(aCPUs[c].name)) {
|
||||||
SetCPU((CPUIndex)c);
|
if (c != cpu)
|
||||||
break;
|
SetCPU((CPUIndex)c);
|
||||||
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ERROR_CPU_NOT_SUPPORTED;
|
return ERROR_CPU_NOT_SUPPORTED;
|
||||||
@@ -3616,7 +3642,6 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
SetCPU(CPU_65C02);
|
SetCPU(CPU_65C02);
|
||||||
break;
|
break;
|
||||||
case AD_TEXT: { // text: add text within quotes
|
case AD_TEXT: { // text: add text within quotes
|
||||||
// for now just copy the windows ascii. TODO: Convert to petscii.
|
|
||||||
// https://en.wikipedia.org/wiki/PETSCII
|
// https://en.wikipedia.org/wiki/PETSCII
|
||||||
// ascii: no change
|
// ascii: no change
|
||||||
// shifted: a-z => $41.. A-Z => $61..
|
// shifted: a-z => $41.. A-Z => $61..
|
||||||
@@ -3857,6 +3882,7 @@ StatusCode Asm::ApplyDirective(AssemblerDirective dir, strref line, strref sourc
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make an educated guess at the intended address mode from an opcode argument
|
||||||
StatusCode Asm::GetAddressMode(strref line, bool flipXY, AddrMode &addrMode, int &len, strref &expression)
|
StatusCode Asm::GetAddressMode(strref line, bool flipXY, AddrMode &addrMode, int &len, strref &expression)
|
||||||
{
|
{
|
||||||
bool force_zp = false;
|
bool force_zp = false;
|
||||||
@@ -3937,7 +3963,7 @@ StatusCode Asm::GetAddressMode(strref line, bool flipXY, AddrMode &addrMode, int
|
|||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push an opcode to the output buffer
|
// Push an opcode to the output buffer in the current section
|
||||||
StatusCode Asm::AddOpcode(strref line, int index, strref source_file)
|
StatusCode Asm::AddOpcode(strref line, int index, strref source_file)
|
||||||
{
|
{
|
||||||
StatusCode error = STATUS_OK;
|
StatusCode error = STATUS_OK;
|
||||||
@@ -4024,26 +4050,19 @@ StatusCode Asm::AddOpcode(strref line, int index, strref source_file)
|
|||||||
addrMode = AMB_ABS_L_X;
|
addrMode = AMB_ABS_L_X;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid_addressing_mode = !!(validModes & (1 << addrMode));
|
if (!(validModes & (1 << addrMode))) {
|
||||||
|
if (addrMode==AMB_ZP_REL_X && (validModes & AMM_REL_X))
|
||||||
if (!valid_addressing_mode) {
|
|
||||||
if (addrMode==AMB_ZP_REL_X && (validModes & AMM_REL_X)) {
|
|
||||||
addrMode = AMB_REL_X;
|
addrMode = AMB_REL_X;
|
||||||
valid_addressing_mode = true;
|
else if (addrMode==AMB_REL && (validModes & AMM_ZP_REL))
|
||||||
} else if (addrMode==AMB_REL && (validModes & AMM_ZP_REL)) {
|
|
||||||
addrMode = AMB_ZP_REL;
|
addrMode = AMB_ZP_REL;
|
||||||
valid_addressing_mode = true;
|
else if (addrMode==AMB_ABS && (validModes & AMM_ABS_L))
|
||||||
} else if (addrMode==AMB_ABS && (validModes & AMM_ABS_L)) {
|
|
||||||
addrMode = AMB_ABS_L;
|
addrMode = AMB_ABS_L;
|
||||||
valid_addressing_mode = true;
|
else if (addrMode==AMB_ABS_X && (validModes & AMM_ABS_L_X))
|
||||||
} else if (addrMode==AMB_ABS_X && (validModes & AMM_ABS_L_X)) {
|
|
||||||
addrMode = AMB_ABS_L_X;
|
addrMode = AMB_ABS_L_X;
|
||||||
valid_addressing_mode = true;
|
else if (addrMode==AMB_REL_L && (validModes & AMM_ZP_REL_L))
|
||||||
} else if (addrMode==AMB_REL_L && (validModes & AMM_ZP_REL_L)) {
|
|
||||||
addrMode = AMB_ZP_REL_L;
|
addrMode = AMB_ZP_REL_L;
|
||||||
valid_addressing_mode = true;
|
else
|
||||||
} else
|
return ERROR_INVALID_ADDRESSING_MODE;
|
||||||
error = ERROR_INVALID_ADDRESSING_MODE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the instruction and argument to the code
|
// Add the instruction and argument to the code
|
||||||
@@ -4085,10 +4104,6 @@ StatusCode Asm::AddOpcode(strref line, int index, strref source_file)
|
|||||||
codeArg = CA_THREE_BYTES;
|
codeArg = CA_THREE_BYTES;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AMB_ACC: // 9 A
|
|
||||||
case AMB_NON: // a
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AMB_ZP_ABS: // d $12, label
|
case AMB_ZP_ABS: // d $12, label
|
||||||
codeArg = CA_BYTE_BRANCH;
|
codeArg = CA_BYTE_BRANCH;
|
||||||
break;
|
break;
|
||||||
@@ -4106,10 +4121,77 @@ StatusCode Asm::AddOpcode(strref line, int index, strref source_file)
|
|||||||
else
|
else
|
||||||
codeArg = CA_ONE_BYTE;
|
codeArg = CA_ONE_BYTE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AMB_ACC: // 9 A
|
||||||
|
case AMB_NON: // a
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (codeArg) {
|
switch (codeArg) {
|
||||||
|
case CA_ONE_BYTE:
|
||||||
|
if (evalLater)
|
||||||
|
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
|
||||||
|
else if (error == STATUS_RELATIVE_SECTION)
|
||||||
|
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(), target_section,
|
||||||
|
target_section_type == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE);
|
||||||
|
AddByte(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CA_TWO_BYTES:
|
||||||
|
if (evalLater)
|
||||||
|
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_ABS_REF);
|
||||||
|
else if (error == STATUS_RELATIVE_SECTION) {
|
||||||
|
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(),
|
||||||
|
target_section, target_section_type);
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
AddWord(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CA_THREE_BYTES:
|
||||||
|
if (evalLater)
|
||||||
|
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_ABS_L_REF);
|
||||||
|
else if (error == STATUS_RELATIVE_SECTION) {
|
||||||
|
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(),
|
||||||
|
target_section, target_section_type);
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
AddTriple(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CA_TWO_ARG_BYTES: {
|
||||||
|
if (evalLater)
|
||||||
|
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
|
||||||
|
else if (error == STATUS_RELATIVE_SECTION) {
|
||||||
|
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(), target_section,
|
||||||
|
target_section_type == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE);
|
||||||
|
}
|
||||||
|
AddByte(value);
|
||||||
|
struct EvalContext etx(CurrSection().GetPC()-2, scope_address[scope_depth], -1, -1);
|
||||||
|
line.split_token_trim(',');
|
||||||
|
error = EvalExpression(line, etx, value);
|
||||||
|
if (error==STATUS_NOT_READY)
|
||||||
|
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], line, source_file, LateEval::LET_BYTE);
|
||||||
|
AddByte(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CA_BRANCH:
|
||||||
|
if (evalLater)
|
||||||
|
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BRANCH);
|
||||||
|
else if (((int)value - (int)CurrSection().GetPC()-1) < -128 || ((int)value - (int)CurrSection().GetPC()-1) > 127)
|
||||||
|
error = ERROR_BRANCH_OUT_OF_RANGE;
|
||||||
|
AddByte(evalLater ? 0 : (unsigned char)((int)value - (int)CurrSection().GetPC()) - 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CA_BRANCH_16:
|
||||||
|
if (evalLater)
|
||||||
|
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BRANCH_16);
|
||||||
|
AddWord(evalLater ? 0 : (value-(CurrSection().GetPC()+2)));
|
||||||
|
break;
|
||||||
|
|
||||||
case CA_BYTE_BRANCH: {
|
case CA_BYTE_BRANCH: {
|
||||||
if (evalLater)
|
if (evalLater)
|
||||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
|
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
|
||||||
@@ -4127,62 +4209,6 @@ StatusCode Asm::AddOpcode(strref line, int index, strref source_file)
|
|||||||
AddByte(error == STATUS_NOT_READY ? 0 : (unsigned char)((int)value - (int)CurrSection().GetPC()) - 1);
|
AddByte(error == STATUS_NOT_READY ? 0 : (unsigned char)((int)value - (int)CurrSection().GetPC()) - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CA_BRANCH:
|
|
||||||
if (evalLater)
|
|
||||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BRANCH);
|
|
||||||
else if (((int)value - (int)CurrSection().GetPC()-1) < -128 || ((int)value - (int)CurrSection().GetPC()-1) > 127)
|
|
||||||
error = ERROR_BRANCH_OUT_OF_RANGE;
|
|
||||||
AddByte(evalLater ? 0 : (unsigned char)((int)value - (int)CurrSection().GetPC()) - 1);
|
|
||||||
break;
|
|
||||||
case CA_BRANCH_16:
|
|
||||||
if (evalLater)
|
|
||||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BRANCH_16);
|
|
||||||
AddWord(evalLater ? 0 : (value-(CurrSection().GetPC()+2)));
|
|
||||||
break;
|
|
||||||
case CA_ONE_BYTE:
|
|
||||||
if (evalLater)
|
|
||||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
|
|
||||||
else if (error == STATUS_RELATIVE_SECTION)
|
|
||||||
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(), target_section,
|
|
||||||
target_section_type == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE);
|
|
||||||
AddByte(value);
|
|
||||||
break;
|
|
||||||
case CA_TWO_ARG_BYTES: {
|
|
||||||
if (evalLater)
|
|
||||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
|
|
||||||
else if (error == STATUS_RELATIVE_SECTION) {
|
|
||||||
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(), target_section,
|
|
||||||
target_section_type == Reloc::HI_BYTE ? Reloc::HI_BYTE : Reloc::LO_BYTE);
|
|
||||||
}
|
|
||||||
AddByte(value);
|
|
||||||
struct EvalContext etx(CurrSection().GetPC()-2, scope_address[scope_depth], -1, -1);
|
|
||||||
line.split_token_trim(',');
|
|
||||||
error = EvalExpression(line, etx, value);
|
|
||||||
if (error==STATUS_NOT_READY)
|
|
||||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], line, source_file, LateEval::LET_BYTE);
|
|
||||||
AddByte(value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CA_TWO_BYTES:
|
|
||||||
if (evalLater)
|
|
||||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_ABS_REF);
|
|
||||||
else if (error == STATUS_RELATIVE_SECTION) {
|
|
||||||
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(),
|
|
||||||
target_section, target_section_type);
|
|
||||||
value = 0;
|
|
||||||
}
|
|
||||||
AddWord(value);
|
|
||||||
break;
|
|
||||||
case CA_THREE_BYTES:
|
|
||||||
if (evalLater)
|
|
||||||
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_ABS_L_REF);
|
|
||||||
else if (error == STATUS_RELATIVE_SECTION) {
|
|
||||||
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(),
|
|
||||||
target_section, target_section_type);
|
|
||||||
value = 0;
|
|
||||||
}
|
|
||||||
AddTriple(value);
|
|
||||||
break;
|
|
||||||
case CA_NONE:
|
case CA_NONE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4583,7 +4609,7 @@ bool Asm::AllOpcodes(strref filename)
|
|||||||
// create an instruction table (mnemonic hash lookup + directives)
|
// create an instruction table (mnemonic hash lookup + directives)
|
||||||
void Asm::Assemble(strref source, strref filename, bool obj_target)
|
void Asm::Assemble(strref source, strref filename, bool obj_target)
|
||||||
{
|
{
|
||||||
num_instructions = BuildInstructionTable(aInstructions, MAX_OPCODES_DIRECTIVES, opcode_table, opcode_count);
|
SetCPU(cpu);
|
||||||
|
|
||||||
StatusCode error = STATUS_OK;
|
StatusCode error = STATUS_OK;
|
||||||
contextStack.push(filename, source, source);
|
contextStack.push(filename, source, source);
|
||||||
@@ -4710,25 +4736,29 @@ static int _AddStrPool(const strref str, pairArray<unsigned int, int> *pLookup,
|
|||||||
if (index<pLookup->count() && str.same_str_case(*strPool + pLookup->getValue(index)))
|
if (index<pLookup->count() && str.same_str_case(*strPool + pLookup->getValue(index)))
|
||||||
return pLookup->getValue(index);
|
return pLookup->getValue(index);
|
||||||
|
|
||||||
if ((strPoolSize + str.get_len() + 1) > strPoolCap) {
|
int strOffs = strPoolSize;
|
||||||
|
if ((strOffs + str.get_len() + 1) > strPoolCap) {
|
||||||
strPoolCap += 4096;
|
strPoolCap += 4096;
|
||||||
char *strPoolGrow = (char*)malloc(strPoolCap);
|
char *strPoolGrow = (char*)malloc(strPoolCap);
|
||||||
if (*strPool && strPoolGrow) {
|
if (strPoolGrow) {
|
||||||
memcpy(strPoolGrow, *strPool, strPoolSize);
|
if (*strPool) {
|
||||||
free(*strPool);
|
memcpy(strPoolGrow, *strPool, strPoolSize);
|
||||||
}
|
free(*strPool);
|
||||||
*strPool = strPoolGrow;
|
}
|
||||||
|
*strPool = strPoolGrow;
|
||||||
|
} else
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
int ret = strPoolSize;
|
|
||||||
if (*strPool) {
|
if (*strPool) {
|
||||||
char *dest = *strPool + strPoolSize;
|
char *dest = *strPool + strPoolSize;
|
||||||
memcpy(dest, str.get(), str.get_len());
|
memcpy(dest, str.get(), str.get_len());
|
||||||
dest[str.get_len()] = 0;
|
dest[str.get_len()] = 0;
|
||||||
strPoolSize += str.get_len()+1;
|
strPoolSize += str.get_len()+1;
|
||||||
pLookup->insert(index, hash);
|
pLookup->insert(index, hash);
|
||||||
pLookup->getValues()[index] = ret;
|
pLookup->getValues()[index] = strOffs;
|
||||||
}
|
}
|
||||||
return ret;
|
return strOffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusCode Asm::WriteObjectFile(strref filename)
|
StatusCode Asm::WriteObjectFile(strref filename)
|
||||||
@@ -5115,7 +5145,7 @@ int main(int argc, char **argv)
|
|||||||
" x65 filename.s code.prg [options]\n"
|
" x65 filename.s code.prg [options]\n"
|
||||||
" * -i(path) : Add include path\n"
|
" * -i(path) : Add include path\n"
|
||||||
" * -D(label)[=<value>] : Define a label with an optional value(otherwise defined as 1)\n"
|
" * -D(label)[=<value>] : Define a label with an optional value(otherwise defined as 1)\n"
|
||||||
" * -cpu=6502/65c02: assemble with opcodes for a different cpu\n"
|
" * -cpu=6502/65c02/65c02wdc/65816: assemble with opcodes for a different cpu\n"
|
||||||
" * -obj(file.x65) : generate object file for later linking\n"
|
" * -obj(file.x65) : generate object file for later linking\n"
|
||||||
" * -bin : Raw binary\n"
|
" * -bin : Raw binary\n"
|
||||||
" * -c64 : Include load address(default)\n"
|
" * -c64 : Include load address(default)\n"
|
||||||
@@ -5125,7 +5155,7 @@ int main(int argc, char **argv)
|
|||||||
" * -opcodes / -opcodes = (file.s) : dump all available opcodes(file or stdout)\n"
|
" * -opcodes / -opcodes = (file.s) : dump all available opcodes(file or stdout)\n"
|
||||||
" * -sect: display sections loaded and built\n"
|
" * -sect: display sections loaded and built\n"
|
||||||
" * -vice(file.vs) : export a vice symbol file\n"
|
" * -vice(file.vs) : export a vice symbol file\n"
|
||||||
" * -nerlin: use Merlin syntax\n"
|
" * -merlin: use Merlin syntax\n"
|
||||||
" * -endm : macros end with endm or endmacro instead of scoped('{' - '}')\n");
|
" * -endm : macros end with endm or endmacro instead of scoped('{' - '}')\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user