mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-09-01 15:28:55 +00:00
Release 0.94.5: Fixed bugs in wrap-around branches and left-shifting floats. Several changes in library.
git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@15 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
parent
6de19a5afe
commit
059238874d
@ -3,86 +3,166 @@
|
||||
!ifdef lib_cbm_basic1_a !eof
|
||||
lib_cbm_basic1_a = 1
|
||||
|
||||
; token values
|
||||
token_END = $80
|
||||
token_FOR = $81
|
||||
token_NEXT = $82
|
||||
token_DATA = $83
|
||||
token_INPUT_ = $84 ; INPUT#
|
||||
token_INPUT = $85
|
||||
token_DIM = $86
|
||||
token_READ = $87
|
||||
token_LET = $88
|
||||
token_GOTO = $89
|
||||
token_RUN = $8a
|
||||
token_IF = $8b
|
||||
token_RESTORE = $8c
|
||||
token_GOSUB = $8d
|
||||
token_RETURN = $8e
|
||||
token_REM = $8f
|
||||
token_STOP = $90
|
||||
token_ON = $91
|
||||
token_WAIT = $92
|
||||
token_LOAD = $93
|
||||
token_SAVE = $94
|
||||
token_VERIFY = $95
|
||||
token_DEF = $96
|
||||
token_POKE = $97
|
||||
token_PRINT_ = $98 ; PRINT#
|
||||
token_PRINT = $99
|
||||
token_CONT = $9a
|
||||
token_LIST = $9b
|
||||
token_CLR = $9c
|
||||
token_CMD = $9d
|
||||
token_SYS = $9e
|
||||
token_OPEN = $9f
|
||||
token_CLOSE = $a0
|
||||
token_GET = $a1
|
||||
token_NEW = $a2
|
||||
token_TAB = $a3 ; the token already includes '('
|
||||
token_TO = $a4
|
||||
token_FN = $a5
|
||||
token_SPC = $a6 ; the token already includes '('
|
||||
token_THEN = $a7
|
||||
token_NOT = $a8
|
||||
token_STEP = $a9
|
||||
token_ADD = $aa ; '+'
|
||||
token_SUBTRACT = $ab ; '-'
|
||||
token_MULTIPLY = $ac ; '*'
|
||||
token_DIVIDE = $ad ; '/'
|
||||
token_POWEROF = $ae ; '^'
|
||||
token_AND = $af
|
||||
token_OR = $b0
|
||||
token_GREATER = $b1 ; '>'
|
||||
token_EQUAL = $b2 ; '='
|
||||
token_LESS = $b3 ; '<'
|
||||
token_SGN = $b4
|
||||
token_INT = $b5
|
||||
token_ABS = $b6
|
||||
token_USR = $b7
|
||||
token_FRE = $b8
|
||||
token_POS = $b9
|
||||
token_SQR = $ba
|
||||
token_RND = $bb
|
||||
token_LOG = $bc
|
||||
token_EXP = $bd
|
||||
token_COS = $be
|
||||
token_SIN = $bf
|
||||
token_TAN = $c0
|
||||
token_ATN = $c1
|
||||
token_PEEK = $c2
|
||||
token_LEN = $c3
|
||||
token_STR_ = $c4 ; STR$
|
||||
token_VAL = $c5
|
||||
token_ASC = $c6
|
||||
token_CHR_ = $c7 ; CHR$
|
||||
token_LEFT_ = $c8 ; LEFT$
|
||||
token_RIGHT_ = $c9 ; RIGHT$
|
||||
token_MID_ = $ca ; MID$
|
||||
|
||||
token_PI = $ff ; greek letter pi
|
||||
|
||||
|
||||
; Macros for inserting BASIC commands. Note that "#" and "$" characters in
|
||||
; BASIC keywords have been converted to "_" in the macro names.
|
||||
; *All* function macros already include the '(' character.
|
||||
|
||||
!macro b_END {!by $80}
|
||||
!macro b_FOR {!by $81}
|
||||
!macro b_NEXT {!by $82}
|
||||
!macro b_DATA {!by $83}
|
||||
!macro b_INPUT_ {!by $84} ; INPUT#
|
||||
!macro b_INPUT {!by $85}
|
||||
!macro b_DIM {!by $86}
|
||||
!macro b_READ {!by $87}
|
||||
!macro b_LET {!by $88}
|
||||
!macro b_GOTO {!by $89}
|
||||
!macro b_RUN {!by $8a}
|
||||
!macro b_IF {!by $8b}
|
||||
!macro b_RESTORE {!by $8c}
|
||||
!macro b_GOSUB {!by $8d}
|
||||
!macro b_RETURN {!by $8e}
|
||||
!macro b_REM {!by $8f}
|
||||
!macro b_STOP {!by $90}
|
||||
!macro b_ON {!by $91}
|
||||
!macro b_WAIT {!by $92}
|
||||
!macro b_LOAD {!by $93}
|
||||
!macro b_SAVE {!by $94}
|
||||
!macro b_VERIFY {!by $95}
|
||||
!macro b_END {!by token_END}
|
||||
!macro b_FOR {!by token_FOR}
|
||||
!macro b_NEXT {!by token_NEXT}
|
||||
!macro b_DATA {!by token_DATA}
|
||||
!macro b_INPUT_ {!by token_INPUT_} ; INPUT#
|
||||
!macro b_INPUT {!by token_INPUT}
|
||||
!macro b_DIM {!by token_DIM}
|
||||
!macro b_READ {!by token_READ}
|
||||
!macro b_LET {!by token_LET}
|
||||
!macro b_GOTO {!by token_GOTO}
|
||||
!macro b_RUN {!by token_RUN}
|
||||
!macro b_IF {!by token_IF}
|
||||
!macro b_RESTORE {!by token_RESTORE}
|
||||
!macro b_GOSUB {!by token_GOSUB}
|
||||
!macro b_RETURN {!by token_RETURN}
|
||||
!macro b_REM {!by token_REM}
|
||||
!macro b_STOP {!by token_STOP}
|
||||
!macro b_ON {!by token_ON}
|
||||
!macro b_WAIT {!by token_WAIT}
|
||||
!macro b_LOAD {!by token_LOAD}
|
||||
!macro b_SAVE {!by token_SAVE}
|
||||
!macro b_VERIFY {!by token_VERIFY}
|
||||
; As "DEF" cannot be used without "FN", here is a macro called "b_DEFFN"
|
||||
; instead of one called "b_DEF":
|
||||
!macro b_DEFFN {!by $96, $a5}
|
||||
!macro b_POKE {!by $97}
|
||||
!macro b_PRINT_ {!by $98} ; PRINT#
|
||||
!macro b_PRINT {!by $99}
|
||||
!macro b_CONT {!by $9a}
|
||||
!macro b_LIST {!by $9b}
|
||||
!macro b_CLR {!by $9c}
|
||||
!macro b_CMD {!by $9d}
|
||||
!macro b_SYS {!by $9e}
|
||||
!macro b_OPEN {!by $9f}
|
||||
!macro b_CLOSE {!by $a0}
|
||||
!macro b_GET {!by $a1}
|
||||
!macro b_NEW {!by $a2}
|
||||
!macro b_TAB {!by $a3} ; the token already includes '('
|
||||
!macro b_TO {!by $a4}
|
||||
!macro b_FN {!by $a5}
|
||||
!macro b_SPC {!by $a6} ; the token already includes '('
|
||||
!macro b_THEN {!by $a7}
|
||||
!macro b_NOT {!by $a8}
|
||||
!macro b_STEP {!by $a9}
|
||||
!macro b_ADD {!by $aa} ; '+'
|
||||
!macro b_SUBTRACT {!by $ab} ; '-'
|
||||
!macro b_MULTIPLY {!by $ac} ; '*'
|
||||
!macro b_DIVIDE {!by $ad} ; '/'
|
||||
!macro b_POWEROF {!by $ae} ; '^'
|
||||
!macro b_AND {!by $af}
|
||||
!macro b_OR {!by $b0}
|
||||
!macro b_GREATER {!by $b1} ; '>'
|
||||
!macro b_EQUAL {!by $b2} ; '='
|
||||
!macro b_LESS {!by $b3} ; '<'
|
||||
!macro b_SGN {!by $b4:!pet '('}
|
||||
!macro b_INT {!by $b5:!pet '('}
|
||||
!macro b_ABS {!by $b6:!pet '('}
|
||||
!macro b_USR {!by $b7:!pet '('}
|
||||
!macro b_FRE {!by $b8:!pet '('}
|
||||
!macro b_POS {!by $b9:!pet '('}
|
||||
!macro b_SQR {!by $ba:!pet '('}
|
||||
!macro b_RND {!by $bb:!pet '('}
|
||||
!macro b_LOG {!by $bc:!pet '('}
|
||||
!macro b_EXP {!by $bd:!pet '('}
|
||||
!macro b_COS {!by $be:!pet '('}
|
||||
!macro b_SIN {!by $bf:!pet '('}
|
||||
!macro b_TAN {!by $c0:!pet '('}
|
||||
!macro b_ATN {!by $c1:!pet '('}
|
||||
!macro b_PEEK {!by $c2:!pet '('}
|
||||
!macro b_LEN {!by $c3:!pet '('}
|
||||
!macro b_STR_ {!by $c4:!pet '('} ; STR$(
|
||||
!macro b_VAL {!by $c5:!pet '('}
|
||||
!macro b_ASC {!by $c6:!pet '('}
|
||||
!macro b_CHR_ {!by $c7:!pet '('} ; CHR$(
|
||||
!macro b_LEFT_ {!by $c8:!pet '('} ; LEFT$(
|
||||
!macro b_RIGHT_ {!by $c9:!pet '('} ; RIGHT$(
|
||||
!macro b_MID_ {!by $ca:!pet '('} ; MID$(
|
||||
!macro b_DEFFN {!by token_DEF, token_FN} ; DEFFN
|
||||
!macro b_POKE {!by token_POKE}
|
||||
!macro b_PRINT_ {!by token_PRINT_} ; PRINT#
|
||||
!macro b_PRINT {!by token_PRINT}
|
||||
!macro b_CONT {!by token_CONT}
|
||||
!macro b_LIST {!by token_LIST}
|
||||
!macro b_CLR {!by token_CLR}
|
||||
!macro b_CMD {!by token_CMD}
|
||||
!macro b_SYS {!by token_SYS}
|
||||
!macro b_OPEN {!by token_OPEN}
|
||||
!macro b_CLOSE {!by token_CLOSE}
|
||||
!macro b_GET {!by token_GET}
|
||||
!macro b_NEW {!by token_NEW}
|
||||
!macro b_TAB {!by token_TAB} ; TAB( the token already includes '('
|
||||
!macro b_TO {!by token_TO}
|
||||
!macro b_FN {!by token_FN}
|
||||
!macro b_SPC {!by token_SPC} ; SPC( the token already includes '('
|
||||
!macro b_THEN {!by token_THEN}
|
||||
!macro b_NOT {!by token_NOT}
|
||||
!macro b_STEP {!by token_STEP}
|
||||
!macro b_ADD {!by token_ADD} ; +
|
||||
!macro b_SUBTRACT {!by token_SUBTRACT} ; -
|
||||
!macro b_MULTIPLY {!by token_MULTIPLY} ; *
|
||||
!macro b_DIVIDE {!by token_DIVIDE} ; /
|
||||
!macro b_POWEROF {!by token_POWEROF} ; ^
|
||||
!macro b_AND {!by token_AND}
|
||||
!macro b_OR {!by token_OR}
|
||||
!macro b_GREATER {!by token_GREATER} ; >
|
||||
!macro b_EQUAL {!by token_EQUAL} ; =
|
||||
!macro b_LESS {!by token_LESS} ; <
|
||||
!macro b_SGN {!by token_SGN, $28} ; SGN(
|
||||
!macro b_INT {!by token_INT, $28} ; INT(
|
||||
!macro b_ABS {!by token_ABS, $28} ; ABS(
|
||||
!macro b_USR {!by token_USR, $28} ; USR(
|
||||
!macro b_FRE {!by token_FRE, $28} ; FRE(
|
||||
!macro b_POS {!by token_POS, $28} ; POS(
|
||||
!macro b_SQR {!by token_SQR, $28} ; SQR(
|
||||
!macro b_RND {!by token_RND, $28} ; RND(
|
||||
!macro b_LOG {!by token_LOG, $28} ; LOG(
|
||||
!macro b_EXP {!by token_EXP, $28} ; EXP(
|
||||
!macro b_COS {!by token_COS, $28} ; COS(
|
||||
!macro b_SIN {!by token_SIN, $28} ; SIN(
|
||||
!macro b_TAN {!by token_TAN, $28} ; TAN(
|
||||
!macro b_ATN {!by token_ATN, $28} ; ATN(
|
||||
!macro b_PEEK {!by token_PEEK, $28} ; PEEK(
|
||||
!macro b_LEN {!by token_LEN, $28} ; LEN(
|
||||
!macro b_STR_ {!by token_STR_, $28} ; STR$(
|
||||
!macro b_VAL {!by token_VAL, $28} ; VAL(
|
||||
!macro b_ASC {!by token_ASC, $28} ; ASC(
|
||||
!macro b_CHR_ {!by token_CHR_, $28} ; CHR$(
|
||||
!macro b_LEFT_ {!by token_LEFT_, $28} ; LEFT$(
|
||||
!macro b_RIGHT_ {!by token_RIGHT_, $28} ; RIGHT$(
|
||||
!macro b_MID_ {!by token_MID_, $28} ; MID$(
|
||||
|
||||
!macro b_PI {!by $ff}
|
||||
!macro b_PI {!by token_PI} ; greek letter pi
|
||||
|
@ -5,12 +5,17 @@ lib_cbm_basic10_a = 1
|
||||
|
||||
!source <cbm/basic7.a> ; from 0x80 to 0xff, 0xce 0x02 to 0xce 0x0a, 0xfe 0x02 to 0xfe 0x26
|
||||
|
||||
; GSHAPE/SSHAPE/DRAW have new names:
|
||||
!macro b_PASTE {!by $e3}
|
||||
!macro b_CUT {!by $e4}
|
||||
!macro b_LINE {!by $e5}
|
||||
; DIRECTORY has a new name:
|
||||
!macro b_DIR {!by $ee}
|
||||
; token values
|
||||
token_PASTE = $e3 ; was called GSHAPE in basic v7
|
||||
token_CUT = $e4 ; was called SSHAPE in basic v7
|
||||
token_LINE = $e5 ; was called DRAW in basic v7
|
||||
token_DIR = $ee ; was called DIRECTORY in basic v7
|
||||
|
||||
; Macros for inserting BASIC commands
|
||||
!macro b_PASTE {!by token_PASTE} ; aka GSHAPE
|
||||
!macro b_CUT {!by token_CUT} ; aka SSHAPE
|
||||
!macro b_LINE {!by token_LINE} ; aka DRAW
|
||||
!macro b_DIR {!by token_DIR} ; aka DIRECTORY
|
||||
|
||||
; STASH/FETCH/SWAP are all decoded to DMA:
|
||||
!macro b_DMA {!by $fe, $1f}
|
||||
|
@ -4,4 +4,9 @@
|
||||
lib_cbm_basic2_a = 1
|
||||
|
||||
!source <cbm/basic1.a> ; from 0x80 to 0xca
|
||||
!macro b_GO {!by $cb}
|
||||
|
||||
; token values
|
||||
token_GO = $cb
|
||||
|
||||
; Macros for inserting BASIC commands
|
||||
!macro b_GO {!by token_GO}
|
||||
|
@ -3,72 +3,124 @@
|
||||
!ifdef lib_cbm_basic3_5_a !eof
|
||||
lib_cbm_basic3_5_a = 1
|
||||
|
||||
; Macros for inserting BASIC commands. Note that "#" and "$" characters in
|
||||
; BASIC keywords have been converted to "_" in the macro names.
|
||||
; *All* function macros already include the '(' character.
|
||||
|
||||
!source <cbm/basic2.a> ; from 0x80 to $cb
|
||||
!macro b_RGR {!by $cc:!pet '('}
|
||||
!macro b_RCLR {!by $cd:!pet '('}
|
||||
|
||||
; token values
|
||||
token_RGR = $cc
|
||||
token_RCLR = $cd
|
||||
; if this file gets included via "cbm/basic7.a" or "cbm/basic10.a", do not define RLUM
|
||||
; (because v7 and higher use $ce as prefix byte for additional functions):
|
||||
!ifndef lib_cbm_basic7_a {
|
||||
!ifndef lib_cbm_basic10_a {
|
||||
!macro b_RLUM {!by $ce:!pet '('}
|
||||
token_RLUM = $ce
|
||||
}
|
||||
}
|
||||
!macro b_JOY {!by $cf:!pet '('}
|
||||
!macro b_RDOT {!by $d0:!pet '('}
|
||||
!macro b_DEC {!by $d1:!pet '('}
|
||||
!macro b_HEX_ {!by $d2:!pet '('} ; HEX$(
|
||||
!macro b_ERR_ {!by $d3:!pet '('} ; ERR$(
|
||||
!macro b_INSTR {!by $d4:!pet '('}
|
||||
!macro b_ELSE {!by $d5}
|
||||
!macro b_RESUME {!by $d6}
|
||||
!macro b_TRAP {!by $d7}
|
||||
!macro b_TRON {!by $d8}
|
||||
!macro b_TROFF {!by $d9}
|
||||
!macro b_SOUND {!by $da}
|
||||
!macro b_VOL {!by $db}
|
||||
!macro b_AUTO {!by $dc}
|
||||
!macro b_PUDEF {!by $dd}
|
||||
!macro b_GRAPHIC {!by $de}
|
||||
!macro b_PAINT {!by $df}
|
||||
!macro b_CHAR {!by $e0}
|
||||
!macro b_BOX {!by $e1}
|
||||
!macro b_CIRCLE {!by $e2}
|
||||
token_JOY = $cf
|
||||
token_RDOT = $d0
|
||||
token_DEC = $d1
|
||||
token_HEX_ = $d2 ; HEX$
|
||||
token_ERR_ = $d3 ; ERR$
|
||||
token_INSTR = $d4
|
||||
token_ELSE = $d5
|
||||
token_RESUME = $d6
|
||||
token_TRAP = $d7
|
||||
token_TRON = $d8
|
||||
token_TROFF = $d9
|
||||
token_SOUND = $da
|
||||
token_VOL = $db
|
||||
token_AUTO = $dc
|
||||
token_PUDEF = $dd
|
||||
token_GRAPHIC = $de
|
||||
token_PAINT = $df
|
||||
token_CHAR = $e0
|
||||
token_BOX = $e1
|
||||
token_CIRCLE = $e2
|
||||
; if this file gets included via "cbm/basic10.a", do not define GSHAPE/SSHAPE/DRAW
|
||||
; (because in v10, they are called PASTE/CUT/LINE):
|
||||
!ifndef lib_cbm_basic10_a {
|
||||
!macro b_GSHAPE {!by $e3}
|
||||
!macro b_SSHAPE {!by $e4}
|
||||
!macro b_DRAW {!by $e5}
|
||||
token_GSHAPE = $e3
|
||||
token_SSHAPE = $e4
|
||||
token_DRAW = $e5
|
||||
}
|
||||
!macro b_LOCATE {!by $e6}
|
||||
!macro b_COLOR {!by $e7}
|
||||
!macro b_SCNCLR {!by $e8}
|
||||
!macro b_SCALE {!by $e9}
|
||||
!macro b_HELP {!by $ea}
|
||||
!macro b_DO {!by $eb}
|
||||
!macro b_LOOP {!by $ec}
|
||||
!macro b_EXIT {!by $ed}
|
||||
token_LOCATE = $e6
|
||||
token_COLOR = $e7
|
||||
token_SCNCLR = $e8
|
||||
token_SCALE = $e9
|
||||
token_HELP = $ea
|
||||
token_DO = $eb
|
||||
token_LOOP = $ec
|
||||
token_EXIT = $ed
|
||||
; if this file gets included via "cbm/basic10.a", do not define DIRECTORY
|
||||
; (because in v10, it is called DIR):
|
||||
!ifndef lib_cbm_basic10_a {
|
||||
!macro b_DIRECTORY {!by $ee}
|
||||
token_DIRECTORY = $ee
|
||||
}
|
||||
!macro b_DSAVE {!by $ef}
|
||||
!macro b_DLOAD {!by $f0}
|
||||
!macro b_HEADER {!by $f1}
|
||||
!macro b_SCRATCH {!by $f2}
|
||||
!macro b_COLLECT {!by $f3}
|
||||
!macro b_COPY {!by $f4}
|
||||
!macro b_RENAME {!by $f5}
|
||||
!macro b_BACKUP {!by $f6}
|
||||
!macro b_DELETE {!by $f7}
|
||||
!macro b_RENUMBER {!by $f8}
|
||||
!macro b_KEY {!by $f9}
|
||||
!macro b_MONITOR {!by $fa}
|
||||
!macro b_USING {!by $fb}
|
||||
!macro b_UNTIL {!by $fc}
|
||||
!macro b_WHILE {!by $fd}
|
||||
token_DSAVE = $ef
|
||||
token_DLOAD = $f0
|
||||
token_HEADER = $f1
|
||||
token_SCRATCH = $f2
|
||||
token_COLLECT = $f3
|
||||
token_COPY = $f4
|
||||
token_RENAME = $f5
|
||||
token_BACKUP = $f6
|
||||
token_DELETE = $f7
|
||||
token_RENUMBER = $f8
|
||||
token_KEY = $f9
|
||||
token_MONITOR = $fa
|
||||
token_USING = $fb
|
||||
token_UNTIL = $fc
|
||||
token_WHILE = $fd
|
||||
|
||||
; Macros for inserting BASIC commands. Note that "#" and "$" characters in
|
||||
; BASIC keywords have been converted to "_" in the macro names.
|
||||
; *All* function macros already include the '(' character.
|
||||
!macro b_RGR {!by token_RGR, $28} ; RGR(
|
||||
!macro b_RCLR {!by token_RCLR, $28} ; RCLR(
|
||||
!macro b_RLUM {!by token_RLUM, $28} ; RLUM(
|
||||
!macro b_JOY {!by token_JOY, $28} ; JOY(
|
||||
!macro b_RDOT {!by token_RDOT, $28} ; RDOT(
|
||||
!macro b_DEC {!by token_DEC, $28} ; DEC(
|
||||
!macro b_HEX_ {!by token_HEX_, $28} ; HEX$(
|
||||
!macro b_ERR_ {!by token_ERR_, $28} ; ERR$(
|
||||
!macro b_INSTR {!by token_INSTR, $28} ; INSTR(
|
||||
!macro b_ELSE {!by token_ELSE}
|
||||
!macro b_RESUME {!by token_RESUME}
|
||||
!macro b_TRAP {!by token_TRAP}
|
||||
!macro b_TRON {!by token_TRON}
|
||||
!macro b_TROFF {!by token_TROFF}
|
||||
!macro b_SOUND {!by token_SOUND}
|
||||
!macro b_VOL {!by token_VOL}
|
||||
!macro b_AUTO {!by token_AUTO}
|
||||
!macro b_PUDEF {!by token_PUDEF}
|
||||
!macro b_GRAPHIC {!by token_GRAPHIC}
|
||||
!macro b_PAINT {!by token_PAINT}
|
||||
!macro b_CHAR {!by token_CHAR}
|
||||
!macro b_BOX {!by token_BOX}
|
||||
!macro b_CIRCLE {!by token_CIRCLE}
|
||||
!macro b_GSHAPE {!by token_GSHAPE}
|
||||
!macro b_SSHAPE {!by token_SSHAPE}
|
||||
!macro b_DRAW {!by token_DRAW}
|
||||
!macro b_LOCATE {!by token_LOCATE}
|
||||
!macro b_COLOR {!by token_COLOR}
|
||||
!macro b_SCNCLR {!by token_SCNCLR}
|
||||
!macro b_SCALE {!by token_SCALE}
|
||||
!macro b_HELP {!by token_HELP}
|
||||
!macro b_DO {!by token_DO}
|
||||
!macro b_LOOP {!by token_LOOP}
|
||||
!macro b_EXIT {!by token_EXIT}
|
||||
!macro b_DIRECTORY {!by token_DIRECTORY}
|
||||
!macro b_DSAVE {!by token_DSAVE}
|
||||
!macro b_DLOAD {!by token_DLOAD}
|
||||
!macro b_HEADER {!by token_HEADER}
|
||||
!macro b_SCRATCH {!by token_SCRATCH}
|
||||
!macro b_COLLECT {!by token_COLLECT}
|
||||
!macro b_COPY {!by token_COPY}
|
||||
!macro b_RENAME {!by token_RENAME}
|
||||
!macro b_BACKUP {!by token_BACKUP}
|
||||
!macro b_DELETE {!by token_DELETE}
|
||||
!macro b_RENUMBER {!by token_RENUMBER}
|
||||
!macro b_KEY {!by token_KEY}
|
||||
!macro b_MONITOR {!by token_MONITOR}
|
||||
!macro b_USING {!by token_USING}
|
||||
!macro b_UNTIL {!by token_UNTIL}
|
||||
!macro b_WHILE {!by token_WHILE}
|
||||
|
@ -4,19 +4,39 @@
|
||||
lib_cbm_basic4_a = 1
|
||||
|
||||
!source <cbm/basic2.a> ; from 0x80 to $cb
|
||||
|
||||
; CAUTION - these tokens are different to the ones in BASIC 3.5, BASIC 7 and BASIC 10!
|
||||
!macro b_CONCAT {!by $cc}
|
||||
!macro b_DOPEN {!by $cd}
|
||||
!macro b_DCLOSE {!by $ce}
|
||||
!macro b_RECORD {!by $cf}
|
||||
!macro b_HEADER {!by $d0}
|
||||
!macro b_COLLECT {!by $d1}
|
||||
!macro b_BACKUP {!by $d2}
|
||||
!macro b_COPY {!by $d3}
|
||||
!macro b_APPEND {!by $d4}
|
||||
!macro b_DSAVE {!by $d5}
|
||||
!macro b_DLOAD {!by $d6}
|
||||
!macro b_CATALOG {!by $d7}
|
||||
!macro b_RENAME {!by $d8}
|
||||
!macro b_SCRATCH {!by $d9}
|
||||
!macro b_DIRECTORY {!by $da}
|
||||
|
||||
; token values
|
||||
token_CONCAT = $cc
|
||||
token_DOPEN = $cd
|
||||
token_DCLOSE = $ce
|
||||
token_RECORD = $cf
|
||||
token_HEADER = $d0
|
||||
token_COLLECT = $d1
|
||||
token_BACKUP = $d2
|
||||
token_COPY = $d3
|
||||
token_APPEND = $d4
|
||||
token_DSAVE = $d5
|
||||
token_DLOAD = $d6
|
||||
token_CATALOG = $d7
|
||||
token_RENAME = $d8
|
||||
token_SCRATCH = $d9
|
||||
token_DIRECTORY = $da
|
||||
|
||||
; Macros for inserting BASIC commands:
|
||||
!macro b_CONCAT {!by token_CONCAT}
|
||||
!macro b_DOPEN {!by token_DOPEN}
|
||||
!macro b_DCLOSE {!by token_DCLOSE}
|
||||
!macro b_RECORD {!by token_RECORD}
|
||||
!macro b_HEADER {!by token_HEADER}
|
||||
!macro b_COLLECT {!by token_COLLECT}
|
||||
!macro b_BACKUP {!by token_BACKUP}
|
||||
!macro b_COPY {!by token_COPY}
|
||||
!macro b_APPEND {!by token_APPEND}
|
||||
!macro b_DSAVE {!by token_DSAVE}
|
||||
!macro b_DLOAD {!by token_DLOAD}
|
||||
!macro b_CATALOG {!by token_CATALOG}
|
||||
!macro b_RENAME {!by token_RENAME}
|
||||
!macro b_SCRATCH {!by token_SCRATCH}
|
||||
!macro b_DIRECTORY {!by token_DIRECTORY}
|
||||
|
106
ACME_Lib/cbm/c64/float.a
Normal file
106
ACME_Lib/cbm/c64/float.a
Normal file
@ -0,0 +1,106 @@
|
||||
;ACME 0.94.4
|
||||
|
||||
!ifdef lib_cbm_c64_float_a !eof
|
||||
lib_cbm_c64_float_a = 1
|
||||
|
||||
; Here are some definitions to help you call the floating-point functions of the
|
||||
; C64's BASIC ROM. They work using two structures in zero page, called fac1 and
|
||||
; fac2 (floating-point accumulator 1 and 2, located at $61 and $69).
|
||||
|
||||
!source <cbm/mflpt.a> ; include macro to store floats in MFLPT format
|
||||
|
||||
; convenience macros:
|
||||
|
||||
; some float functions need a memory address in A (low) and Y (high)
|
||||
!macro movAY .adr {
|
||||
lda #<.adr
|
||||
ldy #>.adr
|
||||
}
|
||||
; ...or in X (low) and Y (high)
|
||||
!macro movXY .adr {
|
||||
ldx #<.adr
|
||||
ldy #>.adr
|
||||
}
|
||||
; other float functions expect or output a value in Y (low) and A (high)
|
||||
!macro movYA .val {
|
||||
ldy #<.val
|
||||
lda #>.val
|
||||
}
|
||||
!macro ldYA .adr {
|
||||
ldy .adr
|
||||
lda .adr + 1
|
||||
}
|
||||
!macro stYA .adr {
|
||||
sty .adr
|
||||
sta .adr + 1
|
||||
}
|
||||
; ...or in X (low) and A (high)
|
||||
!macro ldXA .adr {
|
||||
ldx .adr
|
||||
lda .adr + 1
|
||||
}
|
||||
|
||||
; constants in five-byte "mflpt" format
|
||||
mflpt_pi = $aea8 ; 3.1415926...
|
||||
mflpt_minus32768 = $b1a5 ; -32768
|
||||
mflpt_1 = $b9bc ; 1
|
||||
mflpt_half_sqr2 = $b9d6 ; SQR(2) / 2
|
||||
mflpt_sqr2 = $b9db ; SQR(2)
|
||||
mflpt_minus_point5 = $b9e0 ; -.5
|
||||
mflpt_log_2 = $b9e5 ; LOG(2)
|
||||
mflpt_10 = $baf9 ; 10
|
||||
mflpt_99999999 = $bdb3 ; 99 999 999
|
||||
mflpt_999999999 = $bdb8 ; 999 999 999
|
||||
mflpt_1000000000 = $bdbd ; 1 000 000 000
|
||||
mflpt_point5 = $bf11 ; .5, also known as 1 / 2
|
||||
mflpt_log_2_reciprocal = $bfbf ; 1 / LOG(2)
|
||||
mflpt_half_pi = $e2e0 ; PI / 2
|
||||
mflpt_double_pi = $e2e5 ; 2 * PI (also see $e309)
|
||||
mflpt_point25 = $e2ea ; .25, also known as 1 / 4
|
||||
mflpt_2_pi = $e309 ; 2 * PI (also see $e2e5)
|
||||
|
||||
; functions - a few points to note:
|
||||
; fac1/2 might get clobbered even if not mentioned in the function's name,
|
||||
; because stuff like fac1_times_memYYAA will load the value from memory
|
||||
; into fac2 first.
|
||||
; for subtraction and division, the left operand is in fac2, the right operand in fac1.
|
||||
fac1_print = $aabc ; print string representation of contents of fac1
|
||||
fac1_to_signedYA = $b1aa ; might throw ILLEGAL QUANTITY
|
||||
fac1_to_signed16 = $b1bf ; might throw ILLEGAL QUANTITY
|
||||
fac1_read_signedYA = $b391 ; convert 16 bit signed int to float
|
||||
fac1_read_unsignedY = $b3a2 ; convert 8 bit unsigned int to float
|
||||
fac1_read_string = $b7b5 ; $22/23 must point to string, A must be string length
|
||||
fac1_to_unsignedYA = $b7f7 ; might throw ILLEGAL QUANTITY (result is also in $14/15)
|
||||
fac1_add_point5 = $b849 ; for rounding, call this before fac1_int
|
||||
fac1_memAY_minus_fac1 = $b850
|
||||
fac1_fac2_minus_fac1 = $b853
|
||||
fac1_add_memAY = $b867
|
||||
fac1_add_fac2 = $b86a
|
||||
fac1_log = $b9ea ; LOG()
|
||||
fac1_times_memAY = $ba28
|
||||
fac2_read_memAY = $ba8c ; load value from memory into fac2
|
||||
fac1_times_10 = $bae2
|
||||
fac1_divide_by_10 = $bafe
|
||||
fac1_divide_memAY_by_fac1 = $bb0f
|
||||
fac1_read_memAY = $bba2 ; load value from memory into fac1
|
||||
fac1_to_memXY = $bbd4 ; store fac1 to memory
|
||||
fac1_read_fac2 = $bbfc ; copy fac2 to fac1
|
||||
fac2_read_fac1 = $bc0c ; copy fac1 to fac2
|
||||
fac1_sign_to_A = $bc2b ; $ff, $0, $1 for negative, zero, positive
|
||||
fac1_sgn = $bc39 ; SGN()
|
||||
fac1_abs = $bc58 ; ABS()
|
||||
fac1_compare_to_memAY = $bc5b
|
||||
fac1_to_signed32 = $bc9b
|
||||
fac1_int = $bccc ; INT()
|
||||
fac1_print_unsignedXA = $bdcd
|
||||
fac1_to_string = $bddd ; string is stored at $0100 (address returned in YYAA)
|
||||
fac1_sqr = $bf71 ; SQR()
|
||||
fac1_fac2_to_the_power_of_memAY = $bf78
|
||||
fac1_negate = $bfb4
|
||||
fac1_exp = $bfed ; EXP()
|
||||
; end of basic rom jumps to start of kernel rom!
|
||||
fac1_rnd = $e097 ; RND()
|
||||
fac1_cos = $e264 ; COS()
|
||||
fac1_sin = $e26b ; SIN()
|
||||
fac1_tan = $e2b4 ; TAN()
|
||||
fac1_atn = $e30e ; ATN()
|
79
ACME_Lib/cbm/mflpt.a
Normal file
79
ACME_Lib/cbm/mflpt.a
Normal file
@ -0,0 +1,79 @@
|
||||
;ACME 0.94.5
|
||||
|
||||
!ifdef lib_cbm_mflpt_a !eof
|
||||
lib_cbm_mflpt_a = 1
|
||||
|
||||
; here's a macro for writing floating point numbers in the "mflpt" format used by BASIC.
|
||||
; "mflpt" stands for "memory floating point", where the sign bit is packed into the mantissa.
|
||||
|
||||
; to use it, write:
|
||||
; +mflpt 3.1415926 ; each use will take up five bytes of memory
|
||||
|
||||
|
||||
; now for the technical stuff (stop reading right now if you value your sanity)
|
||||
|
||||
; five-byte layout in memory:
|
||||
; eeeeeeee smmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm ; eight bits exponent, 32 bits mantissa with sign bit overlay
|
||||
|
||||
; exponent byte:
|
||||
; exponent has a bias of 128 (128 means the decimal point is right before the mantissa's leading zero)
|
||||
; if exponent is zero, number value is considered to be zero, regardless of mantissa
|
||||
; exponents 1..128 are for values < 1
|
||||
; exponents 129..255 are for values >= 1
|
||||
|
||||
; mantissa:
|
||||
; mantissa is stored big-endian(!)
|
||||
; the mantissa's mandatory leading '1' is replaced by the sign bit
|
||||
|
||||
; so logically, this is equivalent to:
|
||||
; + .1mmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm * 2^(eeeeeeee - 128) if sign bit is 0
|
||||
; - .1mmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm * 2^(eeeeeeee - 128) if sign bit is 1
|
||||
|
||||
|
||||
|
||||
; this is ugly, but it gets the job done
|
||||
; (if it's stupid, but it works, then it's not stupid)
|
||||
!macro mflpt .value {
|
||||
!set .float = float(.value) ; make sure to do passes until value is defined
|
||||
!ifndef .float {
|
||||
!by $ff, $ff, $ff, $ff, $ff ; place holder
|
||||
} else {
|
||||
; value is defined, so split up into sign and non-negative value
|
||||
!if .float < 0 {
|
||||
!set .sign = $80
|
||||
!set .float = -.float
|
||||
} else {
|
||||
!set .sign = $00
|
||||
}
|
||||
!if .float = 0 {
|
||||
!by 0, 0, 0, 0, 0 ; zero is represented as all bits zero
|
||||
} else {
|
||||
; split up into exponent and mantissa
|
||||
!set .exponent = 128 + 32 ; 128 is cbm's bias, 32 is this algo's bias
|
||||
; if mantissa is too large, shift right and adjust exponent
|
||||
!do while .float >= (2.0 ^ 32.0) {
|
||||
!set .float = .float >> 1
|
||||
!set .exponent = .exponent + 1
|
||||
}
|
||||
; if mantissa is too small, shift left and adjust exponent
|
||||
!do while .float < (2.0 ^ 31.0) {
|
||||
!set .float = .float << 1
|
||||
!set .exponent = .exponent - 1
|
||||
}
|
||||
!if .exponent < 1 {
|
||||
!warn "MFLPT underflow, using zero instead"
|
||||
!set .float = 0
|
||||
!set .exponent = 0
|
||||
!set .sign = 0
|
||||
}
|
||||
!if .exponent > 255 {
|
||||
!error "MFLPT overflow"
|
||||
}
|
||||
!by .exponent
|
||||
!by (127 & int(.float >> 24)) | .sign
|
||||
!by 255 & int(.float >> 16)
|
||||
!by 255 & int(.float >> 8)
|
||||
!by 255 & int(.float)
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,28 @@ platform used. There should be another help file in this archive
|
||||
outlining the platform specific changes.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: New in release 0.94.5
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Fixed bug: wrap-around branches (from $ff80+ to zp and back) were
|
||||
reported as errors. Thanks to Bitbreaker for reporting this.
|
||||
Fixed bug: left-shifting float values went wrong for large shifts.
|
||||
New error message: "Target not in bank (0xTARGET)" for branches.
|
||||
Fixed example program to get it to assemble with current library.
|
||||
Streamlined "Floats.txt" docs.
|
||||
|
||||
Changes in library files:
|
||||
<cbm/basicWHATEVER.a> files now contain opcode_* constants in addition
|
||||
to macros.
|
||||
Added <cbm/mflpt.a>, containing a macro to store a float value in the
|
||||
five-byte format used by CBM basic (and while writing that macro,
|
||||
found the left-shift-float bug mentioned above, so the macro needs
|
||||
this fixed version to work).
|
||||
Added <cbm/c64/float.a>, containing definitions for using the BASIC
|
||||
interpreter's float functions and constants.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: New in release 0.94.4
|
||||
----------------------------------------------------------------------
|
||||
|
@ -47,8 +47,9 @@ Assembling buggy JMP($xxff) instruction
|
||||
The original 6502 processor has a bug: When executing an indirect
|
||||
JMP instruction where the low byte of the argument equals $ff, it
|
||||
fetches the high byte of the jump target address not from memory
|
||||
location ARGUMENT+1, but from ARGUMENT-255. Therefore ACME issues
|
||||
this warning if you are about to generate such an 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.
|
||||
|
||||
@ -157,8 +158,8 @@ Division by zero.
|
||||
Guess what - you attempted to divide by zero.
|
||||
|
||||
Exponent is negative.
|
||||
Using negative exponents would only give sensible results when
|
||||
using floating point maths.
|
||||
Using negative exponents only give sensible results when using
|
||||
floating point maths.
|
||||
|
||||
File name quotes not found ("" or <>).
|
||||
File names have to be given in quotes. Either "" quoting for files
|
||||
@ -227,11 +228,16 @@ Source file contains illegal character.
|
||||
Syntax error.
|
||||
Guess what - there's a syntax error.
|
||||
|
||||
Target not in bank (0xTARGET).
|
||||
You tried to branch to an address not in the 0x0000..0xffff range.
|
||||
Relative addressing (branch commands or PER) cannot leave the
|
||||
current code bank of 64 KiB.
|
||||
|
||||
Target out of range (N; M too far).
|
||||
A relative addressing (branch commands or PER) only has a limited
|
||||
range. You exceeded it. N is the attempted offset, M is the difference
|
||||
to the limit - so if you succeed in optimizing M bytes away, the code
|
||||
would assemble.
|
||||
Branch commands use relative addressing, which only has a limited
|
||||
range. You exceeded it. N is the attempted offset, M is the
|
||||
difference to the limit - so if you succeed in optimizing M bytes
|
||||
away, the code would assemble.
|
||||
|
||||
There's more than one character.
|
||||
You used a text string in an arithmetic expression, but the string
|
||||
|
@ -28,4 +28,3 @@ Just in case you wonder:
|
||||
"macedit" is an unusably bad text editor for the C128. The source
|
||||
code is not meant to be a good example of ACME's capabilities.
|
||||
Please *don't* look at it. :)
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
Hi!
|
||||
|
||||
This is a preliminary release of ACME. I added basic support for
|
||||
floating point maths. Consider this a special version for beta
|
||||
testers. Known bugs: Segment counting may be screwed up at the moment.
|
||||
|
||||
New:
|
||||
The maths parser knows about floating point maths, so you can finally
|
||||
build sin/cos tables directly in ACME. But the expression parser still
|
||||
uses integer calculations per default. Here are the rules:
|
||||
ACME
|
||||
|
||||
...the ACME Crossassembler for Multiple Environments
|
||||
|
||||
--- floating-point support ---
|
||||
|
||||
|
||||
In release 0.92, ACME gained some experimental support for floating-
|
||||
point maths, so you can finally build sin/cos tables directly in ACME.
|
||||
But the expression parser still uses integer calculations per default.
|
||||
Here are the rules:
|
||||
|
||||
a) if a maths operation is useless when done with integers, it is done
|
||||
with floats and returns a float. Applies to sin(), cos(), tan(),
|
||||
@ -28,7 +31,12 @@ To force a numerical value to be flagged as being a float, just add
|
||||
a decimal point and a zero. If a decimal value ends with a
|
||||
dot character, ACME switches to using the C type "double" and keeps
|
||||
reading digits. The value is then flagged internally as being float.
|
||||
|
||||
CAUTION: Float usage is only activated when a decimal point has been
|
||||
found, so don't expect "100000000000000000000" to work.
|
||||
"100000000000000000000.0" won't work either, because when the decimal
|
||||
point gets parsed, the integer value will have overflown already. As
|
||||
there is no support yet for the "e" format (1e20 for 1*10^20) either,
|
||||
the only way to enter this value is by writing "1.0 * 10.0 ^ 20.0".
|
||||
|
||||
Examples:
|
||||
|
||||
@ -46,14 +54,11 @@ You can use the new float() and int() functions to ensure the type of
|
||||
maths:
|
||||
|
||||
!byte a / b * c ; depends on a/b/c's internal flags
|
||||
!byte float(a)/b*c ; calculation is done in FP
|
||||
!byte int(a)/int(b)*int(c); calculation is done in integer
|
||||
!byte float(a) / b * c ; calculation is done as float
|
||||
!byte int(a) / int(b) * int(c) ; calculation is done as int
|
||||
|
||||
As you will have guessed, the trigonometric functions assume radians
|
||||
for measuring angles (90 degrees equals PI/2).
|
||||
|
||||
Have a look at the example source code, it builds some sin/cos tables.
|
||||
|
||||
Have fun, and let me know what you think,
|
||||
|
||||
Marco Baye
|
||||
Have a look at the example source code "trigono.a", it builds some
|
||||
sin/cos tables.
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
...the ACME Crossassembler for Multiple Environments
|
||||
|
||||
Release 0.91
|
||||
Release 0.94.5
|
||||
|
||||
- free software -
|
||||
|
||||
(C) 1998-2006 Marco Baye
|
||||
(C) 1998-2013 Marco Baye
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
@ -54,16 +54,17 @@ The files in the docs directory and what they contain:
|
||||
65816.txt Stuff specific to the 65816 processor
|
||||
AddrModes.txt How to choose non-standard addressing modes
|
||||
AllPOs.txt Lists ACME's pseudo opcodes. Use as a reference.
|
||||
Changes.txt The change log.
|
||||
Changes.txt The change log
|
||||
COPYING Version 2 of the GNU General Public License
|
||||
Errors.txt Lists ACME's error messages and what they mean.
|
||||
Example.txt Information on how to assemble the example sources.
|
||||
Floats.txt About the support for floating-point values
|
||||
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.
|
||||
Source.txt How to compile ACME.
|
||||
Upgrade.txt Incompatibilities to earlier versions.
|
||||
Illegals.txt Support for undocumented opcodes
|
||||
Lib.txt Information about the library
|
||||
QuickRef.txt All the basic stuff about ACME
|
||||
Source.txt How to compile ACME
|
||||
Upgrade.txt Incompatibilities to earlier versions
|
||||
|
||||
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
|
||||
@ -170,7 +171,7 @@ Section: Contacting the author
|
||||
----------------------------------------------------------------------
|
||||
|
||||
The newest version of ACME can be found at the ACME homepage:
|
||||
http://home.pages.de/~mac_bacon/smorbrod/acme/
|
||||
http://sourceforge.net/p/acme-crossass/
|
||||
|
||||
If you want to report a bug or make a suggestion, then simply send
|
||||
me an email:
|
||||
|
@ -246,7 +246,7 @@ Section: The maths parser
|
||||
----------------------------------------------------------------------
|
||||
|
||||
ACME has a relatively powerful maths parser. This parser is used
|
||||
whenever ACME expects to read an integer value. Supported operations
|
||||
whenever ACME expects to read a numerical value. Supported operations
|
||||
include addition, subtraction, multiplication, divisions, comparisons,
|
||||
shifts, negation, boolean operations and some assembler-specific stuff
|
||||
like extracting the "low byte", the "high byte" or the "bank byte"
|
||||
|
@ -12,7 +12,7 @@ General Public License. Therefore, the sources must be made publicly
|
||||
accessible. If this archive does not contain the source file tree, you
|
||||
can download it from the ACME web page at
|
||||
|
||||
http://home.pages.de/~mac_bacon/smorbrod/acme/
|
||||
http://sourceforge.net/p/acme-crossass/
|
||||
|
||||
To build ACME, you need a recent C compiler and a "make" utility. On
|
||||
most systems, typing "make" should suffice to build the binary. See
|
||||
|
@ -9,8 +9,8 @@
|
||||
*= $1300
|
||||
!ct pet
|
||||
!source <6502/std.a>
|
||||
!ifndef Lib_6502_std_a {
|
||||
!serious "To assemble this program, you need to install the ACME library."
|
||||
!ifndef lib_6502_std_a {
|
||||
!serious "To assemble this program, you need to install the current ACME library."
|
||||
}
|
||||
!source "me/macros.a"
|
||||
!source "me/const.a"
|
||||
@ -74,3 +74,5 @@ Spätere Änderungen am Source:
|
||||
Now throws serious error if the library file could not be loaded.
|
||||
7 Apr 2013:
|
||||
Converted to UTF-8
|
||||
27 Jun 2013:
|
||||
Adjusted to change in library.
|
||||
|
@ -15,10 +15,10 @@
|
||||
// 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.94.4" // update before release (FIXME)
|
||||
#define RELEASE "0.94.5" // update before release (FIXME)
|
||||
#define CODENAME "Zarquon" // update before release
|
||||
#define CHANGE_DATE "9 Oct" // update before release
|
||||
#define CHANGE_YEAR "2012" // update before release
|
||||
#define CHANGE_DATE "27 Jun" // update before release
|
||||
#define CHANGE_YEAR "2013" // 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
|
||||
|
||||
|
@ -625,6 +625,7 @@ static void expect_operand_or_monadic_operator(void)
|
||||
// Now GotByte = char after closing quote
|
||||
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
|
||||
GetByte(); // start after '.'
|
||||
// check for fractional part of float value
|
||||
@ -995,7 +996,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
|
||||
// monadic operators
|
||||
case OPHANDLE_NOT:
|
||||
// different operations for fp and int
|
||||
// fp becomes int
|
||||
if (RIGHT_FLAGS & MVALUE_IS_FP)
|
||||
right_fp_to_int();
|
||||
RIGHT_INTVAL = ~(RIGHT_INTVAL);
|
||||
@ -1141,7 +1142,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
if (RIGHT_FLAGS & MVALUE_IS_FP)
|
||||
right_fp_to_int();
|
||||
if (LEFT_FLAGS & MVALUE_IS_FP)
|
||||
LEFT_FPVAL *= (1 << RIGHT_INTVAL);
|
||||
LEFT_FPVAL *= pow(2.0, RIGHT_INTVAL);
|
||||
else
|
||||
LEFT_INTVAL <<= RIGHT_INTVAL;
|
||||
goto handle_flags_and_dec_stacks;
|
||||
@ -1156,6 +1157,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_LSR:
|
||||
// fp become int
|
||||
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
|
||||
both_ensure_int(TRUE);
|
||||
LEFT_INTVAL = ((uintval_t) LEFT_INTVAL) >> RIGHT_INTVAL;
|
||||
@ -1216,6 +1218,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_AND:
|
||||
// fp become int
|
||||
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
|
||||
both_ensure_int(TRUE);
|
||||
LEFT_INTVAL &= RIGHT_INTVAL;
|
||||
@ -1225,12 +1228,14 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
Throw_first_pass_warning("\"EOR\" is deprecated; use \"XOR\" instead.");
|
||||
/*FALLTHROUGH*/
|
||||
case OPHANDLE_XOR:
|
||||
// fp become int
|
||||
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
|
||||
both_ensure_int(TRUE);
|
||||
LEFT_INTVAL ^= RIGHT_INTVAL;
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_OR:
|
||||
// fp become int
|
||||
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
|
||||
both_ensure_int(TRUE);
|
||||
LEFT_INTVAL |= RIGHT_INTVAL;
|
||||
|
@ -189,6 +189,7 @@ static enum eos_t throw_string(const char prefix[], void (*fn)(const char *))
|
||||
|
||||
|
||||
////
|
||||
//static enum eos_t PO_debug(void)
|
||||
//static enum eos_t PO_info(void)
|
||||
//static enum eos_t PO_print(void)
|
||||
//{
|
||||
@ -233,6 +234,7 @@ static struct node_t pseudo_opcodes[] = {
|
||||
PREDEFNODE("binary", PO_binary),
|
||||
PREDEFNODE("fi", PO_fill),
|
||||
PREDEFNODE("fill", PO_fill),
|
||||
// PREDEFNODE("debug", PO_debug),
|
||||
// PREDEFNODE("info", PO_info),
|
||||
// PREDEFNODE("print", PO_print),
|
||||
PREDEFNODE("warn", PO_warn),
|
||||
|
12
src/cpu.c
12
src/cpu.c
@ -66,8 +66,8 @@ static struct cpu_t CPU_65816 = {
|
||||
struct cpu_t *CPU_now; // struct of current CPU type (default 6502)
|
||||
struct result_int_t CPU_pc; // (pseudo) program counter at start of statement
|
||||
int CPU_2add; // increase PC by this after statement
|
||||
static intval_t current_offset; // PseudoPC - MemIndex
|
||||
static int uses_pseudo_pc; // offset assembly active?
|
||||
static intval_t current_offset; // PseudoPC - MemIndex (FIXME - why is this needed?)
|
||||
static int uses_pseudo_pc; // offset assembly active? FIXME - what is this for?
|
||||
// predefined stuff
|
||||
static struct node_t *CPU_tree = NULL; // tree to hold CPU types
|
||||
static struct node_t CPUs[] = {
|
||||
@ -144,16 +144,17 @@ static const char Warning_old_offset_assembly[] =
|
||||
// start offset assembly
|
||||
static enum eos_t PO_pseudopc(void)
|
||||
{
|
||||
// future algo: remember outer memaddress and outer pseudopc
|
||||
int outer_state = uses_pseudo_pc;
|
||||
intval_t new_pc,
|
||||
outer_offset = current_offset;
|
||||
int outer_flags = CPU_pc.flags;
|
||||
|
||||
// set new
|
||||
new_pc = ALU_defined_int();
|
||||
new_pc = ALU_defined_int(); // FIXME - allow for undefined pseudopc!
|
||||
current_offset = (current_offset + new_pc - CPU_pc.intval) & 0xffff;
|
||||
CPU_pc.intval = new_pc;
|
||||
CPU_pc.flags |= MVALUE_DEFINED;
|
||||
CPU_pc.flags |= MVALUE_DEFINED; // FIXME - remove!
|
||||
uses_pseudo_pc = TRUE;
|
||||
// if there's a block, parse that and then restore old value!
|
||||
if (Parse_optional_block()) {
|
||||
@ -162,6 +163,7 @@ static enum eos_t PO_pseudopc(void)
|
||||
CPU_pc.flags = outer_flags;
|
||||
CPU_pc.intval = (outer_offset + CPU_pc.intval - current_offset) & 0xffff;
|
||||
current_offset = outer_offset;
|
||||
// future algo: new outer pseudopc = (old outer pseudopc + (current memaddress - outer memaddress)) & 0xffff
|
||||
} else {
|
||||
Throw_first_pass_warning(Warning_old_offset_assembly);
|
||||
}
|
||||
@ -181,7 +183,7 @@ static enum eos_t PO_realpc(void)
|
||||
}
|
||||
|
||||
|
||||
// return whether offset assembly is active
|
||||
// return whether offset assembly is active (FIXME - remove this function)
|
||||
int CPU_uses_pseudo_pc(void)
|
||||
{
|
||||
return uses_pseudo_pc;
|
||||
|
@ -36,7 +36,7 @@ extern void CPUtype_init(void);
|
||||
extern void CPU_init(void);
|
||||
// set default values for pass
|
||||
extern void CPU_passinit(struct cpu_t *cpu_type);
|
||||
// set program counter to defined value
|
||||
// set program counter to defined value (FIXME - allow undefined!)
|
||||
extern void CPU_set_pc(intval_t new_pc);
|
||||
// try to find CPU type held in DynaBuf. Returns whether succeeded.
|
||||
extern int CPU_find_cpu_struct(struct cpu_t **target);
|
||||
|
26
src/flow.c
26
src/flow.c
@ -25,13 +25,10 @@
|
||||
|
||||
|
||||
// type definitions
|
||||
enum cond_key_t {
|
||||
ID_UNTIL, // Handles to store instead of
|
||||
ID_WHILE, // the UNTIL and WHILE keywords
|
||||
};
|
||||
|
||||
struct loop_condition {
|
||||
enum cond_key_t type; // either ID_UNTIL or ID_WHILE
|
||||
int line; // original line number
|
||||
int invert; // actually bool (0 for WHILE, 1 for UNTIL)
|
||||
char *body; // pointer to actual expression
|
||||
};
|
||||
|
||||
@ -41,8 +38,8 @@ struct loop_condition {
|
||||
// predefined stuff
|
||||
static struct node_t *condkey_tree = NULL; // tree to hold UNTIL and WHILE
|
||||
static struct node_t condkeys[] = {
|
||||
PREDEFNODE("until", ID_UNTIL),
|
||||
PREDEFLAST("while", ID_WHILE),
|
||||
PREDEFNODE("until", TRUE), // UNTIL inverts the condition
|
||||
PREDEFLAST("while", FALSE), // WHILE does not change the condition
|
||||
// ^^^^ this marks the last element
|
||||
};
|
||||
|
||||
@ -62,7 +59,7 @@ static void parse_ram_block(int line_number, char *body)
|
||||
|
||||
|
||||
// try to read a condition into DynaBuf and store copy pointer in
|
||||
// given loopcond_t structure.
|
||||
// given loop_condition structure.
|
||||
// if no condition given, NULL is written to structure.
|
||||
// call with GotByte = first interesting character
|
||||
static void store_condition(struct loop_condition *condition, char terminator)
|
||||
@ -74,6 +71,7 @@ static void store_condition(struct loop_condition *condition, char terminator)
|
||||
// Check for empty condition
|
||||
if (GotByte == terminator) {
|
||||
// Write NULL condition, then return
|
||||
condition->invert = FALSE;
|
||||
condition->body = NULL;
|
||||
return;
|
||||
}
|
||||
@ -83,10 +81,11 @@ static void store_condition(struct loop_condition *condition, char terminator)
|
||||
// Search for new tree item
|
||||
if (!Tree_easy_scan(condkey_tree, &node_body, GlobalDynaBuf)) {
|
||||
Throw_error(exception_syntax);
|
||||
condition->invert = FALSE;
|
||||
condition->body = NULL;
|
||||
return;
|
||||
}
|
||||
condition->type = (enum cond_key_t) node_body;
|
||||
condition->invert = (int) node_body;
|
||||
// Write given condition into buffer
|
||||
SKIPSPACE();
|
||||
DYNABUF_CLEAR(GlobalDynaBuf);
|
||||
@ -104,7 +103,7 @@ static int check_condition(struct loop_condition *condition)
|
||||
|
||||
// First, check whether there actually *is* a condition
|
||||
if (condition->body == NULL)
|
||||
return 1; // non-existant conditions are always true
|
||||
return TRUE; // non-existing conditions are always true
|
||||
|
||||
// set up input for expression evaluation
|
||||
Input_now->line_number = condition->line;
|
||||
@ -113,7 +112,7 @@ static int check_condition(struct loop_condition *condition)
|
||||
expression = ALU_defined_int();
|
||||
if (GotByte)
|
||||
Throw_serious_error(exception_syntax);
|
||||
return (condition->type == ID_UNTIL) ? !expression : !!expression;
|
||||
return condition->invert ? !expression : !!expression;
|
||||
}
|
||||
|
||||
|
||||
@ -128,9 +127,10 @@ static enum eos_t PO_do(void) // Now GotByte = illegal char
|
||||
int go_on,
|
||||
loop_start; // line number of loop pseudo opcode
|
||||
// Init
|
||||
condition2.type = ID_UNTIL;
|
||||
condition2.body = NULL;
|
||||
condition1.invert = FALSE;
|
||||
condition1.body = NULL;
|
||||
condition2.invert = FALSE;
|
||||
condition2.body = NULL;
|
||||
|
||||
// Read head condition to buffer
|
||||
SKIPSPACE();
|
||||
|
@ -275,19 +275,19 @@ void Parse_until_eob_or_eof(void)
|
||||
break;
|
||||
case '+':
|
||||
GetByte();
|
||||
if ((GotByte == '.')
|
||||
if ((GotByte == LOCAL_PREFIX)
|
||||
|| (BYTEFLAGS(GotByte) & CONTS_KEYWORD))
|
||||
Macro_parse_call();
|
||||
else
|
||||
parse_forward_anon_def(&statement_flags);
|
||||
break;
|
||||
case '!':
|
||||
case PSEUDO_OPCODE_PREFIX:
|
||||
parse_pseudo_opcode();
|
||||
break;
|
||||
case '*':
|
||||
parse_pc_def();
|
||||
break;
|
||||
case '.':
|
||||
case LOCAL_PREFIX:
|
||||
parse_local_label_def(&statement_flags);
|
||||
break;
|
||||
default:
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
|
||||
#define PSEUDO_OPCODE_PREFIX '!' // FIXME - this is not yet used consistently!
|
||||
#define LOCAL_PREFIX '.' // FIXME - this is not yet used consistently!
|
||||
|
||||
// Constants
|
||||
|
||||
|
@ -378,14 +378,14 @@ int Input_append_keyword_to_global_dynabuf(void)
|
||||
return length;
|
||||
}
|
||||
|
||||
// Check whether GotByte is a dot.
|
||||
// Check whether GotByte is LOCAL_PREFIX (default '.').
|
||||
// If not, store global zone value.
|
||||
// If yes, store current zone value and read next byte.
|
||||
// Then jump to Input_read_keyword(), which returns length of keyword.
|
||||
int Input_read_zone_and_keyword(zone_t *zone)
|
||||
{
|
||||
SKIPSPACE();
|
||||
if (GotByte == '.') {
|
||||
if (GotByte == LOCAL_PREFIX) {
|
||||
GetByte();
|
||||
*zone = Section_now->zone;
|
||||
} else {
|
||||
|
12
src/macro.c
12
src/macro.c
@ -78,7 +78,7 @@ void Macro_init(void)
|
||||
// Read macro zone and title. Title is read to GlobalDynaBuf and then copied
|
||||
// over to internal_name DynaBuf, where ARG_SEPARATOR is added.
|
||||
// In user_macro_name DynaBuf, the original name is reconstructed (even with
|
||||
// '.' prefix) so a copy can be linked to the resulting macro struct.
|
||||
// LOCAL_PREFIX) so a copy can be linked to the resulting macro struct.
|
||||
static zone_t get_zone_and_title(void)
|
||||
{
|
||||
zone_t macro_zone;
|
||||
@ -89,7 +89,7 @@ static zone_t get_zone_and_title(void)
|
||||
DYNABUF_CLEAR(user_macro_name);
|
||||
DYNABUF_CLEAR(internal_name);
|
||||
if (macro_zone != ZONE_GLOBAL)
|
||||
DynaBuf_append(user_macro_name, '.');
|
||||
DynaBuf_append(user_macro_name, LOCAL_PREFIX);
|
||||
DynaBuf_add_string(user_macro_name, GLOBALDYNABUF_CURRENT);
|
||||
DynaBuf_add_string(internal_name, GLOBALDYNABUF_CURRENT);
|
||||
DynaBuf_append(user_macro_name, '\0');
|
||||
@ -168,7 +168,7 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
|
||||
// now GotByte = first non-space after title
|
||||
DYNABUF_CLEAR(GlobalDynaBuf); // prepare to hold formal parameters
|
||||
// GlobalDynaBuf = "" (will hold formal parameter list)
|
||||
// user_macro_name = ['.'] MacroTitle NUL
|
||||
// user_macro_name = [LOCAL_PREFIX] MacroTitle NUL
|
||||
// internal_name = MacroTitle ARG_SEPARATOR (grows to signature)
|
||||
// Accept n>=0 comma-separated formal parameters before CHAR_SOB ('{').
|
||||
// Valid argument formats are:
|
||||
@ -187,9 +187,9 @@ void Macro_parse_definition(void) // Now GotByte = illegal char after "!macro"
|
||||
DynaBuf_append(GlobalDynaBuf, REFERENCE_CHAR);
|
||||
GetByte();
|
||||
}
|
||||
// handle prefix for local labels ('.')
|
||||
if (GotByte == '.') {
|
||||
DynaBuf_append(GlobalDynaBuf, '.');
|
||||
// handle prefix for local labels (LOCAL_PREFIX, normally '.')
|
||||
if (GotByte == LOCAL_PREFIX) {
|
||||
DynaBuf_append(GlobalDynaBuf, LOCAL_PREFIX);
|
||||
GetByte();
|
||||
}
|
||||
// handle label name
|
||||
|
58
src/mnemo.c
58
src/mnemo.c
@ -571,53 +571,65 @@ static void group_only_implied_addressing(int opcode)
|
||||
Input_ensure_EOS();
|
||||
}
|
||||
|
||||
// helper function to output "Target out of range" message
|
||||
static void too_far(intval_t actual, intval_t minimum, intval_t maximum)
|
||||
// helper function to output "Target not in bank" message
|
||||
static void not_in_bank(intval_t target)
|
||||
{
|
||||
char buffer[60]; // 640K should be enough for anybody
|
||||
|
||||
sprintf(buffer, "Target out of range (%ld; %ld too far).", actual, actual < minimum ? minimum - actual : actual - maximum);
|
||||
sprintf(buffer, "Target not in bank (0x%lx).", target);
|
||||
Throw_error(buffer);
|
||||
}
|
||||
|
||||
// Mnemonics using only 8bit relative addressing (short branch instructions).
|
||||
static void group_only_relative8_addressing(int opcode)
|
||||
{
|
||||
struct result_int_t result;
|
||||
struct result_int_t target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
|
||||
ALU_int_result(&result);
|
||||
if (result.flags & MVALUE_DEFINED) {
|
||||
result.intval -= (CPU_pc.intval + 2);
|
||||
if ((result.intval < -128) || (result.intval > 127))
|
||||
too_far(result.intval, -128, 127);
|
||||
ALU_int_result(&target);
|
||||
if (CPU_pc.flags & target.flags & MVALUE_DEFINED) {
|
||||
if ((target.intval | 0xffff) != 0xffff) {
|
||||
not_in_bank(target.intval);
|
||||
} else {
|
||||
offset = (target.intval - (CPU_pc.intval + 2)) & 0xffff; // clip to 16 bit offset
|
||||
// fix sign
|
||||
if (offset & 0x8000)
|
||||
offset -= 0x10000;
|
||||
// range check
|
||||
if ((offset < -128) || (offset > 127)) {
|
||||
char buffer[60]; // 640K should be enough for anybody
|
||||
|
||||
sprintf(buffer, "Target out of range (%ld; %ld too far).", offset, offset < -128 ? -128 - offset : offset - 127);
|
||||
Throw_error(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
Output_byte(opcode);
|
||||
// this fn has its own range check (see above).
|
||||
// No reason to irritate the user with another error message,
|
||||
// so use Output_byte() instead of Output_8b()
|
||||
//Output_8b(result.value);
|
||||
Output_byte(result.intval);
|
||||
//Output_8b(offset);
|
||||
Output_byte(offset);
|
||||
Input_ensure_EOS();
|
||||
}
|
||||
|
||||
// Mnemonics using only 16bit relative addressing (BRL and PER).
|
||||
static void group_only_relative16_addressing(int opcode)
|
||||
{
|
||||
struct result_int_t result;
|
||||
struct result_int_t target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
|
||||
ALU_int_result(&result);
|
||||
if (result.flags & MVALUE_DEFINED) {
|
||||
result.intval -= (CPU_pc.intval + 3);
|
||||
if ((result.intval < -32768) || (result.intval > 32767))
|
||||
too_far(result.intval, -32768, 32767);
|
||||
ALU_int_result(&target);
|
||||
if (CPU_pc.flags & target.flags & MVALUE_DEFINED) {
|
||||
if ((target.intval | 0xffff) != 0xffff) {
|
||||
not_in_bank(target.intval);
|
||||
} else {
|
||||
offset = (target.intval - (CPU_pc.intval + 3)) & 0xffff;
|
||||
// no further checks necessary, 16-bit branches can access whole bank
|
||||
}
|
||||
}
|
||||
Output_byte(opcode);
|
||||
// this fn has its own range check (see above).
|
||||
// No reason to irritate the user with another error message,
|
||||
// so use Output_byte() instead of Output_16b()
|
||||
//Output_16b(result.value);
|
||||
Output_byte(result.intval);
|
||||
Output_byte(result.intval >> 8);
|
||||
Output_16b(offset);
|
||||
Input_ensure_EOS();
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,7 @@ void Output_passinit(signed long start_addr)
|
||||
segment_start = 0;
|
||||
}
|
||||
// other stuff
|
||||
segment_max = OUTBUFFERSIZE-1;
|
||||
segment_max = OUTBUFFERSIZE - 1;
|
||||
segment_flags = 0;
|
||||
}
|
||||
|
||||
@ -513,6 +513,7 @@ void Output_start_segment(void)
|
||||
new_flags |= (int) node_body;
|
||||
}
|
||||
|
||||
// to allow for undefined pseudopc, this must be changed to use memaddress instead!
|
||||
if (CPU_pc.flags & MVALUE_DEFINED) {
|
||||
// it's a redefinition. Check some things:
|
||||
// check whether new low
|
||||
|
Loading…
Reference in New Issue
Block a user