mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-06-15 12:29:32 +00:00
adjusted docs (added !WHILE, ELSE IF, etc)
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@251 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
7f736ceccb
commit
1261960cad
|
@ -7,12 +7,12 @@
|
||||||
--- addressing modes ---
|
--- addressing modes ---
|
||||||
|
|
||||||
|
|
||||||
If a command can be used with different addressing modes, ACME has to
|
If an instruction can be used with different addressing modes, ACME
|
||||||
decide which one to use. Several commands of the 6502 CPU can be used
|
has to decide which one to use. Several instructions of the 6502 CPU
|
||||||
with either "absolute" addressing or "zeropage-absolute" addressing.
|
can be used with either "absolute" addressing or "zeropage-absolute"
|
||||||
The former one means there's a 16-bit argument, the latter one means
|
addressing. The former one means there's a 16-bit argument, the latter
|
||||||
there's an 8-bit argument.
|
one means there's an 8-bit argument.
|
||||||
And the 65816 CPU even knows some commands with 24-bit addressing...
|
And the 65816 CPU even has some instructions with 24-bit addressing...
|
||||||
|
|
||||||
So how does ACME know which addressing mode to use?
|
So how does ACME know which addressing mode to use?
|
||||||
The simple approach is to always use the smallest possible argument,
|
The simple approach is to always use the smallest possible argument,
|
||||||
|
@ -29,11 +29,10 @@ The two exceptions are:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*** 1) Symbols are defined too late
|
*** 1) Symbols are defined too late
|
||||||
|
|
||||||
If ACME cannot figure out the argument value in the first pass, it
|
If ACME cannot figure out the argument value in the first pass, it
|
||||||
assumes that the command uses 16-bit addressing.
|
assumes that the instruction uses 16-bit addressing.
|
||||||
|
|
||||||
If it later finds out that the argument only needs 8 bits, ACME gives
|
If it later finds out that the argument only needs 8 bits, ACME gives
|
||||||
a warning ("using oversized addressing mode") and continues. However,
|
a warning ("using oversized addressing mode") and continues. However,
|
||||||
|
@ -43,8 +42,7 @@ These problems can be solved by defining the symbols *before* using
|
||||||
them, so that the value can be figured out in the first pass. If this
|
them, so that the value can be figured out in the first pass. If this
|
||||||
is not possible, you can use the postfix method, effectively exactly
|
is not possible, you can use the postfix method, effectively exactly
|
||||||
defining what addressing mode to use. The postfix method is described
|
defining what addressing mode to use. The postfix method is described
|
||||||
in a separate paragraph below.
|
in a separate section below.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,8 +87,7 @@ This feature can be disabled using the "--ignore-zeroes" CLI switch.
|
||||||
|
|
||||||
|
|
||||||
The other possibility is to use the postfix method (described in the
|
The other possibility is to use the postfix method (described in the
|
||||||
next paragraph).
|
next section).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,7 +129,7 @@ will be assembled to
|
||||||
8c fd 00 ; sty $00fd
|
8c fd 00 ; sty $00fd
|
||||||
8f ff 00 00 ; sta $0000ff
|
8f ff 00 00 ; sta $0000ff
|
||||||
|
|
||||||
Postfixes given directly after the command have higher priority than
|
Postfixes added directly to the mnemonic have higher priority than
|
||||||
those given to the argument. As you can see, you can add the postfix
|
those given to the argument. As you can see, you can add the postfix
|
||||||
to the symbol definition as well (equivalent to leading zeros).
|
to the symbol definition as well (equivalent to leading zeros).
|
||||||
|
|
||||||
|
@ -141,8 +138,7 @@ gives the high byte and "^" gives the bank byte of a value) to any
|
||||||
value will clear the argument's Force Bits 2 and 3 and set Force
|
value will clear the argument's Force Bits 2 and 3 and set Force
|
||||||
Bit 1 instead. So "lda <symbol" will use 8-bit addressing, regardless
|
Bit 1 instead. So "lda <symbol" will use 8-bit addressing, regardless
|
||||||
of the symbol's Force Bits. Of course, you can change this by
|
of the symbol's Force Bits. Of course, you can change this by
|
||||||
postfixing the command again... :)
|
postfixing the instruction again... :)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,7 +148,7 @@ You don't need to read this paragraph just to use ACME, I only
|
||||||
included it for completeness' sake. This is a description of ACME's
|
included it for completeness' sake. This is a description of ACME's
|
||||||
strategy for finding the addressing mode to use:
|
strategy for finding the addressing mode to use:
|
||||||
|
|
||||||
First, ACME checks whether the command has any postfix. If it has,
|
First, ACME checks whether the instruction has any postfix. If it has,
|
||||||
ACME acts upon it. So postfixes have the highest priority.
|
ACME acts upon it. So postfixes have the highest priority.
|
||||||
|
|
||||||
Otherwise, ACME checks whether the argument has any Force Bits set
|
Otherwise, ACME checks whether the argument has any Force Bits set
|
||||||
|
|
201
docs/AllPOs.txt
201
docs/AllPOs.txt
|
@ -29,8 +29,9 @@ Examples: !08 127, symbol, -128 ; output some values
|
||||||
Call: !16 EXPRESSION [, EXPRESSION]*
|
Call: !16 EXPRESSION [, EXPRESSION]*
|
||||||
Purpose: Insert 16-bit values in chosen CPU's byte order.
|
Purpose: Insert 16-bit values in chosen CPU's byte order.
|
||||||
Parameters: EXPRESSION: Any formula the value parser accepts.
|
Parameters: EXPRESSION: Any formula the value parser accepts.
|
||||||
Aliases: "!wo", "!word" (and because all currently supported CPUs are
|
Aliases: "!wo", "!word" (and because all currently supported
|
||||||
little-endian, "!le16" is in fact another alias)
|
CPUs are little-endian, "!le16" is in fact another
|
||||||
|
alias)
|
||||||
Examples: !16 65535, symbol, -32768 ; output some values
|
Examples: !16 65535, symbol, -32768 ; output some values
|
||||||
!wo 14, $4f35, %100101010010110, &36304, *, 'c'
|
!wo 14, $4f35, %100101010010110, &36304, *, 'c'
|
||||||
!word 3000 - 4, a1 AND a2, 2 ^ tz, (3+4)*70, l1 & .j2
|
!word 3000 - 4, a1 AND a2, 2 ^ tz, (3+4)*70, l1 & .j2
|
||||||
|
@ -108,12 +109,12 @@ Examples: !be32 $7fffffff, symbol, -$80000000, 14, $46a4f35
|
||||||
|
|
||||||
|
|
||||||
Call: !hex PAIRS_OF_HEX_DIGITS
|
Call: !hex PAIRS_OF_HEX_DIGITS
|
||||||
Purpose: Insert byte values with a minimum of additional syntax.
|
Purpose: Insert byte values with a minimum of additional
|
||||||
This pseudo opcode was added for easier writing of external
|
syntax. This pseudo opcode was added for easier
|
||||||
source code generator tools.
|
writing of external source code generator tools.
|
||||||
Parameters: PAIRS_OF_HEX_DIGITS: Just hexadecimal digits, without any
|
Parameters: PAIRS_OF_HEX_DIGITS: Just hexadecimal digits, without
|
||||||
"0x" or "$" prefix. Spaces and TABs are allowed, but not
|
any "0x" or "$" prefix. Spaces and TABs are allowed,
|
||||||
needed to separate the byte values.
|
but not needed to separate the byte values.
|
||||||
Aliases: "!h"
|
Aliases: "!h"
|
||||||
Examples: !h f0 f1 f2 f3 f4 f5 f6 f7 ; insert values 0xf0..0xf7
|
Examples: !h f0 f1 f2 f3 f4 f5 f6 f7 ; insert values 0xf0..0xf7
|
||||||
!h f0f1f2f3 f4f5f6f7 ; insert values 0xf0..0xf7
|
!h f0f1f2f3 f4f5f6f7 ; insert values 0xf0..0xf7
|
||||||
|
@ -136,10 +137,12 @@ Examples: !fi 256, $ff ; reserve 256 bytes
|
||||||
|
|
||||||
|
|
||||||
Call: !skip AMOUNT
|
Call: !skip AMOUNT
|
||||||
Purpose: Advance in output buffer without starting a new segment.
|
Purpose: Advance in output buffer without starting a new
|
||||||
|
segment.
|
||||||
Parameters: AMOUNT: Any formula the value parser accepts, but it
|
Parameters: AMOUNT: Any formula the value parser accepts, but it
|
||||||
must be solvable even in the first pass (this limitation
|
must be solvable even in the first pass (this
|
||||||
will hopefully be lifted in a future release).
|
limitation will hopefully be lifted in a future
|
||||||
|
release).
|
||||||
Aliases: None
|
Aliases: None
|
||||||
Examples: !skip BUFSIZE ; reserve some bytes
|
Examples: !skip BUFSIZE ; reserve some bytes
|
||||||
!skip 5 ; reserve five bytes
|
!skip 5 ; reserve five bytes
|
||||||
|
@ -155,7 +158,7 @@ Parameters: ANDVALUE: Any formula the value parser accepts, but it
|
||||||
it must be solvable even in the first pass.
|
it must be solvable even in the first pass.
|
||||||
FILLVALUE: Any formula the value parser accepts. If it
|
FILLVALUE: Any formula the value parser accepts. If it
|
||||||
is omitted, a default value is used (currently 234,
|
is omitted, a default value is used (currently 234,
|
||||||
that's the 6502 CPU's NOP command).
|
that's the opcode of the 6502 CPU's NOP instruction).
|
||||||
Examples: !align 255, 0 ; align to page (256 bytes)
|
Examples: !align 255, 0 ; align to page (256 bytes)
|
||||||
!align 63, 0 ; align to C64 sprite block (64 bytes)
|
!align 63, 0 ; align to C64 sprite block (64 bytes)
|
||||||
|
|
||||||
|
@ -378,22 +381,24 @@ Section: Flow control
|
||||||
|
|
||||||
Call: !if CONDITION { BLOCK } [ else { BLOCK } ]
|
Call: !if CONDITION { BLOCK } [ else { BLOCK } ]
|
||||||
Purpose: Conditional assembly. If the given condition is true,
|
Purpose: Conditional assembly. If the given condition is true,
|
||||||
the first block of statements will be parsed;
|
the matching block of statements will be parsed;
|
||||||
if it isn't, the second block will be parsed instead
|
if no condition is true, the ELSE block (if present)
|
||||||
(if present).
|
will be parsed.
|
||||||
Parameters: CONDITION: Any formula the value parser accepts, but
|
Parameters: CONDITION: Any formula the value parser accepts, but
|
||||||
it must be solvable even in the first pass.
|
it must be solvable even in the first pass.
|
||||||
BLOCK: A block of assembler statements.
|
BLOCK: A block of assembler statements.
|
||||||
Examples: !text "Black", 0 ; Choose wording according to
|
Examples: ; Choose word according to "country" symbol:
|
||||||
!if country = uk { ; content of "country" symbol.
|
!if country = uk {
|
||||||
!text "Grey"
|
!text "Grey"
|
||||||
|
} else if country = fr {
|
||||||
|
!text "Gris"
|
||||||
|
} else if country = de {
|
||||||
|
!text "Grau"
|
||||||
} else {
|
} else {
|
||||||
!text "Gray"
|
!text "Gray"
|
||||||
}
|
}
|
||||||
!byte 0
|
|
||||||
!text "White", 0
|
|
||||||
|
|
||||||
; Insert debug commands if symbol "debug" is not zero:
|
; Insert debug code depending on symbol "debug":
|
||||||
!if debug { lda #'z':jsr char_output }
|
!if debug { lda #'z':jsr char_output }
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,12 +442,26 @@ Examples: ; this was taken from <6502/std.a>:
|
||||||
; further instances will be skipped.
|
; further instances will be skipped.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; include at most one driver source code:
|
||||||
|
!ifdef RAM_REU {
|
||||||
|
!src "driver_reu.a"
|
||||||
|
} else ifdef RAM_GEORAM {
|
||||||
|
!src "driver_georam.a"
|
||||||
|
} else ifdef RAM_VDCRAM {
|
||||||
|
!src "driver_vdcram.a"
|
||||||
|
} else ifdef RAM_SUPERRAM {
|
||||||
|
!src "driver_superram.a"
|
||||||
|
} else {
|
||||||
|
!src "driver_noram.a"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Call: !for SYMBOL, START, END { BLOCK }
|
Call: !for SYMBOL, START, END { BLOCK }
|
||||||
Purpose: Looping assembly. The block of statements will be
|
Purpose: Looping assembly. The block of statements will be
|
||||||
parsed a fixed number of times, as specified by the
|
parsed a fixed number of times, as specified by the
|
||||||
values of START and END. For a more flexible
|
values of START and END. For more flexible
|
||||||
possibility, have a look at "!do" below.
|
possibilities, have a look at "!do" and "!while"
|
||||||
|
below.
|
||||||
Parameters: SYMBOL: Any valid symbol name.
|
Parameters: SYMBOL: Any valid symbol name.
|
||||||
START: Any formula the value parser accepts, but it
|
START: Any formula the value parser accepts, but it
|
||||||
must be solvable even in the first pass. SYMBOL will
|
must be solvable even in the first pass. SYMBOL will
|
||||||
|
@ -492,12 +511,13 @@ Examples:
|
||||||
Miscellaneous: The old syntax ("!for SYMBOL, END { BLOCK }" where
|
Miscellaneous: The old syntax ("!for SYMBOL, END { BLOCK }" where
|
||||||
START was always implied to be 1) is still fully
|
START was always implied to be 1) is still fully
|
||||||
supported, but gives a warning to get people to change
|
supported, but gives a warning to get people to change
|
||||||
to the new syntax. You can disable this warning using
|
to the new syntax.
|
||||||
the "-Wno-old-for" switch, but then you will get
|
You can disable this warning using the "--dialect" or
|
||||||
|
the "-Wno-old-for" switches, but then you will get
|
||||||
warnings for using the *new* syntax.
|
warnings for using the *new* syntax.
|
||||||
When migrating your sources, bear in mind that it is
|
When migrating your sources to the current syntax,
|
||||||
no longer possible to skip the block completely by
|
bear in mind that it is no longer possible to skip the
|
||||||
specifying a loop count of zero.
|
block completely by specifying a loop count of zero.
|
||||||
Also note that with the new algorithm, SYMBOL has a
|
Also note that with the new algorithm, SYMBOL has a
|
||||||
different value after the block than during the last
|
different value after the block than during the last
|
||||||
loop cycle, while the old algorithm kept that last
|
loop cycle, while the old algorithm kept that last
|
||||||
|
@ -507,9 +527,9 @@ Miscellaneous: The old syntax ("!for SYMBOL, END { BLOCK }" where
|
||||||
Call: !set SYMBOL = VALUE
|
Call: !set SYMBOL = VALUE
|
||||||
Purpose: Assign given value to symbol even if the symbol
|
Purpose: Assign given value to symbol even if the symbol
|
||||||
already has a different value. Needed for loop
|
already has a different value. Needed for loop
|
||||||
counters when using "!do", for example. Only use this
|
counters when using "!do"or "!while", for example.
|
||||||
opcode for something else if you're sure you *really*
|
Only use this opcode for something else if you're sure
|
||||||
know what you are doing... :)
|
you *really* know what you are doing... :)
|
||||||
Parameters: SYMBOL: Any valid symbol name.
|
Parameters: SYMBOL: Any valid symbol name.
|
||||||
VALUE: Any formula the value parser accepts.
|
VALUE: Any formula the value parser accepts.
|
||||||
Example: see "!do" below
|
Example: see "!do" below
|
||||||
|
@ -549,6 +569,34 @@ Examples: ; a loop with conditions at both start and end
|
||||||
!do until 3 = 4 { } while 3 < 4
|
!do until 3 = 4 { } while 3 < 4
|
||||||
|
|
||||||
|
|
||||||
|
Call: !while [CONDITION] { BLOCK }
|
||||||
|
Purpose: Looping assembly. The block of statements can be
|
||||||
|
parsed several times, depending on the given
|
||||||
|
condition.
|
||||||
|
The condition is parsed in every repetition before the
|
||||||
|
actual block. If it isn't met when first checked, the
|
||||||
|
block will be skipped.
|
||||||
|
Parameters: CONDITION: Any formula the value parser accepts, but
|
||||||
|
it must be solvable even in the first pass.
|
||||||
|
BLOCK: A block of assembler statements.
|
||||||
|
Examples: ; a loop with a counter
|
||||||
|
!set a = 0 ; init loop counter
|
||||||
|
!while a < 6 {
|
||||||
|
lda #a
|
||||||
|
sta label + a
|
||||||
|
!set a = a + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
; a loop depending on program counter
|
||||||
|
!while * < $c000 { nop }
|
||||||
|
|
||||||
|
; a never ending loop - this will cause an error
|
||||||
|
!while 3 < 4 { nop }
|
||||||
|
|
||||||
|
; an empty loop - this will hang ACME
|
||||||
|
!while 3 != 4 { }
|
||||||
|
|
||||||
|
|
||||||
Call: !endoffile
|
Call: !endoffile
|
||||||
Purpose: Stop processing the current source file. Using this
|
Purpose: Stop processing the current source file. Using this
|
||||||
pseudo opcode you can add explanatory text inside your
|
pseudo opcode you can add explanatory text inside your
|
||||||
|
@ -563,22 +611,24 @@ Example: rts ; some assembler mnemonic
|
||||||
"!eof" is reached.
|
"!eof" is reached.
|
||||||
|
|
||||||
|
|
||||||
Call: !warn STRING_VALUE [, STRING_VALUE]*
|
Call: !warn VALUE [, VALUE]*
|
||||||
Purpose: Show a warning during assembly.
|
Purpose: Show a warning during assembly.
|
||||||
Parameters: STRING_VALUE: Can be either a string given in double
|
Parameters: VALUE: Can be either a string given in double quotes
|
||||||
quotes or any formula the value parser accepts.
|
or any formula the value parser accepts.
|
||||||
Numbers will be output in decimal _and_ hex format.
|
Integer numbers will be output in both decimal _and_
|
||||||
|
hex formats.
|
||||||
Example: !if * > $a000 {
|
Example: !if * > $a000 {
|
||||||
!warn "Program reached ROM: ", * - $a000, " bytes overlap."
|
!warn "Program reached ROM: ", * - $a000, " bytes overlap."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Call: !error STRING_VALUE [, STRING_VALUE]*
|
Call: !error VALUE [, VALUE]*
|
||||||
Purpose: Generate an error during assembly (therefore, no
|
Purpose: Generate an error during assembly (therefore, no
|
||||||
output file will be generated).
|
output file will be generated).
|
||||||
Parameters: STRING_VALUE: Can be either a string given in double
|
Parameters: VALUE: Can be either a string given in double quotes
|
||||||
quotes or any formula the value parser accepts.
|
or any formula the value parser accepts.
|
||||||
Numbers will be output in decimal _and_ hex format.
|
Integer numbers will be output in both decimal _and_
|
||||||
|
hex formats.
|
||||||
Example: rts ; end of some function
|
Example: rts ; end of some function
|
||||||
start !source "colors.a"
|
start !source "colors.a"
|
||||||
end !if end - start > 256 {
|
end !if end - start > 256 {
|
||||||
|
@ -586,12 +636,13 @@ Example: rts ; end of some function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Call: !serious STRING_VALUE [, STRING_VALUE]*
|
Call: !serious VALUE [, VALUE]*
|
||||||
Purpose: Generate a serious error, immediately stopping
|
Purpose: Generate a serious error, immediately stopping
|
||||||
assembly.
|
assembly.
|
||||||
Parameters: STRING_VALUE: Can be either a string given in double
|
Parameters: VALUE: Can be either a string given in double quotes
|
||||||
quotes or any formula the value parser accepts.
|
or any formula the value parser accepts.
|
||||||
Numbers will be output in decimal _and_ hex format.
|
Integer numbers will be output in both decimal _and_
|
||||||
|
hex formats.
|
||||||
Example: !source "part1.a" ; sets part1_version
|
Example: !source "part1.a" ; sets part1_version
|
||||||
!source "part2.a" ; sets part2_version
|
!source "part2.a" ; sets part2_version
|
||||||
!if part1_version != part2_version {
|
!if part1_version != part2_version {
|
||||||
|
@ -611,9 +662,9 @@ Parameters: TITLE: The macro's desired name (same rules as for
|
||||||
could want this is beyond me).
|
could want this is beyond me).
|
||||||
SYMBOL: The desired name for the parameter value at
|
SYMBOL: The desired name for the parameter value at
|
||||||
call time. Normally, these parameter symbols should be
|
call time. Normally, these parameter symbols should be
|
||||||
local (first character a dot), as different macro
|
local (first character a '.' or a '@'), as different
|
||||||
calls will almost for sure have different parameter
|
macro calls will almost for sure have different
|
||||||
values.
|
parameter values.
|
||||||
If you prefix SYMBOL with a '~' character, it will be
|
If you prefix SYMBOL with a '~' character, it will be
|
||||||
called by reference, not by value: Changing the value
|
called by reference, not by value: Changing the value
|
||||||
inside the macro will result in the "outer" symbol to
|
inside the macro will result in the "outer" symbol to
|
||||||
|
@ -740,8 +791,10 @@ Purpose: Set program counter to given value and start new
|
||||||
issued. Because some people do this overlapping
|
issued. Because some people do this overlapping
|
||||||
on purpose, the warnings can be suppressed using
|
on purpose, the warnings can be suppressed using
|
||||||
modifier keywords.
|
modifier keywords.
|
||||||
Future versions of ACME may issue errors instead of
|
Using the "--strict-segments" CLI switch, these
|
||||||
warnings.
|
warnings can be turned onto errors. Future versions of
|
||||||
|
ACME may do that by default - so if needed, use the
|
||||||
|
modifier keywords.
|
||||||
Parameters: EXPRESSION: Any formula the value parser accepts, but
|
Parameters: EXPRESSION: Any formula the value parser accepts, but
|
||||||
it must be solvable even in the first pass.
|
it must be solvable even in the first pass.
|
||||||
MODIFIER: "overlay" or "invisible" (without quotes):
|
MODIFIER: "overlay" or "invisible" (without quotes):
|
||||||
|
@ -847,6 +900,13 @@ Examples: ldx #.shifted_end - .shifted_start
|
||||||
}
|
}
|
||||||
.shifted_end
|
.shifted_end
|
||||||
|
|
||||||
|
Miscellaneous: If you need to convert a label or the program counter
|
||||||
|
from its "pseudopc" to its "real" value, you can do
|
||||||
|
that using the "&" operator. Given the example above,
|
||||||
|
the symbol ".target" will evaluate to the value $0400,
|
||||||
|
but "&.target" will evaluate to the same value as
|
||||||
|
".shifted_start" will.
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Section: CPU support pseudo opcodes (especially 65816 support)
|
Section: CPU support pseudo opcodes (especially 65816 support)
|
||||||
|
@ -856,21 +916,23 @@ Call: !cpu KEYWORD [ { BLOCK } ]
|
||||||
Purpose: Select the processor to produce code for. If this PO
|
Purpose: Select the processor to produce code for. If this PO
|
||||||
isn't used, ACME defaults to the 6502 CPU (or to the
|
isn't used, ACME defaults to the 6502 CPU (or to the
|
||||||
one selected by the "--cpu" command line option).
|
one selected by the "--cpu" command line option).
|
||||||
ACME will give errors if you try to assemble commands
|
ACME will give errors if you try to assemble
|
||||||
the chosen CPU does not have. You can change the
|
instructions the chosen CPU does not support. You can
|
||||||
chosen CPU at any time. When used with block syntax,
|
change the chosen CPU at any time. When used with
|
||||||
the previously chosen CPU value is restored
|
block syntax, the previously chosen CPU value is
|
||||||
afterwards.
|
restored afterwards.
|
||||||
Parameters: KEYWORD: Currently valid keywords are:
|
Parameters: KEYWORD: Currently valid keywords are:
|
||||||
6502 for the original MOS 6502
|
6502 for the original MOS 6502
|
||||||
6510 6502 plus undocumented opcodes
|
nmos6502 6502 plus undocumented opcodes
|
||||||
65c02 6502 plus BRA,PHX/Y,PLX/Y,STZ,TRB/TSB
|
6510 (alias for "nmos6502")
|
||||||
r65c02 65c02 plus BBRx, BBSx, RMBx, SMBx
|
65c02 6502 plus BRA,PHX/Y,PLX/Y,STZ,TRB/TSB
|
||||||
w65c02 r65c02 plus STP/WAI
|
r65c02 65c02 plus BBRx, BBSx, RMBx, SMBx
|
||||||
65816 65c02 plus 16/24-bit extensions
|
w65c02 r65c02 plus STP/WAI
|
||||||
65ce02 r65c02 plus Z reg, long branches, ...
|
65816 65c02 plus 16/24-bit extensions
|
||||||
4502 65ce02 with MAP instead of AUG
|
65ce02 r65c02 plus Z reg, long branches, ...
|
||||||
c64dtv2 6502 plus BRA/SAC/SIR plus some of the
|
4502 65ce02 with MAP instead of AUG
|
||||||
|
m65 4502 plus 32-bit extensions
|
||||||
|
c64dtv2 6502 plus BRA/SAC/SIR plus some of the
|
||||||
undocumented opcodes
|
undocumented opcodes
|
||||||
See "docs/cputypes/all.txt" for more info.
|
See "docs/cputypes/all.txt" for more info.
|
||||||
BLOCK: A block of assembler statements.
|
BLOCK: A block of assembler statements.
|
||||||
|
@ -885,7 +947,7 @@ Examples: !if cputype = $65c02 {
|
||||||
pla
|
pla
|
||||||
}
|
}
|
||||||
rts
|
rts
|
||||||
!cpu 65816 ; allow 65816 commands from here on
|
!cpu 65816 ; now allow instructions of 65816 cpu
|
||||||
|
|
||||||
|
|
||||||
Call: !al [ { BLOCK } ]
|
Call: !al [ { BLOCK } ]
|
||||||
|
@ -933,6 +995,8 @@ Parameters: BLOCK: A block of assembler statements
|
||||||
If no block is given, only the current statement will
|
If no block is given, only the current statement will
|
||||||
be affected, which should then be an explicit symbol
|
be affected, which should then be an explicit symbol
|
||||||
definition.
|
definition.
|
||||||
|
To make use of this feature, you need to use the
|
||||||
|
"-Wtype-mismatch" CLI switch.
|
||||||
Aliases: "!addr"
|
Aliases: "!addr"
|
||||||
Examples: !addr k_chrout = $ffd2 ; this is an address
|
Examples: !addr k_chrout = $ffd2 ; this is an address
|
||||||
CLEAR = 147 ; but this is not
|
CLEAR = 147 ; but this is not
|
||||||
|
@ -958,6 +1022,10 @@ Purpose: Use PetSCII as the text conversion table. Now
|
||||||
superseded by the "!convtab" pseudo opcode.
|
superseded by the "!convtab" pseudo opcode.
|
||||||
Old usage: !cbm ; gives "use !ct pet instead" error
|
Old usage: !cbm ; gives "use !ct pet instead" error
|
||||||
Now use: !convtab pet ; does the same without error
|
Now use: !convtab pet ; does the same without error
|
||||||
|
If you just want to assemble an old source code
|
||||||
|
without touching it, use the "--dialect" CLI switch:
|
||||||
|
Using "--dialect 0.94.6" or earlier will assemble this
|
||||||
|
pseudo opcode without throwing an error.
|
||||||
|
|
||||||
|
|
||||||
Call: !subzone [TITLE] { BLOCK }
|
Call: !subzone [TITLE] { BLOCK }
|
||||||
|
@ -972,6 +1040,10 @@ Old usage: !subzone graphics {
|
||||||
Now use: !zone graphics {
|
Now use: !zone graphics {
|
||||||
!source "graphics.a"
|
!source "graphics.a"
|
||||||
}
|
}
|
||||||
|
If you just want to assemble an old source code
|
||||||
|
without touching it, use the "--dialect" CLI switch:
|
||||||
|
Using "--dialect 0.94.6" or earlier will assemble this
|
||||||
|
pseudo opcode without throwing an error.
|
||||||
|
|
||||||
|
|
||||||
Call: !realpc
|
Call: !realpc
|
||||||
|
@ -985,3 +1057,8 @@ Old usage: !pseudopc $0400
|
||||||
Now use: !pseudopc $0400 {
|
Now use: !pseudopc $0400 {
|
||||||
; imagine some code here...
|
; imagine some code here...
|
||||||
}
|
}
|
||||||
|
If you just want to assemble an old source code
|
||||||
|
without touching it, use the "--dialect" CLI switch:
|
||||||
|
Using "--dialect 0.94.6" or earlier will assemble this
|
||||||
|
pseudo opcode without throwing an error.
|
||||||
|
Using "--dialect 0.85", not even a warning is thrown.
|
||||||
|
|
|
@ -38,15 +38,16 @@ Assembling buggy JMP($xxff) instruction
|
||||||
location ARGUMENT + 1, but from ARGUMENT - 255. Therefore ACME
|
location ARGUMENT + 1, but from ARGUMENT - 255. Therefore ACME
|
||||||
issues this warning if you are about to generate such an
|
issues this warning if you are about to generate such an
|
||||||
instruction.
|
instruction.
|
||||||
Note that this warning is only given for CPU types 6502 and 6510,
|
Note that this warning is only given for some CPU types (6502,
|
||||||
because 65c02 and 65816 have been fixed in this respect.
|
nmos6502/6510, c64dtv2) because later ones like 65c02 and 65816
|
||||||
|
have been fixed in this regard.
|
||||||
|
|
||||||
Assembling unstable ANE #NONZERO instruction
|
Assembling unstable ANE #NONZERO instruction
|
||||||
Assembling unstable LXA #NONZERO instruction
|
Assembling unstable LXA #NONZERO instruction
|
||||||
These warnings are only ever given for CPU type 6510. ANE and LXA
|
These warnings are only ever given for CPU type nmos6502 (6510).
|
||||||
are undocumented ("illegal") opcodes of this CPU, and they only
|
ANE and LXA are undocumented ("illegal") opcodes of this CPU, and
|
||||||
work reliably if the argument is zero or the accumulator contains
|
they only work reliably if the argument is zero or the accumulator
|
||||||
0xff.
|
contains 0xff.
|
||||||
Therefore ACME issues these warnings if it is about to generate
|
Therefore ACME issues these warnings if it is about to generate
|
||||||
these instructions with a non-zero argument.
|
these instructions with a non-zero argument.
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ C-style "==" comparison detected.
|
||||||
|
|
||||||
Converted to integer for binary logic operator.
|
Converted to integer for binary logic operator.
|
||||||
Applying binary logic to float values does not make much sense,
|
Applying binary logic to float values does not make much sense,
|
||||||
therefore floats will be converted to integer in this case.
|
therefore floats will be converted to integer in such cases.
|
||||||
|
|
||||||
"EOR" is deprecated; use "XOR" instead.
|
"EOR" is deprecated; use "XOR" instead.
|
||||||
This means the operator, not the mnemonic.
|
This means the operator, not the mnemonic.
|
||||||
|
@ -72,7 +73,9 @@ Converted to integer for binary logic operator.
|
||||||
Found old "!for" syntax.
|
Found old "!for" syntax.
|
||||||
Please update your sources to use the new "!for" syntax. See
|
Please update your sources to use the new "!for" syntax. See
|
||||||
AllPOs.txt for details.
|
AllPOs.txt for details.
|
||||||
You can suppress this warning using the "-Wno-old-for" switch.
|
You can suppress this warning using the "--dialect" or the
|
||||||
|
"-Wno-old-for" CLI switch.
|
||||||
|
("-Wno-old-for" does _exactly_ the same as "--dialect 0.94.8")
|
||||||
|
|
||||||
Found new "!for" syntax.
|
Found new "!for" syntax.
|
||||||
When using the "-Wno-old-for" switch to disable the warning about
|
When using the "-Wno-old-for" switch to disable the warning about
|
||||||
|
@ -187,14 +190,23 @@ Section: Errors during assembly
|
||||||
"!cbm" is obsolete; use "!ct pet" instead.
|
"!cbm" is obsolete; use "!ct pet" instead.
|
||||||
This is given when the now obsolete "!cbm" pseudo opcode is
|
This is given when the now obsolete "!cbm" pseudo opcode is
|
||||||
encountered.
|
encountered.
|
||||||
|
If you want to assemble an old source code without first updating
|
||||||
|
it, you can use the "--dialect" CLI switch to make ACME mimic an
|
||||||
|
older version.
|
||||||
|
|
||||||
"!pseudopc/!realpc" is obsolete; use "!pseudopc {}" instead.
|
"!pseudopc/!realpc" is obsolete; use "!pseudopc {}" instead.
|
||||||
This is given when one of the now obsolete !pseudopc/!realpc
|
This is given when one of the now obsolete !pseudopc/!realpc
|
||||||
pseudo opcodes is encountered.
|
pseudo opcodes is encountered.
|
||||||
|
If you want to assemble an old source code without first updating
|
||||||
|
it, you can use the "--dialect" CLI switch to make ACME mimic an
|
||||||
|
older version.
|
||||||
|
|
||||||
"!subzone {}" is obsolete; use "!zone {}" instead.
|
"!subzone {}" is obsolete; use "!zone {}" instead.
|
||||||
This is given when the now obsolete "!subzone" pseudo opcode is
|
This is given when the now obsolete "!subzone" pseudo opcode is
|
||||||
encountered.
|
encountered.
|
||||||
|
If you want to assemble an old source code without first updating
|
||||||
|
it, you can use the "--dialect" CLI switch to make ACME mimic an
|
||||||
|
older version.
|
||||||
|
|
||||||
!error: ...
|
!error: ...
|
||||||
This is given when the pseudo opcode "!error" is executed. The
|
This is given when the pseudo opcode "!error" is executed. The
|
||||||
|
@ -293,7 +305,7 @@ Negative value - cannot choose addressing mode.
|
||||||
your program to use positive addresses instead.
|
your program to use positive addresses instead.
|
||||||
|
|
||||||
No string given.
|
No string given.
|
||||||
ACME expects a string but doesn't find it.
|
ACME expects a string but doesn't find it, or the string is empty.
|
||||||
|
|
||||||
Number out of range.
|
Number out of range.
|
||||||
A value is too high or too low.
|
A value is too high or too low.
|
||||||
|
@ -315,6 +327,9 @@ Quotes still open at end of line.
|
||||||
Source file contains illegal character.
|
Source file contains illegal character.
|
||||||
Your source code file contained a null byte.
|
Your source code file contained a null byte.
|
||||||
|
|
||||||
|
String length is not 1.
|
||||||
|
You tried something like LDA#"X" with an illegal string length.
|
||||||
|
|
||||||
Symbol already defined.
|
Symbol already defined.
|
||||||
You defined a symbol that already had a different type or value.
|
You defined a symbol that already had a different type or value.
|
||||||
To change a symbol's type or value, use the "!set" pseudo opcode.
|
To change a symbol's type or value, use the "!set" pseudo opcode.
|
||||||
|
@ -334,8 +349,8 @@ Target out of range (N; M too far).
|
||||||
away, the code would assemble.
|
away, the code would assemble.
|
||||||
|
|
||||||
There's more than one character.
|
There's more than one character.
|
||||||
You used a text string in an arithmetic expression, but the string
|
You used a text string containing more than one character in a
|
||||||
contained more than a single character.
|
situation where only a string with length one is allowed.
|
||||||
|
|
||||||
Too late for postfix.
|
Too late for postfix.
|
||||||
You can only postfix symbols at the start, before they are used for
|
You can only postfix symbols at the start, before they are used for
|
||||||
|
@ -346,8 +361,8 @@ Too many '('.
|
||||||
|
|
||||||
Un-pseudopc operator '&' can only be applied to labels.
|
Un-pseudopc operator '&' can only be applied to labels.
|
||||||
You tried to apply the operator '&' to something that is not a
|
You tried to apply the operator '&' to something that is not a
|
||||||
label. This operator only works on labels, it cannot be used on
|
label. This operator only works on labels and on '*' (the program
|
||||||
other objects.
|
counter), it cannot be used on other objects.
|
||||||
|
|
||||||
Un-pseudopc operator '&' has no !pseudopc context.
|
Un-pseudopc operator '&' has no !pseudopc context.
|
||||||
You either tried to apply the operator '&' to something that is
|
You either tried to apply the operator '&' to something that is
|
||||||
|
@ -443,7 +458,7 @@ Too deeply nested. Recursive "!source"?
|
||||||
The default limit is 64, this can be changed using the
|
The default limit is 64, this can be changed using the
|
||||||
"--maxdepth" CLI switch.
|
"--maxdepth" CLI switch.
|
||||||
|
|
||||||
Value not yet defined.
|
Value not defined.
|
||||||
A value could not be worked out. Maybe you mistyped a symbol name.
|
A value could not be worked out. Maybe you mistyped a symbol name.
|
||||||
Whether this is given as a "normal" or as a serious error depends
|
Whether this is given as a "normal" or as a serious error depends
|
||||||
on the currently parsed pseudo opcode.
|
on the currently parsed pseudo opcode.
|
||||||
|
@ -489,6 +504,9 @@ ArgStackNotEmpty
|
||||||
The expression parser has finished though there are still
|
The expression parser has finished though there are still
|
||||||
arguments left to process.
|
arguments left to process.
|
||||||
|
|
||||||
|
ExtendingListWithItself
|
||||||
|
There were multiple references to the same list.
|
||||||
|
|
||||||
IllegalBlockTerminator
|
IllegalBlockTerminator
|
||||||
A RAM block (macro or loop) was terminated incorrectly.
|
A RAM block (macro or loop) was terminated incorrectly.
|
||||||
|
|
||||||
|
@ -502,6 +520,9 @@ IllegalImmediateMode
|
||||||
The mnemonic tree contains invalid info about the size of immediate
|
The mnemonic tree contains invalid info about the size of immediate
|
||||||
arguments.
|
arguments.
|
||||||
|
|
||||||
|
IllegalNumberTypeX
|
||||||
|
A number was neither INT nor FLOAT nor UNDEFINED.
|
||||||
|
|
||||||
IllegalOperatorId
|
IllegalOperatorId
|
||||||
IllegalOperatorGroup
|
IllegalOperatorGroup
|
||||||
The expression parser found an operator that does not exist.
|
The expression parser found an operator that does not exist.
|
||||||
|
|
|
@ -6,15 +6,15 @@
|
||||||
|
|
||||||
- free software -
|
- free software -
|
||||||
|
|
||||||
(C) 1998-2019 Marco Baye
|
(C) 1998-2020 Marco Baye
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
Section: Copyright
|
Section: Copyright
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
ACME - a crossassembler for producing 6502/6510/65c02/65816 code.
|
ACME - a crossassembler for producing 6502/65c02/65816 code.
|
||||||
Copyright (C) 1998-2017 Marco Baye
|
Copyright (C) 1998-2020 Marco Baye
|
||||||
The ACME icon was designed by Wanja "Brix" Gayk
|
The ACME icon was designed by Wanja "Brix" Gayk
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -39,9 +39,9 @@ Section: Introduction
|
||||||
|
|
||||||
ACME is a crossassembler for the 65xx range of processors. It knows
|
ACME is a crossassembler for the 65xx range of processors. It knows
|
||||||
about the standard 6502, the 65c02 and the 65816. It also supports
|
about the standard 6502, the 65c02 and the 65816. It also supports
|
||||||
the undocumented ("illegal") opcodes of the 6510 processor (a 6502-
|
the undocumented ("illegal") opcodes of the NMOS versions of the 6502,
|
||||||
variant that is used in the Commodore C=64), and the extensions added
|
like the 6510 variant that is used in the Commodore C=64, and it also
|
||||||
in the C64DTV2.
|
supports extensions to the intruction set done by other parties.
|
||||||
|
|
||||||
This text and the other files in the same directory only describe the
|
This text and the other files in the same directory only describe the
|
||||||
basic functions independent of the platform used. There should be
|
basic functions independent of the platform used. There should be
|
||||||
|
@ -61,14 +61,16 @@ The files in the docs directory and what they contain:
|
||||||
Help.txt ...is this text.
|
Help.txt ...is this text.
|
||||||
Illegals.txt Support for undocumented opcodes
|
Illegals.txt Support for undocumented opcodes
|
||||||
Lib.txt Information about the library
|
Lib.txt Information about the library
|
||||||
QuickRef.txt All the basic stuff about ACME
|
QuickRef.txt All the basic stuff about ACME <- START HERE!
|
||||||
Source.txt How to compile ACME
|
Source.txt How to compile ACME
|
||||||
Upgrade.txt Incompatibilities to earlier versions
|
Upgrade.txt Incompatibilities to earlier versions
|
||||||
cputypes/ Instruction sets of target CPUs
|
cputypes/ Instruction sets of target CPUs
|
||||||
|
|
||||||
IMPORTANT: If you upgrade from ACME 0.05 or earlier, don't forget to
|
IMPORTANT: If you upgrade from an earlier version of ACME, don't
|
||||||
read the file "Upgrade.txt" - release 0.07 and all later ones are
|
forget to read the files "Changes.txt" and "Upgrade.txt". Adding new
|
||||||
slightly incompatible to 0.05 and earlier.
|
features can not always be done in a 100% compatible way, so newer
|
||||||
|
version may behave slightly different. To solve this problem, the
|
||||||
|
"--dialect" CLI switch can be used.
|
||||||
|
|
||||||
If you want to start using ACME right away, read the file
|
If you want to start using ACME right away, read the file
|
||||||
"QuickRef.txt", it contains the main help text.
|
"QuickRef.txt", it contains the main help text.
|
||||||
|
@ -79,15 +81,14 @@ Section: What it can and does
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
ACME is a crossassembler.
|
ACME is a crossassembler.
|
||||||
ACME can produce code for the 6502, 6510, 65c02 and 65816 processors.
|
ACME can produce code for the 6502, 65c02 and 65816 processors.
|
||||||
It does this *fast*.
|
It does this *fast*.
|
||||||
It can produce at most 64 KBytes of code.
|
It can produce at most 64 KBytes of code.
|
||||||
You can use global labels, local labels and anonymous labels.
|
You can use global labels, local labels and anonymous labels.
|
||||||
It is fast.
|
It is fast.
|
||||||
You can use global and local macros.
|
You can use global and local macros.
|
||||||
You can use conditional assembly.
|
You can use conditional assembly.
|
||||||
You can use looping assembly (There are two ways to do this; a very
|
You can use looping assembly.
|
||||||
simple and a very flexible one).
|
|
||||||
You can include other source files.
|
You can include other source files.
|
||||||
You can include binary files (either whole or parts) directly into the
|
You can include binary files (either whole or parts) directly into the
|
||||||
output.
|
output.
|
||||||
|
@ -100,6 +101,7 @@ ACME's maths parser has no problems concerning parentheses and
|
||||||
indirect addressing modes.
|
indirect addressing modes.
|
||||||
ACME's maths parser knows a shit load of different operations.
|
ACME's maths parser knows a shit load of different operations.
|
||||||
ACME supports both integer and floating point maths operations.
|
ACME supports both integer and floating point maths operations.
|
||||||
|
In addition to numbers, symbols can also hold strings or lists.
|
||||||
You can dump the global symbols into a file.
|
You can dump the global symbols into a file.
|
||||||
ACME supports a library of commonly used macros and symbols.
|
ACME supports a library of commonly used macros and symbols.
|
||||||
It always takes as many passes as are needed.
|
It always takes as many passes as are needed.
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
|
|
||||||
In release 0.87, support for some of the undocumented opcodes of the
|
In release 0.87, support for some of the undocumented opcodes of the
|
||||||
6502 processor was added.
|
NMOS 6502 processor was added.
|
||||||
In release 0.89, some more were added.
|
In release 0.89, some more were added.
|
||||||
In release 0.94.8, another one was added (lxa).
|
In release 0.94.8, another one was added (lxa).
|
||||||
In release 0.95.3, C64DTV2 support was added, which includes these
|
In release 0.95.3, C64DTV2 support was added, which includes these
|
||||||
|
@ -31,7 +31,6 @@ opcodes (mnemonics in parentheses are used by other sources):
|
||||||
dcp (dcm) | c7 d7 cf df db c3 d3 | dec + cmp
|
dcp (dcm) | c7 d7 cf df db c3 d3 | dec + cmp
|
||||||
isc (isb, ins) | e7 f7 ef ff fb e3 f3 | inc + sbc
|
isc (isb, ins) | e7 f7 ef ff fb e3 f3 | inc + sbc
|
||||||
las (lar, lae) | bb | A,X,S = {addr} & S
|
las (lar, lae) | bb | A,X,S = {addr} & S
|
||||||
These five are said to be unstable:
|
|
||||||
tas (shs, xas) | 9b | S = A & X {addr} = A&X& {H+1}
|
tas (shs, xas) | 9b | S = A & X {addr} = A&X& {H+1}
|
||||||
sha (axa, ahx) | 9f 93 | {addr} = A & X & {H+1}
|
sha (axa, ahx) | 9f 93 | {addr} = A & X & {H+1}
|
||||||
shx (xas, sxa) | 9e | {addr} = X & {H+1}
|
shx (xas, sxa) | 9e | {addr} = X & {H+1}
|
||||||
|
@ -53,13 +52,15 @@ These two are somewhat unstable, because they involve an arbitrary value:
|
||||||
lxa (lax, atx) | ab*** | A,X = (A | ??) & arg
|
lxa (lax, atx) | ab*** | A,X = (A | ??) & arg
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
!cpu 6510 ; activate additional mnemonics...
|
!cpu nmos6502 ; activate additional mnemonics...
|
||||||
lax (some_zp_label,x) ; ...and use them. No, this
|
lax (some_zp_label,x) ; ...and use them. No, this
|
||||||
dcp (other_zp_label),y ; example does not make sense.
|
dcp (other_zp_label),y ; example does not make sense.
|
||||||
|
|
||||||
*) Up until ACME version 0.95.1, anc#8 generated opcode 0x2b. Since
|
*) Up until ACME version 0.95.1, anc#8 generated opcode 0x2b. Since
|
||||||
ACME version 0.95.2, anc#8 generates opcode 0x0b. Both opcodes work
|
ACME version 0.95.2, anc#8 generates opcode 0x0b. Both opcodes work
|
||||||
the same way on a real 6510 CPU, but they do not work on the C64DTV2.
|
the same way on a real NMOS 6502 CPU, but they do not work on the
|
||||||
|
C64DTV2.
|
||||||
|
Using the "--dialect" CLI switch does not change the generated opcode!
|
||||||
|
|
||||||
**) Note that DOP ("double nop") and TOP ("triple nop") can be used
|
**) Note that DOP ("double nop") and TOP ("triple nop") can be used
|
||||||
with implied addressing, but the generated opcodes are those for
|
with implied addressing, but the generated opcodes are those for
|
||||||
|
@ -68,7 +69,7 @@ and TOP can be used to skip the following one- or two-byte
|
||||||
instruction.
|
instruction.
|
||||||
Using DOP/TOP with x-indexed addressing might have its uses when
|
Using DOP/TOP with x-indexed addressing might have its uses when
|
||||||
timing is critical (crossing a page border adds a penalty cycle).
|
timing is critical (crossing a page border adds a penalty cycle).
|
||||||
Unless using implied addressing, DOP/TOP can now also be written as NOP.
|
Unless using implied addressing, DOP/TOP can also be written as NOP.
|
||||||
|
|
||||||
***) ANE and LXA first perform an ORA with an arbitrary(!) value and
|
***) ANE and LXA first perform an ORA with an arbitrary(!) value and
|
||||||
then perform an AND with the given argument. So they are unstable and
|
then perform an AND with the given argument. So they are unstable and
|
||||||
|
@ -79,10 +80,8 @@ ACME will output a warning if these opcodes get assembled with a
|
||||||
nonzero argument.
|
nonzero argument.
|
||||||
|
|
||||||
There is no guarantee that these opcodes actually work on a given 6502
|
There is no guarantee that these opcodes actually work on a given 6502
|
||||||
(or 6510, or 8500, or 8502) CPU. But as far as I know, nobody ever
|
(or 6510, or 8500, or 8501, or 8502) CPU. But as far as I know, nobody
|
||||||
found an unmodified C64/C128 where these illegals didn't work. That's
|
ever found an unmodified C64/C128 where these illegals didn't work.
|
||||||
why I used "6510" as the CPU keyword instead of "6502illegal" or
|
|
||||||
something like that.
|
|
||||||
|
|
||||||
These illegals will definitely *not* work on 65c02 and 65816 CPUs. But
|
These illegals will definitely *not* work on 65c02 and 65816 CPUs. But
|
||||||
I really should not have to tell you that ;)
|
I really should not have to tell you that ;)
|
||||||
|
@ -92,7 +91,7 @@ people use different names for them. I hope my choices are not too
|
||||||
exotic for your taste.
|
exotic for your taste.
|
||||||
|
|
||||||
Just for the sake of completeness: Here are all the remaining opcodes
|
Just for the sake of completeness: Here are all the remaining opcodes
|
||||||
(the ones ACME won't generate even with "6510" cpu):
|
(the ones ACME won't generate even with "nmos6502" cpu chosen):
|
||||||
|
|
||||||
Opcode| Description C64DTV2
|
Opcode| Description C64DTV2
|
||||||
------+--------------------------------------------------------------
|
------+--------------------------------------------------------------
|
||||||
|
@ -137,7 +136,10 @@ For more information about what these opcodes do, see these documents:
|
||||||
Extra Instructions Of The 65XX Series CPU, Adam Vardy, 27 Sept. 1996
|
Extra Instructions Of The 65XX Series CPU, Adam Vardy, 27 Sept. 1996
|
||||||
6502 Undocumented Opcodes, by Freddy Offenga, 5/17/1997
|
6502 Undocumented Opcodes, by Freddy Offenga, 5/17/1997
|
||||||
AAY64 (All About Your 64)
|
AAY64 (All About Your 64)
|
||||||
and the most comprehensive work is:
|
|
||||||
"No More Secrets - NMOS 6510 Unintended Opcodes"
|
...but the most comprehensive work is:
|
||||||
Download it from https://csdb.dk/release/?id=185341
|
|
||||||
|
"No More Secrets - NMOS 6510 Unintended Opcodes"
|
||||||
|
|
||||||
|
Download it from https://csdb.dk/release/?id=185341
|
||||||
or ask google for the latest version.
|
or ask google for the latest version.
|
||||||
|
|
|
@ -106,6 +106,10 @@ Then there are local symbols (their names starting with a '.'
|
||||||
character). These can only be accessed from inside the macro or zone
|
character). These can only be accessed from inside the macro or zone
|
||||||
they were defined in (for more about macros and zones, see the file
|
they were defined in (for more about macros and zones, see the file
|
||||||
"AllPOs.txt").
|
"AllPOs.txt").
|
||||||
|
There are also "cheap locals": their names start with a '@' character.
|
||||||
|
The area where these can be accessed is limited automatically by the
|
||||||
|
previous and the following global label (cheap locals are "cheap"
|
||||||
|
because you don't have to put in any extra work to limit their range).
|
||||||
And then there are anonymous labels (their names being sequences of
|
And then there are anonymous labels (their names being sequences of
|
||||||
either '-' or '+' characters). They are also local (bound to their
|
either '-' or '+' characters). They are also local (bound to their
|
||||||
macro/zone), but in addition to that, the "-" labels can only be used
|
macro/zone), but in addition to that, the "-" labels can only be used
|
||||||
|
@ -113,6 +117,7 @@ for backward references, while the "+" labels can only be used for
|
||||||
forward references.
|
forward references.
|
||||||
In contrast to global and local labels, anonymous labels can not be
|
In contrast to global and local labels, anonymous labels can not be
|
||||||
defined explicitly (as in SYMBOL = VALUE).
|
defined explicitly (as in SYMBOL = VALUE).
|
||||||
|
Each macro call automatically gets its own scope for local symbols.
|
||||||
|
|
||||||
Save the given example source code to a file called "tiny.a" and start
|
Save the given example source code to a file called "tiny.a" and start
|
||||||
acme by typing
|
acme by typing
|
||||||
|
@ -149,7 +154,7 @@ found in the file "AllPOs.txt". Here's just a short overview:
|
||||||
!convtab !pet !raw !scr !scrxor !text
|
!convtab !pet !raw !scr !scrxor !text
|
||||||
...for converting and outputting strings.
|
...for converting and outputting strings.
|
||||||
|
|
||||||
!do !endoffile !for !if !ifdef !ifndef !set
|
!do !endoffile !for !if !ifdef !ifndef !set !while
|
||||||
...for flow control; looping assembly and conditional assembly.
|
...for flow control; looping assembly and conditional assembly.
|
||||||
|
|
||||||
!binary !source !to
|
!binary !source !to
|
||||||
|
@ -170,7 +175,7 @@ found in the file "AllPOs.txt". Here's just a short overview:
|
||||||
!warn !error !serious
|
!warn !error !serious
|
||||||
...for generating warnings, errors and serious errors.
|
...for generating warnings, errors and serious errors.
|
||||||
|
|
||||||
!addr
|
!address
|
||||||
...to mark symbols as addresses, for the optional type check system.
|
...to mark symbols as addresses, for the optional type check system.
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,6 +281,8 @@ Available options are:
|
||||||
-Wno-old-for
|
-Wno-old-for
|
||||||
Disables warnings about the old "!for" syntax and at the
|
Disables warnings about the old "!for" syntax and at the
|
||||||
same time enables warnings about the _new_ "!for" syntax.
|
same time enables warnings about the _new_ "!for" syntax.
|
||||||
|
Internally, this does exactly the same as what happens
|
||||||
|
when the "--dialect 0.94.8" CLI switch is used...
|
||||||
-Wtype-mismatch
|
-Wtype-mismatch
|
||||||
Enables type checking system (warns about wrong types).
|
Enables type checking system (warns about wrong types).
|
||||||
|
|
||||||
|
@ -296,6 +303,15 @@ Available options are:
|
||||||
from '!' to '.' (so sources intended for other assemblers can
|
from '!' to '.' (so sources intended for other assemblers can
|
||||||
be converted with less effort).
|
be converted with less effort).
|
||||||
|
|
||||||
|
--dialect VERSION behave like different version
|
||||||
|
This CLI switch tells ACME to mimic the behavior of an older
|
||||||
|
version. Use this with a bogus version to get a list of all
|
||||||
|
supported ones.
|
||||||
|
|
||||||
|
--test enable experimental features
|
||||||
|
This is for people who want to help test new features before
|
||||||
|
they are officially announced.
|
||||||
|
|
||||||
-V, --version show version and exit.
|
-V, --version show version and exit.
|
||||||
|
|
||||||
Platform-specific versions of ACME might offer more options.
|
Platform-specific versions of ACME might offer more options.
|
||||||
|
@ -389,8 +405,8 @@ $d011 hexadecimal values are indicated by either a
|
||||||
more readable, especially when building bitmapped
|
more readable, especially when building bitmapped
|
||||||
objects (like C64 sprites or fonts) in your source
|
objects (like C64 sprites or fonts) in your source
|
||||||
code.
|
code.
|
||||||
"p" character values are indicated by double or single
|
'p' character values are indicated by single or double
|
||||||
'q' quotes. The actual numeric value depends on the
|
"q" quotes. The actual numeric value depends on the
|
||||||
current conversion table (none/petscii/screen),
|
current conversion table (none/petscii/screen),
|
||||||
chosen using the "!ct" pseudo opcode.
|
chosen using the "!ct" pseudo opcode.
|
||||||
poll_joy2 a global symbol
|
poll_joy2 a global symbol
|
||||||
|
|
20
src/alu.c
20
src/alu.c
|
@ -695,7 +695,7 @@ static void list_append_list(struct listitem *selfhead, struct listitem *otherhe
|
||||||
struct listitem *item;
|
struct listitem *item;
|
||||||
|
|
||||||
if (selfhead == otherhead)
|
if (selfhead == otherhead)
|
||||||
Bug_found("ExtendingListWithItself", 0); // TODO - add to docs!
|
Bug_found("ExtendingListWithItself", 0);
|
||||||
item = otherhead->next;
|
item = otherhead->next;
|
||||||
while (item != otherhead) {
|
while (item != otherhead) {
|
||||||
list_append_object(selfhead, &item->u.payload);
|
list_append_object(selfhead, &item->u.payload);
|
||||||
|
@ -1659,7 +1659,7 @@ static void number_handle_monadic_operator(struct object *self, const struct op
|
||||||
float_handle_monadic_operator(self, op);
|
float_handle_monadic_operator(self, op);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Bug_found("IllegalNumberType1", self->u.number.ntype); // FIXME - add to docs!
|
Bug_found("IllegalNumberType1", self->u.number.ntype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2101,7 +2101,7 @@ static void number_handle_dyadic_operator(struct object *self, const struct op *
|
||||||
else if (self->u.number.ntype == NUMTYPE_FLOAT)
|
else if (self->u.number.ntype == NUMTYPE_FLOAT)
|
||||||
float_handle_dyadic_operator(self, op, other);
|
float_handle_dyadic_operator(self, op, other);
|
||||||
else
|
else
|
||||||
Bug_found("IllegalNumberType2", self->u.number.ntype); // FIXME - add to docs!
|
Bug_found("IllegalNumberType2", self->u.number.ntype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2122,7 +2122,7 @@ static int get_valid_index(int *target, int length, const struct object *self, c
|
||||||
if (other->u.number.ntype == NUMTYPE_FLOAT)
|
if (other->u.number.ntype == NUMTYPE_FLOAT)
|
||||||
float_to_int(other);
|
float_to_int(other);
|
||||||
if (other->u.number.ntype != NUMTYPE_INT)
|
if (other->u.number.ntype != NUMTYPE_INT)
|
||||||
Bug_found("IllegalNumberType3", other->u.number.ntype); // FIXME - add to docs!
|
Bug_found("IllegalNumberType3", other->u.number.ntype);
|
||||||
|
|
||||||
index = other->u.number.val.intval;
|
index = other->u.number.val.intval;
|
||||||
// negative indices access from the end
|
// negative indices access from the end
|
||||||
|
@ -2279,7 +2279,7 @@ static void number_fix_result(struct object *self)
|
||||||
&& (self->u.number.val.fpval >= -128.0))
|
&& (self->u.number.val.fpval >= -128.0))
|
||||||
self->u.number.flags |= NUMBER_FITS_BYTE; // FIXME - what for? isn't this flag only of use when undefined?
|
self->u.number.flags |= NUMBER_FITS_BYTE; // FIXME - what for? isn't this flag only of use when undefined?
|
||||||
} else {
|
} else {
|
||||||
Bug_found("IllegalNumberType4", self->u.number.ntype); // FIXME - add to docs!
|
Bug_found("IllegalNumberType4", self->u.number.ntype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2307,7 +2307,7 @@ static void number_print(const struct object *self, struct dynabuf *db)
|
||||||
sprintf(buffer, "%.30g", self->u.number.val.fpval);
|
sprintf(buffer, "%.30g", self->u.number.val.fpval);
|
||||||
DynaBuf_add_string(db, buffer);
|
DynaBuf_add_string(db, buffer);
|
||||||
} else {
|
} else {
|
||||||
Bug_found("IllegalNumberType5", self->u.number.ntype); // FIXME - add to docs!
|
Bug_found("IllegalNumberType5", self->u.number.ntype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2480,7 +2480,7 @@ void ALU_any_int(intval_t *target) // ACCEPT_UNDEFINED
|
||||||
else if (expression.result.u.number.ntype == NUMTYPE_FLOAT)
|
else if (expression.result.u.number.ntype == NUMTYPE_FLOAT)
|
||||||
*target = expression.result.u.number.val.fpval;
|
*target = expression.result.u.number.val.fpval;
|
||||||
else
|
else
|
||||||
Bug_found("IllegalNumberType6", expression.result.u.number.ntype); // FIXME - add to docs!
|
Bug_found("IllegalNumberType6", expression.result.u.number.ntype);
|
||||||
} else {
|
} else {
|
||||||
*target = 0;
|
*target = 0;
|
||||||
Throw_error(exception_not_number);
|
Throw_error(exception_not_number);
|
||||||
|
@ -2510,13 +2510,13 @@ void ALU_defined_int(struct number *intresult) // no ACCEPT constants?
|
||||||
Throw_serious_error(exception_no_value);
|
Throw_serious_error(exception_no_value);
|
||||||
if (expression.result.type == &type_number) {
|
if (expression.result.type == &type_number) {
|
||||||
if (expression.result.u.number.ntype == NUMTYPE_UNDEFINED) {
|
if (expression.result.u.number.ntype == NUMTYPE_UNDEFINED) {
|
||||||
Throw_serious_error(exception_value_not_defined);
|
Throw_serious_error("Value not defined.");
|
||||||
} else if (expression.result.u.number.ntype == NUMTYPE_INT) {
|
} else if (expression.result.u.number.ntype == NUMTYPE_INT) {
|
||||||
// ok
|
// ok
|
||||||
} else if (expression.result.u.number.ntype == NUMTYPE_FLOAT) {
|
} else if (expression.result.u.number.ntype == NUMTYPE_FLOAT) {
|
||||||
float_to_int(&expression.result);
|
float_to_int(&expression.result);
|
||||||
} else {
|
} else {
|
||||||
Bug_found("IllegalNumberType7", expression.result.u.number.ntype); // FIXME - add to docs!
|
Bug_found("IllegalNumberType7", expression.result.u.number.ntype);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Throw_serious_error(exception_not_number);
|
Throw_serious_error(exception_not_number);
|
||||||
|
@ -2548,7 +2548,7 @@ void ALU_addrmode_int(struct expression *expression, int paren) // ACCEPT_UNDEFI
|
||||||
// FIXME - throw a warning?
|
// FIXME - throw a warning?
|
||||||
string_to_byte(&(expression->result), 0);
|
string_to_byte(&(expression->result), 0);
|
||||||
} else {
|
} else {
|
||||||
Throw_error("String length is not 1."); // FIXME - add to docs!
|
Throw_error("String length is not 1.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Throw_error(exception_not_number);
|
Throw_error(exception_not_number);
|
||||||
|
|
|
@ -57,7 +57,6 @@ const char exception_number_out_of_range[] = "Number out of range.";
|
||||||
const char exception_pc_undefined[] = "Program counter undefined.";
|
const char exception_pc_undefined[] = "Program counter undefined.";
|
||||||
const char exception_symbol_defined[] = "Symbol already defined.";
|
const char exception_symbol_defined[] = "Symbol already defined.";
|
||||||
const char exception_syntax[] = "Syntax error.";
|
const char exception_syntax[] = "Syntax error.";
|
||||||
const char exception_value_not_defined[] = "Value not defined.";
|
|
||||||
// default value for number of errors before exiting
|
// default value for number of errors before exiting
|
||||||
#define MAXERRORS 10
|
#define MAXERRORS 10
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ extern const char exception_number_out_of_range[];
|
||||||
extern const char exception_pc_undefined[];
|
extern const char exception_pc_undefined[];
|
||||||
extern const char exception_symbol_defined[];
|
extern const char exception_symbol_defined[];
|
||||||
extern const char exception_syntax[];
|
extern const char exception_syntax[];
|
||||||
extern const char exception_value_not_defined[];
|
|
||||||
// byte flags table
|
// byte flags table
|
||||||
extern const char global_byte_flags[];
|
extern const char global_byte_flags[];
|
||||||
#define BYTE_STARTS_KEYWORD(b) (global_byte_flags[(unsigned char) b] & (1u << 7)) // byte is allowed at start of keyword (a-z, A-Z, _, everything>127)
|
#define BYTE_STARTS_KEYWORD(b) (global_byte_flags[(unsigned char) b] & (1u << 7)) // byte is allowed at start of keyword (a-z, A-Z, _, everything>127)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user