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