mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-09-01 15:28:55 +00:00
Release 0.95.1: Tweaked type system and changed "label" to "symbol" in a lot of places.
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@35 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
d152f60acd
commit
808ccf39a3
@ -30,7 +30,7 @@ The two exceptions are:
|
||||
|
||||
|
||||
|
||||
*** 1) Labels are defined too late
|
||||
*** 1) Symbols are defined too late
|
||||
|
||||
If ACME cannot figure out the argument value in the first pass, it
|
||||
assumes that the command uses 16-bit addressing.
|
||||
@ -39,7 +39,7 @@ If it later finds out that the argument only needs 8 bits, ACME gives
|
||||
a warning ("using oversized addressing mode") and continues. However,
|
||||
if it finds out that the argument needs 24 bits, it gives an error.
|
||||
|
||||
These problems can be solved by defining the labels *before* using
|
||||
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
|
||||
is not possible, you can use the postfix method, effectively exactly
|
||||
defining what addressing mode to use. The postfix method is described
|
||||
@ -65,16 +65,16 @@ target location using leading zeros. ACME will then use an addressing
|
||||
mode that is big enough even if the leading zeros would have been
|
||||
other digits:
|
||||
|
||||
label1 = $fb
|
||||
label2 = $00fd
|
||||
label3 = $0000ff
|
||||
symbol1 = $fb
|
||||
symbol2 = $00fd
|
||||
symbol3 = $0000ff
|
||||
|
||||
lda $fa
|
||||
sta $00fc
|
||||
lda $0000fe
|
||||
sta label1
|
||||
lda label2
|
||||
sta label3
|
||||
sta symbol1
|
||||
lda symbol2
|
||||
sta symbol3
|
||||
|
||||
will be assembled to
|
||||
|
||||
@ -108,17 +108,17 @@ priorities.
|
||||
|
||||
Here's an (overly complicated) example:
|
||||
|
||||
label1 = $fb
|
||||
label2 = $fd
|
||||
label3+3 = $ff ; set Force Bit 3 and store in label's flags
|
||||
symbol1 = $fb
|
||||
symbol2 = $fd
|
||||
symbol3+3 = $ff ; set Force Bit 3 and store in symbol's flags
|
||||
|
||||
ldx $fa
|
||||
ldy+2 $fc ; set Force Bit 2 (16-bit addressing)
|
||||
lda+3 $fe ; set Force Bit 3 (24-bit addressing)
|
||||
stx label1
|
||||
sty+2 label2 ; set Force Bit 2 (16-bit addressing)
|
||||
sta label3 ; no need to set Force Bit 3 as it is
|
||||
; already set in "label3".
|
||||
stx symbol1
|
||||
sty+2 symbol2 ; set Force Bit 2 (16-bit addressing)
|
||||
sta symbol3 ; no need to set Force Bit 3 as it is
|
||||
; already set in "symbol3".
|
||||
|
||||
will be assembled to
|
||||
|
||||
@ -131,13 +131,13 @@ will be assembled to
|
||||
|
||||
Postfixes given directly after the command have higher priority than
|
||||
those given to the argument. As you can see, you can add the postfix
|
||||
to the label definition as well (equivalent to leading zeros).
|
||||
to the symbol definition as well (equivalent to leading zeros).
|
||||
|
||||
Applying the byte extraction operators ("<" gives the low byte, ">"
|
||||
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
|
||||
Bit 1 instead. So "lda <label" will use 8-bit addressing, regardless
|
||||
of the label's Force Bits. Of course, you can change this by
|
||||
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
|
||||
postfixing the command again... :)
|
||||
|
||||
|
||||
@ -154,9 +154,9 @@ ACME acts upon it. So postfixes have the highest priority.
|
||||
|
||||
Otherwise, ACME checks whether the argument has any Force Bits set
|
||||
(because of leading zeros or byte extraction operators, for example)
|
||||
or references to labels that have. If any Force Bit is set, ACME acts
|
||||
or references symbols that have. If any Force Bit is set, ACME acts
|
||||
upon it. This is the next priority level: Leading zeros or postfixes
|
||||
added to the label definition.
|
||||
added to the symbol definition.
|
||||
|
||||
Otherwise, ACME checks whether the argument could be figured out in
|
||||
the first pass. If it couldn't, ACME tries to use a default addressing
|
||||
|
126
docs/AllPOs.txt
126
docs/AllPOs.txt
@ -21,16 +21,16 @@ Call: !8 EXPRESSION [, EXPRESSION]*
|
||||
Purpose: Insert 8-bit values.
|
||||
Parameters: EXPRESSION: Any formula the value parser accepts.
|
||||
Aliases: "!08", "!by", "!byte"
|
||||
Examples: !08 127, label, -128 ; output some values
|
||||
Examples: !08 127, symbol, -128 ; output some values
|
||||
!by 14, $3d, %0110, &304, <*, "c"
|
||||
!byte 3 - 4, label1 XOR label2, 2 ^ tz, (3+4)*7
|
||||
!byte 3 - 4, symbol1 XOR symbol2, 2 ^ tz, (3+4)*7
|
||||
|
||||
|
||||
Call: !16 EXPRESSION [, EXPRESSION]*
|
||||
Purpose: Insert 16-bit values.
|
||||
Parameters: EXPRESSION: Any formula the value parser accepts.
|
||||
Aliases: "!wo", "!word"
|
||||
Examples: !16 65535, label, -32768 ; output some values
|
||||
Examples: !16 65535, symbol, -32768 ; output some values
|
||||
!wo 14, $4f35, %100101010010110, &36304, *, "c"
|
||||
!word 3000 - 4, a1 AND a2, 2 ^ tz, (3+4)*70, l1 & .j2
|
||||
|
||||
@ -38,7 +38,7 @@ Examples: !16 65535, label, -32768 ; output some values
|
||||
Call: !24 EXPRESSION [, EXPRESSION]*
|
||||
Purpose: Insert 24-bit values.
|
||||
Parameters: EXPRESSION: Any formula the value parser accepts.
|
||||
Examples: !24 16777215, label, -8388608, 14, $6a4f35
|
||||
Examples: !24 16777215, symbol, -8388608, 14, $6a4f35
|
||||
!24 %10010110100101010010110, &47336304, *, "c"
|
||||
!24 300000 - 4, a1 AND a2, 2 ^ tz, (3+4)*70, l1 & .j2
|
||||
|
||||
@ -46,7 +46,7 @@ Examples: !24 16777215, label, -8388608, 14, $6a4f35
|
||||
Call: !32 EXPRESSION [, EXPRESSION]*
|
||||
Purpose: Insert 32-bit values.
|
||||
Parameters: EXPRESSION: Any formula the value parser accepts.
|
||||
Examples: !32 $7fffffff, label, -$80000000, 14, $46a4f35
|
||||
Examples: !32 $7fffffff, symbol, -$80000000, 14, $46a4f35
|
||||
!32 %1001011010010101001011010010, &4733630435, *, "c"
|
||||
!32 300000 - 4, a AND a2, 2 ^ tz, (3+4)*70, l1 & .j2
|
||||
|
||||
@ -247,11 +247,11 @@ Examples: !binary <Own/menudata.b> ; insert library file
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: Labels
|
||||
Section: Symbols
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Call: !zone [TITLE] [ { BLOCK } ]
|
||||
Purpose: Switch to new zone of local labels. Zones can either
|
||||
Purpose: Switch to new zone of local symbols. Zones can either
|
||||
be nested or used sequentially.
|
||||
Parameters: TITLE: May consist of letters and digits. Its only
|
||||
purpose is to be displayed in error messages, so it'll
|
||||
@ -262,9 +262,9 @@ Parameters: TITLE: May consist of letters and digits. Its only
|
||||
If a block is given, the old zone continues after the
|
||||
block.
|
||||
Aliases: "!zn"
|
||||
Examples: .backgroundcolor = 0 ; some local label
|
||||
!zone File_IO ; new zone begins here
|
||||
.backgroundcolor = 1 ; so this is a different label
|
||||
Examples: .backgroundcolor = 0 ; some local symbol
|
||||
!zone File_IO ; new zone begins here, so
|
||||
.backgroundcolor = 1 ; this is a different symbol
|
||||
!zn LinkedList_Init
|
||||
.backgroundcolor = 2
|
||||
!zone LinkedList { ; start of nested zone
|
||||
@ -279,17 +279,17 @@ Examples: .backgroundcolor = 0 ; some local label
|
||||
!zone LinkedList_End
|
||||
; you know what to imagine here...
|
||||
}
|
||||
.backgroundcolor = 3 ; => "Label already defined."
|
||||
.backgroundcolor = 3 ; => "Symbol already defined."
|
||||
|
||||
|
||||
Call: !sl FILENAME
|
||||
Purpose: Save all the global labels to the given file after the
|
||||
assembly is finished. This table could be loaded
|
||||
Purpose: Save all the global symbols to the given file after
|
||||
the assembly is finished. This table could be loaded
|
||||
during another assembly session using the "!source"
|
||||
pseudo opcode.
|
||||
Parameters: FILENAME: A file name given in "..." quoting.
|
||||
Examples: !sl "Labels.a" ; produce label dump after assembly
|
||||
!sl "global" ; produce label dump after assembly
|
||||
Examples: !sl "Symbols.a" ; produce symbol dump after assembly
|
||||
!sl "global" ; produce symbol dump after assembly
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
@ -305,7 +305,7 @@ 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: !text "Black", 0 ; Choose wording according to
|
||||
!if country = uk { ; content of "country" label.
|
||||
!if country = uk { ; content of "country" symbol.
|
||||
!text "Grey"
|
||||
} else {
|
||||
!text "Gray"
|
||||
@ -313,38 +313,38 @@ Examples: !text "Black", 0 ; Choose wording according to
|
||||
!byte 0
|
||||
!text "White", 0
|
||||
|
||||
; Insert debug commands if label "debug" is not zero:
|
||||
; Insert debug commands if symbol "debug" is not zero:
|
||||
!if debug { lda #"z":jsr char_output }
|
||||
|
||||
|
||||
Call: !ifdef LABEL { BLOCK } [ else { BLOCK } ]
|
||||
or: !ifdef LABEL STATEMENT
|
||||
Call: !ifndef LABEL { BLOCK } [ else { BLOCK } ]
|
||||
or: !ifndef LABEL STATEMENT
|
||||
Purpose: Conditional assembly, depending on whether a label is
|
||||
Call: !ifdef SYMBOL { BLOCK } [ else { BLOCK } ]
|
||||
or: !ifdef SYMBOL STATEMENT
|
||||
Call: !ifndef SYMBOL { BLOCK } [ else { BLOCK } ]
|
||||
or: !ifndef SYMBOL STATEMENT
|
||||
Purpose: Conditional assembly, depending on whether a symbol is
|
||||
already defined or not.
|
||||
With "ifdef", if the label is defined, the first block
|
||||
of statements will be parsed; if it isn't, the second
|
||||
block will be parsed instead (if present).
|
||||
With "ifndef", it's the other way around: If the label
|
||||
isn't defined, the first block of statements will be
|
||||
parsed; if it is defined, the second block will be
|
||||
parsed instead (if present).
|
||||
With "ifdef", if the symbol is defined, the first
|
||||
block of statements will be parsed; if it isn't, the
|
||||
second block will be parsed instead (if present).
|
||||
With "ifndef", it's the other way around: If the
|
||||
symbol isn't defined, the first block of statements
|
||||
will be parsed; if it is defined, the second block
|
||||
will be parsed instead (if present).
|
||||
CAUTION: These opcodes were added to speed up parsing
|
||||
of library files (see example below). They can be used
|
||||
to tell passes apart, therefore only use them in your
|
||||
own files if you're sure you *really* know what you
|
||||
are doing - using them in the wrong way will result in
|
||||
loads of error messages.
|
||||
Parameters: LABEL: Any valid label name.
|
||||
Parameters: SYMBOL: Any valid symbol name.
|
||||
BLOCK: A block of assembler statements.
|
||||
STATEMENT: Any assembler statement.
|
||||
Examples: ; this was taken from <6502/std.a>:
|
||||
!ifdef Lib_6502_std_a !eof ; in later passes,
|
||||
Lib_6502_std_a = 1 ; skip this file.
|
||||
; During the first pass, the label is not defined,
|
||||
; During the first pass, the symbol is not defined,
|
||||
; therefore the file will get parsed. During all
|
||||
; further passes, the label is already defined,
|
||||
; further passes, the symbol is already defined,
|
||||
; therefore the file will be skipped.
|
||||
|
||||
; if the following code gets included several times,
|
||||
@ -358,32 +358,32 @@ Examples: ; this was taken from <6502/std.a>:
|
||||
}
|
||||
|
||||
|
||||
Call: !for LABEL, START, END { BLOCK }
|
||||
Call: !for SYMBOL, START, END { BLOCK }
|
||||
Purpose: Looping assembly. The block of statements will be
|
||||
parsed a fixed number of times, as specified by the
|
||||
values of START and END. For a more flexible
|
||||
possibility, have a look at "!do" below.
|
||||
Parameters: LABEL: Any valid label name.
|
||||
Parameters: SYMBOL: Any valid symbol name.
|
||||
START: Any formula the value parser accepts, but it
|
||||
must be solvable even in the first pass. LABEL will
|
||||
must be solvable even in the first pass. SYMBOL will
|
||||
have this value during the first loop cycle.
|
||||
END: Any formula the value parser accepts, but it must
|
||||
be solvable even in the first pass. LABEL will have
|
||||
be solvable even in the first pass. SYMBOL will have
|
||||
this value during the last loop cycle.
|
||||
BLOCK: A block of assembler statements.
|
||||
If START or END are floats, they will be converted to
|
||||
integers (never use floats for loop counters). If
|
||||
START is less than or equal to END, LABEL will get
|
||||
START is less than or equal to END, SYMBOL will get
|
||||
incremented at the end of each cycle; if START is
|
||||
greater than END, LABEL will get decremented at the
|
||||
end of each cycle. So after leaving the loop, LABEL
|
||||
greater than END, SYMBOL will get decremented at the
|
||||
end of each cycle. So after leaving the loop, SYMBOL
|
||||
will have an "illegal" value (END + 1 if counting up,
|
||||
END - 1 if counting down).
|
||||
Please note that it is impossible to change the number
|
||||
of loop cycles "inside" the loop by fiddling with the
|
||||
counter using the "!set" pseudo opcode: The "!for"
|
||||
routine keeps its own copy of the counter value and
|
||||
only sets the label value, it never reads it back.
|
||||
only sets the symbol value, it never reads it back.
|
||||
This was done to eliminate a possibility to hang ACME.
|
||||
Examples:
|
||||
int2BCD ; conversion table: integer to BCD
|
||||
@ -409,7 +409,7 @@ Examples:
|
||||
sta $0400 + i
|
||||
}
|
||||
|
||||
Miscellaneous: The old syntax ("!for LABEL, END { BLOCK }" where
|
||||
Miscellaneous: The old syntax ("!for SYMBOL, END { BLOCK }" where
|
||||
START was always implied to be 1) is still fully
|
||||
supported, but gives a warning to get people to change
|
||||
to the new syntax. You can disable this warning using
|
||||
@ -418,19 +418,19 @@ Miscellaneous: The old syntax ("!for LABEL, END { BLOCK }" where
|
||||
When migrating your sources, bear in mind that it is
|
||||
no longer possible to skip the block completely by
|
||||
specifying a loop count of zero.
|
||||
Also note that with the new algorithm, LABEL has a
|
||||
Also note that with the new algorithm, SYMBOL has a
|
||||
different value after the block than during the last
|
||||
loop cycle, while the old algorithm kept that last
|
||||
value.
|
||||
|
||||
|
||||
Call: !set LABEL = VALUE
|
||||
Purpose: Assign given value to label even if the label already
|
||||
has a different value. Needed for loop counters when
|
||||
using "!do", for example. Only use this opcode for
|
||||
something else if you're sure you *really* know what
|
||||
you are doing... :)
|
||||
Parameters: LABEL: Any valid label name.
|
||||
Call: !set SYMBOL = VALUE
|
||||
Purpose: Assign given value to symbol even if the symbol
|
||||
already has a different value. Needed for loop
|
||||
counters when using "!do", for example. Only use this
|
||||
opcode for something else if you're sure you *really*
|
||||
know what you are doing... :)
|
||||
Parameters: SYMBOL: Any valid symbol name.
|
||||
VALUE: Any formula the value parser accepts.
|
||||
Example: see "!do" below
|
||||
|
||||
@ -523,20 +523,20 @@ Example: !source "part1.a" ; sets part1_version
|
||||
Section: Macro usage
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Call: !macro TITLE [[~]LABEL [, [~]LABEL]*] { BLOCK }
|
||||
Call: !macro TITLE [[~]SYMBOL [, [~]SYMBOL]*] { BLOCK }
|
||||
Purpose: Define a macro.
|
||||
Parameters: TITLE: The macro's desired name (same rules as for
|
||||
label names). If the title's first character is a dot
|
||||
symbol names). If the title's first character is a dot
|
||||
("."), the macro will be local (though why anyone
|
||||
could want this is beyond me).
|
||||
LABEL: The desired name for the parameter value at
|
||||
call time. Normally, these parameter labels should be
|
||||
SYMBOL: The desired name for the parameter value at
|
||||
call time. Normally, these parameter symbols should be
|
||||
local (first character a dot), as different macro
|
||||
calls will almost for sure have different parameter
|
||||
values.
|
||||
If you prefix LABEL 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
|
||||
inside the macro will result in the "outer" label to
|
||||
inside the macro will result in the "outer" symbol to
|
||||
be changed as well.
|
||||
BLOCK: A block of assembler statements.
|
||||
Examples: ; far branch, as defined in <6502/std.a>
|
||||
@ -586,10 +586,10 @@ Purpose: Call a macro, using the given parameter values.
|
||||
Parameters: TITLE: The macro's name as given in its definition.
|
||||
ARGUMENT: This is either any formula the value parser
|
||||
accepts, or (new in release 0.86) a '~' character
|
||||
followed by a label name. The '~'-prefix indicates
|
||||
followed by a symbol name. The '~'-prefix indicates
|
||||
call-by-reference semantics, which means that when the
|
||||
macro changes the label's value, the caller's label's
|
||||
value will change as well.
|
||||
macro changes the symbol's value, the caller's
|
||||
symbol's value will change as well.
|
||||
Examples: inc label
|
||||
bne mark ; "near" branch
|
||||
inc label2
|
||||
@ -819,15 +819,15 @@ Section: Type system
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Call: !address [ { BLOCK } ]
|
||||
or: !address LABEL = VALUE
|
||||
or: !address SYMBOL = VALUE
|
||||
Purpose: Mark a block or a statement as "explicitly defined
|
||||
labels are holding addresses".
|
||||
symbols are holding addresses".
|
||||
Parameters: BLOCK: A block of assembler statements
|
||||
Everything inside the block will be parsed as usual,
|
||||
but labels getting explicitly defined will be marked
|
||||
as referencing memory.
|
||||
but explicitly defined symbols will be marked as
|
||||
referencing memory.
|
||||
If no block is given, only the current statement will
|
||||
be affected, which should then be an explicit label
|
||||
be affected, which should then be an explicit symbol
|
||||
definition.
|
||||
Aliases: "!addr"
|
||||
Examples: !addr k_chrout = $ffd2 ; this is an address
|
||||
|
@ -12,6 +12,18 @@ platform used. There should be another help file in this archive
|
||||
outlining the platform specific changes.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: New in release 0.95.1
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Fixed a bug: Anonymous forward labels were allowed to be redefined.
|
||||
Tweaked type system: When negating a value, address reference count
|
||||
will now be negated as well.
|
||||
When using type system, label dump file will now contain "!addr" to
|
||||
mark addresses.
|
||||
Changed "label" to "symbol" in a lot of code, error messages and docs.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: New in release 0.95
|
||||
----------------------------------------------------------------------
|
||||
|
@ -55,6 +55,13 @@ Bug in ACME, code follows
|
||||
C-style "==" comparison detected.
|
||||
To check for equality, use a single '=' character instead.
|
||||
|
||||
Converted to integer for binary logic operator.
|
||||
Applying binary logic to float values does not make much sense,
|
||||
therefore floats will be converted to integer in this case.
|
||||
|
||||
"EOR" is deprecated; use "XOR" instead.
|
||||
This means the operator, not the mnemonic.
|
||||
|
||||
Found old "!for" syntax.
|
||||
Please update your sources to use the new "!for" syntax. See
|
||||
AllPOs.txt for details.
|
||||
@ -64,23 +71,23 @@ Found new "!for" syntax.
|
||||
When using the "-Wno-old-for" switch to disable the warning about
|
||||
the older syntax, the new syntax will trigger this warning.
|
||||
|
||||
Implicit label definition not in leftmost column.
|
||||
An implicit label definition has blanks before the label name.
|
||||
Label dump file already chosen.
|
||||
The "!sl" command was given more than once (or in addition to the
|
||||
"--labeldump" command line option). Only use it once.
|
||||
|
||||
Label name not in leftmost column.
|
||||
A label definition has blanks before the label name.
|
||||
Imagine this source code:
|
||||
lda #00
|
||||
imx
|
||||
rts
|
||||
Obviously, there's a typo in the middle line (imx instead of inx),
|
||||
but ACME does not recognize this: It looks just like an implicit
|
||||
label definition! Therefore releases 0.89 and higher warn you when
|
||||
an implicit label does not start in column 1. Releases 0.94 and
|
||||
higher support a command line option to switch off this warning
|
||||
but ACME does not recognize this: It looks just like a label
|
||||
definition! Therefore releases 0.89 and higher warn you when a
|
||||
label name does not start in column 1. Releases 0.94 and higher
|
||||
support a command line option to switch off this warning
|
||||
("-Wno-label-indent").
|
||||
|
||||
Label dump file already chosen.
|
||||
The "!sl" command was given more than once (or in addition to the
|
||||
"--labeldump" command line option). Only use it once.
|
||||
|
||||
Label name starts with a shift-space character.
|
||||
The name of a global label starts with a shift-space character. It
|
||||
is highly likely that this is a typing error, therefore this
|
||||
@ -122,7 +129,7 @@ Using oversized addressing mode.
|
||||
the argument's value in the first pass, therefore assuming a 16-
|
||||
bit addressing mode. If, in a later pass, ACME finds out that the
|
||||
argument is small enough to fit in 8 bits, then this warning is
|
||||
shown. If you define all your zeropage labels *before* they are
|
||||
shown. If you define all your zeropage symbols *before* they are
|
||||
first used, this shouldn't happen. If you know that a specific
|
||||
argument fits in 8 bits, you can force ACME to use 8 bits
|
||||
addressing by postfixing the command with "+1". Example:
|
||||
@ -202,10 +209,6 @@ Illegal combination of command and postfix.
|
||||
Illegal postfix.
|
||||
You used a postfix other than "+1", "+2" or "+3".
|
||||
|
||||
Label already defined.
|
||||
You defined a label that already had a different value. To change
|
||||
a label's value, use the "!set" pseudo opcode.
|
||||
|
||||
Macro already defined.
|
||||
Macros can only be defined once. If you define a macro twice, ACME
|
||||
will help you find the definitions by giving a warning for the
|
||||
@ -219,7 +222,7 @@ Macro not defined (or wrong signature).
|
||||
formal parameters and the call's actual arguments.
|
||||
|
||||
Macro parameter twice.
|
||||
The same label name is used two (or more) times in the same macro
|
||||
The same symbol name is used two (or more) times in the same macro
|
||||
parameter list.
|
||||
|
||||
Negative value - cannot choose addressing mode.
|
||||
@ -244,6 +247,10 @@ Quotes still open at end of line.
|
||||
Source file contains illegal character.
|
||||
Your source code file contained a null byte.
|
||||
|
||||
Symbol already defined.
|
||||
You defined a symbol that already had a different value. To change
|
||||
a symbol's value, use the "!set" pseudo opcode.
|
||||
|
||||
Syntax error.
|
||||
Guess what - there's a syntax error.
|
||||
|
||||
@ -263,7 +270,7 @@ There's more than one character.
|
||||
contained more than a single character.
|
||||
|
||||
Too late for postfix.
|
||||
You can only postfix labels at the start, before they are used for
|
||||
You can only postfix symbols at the start, before they are used for
|
||||
the first time.
|
||||
|
||||
Too many '('.
|
||||
@ -291,7 +298,7 @@ Unknown "* =" segment modifier.
|
||||
You used a modifier keyword ACME does not know.
|
||||
|
||||
Value not yet defined.
|
||||
A value could not be worked out. Maybe you mistyped a label 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
|
||||
on the currently parsed pseudo opcode.
|
||||
|
||||
@ -346,7 +353,7 @@ Too deeply nested. Recursive "!source"?
|
||||
64.
|
||||
|
||||
Value not yet defined.
|
||||
A value could not be worked out. Maybe you mistyped a label 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
|
||||
on the currently parsed pseudo opcode.
|
||||
|
||||
|
@ -98,8 +98,8 @@ ACME's maths parser has no problems concerning parentheses and
|
||||
indirect addressing modes.
|
||||
ACME's maths parser knows a shit load of different operations.
|
||||
ACME supports both integer and floating point maths operations.
|
||||
You can dump the global labels into a file.
|
||||
ACME supports a library of commonly used macros and labels.
|
||||
You can dump the global symbols into a file.
|
||||
ACME supports a library of commonly used macros and symbols.
|
||||
It always takes as many passes as are needed.
|
||||
ACME exists on several platforms, meaning you can easily exchange your
|
||||
sources with other people (preferring other OSes).
|
||||
@ -152,7 +152,7 @@ A minor problem is the different character tables used on different
|
||||
systems. As all predefined ACME keywords only use 7-bit ASCII, the
|
||||
assembler will work on any system that uses a superset of this
|
||||
character table: UTF-8, ANSI, ISO 8859, etc.
|
||||
Label names can contain top-bit-set characters - these may look
|
||||
Symbol names can contain top-bit-set characters - these may look
|
||||
strange if the sources are edited on a different platform, but ACME
|
||||
will still work.
|
||||
|
||||
|
@ -21,7 +21,7 @@ Section: Example of what an ACME source code file looks like
|
||||
!to "tiny.o", cbm ; set output file and format
|
||||
* = $c000 ; set program counter
|
||||
|
||||
CLEAR = 147 ; a global label definition
|
||||
CLEAR = 147 ; a global symbol definition
|
||||
!addr basout = $ffd2 ; another one, marked as an address
|
||||
|
||||
; a string output loop:
|
||||
@ -49,11 +49,11 @@ Here's the same fragment again, now with some additional info:
|
||||
* = $c000 ; set program counter
|
||||
; This can also be done using the command line option "--setpc".
|
||||
|
||||
; some global label definitions
|
||||
; some global symbol definitions
|
||||
CLEAR = 147 ; this is a simple constant
|
||||
; Now "CLEAR" is defined as a global label having the value 147.
|
||||
; Now "CLEAR" is defined as a global symbol having the value 147.
|
||||
!addr basout = $ffd2 ; this gets marked as an address
|
||||
; Now "basout" is defined as a global "address" type label having the
|
||||
; Now "basout" is defined as a global "address" type symbol having the
|
||||
; value $ffd2.
|
||||
; The distinction between addresses and non-addresses only
|
||||
; matters when the type check system gets activated using
|
||||
@ -65,20 +65,20 @@ Here's the same fragment again, now with some additional info:
|
||||
ldx #0
|
||||
beq + ; enter loop
|
||||
; "+" is an anonymous forward label. Other ones are "++", "+++", etc.
|
||||
; They can be used like any other label, but they always reference
|
||||
; They can be used like any other symbol, but they always reference
|
||||
; their *NEXT* definition. This saves having to think of names for
|
||||
; unimportant labels. As the label's value is not defined yet, ACME
|
||||
; will need to perform a second pass.
|
||||
- jsr basout ; output character
|
||||
; "-" is an anonymous backward label. Other ones are "--", "---", etc.
|
||||
; They can be used like any other label, but they always reference
|
||||
; They can be used like any other symbol, but they always reference
|
||||
; their *PREVIOUS* definition. This saves having to think of names for
|
||||
; unimportant labels. In the line above, the value of "-" is set to
|
||||
; the current program counter.
|
||||
inx ; advance pointer
|
||||
+ lda .string,x ; get character
|
||||
; Here the value of "+" is set to the current program counter.
|
||||
; ".string" is a local label (because its name starts with a '.'
|
||||
; ".string" is a local symbol (because its name starts with a '.'
|
||||
; character), but as its value is not defined yet, ACME will need to
|
||||
; perform a second pass.
|
||||
bne - ; check whether last
|
||||
@ -97,12 +97,12 @@ As you can see, pseudo opcodes are prefixed with an exclamation mark.
|
||||
That's non-standard, but: Backwards compatibility is the root of all
|
||||
evil. :)
|
||||
|
||||
Summary about labels:
|
||||
Summary about symbols:
|
||||
|
||||
There are global labels (their names starting with a letter or an
|
||||
There are global symbols (their names starting with a letter or an
|
||||
underscore character). These can be accessed throughout the whole
|
||||
assembly.
|
||||
Then there are local labels (their names starting with a '.'
|
||||
Then there are local symbols (their names starting with a '.'
|
||||
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
|
||||
"AllPOs.txt").
|
||||
@ -112,7 +112,7 @@ macro/zone), but in addition to that, the "-" labels can only be used
|
||||
for backward references, while the "+" labels can only be used for
|
||||
forward references.
|
||||
In contrast to global and local labels, anonymous labels can not be
|
||||
defined explicitly (as in LABEL = VALUE).
|
||||
defined explicitly (as in SYMBOL = VALUE).
|
||||
|
||||
Save the given example source code to a file called "tiny.a" and start
|
||||
acme by typing
|
||||
@ -144,7 +144,7 @@ found in the file "AllPOs.txt". Here's just a short overview:
|
||||
...for directly placing values into the output file.
|
||||
|
||||
!zone !sl
|
||||
...for defining the scope of local labels and saving global labels.
|
||||
...for defining the scope of local symbols and saving global symbols.
|
||||
|
||||
!convtab !pet !raw !scr !scrxor !text
|
||||
...for converting and outputting strings.
|
||||
@ -171,7 +171,7 @@ found in the file "AllPOs.txt". Here's just a short overview:
|
||||
...for generating warnings, errors and serious errors.
|
||||
|
||||
!addr
|
||||
...to mark labels as addresses, for the optional type check system.
|
||||
...to mark symbols as addresses, for the optional type check system.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
@ -231,7 +231,7 @@ Available options are:
|
||||
In addition to the "-v2" output, ACME will now announce
|
||||
each source file.
|
||||
|
||||
-DLABEL=VALUE define global label
|
||||
-DSYMBOL=VALUE define global symbol
|
||||
This option is useful if you build your projects using
|
||||
Makefiles: "-DSYSTEM=64" could build the C64 version while
|
||||
"-DSYSTEM=128" could build the C128 version of the software
|
||||
@ -239,8 +239,8 @@ Available options are:
|
||||
|
||||
-W fine-tune amount and type of warnings
|
||||
-Wno-label-indent
|
||||
Disables warnings about implicit label definitions not
|
||||
being in the leftmost column.
|
||||
Disables warnings about labels not being in the leftmost
|
||||
column.
|
||||
-Wno-old-for
|
||||
Disables warnings about the old "!for" syntax and at the
|
||||
same time enables warnings about the _new_ "!for" syntax.
|
||||
@ -269,8 +269,8 @@ shifts, negation, boolean operations and some assembler-specific stuff
|
||||
like extracting the "low byte", the "high byte" or the "bank byte"
|
||||
of a value.
|
||||
Calculations are done using either signed 32-bit integer arithmetic or
|
||||
floating point arithmetic using the C "double" data type. Label values
|
||||
are stored the same way.
|
||||
floating point arithmetic using the C "double" data type. Symbol
|
||||
values are stored the same way.
|
||||
|
||||
This is a list of the operators currently known by ACME:
|
||||
|
||||
@ -350,8 +350,8 @@ $d011 hexadecimal values are indicated by either a
|
||||
'q' quotes. The actual numeric value depends on the
|
||||
current conversion table (none/petscii/screen),
|
||||
chosen using the "!ct" pseudo opcode.
|
||||
poll_joy2 a global label
|
||||
.fail a local label, indicated by leading dot
|
||||
poll_joy2 a global symbol
|
||||
.fail a local symbol, indicated by leading dot
|
||||
* the current program counter. During offset assembly,
|
||||
"*" gives the value of the "Pseudo PC". Just to
|
||||
make sure: The value of the program counter is
|
||||
@ -376,24 +376,23 @@ optional comment. Statements have to be separated from each other
|
||||
using colon (":") characters, the comment has to be prefixed with a
|
||||
semicolon (";") character.
|
||||
|
||||
Every statement consists of an optional "implicit label definition"
|
||||
and an optional "command". These are separated from each other using
|
||||
any number of SPACE or TAB characters. If an implicit label definition
|
||||
has blanks before it, a warning is given (to spot typing errors - see
|
||||
Errors.txt for more info).
|
||||
Every statement consists of an optional "label" and an optional
|
||||
"command". These are separated from each other using any number of
|
||||
SPACE or TAB characters. If a label has blanks before it, a warning is
|
||||
issued (to spot typing errors - see Errors.txt for more info).
|
||||
|
||||
Every label consists of these characters: "a" to "z", "A" to "Z", "0"
|
||||
to "9", the underscore character "_" and all characters with values
|
||||
beyond 127. The first character must not be a digit though. But it can
|
||||
be a dot ("."), making the label a local one. Two other possibilities
|
||||
for label names are "all-characters-are-minus" (then it's an anonymous
|
||||
backward label) and "all-characters-are-plus" (then it's an anonymous
|
||||
forward label).
|
||||
Every symbol name consists of these characters: "a" to "z", "A" to
|
||||
"Z", "0" to "9", the underscore character "_" and all characters with
|
||||
values beyond 127. The first character must not be a digit though. But
|
||||
it can be a dot ("."), making the symbol a local one. Two other
|
||||
possibilities for label names are "all-characters-are-minus" (then it
|
||||
is an anonymous backward label) and "all-characters-are-plus" (then it
|
||||
is an anonymous forward label).
|
||||
|
||||
Every command is one of the following:
|
||||
An assembler opcode
|
||||
A pseudo opcode, beginning with a "!" character
|
||||
An explicit label definition (label=value)
|
||||
A symbol definition (symbol=value)
|
||||
A pc definition, beginning with a "*" character
|
||||
A macro call, beginning with a "+" character
|
||||
...and the syntax of those things varies. :)
|
||||
@ -404,5 +403,5 @@ whether you write "LDA" or "lda" or "LdA" does not make a difference.
|
||||
In earlier releases of ACME, arithmetic operators like MOD, XOR, LSL
|
||||
had to be written in UPPER CASE. This is no longer needed.
|
||||
|
||||
Label names are case sensitive, so "label" and "Label" are two
|
||||
Symbol names are case sensitive, so "label" and "Label" are two
|
||||
different things.
|
||||
|
18
src/Makefile
18
src/Makefile
@ -8,7 +8,7 @@ RM = rm
|
||||
PROGS = acme
|
||||
BINDIR = /usr/local/bin
|
||||
USERBIN = $(HOME)/bin
|
||||
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o
|
||||
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
@ -17,9 +17,9 @@ acme: $(OBJS)
|
||||
strip acme
|
||||
|
||||
|
||||
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h label.h macro.h mnemo.h output.h section.h acme.h acme.c
|
||||
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h acme.c
|
||||
|
||||
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h label.h section.h tree.h alu.h alu.c
|
||||
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c
|
||||
|
||||
cliargs.o: cliargs.h cliargs.c
|
||||
|
||||
@ -29,15 +29,13 @@ dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
|
||||
|
||||
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
|
||||
|
||||
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h macro.h mnemo.h tree.h flow.h flow.c
|
||||
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h tree.h symbol.h flow.h flow.c
|
||||
|
||||
global.o: config.h platform.h acme.h cpu.h input.h label.h macro.h section.h global.h global.c
|
||||
global.o: config.h platform.h acme.h cpu.h input.h macro.h section.h symbol.h global.h global.c
|
||||
|
||||
input.o: config.h dynabuf.h global.h section.h tree.h input.h input.c
|
||||
|
||||
label.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h label.h label.c
|
||||
|
||||
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h section.h tree.h macro.h macro.c
|
||||
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c
|
||||
|
||||
mnemo.o: config.h alu.h cpu.h dynabuf.h global.h input.h output.h tree.h mnemo.h mnemo.c
|
||||
|
||||
@ -47,7 +45,9 @@ platform.o: config.h platform.h platform.c
|
||||
|
||||
section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
|
||||
|
||||
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
|
||||
symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h symbol.h symbol.c
|
||||
|
||||
tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c
|
||||
|
||||
typesystem.o: config.h global.h typesystem.h typesystem.c
|
||||
|
||||
|
@ -8,7 +8,7 @@ RM = rm
|
||||
PROGS = acme
|
||||
#BINDIR = /usr/local/bin
|
||||
#USERBIN = $(HOME)/bin
|
||||
OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o
|
||||
OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
@ -18,9 +18,9 @@ acme: $(OBJS)
|
||||
djp acme.exe
|
||||
djp acmepmod.exe
|
||||
|
||||
acme.o: config.h platform.h acme.h alu.h cpu.h dynabuf.h encoding.h flow.h global.h input.h label.h macro.h mnemo.h output.h section.h acme.h acme.c
|
||||
acme.o: config.h platform.h acme.h alu.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h acme.c
|
||||
|
||||
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h label.h section.h tree.h alu.h alu.c
|
||||
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c
|
||||
|
||||
cliargs.o: cliargs.h cliargs.c
|
||||
|
||||
@ -30,15 +30,13 @@ dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
|
||||
|
||||
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
|
||||
|
||||
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h macro.h mnemo.h tree.h flow.h flow.c
|
||||
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c
|
||||
|
||||
global.o: config.h platform.h acme.h cpu.h input.h label.h macro.h section.h global.h global.c
|
||||
global.o: config.h platform.h acme.h cpu.h input.h macro.h section.h symbol.h global.h global.c
|
||||
|
||||
input.o: config.h dynabuf.h global.h section.h tree.h input.h input.c
|
||||
|
||||
label.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h label.h label.c
|
||||
|
||||
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h section.h tree.h macro.h macro.c
|
||||
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c
|
||||
|
||||
mnemo.o: config.h alu.h cpu.h dynabuf.h global.h input.h output.h tree.h mnemo.h mnemo.c
|
||||
|
||||
@ -48,7 +46,9 @@ platform.o: config.h platform.h platform.c
|
||||
|
||||
section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
|
||||
|
||||
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
|
||||
symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h symbol.h symbol.c
|
||||
|
||||
tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c
|
||||
|
||||
typesystem.o: config.h global.h typesystem.h typesystem.c
|
||||
|
||||
|
@ -15,15 +15,15 @@ USERBIN = $(HOME)/bin
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
acme.exe: acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o_dos.o resource.res
|
||||
$(CC) $(LIBS) $(CFLAGS) -o acme acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o resource.res
|
||||
acme.exe: acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o_dos.o resource.res
|
||||
$(CC) $(LIBS) $(CFLAGS) -o acme acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o resource.res
|
||||
strip acme.exe
|
||||
|
||||
|
||||
|
||||
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h label.h macro.h mnemo.h output.h section.h acme.h _dos.h acme.c
|
||||
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h _dos.h acme.c
|
||||
|
||||
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h label.h section.h tree.h alu.h alu.c
|
||||
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c
|
||||
|
||||
cliargs.o: cliargs.h cliargs.c
|
||||
|
||||
@ -33,15 +33,13 @@ dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
|
||||
|
||||
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
|
||||
|
||||
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h macro.h mnemo.h tree.h flow.h flow.c
|
||||
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c
|
||||
|
||||
global.o: config.h platform.h acme.h cpu.h input.h label.h macro.h section.h global.h global.c
|
||||
global.o: config.h platform.h acme.h cpu.h input.h macro.h section.h symbol.h global.h global.c
|
||||
|
||||
input.o: config.h dynabuf.h global.h section.h tree.h input.h input.c
|
||||
|
||||
label.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h label.h label.c
|
||||
|
||||
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h section.h tree.h macro.h macro.c
|
||||
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c
|
||||
|
||||
mnemo.o: config.h alu.h cpu.h dynabuf.h global.h input.h output.h tree.h mnemo.h mnemo.c
|
||||
|
||||
@ -51,7 +49,9 @@ platform.o: config.h platform.h platform.c
|
||||
|
||||
section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
|
||||
|
||||
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
|
||||
symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h mnemo.h section.h tree.h symbol.h symbol.c
|
||||
|
||||
tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c
|
||||
|
||||
typesystem.o: config.h global.h typesystem.h typesystem.c
|
||||
|
||||
|
@ -8,7 +8,7 @@ RM = rm
|
||||
PROGS = acme
|
||||
#BINDIR = /usr/local/bin
|
||||
#USERBIN = $(HOME)/bin
|
||||
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o
|
||||
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o macro.o mnemo.o output.o platform.o section.o symbol.o tree.o typesystem.o
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
@ -16,9 +16,9 @@ acme: $(OBJS)
|
||||
$(CC) $(CFLAGS) -o !Unsqueezed $(OBJS) $(LIBS)
|
||||
Squeeze -f -v !Unsqueezed !ACME.!RunImage
|
||||
|
||||
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h label.h macro.h mnemo.h output.h section.h acme.h acme.c
|
||||
acme.o: config.h platform.h acme.h alu.h basics.h cpu.h dynabuf.h encoding.h flow.h global.h input.h macro.h mnemo.h output.h section.h symbol.h acme.h acme.c
|
||||
|
||||
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h label.h section.h tree.h alu.h alu.c
|
||||
alu.o: config.h platform.h cpu.h dynabuf.h encoding.h global.h input.h section.h symbol.h tree.h alu.h alu.c
|
||||
|
||||
basics.o: config.h alu.h cpu.h dynabuf.h input.h global.h output.h tree.h basics.h basics.c
|
||||
|
||||
@ -30,15 +30,13 @@ dynabuf.o: config.h acme.h global.h input.h dynabuf.h dynabuf.c
|
||||
|
||||
encoding.o: config.h alu.h acme.h dynabuf.h global.h output.h input.h tree.h encoding.h encoding.c
|
||||
|
||||
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h macro.h mnemo.h tree.h flow.h flow.c
|
||||
flow.o: config.h acme.h alu.h dynabuf.h global.h input.h macro.h mnemo.h symbol.h tree.h flow.h flow.c
|
||||
|
||||
global.o: config.h platform.h acme.h cpu.h input.h label.h macro.h output.h section.h tree.h global.h global.c
|
||||
global.o: config.h platform.h acme.h cpu.h input.h macro.h output.h section.h symbol.h tree.h global.h global.c
|
||||
|
||||
input.o: config.h alu.h dynabuf.h global.h section.h tree.h input.h input.c
|
||||
|
||||
label.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h section.h tree.h label.h label.c
|
||||
|
||||
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h label.h section.h tree.h macro.h macro.c
|
||||
macro.o: config.h acme.h alu.h dynabuf.h global.h input.h section.h symbol.h tree.h macro.h macro.c
|
||||
|
||||
mnemo.o: config.h alu.h cpu.h dynabuf.h global.h input.h output.h tree.h mnemo.h mnemo.c
|
||||
|
||||
@ -48,7 +46,9 @@ platform.o: config.h platform.h platform.c
|
||||
|
||||
section.o: config.h dynabuf.h global.h section.h tree.h section.h section.c
|
||||
|
||||
tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
|
||||
symbol.o: config.h acme.h alu.h cpu.h dynabuf.h global.h input.h section.h tree.h symbol.h symbol.c
|
||||
|
||||
tree.o: config.h dynabuf.h global.h symbol.h tree.h tree.c
|
||||
|
||||
typesystem.o: config.h global.h typesystem.h typesystem.c
|
||||
|
||||
|
38
src/acme.c
38
src/acme.c
@ -15,9 +15,9 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
#define RELEASE "0.95" // update before release (FIXME)
|
||||
#define RELEASE "0.95.1" // update before release (FIXME)
|
||||
#define CODENAME "Fenchurch" // update before release
|
||||
#define CHANGE_DATE "2 Jun" // update before release
|
||||
#define CHANGE_DATE "7 Jun" // update before release
|
||||
#define CHANGE_YEAR "2014" // update before release
|
||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" // FIXME
|
||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||
@ -36,12 +36,12 @@
|
||||
#include "flow.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "label.h"
|
||||
#include "macro.h"
|
||||
#include "mnemo.h"
|
||||
#include "output.h"
|
||||
#include "platform.h"
|
||||
#include "section.h"
|
||||
#include "symbol.h"
|
||||
|
||||
|
||||
// constants
|
||||
@ -75,7 +75,7 @@ static int toplevel_src_count = 0;
|
||||
static signed long start_address = ILLEGAL_START_ADDRESS;
|
||||
static signed long fill_value = MEMINIT_USE_DEFAULT;
|
||||
static const struct cpu_type *default_cpu = NULL;
|
||||
const char *labeldump_filename = NULL;
|
||||
const char *symboldump_filename = NULL;
|
||||
const char *output_filename = NULL;
|
||||
// maximum recursion depth for macro calls and "!source"
|
||||
signed long macro_recursions_left = MAX_NESTING;
|
||||
@ -124,7 +124,7 @@ static void show_help_and_exit(void)
|
||||
" --" OPTION_MAXERRORS " NUMBER set number of errors before exiting\n"
|
||||
" --" OPTION_MAXDEPTH " NUMBER set recursion depth for macro calls and !src\n"
|
||||
" -vDIGIT set verbosity level\n"
|
||||
" -DLABEL=VALUE define global label\n"
|
||||
" -DSYMBOL=VALUE define global symbol\n"
|
||||
// as long as there is only one -W option:
|
||||
#define OPTIONWNO_LABEL_INDENT "no-label-indent"
|
||||
" -W" OPTIONWNO_LABEL_INDENT " suppress warnings about indented labels\n"
|
||||
@ -141,20 +141,20 @@ PLATFORM_OPTION_HELP
|
||||
|
||||
// error handling
|
||||
|
||||
// tidy up before exiting by saving label dump
|
||||
// tidy up before exiting by saving symbol dump
|
||||
int ACME_finalize(int exit_code)
|
||||
{
|
||||
FILE *fd;
|
||||
|
||||
if (labeldump_filename) {
|
||||
fd = fopen(labeldump_filename, FILE_WRITETEXT);
|
||||
if (symboldump_filename) {
|
||||
fd = fopen(symboldump_filename, FILE_WRITETEXT);
|
||||
if (fd) {
|
||||
Label_dump_all(fd);
|
||||
symbols_dump_all(fd);
|
||||
fclose(fd);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error: Cannot open label dump file \"%s\".\n",
|
||||
labeldump_filename);
|
||||
symboldump_filename);
|
||||
exit_code = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
@ -344,8 +344,8 @@ static void set_mem_contents(void)
|
||||
}
|
||||
|
||||
|
||||
// define label
|
||||
static void define_label(const char definition[])
|
||||
// define symbol
|
||||
static void define_symbol(const char definition[])
|
||||
{
|
||||
const char *walk = definition;
|
||||
signed long value;
|
||||
@ -358,7 +358,7 @@ static void define_label(const char definition[])
|
||||
could_not_parse(definition);
|
||||
value = string_to_number(walk + 1);
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
Label_define(value);
|
||||
symbol_define(value);
|
||||
}
|
||||
|
||||
|
||||
@ -372,7 +372,7 @@ static const char *long_option(const char *string)
|
||||
else if (strcmp(string, OPTION_OUTFILE) == 0)
|
||||
output_filename = cliargs_safe_get_next(name_outfile);
|
||||
else if (strcmp(string, OPTION_LABELDUMP) == 0)
|
||||
labeldump_filename = cliargs_safe_get_next(name_dumpfile);
|
||||
symboldump_filename = cliargs_safe_get_next(name_dumpfile);
|
||||
else if (strcmp(string, OPTION_SETPC) == 0)
|
||||
set_starting_pc();
|
||||
else if (strcmp(string, OPTION_CPU) == 0)
|
||||
@ -402,7 +402,7 @@ static char short_option(const char *argument)
|
||||
while (*argument) {
|
||||
switch (*argument) {
|
||||
case 'D': // "-D" define constants
|
||||
define_label(argument + 1);
|
||||
define_symbol(argument + 1);
|
||||
goto done;
|
||||
case 'h': // "-h" shows help
|
||||
show_help_and_exit();
|
||||
@ -412,8 +412,8 @@ static char short_option(const char *argument)
|
||||
case 'o': // "-o" selects output filename
|
||||
output_filename = cliargs_safe_get_next(name_outfile);
|
||||
break;
|
||||
case 'l': // "-l" selects label dump filename
|
||||
labeldump_filename = cliargs_safe_get_next(name_dumpfile);
|
||||
case 'l': // "-l" selects symbol dump filename
|
||||
symboldump_filename = cliargs_safe_get_next(name_dumpfile);
|
||||
break;
|
||||
case 'v': // "-v" changes verbosity
|
||||
Process_verbosity++;
|
||||
@ -465,7 +465,7 @@ int main(int argc, const char *argv[])
|
||||
PLATFORM_INIT;
|
||||
// init some keyword trees needed for argument handling
|
||||
CPUtype_init();
|
||||
Label_clear_init(); // needed so
|
||||
symbols_clear_init(); // needed so
|
||||
Outputfile_init();
|
||||
// prepare a buffer large enough to hold pointers to "-D" switch values
|
||||
// cli_defines = safe_malloc(argc * sizeof(*cli_defines));
|
||||
@ -481,7 +481,7 @@ int main(int argc, const char *argv[])
|
||||
Encoding_init();
|
||||
Flow_init();
|
||||
Input_init();
|
||||
Label_register_init();
|
||||
symbols_register_init();
|
||||
Macro_init();
|
||||
Mnemo_init();
|
||||
Output_init(fill_value);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816 code.
|
||||
// Copyright (C) 1998-2009 Marco Baye
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Main definitions
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
|
||||
// Variables
|
||||
extern const char *labeldump_filename;
|
||||
extern const char *symboldump_filename;
|
||||
extern const char *output_filename;
|
||||
// maximum recursion depth for macro calls and "!source"
|
||||
extern signed long macro_recursions_left;
|
||||
@ -20,7 +20,7 @@ extern signed long source_recursions_left;
|
||||
|
||||
// Prototypes
|
||||
|
||||
// Tidy up before exiting by saving label dump
|
||||
// tidy up before exiting by saving symbol dump
|
||||
extern int ACME_finalize(int exit_code);
|
||||
|
||||
|
||||
|
71
src/alu.c
71
src/alu.c
@ -19,9 +19,9 @@
|
||||
#include "encoding.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "label.h"
|
||||
#include "output.h"
|
||||
#include "section.h"
|
||||
#include "symbol.h"
|
||||
#include "tree.h"
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ static struct dynabuf *function_dyna_buf; // dynamic buffer for fn names
|
||||
static struct operator **operator_stack = NULL;
|
||||
static int operator_stk_size = HALF_INITIAL_STACK_SIZE;
|
||||
static int operator_sp; // operator stack pointer
|
||||
static struct result_t *operand_stack = NULL; // flags and value
|
||||
static struct result *operand_stack = NULL; // flags and value
|
||||
static int operand_stk_size = HALF_INITIAL_STACK_SIZE;
|
||||
static int operand_sp; // value stack pointer
|
||||
static int indirect_flag; // Flag for indirect addressing
|
||||
@ -313,21 +313,21 @@ static intval_t my_asr(intval_t left, intval_t right)
|
||||
}
|
||||
|
||||
|
||||
// Lookup (and create, if necessary) label tree item and return its value.
|
||||
// DynaBuf holds the label's name and "zone" its zone.
|
||||
// Lookup (and create, if necessary) symbol tree item and return its value.
|
||||
// DynaBuf holds the symbol's name and "zone" its zone.
|
||||
// This function is not allowed to change DynaBuf because that's where the
|
||||
// label name is stored!
|
||||
static void get_label_value(zone_t zone)
|
||||
// symbol name is stored!
|
||||
static void get_symbol_value(zone_t zone)
|
||||
{
|
||||
struct label *label;
|
||||
struct symbol *symbol;
|
||||
|
||||
// if the label gets created now, mark it as unsure
|
||||
label = Label_find(zone, MVALUE_UNSURE);
|
||||
// if the symbol gets created now, mark it as unsure
|
||||
symbol = symbol_find(zone, MVALUE_UNSURE);
|
||||
// in first pass, count usage
|
||||
if (pass_count == 0)
|
||||
label->usage++;
|
||||
symbol->usage++;
|
||||
// push operand, regardless of whether int or float
|
||||
operand_stack[operand_sp] = label->result;
|
||||
operand_stack[operand_sp] = symbol->result;
|
||||
operand_stack[operand_sp++].flags |= MVALUE_EXISTS;
|
||||
}
|
||||
|
||||
@ -542,7 +542,7 @@ static void parse_octal_value(void) // Now GotByte = "&"
|
||||
// Parse program counter ('*')
|
||||
static void parse_program_counter(void) // Now GotByte = "*"
|
||||
{
|
||||
struct result_t pc;
|
||||
struct result pc;
|
||||
|
||||
GetByte();
|
||||
vcpu_read_pc(&pc);
|
||||
@ -579,8 +579,8 @@ static void expect_operand_or_monadic_operator(void)
|
||||
do
|
||||
DYNABUF_APPEND(GlobalDynaBuf, '+');
|
||||
while (GetByte() == '+');
|
||||
Label_fix_forward_name();
|
||||
get_label_value(Section_now->zone);
|
||||
symbol_fix_forward_anon_name(FALSE); // FALSE: do not increment counter
|
||||
get_symbol_value(Section_now->zone);
|
||||
goto now_expect_dyadic;
|
||||
|
||||
case '-': // NEGATION operator or anonymous backward label
|
||||
@ -594,7 +594,7 @@ static void expect_operand_or_monadic_operator(void)
|
||||
SKIPSPACE();
|
||||
if (BYTEFLAGS(GotByte) & FOLLOWS_ANON) {
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
get_label_value(Section_now->zone);
|
||||
get_symbol_value(Section_now->zone);
|
||||
goto now_expect_dyadic;
|
||||
}
|
||||
|
||||
@ -656,7 +656,7 @@ static void expect_operand_or_monadic_operator(void)
|
||||
goto now_expect_dyadic;
|
||||
|
||||
// FIXME - find a way to tell decimal point and LOCAL_PREFIX apart!
|
||||
case '.': // Local label or fractional part of float value
|
||||
case '.': // local symbol or fractional part of float value
|
||||
GetByte(); // start after '.'
|
||||
// check for fractional part of float value
|
||||
if ((GotByte >= '0') && (GotByte <= '9')) {
|
||||
@ -667,13 +667,13 @@ static void expect_operand_or_monadic_operator(void)
|
||||
|
||||
if (Input_read_keyword()) {
|
||||
// Now GotByte = illegal char
|
||||
get_label_value(Section_now->zone);
|
||||
get_symbol_value(Section_now->zone);
|
||||
goto now_expect_dyadic;
|
||||
}
|
||||
|
||||
alu_state = STATE_ERROR;
|
||||
break;
|
||||
// Decimal values and global labels
|
||||
// decimal values and global symbols
|
||||
default: // all other characters
|
||||
if ((GotByte >= '0') && (GotByte <= '9')) {
|
||||
parse_decimal_value();
|
||||
@ -698,7 +698,7 @@ static void expect_operand_or_monadic_operator(void)
|
||||
if (GotByte == '(') {
|
||||
parse_function_call();
|
||||
} else {
|
||||
get_label_value(ZONE_GLOBAL);
|
||||
get_symbol_value(ZONE_GLOBAL);
|
||||
goto now_expect_dyadic;
|
||||
}
|
||||
|
||||
@ -1061,6 +1061,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
else
|
||||
RIGHT_INTVAL = -(RIGHT_INTVAL);
|
||||
RIGHT_FLAGS &= ~MVALUE_ISBYTE;
|
||||
RIGHT_ADDRREFS = -RIGHT_ADDRREFS; // negate address ref count as well
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_LOWBYTEOF:
|
||||
@ -1346,7 +1347,7 @@ RNTLObutDontTouchIndirectFlag:
|
||||
|
||||
// The core of it. Returns number of parentheses left open.
|
||||
// FIXME - make state machine using function pointers? or too slow?
|
||||
static int parse_expression(struct result_t *result)
|
||||
static int parse_expression(struct result *result)
|
||||
{
|
||||
int open_parentheses = 0;
|
||||
|
||||
@ -1427,31 +1428,13 @@ static int parse_expression(struct result_t *result)
|
||||
}
|
||||
|
||||
|
||||
// These functions handle numerical expressions.
|
||||
// There are several different ways to call the core function:
|
||||
// intval_t ALU_any_int(void);
|
||||
// returns int value (0 if result was undefined)
|
||||
// intval_t ALU_defined_int(void);
|
||||
// returns int value
|
||||
// if result was undefined, serious error is thrown
|
||||
// void ALU_int_result(result_int_t*);
|
||||
// stores int value and flags (floats are transformed to int)
|
||||
// void ALU_any_result(result_t*);
|
||||
// stores value and flags (result may be either int or float)
|
||||
// int ALU_liberal_int(result_int_t*);
|
||||
// stores int value and flags. allows one '(' too many (for x-
|
||||
// indirect addressing). returns number of additional '(' (1 or 0).
|
||||
// int ALU_optional_defined_int(intval_t*);
|
||||
// stores int value if given. Returns whether stored.
|
||||
// Throws error if undefined.
|
||||
|
||||
// return int value (if result is undefined, returns zero)
|
||||
// If the result's "exists" flag is clear (=empty expression), it throws an
|
||||
// error.
|
||||
// If the result's "defined" flag is clear, result_is_undefined() is called.
|
||||
intval_t ALU_any_int(void)
|
||||
{
|
||||
struct result_t result;
|
||||
struct result result;
|
||||
|
||||
if (parse_expression(&result))
|
||||
Throw_error(exception_paren_open);
|
||||
@ -1469,7 +1452,7 @@ intval_t ALU_any_int(void)
|
||||
// return int value (if result is undefined, serious error is thrown)
|
||||
intval_t ALU_defined_int(void)
|
||||
{
|
||||
struct result_t result;
|
||||
struct result result;
|
||||
|
||||
if (parse_expression(&result))
|
||||
Throw_error(exception_paren_open);
|
||||
@ -1489,7 +1472,7 @@ intval_t ALU_defined_int(void)
|
||||
// throws a serious error and therefore stops assembly.
|
||||
int ALU_optional_defined_int(intval_t *target)
|
||||
{
|
||||
struct result_t result;
|
||||
struct result result;
|
||||
|
||||
if (parse_expression(&result))
|
||||
Throw_error(exception_paren_open);
|
||||
@ -1510,7 +1493,7 @@ int ALU_optional_defined_int(intval_t *target)
|
||||
// It the result's "exists" flag is clear (=empty expression), it throws an
|
||||
// error.
|
||||
// If the result's "defined" flag is clear, result_is_undefined() is called.
|
||||
void ALU_int_result(struct result_t *intresult)
|
||||
void ALU_int_result(struct result *intresult)
|
||||
{
|
||||
if (parse_expression(intresult))
|
||||
Throw_error(exception_paren_open);
|
||||
@ -1530,7 +1513,7 @@ void ALU_int_result(struct result_t *intresult)
|
||||
// This function allows for one '(' too many. Needed when parsing indirect
|
||||
// addressing modes where internal indices have to be possible. Returns number
|
||||
// of parentheses still open (either 0 or 1).
|
||||
int ALU_liberal_int(struct result_t *intresult)
|
||||
int ALU_liberal_int(struct result *intresult)
|
||||
{
|
||||
int parentheses_still_open;
|
||||
|
||||
@ -1555,7 +1538,7 @@ int ALU_liberal_int(struct result_t *intresult)
|
||||
// It the result's "exists" flag is clear (=empty expression), it throws an
|
||||
// error.
|
||||
// If the result's "defined" flag is clear, result_is_undefined() is called.
|
||||
void ALU_any_result(struct result_t *result)
|
||||
void ALU_any_result(struct result *result)
|
||||
{
|
||||
if (parse_expression(result))
|
||||
Throw_error(exception_paren_open);
|
||||
|
49
src/alu.h
49
src/alu.h
@ -12,31 +12,21 @@
|
||||
|
||||
// constants
|
||||
|
||||
// meaning of bits in "flags" of result_t structure:
|
||||
#define MVALUE_IS_FP (1u << 8)
|
||||
// floating point value
|
||||
#define MVALUE_INDIRECT (1u << 7)
|
||||
// needless parentheses indicate use of indirect addressing modes
|
||||
#define MVALUE_EXISTS (1u << 6)
|
||||
// 0: expression was empty. 1: there was *something* to parse.
|
||||
#define MVALUE_UNSURE (1u << 5)
|
||||
// value once was related to undefined expression. Needed for producing
|
||||
// the same addresses in all passes; because in the first pass there
|
||||
// will almost for sure be labels that are undefined, you can't simply
|
||||
// get the addressing mode from looking at the parameter's value.
|
||||
#define MVALUE_DEFINED (1u << 4)
|
||||
// 0: undefined expression (value will be zero). 1: known result
|
||||
#define MVALUE_ISBYTE (1u << 3)
|
||||
// value is guaranteed to fit in one byte
|
||||
#define MVALUE_FORCE24 (1u << 2)
|
||||
// value usage forces 24-bit usage
|
||||
#define MVALUE_FORCE16 (1u << 1)
|
||||
// value usage forces 16-bit usage
|
||||
#define MVALUE_FORCE08 (1u << 0)
|
||||
// value usage forces 8-bit usage
|
||||
// meaning of bits in "flags" of struct result:
|
||||
#define MVALUE_IS_FP (1u << 8) // floating point value
|
||||
#define MVALUE_INDIRECT (1u << 7) // needless parentheses indicate use of indirect addressing modes
|
||||
#define MVALUE_EXISTS (1u << 6) // 0: expression was empty. 1: there was *something* to parse.
|
||||
#define MVALUE_UNSURE (1u << 5) // value once was related to undefined
|
||||
// expression. Needed for producing the same addresses in all passes; because in
|
||||
// the first pass there will almost for sure be labels that are undefined, you
|
||||
// can't simply get the addressing mode from looking at the parameter's value.
|
||||
#define MVALUE_DEFINED (1u << 4) // 0: undefined expression (value will be zero). 1: known result
|
||||
#define MVALUE_ISBYTE (1u << 3) // value is guaranteed to fit in one byte
|
||||
#define MVALUE_FORCE24 (1u << 2) // value usage forces 24-bit usage
|
||||
#define MVALUE_FORCE16 (1u << 1) // value usage forces 16-bit usage
|
||||
#define MVALUE_FORCE08 (1u << 0) // value usage forces 8-bit usage
|
||||
#define MVALUE_FORCEBITS (MVALUE_FORCE08|MVALUE_FORCE16|MVALUE_FORCE24)
|
||||
#define MVALUE_GIVEN (MVALUE_DEFINED | MVALUE_EXISTS)
|
||||
// bit mask for fixed values (defined and existing)
|
||||
#define MVALUE_GIVEN (MVALUE_DEFINED | MVALUE_EXISTS) // bit mask for fixed values (defined and existing)
|
||||
|
||||
|
||||
// create dynamic buffer, operator/function trees and operator/operand stacks
|
||||
@ -48,13 +38,14 @@ extern intval_t ALU_any_int(void);
|
||||
// returns int value (if result was undefined, serious error is thrown)
|
||||
extern intval_t ALU_defined_int(void);
|
||||
// stores int value if given. Returns whether stored. Throws error if undefined.
|
||||
extern int ALU_optional_defined_int(intval_t *);
|
||||
extern int ALU_optional_defined_int(intval_t *target);
|
||||
// stores int value and flags (floats are transformed to int)
|
||||
extern void ALU_int_result(struct result_t *);
|
||||
// stores int value and flags, allowing for one '(' too many (x-indirect addr)
|
||||
extern int ALU_liberal_int(struct result_t *);
|
||||
extern void ALU_int_result(struct result *intresult);
|
||||
// stores int value and flags, allowing for one '(' too many (x-indirect addr).
|
||||
// returns number of additional '(' (1 or 0).
|
||||
extern int ALU_liberal_int(struct result *intresult);
|
||||
// stores value and flags (result may be either int or float)
|
||||
extern void ALU_any_result(struct result_t *);
|
||||
extern void ALU_any_result(struct result *result);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -156,7 +156,7 @@ static enum eos PO_addr(void) // Now GotByte = illegal char
|
||||
// show user-defined message
|
||||
static enum eos throw_string(const char prefix[], void (*fn)(const char *))
|
||||
{
|
||||
struct result_t result;
|
||||
struct result result;
|
||||
|
||||
DYNABUF_CLEAR(user_message);
|
||||
DynaBuf_add_string(user_message, prefix);
|
||||
|
@ -12,7 +12,7 @@ typedef unsigned int zone_t;
|
||||
typedef signed long intval_t; // at least 32 bits
|
||||
typedef unsigned long uintval_t; // just for logical shift right
|
||||
// result structure type definition with support for floating point
|
||||
struct result_t { // either int or float
|
||||
struct result { // either int or float
|
||||
int flags; // expression flags
|
||||
union {
|
||||
intval_t intval; // integer value
|
||||
|
30
src/flow.c
30
src/flow.c
@ -18,9 +18,9 @@
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "label.h"
|
||||
#include "macro.h"
|
||||
#include "mnemo.h"
|
||||
#include "symbol.h"
|
||||
#include "tree.h"
|
||||
|
||||
|
||||
@ -185,14 +185,14 @@ static enum eos PO_for(void) // Now GotByte = illegal char
|
||||
{
|
||||
struct input loop_input,
|
||||
*outer_input;
|
||||
struct result_t loop_counter;
|
||||
struct result loop_counter;
|
||||
intval_t first_arg,
|
||||
counter_first,
|
||||
counter_last,
|
||||
counter_increment;
|
||||
int old_algo; // actually bool
|
||||
char *loop_body; // pointer to loop's body block
|
||||
struct label *label;
|
||||
struct symbol *symbol;
|
||||
zone_t zone;
|
||||
int force_bit,
|
||||
loop_start; // line number of "!for" pseudo opcode
|
||||
@ -201,7 +201,7 @@ static enum eos PO_for(void) // Now GotByte = illegal char
|
||||
return SKIP_REMAINDER;
|
||||
// Now GotByte = illegal char
|
||||
force_bit = Input_get_force_bit(); // skips spaces after
|
||||
label = Label_find(zone, force_bit);
|
||||
symbol = symbol_find(zone, force_bit);
|
||||
if (!Input_accept_comma()) {
|
||||
Throw_error(exception_syntax);
|
||||
return SKIP_REMAINDER;
|
||||
@ -242,14 +242,14 @@ static enum eos PO_for(void) // Now GotByte = illegal char
|
||||
// init counter
|
||||
loop_counter.flags = MVALUE_DEFINED | MVALUE_EXISTS;
|
||||
loop_counter.val.intval = counter_first;
|
||||
Label_set_value(label, &loop_counter, TRUE);
|
||||
symbol_set_value(symbol, &loop_counter, TRUE);
|
||||
if (old_algo) {
|
||||
// old algo for old syntax:
|
||||
// if count == 0, skip loop
|
||||
if (counter_last) {
|
||||
do {
|
||||
loop_counter.val.intval += counter_increment;
|
||||
Label_set_value(label, &loop_counter, TRUE);
|
||||
symbol_set_value(symbol, &loop_counter, TRUE);
|
||||
parse_ram_block(loop_start, loop_body);
|
||||
} while (loop_counter.val.intval < counter_last);
|
||||
}
|
||||
@ -258,7 +258,7 @@ static enum eos PO_for(void) // Now GotByte = illegal char
|
||||
do {
|
||||
parse_ram_block(loop_start, loop_body);
|
||||
loop_counter.val.intval += counter_increment;
|
||||
Label_set_value(label, &loop_counter, TRUE);
|
||||
symbol_set_value(symbol, &loop_counter, TRUE);
|
||||
} while (loop_counter.val.intval != (counter_last + counter_increment));
|
||||
}
|
||||
// Free memory
|
||||
@ -337,30 +337,30 @@ static enum eos PO_if(void) // Now GotByte = illegal char
|
||||
static enum eos ifdef_ifndef(int invert) // Now GotByte = illegal char
|
||||
{
|
||||
struct node_ra_t *node;
|
||||
struct label *label;
|
||||
struct symbol *symbol;
|
||||
zone_t zone;
|
||||
int defined = FALSE;
|
||||
|
||||
if (Input_read_zone_and_keyword(&zone) == 0) // skips spaces before
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
Tree_hard_scan(&node, Label_forest, zone, FALSE);
|
||||
Tree_hard_scan(&node, symbols_forest, zone, FALSE);
|
||||
if (node) {
|
||||
label = (struct label *) node->body;
|
||||
symbol = (struct symbol *) node->body;
|
||||
// in first pass, count usage
|
||||
if (pass_count == 0)
|
||||
label->usage++;
|
||||
if (label->result.flags & MVALUE_DEFINED)
|
||||
symbol->usage++;
|
||||
if (symbol->result.flags & MVALUE_DEFINED)
|
||||
defined = TRUE;
|
||||
}
|
||||
SKIPSPACE();
|
||||
// if "ifndef", invert condition
|
||||
if (invert)
|
||||
defined = !defined;
|
||||
if (GotByte == CHAR_SOB)
|
||||
parse_block_else_block(defined);
|
||||
else
|
||||
if (GotByte != CHAR_SOB)
|
||||
return defined ? PARSE_REMAINDER : SKIP_REMAINDER;
|
||||
|
||||
parse_block_else_block(defined);
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
31
src/global.c
31
src/global.c
@ -13,10 +13,10 @@
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "label.h"
|
||||
#include "macro.h"
|
||||
#include "output.h"
|
||||
#include "section.h"
|
||||
#include "symbol.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
|
||||
@ -183,8 +183,8 @@ static int first_label_of_statement(int *statement_flags)
|
||||
}
|
||||
|
||||
|
||||
// Parse global label definition or assembler mnemonic
|
||||
static void parse_mnemo_or_global_label_def(int *statement_flags)
|
||||
// Parse global symbol definition or assembler mnemonic
|
||||
static void parse_mnemo_or_global_symbol_def(int *statement_flags)
|
||||
{
|
||||
// It is only a label if it isn't a mnemonic
|
||||
if ((CPU_state.type->keyword_is_mnemonic(Input_read_keyword()) == FALSE)
|
||||
@ -195,23 +195,23 @@ static void parse_mnemo_or_global_label_def(int *statement_flags)
|
||||
if ((*GLOBALDYNABUF_CURRENT == (char) 0xa0)
|
||||
|| ((GlobalDynaBuf->size >= 2) && (GLOBALDYNABUF_CURRENT[0] == (char) 0xc2) && (GLOBALDYNABUF_CURRENT[1] == (char) 0xa0)))
|
||||
Throw_first_pass_warning("Label name starts with a shift-space character.");
|
||||
Label_parse_definition(ZONE_GLOBAL, *statement_flags);
|
||||
symbol_parse_definition(ZONE_GLOBAL, *statement_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parse local label definition
|
||||
static void parse_local_label_def(int *statement_flags)
|
||||
// parse local symbol definition
|
||||
static void parse_local_symbol_def(int *statement_flags)
|
||||
{
|
||||
if (!first_label_of_statement(statement_flags))
|
||||
return;
|
||||
GetByte(); // start after '.'
|
||||
if (Input_read_keyword())
|
||||
Label_parse_definition(Section_now->zone, *statement_flags);
|
||||
symbol_parse_definition(Section_now->zone, *statement_flags);
|
||||
}
|
||||
|
||||
|
||||
// Parse anonymous backward label definition. Called with GotByte == '-'
|
||||
// parse anonymous backward label definition. Called with GotByte == '-'
|
||||
static void parse_backward_anon_def(int *statement_flags)
|
||||
{
|
||||
if (!first_label_of_statement(statement_flags))
|
||||
@ -221,15 +221,13 @@ static void parse_backward_anon_def(int *statement_flags)
|
||||
DYNABUF_APPEND(GlobalDynaBuf, '-');
|
||||
while (GetByte() == '-');
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
Label_implicit_definition(Section_now->zone, *statement_flags, 0, TRUE);
|
||||
symbol_set_label(Section_now->zone, *statement_flags, 0, TRUE); // this "TRUE" is the whole secret
|
||||
}
|
||||
|
||||
|
||||
// Parse anonymous forward label definition. Called with GotByte == ?
|
||||
// parse anonymous forward label definition. called with GotByte == ?
|
||||
static void parse_forward_anon_def(int *statement_flags)
|
||||
{
|
||||
struct label *counter_label;
|
||||
|
||||
if (!first_label_of_statement(statement_flags))
|
||||
return;
|
||||
DYNABUF_CLEAR(GlobalDynaBuf);
|
||||
@ -238,10 +236,9 @@ static void parse_forward_anon_def(int *statement_flags)
|
||||
DYNABUF_APPEND(GlobalDynaBuf, '+');
|
||||
GetByte();
|
||||
}
|
||||
counter_label = Label_fix_forward_name();
|
||||
counter_label->result.val.intval++;
|
||||
symbol_fix_forward_anon_name(TRUE); // TRUE: increment counter
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
Label_implicit_definition(Section_now->zone, *statement_flags, 0, TRUE);
|
||||
symbol_set_label(Section_now->zone, *statement_flags, 0, FALSE);
|
||||
}
|
||||
|
||||
|
||||
@ -294,11 +291,11 @@ void Parse_until_eob_or_eof(void)
|
||||
parse_pc_def();
|
||||
break;
|
||||
case LOCAL_PREFIX:
|
||||
parse_local_label_def(&statement_flags);
|
||||
parse_local_symbol_def(&statement_flags);
|
||||
break;
|
||||
default:
|
||||
if (BYTEFLAGS(GotByte) & STARTS_KEYWORD) {
|
||||
parse_mnemo_or_global_label_def(&statement_flags);
|
||||
parse_mnemo_or_global_symbol_def(&statement_flags);
|
||||
} else {
|
||||
Throw_error(exception_syntax);
|
||||
Input_skip_remainder();
|
||||
|
321
src/label.c
321
src/label.c
@ -1,321 +0,0 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816 code.
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Label stuff
|
||||
//
|
||||
// 22 Nov 2007 "warn on indented labels" is now a CLI switch
|
||||
// 25 Sep 2011 Fixed bug in !sl (colons in filename could be interpreted as EOS)
|
||||
#include <stdio.h>
|
||||
#include "acme.h"
|
||||
#include "alu.h"
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "label.h"
|
||||
#include "output.h"
|
||||
#include "platform.h"
|
||||
#include "section.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
|
||||
|
||||
// constants
|
||||
#define s_sl (s_asl + 1) // Yes, I know I'm sick
|
||||
|
||||
|
||||
// variables
|
||||
struct node_ra_t *Label_forest[256]; // ... (because of 8-bit hash)
|
||||
|
||||
|
||||
// Dump label value and flags to dump file
|
||||
static void dump_one_label(struct node_ra_t *node, FILE *fd)
|
||||
{
|
||||
struct label *label = node->body;
|
||||
|
||||
// output name
|
||||
fprintf(fd, "%s", node->id_string);
|
||||
switch (label->result.flags & MVALUE_FORCEBITS) {
|
||||
case MVALUE_FORCE16:
|
||||
fprintf(fd, "+2\t= ");
|
||||
break;
|
||||
case MVALUE_FORCE16 | MVALUE_FORCE24:
|
||||
/*FALLTHROUGH*/
|
||||
case MVALUE_FORCE24:
|
||||
fprintf(fd, "+3\t= ");
|
||||
break;
|
||||
default:
|
||||
fprintf(fd, "\t= ");
|
||||
}
|
||||
if (label->result.flags & MVALUE_DEFINED) {
|
||||
if (label->result.flags & MVALUE_IS_FP)
|
||||
fprintf(fd, "%.30f", label->result.val.fpval); //FIXME %g
|
||||
else
|
||||
fprintf(fd, "$%x", (unsigned) label->result.val.intval);
|
||||
} else {
|
||||
fprintf(fd, " ?");
|
||||
}
|
||||
if (label->result.flags & MVALUE_UNSURE)
|
||||
fprintf(fd, "\t; ?");
|
||||
if (label->usage == 0)
|
||||
fprintf(fd, "\t; unused");
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
|
||||
|
||||
// Search for label. Create if nonexistant. If created, give it flags "flags".
|
||||
// The label name must be held in GlobalDynaBuf.
|
||||
struct label *Label_find(zone_t zone, int flags)
|
||||
{
|
||||
struct node_ra_t *node;
|
||||
struct label *label;
|
||||
int node_created,
|
||||
force_bits = flags & MVALUE_FORCEBITS;
|
||||
|
||||
node_created = Tree_hard_scan(&node, Label_forest, zone, TRUE);
|
||||
// if node has just been created, create label as well
|
||||
if (node_created) {
|
||||
// Create new label structure
|
||||
label = safe_malloc(sizeof(*label));
|
||||
// Finish empty label item
|
||||
label->result.flags = flags;
|
||||
label->result.addr_refs = 0;
|
||||
if (flags & MVALUE_IS_FP)
|
||||
label->result.val.fpval = 0;
|
||||
else
|
||||
label->result.val.intval = 0;
|
||||
label->usage = 0; // usage count
|
||||
label->pass = pass_count;
|
||||
node->body = label;
|
||||
} else {
|
||||
label = node->body;
|
||||
}
|
||||
// make sure the force bits don't clash
|
||||
if ((node_created == FALSE) && force_bits)
|
||||
if ((label->result.flags & MVALUE_FORCEBITS) != force_bits)
|
||||
Throw_error("Too late for postfix.");
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
// Assign value to label. The function acts upon the label's flag bits and
|
||||
// produces an error if needed.
|
||||
void Label_set_value(struct label *label, struct result_t *newvalue, int change_allowed)
|
||||
{
|
||||
int oldflags = label->result.flags;
|
||||
|
||||
// value stuff
|
||||
if ((oldflags & MVALUE_DEFINED) && (change_allowed == FALSE)) {
|
||||
// Label is already defined, so compare new and old values
|
||||
// if different type OR same type but different value, complain
|
||||
if (((oldflags ^ newvalue->flags) & MVALUE_IS_FP)
|
||||
|| ((oldflags & MVALUE_IS_FP)
|
||||
? (label->result.val.fpval != newvalue->val.fpval)
|
||||
: (label->result.val.intval != newvalue->val.intval)))
|
||||
Throw_error("Label already defined.");
|
||||
} else {
|
||||
// Label is not defined yet OR redefinitions are allowed
|
||||
label->result = *newvalue;
|
||||
}
|
||||
// flags stuff
|
||||
// Ensure that "unsure" labels without "isByte" state don't get that
|
||||
if ((oldflags & (MVALUE_UNSURE | MVALUE_ISBYTE)) == MVALUE_UNSURE)
|
||||
newvalue->flags &= ~MVALUE_ISBYTE;
|
||||
if (change_allowed) {
|
||||
oldflags = (oldflags & MVALUE_UNSURE) | newvalue->flags;
|
||||
} else {
|
||||
if ((oldflags & MVALUE_FORCEBITS) == 0)
|
||||
if ((oldflags & (MVALUE_UNSURE | MVALUE_DEFINED)) == 0)
|
||||
oldflags |= newvalue->flags & MVALUE_FORCEBITS;
|
||||
oldflags |= newvalue->flags & ~MVALUE_FORCEBITS;
|
||||
}
|
||||
label->result.flags = oldflags;
|
||||
}
|
||||
|
||||
|
||||
// (Re)set label
|
||||
static enum eos PO_set(void) // Now GotByte = illegal char
|
||||
{
|
||||
struct result_t result;
|
||||
int force_bit;
|
||||
struct label *label;
|
||||
zone_t zone;
|
||||
|
||||
if (Input_read_zone_and_keyword(&zone) == 0) // skips spaces before
|
||||
// Now GotByte = illegal char
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
force_bit = Input_get_force_bit(); // skips spaces after
|
||||
label = Label_find(zone, force_bit);
|
||||
if (GotByte != '=') {
|
||||
Throw_error(exception_syntax);
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
|
||||
// label = parsed value
|
||||
GetByte(); // proceed with next char
|
||||
ALU_any_result(&result);
|
||||
// clear label's force bits and set new ones
|
||||
label->result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE);
|
||||
if (force_bit) {
|
||||
label->result.flags |= force_bit;
|
||||
result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE);
|
||||
}
|
||||
Label_set_value(label, &result, TRUE);
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// Select dump file
|
||||
static enum eos PO_sl(void)
|
||||
{
|
||||
// bugfix: first read filename, *then* check for first pass.
|
||||
// if skipping right away, quoted colons might be misinterpreted as EOS
|
||||
// FIXME - why not just fix the skipping code to handle quotes? :)
|
||||
// "!to" has been fixed as well
|
||||
|
||||
// read filename to global dynamic buffer
|
||||
// if no file name given, exit (complaining will have been done)
|
||||
if (Input_read_filename(FALSE))
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// only process this pseudo opcode in first pass
|
||||
if (pass_count)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// if label dump file already chosen, complain and exit
|
||||
if (labeldump_filename) {
|
||||
Throw_warning("Label dump file already chosen.");
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
|
||||
// get malloc'd copy of filename
|
||||
labeldump_filename = DynaBuf_get_copy(GlobalDynaBuf);
|
||||
// ensure there's no garbage at end of line
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// predefined stuff
|
||||
static struct node_t pseudo_opcodes[] = {
|
||||
PREDEFNODE("set", PO_set),
|
||||
PREDEFLAST(s_sl, PO_sl),
|
||||
// ^^^^ this marks the last element
|
||||
};
|
||||
|
||||
|
||||
// Parse implicit label definition (can be either global or local).
|
||||
// GlobalDynaBuf holds the label name.
|
||||
void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change)
|
||||
{
|
||||
struct result_t pc,
|
||||
result;
|
||||
struct label *label;
|
||||
|
||||
label = Label_find(zone, force_bit);
|
||||
// implicit label definition (label)
|
||||
if ((stat_flags & SF_FOUND_BLANK) && warn_on_indented_labels)
|
||||
Throw_first_pass_warning("Implicit label definition not in leftmost column.");
|
||||
vcpu_read_pc(&pc);
|
||||
result.flags = pc.flags & MVALUE_DEFINED;
|
||||
result.val.intval = pc.val.intval;
|
||||
result.addr_refs = pc.addr_refs;
|
||||
Label_set_value(label, &result, change);
|
||||
}
|
||||
|
||||
|
||||
// parse label definition (can be either global or local).
|
||||
// GlobalDynaBuf holds the label name.
|
||||
void Label_parse_definition(zone_t zone, int stat_flags)
|
||||
{
|
||||
struct result_t result;
|
||||
struct label *label;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
// FIXME - force bit is allowed for implicit label defs?!
|
||||
|
||||
if (GotByte == '=') {
|
||||
// explicit label definition (label = <something>)
|
||||
label = Label_find(zone, force_bit);
|
||||
// label = parsed value
|
||||
GetByte(); // skip '='
|
||||
ALU_any_result(&result);
|
||||
// if wanted, mark as address reference
|
||||
if (typesystem_says_address())
|
||||
result.addr_refs = 1;
|
||||
Label_set_value(label, &result, FALSE);
|
||||
Input_ensure_EOS();
|
||||
} else {
|
||||
Label_implicit_definition(zone, stat_flags, force_bit, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set global label to value, no questions asked (for "-D" switch)
|
||||
// Name must be held in GlobalDynaBuf.
|
||||
void Label_define(intval_t value)
|
||||
{
|
||||
struct result_t result;
|
||||
struct label *label;
|
||||
|
||||
result.flags = MVALUE_GIVEN;
|
||||
result.val.intval = value;
|
||||
label = Label_find(ZONE_GLOBAL, 0);
|
||||
Label_set_value(label, &result, TRUE);
|
||||
}
|
||||
|
||||
|
||||
// dump global labels to file
|
||||
void Label_dump_all(FILE *fd)
|
||||
{
|
||||
Tree_dump_forest(Label_forest, ZONE_GLOBAL, dump_one_label, fd);
|
||||
PLATFORM_SETFILETYPE_TEXT(labeldump_filename);
|
||||
}
|
||||
|
||||
|
||||
// clear label forest (is done early)
|
||||
void Label_clear_init(void)
|
||||
{
|
||||
struct node_ra_t **ptr;
|
||||
int ii;
|
||||
|
||||
// cut down all the trees (clear pointer table)
|
||||
ptr = Label_forest;
|
||||
for (ii = 255; ii >= 0; ii--)
|
||||
*ptr++ = NULL;
|
||||
}
|
||||
|
||||
|
||||
// register pseudo opcodes (done later)
|
||||
void Label_register_init(void)
|
||||
{
|
||||
Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes);
|
||||
}
|
||||
|
||||
|
||||
// fix name of anonymous forward label (held in DynaBuf, NOT TERMINATED!) so it
|
||||
// references the *next* anonymous forward label definition. The tricky bit is,
|
||||
// each name length would need its own counter. But hey, ACME's real quick in
|
||||
// finding labels, so I'll just abuse the label system to store those counters.
|
||||
struct label *Label_fix_forward_name(void)
|
||||
{
|
||||
struct label *counter_label;
|
||||
unsigned long number;
|
||||
|
||||
// terminate name, find "counter" label and read value
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
counter_label = Label_find(Section_now->zone, 0);
|
||||
// make sure it gets reset to zero in each new pass
|
||||
if (counter_label->pass != pass_count) {
|
||||
counter_label->pass = pass_count;
|
||||
counter_label->result.val.intval = 0;
|
||||
}
|
||||
number = (unsigned long) counter_label->result.val.intval;
|
||||
// now append to the name to make it unique
|
||||
GlobalDynaBuf->size--; // forget terminator, we want to append
|
||||
do {
|
||||
DYNABUF_APPEND(GlobalDynaBuf, 'a' + (number & 15));
|
||||
number >>= 4;
|
||||
} while (number);
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
return counter_label;
|
||||
}
|
51
src/label.h
51
src/label.h
@ -1,51 +0,0 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816 code.
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// Label stuff
|
||||
#ifndef label_H
|
||||
#define label_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
|
||||
|
||||
// "label" structure type definition
|
||||
struct label {
|
||||
struct result_t result; // Expression flags and value
|
||||
int usage; // usage count
|
||||
int pass; // pass of creation (for anon counters)
|
||||
};
|
||||
|
||||
|
||||
// variables
|
||||
extern struct node_ra_t *Label_forest[]; // trees (because of 8-bit hash)
|
||||
|
||||
|
||||
// clear label forest (is done early)
|
||||
extern void Label_clear_init(void);
|
||||
// register pseudo opcodes (done later)
|
||||
extern void Label_register_init(void);
|
||||
// function acts upon the label's flag bits and produces an error if needed.
|
||||
extern void Label_set_value(struct label *, struct result_t *, int change_allowed);
|
||||
// Parse implicit label definition (can be either global or local).
|
||||
// Name must be held in GlobalDynaBuf.
|
||||
extern void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change);
|
||||
// Parse label definition (can be either global or local).
|
||||
// Name must be held in GlobalDynaBuf.
|
||||
extern void Label_parse_definition(zone_t zone, int stat_flags);
|
||||
// Search for label. Create if nonexistant. If created, assign flags.
|
||||
// Name must be held in GlobalDynaBuf.
|
||||
extern struct label *Label_find(zone_t, int flags);
|
||||
// set global label to value, no questions asked (for "-D" switch)
|
||||
// Name must be held in GlobalDynaBuf.
|
||||
extern void Label_define(intval_t value);
|
||||
// Dump global labels to file
|
||||
extern void Label_dump_all(FILE *fd);
|
||||
// Fix name of anonymous forward label (held in GlobalDynaBuf, NOT TERMINATED!)
|
||||
// so it references the *next* anonymous forward label definition.
|
||||
extern struct label *Label_fix_forward_name(void);
|
||||
|
||||
|
||||
#endif
|
40
src/macro.c
40
src/macro.c
@ -11,8 +11,8 @@
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "label.h"
|
||||
#include "section.h"
|
||||
#include "symbol.h"
|
||||
#include "tree.h"
|
||||
#include "macro.h"
|
||||
|
||||
@ -42,8 +42,8 @@ struct macro {
|
||||
// gives us the possibility to find out which args are call-by-value and
|
||||
// which ones are call-by-reference.
|
||||
union macro_arg_t {
|
||||
struct result_t result; // value and flags (call by value)
|
||||
struct label *label; // pointer to label struct (call by reference)
|
||||
struct result result; // value and flags (call by value)
|
||||
struct symbol *symbol; // pointer to symbol struct (call by reference)
|
||||
};
|
||||
|
||||
|
||||
@ -187,12 +187,12 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
|
||||
DynaBuf_append(GlobalDynaBuf, REFERENCE_CHAR);
|
||||
GetByte();
|
||||
}
|
||||
// handle prefix for local labels (LOCAL_PREFIX, normally '.')
|
||||
// handle prefix for local symbols (LOCAL_PREFIX, normally '.')
|
||||
if (GotByte == LOCAL_PREFIX) {
|
||||
DynaBuf_append(GlobalDynaBuf, LOCAL_PREFIX);
|
||||
GetByte();
|
||||
}
|
||||
// handle label name
|
||||
// handle symbol name
|
||||
Input_append_keyword_to_global_dynabuf();
|
||||
} while (pipe_comma());
|
||||
// ensure CHAR_SOB ('{')
|
||||
@ -225,16 +225,16 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
|
||||
void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
|
||||
{
|
||||
char local_gotbyte;
|
||||
struct label *label;
|
||||
struct symbol *symbol;
|
||||
struct section new_section,
|
||||
*outer_section;
|
||||
struct input new_input,
|
||||
*outer_input;
|
||||
struct macro *actual_macro;
|
||||
struct node_ra_t *macro_node,
|
||||
*label_node;
|
||||
*symbol_node;
|
||||
zone_t macro_zone,
|
||||
label_zone;
|
||||
symbol_zone;
|
||||
int arg_count = 0;
|
||||
|
||||
// Enter deeper nesting level
|
||||
@ -261,10 +261,9 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
|
||||
// read call-by-reference arg
|
||||
DynaBuf_append(internal_name, ARGTYPE_NUM_REF);
|
||||
GetByte(); // skip '~' character
|
||||
Input_read_zone_and_keyword(&label_zone);
|
||||
Input_read_zone_and_keyword(&symbol_zone);
|
||||
// GotByte = illegal char
|
||||
arg_table[arg_count].label =
|
||||
Label_find(label_zone, 0);
|
||||
arg_table[arg_count].symbol = symbol_find(symbol_zone, 0);
|
||||
} else {
|
||||
// read call-by-value arg
|
||||
DynaBuf_append(internal_name, ARGTYPE_NUM_VAL);
|
||||
@ -299,8 +298,7 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
|
||||
outer_section = Section_now;
|
||||
// start new section (with new zone)
|
||||
// FALSE = title mustn't be freed
|
||||
Section_new_zone(&new_section, "Macro",
|
||||
actual_macro->original_name, FALSE);
|
||||
Section_new_zone(&new_section, "Macro", actual_macro->original_name, FALSE);
|
||||
GetByte(); // fetch first byte of parameter list
|
||||
// assign arguments
|
||||
if (GotByte != CHAR_EOS) { // any at all?
|
||||
@ -312,19 +310,19 @@ void Macro_parse_call(void) // Now GotByte = dot or first char of macro name
|
||||
if (GotByte == REFERENCE_CHAR) {
|
||||
// assign call-by-reference arg
|
||||
GetByte(); // skip '~' character
|
||||
Input_read_zone_and_keyword(&label_zone);
|
||||
if ((Tree_hard_scan(&label_node, Label_forest, label_zone, TRUE) == FALSE)
|
||||
Input_read_zone_and_keyword(&symbol_zone);
|
||||
if ((Tree_hard_scan(&symbol_node, symbols_forest, symbol_zone, TRUE) == FALSE)
|
||||
&& (pass_count == 0))
|
||||
Throw_error("Macro parameter twice.");
|
||||
label_node->body = arg_table[arg_count].label;
|
||||
symbol_node->body = arg_table[arg_count].symbol;
|
||||
} else {
|
||||
// assign call-by-value arg
|
||||
Input_read_zone_and_keyword(&label_zone);
|
||||
label = Label_find(label_zone, 0);
|
||||
// FIXME - add a possibility to Label_find to make it possible to find out
|
||||
// whether label was just created. Then check for the same error message here
|
||||
Input_read_zone_and_keyword(&symbol_zone);
|
||||
symbol = symbol_find(symbol_zone, 0);
|
||||
// FIXME - add a possibility to symbol_find to make it possible to find out
|
||||
// whether symbol was just created. Then check for the same error message here
|
||||
// as above ("Macro parameter twice.").
|
||||
label->result = arg_table[arg_count].result;
|
||||
symbol->result = arg_table[arg_count].result;
|
||||
}
|
||||
arg_count++;
|
||||
} while (Input_accept_comma());
|
||||
|
20
src/mnemo.c
20
src/mnemo.c
@ -396,9 +396,9 @@ static int get_index(int next)
|
||||
return addressing_mode;
|
||||
}
|
||||
|
||||
// This function stores the command's argument in the given result_t
|
||||
// This function stores the command's argument in the given result
|
||||
// structure (using the valueparser). The addressing mode is returned.
|
||||
static int get_argument(struct result_t *result)
|
||||
static int get_argument(struct result *result)
|
||||
{
|
||||
int open_paren,
|
||||
addressing_mode = HAM_ABS;
|
||||
@ -451,7 +451,7 @@ static int get_argument(struct result_t *result)
|
||||
|
||||
// Helper function for calc_arg_size()
|
||||
// Only call with "size_bit = MVALUE_FORCE16" or "size_bit = MVALUE_FORCE24"
|
||||
static int check_oversize(int size_bit, struct result_t *argument)
|
||||
static int check_oversize(int size_bit, struct result *argument)
|
||||
{
|
||||
// only check if value is *defined*
|
||||
if ((argument->flags & MVALUE_DEFINED) == 0)
|
||||
@ -478,7 +478,7 @@ static int check_oversize(int size_bit, struct result_t *argument)
|
||||
// argument value and flags of parameter
|
||||
// addressing_modes adressing modes (8b, 16b, 24b or any combination)
|
||||
// Return value = force bit for number of parameter bytes to send (0 = error)
|
||||
static int calc_arg_size(int force_bit, struct result_t *argument, int addressing_modes)
|
||||
static int calc_arg_size(int force_bit, struct result *argument, int addressing_modes)
|
||||
{
|
||||
// if there are no possible addressing modes, complain
|
||||
if (addressing_modes == MAYBE______) {
|
||||
@ -588,7 +588,7 @@ static void not_in_bank(intval_t target)
|
||||
// Mnemonics using only 8bit relative addressing (short branch instructions).
|
||||
static void group_only_relative8_addressing(int opcode)
|
||||
{
|
||||
struct result_t target;
|
||||
struct result target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
|
||||
ALU_int_result(&target);
|
||||
@ -623,7 +623,7 @@ static void group_only_relative8_addressing(int opcode)
|
||||
// Mnemonics using only 16bit relative addressing (BRL and PER).
|
||||
static void group_only_relative16_addressing(int opcode)
|
||||
{
|
||||
struct result_t target;
|
||||
struct result target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
|
||||
ALU_int_result(&target);
|
||||
@ -644,7 +644,7 @@ static void group_only_relative16_addressing(int opcode)
|
||||
|
||||
// set addressing mode bits depending on which opcodes exist, then calculate
|
||||
// argument size and output both opcode and argument
|
||||
static void make_command(int force_bit, struct result_t *result, unsigned long opcodes)
|
||||
static void make_command(int force_bit, struct result *result, unsigned long opcodes)
|
||||
{
|
||||
int addressing_modes = MAYBE______;
|
||||
|
||||
@ -695,7 +695,7 @@ static unsigned int imm_ops(int *force_bit, unsigned char opcode, int imm_flag)
|
||||
static void group_main(int index, int imm_flag)
|
||||
{
|
||||
unsigned long imm_opcodes;
|
||||
struct result_t result;
|
||||
struct result result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_argument(&result)) {
|
||||
@ -744,7 +744,7 @@ static void group_main(int index, int imm_flag)
|
||||
static void group_misc(int index, int imm_flag)
|
||||
{
|
||||
unsigned long imm_opcodes;
|
||||
struct result_t result;
|
||||
struct result result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_argument(&result)) {
|
||||
@ -802,7 +802,7 @@ static void group_move(int opcode)
|
||||
// The jump instructions.
|
||||
static void group_jump(int index)
|
||||
{
|
||||
struct result_t result;
|
||||
struct result result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_argument(&result)) {
|
||||
|
@ -615,7 +615,7 @@ void PO_setpc(void)
|
||||
|
||||
|
||||
// get program counter
|
||||
void vcpu_read_pc(struct result_t *target)
|
||||
void vcpu_read_pc(struct result *target)
|
||||
{
|
||||
*target = CPU_state.pc;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
// FIXME - move struct definition to .c file and change other .c files' accesses to fn calls
|
||||
struct vcpu {
|
||||
const struct cpu_type *type; // current CPU type (default 6502) (FIXME - move out of struct again?)
|
||||
struct result_t pc; // current program counter (pseudo value)
|
||||
struct result pc; // current program counter (pseudo value)
|
||||
int add_to_pc; // add to PC after statement
|
||||
int a_is_long;
|
||||
int xy_are_long;
|
||||
@ -65,7 +65,7 @@ extern void Output_end_segment(void);
|
||||
// set program counter to defined value (FIXME - allow undefined!)
|
||||
extern void vcpu_set_pc(intval_t new_pc, int flags);
|
||||
// get program counter
|
||||
extern void vcpu_read_pc(struct result_t *target);
|
||||
extern void vcpu_read_pc(struct result *target);
|
||||
// get size of current statement (until now) - needed for "!bin" verbose output
|
||||
extern int vcpu_get_statement_size(void);
|
||||
// adjust program counter (called at end of each statement)
|
||||
|
325
src/symbol.c
Normal file
325
src/symbol.c
Normal file
@ -0,0 +1,325 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816 code.
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// symbol stuff
|
||||
//
|
||||
// 22 Nov 2007 "warn on indented labels" is now a CLI switch
|
||||
// 25 Sep 2011 Fixed bug in !sl (colons in filename could be interpreted as EOS)
|
||||
#include <stdio.h>
|
||||
#include "acme.h"
|
||||
#include "alu.h"
|
||||
#include "dynabuf.h"
|
||||
#include "global.h"
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "platform.h"
|
||||
#include "section.h"
|
||||
#include "symbol.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
|
||||
|
||||
// constants
|
||||
#define s_sl (s_asl + 1) // Yes, I know I'm sick
|
||||
|
||||
|
||||
// variables
|
||||
struct node_ra_t *symbols_forest[256]; // ... (because of 8-bit hash)
|
||||
|
||||
|
||||
// Dump symbol value and flags to dump file
|
||||
static void dump_one_symbol(struct node_ra_t *node, FILE *fd)
|
||||
{
|
||||
struct symbol *symbol = node->body;
|
||||
|
||||
// output name
|
||||
if (warn_on_type_mismatch
|
||||
&& symbol->result.addr_refs == 1)
|
||||
fprintf(fd, "!addr\t");
|
||||
fprintf(fd, "%s", node->id_string);
|
||||
switch (symbol->result.flags & MVALUE_FORCEBITS) {
|
||||
case MVALUE_FORCE16:
|
||||
fprintf(fd, "+2\t= ");
|
||||
break;
|
||||
case MVALUE_FORCE16 | MVALUE_FORCE24:
|
||||
/*FALLTHROUGH*/
|
||||
case MVALUE_FORCE24:
|
||||
fprintf(fd, "+3\t= ");
|
||||
break;
|
||||
default:
|
||||
fprintf(fd, "\t= ");
|
||||
}
|
||||
if (symbol->result.flags & MVALUE_DEFINED) {
|
||||
if (symbol->result.flags & MVALUE_IS_FP)
|
||||
fprintf(fd, "%.30f", symbol->result.val.fpval); //FIXME %g
|
||||
else
|
||||
fprintf(fd, "$%x", (unsigned) symbol->result.val.intval);
|
||||
} else {
|
||||
fprintf(fd, " ?");
|
||||
}
|
||||
if (symbol->result.flags & MVALUE_UNSURE)
|
||||
fprintf(fd, "\t; ?");
|
||||
if (symbol->usage == 0)
|
||||
fprintf(fd, "\t; unused");
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
|
||||
|
||||
// search for symbol. create if nonexistant. if created, give it flags "flags".
|
||||
// the symbol name must be held in GlobalDynaBuf.
|
||||
struct symbol *symbol_find(zone_t zone, int flags)
|
||||
{
|
||||
struct node_ra_t *node;
|
||||
struct symbol *symbol;
|
||||
int node_created,
|
||||
force_bits = flags & MVALUE_FORCEBITS;
|
||||
|
||||
node_created = Tree_hard_scan(&node, symbols_forest, zone, TRUE);
|
||||
// if node has just been created, create symbol as well
|
||||
if (node_created) {
|
||||
// create new symbol structure
|
||||
symbol = safe_malloc(sizeof(*symbol));
|
||||
// finish empty symbol item
|
||||
symbol->result.flags = flags;
|
||||
symbol->result.addr_refs = 0;
|
||||
if (flags & MVALUE_IS_FP)
|
||||
symbol->result.val.fpval = 0;
|
||||
else
|
||||
symbol->result.val.intval = 0;
|
||||
symbol->usage = 0; // usage count
|
||||
symbol->pass = pass_count;
|
||||
node->body = symbol;
|
||||
} else {
|
||||
symbol = node->body;
|
||||
}
|
||||
// make sure the force bits don't clash
|
||||
if ((node_created == FALSE) && force_bits)
|
||||
if ((symbol->result.flags & MVALUE_FORCEBITS) != force_bits)
|
||||
Throw_error("Too late for postfix.");
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
// assign value to symbol. the function acts upon the symbol's flag bits and
|
||||
// produces an error if needed.
|
||||
void symbol_set_value(struct symbol *symbol, struct result *new_value, int change_allowed)
|
||||
{
|
||||
int oldflags = symbol->result.flags;
|
||||
|
||||
// value stuff
|
||||
if ((oldflags & MVALUE_DEFINED) && (change_allowed == FALSE)) {
|
||||
// symbol is already defined, so compare new and old values
|
||||
// if different type OR same type but different value, complain
|
||||
if (((oldflags ^ new_value->flags) & MVALUE_IS_FP)
|
||||
|| ((oldflags & MVALUE_IS_FP)
|
||||
? (symbol->result.val.fpval != new_value->val.fpval)
|
||||
: (symbol->result.val.intval != new_value->val.intval)))
|
||||
Throw_error("Symbol already defined.");
|
||||
} else {
|
||||
// symbol is not defined yet OR redefinitions are allowed
|
||||
symbol->result = *new_value;
|
||||
}
|
||||
// flags stuff
|
||||
// Ensure that "unsure" symbols without "isByte" state don't get that
|
||||
if ((oldflags & (MVALUE_UNSURE | MVALUE_ISBYTE)) == MVALUE_UNSURE)
|
||||
new_value->flags &= ~MVALUE_ISBYTE;
|
||||
if (change_allowed) {
|
||||
oldflags = (oldflags & MVALUE_UNSURE) | new_value->flags;
|
||||
} else {
|
||||
if ((oldflags & MVALUE_FORCEBITS) == 0)
|
||||
if ((oldflags & (MVALUE_UNSURE | MVALUE_DEFINED)) == 0)
|
||||
oldflags |= new_value->flags & MVALUE_FORCEBITS;
|
||||
oldflags |= new_value->flags & ~MVALUE_FORCEBITS;
|
||||
}
|
||||
symbol->result.flags = oldflags;
|
||||
}
|
||||
|
||||
|
||||
// (Re)set symbol
|
||||
static enum eos PO_set(void) // Now GotByte = illegal char
|
||||
{
|
||||
struct result result;
|
||||
int force_bit;
|
||||
struct symbol *symbol;
|
||||
zone_t zone;
|
||||
|
||||
if (Input_read_zone_and_keyword(&zone) == 0) // skips spaces before
|
||||
// Now GotByte = illegal char
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
force_bit = Input_get_force_bit(); // skips spaces after
|
||||
symbol = symbol_find(zone, force_bit);
|
||||
if (GotByte != '=') {
|
||||
Throw_error(exception_syntax);
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
|
||||
// symbol = parsed value
|
||||
GetByte(); // proceed with next char
|
||||
ALU_any_result(&result);
|
||||
// clear symbol's force bits and set new ones
|
||||
symbol->result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE);
|
||||
if (force_bit) {
|
||||
symbol->result.flags |= force_bit;
|
||||
result.flags &= ~(MVALUE_FORCEBITS | MVALUE_ISBYTE);
|
||||
}
|
||||
symbol_set_value(symbol, &result, TRUE);
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// Select dump file
|
||||
static enum eos PO_sl(void)
|
||||
{
|
||||
// bugfix: first read filename, *then* check for first pass.
|
||||
// if skipping right away, quoted colons might be misinterpreted as EOS
|
||||
// FIXME - why not just fix the skipping code to handle quotes? :)
|
||||
// "!to" has been fixed as well
|
||||
|
||||
// read filename to global dynamic buffer
|
||||
// if no file name given, exit (complaining will have been done)
|
||||
if (Input_read_filename(FALSE))
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// only process this pseudo opcode in first pass
|
||||
if (pass_count)
|
||||
return SKIP_REMAINDER;
|
||||
|
||||
// if symbol dump file already chosen, complain and exit
|
||||
if (symboldump_filename) {
|
||||
Throw_warning("Label dump file already chosen.");
|
||||
return SKIP_REMAINDER;
|
||||
}
|
||||
|
||||
// get malloc'd copy of filename
|
||||
symboldump_filename = DynaBuf_get_copy(GlobalDynaBuf);
|
||||
// ensure there's no garbage at end of line
|
||||
return ENSURE_EOS;
|
||||
}
|
||||
|
||||
|
||||
// predefined stuff
|
||||
static struct node_t pseudo_opcodes[] = {
|
||||
PREDEFNODE("set", PO_set),
|
||||
PREDEFLAST(s_sl, PO_sl),
|
||||
// ^^^^ this marks the last element
|
||||
};
|
||||
|
||||
|
||||
// parse label definition (can be either global or local).
|
||||
// name must be held in GlobalDynaBuf.
|
||||
void symbol_set_label(zone_t zone, int stat_flags, int force_bit, int change_allowed)
|
||||
{
|
||||
struct result pc,
|
||||
result;
|
||||
struct symbol *symbol;
|
||||
|
||||
symbol = symbol_find(zone, force_bit);
|
||||
// label definition
|
||||
if ((stat_flags & SF_FOUND_BLANK) && warn_on_indented_labels)
|
||||
Throw_first_pass_warning("Label name not in leftmost column.");
|
||||
vcpu_read_pc(&pc);
|
||||
result.flags = pc.flags & MVALUE_DEFINED;
|
||||
result.val.intval = pc.val.intval;
|
||||
result.addr_refs = pc.addr_refs;
|
||||
symbol_set_value(symbol, &result, change_allowed);
|
||||
}
|
||||
|
||||
|
||||
// parse symbol definition (can be either global or local, may turn out to be a label).
|
||||
// name must be held in GlobalDynaBuf.
|
||||
void symbol_parse_definition(zone_t zone, int stat_flags)
|
||||
{
|
||||
struct result result;
|
||||
struct symbol *symbol;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
// FIXME - force bit is allowed for label definitions?!
|
||||
|
||||
if (GotByte == '=') {
|
||||
// explicit symbol definition (symbol = <something>)
|
||||
symbol = symbol_find(zone, force_bit);
|
||||
// symbol = parsed value
|
||||
GetByte(); // skip '='
|
||||
ALU_any_result(&result);
|
||||
// if wanted, mark as address reference
|
||||
if (typesystem_says_address())
|
||||
result.addr_refs = 1;
|
||||
symbol_set_value(symbol, &result, FALSE);
|
||||
Input_ensure_EOS();
|
||||
} else {
|
||||
symbol_set_label(zone, stat_flags, force_bit, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set global symbol to value, no questions asked (for "-D" switch)
|
||||
// Name must be held in GlobalDynaBuf.
|
||||
void symbol_define(intval_t value)
|
||||
{
|
||||
struct result result;
|
||||
struct symbol *symbol;
|
||||
|
||||
result.flags = MVALUE_GIVEN;
|
||||
result.val.intval = value;
|
||||
symbol = symbol_find(ZONE_GLOBAL, 0);
|
||||
symbol_set_value(symbol, &result, TRUE);
|
||||
}
|
||||
|
||||
|
||||
// dump global symbols to file
|
||||
void symbols_dump_all(FILE *fd)
|
||||
{
|
||||
Tree_dump_forest(symbols_forest, ZONE_GLOBAL, dump_one_symbol, fd);
|
||||
PLATFORM_SETFILETYPE_TEXT(symboldump_filename);
|
||||
}
|
||||
|
||||
|
||||
// clear symbols forest (is done early)
|
||||
void symbols_clear_init(void)
|
||||
{
|
||||
struct node_ra_t **ptr;
|
||||
int ii;
|
||||
|
||||
// cut down all the trees (clear pointer table)
|
||||
ptr = symbols_forest;
|
||||
for (ii = 255; ii >= 0; ii--)
|
||||
*ptr++ = NULL;
|
||||
}
|
||||
|
||||
|
||||
// register pseudo opcodes (done later)
|
||||
void symbols_register_init(void)
|
||||
{
|
||||
Tree_add_table(&pseudo_opcode_tree, pseudo_opcodes);
|
||||
}
|
||||
|
||||
|
||||
// fix name of anonymous forward label (held in DynaBuf, NOT TERMINATED!) so it
|
||||
// references the *next* anonymous forward label definition. The tricky bit is,
|
||||
// each name length would need its own counter. But hey, ACME's real quick in
|
||||
// finding symbols, so I'll just abuse the symbol system to store those counters.
|
||||
void symbol_fix_forward_anon_name(int increment)
|
||||
{
|
||||
struct symbol *counter_symbol;
|
||||
unsigned long number;
|
||||
|
||||
// terminate name, find "counter" symbol and read value
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
counter_symbol = symbol_find(Section_now->zone, 0);
|
||||
// make sure it gets reset to zero in each new pass
|
||||
if (counter_symbol->pass != pass_count) {
|
||||
counter_symbol->pass = pass_count;
|
||||
counter_symbol->result.val.intval = 0;
|
||||
}
|
||||
number = (unsigned long) counter_symbol->result.val.intval;
|
||||
// now append to the name to make it unique
|
||||
GlobalDynaBuf->size--; // forget terminator, we want to append
|
||||
do {
|
||||
DYNABUF_APPEND(GlobalDynaBuf, 'a' + (number & 15));
|
||||
number >>= 4;
|
||||
} while (number);
|
||||
DynaBuf_append(GlobalDynaBuf, '\0');
|
||||
if (increment)
|
||||
counter_symbol->result.val.intval++;
|
||||
}
|
50
src/symbol.h
Normal file
50
src/symbol.h
Normal file
@ -0,0 +1,50 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816 code.
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// symbol stuff
|
||||
#ifndef symbol_H
|
||||
#define symbol_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
|
||||
|
||||
struct symbol {
|
||||
struct result result; // expression flags and value
|
||||
int usage; // usage count
|
||||
int pass; // pass of creation (for anon counters)
|
||||
};
|
||||
|
||||
|
||||
// variables
|
||||
extern struct node_ra_t *symbols_forest[]; // trees (because of 8-bit hash)
|
||||
|
||||
|
||||
// clear symbol forest (is done early)
|
||||
extern void symbols_clear_init(void);
|
||||
// register pseudo opcodes (done later)
|
||||
extern void symbols_register_init(void);
|
||||
// function acts upon the symbol's flag bits and produces an error if needed.
|
||||
extern void symbol_set_value(struct symbol *symbol, struct result *new_value, int change_allowed);
|
||||
// parse label definition (can be either global or local).
|
||||
// name must be held in GlobalDynaBuf.
|
||||
extern void symbol_set_label(zone_t zone, int stat_flags, int force_bit, int change_allowed);
|
||||
// parse symbol definition (can be either global or local, may turn out to be a label).
|
||||
// name must be held in GlobalDynaBuf.
|
||||
extern void symbol_parse_definition(zone_t zone, int stat_flags);
|
||||
// search for symbol. create if nonexistant. if created, assign flags.
|
||||
// name must be held in GlobalDynaBuf.
|
||||
extern struct symbol *symbol_find(zone_t, int flags);
|
||||
// set global symbol to value, no questions asked (for "-D" switch)
|
||||
// name must be held in GlobalDynaBuf.
|
||||
extern void symbol_define(intval_t value);
|
||||
// dump global symbols to file
|
||||
extern void symbols_dump_all(FILE *fd);
|
||||
// fix name of anonymous forward label (held in GlobalDynaBuf, NOT TERMINATED!)
|
||||
// so it references the *next* anonymous forward label definition.
|
||||
extern void symbol_fix_forward_anon_name(int increment);
|
||||
|
||||
|
||||
#endif
|
@ -33,7 +33,7 @@ void typesystem_force_address_statement(int value)
|
||||
in_address_statement = value;
|
||||
}
|
||||
|
||||
void typesystem_want_imm(struct result_t *result)
|
||||
void typesystem_want_imm(struct result *result)
|
||||
{
|
||||
if (!warn_on_type_mismatch)
|
||||
return;
|
||||
@ -42,7 +42,7 @@ void typesystem_want_imm(struct result_t *result)
|
||||
if (result->addr_refs != 0)
|
||||
Throw_warning("Wrong type - expected integer.");
|
||||
}
|
||||
void typesystem_want_addr(struct result_t *result)
|
||||
void typesystem_want_addr(struct result *result)
|
||||
{
|
||||
if (!warn_on_type_mismatch)
|
||||
return;
|
||||
|
@ -10,16 +10,16 @@
|
||||
#include "config.h"
|
||||
|
||||
|
||||
// return whether explicit label definitions should force "address" mode
|
||||
// return whether explicit symbol definitions should force "address" mode
|
||||
extern int typesystem_says_address(void);
|
||||
// parse a block while forcing address mode
|
||||
extern void typesystem_force_address_block(void);
|
||||
// force address mode on or off for the next statement
|
||||
extern void typesystem_force_address_statement(int value);
|
||||
// warn if result is address instead of integer
|
||||
extern void typesystem_want_imm(struct result_t *result);
|
||||
// warn if result is integer instead of address
|
||||
extern void typesystem_want_addr(struct result_t *result);
|
||||
// warn if result is not integer
|
||||
extern void typesystem_want_imm(struct result *result);
|
||||
// warn if result is not address
|
||||
extern void typesystem_want_addr(struct result *result);
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user