Release 0.95: Added experimental type checking system (still missing docs, however). Made warning about old "!for" syntax configurable.

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@34 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye
2014-06-02 00:47:46 +00:00
parent c8ff626943
commit d152f60acd
43 changed files with 1516 additions and 1219 deletions

View File

@@ -1,13 +1,15 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_6502_std_a !eof !ifdef lib_6502_std_a !eof
lib_6502_std_a = 1 lib_6502_std_a = 1
; labels and macros for plain 6502 processor ; labels and macros for plain 6502 processor
cpu_nmi = $fffa !address {
cpu_reset = $fffc cpu_nmi = $fffa
cpu_irq = $fffe cpu_reset = $fffc
cpu_irq = $fffe
}
; skip byte ; skip byte
!macro bit8 { !macro bit8 {

View File

@@ -1,21 +1,23 @@
;ACME 0.07 ;ACME 0.95
!ifdef Lib_65816_std_a !eof !ifdef lib_65816_std_a !eof
Lib_65816_std_a = 1 lib_65816_std_a = 1
; Labels and macros for Western Digital's 65c816 processor ; Labels and macros for Western Digital's 65c816 processor
cpu_e_cop = $fff4 !address {
cpu_e_abort = $fff8 cpu_e_cop = $fff4
cpu_e_nmi = $fffa cpu_e_abort = $fff8
cpu_e_reset = $fffc cpu_e_nmi = $fffa
cpu_e_irq = $fffe cpu_e_reset = $fffc
cpu_e_irq = $fffe
cpu_n_cop = $fff4 cpu_n_cop = $fff4
cpu_n_brk = $fff6 cpu_n_brk = $fff6
cpu_n_abort = $fff8 cpu_n_abort = $fff8
cpu_n_nmi = $fffa cpu_n_nmi = $fffa
cpu_n_irq = $fffe cpu_n_irq = $fffe
}
!macro cpu_emu {; switch to emulation mode !macro cpu_emu {; switch to emulation mode
sec sec
@@ -71,10 +73,9 @@ cpu_n_irq = $fffe
!macro inc24 .t {; increase 24-bit counter !macro inc24 .t {; increase 24-bit counter
inc .t inc .t
bne .j; "*" syntax not used here because size of ".t" is unknown bne +
inc .t + 1 inc .t + 1
bne .j bne +
inc .t + 2 inc .t + 2
.j +
} }

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c128_kernel_a !eof !ifdef lib_cbm_c128_kernel_a !eof
lib_cbm_c128_kernel_a = 1 lib_cbm_c128_kernel_a = 1
@@ -6,27 +6,31 @@ lib_cbm_c128_kernel_a = 1
; Taken from the web. ; Taken from the web.
; Sorry, I can't give credit because I don't have the URL anymore. ; Sorry, I can't give credit because I don't have the URL anymore.
k_spin_spout = $ff47 !address {
k_close_all = $ff4a k_spin_spout = $ff47
k_c64mode = $ff4d k_close_all = $ff4a
k_dma_call = $ff50 k_c64mode = $ff4d
k_boot_call = $ff53 k_dma_call = $ff50
k_phoenix = $ff56 k_boot_call = $ff53
k_lkupla = $ff59 k_phoenix = $ff56
k_lkupsa = $ff5c k_lkupla = $ff59
k_swapper = $ff5f k_lkupsa = $ff5c
k_dlchr = $ff62 k_swapper = $ff5f
k_pfkey = $ff65 k_dlchr = $ff62
k_setbnk = $ff68 k_pfkey = $ff65
k_getcfg = $ff6b k_setbnk = $ff68
k_jsrfar = $ff6e k_getcfg = $ff6b
k_jmpfar = $ff71 k_jsrfar = $ff6e
k_indfet = $ff74 k_jmpfar = $ff71
k_indsta = $ff77 k_indfet = $ff74
k_indcmp = $ff7a k_indsta = $ff77
k_primm = $ff7d k_indcmp = $ff7a
k_release_number = $ff80 k_primm = $ff7d
k_release_number = $ff80
}
!source <cbm/kernel.a> ; $ff81-$fff5 is backward compatible to older machines !source <cbm/kernel.a> ; $ff81-$fff5 is backward compatible to older machines
; $fff6/$fff7 are unused (ff ff) ; $fff6/$fff7 are unused (ff ff)
k_indirect128mode = $fff8 ; indirect vector, without JMP command! !address {
k_indirect128mode = $fff8 ; indirect vector, without JMP command!
}
; $fffa through $ffff are cpu hardware vectors (see <6502/std.a>) ; $fffa through $ffff are cpu hardware vectors (see <6502/std.a>)

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c128_mmu_a !eof !ifdef lib_cbm_c128_mmu_a !eof
lib_cbm_c128_mmu_a = 1 lib_cbm_c128_mmu_a = 1
@@ -8,138 +8,151 @@ lib_cbm_c128_mmu_a = 1
; registers in i/o area (i/o needs to be enabled to access these): ; registers in i/o area (i/o needs to be enabled to access these):
; configuration register !address {
mmu_cr_d500 = $d500 ; same as "mmu_cr" at $ff00. Use "mmu_cr" instead, as that is *always* available. ; configuration register
; preconfiguration registers (internal format just like mmu_cr) mmu_cr_d500 = $d500 ; same as "mmu_cr" at $ff00. Use "mmu_cr" instead, as that is *always* available.
mmu_pcr_a = $d501 ; c128 kernel default is $3f (BANK 0) ; preconfiguration registers (internal format just like mmu_cr)
mmu_pcr_b = $d502 ; c128 kernel default is $7f (BANK 1) mmu_pcr_a = $d501 ; c128 kernel default is $3f (BANK 0)
mmu_pcr_c = $d503 ; c128 kernel default is $01 (BANK 14) mmu_pcr_b = $d502 ; c128 kernel default is $7f (BANK 1)
mmu_pcr_d = $d504 ; c128 kernel default is $41 (all system roms, with ram 1) mmu_pcr_c = $d503 ; c128 kernel default is $01 (BANK 14)
; contents of cr and all four pcr: mmu_pcr_d = $d504 ; c128 kernel default is $41 (all system roms, with ram 1)
mmu_CR_RAMBANK_MASK = %##...... ; this controls which RAM bank is used in areas where RAM is enabled }
; mmu_CR_RAMBANK_0 = %........ ; contents of cr and all four pcr:
mmu_CR_RAMBANK_1 = %.#...... mmu_CR_RAMBANK_MASK = %##...... ; this controls which RAM bank is used in areas where RAM is enabled
mmu_CR_RAMBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead) ;mmu_CR_RAMBANK_0 = %........
mmu_CR_RAMBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead) mmu_CR_RAMBANK_1 = %.#......
mmu_CR_RAMBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead)
mmu_CR_RAMBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
mmu_CR_HIGH_MASK = %..##.... ; this controls the "high area" (c000..ffff), but i/o (d000..dfff) is separate mmu_CR_HIGH_MASK = %..##.... ; this controls the "high area" (c000..ffff), but i/o (d000..dfff) is separate
; mmu_CR_HIGH_SYSROM = %........ ; editor, charset (or i/o, see below), kernel ;mmu_CR_HIGH_SYSROM = %........ ; editor, charset (or i/o, see below), kernel
mmu_CR_HIGH_INTFUNCROM = %...#.... mmu_CR_HIGH_INTFUNCROM = %...#....
mmu_CR_HIGH_EXTFUNCROM = %..#..... mmu_CR_HIGH_EXTFUNCROM = %..#.....
mmu_CR_HIGH_RAM = %..##.... mmu_CR_HIGH_RAM = %..##....
mmu_CR_MID_MASK = %....##.. ; this controls the "middle area" (8000..bfff) mmu_CR_MID_MASK = %....##.. ; this controls the "middle area" (8000..bfff)
; mmu_CR_MID_SYSROM = %........ ; this is the upper half of basic ;mmu_CR_MID_SYSROM = %........ ; this is the upper half of basic
mmu_CR_MID_INTFUNCROM = %.....#.. mmu_CR_MID_INTFUNCROM = %.....#..
mmu_CR_MID_EXTFUNCROM = %....#... mmu_CR_MID_EXTFUNCROM = %....#...
mmu_CR_MID_RAM = %....##.. mmu_CR_MID_RAM = %....##..
mmu_CR_LOW_MASK = %......#. ; this controls the "low area" (4000..7fff) mmu_CR_LOW_MASK = %......#. ; this controls the "low area" (4000..7fff)
; mmu_CR_LOW_SYSROM = %........ ; this is the lower half of basic ;mmu_CR_LOW_SYSROM = %........ ; this is the lower half of basic
mmu_CR_LOW_RAM = %......#. mmu_CR_LOW_RAM = %......#.
mmu_CR_IO_MASK = %.......# ; this controls i/o space (d000..dfff) mmu_CR_IO_MASK = %.......# ; this controls i/o space (d000..dfff)
; mmu_CR_IO_ON = %........ ;mmu_CR_IO_ON = %........
mmu_CR_IO_OFF = %.......# ; if i/o is off, contents depend on "high area" mmu_CR_IO_OFF = %.......# ; if i/o is off, contents depend on "high area"
; configuration register values used by C128 firmware (lookup table at $f7f0, see end of file): ; configuration register values used by C128 firmware (lookup table at $f7f0, see end of file):
mmu_CR_BANK0 = $3f ; full 64 KiB ram bank 0 mmu_CR_BANK0 = $3f ; full 64 KiB ram bank 0
mmu_CR_BANK1 = $7f ; full 64 KiB ram bank 1 mmu_CR_BANK1 = $7f ; full 64 KiB ram bank 1
mmu_CR_BANK2 = $bf ; full 64 KiB ram bank 2 mmu_CR_BANK2 = $bf ; full 64 KiB ram bank 2
mmu_CR_BANK3 = $ff ; full 64 KiB ram bank 3 mmu_CR_BANK3 = $ff ; full 64 KiB ram bank 3
mmu_CR_BANK4 = $16 ; 32 KiB bank 0; 32 KiB IFROM with i/o overlay mmu_CR_BANK4 = $16 ; 32 KiB bank 0; 32 KiB IFROM with i/o overlay
mmu_CR_BANK5 = $56 ; 32 KiB bank 1; 32 KiB IFROM with i/o overlay mmu_CR_BANK5 = $56 ; 32 KiB bank 1; 32 KiB IFROM with i/o overlay
mmu_CR_BANK6 = $96 ; 32 KiB bank 2; 32 KiB IFROM with i/o overlay mmu_CR_BANK6 = $96 ; 32 KiB bank 2; 32 KiB IFROM with i/o overlay
mmu_CR_BANK7 = $d6 ; 32 KiB bank 3; 32 KiB IFROM with i/o overlay mmu_CR_BANK7 = $d6 ; 32 KiB bank 3; 32 KiB IFROM with i/o overlay
mmu_CR_BANK8 = $2a ; 32 KiB bank 0; 32 KiB EFROM with i/o overlay mmu_CR_BANK8 = $2a ; 32 KiB bank 0; 32 KiB EFROM with i/o overlay
mmu_CR_BANK9 = $6a ; 32 KiB bank 1; 32 KiB EFROM with i/o overlay mmu_CR_BANK9 = $6a ; 32 KiB bank 1; 32 KiB EFROM with i/o overlay
mmu_CR_BANK10 = $aa ; 32 KiB bank 2; 32 KiB EFROM with i/o overlay mmu_CR_BANK10 = $aa ; 32 KiB bank 2; 32 KiB EFROM with i/o overlay
mmu_CR_BANK11 = $ea ; 32 KiB bank 3; 32 KiB EFROM with i/o overlay mmu_CR_BANK11 = $ea ; 32 KiB bank 3; 32 KiB EFROM with i/o overlay
mmu_CR_BANK12 = $06 ; 32 KiB bank 0; 16 KiB IFROM; 16 KiB kernel with i/o overlay mmu_CR_BANK12 = $06 ; 32 KiB bank 0; 16 KiB IFROM; 16 KiB kernel with i/o overlay
mmu_CR_BANK13 = $0a ; 32 KiB bank 0; 16 KiB EFROM; 16 KiB kernel with i/o overlay mmu_CR_BANK13 = $0a ; 32 KiB bank 0; 16 KiB EFROM; 16 KiB kernel with i/o overlay
mmu_CR_BANK14 = $01 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with font overlay mmu_CR_BANK14 = $01 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with font overlay
mmu_CR_BANK15 = $00 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with i/o overlay mmu_CR_BANK15 = $00 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with i/o overlay
; An unmodified C128 does not have a "ram bank 2" or "ram bank 3". ; An unmodified C128 does not have a "ram bank 2" or "ram bank 3".
; Whenever one of these is activated, ram banks 0 and 1 will be used instead. ; Whenever one of these is activated, ram banks 0 and 1 will be used instead.
; IFROM means internal function ROM (socket U36) ; IFROM means internal function ROM (socket U36)
; EFROM means external function ROM (socket in a REU, for example) ; EFROM means external function ROM (socket in a REU, for example)
; mode configuration register !address {
mmu_mcr = $d505 ; mode configuration register
; contents: mmu_mcr = $d505
mmu_MCR_40COLUMNS = %#....... ; 40/80 key: 0 means pressed, 1 means released (writable! if cleared, will always read as 0!) }
mmu_MCR_C64MODE = %.#...... ; setting this bit makes the MMU disappear from the memory map :) ; contents:
mmu_MCR_EXROM = %..#..... ; if zero on boot, system will enter c64 mode (writable!) mmu_MCR_40COLUMNS = %#....... ; 40/80 key: 0 means pressed, 1 means released (writable! if cleared, will always read as 0!)
mmu_MCR_GAME = %...#.... ; if zero on boot, system will enter c64 mode (writable!) mmu_MCR_C64MODE = %.#...... ; setting this bit makes the MMU disappear from the memory map :)
mmu_MCR_FSDIR_OUTPUT = %....#... ; direction of fast serial bus mmu_MCR_EXROM = %..#..... ; if zero on boot, system will enter c64 mode (writable!)
mmu_MCR_UNUSED = %.....##. ; always set mmu_MCR_GAME = %...#.... ; if zero on boot, system will enter c64 mode (writable!)
mmu_MCR_8502MODE = %.......# ; setting this to zero switches to Z80 cpu mmu_MCR_FSDIR_OUTPUT = %....#... ; direction of fast serial bus
mmu_MCR_UNUSED = %.....##. ; always set
mmu_MCR_8502MODE = %.......# ; setting this to zero switches to Z80 cpu
; ram configuration register !address {
mmu_rcr = $d506 ; ram configuration register
; contents: mmu_rcr = $d506
mmu_RCR_VICBANK_MASK = %##...... ; this controls which RAM bank is "seen" by VIC }
; mmu_RCR_VICBANK_0 = %........ ; contents:
mmu_RCR_VICBANK_1 = %.#...... mmu_RCR_VICBANK_MASK = %##...... ; this controls which RAM bank is "seen" by VIC
mmu_RCR_VICBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead) ;mmu_RCR_VICBANK_0 = %........
mmu_RCR_VICBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead) mmu_RCR_VICBANK_1 = %.#......
mmu_RCR_VICBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead)
mmu_RCR_VICBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
mmu_RCR_RAMBLOCK_MASK = %..##.... ; on an unmodified c128, these bits are irrelevant (they select 256 KiB of 1 MiB of memory) mmu_RCR_RAMBLOCK_MASK = %..##.... ; on an unmodified c128, these bits are irrelevant (they select 256 KiB of 1 MiB of memory)
; mmu_RCR_RAMBLOCK_0 = %........ ;mmu_RCR_RAMBLOCK_0 = %........
mmu_RCR_RAMBLOCK_1 = %...#.... ; on an unmodified c128, there is only ram block 0 mmu_RCR_RAMBLOCK_1 = %...#.... ; on an unmodified c128, there is only ram block 0
mmu_RCR_RAMBLOCK_2 = %..#..... ; on an unmodified c128, there is only ram block 0 mmu_RCR_RAMBLOCK_2 = %..#..... ; on an unmodified c128, there is only ram block 0
mmu_RCR_RAMBLOCK_3 = %..##.... ; on an unmodified c128, there is only ram block 0 mmu_RCR_RAMBLOCK_3 = %..##.... ; on an unmodified c128, there is only ram block 0
mmu_RCR_SHARE_MASK = %....##.. mmu_RCR_SHARE_MASK = %....##..
; mmu_RCR_SHARE_NONE = %........ ;mmu_RCR_SHARE_NONE = %........
mmu_RCR_SHARE_BOTTOM = %.....#.. ; system default mmu_RCR_SHARE_BOTTOM = %.....#.. ; system default
mmu_RCR_SHARE_TOP = %....#... mmu_RCR_SHARE_TOP = %....#...
mmu_RCR_SHARESIZE_MASK = %......## mmu_RCR_SHARESIZE_MASK = %......##
; mmu_RCR_SHARESIZE_1K = %........ ; system default ;mmu_RCR_SHARESIZE_1K = %........ ; system default
mmu_RCR_SHARESIZE_4K = %.......# mmu_RCR_SHARESIZE_4K = %.......#
mmu_RCR_SHARESIZE_8K = %......#. mmu_RCR_SHARESIZE_8K = %......#.
mmu_RCR_SHARESIZE_16K = %......## mmu_RCR_SHARESIZE_16K = %......##
; page pointers. writes to "high" register will be latched (reading gives old value) until "low" register is written to !address {
mmu_p0low = $d507 ; page 0 pointer low (a8..a15), default $00 ; page pointers. writes to "high" register will be latched (reading gives old value) until "low" register is written to
mmu_p0high = $d508 ; page 0 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful) mmu_p0low = $d507 ; page 0 pointer low (a8..a15), default $00
mmu_p1low = $d509 ; page 1 pointer low (a8..a15), default $01 mmu_p0high = $d508 ; page 0 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful)
mmu_p1high = $d50a ; page 1 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful) mmu_p1low = $d509 ; page 1 pointer low (a8..a15), default $01
mmu_PxH_UNUSED = %####.... ; always set mmu_p1high = $d50a ; page 1 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful)
}
mmu_PxH_UNUSED = %####.... ; always set
mmu_PxH_RAMBLOCK_MASK = %....##.. mmu_PxH_RAMBLOCK_MASK = %....##..
; mmu_PxH_RAMBLOCK_0 = %........ ;mmu_PxH_RAMBLOCK_0 = %........
mmu_PxH_RAMBLOCK_1 = %.....#.. ; on an unmodified c128, there is only ram block 0 mmu_PxH_RAMBLOCK_1 = %.....#.. ; on an unmodified c128, there is only ram block 0
mmu_PxH_RAMBLOCK_2 = %....#... ; on an unmodified c128, there is only ram block 0 mmu_PxH_RAMBLOCK_2 = %....#... ; on an unmodified c128, there is only ram block 0
mmu_PxH_RAMBLOCK_3 = %....##.. ; on an unmodified c128, there is only ram block 0 mmu_PxH_RAMBLOCK_3 = %....##.. ; on an unmodified c128, there is only ram block 0
mmu_PxH_RAMBANK_MASK = %......## mmu_PxH_RAMBANK_MASK = %......##
; mmu_PxH_RAMBANK_0 = %........ ;mmu_PxH_RAMBANK_0 = %........
mmu_PxH_RAMBANK_1 = %.......# mmu_PxH_RAMBANK_1 = %.......#
mmu_PxH_RAMBANK_2 = %......#. ; on an unmodified c128, there is no ram bank 2 (0 will be used instead) mmu_PxH_RAMBANK_2 = %......#. ; on an unmodified c128, there is no ram bank 2 (0 will be used instead)
mmu_PxH_RAMBANK_3 = %......## ; on an unmodified c128, there is no ram bank 3 (1 will be used instead) mmu_PxH_RAMBANK_3 = %......## ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
!address {
; version register
mmu_vr = $d50b ; read-only, value is $20
}
mmu_VR_BANKS_MASK = %####.... ; 2 ram banks
mmu_VR_VERSION_MASK = %....#### ; mmu version 0
; version register
mmu_vr = $d50b ; read-only, value is $20
mmu_VR_BANKS_MASK = %####.... ; 2 ram banks
mmu_VR_VERSION_MASK = %....#### ; mmu version 0
; reading addresses up until $d5ff returns $ff ; reading addresses up until $d5ff returns $ff
; these registers are always available (in *every* memory configuration) unless C64 mode is entered: ; these registers are always available (in *every* memory configuration) unless C64 mode is entered:
; configuration register !address {
mmu_cr = $ff00 ; always use this instead of $d500 ; configuration register
; load configuration registers: mmu_cr = $ff00 ; always use this instead of $d500
; a read access will return the value of the corresponding preconfiguration register ; load configuration registers:
; any write access will copy the value of the corresponding preconfiguration register to mmu_cr ; a read access will return the value of the corresponding preconfiguration register
mmu_lcr_a = $ff01 ; c128 kernel default is $3f (BANK 0) ; any write access will copy the value of the corresponding preconfiguration register to mmu_cr
mmu_lcr_b = $ff02 ; c128 kernel default is $7f (BANK 1) mmu_lcr_a = $ff01 ; c128 kernel default is $3f (BANK 0)
mmu_lcr_c = $ff03 ; c128 kernel default is $01 (BANK 14) mmu_lcr_b = $ff02 ; c128 kernel default is $7f (BANK 1)
mmu_lcr_d = $ff04 ; c128 kernel default is $41 (all system roms, with ram 1) mmu_lcr_c = $ff03 ; c128 kernel default is $01 (BANK 14)
mmu_lcr_d = $ff04 ; c128 kernel default is $41 (all system roms, with ram 1)
; the c128 ROMs contain a look-up table to convert bank numbers to their ; the c128 ROMs contain a look-up table to convert bank numbers to their
; corresponding configuration register values: ; corresponding configuration register values:
; romc_* needs "high rom area" enabled ($c000..$ffff) ; romc_* needs "high rom area" enabled ($c000..$ffff)
romc_bank_to_cr_table = $f7f0 ; 3f 7f bf ff 16 56 96 d6 2a 6a aa ea 06 0a 01 00 romc_bank_to_cr_table = $f7f0 ; 3f 7f bf ff 16 56 96 d6 2a 6a aa ea 06 0a 01 00
}

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c128_vdc_a !eof !ifdef lib_cbm_c128_vdc_a !eof
lib_cbm_c128_vdc_a = 1 lib_cbm_c128_vdc_a = 1
@@ -135,14 +135,17 @@ vdcattr_B = %......#. ; blue
vdcattr_I = %.......# ; intensity vdcattr_I = %.......# ; intensity
; direct registers !address {
vdc_state = $d600 ; READING this location yields status flags: ; direct registers
vdcstate_READY = %#....... ; RAM access is finished vdc_state = $d600 ; READING this location yields status flags, see below
vdcstate_LIGHTPEN = %.#...... ; light pen has been activated vdc_reg = $d600 ; WRITING this location selects an indirect register
vdcstate_IN_BORDER = %..#..... ; electron beam is in upper or lower border vdc_data = $d601 ; data of selected indirect register
vdcstate_VERSIONMASK = %...##### ; vdc version (0, 1 or 2) }
vdc_reg = $d600 ; WRITING this location selects an indirect register ; status flags in vdc_state:
vdc_data = $d601 ; data of selected indirect register vdcstate_READY = %#....... ; RAM access is finished
vdcstate_LIGHTPEN = %.#...... ; light pen has been activated
vdcstate_IN_BORDER = %..#..... ; electron beam is in upper or lower border
vdcstate_VERSIONMASK = %...##### ; vdc version (0, 1 or 2)
; indirect registers (default value, see $e179 in C128 kernal) ; indirect registers (default value, see $e179 in C128 kernal)
@@ -219,11 +222,13 @@ vdcr_sync_polarity = $25 ; -- only in VDC 8568
vdcr_HSYNC_POLARITY = %#....... vdcr_HSYNC_POLARITY = %#.......
vdcr_VSYNC_POLARITY = %.#...... vdcr_VSYNC_POLARITY = %.#......
; the c128 ROMs contain look-up tables to convert vic color values to vdc color !address {
; values and vice-versa: ; the c128 ROMs contain look-up tables to convert vic color values to vdc color
; rom4_* needs "low rom area" enabled ($4000..$7fff) ; values and vice-versa:
; rom8_* needs "middle rom area" enabled ($8000..$bfff) ; rom4_* needs "low rom area" enabled ($4000..$7fff)
; romc_* needs "high rom area" enabled ($c000..$ffff) ; rom8_* needs "middle rom area" enabled ($8000..$bfff)
rom4_vic_to_vdc_color_table = $6a4c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e ; romc_* needs "high rom area" enabled ($c000..$ffff)
rom8_vdc_to_vic_color_table = $81f3 ; 00 0c 06 0e 05 0d 0b 03 02 0a 08 04 09 07 0f 01 rom4_vic_to_vdc_color_table = $6a4c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e
romc_vic_to_vdc_color_table = $ce5c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e rom8_vdc_to_vic_color_table = $81f3 ; 00 0c 06 0e 05 0d 0b 03 02 0a 08 04 09 07 0f 01
romc_vic_to_vdc_color_table = $ce5c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e
}

View File

@@ -1,17 +1,19 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c128_vic_a !eof !ifdef lib_cbm_c128_vic_a !eof
lib_cbm_c128_vic_a = 1 lib_cbm_c128_vic_a = 1
!source <cbm/c64/vic.a> ; registers 0..2e !source <cbm/c64/vic.a> ; registers 0..2e
; registers only present in the C128 variant of this chip: !address {
vic_keyboard = $d02f ; registers only present in the C128 variant of this chip:
vic_clock = $d030 vic_keyboard = $d02f
vic_clock = $d030
; the c128 ROMs contain two copies of a look-up table to convert vic color ; the c128 ROMs contain two copies of a look-up table to convert vic color
; values to their corresponding petscii color codes: ; values to their corresponding petscii color codes:
; rom4_* needs "low rom area" enabled ($4000..$7fff) ; rom4_* needs "low rom area" enabled ($4000..$7fff)
; romc_* needs "high rom area" enabled ($c000..$ffff) ; romc_* needs "high rom area" enabled ($c000..$ffff)
rom4_vic_to_petscii_color_table = $76b5 ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b rom4_vic_to_petscii_color_table = $76b5 ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b
romc_vic_to_petscii_color_table = $ce4c ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b romc_vic_to_petscii_color_table = $ce4c ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,23 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c64_cia1_a !eof !ifdef lib_cbm_c64_cia1_a !eof
lib_cbm_c64_cia1_a = 1 lib_cbm_c64_cia1_a = 1
cia1_pra = $dc00 !address {
cia1_prb = $dc01 cia1_pra = $dc00
cia1_ddra = $dc02 cia1_prb = $dc01
cia1_ddrb = $dc03 cia1_ddra = $dc02
cia1_ta_lo = $dc04 cia1_ddrb = $dc03
cia1_ta_hi = $dc05 cia1_ta_lo = $dc04
cia1_tb_lo = $dc06 cia1_ta_hi = $dc05
cia1_tb_hi = $dc07 cia1_tb_lo = $dc06
cia1_tod10ths = $dc08 cia1_tb_hi = $dc07
cia1_todsec = $dc09 cia1_tod10ths = $dc08
cia1_todmin = $dc0a cia1_todsec = $dc09
cia1_todhr = $dc0b cia1_todmin = $dc0a
cia1_sdr = $dc0c cia1_todhr = $dc0b
cia1_icr = $dc0d cia1_sdr = $dc0c
cia1_cra = $dc0e cia1_icr = $dc0d
cia1_crb = $dc0f cia1_cra = $dc0e
cia1_crb = $dc0f
}

View File

@@ -1,21 +1,23 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c64_cia2_a !eof !ifdef lib_cbm_c64_cia2_a !eof
lib_cbm_c64_cia2_a = 1 lib_cbm_c64_cia2_a = 1
cia2_pra = $dd00 !address {
cia2_prb = $dd01 cia2_pra = $dd00
cia2_ddra = $dd02 cia2_prb = $dd01
cia2_ddrb = $dd03 cia2_ddra = $dd02
cia2_ta_lo = $dd04 cia2_ddrb = $dd03
cia2_ta_hi = $dd05 cia2_ta_lo = $dd04
cia2_tb_lo = $dd06 cia2_ta_hi = $dd05
cia2_tb_hi = $dd07 cia2_tb_lo = $dd06
cia2_tod10ths = $dd08 cia2_tb_hi = $dd07
cia2_todsec = $dd09 cia2_tod10ths = $dd08
cia2_todmin = $dd0a cia2_todsec = $dd09
cia2_todhr = $dd0b cia2_todmin = $dd0a
cia2_sdr = $dd0c cia2_todhr = $dd0b
cia2_icr = $dd0d cia2_sdr = $dd0c
cia2_cra = $dd0e cia2_icr = $dd0d
cia2_crb = $dd0f cia2_cra = $dd0e
cia2_crb = $dd0f
}

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c64_float_a !eof !ifdef lib_cbm_c64_float_a !eof
lib_cbm_c64_float_a = 1 lib_cbm_c64_float_a = 1
@@ -6,8 +6,10 @@ lib_cbm_c64_float_a = 1
; Here are some definitions to help you call the floating-point functions of the ; Here are some definitions to help you call the floating-point functions of the
; C64's BASIC ROM. They work on "float registers", which are actually just ; C64's BASIC ROM. They work on "float registers", which are actually just
; structures in zero page: ; structures in zero page:
fac1_base = $61 ; base address of floating-point accumulator 1 !address {
fac2_base = $69 ; base address of floating-point accumulator 2 fac1_base = $61 ; base address of floating-point accumulator 1
fac2_base = $69 ; base address of floating-point accumulator 2
}
; There is really no need to use these addresses directly when calling the ROM ; There is really no need to use these addresses directly when calling the ROM
; functions. You'd only need the addresses when using <cbm/flpt.a>. ; functions. You'd only need the addresses when using <cbm/flpt.a>.
@@ -45,69 +47,71 @@ fac2_base = $69 ; base address of floating-point accumulator 2
lda .adr + 1 lda .adr + 1
} }
; constants in five-byte "mflpt" format !address {
mflpt_pi = $aea8 ; 3.1415926... ; constants in five-byte "mflpt" format
mflpt_minus32768 = $b1a5 ; -32768 mflpt_pi = $aea8 ; 3.1415926...
mflpt_1 = $b9bc ; 1 mflpt_minus32768 = $b1a5 ; -32768
mflpt_half_sqr2 = $b9d6 ; SQR(2) / 2 mflpt_1 = $b9bc ; 1
mflpt_sqr2 = $b9db ; SQR(2) mflpt_half_sqr2 = $b9d6 ; SQR(2) / 2
mflpt_minus_point5 = $b9e0 ; -.5 mflpt_sqr2 = $b9db ; SQR(2)
mflpt_log_2 = $b9e5 ; LOG(2) mflpt_minus_point5 = $b9e0 ; -.5
mflpt_10 = $baf9 ; 10 mflpt_log_2 = $b9e5 ; LOG(2)
mflpt_99999999 = $bdb3 ; 99 999 999 mflpt_10 = $baf9 ; 10
mflpt_999999999 = $bdb8 ; 999 999 999 mflpt_99999999 = $bdb3 ; 99 999 999
mflpt_1000000000 = $bdbd ; 1 000 000 000 mflpt_999999999 = $bdb8 ; 999 999 999
mflpt_point5 = $bf11 ; .5, also known as 1 / 2 mflpt_1000000000 = $bdbd ; 1 000 000 000
mflpt_log_2_reciprocal = $bfbf ; 1 / LOG(2) mflpt_point5 = $bf11 ; .5, also known as 1 / 2
mflpt_half_pi = $e2e0 ; PI / 2 mflpt_log_2_reciprocal = $bfbf ; 1 / LOG(2)
mflpt_double_pi = $e2e5 ; 2 * PI (also see $e309) mflpt_half_pi = $e2e0 ; PI / 2
mflpt_point25 = $e2ea ; .25, also known as 1 / 4 mflpt_double_pi = $e2e5 ; 2 * PI (also see $e309)
mflpt_2_pi = $e309 ; 2 * PI (also see $e2e5) mflpt_point25 = $e2ea ; .25, also known as 1 / 4
mflpt_2_pi = $e309 ; 2 * PI (also see $e2e5)
; functions - a few points to note: ; functions - a few points to note:
; fac1/2 might get clobbered even if not mentioned in the function's name, ; fac1/2 might get clobbered even if not mentioned in the function's name,
; because stuff like fac1_times_memAY will load the value from memory ; because stuff like fac1_times_memAY will load the value from memory
; into fac2 first. ; into fac2 first.
; for subtraction and division, the left operand is in fac2, the right operand in fac1. ; 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_print = $aabc ; print string representation of contents of fac1
fac1_to_signedYA = $b1aa ; might throw ILLEGAL QUANTITY fac1_to_signedYA = $b1aa ; might throw ILLEGAL QUANTITY
fac1_to_signed16 = $b1bf ; 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_signedYA = $b391 ; convert 16 bit signed int to float
fac1_read_unsignedY = $b3a2 ; convert 8 bit unsigned 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_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_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_add_point5 = $b849 ; for rounding, call this before fac1_int
fac1_memAY_minus_fac1 = $b850 ; subtract fac1 from mflpt value fac1_memAY_minus_fac1 = $b850 ; subtract fac1 from mflpt value
fac1_fac2_minus_fac1 = $b853 fac1_fac2_minus_fac1 = $b853
fac1_add_memAY = $b867 ; add mflpt value fac1_add_memAY = $b867 ; add mflpt value
fac1_add_fac2 = $b86a fac1_add_fac2 = $b86a
fac1_log = $b9ea ; LOG() fac1_log = $b9ea ; LOG()
fac1_times_memAY = $ba28 ; multiply by mflpt value fac1_times_memAY = $ba28 ; multiply by mflpt value
fac2_read_memAY = $ba8c ; load mflpt value from memory into fac2 fac2_read_memAY = $ba8c ; load mflpt value from memory into fac2
fac2_read_mem_via0x22ptr = $ba90 ; load mflpt value from memory into fac2 fac2_read_mem_via0x22ptr = $ba90 ; load mflpt value from memory into fac2
fac1_times_10 = $bae2 fac1_times_10 = $bae2
fac1_divide_by_10 = $bafe fac1_divide_by_10 = $bafe
fac1_divide_memAY_by_fac1 = $bb0f ; divide mflpt value by fac1 value fac1_divide_memAY_by_fac1 = $bb0f ; divide mflpt value by fac1 value
fac1_read_memAY = $bba2 ; load mflpt value from memory into fac1 fac1_read_memAY = $bba2 ; load mflpt value from memory into fac1
fac1_read_mem_via0x22ptr = $bba6 ; load mflpt value from memory into fac1 fac1_read_mem_via0x22ptr = $bba6 ; load mflpt value from memory into fac1
fac1_to_memXY = $bbd4 ; store fac1 to memory as mflpt fac1_to_memXY = $bbd4 ; store fac1 to memory as mflpt
fac1_read_fac2 = $bbfc ; copy fac2 to fac1 fac1_read_fac2 = $bbfc ; copy fac2 to fac1
fac2_read_fac1 = $bc0c ; copy fac1 to fac2 fac2_read_fac1 = $bc0c ; copy fac1 to fac2
fac1_sign_to_A = $bc2b ; $ff, $0, $1 for negative, zero, positive fac1_sign_to_A = $bc2b ; $ff, $0, $1 for negative, zero, positive
fac1_sgn = $bc39 ; SGN() fac1_sgn = $bc39 ; SGN()
fac1_abs = $bc58 ; ABS() fac1_abs = $bc58 ; ABS()
fac1_compare_to_memAY = $bc5b ; compare to mflpt value in memory fac1_compare_to_memAY = $bc5b ; compare to mflpt value in memory
fac1_to_signed32 = $bc9b fac1_to_signed32 = $bc9b
fac1_int = $bccc ; INT() fac1_int = $bccc ; INT()
fac1_print_unsignedXA = $bdcd fac1_print_unsignedXA = $bdcd
fac1_to_string = $bddd ; string is stored at $0100 (address returned in AY) fac1_to_string = $bddd ; string is stored at $0100 (address returned in AY)
fac1_sqr = $bf71 ; SQR() fac1_sqr = $bf71 ; SQR()
fac1_fac2_to_the_power_of_memAY = $bf78 fac1_fac2_to_the_power_of_memAY = $bf78
fac1_negate = $bfb4 fac1_negate = $bfb4
fac1_exp = $bfed ; EXP() fac1_exp = $bfed ; EXP()
; end of basic rom jumps to start of kernel rom! ; end of basic rom jumps to start of kernel rom!
fac1_rnd = $e097 ; RND() fac1_rnd = $e097 ; RND()
fac1_cos = $e264 ; COS() fac1_cos = $e264 ; COS()
fac1_sin = $e26b ; SIN() fac1_sin = $e26b ; SIN()
fac1_tan = $e2b4 ; TAN() fac1_tan = $e2b4 ; TAN()
fac1_atn = $e30e ; ATN() fac1_atn = $e30e ; ATN()
}

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c64_georam_a !eof !ifdef lib_cbm_c64_georam_a !eof
lib_cbm_c64_georam_a = 1 lib_cbm_c64_georam_a = 1
@@ -9,12 +9,13 @@ lib_cbm_c64_georam_a = 1
; address $de00 in i/o space. Writing to registers allows to change which ; address $de00 in i/o space. Writing to registers allows to change which
; memory page is visible at that location. ; memory page is visible at that location.
; memory page !address {
georam_page = $de00 ; memory page
georam_page = $de00
; control registers (write-only, these registers can not be read) ; control registers (write-only, these registers can not be read)
georam_track = $dffe ; 0..63, i.e. the lower six bits are significant georam_track = $dffe ; 0..63, i.e. the lower six bits are significant
georam_sector = $dfff ; 0..31, i.e. the lower five bits are significant georam_sector = $dfff ; 0..31, i.e. the lower five bits are significant
}
; these are the official addresses - actually the registers are accessible ; these are the official addresses - actually the registers are accessible
; *everywhere* at $dfxx, but using these locations does not clash with the ; *everywhere* at $dfxx, but using these locations does not clash with the
; registers of a Commodore REU. ; registers of a Commodore REU.

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c64_reu_a !eof !ifdef lib_cbm_c64_reu_a !eof
lib_cbm_c64_reu_a = 1 lib_cbm_c64_reu_a = 1
@@ -8,48 +8,56 @@ lib_cbm_c64_reu_a = 1
; (RAM Expansion Controller) capable of direct memory access (DMA). ; (RAM Expansion Controller) capable of direct memory access (DMA).
; Standard base address of control registers is $df00 in i/o space. ; Standard base address of control registers is $df00 in i/o space.
; status register !address {
rec_status = $df00 ; reading will clear IRQ, END and ERROR bits ; status register
rec_STATUS_IRQ = %#....... rec_status = $df00 ; reading will clear IRQ, END and ERROR bits
rec_STATUS_END = %.#...... }
rec_STATUS_ERROR = %..#..... ; for verify command rec_STATUS_IRQ = %#.......
rec_STATUS_TYPE = %...#.... ; chip type (do not use to determine unit size!) rec_STATUS_END = %.#......
rec_STATUS_VERSION = %....#### rec_STATUS_ERROR = %..#..... ; for verify command
; command register rec_STATUS_TYPE = %...#.... ; chip type (do not use to determine unit size!)
rec_command = $df01 rec_STATUS_VERSION = %....####
rec_COMMAND_EXECUTE = %#....... !address {
;reserved = %.#...... ; command register
rec_COMMAND_RELOAD = %..#..... rec_command = $df01
rec_COMMAND_IMMEDIATELY = %...#.... ; do not wait for $ff00 write }
;reserved = %....##.. rec_COMMAND_EXECUTE = %#.......
rec_COMMAND_MODE_MASK = %......## ; bit mask for the four modes ;reserved = %.#......
rec_COMMAND_MODE_STASH = %........ ; computer-to-REU rec_COMMAND_RELOAD = %..#.....
rec_COMMAND_MODE_FETCH = %.......# ; REU-to-computer rec_COMMAND_IMMEDIATELY = %...#.... ; do not wait for $ff00 write
rec_COMMAND_MODE_SWAP = %......#. ; exchange ;reserved = %....##..
rec_COMMAND_MODE_VERIFY = %......## ; compare rec_COMMAND_MODE_MASK = %......## ; bit mask for the four modes
rec_COMMAND_STASH = %#.#..... ; these wait for $ff00 before rec_COMMAND_MODE_STASH = %........ ; computer-to-REU
rec_COMMAND_FETCH = %#.#....# ; starting and then reload values. rec_COMMAND_MODE_FETCH = %.......# ; REU-to-computer
; internal address (computer RAM) rec_COMMAND_MODE_SWAP = %......#. ; exchange
rec_int_low = $df02 rec_COMMAND_MODE_VERIFY = %......## ; compare
rec_int_high = $df03 rec_COMMAND_STASH = %#.#..... ; these wait for $ff00 before
; external address (expansion RAM) rec_COMMAND_FETCH = %#.#....# ; starting and then reload values.
rec_ext_low = $df04 !address {
rec_ext_high = $df05 ; internal address (computer RAM)
rec_ext_bank = $df06 rec_int_low = $df02
rec_int_high = $df03
; external address (expansion RAM)
rec_ext_low = $df04
rec_ext_high = $df05
rec_ext_bank = $df06
; A stock 1700 unit has two banks (128 KiB). ; A stock 1700 unit has two banks (128 KiB).
; A stock 1764 unit has four banks (256 KiB). ; A stock 1764 unit has four banks (256 KiB).
; A stock 1750 unit has eight banks (512 KiB). ; A stock 1750 unit has eight banks (512 KiB).
; Upgraded units and clones may have more, but the REC chip will always ; Upgraded units and clones may have more, but the REC chip will always
; "wrap around" after eight banks if crossing bank borders! ; "wrap around" after eight banks if crossing bank borders!
; amount of bytes to process ; amount of bytes to process
rec_amount_low = $df07 rec_amount_low = $df07
rec_amount_high = $df08 rec_amount_high = $df08
; when to request interrupts ; when to request interrupts
rec_irqctrl = $df09 rec_irqctrl = $df09
rec_IRQCTRL_ENABLE = %#....... }
rec_IRQCTRL_ON_END = %.#...... rec_IRQCTRL_ENABLE = %#.......
rec_IRQCTRL_ON_ERROR = %..#..... ; for verify errors rec_IRQCTRL_ON_END = %.#......
; address control (set to zero for normal operation) rec_IRQCTRL_ON_ERROR = %..#..... ; for verify errors
rec_addrctrl = $df0a !address {
rec_ADDRCTRL_FIX_INT = %#....... ; address control (set to zero for normal operation)
rec_ADDRCTRL_FIX_EXT = %.#...... rec_addrctrl = $df0a
}
rec_ADDRCTRL_FIX_INT = %#.......
rec_ADDRCTRL_FIX_EXT = %.#......

View File

@@ -1,52 +1,55 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c64_sid_a !eof !ifdef lib_cbm_c64_sid_a !eof
lib_cbm_c64_sid_a = 1 lib_cbm_c64_sid_a = 1
; write-only registers: !address {
; voice 1: ; write-only registers:
sid_v1_freq_lo = $d400 ; voice 1:
sid_v1_freq_hi = $d401 sid_v1_freq_lo = $d400
sid_v1_width_lo = $d402 sid_v1_freq_hi = $d401
sid_v1_width_hi = $d403 sid_v1_width_lo = $d402
sid_v1_control = $d404 ; see below for bits sid_v1_width_hi = $d403
sid_v1_attack_decay = $d405 ; hi-nibble: attack length, low-nibble: decay length sid_v1_control = $d404 ; see below for bits
sid_v1_sustain_release = $d406 ; hi-nibble: sustain volumne, low-nibble: release length sid_v1_attack_decay = $d405 ; hi-nibble: attack length, low-nibble: decay length
; voice 2: sid_v1_sustain_release = $d406 ; hi-nibble: sustain volumne, low-nibble: release length
sid_v2_freq_lo = $d407 ; voice 2:
sid_v2_freq_hi = $d408 sid_v2_freq_lo = $d407
sid_v2_width_lo = $d409 sid_v2_freq_hi = $d408
sid_v2_width_hi = $d40a sid_v2_width_lo = $d409
sid_v2_control = $d40b ; see below for bits sid_v2_width_hi = $d40a
sid_v2_attack_decay = $d40c ; hi-nibble: attack length, low-nibble: decay length sid_v2_control = $d40b ; see below for bits
sid_v2_sustain_release = $d40d ; hi-nibble: sustain volumne, low-nibble: release length sid_v2_attack_decay = $d40c ; hi-nibble: attack length, low-nibble: decay length
; voice 3: sid_v2_sustain_release = $d40d ; hi-nibble: sustain volumne, low-nibble: release length
sid_v3_freq_lo = $d40e ; voice 3:
sid_v3_freq_hi = $d40f sid_v3_freq_lo = $d40e
sid_v3_width_lo = $d410 sid_v3_freq_hi = $d40f
sid_v3_width_hi = $d411 sid_v3_width_lo = $d410
sid_v3_control = $d412 ; see below for bits sid_v3_width_hi = $d411
sid_v3_attack_decay = $d413 ; hi-nibble: attack length, low-nibble: decay length sid_v3_control = $d412 ; see below for bits
sid_v3_sustain_release = $d414 ; hi-nibble: sustain volumne, low-nibble: release length sid_v3_attack_decay = $d413 ; hi-nibble: attack length, low-nibble: decay length
sid_v3_sustain_release = $d414 ; hi-nibble: sustain volumne, low-nibble: release length
}
; voice control bits: ; voice control bits:
sid_VOICECONTROL_NOISE = %#....... sid_VOICECONTROL_NOISE = %#.......
sid_VOICECONTROL_RECTANGLE = %.#...... sid_VOICECONTROL_RECTANGLE = %.#......
sid_VOICECONTROL_SAWTOOTH = %..#..... sid_VOICECONTROL_SAWTOOTH = %..#.....
sid_VOICECONTROL_TRIANGLE = %...#.... sid_VOICECONTROL_TRIANGLE = %...#....
sid_VOICECONTROL_DISABLE_RESET = %....#... ; 1 = disable voice, reset noise generator sid_VOICECONTROL_DISABLE_RESET = %....#... ; 1 = disable voice, reset noise generator
sid_VOICECONTROL_RINGMODULATION = %.....#.. sid_VOICECONTROL_RINGMODULATION = %.....#..
sid_VOICECONTROL_SYNC = %......#. sid_VOICECONTROL_SYNC = %......#.
sid_VOICECONTROL_ON = %.......# ; 0 = release, 1 = attack/sustain/decay sid_VOICECONTROL_ON = %.......# ; 0 = release, 1 = attack/sustain/decay
; registers shared by all voices: !address {
sid_filter_cutoff_lo = $d415 ; only bits 0/1/2! ; registers shared by all voices:
sid_filter_cutoff_hi = $d416 sid_filter_cutoff_lo = $d415 ; only bits 0/1/2!
sid_filter_control = $d417 ; hi-nibble: resonance, lo-nibble: filter ext/v3/v2/v1 sid_filter_cutoff_hi = $d416
sid_filter_volume = $d418 ; hi-nibble: filter mode (disable v3, high, band, low), lo-nibble: volume sid_filter_control = $d417 ; hi-nibble: resonance, lo-nibble: filter ext/v3/v2/v1
; read-only registers: sid_filter_volume = $d418 ; hi-nibble: filter mode (disable v3, high, band, low), lo-nibble: volume
sid_potx = $d419 ; read-only registers:
sid_poty = $d41a sid_potx = $d419
sid_v3_waveform_output = $d41b sid_poty = $d41a
sid_v3_adsr_output = $d41c sid_v3_waveform_output = $d41b
sid_v3_adsr_output = $d41c
; Do not use the shadow copies of these registers at $d500, $d600 or $d700, }
; Do not use the shadow copies of these registers at $d5xx, $d6xx or $d7xx:
; on a C128 they do not exist! ; on a C128 they do not exist!

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_c64_vic_a !eof !ifdef lib_cbm_c64_vic_a !eof
lib_cbm_c64_vic_a = 1 lib_cbm_c64_vic_a = 1
@@ -21,58 +21,58 @@ viccolor_LGREEN = $d
viccolor_LBLUE = $e viccolor_LBLUE = $e
viccolor_GRAY3 = $f viccolor_GRAY3 = $f
; register addresses !address {
vic_xs0 = $d000 ; register addresses
vic_ys0 = $d001 vic_xs0 = $d000
vic_xs1 = $d002 vic_ys0 = $d001
vic_ys1 = $d003 vic_xs1 = $d002
vic_xs2 = $d004 vic_ys1 = $d003
vic_ys2 = $d005 vic_xs2 = $d004
vic_xs3 = $d006 vic_ys2 = $d005
vic_ys3 = $d007 vic_xs3 = $d006
vic_xs4 = $d008 vic_ys3 = $d007
vic_ys4 = $d009 vic_xs4 = $d008
vic_xs5 = $d00a vic_ys4 = $d009
vic_ys5 = $d00b vic_xs5 = $d00a
vic_xs6 = $d00c vic_ys5 = $d00b
vic_ys6 = $d00d vic_xs6 = $d00c
vic_xs7 = $d00e vic_ys6 = $d00d
vic_ys7 = $d00f vic_xs7 = $d00e
vic_msb_xs = $d010 vic_ys7 = $d00f
vic_controlv = $d011 ; vertical control (and much other stuff) vic_msb_xs = $d010
vic_line = $d012 ; raster line vic_controlv = $d011 ; vertical control (and much other stuff)
vic_xlp = $d013 ; light pen coordinates vic_line = $d012 ; raster line
vic_ylp = $d014 vic_xlp = $d013 ; light pen coordinates
vic_sactive = $d015 ; sprites: active vic_ylp = $d014
vic_controlh = $d016 ; horizontal control (and much other stuff) vic_sactive = $d015 ; sprites: active
vic_sdy = $d017 ; sprites: double height vic_controlh = $d016 ; horizontal control (and much other stuff)
vic_ram = $d018 ; RAM pointer vic_sdy = $d017 ; sprites: double height
vic_irq = $d019 vic_ram = $d018 ; RAM pointer
vic_irqmask = $d01a vic_irq = $d019
vic_sback = $d01b ; sprites: background mode vic_irqmask = $d01a
vic_smc = $d01c ; sprites: multi color mode vic_sback = $d01b ; sprites: background mode
vic_sdx = $d01d ; sprites: double width vic_smc = $d01c ; sprites: multi color mode
vic_ss_collided = $d01e ; sprite-sprite collision detect vic_sdx = $d01d ; sprites: double width
vic_sd_collided = $d01f ; sprite-data collision detect vic_ss_collided = $d01e ; sprite-sprite collision detect
vic_sd_collided = $d01f ; sprite-data collision detect
; color registers ; color registers
vic_cborder = $d020 ; border color vic_cborder = $d020 ; border color
vic_cbg = $d021 ; general background color vic_cbg = $d021 ; general background color
vic_cbg0 = $d021 vic_cbg0 = $d021
vic_cbg1 = $d022 ; background color 1 (for EBC and MC text mode) vic_cbg1 = $d022 ; background color 1 (for EBC and MC text mode)
vic_cbg2 = $d023 ; background color 2 (for EBC and MC text mode) vic_cbg2 = $d023 ; background color 2 (for EBC and MC text mode)
vic_cbg3 = $d024 ; background color 3 (for EBC mode) vic_cbg3 = $d024 ; background color 3 (for EBC mode)
vic_sc01 = $d025 ; sprite color for MC-bitpattern %01 vic_sc01 = $d025 ; sprite color for MC-bitpattern %01
vic_sc11 = $d026 ; sprite color for MC-bitpattern %11 vic_sc11 = $d026 ; sprite color for MC-bitpattern %11
vic_cs0 = $d027 ; sprite colors vic_cs0 = $d027 ; sprite colors
vic_cs1 = $d028 vic_cs1 = $d028
vic_cs2 = $d029 vic_cs2 = $d029
vic_cs3 = $d02a vic_cs3 = $d02a
vic_cs4 = $d02b vic_cs4 = $d02b
vic_cs5 = $d02c vic_cs5 = $d02c
vic_cs6 = $d02d vic_cs6 = $d02d
vic_cs7 = $d02e vic_cs7 = $d02e
}
; See <cbm/c128/vic.a> for the C128's two additional registers at $d02f/$d030. ; See <cbm/c128/vic.a> for the C128's two additional registers at $d02f/$d030.
; They are accessible even in C64 mode and $d030 can garble the video output, ; They are accessible even in C64 mode and $d030 can garble the video output,
; so be careful not to write to it accidentally in a C64 program! ; so be careful not to write to it accidentally in a C64 program!

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
!ifdef lib_cbm_kernel_a !eof !ifdef lib_cbm_kernel_a !eof
lib_cbm_kernel_a = 1 lib_cbm_kernel_a = 1
@@ -7,42 +7,44 @@ lib_cbm_kernel_a = 1
; Sorry, I can't give credit because I don't have the URL anymore. ; Sorry, I can't give credit because I don't have the URL anymore.
; There are alternative names for some calls. ; There are alternative names for some calls.
k_cint = $ff81 !address {
k_ioinit = $ff84 k_cint = $ff81
k_ramtas = $ff87 k_ioinit = $ff84
k_restor = $ff8a k_ramtas = $ff87
k_vector = $ff8d k_restor = $ff8a
k_setmsg = $ff90 k_vector = $ff8d
k_secnd = $ff93 k_setmsg = $ff90
k_tksa = $ff96 k_secnd = $ff93
k_memtop = $ff99 k_tksa = $ff96
k_membot = $ff9c k_memtop = $ff99
k_key = $ff9f k_membot = $ff9c
k_settmo = $ffa2 k_key = $ff9f
k_iecin = $ffa5:k_acptr = $ffa5 k_settmo = $ffa2
k_iecout = $ffa8:k_ciout = $ffa8 k_iecin = $ffa5:k_acptr = $ffa5
k_untalk = $ffab:k_untlk = $ffab k_iecout = $ffa8:k_ciout = $ffa8
k_unlisten = $ffae:k_unlsn = $ffae k_untalk = $ffab:k_untlk = $ffab
k_listen = $ffb1:k_listn = $ffb1 k_unlisten = $ffae:k_unlsn = $ffae
k_talk = $ffb4 k_listen = $ffb1:k_listn = $ffb1
k_readss = $ffb7 k_talk = $ffb4
k_setlfs = $ffba k_readss = $ffb7
k_setnam = $ffbd ; A is length, X is ptr-low, Y is ptr-high k_setlfs = $ffba
k_open = $ffc0 k_setnam = $ffbd ; A is length, X is ptr-low, Y is ptr-high
k_close = $ffc3:k_close_A = $ffc3 k_open = $ffc0
k_chkin = $ffc6:k_chkin_X = $ffc6 k_close = $ffc3:k_close_A = $ffc3
k_chkout = $ffc9:k_chkout_X = $ffc9:k_ckout = $ffc9 k_chkin = $ffc6:k_chkin_X = $ffc6
k_clrchn = $ffcc:k_clrch = $ffcc k_chkout = $ffc9:k_chkout_X = $ffc9:k_ckout = $ffc9
k_chrin = $ffcf:k_basin = $ffcf k_clrchn = $ffcc:k_clrch = $ffcc
k_chrout = $ffd2:k_basout = $ffd2:k_bsout = $ffd2 k_chrin = $ffcf:k_basin = $ffcf
k_load = $ffd5:k_load_AXY = $ffd5 ; A means verify, YYXX is desired load address (if channel == 0), returns end+1 in YYXX k_chrout = $ffd2:k_basout = $ffd2:k_bsout = $ffd2
k_save = $ffd8:k_save_AXY = $ffd8 ; A is zp address of start ptr(!), YYXX is end address (+1) k_load = $ffd5:k_load_AXY = $ffd5 ; A means verify, YYXX is desired load address (if channel == 0), returns end+1 in YYXX
k_settim = $ffdb k_save = $ffd8:k_save_AXY = $ffd8 ; A is zp address of start ptr(!), YYXX is end address (+1)
k_rdtim = $ffde k_settim = $ffdb
k_stop = $ffe1 k_rdtim = $ffde
k_getin = $ffe4:k_get = $ffe4 k_stop = $ffe1
k_clall = $ffe7 k_getin = $ffe4:k_get = $ffe4
k_udtim = $ffea k_clall = $ffe7
k_scrorg = $ffed k_udtim = $ffea
k_plot = $fff0 ; get/set cursor (to set, clear carry) k_scrorg = $ffed
k_iobase = $fff3 k_plot = $fff0 ; get/set cursor (to set, clear carry)
k_iobase = $fff3
}

View File

@@ -412,9 +412,12 @@ Examples:
Miscellaneous: The old syntax ("!for LABEL, END { BLOCK }" where Miscellaneous: The old syntax ("!for LABEL, END { BLOCK }" where
START was always implied to be 1) is still fully START was always implied to be 1) is still fully
supported, but gives a warning to get people to change supported, but gives a warning to get people to change
to the new syntax. When migrating your sources, bear to the new syntax. You can disable this warning using
in mind that it is no longer possible to skip the the "-Wno-old-for" switch, but then you will get
block completely by specifying a loop count of zero. 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.
Also note that with the new algorithm, LABEL has a Also note that with the new algorithm, LABEL has a
different value after the block than during the last different value after the block than during the last
loop cycle, while the old algorithm kept that last loop cycle, while the old algorithm kept that last
@@ -811,6 +814,37 @@ Purpose: Assume short (8 bits) index registers. Only needed
pass. pass.
----------------------------------------------------------------------
Section: Type system
----------------------------------------------------------------------
Call: !address [ { BLOCK } ]
or: !address LABEL = VALUE
Purpose: Mark a block or a statement as "explicitly defined
labels 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.
If no block is given, only the current statement will
be affected, which should then be an explicit label
definition.
Aliases: "!addr"
Examples: !addr k_chrout = $ffd2 ; this is an address
CLEAR = 147 ; but this is not
!addr {
; these are addresses:
sid_v1_control = $d404
sid_v2_control = $d40b
sid_v3_control = $d412
}
; these are not:
sid_VOICECONTROL_NOISE = %#.......
sid_VOICECONTROL_RECTANGLE = %.#......
sid_VOICECONTROL_SAWTOOTH = %..#.....
sid_VOICECONTROL_TRIANGLE = %...#....
---------------------------------------------------------------------- ----------------------------------------------------------------------
Section: Obsolete pseudo opcodes (they will throw errors if used) Section: Obsolete pseudo opcodes (they will throw errors if used)
---------------------------------------------------------------------- ----------------------------------------------------------------------

View File

@@ -12,6 +12,19 @@ platform used. There should be another help file in this archive
outlining the platform specific changes. outlining the platform specific changes.
----------------------------------------------------------------------
Section: New in release 0.95
----------------------------------------------------------------------
Added an experimental type system to tell addresses and non-addresses
apart (per default disabled; must be activated using the
"-Wtype-mismatch" CLI switch). The new "!address" pseudo opcode is
used to mark label definitions as setting address values.
Added "-Wno-old-for" switch to disable warning about old "!for"
syntax. However, this will in turn enable warnings about using the
*new* syntax.
---------------------------------------------------------------------- ----------------------------------------------------------------------
Section: New in release 0.94.12 Section: New in release 0.94.12
---------------------------------------------------------------------- ----------------------------------------------------------------------

View File

@@ -55,9 +55,14 @@ Bug in ACME, code follows
C-style "==" comparison detected. C-style "==" comparison detected.
To check for equality, use a single '=' character instead. To check for equality, use a single '=' character instead.
Found deprecated "!for" syntax. Found old "!for" syntax.
Please update your sources to use the new "!for" syntax. See Please update your sources to use the new "!for" syntax. See
AllPOs.txt for details. AllPOs.txt for details.
You can suppress this warning using the "-Wno-old-for" switch.
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. Implicit label definition not in leftmost column.
An implicit label definition has blanks before the label name. An implicit label definition has blanks before the label name.
@@ -128,6 +133,12 @@ Using oversized addressing mode.
always truncate a value to 8 bits, use the '<' operator). always truncate a value to 8 bits, use the '<' operator).
More about the postfixing method can be found in "AddrModes.txt". More about the postfixing method can be found in "AddrModes.txt".
Wrong type - expected address.
Wrong type - expected integer.
These warnings are only given when type checking has been enabled
using the "-Wtype-mismatch" switch. Make sure the argument type
matches the instruction's addressing mode.
---------------------------------------------------------------------- ----------------------------------------------------------------------
Section: Errors during assembly Section: Errors during assembly

View File

@@ -105,6 +105,8 @@ ACME exists on several platforms, meaning you can easily exchange your
sources with other people (preferring other OSes). sources with other people (preferring other OSes).
ACME can convert its strings to PetSCII and screen code (Okay, this is ACME can convert its strings to PetSCII and screen code (Okay, this is
C64-specific). C64-specific).
ACME has a rudimentary type checking system to catch errors like
missing '#' characters.
Did I mention that it is fast? Did I mention that it is fast?

View File

@@ -21,7 +21,9 @@ Section: Example of what an ACME source code file looks like
!to "tiny.o", cbm ; set output file and format !to "tiny.o", cbm ; set output file and format
* = $c000 ; set program counter * = $c000 ; set program counter
basout = $ffd2 ; explicit global label def. CLEAR = 147 ; a global label definition
!addr basout = $ffd2 ; another one, marked as an address
; a string output loop: ; a string output loop:
ldx #0 ldx #0
beq + ; enter loop beq + ; enter loop
@@ -46,8 +48,19 @@ Here's the same fragment again, now with some additional info:
; respectively. ; respectively.
* = $c000 ; set program counter * = $c000 ; set program counter
; This can also be done using the command line option "--setpc". ; This can also be done using the command line option "--setpc".
basout = $ffd2 ; explicit global label def.
; Now "basout" is defined as a global label having the value $ffd2. ; some global label definitions
CLEAR = 147 ; this is a simple constant
; Now "CLEAR" is defined as a global label 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
; value $ffd2.
; The distinction between addresses and non-addresses only
; matters when the type check system gets activated using
; the "-Wtype-mismatch" switch. Then, a line like
; "lda CLEAR" would trigger a type mismatch warning because
; of the missing '#' character.
; a string output loop: ; a string output loop:
ldx #0 ldx #0
beq + ; enter loop beq + ; enter loop
@@ -157,6 +170,9 @@ found in the file "AllPOs.txt". Here's just a short overview:
!warn !error !serious !warn !error !serious
...for generating warnings, errors and serious errors. ...for generating warnings, errors and serious errors.
!addr
...to mark labels as addresses, for the optional type check system.
---------------------------------------------------------------------- ----------------------------------------------------------------------
Section: Command line arguments Section: Command line arguments
@@ -180,13 +196,13 @@ Available options are:
-l, --labeldump FILE select label dump file -l, --labeldump FILE select label dump file
This can also be given using the "!sl" pseudo opcode. This can also be given using the "!sl" pseudo opcode.
--setpc NUMBER set program counter
This can also be given in the source code using "* = NUMBER".
--cpu CPU_TYPE set processor type --cpu CPU_TYPE set processor type
This can be changed in the source code using the "!cpu" pseudo This can be changed in the source code using the "!cpu" pseudo
opcode. Defaults to 6502. opcode. Defaults to 6502.
--setpc NUMBER set program counter
This can also be given in the source code using "* = NUMBER".
--initmem NUMBER define 'empty' memory --initmem NUMBER define 'empty' memory
This can also be given using the "!initmem" pseudo opcode. This can also be given using the "!initmem" pseudo opcode.
Defaults to zero. Defaults to zero.
@@ -200,22 +216,18 @@ Available options are:
-vDIGIT set verbosity level -vDIGIT set verbosity level
Sets how much additional informational output is generated. Sets how much additional informational output is generated.
Higher values mean more output: Higher values mean more output:
acme -v0 source.a
acme -v0 source.a
This is the default: No additional output is generated, This is the default: No additional output is generated,
ACME will only display warnings and errors. ACME will only display warnings and errors.
acme -v1 source.a
acme -v1 source.a
Now the start and end addresses of the generated output Now the start and end addresses of the generated output
file are displayed, along with its size (a CBM-style file are displayed, along with its size (a CBM-style
"load address" is *not* counted). "load address" is *not* counted).
acme -v2 source.a
acme -v2 source.a
In addition to the "-v1" output, ACME will announce each In addition to the "-v1" output, ACME will announce each
pass, will show amount and offset of "!binary" loads, and pass, will show amount and offset of "!binary" loads, and
show start and end addresses and size of each segment. show start and end addresses and size of each segment.
acme -v3 source.a
acme -v3 source.a
In addition to the "-v2" output, ACME will now announce In addition to the "-v2" output, ACME will now announce
each source file. each source file.
@@ -226,9 +238,14 @@ Available options are:
(using conditional assembly in your source code file). (using conditional assembly in your source code file).
-W fine-tune amount and type of warnings -W fine-tune amount and type of warnings
Currently only sub-option is supported: "-Wno-label-indent" -Wno-label-indent
will switch off warnings about implicit label definitions not Disables warnings about implicit label definitions not
being in the leftmost column. 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.
-Wtype-mismatch
Enables type checking system (warns about wrong types).
--use-stdout fix for 'Relaunch64' IDE --use-stdout fix for 'Relaunch64' IDE
With this option, errors are written to the standard output With this option, errors are written to the standard output
@@ -265,6 +282,7 @@ This is a list of the operators currently known by ACME:
14 arcsin(v) Inverse of sin() 14 arcsin(v) Inverse of sin()
14 arccos(v) Inverse of cos() 14 arccos(v) Inverse of cos()
14 arctan(v) Inverse of tan() 14 arctan(v) Inverse of tan()
14 addr(v) Mark as address
14 int(v) Convert to integer 14 int(v) Convert to integer
14 float(v) Convert to float 14 float(v) Convert to float
13 ! v Complement of NOT 13 ! v Complement of NOT

View File

@@ -1,4 +1,4 @@
;ACME 0.94 ;ACME 0.95
;!sl "ddrv.l" ;!sl "ddrv.l"
; Name DuoDriver ; Name DuoDriver
; Purpose Input driver for mouse and joystick ; Purpose Input driver for mouse and joystick
@@ -26,6 +26,7 @@
; 26 Mar 2006 Release 4.03. Adjusted source to ACME 0.91 capabilities. ; 26 Mar 2006 Release 4.03. Adjusted source to ACME 0.91 capabilities.
; 25 Nov 2007 Release 4.04. Adjusted source to ACME 0.94 capabilities. ; 25 Nov 2007 Release 4.04. Adjusted source to ACME 0.94 capabilities.
; 7 Apr 2013 Slightly reformatted. ; 7 Apr 2013 Slightly reformatted.
; 1 Jun 2014 Adjusted to experimental type system of ACME 0.95
; This source code file uses conditional assembly ; This source code file uses conditional assembly
; to decide which version to produce (C64 or C128). ; to decide which version to produce (C64 or C128).
@@ -47,12 +48,12 @@
!if SYSTEM = 64 { !if SYSTEM = 64 {
* = $c000 * = $c000
!to "ddrv64.prg", cbm !to "ddrv64.prg", cbm
VIC_Base = $d000 !addr VIC_Base = $d000
} }
!if SYSTEM = 128 { !if SYSTEM = 128 {
* = $0c00 * = $0c00
!to "ddrv128.prg", cbm !to "ddrv128.prg", cbm
VIC_Base = $11d6 ; Location of mirror registers !addr VIC_Base = $11d6 ; Location of mirror registers
} }
; Pointer's maximum coordinates ; Pointer's maximum coordinates
@@ -78,11 +79,14 @@
; Locations to store button states, $ff = pressed, $00 = not pressed. ; Locations to store button states, $ff = pressed, $00 = not pressed.
; Mouse uses both buttons, joystick only uses "LeftButton". ; Mouse uses both buttons, joystick only uses "LeftButton".
; Location to store pointer's current character coordinates. ; Location to store pointer's current character coordinates.
!addr {
!if SYSTEM = 64 { !if SYSTEM = 64 {
LeftButton = $a4 LeftButton = $a4
RightButton = $a5 RightButton = $a5
CharX = $b3 CharX = $b3
CharY = $b4 CharY = $b4
tapebuf = $0340
spr_ptrs = 2040
} }
!if SYSTEM = 128 { !if SYSTEM = 128 {
LeftButton = $fa LeftButton = $fa
@@ -96,7 +100,6 @@
; x low, x high, y low, y high ; x low, x high, y low, y high
Coordinates = $fb ; $fb..$fe Coordinates = $fb ; $fb..$fe
; --- System constants ; --- System constants
; Interrupt vector ; Interrupt vector
@@ -108,7 +111,7 @@
cia1_prb = $dc01 cia1_prb = $dc01
cia1_ddrb = $dc03 cia1_ddrb = $dc03
mmu_cr = $ff00 ; c128 only mmu_cr = $ff00 ; c128 only
};addr
; --- Label definitions ; --- Label definitions
@@ -168,15 +171,15 @@ Init lda sys_iirq
; Copy sprites to tape buffer ; Copy sprites to tape buffer
ldx #127 ldx #127
- lda Sprites, x - lda Sprites, x
sta $0340, x sta tapebuf, x
dex dex
bpl - bpl -
lda #Sprites_Bitmask lda #Sprites_Bitmask
; Set sprite block pointers ; Set sprite block pointers
ldx #$0d ldx #$0d
stx 2040 + Sprite_A stx spr_ptrs + Sprite_A
inx inx
stx 2040 + Sprite_B stx spr_ptrs + Sprite_B
; Activate pointer sprites ; Activate pointer sprites
ora VIC_Base + 21 ora VIC_Base + 21
sta VIC_Base + 21 sta VIC_Base + 21
@@ -419,7 +422,7 @@ StoreOF sta Sprites_OF ; set x overflow
; The initialisation routine sets the argument to the address of the ; The initialisation routine sets the argument to the address of the
; previous IRQ routine. ; previous IRQ routine.
mod16 = * + 1: jmp $ffff ; (self-modifying) mod16 = * + 1: jmp addr($ffff) ; (self-modifying)
; This table is for part 8. ; This table is for part 8.
;OrTable !byte 0, 32, 64 ; VDC only ;OrTable !byte 0, 32, 64 ; VDC only

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
; ist der komplette Sourcecode von MacEdit ; ist der komplette Sourcecode von MacEdit
; (80-Zeichen-Version) ; (80-Zeichen-Version)
; Version 0.7 ; Version 0.7
@@ -76,3 +76,5 @@ Spätere Änderungen am Source:
Converted to UTF-8 Converted to UTF-8
27 Jun 2013: 27 Jun 2013:
Adjusted to change in library. Adjusted to change in library.
1 Jun 2014:
Adjusted to experimental type system of ACME 0.95

View File

@@ -1,10 +1,10 @@
;ACME 0.94.4 ;ACME 0.95
; Konstanten: ; Konstanten:
FALSE = 0 ; Das Programm verläßt sich an etlichen Stellen FALSE = 0 ; Das Programm verläßt sich an etlichen Stellen
TRUE = $ff ; darauf, daß genau diese Werte zugewiesen wurden. TRUE = $ff ; darauf, daß genau diese Werte zugewiesen wurden.
MODIFIED8 = $ff ; Defaultwerte für MODIFIED8 = $ff ; Defaultwerte für
MODIFIED16 = $ffff ; Selbstmodifikationen !addr MODIFIED16 = $ffff ; Selbstmodifikationen
Char_NUL = $00 Char_NUL = $00
Char_STOP = $03 Char_STOP = $03
@@ -46,6 +46,7 @@
lf = 8 ; Filenr. & Sek.-Addy lf = 8 ; Filenr. & Sek.-Addy
; Zeropage: ; Zeropage:
!addr {
D8502 = $00 ; Direction D8502 = $00 ; Direction
R8502 = $01 ; Register R8502 = $01 ; Register
vvek = $83 ; Vektor auf LineVektor vvek = $83 ; Vektor auf LineVektor
@@ -91,3 +92,4 @@
clrchn = $ffcc clrchn = $ffcc
basin = $ffcf basin = $ffcf
basout = $ffd2 basout = $ffd2
}

View File

@@ -1,4 +1,4 @@
;ACME 0.94.4 ;ACME 0.95
!zone !zone
F_info ldx #hWindow_InfoBox F_info ldx #hWindow_InfoBox
@@ -483,7 +483,7 @@ swin !byte 0 ; Auch fuer 'lwin'
bckgrnd = 26 ; screencolor-register bckgrnd = 26 ; screencolor-register
flnmpos = 87 ; filenameposition flnmpos = 87 ; filenameposition
wsstart = $0fd0 ; windowstack-start wsstart = $0fd0 ; windowstack-start
tcolor = $f2 ; attribute-buffer !addr tcolor = $f2 ; attribute-buffer
; Subs: ; Subs:
!zone !zone
@@ -505,11 +505,11 @@ init ldx repeatedtry ; first start ?
stx fnbank ; filename-CR stx fnbank ; filename-CR
dex dex
stx locks ; 'CBM-shift' off stx locks ; 'CBM-shift' off
stx $0ac5 ; 'ASC/DIN' off stx addr($0ac5) ; 'ASC/DIN' off
stx basic ; 'Basic-IRQ' off stx basic ; 'Basic-IRQ' off
jsr crsrinit ; init crsr jsr crsrinit ; init crsr
ldx #$0b ; VIC off ldx #$0b ; VIC off
stx $11e7 stx addr($11e7)
lda mode ; which mode ? lda mode ; which mode ?
bmi + ; if 40 then bmi + ; if 40 then
jsr kernel_switchmode ; switch mode jsr kernel_switchmode ; switch mode
@@ -567,7 +567,7 @@ init ldx repeatedtry ; first start ?
sta conreg + 1 ; full RAM sta conreg + 1 ; full RAM
ldx #$0b ; loop for new ldx #$0b ; loop for new
- lda keyb, x ; keyboard-tabs - lda keyb, x ; keyboard-tabs
sta $033e, x sta addr($033e), x
dex dex
bpl - bpl -
jsr handleid ; old ID ? jsr handleid ; old ID ?
@@ -747,7 +747,7 @@ F_gosys +bank15
jsr kernel_cls ; CLS jsr kernel_cls ; CLS
lda #0 ; '0' for lda #0 ; '0' for
sta locks ; 'CBM-Shift' on sta locks ; 'CBM-Shift' on
sta $0ac5 ; 'ASC/DIN' on sta addr($0ac5) ; 'ASC/DIN' on
sta basic ; 'Basic-IRQ' on sta basic ; 'Basic-IRQ' on
lda nmibuf ; restore NMI lda nmibuf ; restore NMI
ldx nmibuf + 1 ldx nmibuf + 1

View File

@@ -8,7 +8,7 @@ RM = rm
PROGS = acme PROGS = acme
BINDIR = /usr/local/bin BINDIR = /usr/local/bin
USERBIN = $(HOME)/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 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
all: $(PROGS) all: $(PROGS)
@@ -49,6 +49,8 @@ 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 tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c
clean: clean:
-$(RM) -f *.o $(PROGS) *~ core -$(RM) -f *.o $(PROGS) *~ core

View File

@@ -8,7 +8,7 @@ RM = rm
PROGS = acme PROGS = acme
#BINDIR = /usr/local/bin #BINDIR = /usr/local/bin
#USERBIN = $(HOME)/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 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
all: $(PROGS) all: $(PROGS)
@@ -50,6 +50,8 @@ 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 tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c
clean: clean:
del *.o del *.o
# -$(RM) -f *.o $(PROGS) *~ core # -$(RM) -f *.o $(PROGS) *~ core

View File

@@ -15,8 +15,8 @@ USERBIN = $(HOME)/bin
all: $(PROGS) 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 _dos.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 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 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
strip acme.exe strip acme.exe
@@ -53,6 +53,8 @@ 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 tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c
# _dos.o: _dos.h # _dos.o: _dos.h
win/resource.rc: acme.c win/resource.rc: acme.c

View File

@@ -8,7 +8,7 @@ RM = rm
PROGS = acme PROGS = acme
#BINDIR = /usr/local/bin #BINDIR = /usr/local/bin
#USERBIN = $(HOME)/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 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
all: $(PROGS) all: $(PROGS)
@@ -50,6 +50,8 @@ 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 tree.o: config.h dynabuf.h global.h label.h tree.h tree.c
typesystem.o: config.h global.h typesystem.h typesystem.c
clean: clean:
wipe o.* ~c wipe o.* ~c
# -$(RM) -f *.o $(PROGS) *~ core # -$(RM) -f *.o $(PROGS) *~ core

View File

@@ -15,9 +15,9 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define RELEASE "0.94.12" // update before release (FIXME) #define RELEASE "0.95" // update before release (FIXME)
#define CODENAME "Zarquon" // update before release #define CODENAME "Fenchurch" // update before release
#define CHANGE_DATE "31 May" // update before release #define CHANGE_DATE "2 Jun" // update before release
#define CHANGE_YEAR "2014" // 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://home.pages.de/~mac_bacon/smorbrod/acme/" // FIXME
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME #define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
@@ -64,6 +64,8 @@ static const char name_dumpfile[] = "label dump filename";
#define OPTION_VERSION "version" #define OPTION_VERSION "version"
// options for "-W" // options for "-W"
#define OPTIONWNO_LABEL_INDENT "no-label-indent" #define OPTIONWNO_LABEL_INDENT "no-label-indent"
#define OPTIONWNO_OLD_FOR "no-old-for"
#define OPTIONWTYPE_MISMATCH "type-mismatch"
// variables // variables
@@ -126,6 +128,8 @@ static void show_help_and_exit(void)
// as long as there is only one -W option: // as long as there is only one -W option:
#define OPTIONWNO_LABEL_INDENT "no-label-indent" #define OPTIONWNO_LABEL_INDENT "no-label-indent"
" -W" OPTIONWNO_LABEL_INDENT " suppress warnings about indented labels\n" " -W" OPTIONWNO_LABEL_INDENT " suppress warnings about indented labels\n"
" -W" OPTIONWNO_OLD_FOR " suppress warnings about old \"!for\" syntax\n"
" -W" OPTIONWTYPE_MISMATCH " enable type checking (warn about type mismatch)\n"
// when there are more, use next line and add a separate function: // when there are more, use next line and add a separate function:
//" -W show warning level options\n" //" -W show warning level options\n"
" --" OPTION_USE_STDOUT " fix for 'Relaunch64' IDE (see docs)\n" " --" OPTION_USE_STDOUT " fix for 'Relaunch64' IDE (see docs)\n"
@@ -425,6 +429,12 @@ static char short_option(const char *argument)
if (strcmp(argument + 1, OPTIONWNO_LABEL_INDENT) == 0) { if (strcmp(argument + 1, OPTIONWNO_LABEL_INDENT) == 0) {
warn_on_indented_labels = FALSE; warn_on_indented_labels = FALSE;
goto done; goto done;
} else if (strcmp(argument + 1, OPTIONWNO_OLD_FOR) == 0) {
warn_on_old_for = FALSE;
goto done;
} else if (strcmp(argument + 1, OPTIONWTYPE_MISMATCH) == 0) {
warn_on_type_mismatch = TRUE;
goto done;
} else { } else {
fprintf(stderr, "%sUnknown warning level.\n", cliargs_error); fprintf(stderr, "%sUnknown warning level.\n", cliargs_error);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

126
src/alu.c
View File

@@ -48,6 +48,7 @@ enum operator_handle {
OPHANDLE_END, // "reached end of expression" OPHANDLE_END, // "reached end of expression"
OPHANDLE_RETURN, // "return value to caller" OPHANDLE_RETURN, // "return value to caller"
// functions // functions
OPHANDLE_ADDR, // addr(v)
OPHANDLE_INT, // int(v) OPHANDLE_INT, // int(v)
OPHANDLE_FLOAT, // float(v) OPHANDLE_FLOAT, // float(v)
OPHANDLE_SIN, // sin(v) OPHANDLE_SIN, // sin(v)
@@ -129,6 +130,7 @@ static struct operator ops_negate = {OPHANDLE_NEGATE, 28}; // monadic
static struct operator ops_powerof = {OPHANDLE_POWEROF, 29}; // dyadic, right-associative static struct operator ops_powerof = {OPHANDLE_POWEROF, 29}; // dyadic, right-associative
static struct operator ops_not = {OPHANDLE_NOT, 30}; // monadic static struct operator ops_not = {OPHANDLE_NOT, 30}; // monadic
// function calls act as if they were monadic operators // function calls act as if they were monadic operators
static struct operator ops_addr = {OPHANDLE_ADDR, 32}; // function
static struct operator ops_int = {OPHANDLE_INT, 32}; // function static struct operator ops_int = {OPHANDLE_INT, 32}; // function
static struct operator ops_float = {OPHANDLE_FLOAT, 32}; // function static struct operator ops_float = {OPHANDLE_FLOAT, 32}; // function
static struct operator ops_sin = {OPHANDLE_SIN, 32}; // function static struct operator ops_sin = {OPHANDLE_SIN, 32}; // function
@@ -176,6 +178,7 @@ static struct node_t operator_list[] = {
}; };
static struct node_t *function_tree = NULL; // tree to hold functions static struct node_t *function_tree = NULL; // tree to hold functions
static struct node_t function_list[] = { static struct node_t function_list[] = {
PREDEFNODE("addr", &ops_addr),
PREDEFNODE("int", &ops_int), PREDEFNODE("int", &ops_int),
PREDEFNODE("float", &ops_float), PREDEFNODE("float", &ops_float),
PREDEFNODE(s_arcsin, &ops_arcsin), PREDEFNODE(s_arcsin, &ops_arcsin),
@@ -193,18 +196,22 @@ static struct node_t function_list[] = {
#define RIGHT_INTVAL (operand_stack[operand_sp-1].val.intval) #define RIGHT_INTVAL (operand_stack[operand_sp-1].val.intval)
#define LEFT_FPVAL (operand_stack[operand_sp-2].val.fpval) #define LEFT_FPVAL (operand_stack[operand_sp-2].val.fpval)
#define RIGHT_FPVAL (operand_stack[operand_sp-1].val.fpval) #define RIGHT_FPVAL (operand_stack[operand_sp-1].val.fpval)
#define LEFT_ADDRREFS (operand_stack[operand_sp-2].addr_refs)
#define RIGHT_ADDRREFS (operand_stack[operand_sp-1].addr_refs)
#define PUSH_OPERATOR(x) operator_stack[operator_sp++] = (x) #define PUSH_OPERATOR(x) operator_stack[operator_sp++] = (x)
#define PUSH_INTOPERAND(i, f) \ #define PUSH_INTOPERAND(i, f, r) \
do { \ do { \
operand_stack[operand_sp].flags = (f); \ operand_stack[operand_sp].flags = (f); \
operand_stack[operand_sp++].val.intval = (i); \ operand_stack[operand_sp].val.intval = (i); \
operand_stack[operand_sp++].addr_refs = (r); \
} while (0) } while (0)
#define PUSH_FPOPERAND(fp, f) \ #define PUSH_FPOPERAND(fp, f) \
do { \ do { \
operand_stack[operand_sp].flags = (f) | MVALUE_IS_FP; \ operand_stack[operand_sp].flags = (f) | MVALUE_IS_FP; \
operand_stack[operand_sp++].val.fpval = (fp); \ operand_stack[operand_sp].val.fpval = (fp); \
operand_stack[operand_sp++].addr_refs = 0; \
} while (0) } while (0)
@@ -353,7 +360,7 @@ static void parse_quoted_character(char closing_quote)
Throw_error("There's more than one character."); Throw_error("There's more than one character.");
Input_skip_remainder(); Input_skip_remainder();
} }
PUSH_INTOPERAND(value, MVALUE_GIVEN | MVALUE_ISBYTE); PUSH_INTOPERAND(value, MVALUE_GIVEN | MVALUE_ISBYTE, 0);
// Now GotByte = char following closing quote (or CHAR_EOS on error) // Now GotByte = char following closing quote (or CHAR_EOS on error)
} }
@@ -393,7 +400,7 @@ static void parse_binary_value(void) // Now GotByte = "%" or "b"
flags |= MVALUE_FORCE16; flags |= MVALUE_FORCE16;
} }
} }
PUSH_INTOPERAND(value, flags); PUSH_INTOPERAND(value, flags, 0);
// Now GotByte = non-binary char // Now GotByte = non-binary char
} }
@@ -437,7 +444,7 @@ static void parse_hexadecimal_value(void) // Now GotByte = "$" or "x"
flags |= MVALUE_FORCE16; flags |= MVALUE_FORCE16;
} }
} }
PUSH_INTOPERAND(value, flags); PUSH_INTOPERAND(value, flags, 0);
// Now GotByte = non-hexadecimal char // Now GotByte = non-hexadecimal char
} }
@@ -497,7 +504,7 @@ static void parse_decimal_value(void) // Now GotByte = first digit
GetByte(); GetByte();
parse_frac_part(intval); parse_frac_part(intval);
} else { } else {
PUSH_INTOPERAND(intval, MVALUE_GIVEN); PUSH_INTOPERAND(intval, MVALUE_GIVEN, 0);
} }
// Now GotByte = non-decimal char // Now GotByte = non-decimal char
} }
@@ -527,7 +534,7 @@ static void parse_octal_value(void) // Now GotByte = "&"
flags |= MVALUE_FORCE16; flags |= MVALUE_FORCE16;
} }
} }
PUSH_INTOPERAND(value, flags); PUSH_INTOPERAND(value, flags, 0);
// Now GotByte = non-octal char // Now GotByte = non-octal char
} }
@@ -535,11 +542,11 @@ static void parse_octal_value(void) // Now GotByte = "&"
// Parse program counter ('*') // Parse program counter ('*')
static void parse_program_counter(void) // Now GotByte = "*" static void parse_program_counter(void) // Now GotByte = "*"
{ {
struct result_int_t pc; struct result_t pc;
GetByte(); GetByte();
vcpu_read_pc(&pc); vcpu_read_pc(&pc);
PUSH_INTOPERAND(pc.intval, pc.flags | MVALUE_EXISTS); PUSH_INTOPERAND(pc.val.intval, pc.flags | MVALUE_EXISTS, pc.addr_refs);
} }
@@ -698,7 +705,7 @@ static void expect_operand_or_monadic_operator(void)
} }
} else { } else {
// illegal character read - so don't go on // illegal character read - so don't go on
PUSH_INTOPERAND(0, 0); PUSH_INTOPERAND(0, 0, 0); // push dummy operand so stack is ok
// push pseudo value, EXISTS flag is clear // push pseudo value, EXISTS flag is clear
if (operator_stack[operator_sp-1] == &ops_return) { if (operator_stack[operator_sp-1] == &ops_return) {
PUSH_OPERATOR(&ops_end); PUSH_OPERATOR(&ops_end);
@@ -840,7 +847,7 @@ static void expect_dyadic_operator(void)
//break; unreachable //break; unreachable
// end of expression or text version of dyadic operator // end of expression or text version of dyadic operator
default: default:
// check string version of operators // check string versions of operators
if (BYTEFLAGS(GotByte) & STARTS_KEYWORD) { if (BYTEFLAGS(GotByte) & STARTS_KEYWORD) {
Input_read_and_lower_keyword(); Input_read_and_lower_keyword();
// Now GotByte = illegal char // Now GotByte = illegal char
@@ -878,6 +885,7 @@ static void perform_fp(double (*fn)(double))
RIGHT_FLAGS |= MVALUE_IS_FP; RIGHT_FLAGS |= MVALUE_IS_FP;
} }
RIGHT_FPVAL = fn(RIGHT_FPVAL); RIGHT_FPVAL = fn(RIGHT_FPVAL);
RIGHT_ADDRREFS = 0; // result now is a non-address
} }
@@ -895,6 +903,7 @@ static void perform_ranged_fp(double (*fn)(double))
Throw_error("Argument out of range."); Throw_error("Argument out of range.");
RIGHT_FPVAL = 0; RIGHT_FPVAL = 0;
} }
RIGHT_ADDRREFS = 0; // result now is a non-address
} }
@@ -918,7 +927,7 @@ static void both_ensure_int(int warn)
RIGHT_INTVAL = RIGHT_FPVAL; RIGHT_INTVAL = RIGHT_FPVAL;
RIGHT_FLAGS &= ~MVALUE_IS_FP; RIGHT_FLAGS &= ~MVALUE_IS_FP;
} }
// FIXME - "warn" is not used // FIXME - warning is never seen if both operands are undefined in first pass!
Throw_first_pass_warning("Converted to integer for binary logic operator."); Throw_first_pass_warning("Converted to integer for binary logic operator.");
} }
@@ -993,9 +1002,14 @@ static void try_to_reduce_stacks(int *open_parentheses)
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
// functions // functions
case OPHANDLE_ADDR:
RIGHT_ADDRREFS = 1; // result now is an address
goto remove_next_to_last_operator;
case OPHANDLE_INT: case OPHANDLE_INT:
if (RIGHT_FLAGS & MVALUE_IS_FP) if (RIGHT_FLAGS & MVALUE_IS_FP)
right_fp_to_int(); right_fp_to_int();
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
case OPHANDLE_FLOAT: case OPHANDLE_FLOAT:
@@ -1004,30 +1018,31 @@ static void try_to_reduce_stacks(int *open_parentheses)
RIGHT_FPVAL = RIGHT_INTVAL; RIGHT_FPVAL = RIGHT_INTVAL;
RIGHT_FLAGS |= MVALUE_IS_FP; RIGHT_FLAGS |= MVALUE_IS_FP;
} }
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
case OPHANDLE_SIN: case OPHANDLE_SIN:
perform_fp(sin); perform_fp(sin); // also zeroes addr_refs
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
case OPHANDLE_COS: case OPHANDLE_COS:
perform_fp(cos); perform_fp(cos); // also zeroes addr_refs
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
case OPHANDLE_TAN: case OPHANDLE_TAN:
perform_fp(tan); perform_fp(tan); // also zeroes addr_refs
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
case OPHANDLE_ARCSIN: case OPHANDLE_ARCSIN:
perform_ranged_fp(asin); perform_ranged_fp(asin); // also zeroes addr_refs
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
case OPHANDLE_ARCCOS: case OPHANDLE_ARCCOS:
perform_ranged_fp(acos); perform_ranged_fp(acos); // also zeroes addr_refs
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
case OPHANDLE_ARCTAN: case OPHANDLE_ARCTAN:
perform_fp(atan); perform_fp(atan); // also zeroes addr_refs
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
// monadic operators // monadic operators
@@ -1055,6 +1070,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
RIGHT_INTVAL = (RIGHT_INTVAL) & 255; RIGHT_INTVAL = (RIGHT_INTVAL) & 255;
RIGHT_FLAGS |= MVALUE_ISBYTE; RIGHT_FLAGS |= MVALUE_ISBYTE;
RIGHT_FLAGS &= ~MVALUE_FORCEBITS; RIGHT_FLAGS &= ~MVALUE_FORCEBITS;
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
case OPHANDLE_HIGHBYTEOF: case OPHANDLE_HIGHBYTEOF:
@@ -1064,6 +1080,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
RIGHT_INTVAL = ((RIGHT_INTVAL) >> 8) & 255; RIGHT_INTVAL = ((RIGHT_INTVAL) >> 8) & 255;
RIGHT_FLAGS |= MVALUE_ISBYTE; RIGHT_FLAGS |= MVALUE_ISBYTE;
RIGHT_FLAGS &= ~MVALUE_FORCEBITS; RIGHT_FLAGS &= ~MVALUE_FORCEBITS;
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
case OPHANDLE_BANKBYTEOF: case OPHANDLE_BANKBYTEOF:
@@ -1073,6 +1090,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
RIGHT_INTVAL = ((RIGHT_INTVAL) >> 16) & 255; RIGHT_INTVAL = ((RIGHT_INTVAL) >> 16) & 255;
RIGHT_FLAGS |= MVALUE_ISBYTE; RIGHT_FLAGS |= MVALUE_ISBYTE;
RIGHT_FLAGS &= ~MVALUE_FORCEBITS; RIGHT_FLAGS &= ~MVALUE_FORCEBITS;
RIGHT_ADDRREFS = 0; // result now is a non-address
goto remove_next_to_last_operator; goto remove_next_to_last_operator;
// dyadic operators // dyadic operators
@@ -1080,6 +1098,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) { if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) {
both_ensure_fp(); both_ensure_fp();
LEFT_FPVAL = pow(LEFT_FPVAL, RIGHT_FPVAL); LEFT_FPVAL = pow(LEFT_FPVAL, RIGHT_FPVAL);
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
} }
@@ -1090,6 +1109,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
Throw_error("Exponent is negative."); Throw_error("Exponent is negative.");
LEFT_INTVAL = 0; LEFT_INTVAL = 0;
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_MULTIPLY: case OPHANDLE_MULTIPLY:
@@ -1099,6 +1119,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else { } else {
LEFT_INTVAL *= RIGHT_INTVAL; LEFT_INTVAL *= RIGHT_INTVAL;
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_DIVIDE: case OPHANDLE_DIVIDE:
@@ -1120,6 +1141,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
LEFT_INTVAL = 0; LEFT_INTVAL = 0;
} }
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_INTDIV: case OPHANDLE_INTDIV:
@@ -1142,6 +1164,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
LEFT_INTVAL = 0; LEFT_INTVAL = 0;
} }
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_MODULO: case OPHANDLE_MODULO:
@@ -1154,6 +1177,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
Throw_error(exception_div_by_zero); Throw_error(exception_div_by_zero);
LEFT_INTVAL = 0; LEFT_INTVAL = 0;
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_ADD: case OPHANDLE_ADD:
@@ -1163,6 +1187,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else { } else {
LEFT_INTVAL += RIGHT_INTVAL; LEFT_INTVAL += RIGHT_INTVAL;
} }
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_SUBTRACT: case OPHANDLE_SUBTRACT:
@@ -1172,6 +1197,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else { } else {
LEFT_INTVAL -= RIGHT_INTVAL; LEFT_INTVAL -= RIGHT_INTVAL;
} }
LEFT_ADDRREFS -= RIGHT_ADDRREFS; // subtract address references
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_SL: case OPHANDLE_SL:
@@ -1181,6 +1207,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
LEFT_FPVAL *= pow(2.0, RIGHT_INTVAL); LEFT_FPVAL *= pow(2.0, RIGHT_INTVAL);
else else
LEFT_INTVAL <<= RIGHT_INTVAL; LEFT_INTVAL <<= RIGHT_INTVAL;
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_ASR: case OPHANDLE_ASR:
@@ -1190,6 +1217,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
LEFT_FPVAL /= (1 << RIGHT_INTVAL); LEFT_FPVAL /= (1 << RIGHT_INTVAL);
else else
LEFT_INTVAL = my_asr(LEFT_INTVAL, RIGHT_INTVAL); LEFT_INTVAL = my_asr(LEFT_INTVAL, RIGHT_INTVAL);
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_LSR: case OPHANDLE_LSR:
@@ -1197,6 +1225,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
both_ensure_int(TRUE); both_ensure_int(TRUE);
LEFT_INTVAL = ((uintval_t) LEFT_INTVAL) >> RIGHT_INTVAL; LEFT_INTVAL = ((uintval_t) LEFT_INTVAL) >> RIGHT_INTVAL;
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_LE: case OPHANDLE_LE:
@@ -1206,6 +1235,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else { } else {
LEFT_INTVAL = (LEFT_INTVAL <= RIGHT_INTVAL); LEFT_INTVAL = (LEFT_INTVAL <= RIGHT_INTVAL);
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_LESSTHAN: case OPHANDLE_LESSTHAN:
@@ -1215,6 +1245,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else { } else {
LEFT_INTVAL = (LEFT_INTVAL < RIGHT_INTVAL); LEFT_INTVAL = (LEFT_INTVAL < RIGHT_INTVAL);
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_GE: case OPHANDLE_GE:
@@ -1224,6 +1255,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else { } else {
LEFT_INTVAL = (LEFT_INTVAL >= RIGHT_INTVAL); LEFT_INTVAL = (LEFT_INTVAL >= RIGHT_INTVAL);
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_GREATERTHAN: case OPHANDLE_GREATERTHAN:
@@ -1233,6 +1265,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else { } else {
LEFT_INTVAL = (LEFT_INTVAL > RIGHT_INTVAL); LEFT_INTVAL = (LEFT_INTVAL > RIGHT_INTVAL);
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_NOTEQUAL: case OPHANDLE_NOTEQUAL:
@@ -1242,6 +1275,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else { } else {
LEFT_INTVAL = (LEFT_INTVAL != RIGHT_INTVAL); LEFT_INTVAL = (LEFT_INTVAL != RIGHT_INTVAL);
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_EQUALS: case OPHANDLE_EQUALS:
@@ -1251,6 +1285,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
} else { } else {
LEFT_INTVAL = (LEFT_INTVAL == RIGHT_INTVAL); LEFT_INTVAL = (LEFT_INTVAL == RIGHT_INTVAL);
} }
LEFT_ADDRREFS = 0; // result now is a non-address
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_AND: case OPHANDLE_AND:
@@ -1258,6 +1293,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
both_ensure_int(TRUE); both_ensure_int(TRUE);
LEFT_INTVAL &= RIGHT_INTVAL; LEFT_INTVAL &= RIGHT_INTVAL;
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_EOR: case OPHANDLE_EOR:
@@ -1268,6 +1304,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
both_ensure_int(TRUE); both_ensure_int(TRUE);
LEFT_INTVAL ^= RIGHT_INTVAL; LEFT_INTVAL ^= RIGHT_INTVAL;
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
case OPHANDLE_OR: case OPHANDLE_OR:
@@ -1275,6 +1312,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
both_ensure_int(TRUE); both_ensure_int(TRUE);
LEFT_INTVAL |= RIGHT_INTVAL; LEFT_INTVAL |= RIGHT_INTVAL;
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
goto handle_flags_and_dec_stacks; goto handle_flags_and_dec_stacks;
default: default:
@@ -1389,8 +1427,7 @@ static int parse_expression(struct result_t *result)
} }
// These functions handle numerical expressions. There are operators for // These functions handle numerical expressions.
// arithmetic, logic, shift and comparison operations.
// There are several different ways to call the core function: // There are several different ways to call the core function:
// intval_t ALU_any_int(void); // intval_t ALU_any_int(void);
// returns int value (0 if result was undefined) // returns int value (0 if result was undefined)
@@ -1473,23 +1510,19 @@ int ALU_optional_defined_int(intval_t *target)
// It the result's "exists" flag is clear (=empty expression), it throws an // It the result's "exists" flag is clear (=empty expression), it throws an
// error. // error.
// If the result's "defined" flag is clear, result_is_undefined() is called. // If the result's "defined" flag is clear, result_is_undefined() is called.
void ALU_int_result(struct result_int_t *intresult) void ALU_int_result(struct result_t *intresult)
{ {
struct result_t result; if (parse_expression(intresult))
if (parse_expression(&result))
Throw_error(exception_paren_open); Throw_error(exception_paren_open);
if ((result.flags & MVALUE_EXISTS) == 0) // make sure result is not float
Throw_error(exception_no_value); if (intresult->flags & MVALUE_IS_FP) {
else if ((result.flags & MVALUE_DEFINED) == 0) intresult->val.intval = intresult->val.fpval;
result_is_undefined(); intresult->flags &= ~MVALUE_IS_FP;
if (result.flags & MVALUE_IS_FP) {
intresult->intval = result.val.fpval;
intresult->flags = result.flags & ~MVALUE_IS_FP;
} else {
intresult->intval = result.val.intval;
intresult->flags = result.flags;
} }
if ((intresult->flags & MVALUE_EXISTS) == 0)
Throw_error(exception_no_value);
else if ((intresult->flags & MVALUE_DEFINED) == 0)
result_is_undefined();
} }
@@ -1497,26 +1530,23 @@ void ALU_int_result(struct result_int_t *intresult)
// This function allows for one '(' too many. Needed when parsing indirect // This function allows for one '(' too many. Needed when parsing indirect
// addressing modes where internal indices have to be possible. Returns number // addressing modes where internal indices have to be possible. Returns number
// of parentheses still open (either 0 or 1). // of parentheses still open (either 0 or 1).
int ALU_liberal_int(struct result_int_t *intresult) int ALU_liberal_int(struct result_t *intresult)
{ {
struct result_t result; int parentheses_still_open;
int parentheses_still_open;
parentheses_still_open = parse_expression(&result); parentheses_still_open = parse_expression(intresult);
// make sure result is not float
if (intresult->flags & MVALUE_IS_FP) {
intresult->val.intval = intresult->val.fpval;
intresult->flags &= ~MVALUE_IS_FP;
}
if (parentheses_still_open > 1) { if (parentheses_still_open > 1) {
parentheses_still_open = 0; parentheses_still_open = 0;
Throw_error(exception_paren_open); Throw_error(exception_paren_open);
} }
if ((result.flags & MVALUE_EXISTS) if ((intresult->flags & MVALUE_EXISTS)
&& ((result.flags & MVALUE_DEFINED) == 0)) && ((intresult->flags & MVALUE_DEFINED) == 0))
result_is_undefined(); result_is_undefined();
if (result.flags & MVALUE_IS_FP) {
intresult->intval = result.val.fpval;
intresult->flags = result.flags & ~MVALUE_IS_FP;
} else {
intresult->intval = result.val.intval;
intresult->flags = result.flags;
}
return parentheses_still_open; return parentheses_still_open;
} }

View File

@@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code. // 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 // Have a look at "acme.c" for further info
// //
// ALU stuff (the expression parser) // ALU stuff (the expression parser)
@@ -12,9 +12,9 @@
// constants // constants
// meaning of bits in "flags" of result_t and result_int_t structures: // meaning of bits in "flags" of result_t structure:
#define MVALUE_IS_FP (1u << 8) #define MVALUE_IS_FP (1u << 8)
// floating point value (never set in result_int_t) // floating point value
#define MVALUE_INDIRECT (1u << 7) #define MVALUE_INDIRECT (1u << 7)
// needless parentheses indicate use of indirect addressing modes // needless parentheses indicate use of indirect addressing modes
#define MVALUE_EXISTS (1u << 6) #define MVALUE_EXISTS (1u << 6)
@@ -50,9 +50,9 @@ extern intval_t ALU_defined_int(void);
// stores int value if given. Returns whether stored. Throws error if undefined. // 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 *);
// stores int value and flags (floats are transformed to int) // stores int value and flags (floats are transformed to int)
extern void ALU_int_result(struct result_int_t *); extern void ALU_int_result(struct result_t *);
// stores int value and flags, allowing for one '(' too many (x-indirect addr) // stores int value and flags, allowing for one '(' too many (x-indirect addr)
extern int ALU_liberal_int(struct result_int_t *); extern int ALU_liberal_int(struct result_t *);
// stores value and flags (result may be either int or float) // 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_t *);

View File

@@ -14,6 +14,7 @@
#include "global.h" #include "global.h"
#include "output.h" #include "output.h"
#include "tree.h" #include "tree.h"
#include "typesystem.h"
// constants // constants
@@ -139,6 +140,19 @@ static enum eos PO_fill(void)
} }
// force explicit label definitions to set "address" flag ("!addr"). Has to be re-entrant.
static enum eos PO_addr(void) // Now GotByte = illegal char
{
SKIPSPACE();
if (GotByte == CHAR_SOB) {
typesystem_force_address_block();
return ENSURE_EOS;
}
typesystem_force_address_statement(TRUE);
return PARSE_REMAINDER;
}
// show user-defined message // show user-defined message
static enum eos throw_string(const char prefix[], void (*fn)(const char *)) static enum eos throw_string(const char prefix[], void (*fn)(const char *))
{ {
@@ -240,6 +254,8 @@ static struct node_t pseudo_opcodes[] = {
PREDEFNODE("binary", PO_binary), PREDEFNODE("binary", PO_binary),
PREDEFNODE("fi", PO_fill), PREDEFNODE("fi", PO_fill),
PREDEFNODE("fill", PO_fill), PREDEFNODE("fill", PO_fill),
PREDEFNODE("addr", PO_addr),
PREDEFNODE("address", PO_addr),
// PREDEFNODE("debug", PO_debug), // PREDEFNODE("debug", PO_debug),
// PREDEFNODE("info", PO_info), // PREDEFNODE("info", PO_info),
// PREDEFNODE("print", PO_print), // PREDEFNODE("print", PO_print),

View File

@@ -18,11 +18,7 @@ struct result_t { // either int or float
intval_t intval; // integer value intval_t intval; // integer value
double fpval; // floating point value double fpval; // floating point value
} val; // Expression value } val; // Expression value
}; int addr_refs; // address reference count (only look at this if value is DEFINED)
// result structure type definition for int
struct result_int_t {
int flags; // expression flags
intval_t intval; // expression value
}; };

View File

@@ -75,7 +75,7 @@ static enum eos PO_align(void)
intval_t and, intval_t and,
equal, equal,
fill, fill,
test = CPU_state.pc.intval; test = CPU_state.pc.val.intval;
// make sure PC is defined. // make sure PC is defined.
if ((CPU_state.pc.flags & MVALUE_DEFINED) == 0) { if ((CPU_state.pc.flags & MVALUE_DEFINED) == 0) {
@@ -152,13 +152,13 @@ static enum eos PO_pseudopc(void)
// set new // set new
new_pc = ALU_defined_int(); // FIXME - allow for undefined! new_pc = ALU_defined_int(); // FIXME - allow for undefined!
new_offset = (new_pc - CPU_state.pc.intval) & 0xffff; new_offset = (new_pc - CPU_state.pc.val.intval) & 0xffff;
CPU_state.pc.intval = new_pc; CPU_state.pc.val.intval = new_pc;
CPU_state.pc.flags |= MVALUE_DEFINED; // FIXME - remove when allowing undefined! CPU_state.pc.flags |= MVALUE_DEFINED; // FIXME - remove when allowing undefined!
// if there's a block, parse that and then restore old value! // if there's a block, parse that and then restore old value!
if (Parse_optional_block()) { if (Parse_optional_block()) {
// restore old // restore old
CPU_state.pc.intval = (CPU_state.pc.intval - new_offset) & 0xffff; CPU_state.pc.val.intval = (CPU_state.pc.val.intval - new_offset) & 0xffff;
CPU_state.pc.flags = outer_flags; CPU_state.pc.flags = outer_flags;
} else { } else {
// not using a block is no longer allowed // not using a block is no longer allowed

View File

@@ -209,12 +209,15 @@ static enum eos PO_for(void) // Now GotByte = illegal char
first_arg = ALU_defined_int(); first_arg = ALU_defined_int();
if (Input_accept_comma()) { if (Input_accept_comma()) {
old_algo = FALSE; // new format - yay! old_algo = FALSE; // new format - yay!
if (!warn_on_old_for)
Throw_first_pass_warning("Found new \"!for\" syntax.");
counter_first = first_arg; // use given argument counter_first = first_arg; // use given argument
counter_last = ALU_defined_int(); // read second argument counter_last = ALU_defined_int(); // read second argument
counter_increment = (counter_last < counter_first) ? -1 : 1; counter_increment = (counter_last < counter_first) ? -1 : 1;
} else { } else {
old_algo = TRUE; // old format - booo! old_algo = TRUE; // old format - booo!
Throw_first_pass_warning("Found deprecated \"!for\" syntax."); if (warn_on_old_for)
Throw_first_pass_warning("Found old \"!for\" syntax.");
if (first_arg < 0) if (first_arg < 0)
Throw_serious_error("Loop count is negative."); Throw_serious_error("Loop count is negative.");
counter_first = 0; // CAUTION - old algo pre-increments and therefore starts with 1! counter_first = 0; // CAUTION - old algo pre-increments and therefore starts with 1!

View File

@@ -5,6 +5,7 @@
// Global stuff - things that are needed by several modules // Global stuff - things that are needed by several modules
// 4 Oct 2006 Fixed a typo in a comment // 4 Oct 2006 Fixed a typo in a comment
// 22 Nov 2007 Added warn_on_indented_labels // 22 Nov 2007 Added warn_on_indented_labels
// 2 Jun 2014 Added warn_on_old_for and warn_on_type_mismatch
#include <stdio.h> #include <stdio.h>
#include "platform.h" #include "platform.h"
#include "acme.h" #include "acme.h"
@@ -17,6 +18,7 @@
#include "output.h" #include "output.h"
#include "section.h" #include "section.h"
#include "tree.h" #include "tree.h"
#include "typesystem.h"
// constants // constants
@@ -55,7 +57,7 @@ const char exception_syntax[] = "Syntax error.";
// ...4.... special character for input syntax: 0x00 TAB LF CR SPC : ; } // ...4.... special character for input syntax: 0x00 TAB LF CR SPC : ; }
// ....3... preceding sequence of '-' characters is anonymous backward // ....3... preceding sequence of '-' characters is anonymous backward
// label. Currently only set for ')', ',' and CHAR_EOS. // label. Currently only set for ')', ',' and CHAR_EOS.
// .....210 unused // .....210 currently unused
const char Byte_flags[256] = { const char Byte_flags[256] = {
/*$00*/ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// control characters /*$00*/ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// control characters
0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00,
@@ -98,6 +100,8 @@ int pass_count; // number of current pass (starts 0)
char GotByte; // Last byte read (processed) char GotByte; // Last byte read (processed)
int Process_verbosity = 0; // Level of additional output int Process_verbosity = 0; // Level of additional output
int warn_on_indented_labels = TRUE; // warn if indented label is encountered int warn_on_indented_labels = TRUE; // warn if indented label is encountered
int warn_on_old_for = TRUE; // warn if "!for" with old syntax is found
int warn_on_type_mismatch = FALSE; // use type-checking system
// global counters // global counters
int pass_undefined_count; // "NeedValue" type errors int pass_undefined_count; // "NeedValue" type errors
int pass_real_errors; // Errors yet int pass_real_errors; // Errors yet
@@ -256,9 +260,10 @@ void Parse_until_eob_or_eof(void)
while ((GotByte != CHAR_EOB) && (GotByte != CHAR_EOF)) { while ((GotByte != CHAR_EOB) && (GotByte != CHAR_EOF)) {
// process one statement // process one statement
statement_flags = 0; // no "label = pc" definition yet statement_flags = 0; // no "label = pc" definition yet
typesystem_force_address_statement(FALSE);
// Parse until end of statement. Only loops if statement // Parse until end of statement. Only loops if statement
// contains "label = pc" definition and something else; or // contains "label = pc" definition and something else; or
// if "!ifdef" is true. // if "!ifdef" is true, or if "!addr" is used without block.
do { do {
switch (GotByte) { switch (GotByte) {
case CHAR_EOS: // end of statement case CHAR_EOS: // end of statement

View File

@@ -1,5 +1,5 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code. // 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 // Have a look at "acme.c" for further info
// //
// Global stuff - things that are needed by several modules // Global stuff - things that are needed by several modules
@@ -47,7 +47,7 @@ extern const char Byte_flags[];
// converted to lower case by OR-ing this bit(!) // converted to lower case by OR-ing this bit(!)
#define BYTEIS_SYNTAX (1u << 4) // special character for input syntax #define BYTEIS_SYNTAX (1u << 4) // special character for input syntax
#define FOLLOWS_ANON (1u << 3) // preceding '-' are backward label #define FOLLOWS_ANON (1u << 3) // preceding '-' are backward label
// bits 2, 1 and 0 are unused // bits 2, 1 and 0 are currently unused
// Variables // Variables
@@ -64,6 +64,8 @@ enum eos {
extern int pass_count; extern int pass_count;
extern int Process_verbosity; // Level of additional output extern int Process_verbosity; // Level of additional output
extern int warn_on_indented_labels; // warn if indented label is encountered extern int warn_on_indented_labels; // warn if indented label is encountered
extern int warn_on_old_for; // warn if "!for" with old syntax is found
extern int warn_on_type_mismatch; // use type-checking system
extern char GotByte; // Last byte read (processed) extern char GotByte; // Last byte read (processed)
// Global counters // Global counters
extern int pass_undefined_count; // "NeedValue" type errors in current pass extern int pass_undefined_count; // "NeedValue" type errors in current pass

View File

@@ -17,6 +17,7 @@
#include "platform.h" #include "platform.h"
#include "section.h" #include "section.h"
#include "tree.h" #include "tree.h"
#include "typesystem.h"
// constants // constants
@@ -62,7 +63,7 @@ static void dump_one_label(struct node_ra_t *node, FILE *fd)
} }
// Search for label. Create if nonexistant. If created, give it flags "Flags". // Search for label. Create if nonexistant. If created, give it flags "flags".
// The label name must be held in GlobalDynaBuf. // The label name must be held in GlobalDynaBuf.
struct label *Label_find(zone_t zone, int flags) struct label *Label_find(zone_t zone, int flags)
{ {
@@ -78,6 +79,7 @@ struct label *Label_find(zone_t zone, int flags)
label = safe_malloc(sizeof(*label)); label = safe_malloc(sizeof(*label));
// Finish empty label item // Finish empty label item
label->result.flags = flags; label->result.flags = flags;
label->result.addr_refs = 0;
if (flags & MVALUE_IS_FP) if (flags & MVALUE_IS_FP)
label->result.val.fpval = 0; label->result.val.fpval = 0;
else else
@@ -206,9 +208,9 @@ static struct node_t pseudo_opcodes[] = {
// GlobalDynaBuf holds the label name. // GlobalDynaBuf holds the label name.
void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change) void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change)
{ {
struct result_int_t pc; struct result_t pc,
struct result_t result; result;
struct label *label; struct label *label;
label = Label_find(zone, force_bit); label = Label_find(zone, force_bit);
// implicit label definition (label) // implicit label definition (label)
@@ -216,7 +218,8 @@ void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int c
Throw_first_pass_warning("Implicit label definition not in leftmost column."); Throw_first_pass_warning("Implicit label definition not in leftmost column.");
vcpu_read_pc(&pc); vcpu_read_pc(&pc);
result.flags = pc.flags & MVALUE_DEFINED; result.flags = pc.flags & MVALUE_DEFINED;
result.val.intval = pc.intval; result.val.intval = pc.val.intval;
result.addr_refs = pc.addr_refs;
Label_set_value(label, &result, change); Label_set_value(label, &result, change);
} }
@@ -236,6 +239,9 @@ void Label_parse_definition(zone_t zone, int stat_flags)
// label = parsed value // label = parsed value
GetByte(); // skip '=' GetByte(); // skip '='
ALU_any_result(&result); ALU_any_result(&result);
// if wanted, mark as address reference
if (typesystem_says_address())
result.addr_refs = 1;
Label_set_value(label, &result, FALSE); Label_set_value(label, &result, FALSE);
Input_ensure_EOS(); Input_ensure_EOS();
} else { } else {

View File

@@ -11,6 +11,7 @@
#include "input.h" #include "input.h"
#include "output.h" #include "output.h"
#include "tree.h" #include "tree.h"
#include "typesystem.h"
// Constants // Constants
@@ -395,9 +396,9 @@ static int get_index(int next)
return addressing_mode; return addressing_mode;
} }
// This function stores the command's argument in the given result_int_t // This function stores the command's argument in the given result_t
// structure (using the valueparser). The addressing mode is returned. // structure (using the valueparser). The addressing mode is returned.
static int get_argument(struct result_int_t *result) static int get_argument(struct result_t *result)
{ {
int open_paren, int open_paren,
addressing_mode = HAM_ABS; addressing_mode = HAM_ABS;
@@ -407,6 +408,7 @@ static int get_argument(struct result_int_t *result)
case '[': case '[':
GetByte(); // proceed with next char GetByte(); // proceed with next char
ALU_int_result(result); ALU_int_result(result);
typesystem_want_addr(result);
if (GotByte == ']') if (GotByte == ']')
addressing_mode |= HAM_LIND | get_index(TRUE); addressing_mode |= HAM_LIND | get_index(TRUE);
else else
@@ -416,10 +418,12 @@ static int get_argument(struct result_int_t *result)
GetByte(); // proceed with next char GetByte(); // proceed with next char
addressing_mode |= HAM_IMM; addressing_mode |= HAM_IMM;
ALU_int_result(result); ALU_int_result(result);
typesystem_want_imm(result);
break; break;
default: default:
// liberal, to allow for "(...," // liberal, to allow for "(...,"
open_paren = ALU_liberal_int(result); open_paren = ALU_liberal_int(result);
typesystem_want_addr(result);
// check for implied addressing // check for implied addressing
if ((result->flags & MVALUE_EXISTS) == 0) if ((result->flags & MVALUE_EXISTS) == 0)
addressing_mode |= HAM_IMP; addressing_mode |= HAM_IMP;
@@ -447,7 +451,7 @@ static int get_argument(struct result_int_t *result)
// Helper function for calc_arg_size() // Helper function for calc_arg_size()
// Only call with "size_bit = MVALUE_FORCE16" or "size_bit = MVALUE_FORCE24" // Only call with "size_bit = MVALUE_FORCE16" or "size_bit = MVALUE_FORCE24"
static int check_oversize(int size_bit, struct result_int_t *argument) static int check_oversize(int size_bit, struct result_t *argument)
{ {
// only check if value is *defined* // only check if value is *defined*
if ((argument->flags & MVALUE_DEFINED) == 0) if ((argument->flags & MVALUE_DEFINED) == 0)
@@ -456,11 +460,11 @@ static int check_oversize(int size_bit, struct result_int_t *argument)
// value is defined, so check // value is defined, so check
if (size_bit == MVALUE_FORCE16) { if (size_bit == MVALUE_FORCE16) {
// check 16-bit argument for high byte zero // check 16-bit argument for high byte zero
if ((argument->intval <= 255) && (argument->intval >= -128)) if ((argument->val.intval <= 255) && (argument->val.intval >= -128))
Throw_warning(exception_highbyte_zero); Throw_warning(exception_highbyte_zero);
} else { } else {
// check 24-bit argument for bank byte zero // check 24-bit argument for bank byte zero
if ((argument->intval <= 65535) && (argument->intval >= -32768)) if ((argument->val.intval <= 65535) && (argument->val.intval >= -32768))
Throw_warning(exception_highbyte_zero); Throw_warning(exception_highbyte_zero);
} }
return size_bit; // pass on result return size_bit; // pass on result
@@ -474,7 +478,7 @@ static int check_oversize(int size_bit, struct result_int_t *argument)
// argument value and flags of parameter // argument value and flags of parameter
// addressing_modes adressing modes (8b, 16b, 24b or any combination) // addressing_modes adressing modes (8b, 16b, 24b or any combination)
// Return value = force bit for number of parameter bytes to send (0 = error) // Return value = force bit for number of parameter bytes to send (0 = error)
static int calc_arg_size(int force_bit, struct result_int_t *argument, int addressing_modes) static int calc_arg_size(int force_bit, struct result_t *argument, int addressing_modes)
{ {
// if there are no possible addressing modes, complain // if there are no possible addressing modes, complain
if (addressing_modes == MAYBE______) { if (addressing_modes == MAYBE______) {
@@ -541,18 +545,18 @@ static int calc_arg_size(int force_bit, struct result_int_t *argument, int addre
// Value is sure, so use its own size // Value is sure, so use its own size
// if value is negative, size cannot be chosen. Complain! // if value is negative, size cannot be chosen. Complain!
if (argument->intval < 0) { if (argument->val.intval < 0) {
Throw_error("Negative value - cannot choose addressing mode."); Throw_error("Negative value - cannot choose addressing mode.");
return 0; return 0;
} }
// Value is positive or zero. Check size ranges // Value is positive or zero. Check size ranges
// if there is an 8-bit addressing mode and value fits, use 8 bits // if there is an 8-bit addressing mode and value fits, use 8 bits
if ((addressing_modes & MVALUE_FORCE08) && (argument->intval < 256)) if ((addressing_modes & MVALUE_FORCE08) && (argument->val.intval < 256))
return MVALUE_FORCE08; return MVALUE_FORCE08;
// if there is a 16-bit addressing mode and value fits, use 16 bits // if there is a 16-bit addressing mode and value fits, use 16 bits
if ((addressing_modes & MVALUE_FORCE16) && (argument->intval < 65536)) if ((addressing_modes & MVALUE_FORCE16) && (argument->val.intval < 65536))
return MVALUE_FORCE16; return MVALUE_FORCE16;
// if there is a 24-bit addressing mode, use that. In case the // if there is a 24-bit addressing mode, use that. In case the
@@ -584,16 +588,17 @@ static void not_in_bank(intval_t target)
// Mnemonics using only 8bit relative addressing (short branch instructions). // Mnemonics using only 8bit relative addressing (short branch instructions).
static void group_only_relative8_addressing(int opcode) static void group_only_relative8_addressing(int opcode)
{ {
struct result_int_t target; struct result_t target;
intval_t offset = 0; // dummy value, to not throw more errors than necessary intval_t offset = 0; // dummy value, to not throw more errors than necessary
ALU_int_result(&target); ALU_int_result(&target);
typesystem_want_addr(&target);
// FIXME - read pc via function call instead! // FIXME - read pc via function call instead!
if (CPU_state.pc.flags & target.flags & MVALUE_DEFINED) { if (CPU_state.pc.flags & target.flags & MVALUE_DEFINED) {
if ((target.intval | 0xffff) != 0xffff) { if ((target.val.intval | 0xffff) != 0xffff) {
not_in_bank(target.intval); not_in_bank(target.val.intval);
} else { } else {
offset = (target.intval - (CPU_state.pc.intval + 2)) & 0xffff; // clip to 16 bit offset offset = (target.val.intval - (CPU_state.pc.val.intval + 2)) & 0xffff; // clip to 16 bit offset
// fix sign // fix sign
if (offset & 0x8000) if (offset & 0x8000)
offset -= 0x10000; offset -= 0x10000;
@@ -618,16 +623,17 @@ static void group_only_relative8_addressing(int opcode)
// Mnemonics using only 16bit relative addressing (BRL and PER). // Mnemonics using only 16bit relative addressing (BRL and PER).
static void group_only_relative16_addressing(int opcode) static void group_only_relative16_addressing(int opcode)
{ {
struct result_int_t target; struct result_t target;
intval_t offset = 0; // dummy value, to not throw more errors than necessary intval_t offset = 0; // dummy value, to not throw more errors than necessary
ALU_int_result(&target); ALU_int_result(&target);
typesystem_want_addr(&target);
// FIXME - read pc via function call instead! // FIXME - read pc via function call instead!
if (CPU_state.pc.flags & target.flags & MVALUE_DEFINED) { if (CPU_state.pc.flags & target.flags & MVALUE_DEFINED) {
if ((target.intval | 0xffff) != 0xffff) { if ((target.val.intval | 0xffff) != 0xffff) {
not_in_bank(target.intval); not_in_bank(target.val.intval);
} else { } else {
offset = (target.intval - (CPU_state.pc.intval + 3)) & 0xffff; offset = (target.val.intval - (CPU_state.pc.val.intval + 3)) & 0xffff;
// no further checks necessary, 16-bit branches can access whole bank // no further checks necessary, 16-bit branches can access whole bank
} }
} }
@@ -638,7 +644,7 @@ static void group_only_relative16_addressing(int opcode)
// set addressing mode bits depending on which opcodes exist, then calculate // set addressing mode bits depending on which opcodes exist, then calculate
// argument size and output both opcode and argument // argument size and output both opcode and argument
static void make_command(int force_bit, struct result_int_t *result, unsigned long opcodes) static void make_command(int force_bit, struct result_t *result, unsigned long opcodes)
{ {
int addressing_modes = MAYBE______; int addressing_modes = MAYBE______;
@@ -651,15 +657,15 @@ static void make_command(int force_bit, struct result_int_t *result, unsigned lo
switch (calc_arg_size(force_bit, result, addressing_modes)) { switch (calc_arg_size(force_bit, result, addressing_modes)) {
case MVALUE_FORCE08: case MVALUE_FORCE08:
Output_byte(opcodes & 255); Output_byte(opcodes & 255);
Output_8b(result->intval); Output_8b(result->val.intval);
break; break;
case MVALUE_FORCE16: case MVALUE_FORCE16:
Output_byte((opcodes >> 8) & 255); Output_byte((opcodes >> 8) & 255);
Output_16b(result->intval); Output_16b(result->val.intval);
break; break;
case MVALUE_FORCE24: case MVALUE_FORCE24:
Output_byte((opcodes >> 16) & 255); Output_byte((opcodes >> 16) & 255);
Output_24b(result->intval); Output_24b(result->val.intval);
} }
} }
@@ -688,9 +694,9 @@ static unsigned int imm_ops(int *force_bit, unsigned char opcode, int imm_flag)
// plus PEI. // plus PEI.
static void group_main(int index, int imm_flag) static void group_main(int index, int imm_flag)
{ {
unsigned long imm_opcodes; unsigned long imm_opcodes;
struct result_int_t result; struct result_t result;
int force_bit = Input_get_force_bit(); // skips spaces after int force_bit = Input_get_force_bit(); // skips spaces after
switch (get_argument(&result)) { switch (get_argument(&result)) {
case HAM_IMM: // #$ff or #$ffff (depending on accu length) case HAM_IMM: // #$ff or #$ffff (depending on accu length)
@@ -737,9 +743,9 @@ static void group_main(int index, int imm_flag)
// Various mnemonics with different addressing modes. // Various mnemonics with different addressing modes.
static void group_misc(int index, int imm_flag) static void group_misc(int index, int imm_flag)
{ {
unsigned long imm_opcodes; unsigned long imm_opcodes;
struct result_int_t result; struct result_t result;
int force_bit = Input_get_force_bit(); // skips spaces after int force_bit = Input_get_force_bit(); // skips spaces after
switch (get_argument(&result)) { switch (get_argument(&result)) {
case HAM_IMP: // implied addressing case HAM_IMP: // implied addressing
@@ -755,7 +761,7 @@ static void group_misc(int index, int imm_flag)
make_command(force_bit, &result, imm_opcodes); make_command(force_bit, &result, imm_opcodes);
// check whether to warn about 6510's unstable LXA // check whether to warn about 6510's unstable LXA
if ((imm_opcodes == 0xab) if ((imm_opcodes == 0xab)
&& ((result.intval & 0xff) != 0x00) && ((result.val.intval & 0xff) != 0x00)
&& (result.flags & MVALUE_DEFINED) && (result.flags & MVALUE_DEFINED)
&& (CPU_state.type->flags & CPUFLAG_AB_NEEDS_0_ARG)) && (CPU_state.type->flags & CPUFLAG_AB_NEEDS_0_ARG))
Throw_warning("Assembling unstable LXA #NONZERO instruction"); Throw_warning("Assembling unstable LXA #NONZERO instruction");
@@ -796,8 +802,8 @@ static void group_move(int opcode)
// The jump instructions. // The jump instructions.
static void group_jump(int index) static void group_jump(int index)
{ {
struct result_int_t result; struct result_t result;
int force_bit = Input_get_force_bit(); // skips spaces after int force_bit = Input_get_force_bit(); // skips spaces after
switch (get_argument(&result)) { switch (get_argument(&result)) {
case HAM_ABS: // absolute16 or absolute24 case HAM_ABS: // absolute16 or absolute24
@@ -806,7 +812,7 @@ static void group_jump(int index)
case HAM_IND: // ($ffff) case HAM_IND: // ($ffff)
make_command(force_bit, &result, jump_ind[index]); make_command(force_bit, &result, jump_ind[index]);
// check whether to warn about 6502's JMP() bug // check whether to warn about 6502's JMP() bug
if (((result.intval & 0xff) == 0xff) if (((result.val.intval & 0xff) == 0xff)
&& (result.flags & MVALUE_DEFINED) && (result.flags & MVALUE_DEFINED)
&& (CPU_state.type->flags & CPUFLAG_INDIRECTJMPBUGGY)) && (CPU_state.type->flags & CPUFLAG_INDIRECTJMPBUGGY))
Throw_warning("Assembling buggy JMP($xxff) instruction"); Throw_warning("Assembling buggy JMP($xxff) instruction");

View File

@@ -485,7 +485,7 @@ void Output_passinit(void)
//vcpu stuff: //vcpu stuff:
CPU_state.pc.flags = 0; // not defined yet CPU_state.pc.flags = 0; // not defined yet
CPU_state.pc.intval = 0; // same as output's write_idx on pass init CPU_state.pc.val.intval = 0; // same as output's write_idx on pass init
CPU_state.add_to_pc = 0; // increase PC by this at end of statement CPU_state.add_to_pc = 0; // increase PC by this at end of statement
CPU_state.a_is_long = FALSE; // short accu CPU_state.a_is_long = FALSE; // short accu
CPU_state.xy_are_long = FALSE; // short index regs CPU_state.xy_are_long = FALSE; // short index regs
@@ -554,9 +554,10 @@ void vcpu_set_pc(intval_t new_pc, int segment_flags)
{ {
intval_t new_offset; intval_t new_offset;
new_offset = (new_pc - CPU_state.pc.intval) & 0xffff; new_offset = (new_pc - CPU_state.pc.val.intval) & 0xffff;
CPU_state.pc.intval = new_pc; CPU_state.pc.val.intval = new_pc;
CPU_state.pc.flags |= MVALUE_DEFINED; // FIXME - remove when allowing undefined! CPU_state.pc.flags |= MVALUE_DEFINED; // FIXME - remove when allowing undefined!
CPU_state.pc.addr_refs = 1; // yes, PC counts as address
// now tell output buffer to start a new segment // now tell output buffer to start a new segment
Output_start_segment(new_offset, segment_flags); Output_start_segment(new_offset, segment_flags);
} }
@@ -614,7 +615,7 @@ void PO_setpc(void)
// get program counter // get program counter
void vcpu_read_pc(struct result_int_t *target) void vcpu_read_pc(struct result_t *target)
{ {
*target = CPU_state.pc; *target = CPU_state.pc;
} }
@@ -630,6 +631,6 @@ int vcpu_get_statement_size(void)
// adjust program counter (called at end of each statement) // adjust program counter (called at end of each statement)
void vcpu_end_statement(void) void vcpu_end_statement(void)
{ {
CPU_state.pc.intval = (CPU_state.pc.intval + CPU_state.add_to_pc) & 0xffff; CPU_state.pc.val.intval = (CPU_state.pc.val.intval + CPU_state.add_to_pc) & 0xffff;
CPU_state.add_to_pc = 0; CPU_state.add_to_pc = 0;
} }

View File

@@ -19,7 +19,7 @@
// FIXME - move struct definition to .c file and change other .c files' accesses to fn calls // FIXME - move struct definition to .c file and change other .c files' accesses to fn calls
struct vcpu { struct vcpu {
const struct cpu_type *type; // current CPU type (default 6502) (FIXME - move out of struct again?) const struct cpu_type *type; // current CPU type (default 6502) (FIXME - move out of struct again?)
struct result_int_t pc; // current program counter (pseudo value) struct result_t pc; // current program counter (pseudo value)
int add_to_pc; // add to PC after statement int add_to_pc; // add to PC after statement
int a_is_long; int a_is_long;
int xy_are_long; int xy_are_long;
@@ -65,7 +65,7 @@ extern void Output_end_segment(void);
// set program counter to defined value (FIXME - allow undefined!) // set program counter to defined value (FIXME - allow undefined!)
extern void vcpu_set_pc(intval_t new_pc, int flags); extern void vcpu_set_pc(intval_t new_pc, int flags);
// get program counter // get program counter
extern void vcpu_read_pc(struct result_int_t *target); extern void vcpu_read_pc(struct result_t *target);
// get size of current statement (until now) - needed for "!bin" verbose output // get size of current statement (until now) - needed for "!bin" verbose output
extern int vcpu_get_statement_size(void); extern int vcpu_get_statement_size(void);
// adjust program counter (called at end of each statement) // adjust program counter (called at end of each statement)

53
src/typesystem.c Normal file
View File

@@ -0,0 +1,53 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// Type system stuff
#include "typesystem.h"
#include "config.h"
#include "alu.h"
#include "global.h"
static int in_address_block = FALSE;
static int in_address_statement = FALSE;
// Functions
int typesystem_says_address(void)
{
return in_address_block | in_address_statement;
}
void typesystem_force_address_block(void)
{
int buffer = in_address_block;
in_address_block = TRUE;
Parse_optional_block();
in_address_block = buffer;
}
void typesystem_force_address_statement(int value)
{
in_address_statement = value;
}
void typesystem_want_imm(struct result_t *result)
{
if (!warn_on_type_mismatch)
return;
if (!(result->flags & MVALUE_DEFINED))
return;
if (result->addr_refs != 0)
Throw_warning("Wrong type - expected integer.");
}
void typesystem_want_addr(struct result_t *result)
{
if (!warn_on_type_mismatch)
return;
if (!(result->flags & MVALUE_DEFINED))
return;
if (result->addr_refs != 1)
Throw_warning("Wrong type - expected address.");
}

25
src/typesystem.h Normal file
View File

@@ -0,0 +1,25 @@
// ACME - a crossassembler for producing 6502/65c02/65816 code.
// Copyright (C) 1998-2014 Marco Baye
// Have a look at "acme.c" for further info
//
// Type system stuff
#ifndef typesystem_H
#define typesystem_H
#include "config.h"
// return whether explicit label 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);
#endif