mirror of
https://github.com/uffejakobsen/acme.git
synced 2024-12-23 10:29:46 +00:00
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:
parent
c8ff626943
commit
d152f60acd
@ -1,13 +1,15 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_6502_std_a !eof
|
||||
lib_6502_std_a = 1
|
||||
|
||||
; labels and macros for plain 6502 processor
|
||||
|
||||
cpu_nmi = $fffa
|
||||
cpu_reset = $fffc
|
||||
cpu_irq = $fffe
|
||||
!address {
|
||||
cpu_nmi = $fffa
|
||||
cpu_reset = $fffc
|
||||
cpu_irq = $fffe
|
||||
}
|
||||
|
||||
; skip byte
|
||||
!macro bit8 {
|
||||
|
@ -1,21 +1,23 @@
|
||||
;ACME 0.07
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef Lib_65816_std_a !eof
|
||||
Lib_65816_std_a = 1
|
||||
!ifdef lib_65816_std_a !eof
|
||||
lib_65816_std_a = 1
|
||||
|
||||
; Labels and macros for Western Digital's 65c816 processor
|
||||
|
||||
cpu_e_cop = $fff4
|
||||
cpu_e_abort = $fff8
|
||||
cpu_e_nmi = $fffa
|
||||
cpu_e_reset = $fffc
|
||||
cpu_e_irq = $fffe
|
||||
!address {
|
||||
cpu_e_cop = $fff4
|
||||
cpu_e_abort = $fff8
|
||||
cpu_e_nmi = $fffa
|
||||
cpu_e_reset = $fffc
|
||||
cpu_e_irq = $fffe
|
||||
|
||||
cpu_n_cop = $fff4
|
||||
cpu_n_brk = $fff6
|
||||
cpu_n_abort = $fff8
|
||||
cpu_n_nmi = $fffa
|
||||
cpu_n_irq = $fffe
|
||||
cpu_n_cop = $fff4
|
||||
cpu_n_brk = $fff6
|
||||
cpu_n_abort = $fff8
|
||||
cpu_n_nmi = $fffa
|
||||
cpu_n_irq = $fffe
|
||||
}
|
||||
|
||||
!macro cpu_emu {; switch to emulation mode
|
||||
sec
|
||||
@ -71,10 +73,9 @@ cpu_n_irq = $fffe
|
||||
|
||||
!macro inc24 .t {; increase 24-bit counter
|
||||
inc .t
|
||||
bne .j; "*" syntax not used here because size of ".t" is unknown
|
||||
bne +
|
||||
inc .t + 1
|
||||
bne .j
|
||||
bne +
|
||||
inc .t + 2
|
||||
.j
|
||||
+
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c128_kernel_a !eof
|
||||
lib_cbm_c128_kernel_a = 1
|
||||
@ -6,27 +6,31 @@ lib_cbm_c128_kernel_a = 1
|
||||
; Taken from the web.
|
||||
; Sorry, I can't give credit because I don't have the URL anymore.
|
||||
|
||||
k_spin_spout = $ff47
|
||||
k_close_all = $ff4a
|
||||
k_c64mode = $ff4d
|
||||
k_dma_call = $ff50
|
||||
k_boot_call = $ff53
|
||||
k_phoenix = $ff56
|
||||
k_lkupla = $ff59
|
||||
k_lkupsa = $ff5c
|
||||
k_swapper = $ff5f
|
||||
k_dlchr = $ff62
|
||||
k_pfkey = $ff65
|
||||
k_setbnk = $ff68
|
||||
k_getcfg = $ff6b
|
||||
k_jsrfar = $ff6e
|
||||
k_jmpfar = $ff71
|
||||
k_indfet = $ff74
|
||||
k_indsta = $ff77
|
||||
k_indcmp = $ff7a
|
||||
k_primm = $ff7d
|
||||
k_release_number = $ff80
|
||||
!address {
|
||||
k_spin_spout = $ff47
|
||||
k_close_all = $ff4a
|
||||
k_c64mode = $ff4d
|
||||
k_dma_call = $ff50
|
||||
k_boot_call = $ff53
|
||||
k_phoenix = $ff56
|
||||
k_lkupla = $ff59
|
||||
k_lkupsa = $ff5c
|
||||
k_swapper = $ff5f
|
||||
k_dlchr = $ff62
|
||||
k_pfkey = $ff65
|
||||
k_setbnk = $ff68
|
||||
k_getcfg = $ff6b
|
||||
k_jsrfar = $ff6e
|
||||
k_jmpfar = $ff71
|
||||
k_indfet = $ff74
|
||||
k_indsta = $ff77
|
||||
k_indcmp = $ff7a
|
||||
k_primm = $ff7d
|
||||
k_release_number = $ff80
|
||||
}
|
||||
!source <cbm/kernel.a> ; $ff81-$fff5 is backward compatible to older machines
|
||||
; $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>)
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c128_mmu_a !eof
|
||||
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):
|
||||
|
||||
; configuration register
|
||||
mmu_cr_d500 = $d500 ; same as "mmu_cr" at $ff00. Use "mmu_cr" instead, as that is *always* available.
|
||||
; preconfiguration registers (internal format just like mmu_cr)
|
||||
mmu_pcr_a = $d501 ; c128 kernel default is $3f (BANK 0)
|
||||
mmu_pcr_b = $d502 ; c128 kernel default is $7f (BANK 1)
|
||||
mmu_pcr_c = $d503 ; c128 kernel default is $01 (BANK 14)
|
||||
mmu_pcr_d = $d504 ; c128 kernel default is $41 (all system roms, with ram 1)
|
||||
; contents of cr and all four pcr:
|
||||
mmu_CR_RAMBANK_MASK = %##...... ; this controls which RAM bank is used in areas where RAM is enabled
|
||||
; mmu_CR_RAMBANK_0 = %........
|
||||
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)
|
||||
!address {
|
||||
; configuration register
|
||||
mmu_cr_d500 = $d500 ; same as "mmu_cr" at $ff00. Use "mmu_cr" instead, as that is *always* available.
|
||||
; preconfiguration registers (internal format just like mmu_cr)
|
||||
mmu_pcr_a = $d501 ; c128 kernel default is $3f (BANK 0)
|
||||
mmu_pcr_b = $d502 ; c128 kernel default is $7f (BANK 1)
|
||||
mmu_pcr_c = $d503 ; c128 kernel default is $01 (BANK 14)
|
||||
mmu_pcr_d = $d504 ; c128 kernel default is $41 (all system roms, with ram 1)
|
||||
}
|
||||
; contents of cr and all four pcr:
|
||||
mmu_CR_RAMBANK_MASK = %##...... ; this controls which RAM bank is used in areas where RAM is enabled
|
||||
;mmu_CR_RAMBANK_0 = %........
|
||||
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_SYSROM = %........ ; editor, charset (or i/o, see below), kernel
|
||||
mmu_CR_HIGH_INTFUNCROM = %...#....
|
||||
mmu_CR_HIGH_EXTFUNCROM = %..#.....
|
||||
mmu_CR_HIGH_RAM = %..##....
|
||||
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_INTFUNCROM = %...#....
|
||||
mmu_CR_HIGH_EXTFUNCROM = %..#.....
|
||||
mmu_CR_HIGH_RAM = %..##....
|
||||
|
||||
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_INTFUNCROM = %.....#..
|
||||
mmu_CR_MID_EXTFUNCROM = %....#...
|
||||
mmu_CR_MID_RAM = %....##..
|
||||
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_INTFUNCROM = %.....#..
|
||||
mmu_CR_MID_EXTFUNCROM = %....#...
|
||||
mmu_CR_MID_RAM = %....##..
|
||||
|
||||
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_RAM = %......#.
|
||||
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_RAM = %......#.
|
||||
|
||||
mmu_CR_IO_MASK = %.......# ; this controls i/o space (d000..dfff)
|
||||
; mmu_CR_IO_ON = %........
|
||||
mmu_CR_IO_OFF = %.......# ; if i/o is off, contents depend on "high area"
|
||||
mmu_CR_IO_MASK = %.......# ; this controls i/o space (d000..dfff)
|
||||
;mmu_CR_IO_ON = %........
|
||||
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):
|
||||
mmu_CR_BANK0 = $3f ; full 64 KiB ram bank 0
|
||||
mmu_CR_BANK1 = $7f ; full 64 KiB ram bank 1
|
||||
mmu_CR_BANK2 = $bf ; full 64 KiB ram bank 2
|
||||
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_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_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_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_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_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_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".
|
||||
; Whenever one of these is activated, ram banks 0 and 1 will be used instead.
|
||||
; IFROM means internal function ROM (socket U36)
|
||||
; EFROM means external function ROM (socket in a REU, for example)
|
||||
; 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_BANK1 = $7f ; full 64 KiB ram bank 1
|
||||
mmu_CR_BANK2 = $bf ; full 64 KiB ram bank 2
|
||||
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_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_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_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_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_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_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".
|
||||
; Whenever one of these is activated, ram banks 0 and 1 will be used instead.
|
||||
; IFROM means internal function ROM (socket U36)
|
||||
; EFROM means external function ROM (socket in a REU, for example)
|
||||
|
||||
; mode configuration register
|
||||
mmu_mcr = $d505
|
||||
; contents:
|
||||
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 :)
|
||||
mmu_MCR_EXROM = %..#..... ; if zero on boot, system will enter c64 mode (writable!)
|
||||
mmu_MCR_GAME = %...#.... ; if zero on boot, system will enter c64 mode (writable!)
|
||||
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
|
||||
!address {
|
||||
; mode configuration register
|
||||
mmu_mcr = $d505
|
||||
}
|
||||
; contents:
|
||||
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 :)
|
||||
mmu_MCR_EXROM = %..#..... ; if zero on boot, system will enter c64 mode (writable!)
|
||||
mmu_MCR_GAME = %...#.... ; if zero on boot, system will enter c64 mode (writable!)
|
||||
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
|
||||
mmu_rcr = $d506
|
||||
; contents:
|
||||
mmu_RCR_VICBANK_MASK = %##...... ; this controls which RAM bank is "seen" by VIC
|
||||
; mmu_RCR_VICBANK_0 = %........
|
||||
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)
|
||||
!address {
|
||||
; ram configuration register
|
||||
mmu_rcr = $d506
|
||||
}
|
||||
; contents:
|
||||
mmu_RCR_VICBANK_MASK = %##...... ; this controls which RAM bank is "seen" by VIC
|
||||
;mmu_RCR_VICBANK_0 = %........
|
||||
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_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_3 = %..##.... ; on an unmodified c128, there is only ram block 0
|
||||
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_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_3 = %..##.... ; on an unmodified c128, there is only ram block 0
|
||||
|
||||
mmu_RCR_SHARE_MASK = %....##..
|
||||
; mmu_RCR_SHARE_NONE = %........
|
||||
mmu_RCR_SHARE_BOTTOM = %.....#.. ; system default
|
||||
mmu_RCR_SHARE_TOP = %....#...
|
||||
mmu_RCR_SHARE_MASK = %....##..
|
||||
;mmu_RCR_SHARE_NONE = %........
|
||||
mmu_RCR_SHARE_BOTTOM = %.....#.. ; system default
|
||||
mmu_RCR_SHARE_TOP = %....#...
|
||||
|
||||
mmu_RCR_SHARESIZE_MASK = %......##
|
||||
; mmu_RCR_SHARESIZE_1K = %........ ; system default
|
||||
mmu_RCR_SHARESIZE_4K = %.......#
|
||||
mmu_RCR_SHARESIZE_8K = %......#.
|
||||
mmu_RCR_SHARESIZE_16K = %......##
|
||||
mmu_RCR_SHARESIZE_MASK = %......##
|
||||
;mmu_RCR_SHARESIZE_1K = %........ ; system default
|
||||
mmu_RCR_SHARESIZE_4K = %.......#
|
||||
mmu_RCR_SHARESIZE_8K = %......#.
|
||||
mmu_RCR_SHARESIZE_16K = %......##
|
||||
|
||||
; page pointers. writes to "high" register will be latched (reading gives old value) until "low" register is written to
|
||||
mmu_p0low = $d507 ; page 0 pointer low (a8..a15), default $00
|
||||
mmu_p0high = $d508 ; page 0 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_p1high = $d50a ; page 1 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful)
|
||||
mmu_PxH_UNUSED = %####.... ; always set
|
||||
!address {
|
||||
; page pointers. writes to "high" register will be latched (reading gives old value) until "low" register is written to
|
||||
mmu_p0low = $d507 ; page 0 pointer low (a8..a15), default $00
|
||||
mmu_p0high = $d508 ; page 0 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_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_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_3 = %....##.. ; on an unmodified c128, there is only ram block 0
|
||||
mmu_PxH_RAMBLOCK_MASK = %....##..
|
||||
;mmu_PxH_RAMBLOCK_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_3 = %....##.. ; on an unmodified c128, there is only ram block 0
|
||||
|
||||
mmu_PxH_RAMBANK_MASK = %......##
|
||||
; mmu_PxH_RAMBANK_0 = %........
|
||||
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_3 = %......## ; on an unmodified c128, there is no ram bank 3 (1 will be used instead)
|
||||
mmu_PxH_RAMBANK_MASK = %......##
|
||||
;mmu_PxH_RAMBANK_0 = %........
|
||||
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_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
|
||||
|
||||
|
||||
; these registers are always available (in *every* memory configuration) unless C64 mode is entered:
|
||||
|
||||
; configuration register
|
||||
mmu_cr = $ff00 ; always use this instead of $d500
|
||||
; load configuration registers:
|
||||
; a read access will return the value of the corresponding preconfiguration register
|
||||
; any write access will copy the value of the corresponding preconfiguration register to mmu_cr
|
||||
mmu_lcr_a = $ff01 ; c128 kernel default is $3f (BANK 0)
|
||||
mmu_lcr_b = $ff02 ; c128 kernel default is $7f (BANK 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)
|
||||
!address {
|
||||
; configuration register
|
||||
mmu_cr = $ff00 ; always use this instead of $d500
|
||||
; load configuration registers:
|
||||
; a read access will return the value of the corresponding preconfiguration register
|
||||
; any write access will copy the value of the corresponding preconfiguration register to mmu_cr
|
||||
mmu_lcr_a = $ff01 ; c128 kernel default is $3f (BANK 0)
|
||||
mmu_lcr_b = $ff02 ; c128 kernel default is $7f (BANK 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
|
||||
; corresponding configuration register values:
|
||||
; 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
|
||||
; the c128 ROMs contain a look-up table to convert bank numbers to their
|
||||
; corresponding configuration register values:
|
||||
; 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
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c128_vdc_a !eof
|
||||
lib_cbm_c128_vdc_a = 1
|
||||
@ -135,14 +135,17 @@ vdcattr_B = %......#. ; blue
|
||||
vdcattr_I = %.......# ; intensity
|
||||
|
||||
|
||||
; direct registers
|
||||
vdc_state = $d600 ; READING this location yields status flags:
|
||||
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)
|
||||
vdc_reg = $d600 ; WRITING this location selects an indirect register
|
||||
vdc_data = $d601 ; data of selected indirect register
|
||||
!address {
|
||||
; direct registers
|
||||
vdc_state = $d600 ; READING this location yields status flags, see below
|
||||
vdc_reg = $d600 ; WRITING this location selects an indirect register
|
||||
vdc_data = $d601 ; data of selected indirect register
|
||||
}
|
||||
; status flags in vdc_state:
|
||||
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)
|
||||
@ -219,11 +222,13 @@ vdcr_sync_polarity = $25 ; -- only in VDC 8568
|
||||
vdcr_HSYNC_POLARITY = %#.......
|
||||
vdcr_VSYNC_POLARITY = %.#......
|
||||
|
||||
; the c128 ROMs contain look-up tables to convert vic color values to vdc color
|
||||
; values and vice-versa:
|
||||
; rom4_* needs "low rom area" enabled ($4000..$7fff)
|
||||
; rom8_* needs "middle rom area" enabled ($8000..$bfff)
|
||||
; romc_* needs "high rom area" enabled ($c000..$ffff)
|
||||
rom4_vic_to_vdc_color_table = $6a4c ; 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
|
||||
!address {
|
||||
; the c128 ROMs contain look-up tables to convert vic color values to vdc color
|
||||
; values and vice-versa:
|
||||
; rom4_* needs "low rom area" enabled ($4000..$7fff)
|
||||
; rom8_* needs "middle rom area" enabled ($8000..$bfff)
|
||||
; romc_* needs "high rom area" enabled ($c000..$ffff)
|
||||
rom4_vic_to_vdc_color_table = $6a4c ; 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
|
||||
}
|
||||
|
@ -1,17 +1,19 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c128_vic_a !eof
|
||||
lib_cbm_c128_vic_a = 1
|
||||
|
||||
!source <cbm/c64/vic.a> ; registers 0..2e
|
||||
|
||||
; registers only present in the C128 variant of this chip:
|
||||
vic_keyboard = $d02f
|
||||
vic_clock = $d030
|
||||
!address {
|
||||
; registers only present in the C128 variant of this chip:
|
||||
vic_keyboard = $d02f
|
||||
vic_clock = $d030
|
||||
|
||||
; the c128 ROMs contain two copies of a look-up table to convert vic color
|
||||
; values to their corresponding petscii color codes:
|
||||
; rom4_* needs "low rom area" enabled ($4000..$7fff)
|
||||
; 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
|
||||
romc_vic_to_petscii_color_table = $ce4c ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b
|
||||
; the c128 ROMs contain two copies of a look-up table to convert vic color
|
||||
; values to their corresponding petscii color codes:
|
||||
; rom4_* needs "low rom area" enabled ($4000..$7fff)
|
||||
; 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
|
||||
romc_vic_to_petscii_color_table = $ce4c ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,23 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_cia1_a !eof
|
||||
lib_cbm_c64_cia1_a = 1
|
||||
|
||||
cia1_pra = $dc00
|
||||
cia1_prb = $dc01
|
||||
cia1_ddra = $dc02
|
||||
cia1_ddrb = $dc03
|
||||
cia1_ta_lo = $dc04
|
||||
cia1_ta_hi = $dc05
|
||||
cia1_tb_lo = $dc06
|
||||
cia1_tb_hi = $dc07
|
||||
cia1_tod10ths = $dc08
|
||||
cia1_todsec = $dc09
|
||||
cia1_todmin = $dc0a
|
||||
cia1_todhr = $dc0b
|
||||
cia1_sdr = $dc0c
|
||||
cia1_icr = $dc0d
|
||||
cia1_cra = $dc0e
|
||||
cia1_crb = $dc0f
|
||||
!address {
|
||||
cia1_pra = $dc00
|
||||
cia1_prb = $dc01
|
||||
cia1_ddra = $dc02
|
||||
cia1_ddrb = $dc03
|
||||
cia1_ta_lo = $dc04
|
||||
cia1_ta_hi = $dc05
|
||||
cia1_tb_lo = $dc06
|
||||
cia1_tb_hi = $dc07
|
||||
cia1_tod10ths = $dc08
|
||||
cia1_todsec = $dc09
|
||||
cia1_todmin = $dc0a
|
||||
cia1_todhr = $dc0b
|
||||
cia1_sdr = $dc0c
|
||||
cia1_icr = $dc0d
|
||||
cia1_cra = $dc0e
|
||||
cia1_crb = $dc0f
|
||||
}
|
||||
|
@ -1,21 +1,23 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_cia2_a !eof
|
||||
lib_cbm_c64_cia2_a = 1
|
||||
|
||||
cia2_pra = $dd00
|
||||
cia2_prb = $dd01
|
||||
cia2_ddra = $dd02
|
||||
cia2_ddrb = $dd03
|
||||
cia2_ta_lo = $dd04
|
||||
cia2_ta_hi = $dd05
|
||||
cia2_tb_lo = $dd06
|
||||
cia2_tb_hi = $dd07
|
||||
cia2_tod10ths = $dd08
|
||||
cia2_todsec = $dd09
|
||||
cia2_todmin = $dd0a
|
||||
cia2_todhr = $dd0b
|
||||
cia2_sdr = $dd0c
|
||||
cia2_icr = $dd0d
|
||||
cia2_cra = $dd0e
|
||||
cia2_crb = $dd0f
|
||||
!address {
|
||||
cia2_pra = $dd00
|
||||
cia2_prb = $dd01
|
||||
cia2_ddra = $dd02
|
||||
cia2_ddrb = $dd03
|
||||
cia2_ta_lo = $dd04
|
||||
cia2_ta_hi = $dd05
|
||||
cia2_tb_lo = $dd06
|
||||
cia2_tb_hi = $dd07
|
||||
cia2_tod10ths = $dd08
|
||||
cia2_todsec = $dd09
|
||||
cia2_todmin = $dd0a
|
||||
cia2_todhr = $dd0b
|
||||
cia2_sdr = $dd0c
|
||||
cia2_icr = $dd0d
|
||||
cia2_cra = $dd0e
|
||||
cia2_crb = $dd0f
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_float_a !eof
|
||||
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
|
||||
; C64's BASIC ROM. They work on "float registers", which are actually just
|
||||
; structures in zero page:
|
||||
fac1_base = $61 ; base address of floating-point accumulator 1
|
||||
fac2_base = $69 ; base address of floating-point accumulator 2
|
||||
!address {
|
||||
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
|
||||
; 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
|
||||
}
|
||||
|
||||
; constants in five-byte "mflpt" format
|
||||
mflpt_pi = $aea8 ; 3.1415926...
|
||||
mflpt_minus32768 = $b1a5 ; -32768
|
||||
mflpt_1 = $b9bc ; 1
|
||||
mflpt_half_sqr2 = $b9d6 ; SQR(2) / 2
|
||||
mflpt_sqr2 = $b9db ; SQR(2)
|
||||
mflpt_minus_point5 = $b9e0 ; -.5
|
||||
mflpt_log_2 = $b9e5 ; LOG(2)
|
||||
mflpt_10 = $baf9 ; 10
|
||||
mflpt_99999999 = $bdb3 ; 99 999 999
|
||||
mflpt_999999999 = $bdb8 ; 999 999 999
|
||||
mflpt_1000000000 = $bdbd ; 1 000 000 000
|
||||
mflpt_point5 = $bf11 ; .5, also known as 1 / 2
|
||||
mflpt_log_2_reciprocal = $bfbf ; 1 / LOG(2)
|
||||
mflpt_half_pi = $e2e0 ; PI / 2
|
||||
mflpt_double_pi = $e2e5 ; 2 * PI (also see $e309)
|
||||
mflpt_point25 = $e2ea ; .25, also known as 1 / 4
|
||||
mflpt_2_pi = $e309 ; 2 * PI (also see $e2e5)
|
||||
!address {
|
||||
; constants in five-byte "mflpt" format
|
||||
mflpt_pi = $aea8 ; 3.1415926...
|
||||
mflpt_minus32768 = $b1a5 ; -32768
|
||||
mflpt_1 = $b9bc ; 1
|
||||
mflpt_half_sqr2 = $b9d6 ; SQR(2) / 2
|
||||
mflpt_sqr2 = $b9db ; SQR(2)
|
||||
mflpt_minus_point5 = $b9e0 ; -.5
|
||||
mflpt_log_2 = $b9e5 ; LOG(2)
|
||||
mflpt_10 = $baf9 ; 10
|
||||
mflpt_99999999 = $bdb3 ; 99 999 999
|
||||
mflpt_999999999 = $bdb8 ; 999 999 999
|
||||
mflpt_1000000000 = $bdbd ; 1 000 000 000
|
||||
mflpt_point5 = $bf11 ; .5, also known as 1 / 2
|
||||
mflpt_log_2_reciprocal = $bfbf ; 1 / LOG(2)
|
||||
mflpt_half_pi = $e2e0 ; PI / 2
|
||||
mflpt_double_pi = $e2e5 ; 2 * PI (also see $e309)
|
||||
mflpt_point25 = $e2ea ; .25, also known as 1 / 4
|
||||
mflpt_2_pi = $e309 ; 2 * PI (also see $e2e5)
|
||||
|
||||
; functions - a few points to note:
|
||||
; fac1/2 might get clobbered even if not mentioned in the function's name,
|
||||
; because stuff like fac1_times_memAY will load the value from memory
|
||||
; into fac2 first.
|
||||
; for subtraction and division, the left operand is in fac2, the right operand in fac1.
|
||||
fac1_print = $aabc ; print string representation of contents of fac1
|
||||
fac1_to_signedYA = $b1aa ; might throw ILLEGAL QUANTITY
|
||||
fac1_to_signed16 = $b1bf ; might throw ILLEGAL QUANTITY
|
||||
fac1_read_signedYA = $b391 ; convert 16 bit signed int to float
|
||||
fac1_read_unsignedY = $b3a2 ; convert 8 bit unsigned int to float
|
||||
fac1_read_string = $b7b5 ; $22/23 must point to string, A must be string length
|
||||
fac1_to_unsignedYA = $b7f7 ; might throw ILLEGAL QUANTITY (result is also in $14/15)
|
||||
fac1_add_point5 = $b849 ; for rounding, call this before fac1_int
|
||||
fac1_memAY_minus_fac1 = $b850 ; subtract fac1 from mflpt value
|
||||
fac1_fac2_minus_fac1 = $b853
|
||||
fac1_add_memAY = $b867 ; add mflpt value
|
||||
fac1_add_fac2 = $b86a
|
||||
fac1_log = $b9ea ; LOG()
|
||||
fac1_times_memAY = $ba28 ; multiply by mflpt value
|
||||
fac2_read_memAY = $ba8c ; load mflpt value from memory into fac2
|
||||
fac2_read_mem_via0x22ptr = $ba90 ; load mflpt value from memory into fac2
|
||||
fac1_times_10 = $bae2
|
||||
fac1_divide_by_10 = $bafe
|
||||
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_mem_via0x22ptr = $bba6 ; load mflpt value from memory into fac1
|
||||
fac1_to_memXY = $bbd4 ; store fac1 to memory as mflpt
|
||||
fac1_read_fac2 = $bbfc ; copy fac2 to fac1
|
||||
fac2_read_fac1 = $bc0c ; copy fac1 to fac2
|
||||
fac1_sign_to_A = $bc2b ; $ff, $0, $1 for negative, zero, positive
|
||||
fac1_sgn = $bc39 ; SGN()
|
||||
fac1_abs = $bc58 ; ABS()
|
||||
fac1_compare_to_memAY = $bc5b ; compare to mflpt value in memory
|
||||
fac1_to_signed32 = $bc9b
|
||||
fac1_int = $bccc ; INT()
|
||||
fac1_print_unsignedXA = $bdcd
|
||||
fac1_to_string = $bddd ; string is stored at $0100 (address returned in AY)
|
||||
fac1_sqr = $bf71 ; SQR()
|
||||
fac1_fac2_to_the_power_of_memAY = $bf78
|
||||
fac1_negate = $bfb4
|
||||
fac1_exp = $bfed ; EXP()
|
||||
; end of basic rom jumps to start of kernel rom!
|
||||
fac1_rnd = $e097 ; RND()
|
||||
fac1_cos = $e264 ; COS()
|
||||
fac1_sin = $e26b ; SIN()
|
||||
fac1_tan = $e2b4 ; TAN()
|
||||
fac1_atn = $e30e ; ATN()
|
||||
; functions - a few points to note:
|
||||
; fac1/2 might get clobbered even if not mentioned in the function's name,
|
||||
; because stuff like fac1_times_memAY will load the value from memory
|
||||
; into fac2 first.
|
||||
; for subtraction and division, the left operand is in fac2, the right operand in fac1.
|
||||
fac1_print = $aabc ; print string representation of contents of fac1
|
||||
fac1_to_signedYA = $b1aa ; might throw ILLEGAL QUANTITY
|
||||
fac1_to_signed16 = $b1bf ; might throw ILLEGAL QUANTITY
|
||||
fac1_read_signedYA = $b391 ; convert 16 bit signed int to float
|
||||
fac1_read_unsignedY = $b3a2 ; convert 8 bit unsigned int to float
|
||||
fac1_read_string = $b7b5 ; $22/23 must point to string, A must be string length
|
||||
fac1_to_unsignedYA = $b7f7 ; might throw ILLEGAL QUANTITY (result is also in $14/15)
|
||||
fac1_add_point5 = $b849 ; for rounding, call this before fac1_int
|
||||
fac1_memAY_minus_fac1 = $b850 ; subtract fac1 from mflpt value
|
||||
fac1_fac2_minus_fac1 = $b853
|
||||
fac1_add_memAY = $b867 ; add mflpt value
|
||||
fac1_add_fac2 = $b86a
|
||||
fac1_log = $b9ea ; LOG()
|
||||
fac1_times_memAY = $ba28 ; multiply by mflpt value
|
||||
fac2_read_memAY = $ba8c ; load mflpt value from memory into fac2
|
||||
fac2_read_mem_via0x22ptr = $ba90 ; load mflpt value from memory into fac2
|
||||
fac1_times_10 = $bae2
|
||||
fac1_divide_by_10 = $bafe
|
||||
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_mem_via0x22ptr = $bba6 ; load mflpt value from memory into fac1
|
||||
fac1_to_memXY = $bbd4 ; store fac1 to memory as mflpt
|
||||
fac1_read_fac2 = $bbfc ; copy fac2 to fac1
|
||||
fac2_read_fac1 = $bc0c ; copy fac1 to fac2
|
||||
fac1_sign_to_A = $bc2b ; $ff, $0, $1 for negative, zero, positive
|
||||
fac1_sgn = $bc39 ; SGN()
|
||||
fac1_abs = $bc58 ; ABS()
|
||||
fac1_compare_to_memAY = $bc5b ; compare to mflpt value in memory
|
||||
fac1_to_signed32 = $bc9b
|
||||
fac1_int = $bccc ; INT()
|
||||
fac1_print_unsignedXA = $bdcd
|
||||
fac1_to_string = $bddd ; string is stored at $0100 (address returned in AY)
|
||||
fac1_sqr = $bf71 ; SQR()
|
||||
fac1_fac2_to_the_power_of_memAY = $bf78
|
||||
fac1_negate = $bfb4
|
||||
fac1_exp = $bfed ; EXP()
|
||||
; end of basic rom jumps to start of kernel rom!
|
||||
fac1_rnd = $e097 ; RND()
|
||||
fac1_cos = $e264 ; COS()
|
||||
fac1_sin = $e26b ; SIN()
|
||||
fac1_tan = $e2b4 ; TAN()
|
||||
fac1_atn = $e30e ; ATN()
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_georam_a !eof
|
||||
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
|
||||
; memory page is visible at that location.
|
||||
|
||||
; memory page
|
||||
georam_page = $de00
|
||||
|
||||
; control registers (write-only, these registers can not be read)
|
||||
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
|
||||
!address {
|
||||
; memory page
|
||||
georam_page = $de00
|
||||
; control registers (write-only, these registers can not be read)
|
||||
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
|
||||
}
|
||||
; these are the official addresses - actually the registers are accessible
|
||||
; *everywhere* at $dfxx, but using these locations does not clash with the
|
||||
; registers of a Commodore REU.
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_reu_a !eof
|
||||
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).
|
||||
; Standard base address of control registers is $df00 in i/o space.
|
||||
|
||||
; status register
|
||||
rec_status = $df00 ; reading will clear IRQ, END and ERROR bits
|
||||
rec_STATUS_IRQ = %#.......
|
||||
rec_STATUS_END = %.#......
|
||||
rec_STATUS_ERROR = %..#..... ; for verify command
|
||||
rec_STATUS_TYPE = %...#.... ; chip type (do not use to determine unit size!)
|
||||
rec_STATUS_VERSION = %....####
|
||||
; command register
|
||||
rec_command = $df01
|
||||
rec_COMMAND_EXECUTE = %#.......
|
||||
;reserved = %.#......
|
||||
rec_COMMAND_RELOAD = %..#.....
|
||||
rec_COMMAND_IMMEDIATELY = %...#.... ; do not wait for $ff00 write
|
||||
;reserved = %....##..
|
||||
rec_COMMAND_MODE_MASK = %......## ; bit mask for the four modes
|
||||
rec_COMMAND_MODE_STASH = %........ ; computer-to-REU
|
||||
rec_COMMAND_MODE_FETCH = %.......# ; REU-to-computer
|
||||
rec_COMMAND_MODE_SWAP = %......#. ; exchange
|
||||
rec_COMMAND_MODE_VERIFY = %......## ; compare
|
||||
rec_COMMAND_STASH = %#.#..... ; these wait for $ff00 before
|
||||
rec_COMMAND_FETCH = %#.#....# ; starting and then reload values.
|
||||
; internal address (computer RAM)
|
||||
rec_int_low = $df02
|
||||
rec_int_high = $df03
|
||||
; external address (expansion RAM)
|
||||
rec_ext_low = $df04
|
||||
rec_ext_high = $df05
|
||||
rec_ext_bank = $df06
|
||||
!address {
|
||||
; status register
|
||||
rec_status = $df00 ; reading will clear IRQ, END and ERROR bits
|
||||
}
|
||||
rec_STATUS_IRQ = %#.......
|
||||
rec_STATUS_END = %.#......
|
||||
rec_STATUS_ERROR = %..#..... ; for verify command
|
||||
rec_STATUS_TYPE = %...#.... ; chip type (do not use to determine unit size!)
|
||||
rec_STATUS_VERSION = %....####
|
||||
!address {
|
||||
; command register
|
||||
rec_command = $df01
|
||||
}
|
||||
rec_COMMAND_EXECUTE = %#.......
|
||||
;reserved = %.#......
|
||||
rec_COMMAND_RELOAD = %..#.....
|
||||
rec_COMMAND_IMMEDIATELY = %...#.... ; do not wait for $ff00 write
|
||||
;reserved = %....##..
|
||||
rec_COMMAND_MODE_MASK = %......## ; bit mask for the four modes
|
||||
rec_COMMAND_MODE_STASH = %........ ; computer-to-REU
|
||||
rec_COMMAND_MODE_FETCH = %.......# ; REU-to-computer
|
||||
rec_COMMAND_MODE_SWAP = %......#. ; exchange
|
||||
rec_COMMAND_MODE_VERIFY = %......## ; compare
|
||||
rec_COMMAND_STASH = %#.#..... ; these wait for $ff00 before
|
||||
rec_COMMAND_FETCH = %#.#....# ; starting and then reload values.
|
||||
!address {
|
||||
; internal address (computer RAM)
|
||||
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 1764 unit has four banks (256 KiB).
|
||||
; A stock 1750 unit has eight banks (512 KiB).
|
||||
; Upgraded units and clones may have more, but the REC chip will always
|
||||
; "wrap around" after eight banks if crossing bank borders!
|
||||
; amount of bytes to process
|
||||
rec_amount_low = $df07
|
||||
rec_amount_high = $df08
|
||||
; when to request interrupts
|
||||
rec_irqctrl = $df09
|
||||
rec_IRQCTRL_ENABLE = %#.......
|
||||
rec_IRQCTRL_ON_END = %.#......
|
||||
rec_IRQCTRL_ON_ERROR = %..#..... ; for verify errors
|
||||
; address control (set to zero for normal operation)
|
||||
rec_addrctrl = $df0a
|
||||
rec_ADDRCTRL_FIX_INT = %#.......
|
||||
rec_ADDRCTRL_FIX_EXT = %.#......
|
||||
; amount of bytes to process
|
||||
rec_amount_low = $df07
|
||||
rec_amount_high = $df08
|
||||
; when to request interrupts
|
||||
rec_irqctrl = $df09
|
||||
}
|
||||
rec_IRQCTRL_ENABLE = %#.......
|
||||
rec_IRQCTRL_ON_END = %.#......
|
||||
rec_IRQCTRL_ON_ERROR = %..#..... ; for verify errors
|
||||
!address {
|
||||
; address control (set to zero for normal operation)
|
||||
rec_addrctrl = $df0a
|
||||
}
|
||||
rec_ADDRCTRL_FIX_INT = %#.......
|
||||
rec_ADDRCTRL_FIX_EXT = %.#......
|
||||
|
@ -1,52 +1,55 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_sid_a !eof
|
||||
lib_cbm_c64_sid_a = 1
|
||||
|
||||
; write-only registers:
|
||||
; voice 1:
|
||||
sid_v1_freq_lo = $d400
|
||||
sid_v1_freq_hi = $d401
|
||||
sid_v1_width_lo = $d402
|
||||
sid_v1_width_hi = $d403
|
||||
sid_v1_control = $d404 ; see below for bits
|
||||
sid_v1_attack_decay = $d405 ; hi-nibble: attack length, low-nibble: decay length
|
||||
sid_v1_sustain_release = $d406 ; hi-nibble: sustain volumne, low-nibble: release length
|
||||
; voice 2:
|
||||
sid_v2_freq_lo = $d407
|
||||
sid_v2_freq_hi = $d408
|
||||
sid_v2_width_lo = $d409
|
||||
sid_v2_width_hi = $d40a
|
||||
sid_v2_control = $d40b ; see below for bits
|
||||
sid_v2_attack_decay = $d40c ; hi-nibble: attack length, low-nibble: decay length
|
||||
sid_v2_sustain_release = $d40d ; hi-nibble: sustain volumne, low-nibble: release length
|
||||
; voice 3:
|
||||
sid_v3_freq_lo = $d40e
|
||||
sid_v3_freq_hi = $d40f
|
||||
sid_v3_width_lo = $d410
|
||||
sid_v3_width_hi = $d411
|
||||
sid_v3_control = $d412 ; see below for bits
|
||||
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
|
||||
!address {
|
||||
; write-only registers:
|
||||
; voice 1:
|
||||
sid_v1_freq_lo = $d400
|
||||
sid_v1_freq_hi = $d401
|
||||
sid_v1_width_lo = $d402
|
||||
sid_v1_width_hi = $d403
|
||||
sid_v1_control = $d404 ; see below for bits
|
||||
sid_v1_attack_decay = $d405 ; hi-nibble: attack length, low-nibble: decay length
|
||||
sid_v1_sustain_release = $d406 ; hi-nibble: sustain volumne, low-nibble: release length
|
||||
; voice 2:
|
||||
sid_v2_freq_lo = $d407
|
||||
sid_v2_freq_hi = $d408
|
||||
sid_v2_width_lo = $d409
|
||||
sid_v2_width_hi = $d40a
|
||||
sid_v2_control = $d40b ; see below for bits
|
||||
sid_v2_attack_decay = $d40c ; hi-nibble: attack length, low-nibble: decay length
|
||||
sid_v2_sustain_release = $d40d ; hi-nibble: sustain volumne, low-nibble: release length
|
||||
; voice 3:
|
||||
sid_v3_freq_lo = $d40e
|
||||
sid_v3_freq_hi = $d40f
|
||||
sid_v3_width_lo = $d410
|
||||
sid_v3_width_hi = $d411
|
||||
sid_v3_control = $d412 ; see below for bits
|
||||
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:
|
||||
sid_VOICECONTROL_NOISE = %#.......
|
||||
sid_VOICECONTROL_RECTANGLE = %.#......
|
||||
sid_VOICECONTROL_SAWTOOTH = %..#.....
|
||||
sid_VOICECONTROL_TRIANGLE = %...#....
|
||||
sid_VOICECONTROL_DISABLE_RESET = %....#... ; 1 = disable voice, reset noise generator
|
||||
sid_VOICECONTROL_RINGMODULATION = %.....#..
|
||||
sid_VOICECONTROL_SYNC = %......#.
|
||||
sid_VOICECONTROL_ON = %.......# ; 0 = release, 1 = attack/sustain/decay
|
||||
; registers shared by all voices:
|
||||
sid_filter_cutoff_lo = $d415 ; only bits 0/1/2!
|
||||
sid_filter_cutoff_hi = $d416
|
||||
sid_filter_control = $d417 ; hi-nibble: resonance, lo-nibble: filter ext/v3/v2/v1
|
||||
sid_filter_volume = $d418 ; hi-nibble: filter mode (disable v3, high, band, low), lo-nibble: volume
|
||||
; read-only registers:
|
||||
sid_potx = $d419
|
||||
sid_poty = $d41a
|
||||
sid_v3_waveform_output = $d41b
|
||||
sid_v3_adsr_output = $d41c
|
||||
|
||||
; Do not use the shadow copies of these registers at $d500, $d600 or $d700,
|
||||
sid_VOICECONTROL_NOISE = %#.......
|
||||
sid_VOICECONTROL_RECTANGLE = %.#......
|
||||
sid_VOICECONTROL_SAWTOOTH = %..#.....
|
||||
sid_VOICECONTROL_TRIANGLE = %...#....
|
||||
sid_VOICECONTROL_DISABLE_RESET = %....#... ; 1 = disable voice, reset noise generator
|
||||
sid_VOICECONTROL_RINGMODULATION = %.....#..
|
||||
sid_VOICECONTROL_SYNC = %......#.
|
||||
sid_VOICECONTROL_ON = %.......# ; 0 = release, 1 = attack/sustain/decay
|
||||
!address {
|
||||
; registers shared by all voices:
|
||||
sid_filter_cutoff_lo = $d415 ; only bits 0/1/2!
|
||||
sid_filter_cutoff_hi = $d416
|
||||
sid_filter_control = $d417 ; hi-nibble: resonance, lo-nibble: filter ext/v3/v2/v1
|
||||
sid_filter_volume = $d418 ; hi-nibble: filter mode (disable v3, high, band, low), lo-nibble: volume
|
||||
; read-only registers:
|
||||
sid_potx = $d419
|
||||
sid_poty = $d41a
|
||||
sid_v3_waveform_output = $d41b
|
||||
sid_v3_adsr_output = $d41c
|
||||
}
|
||||
; Do not use the shadow copies of these registers at $d5xx, $d6xx or $d7xx:
|
||||
; on a C128 they do not exist!
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_vic_a !eof
|
||||
lib_cbm_c64_vic_a = 1
|
||||
@ -21,58 +21,58 @@ viccolor_LGREEN = $d
|
||||
viccolor_LBLUE = $e
|
||||
viccolor_GRAY3 = $f
|
||||
|
||||
; register addresses
|
||||
vic_xs0 = $d000
|
||||
vic_ys0 = $d001
|
||||
vic_xs1 = $d002
|
||||
vic_ys1 = $d003
|
||||
vic_xs2 = $d004
|
||||
vic_ys2 = $d005
|
||||
vic_xs3 = $d006
|
||||
vic_ys3 = $d007
|
||||
vic_xs4 = $d008
|
||||
vic_ys4 = $d009
|
||||
vic_xs5 = $d00a
|
||||
vic_ys5 = $d00b
|
||||
vic_xs6 = $d00c
|
||||
vic_ys6 = $d00d
|
||||
vic_xs7 = $d00e
|
||||
vic_ys7 = $d00f
|
||||
vic_msb_xs = $d010
|
||||
vic_controlv = $d011 ; vertical control (and much other stuff)
|
||||
vic_line = $d012 ; raster line
|
||||
vic_xlp = $d013 ; light pen coordinates
|
||||
vic_ylp = $d014
|
||||
vic_sactive = $d015 ; sprites: active
|
||||
vic_controlh = $d016 ; horizontal control (and much other stuff)
|
||||
vic_sdy = $d017 ; sprites: double height
|
||||
vic_ram = $d018 ; RAM pointer
|
||||
vic_irq = $d019
|
||||
vic_irqmask = $d01a
|
||||
vic_sback = $d01b ; sprites: background mode
|
||||
vic_smc = $d01c ; sprites: multi color mode
|
||||
vic_sdx = $d01d ; sprites: double width
|
||||
vic_ss_collided = $d01e ; sprite-sprite collision detect
|
||||
vic_sd_collided = $d01f ; sprite-data collision detect
|
||||
|
||||
; color registers
|
||||
vic_cborder = $d020 ; border color
|
||||
vic_cbg = $d021 ; general background color
|
||||
vic_cbg0 = $d021
|
||||
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_cbg3 = $d024 ; background color 3 (for EBC mode)
|
||||
vic_sc01 = $d025 ; sprite color for MC-bitpattern %01
|
||||
vic_sc11 = $d026 ; sprite color for MC-bitpattern %11
|
||||
vic_cs0 = $d027 ; sprite colors
|
||||
vic_cs1 = $d028
|
||||
vic_cs2 = $d029
|
||||
vic_cs3 = $d02a
|
||||
vic_cs4 = $d02b
|
||||
vic_cs5 = $d02c
|
||||
vic_cs6 = $d02d
|
||||
vic_cs7 = $d02e
|
||||
|
||||
!address {
|
||||
; register addresses
|
||||
vic_xs0 = $d000
|
||||
vic_ys0 = $d001
|
||||
vic_xs1 = $d002
|
||||
vic_ys1 = $d003
|
||||
vic_xs2 = $d004
|
||||
vic_ys2 = $d005
|
||||
vic_xs3 = $d006
|
||||
vic_ys3 = $d007
|
||||
vic_xs4 = $d008
|
||||
vic_ys4 = $d009
|
||||
vic_xs5 = $d00a
|
||||
vic_ys5 = $d00b
|
||||
vic_xs6 = $d00c
|
||||
vic_ys6 = $d00d
|
||||
vic_xs7 = $d00e
|
||||
vic_ys7 = $d00f
|
||||
vic_msb_xs = $d010
|
||||
vic_controlv = $d011 ; vertical control (and much other stuff)
|
||||
vic_line = $d012 ; raster line
|
||||
vic_xlp = $d013 ; light pen coordinates
|
||||
vic_ylp = $d014
|
||||
vic_sactive = $d015 ; sprites: active
|
||||
vic_controlh = $d016 ; horizontal control (and much other stuff)
|
||||
vic_sdy = $d017 ; sprites: double height
|
||||
vic_ram = $d018 ; RAM pointer
|
||||
vic_irq = $d019
|
||||
vic_irqmask = $d01a
|
||||
vic_sback = $d01b ; sprites: background mode
|
||||
vic_smc = $d01c ; sprites: multi color mode
|
||||
vic_sdx = $d01d ; sprites: double width
|
||||
vic_ss_collided = $d01e ; sprite-sprite collision detect
|
||||
vic_sd_collided = $d01f ; sprite-data collision detect
|
||||
; color registers
|
||||
vic_cborder = $d020 ; border color
|
||||
vic_cbg = $d021 ; general background color
|
||||
vic_cbg0 = $d021
|
||||
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_cbg3 = $d024 ; background color 3 (for EBC mode)
|
||||
vic_sc01 = $d025 ; sprite color for MC-bitpattern %01
|
||||
vic_sc11 = $d026 ; sprite color for MC-bitpattern %11
|
||||
vic_cs0 = $d027 ; sprite colors
|
||||
vic_cs1 = $d028
|
||||
vic_cs2 = $d029
|
||||
vic_cs3 = $d02a
|
||||
vic_cs4 = $d02b
|
||||
vic_cs5 = $d02c
|
||||
vic_cs6 = $d02d
|
||||
vic_cs7 = $d02e
|
||||
}
|
||||
; 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,
|
||||
; so be careful not to write to it accidentally in a C64 program!
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_kernel_a !eof
|
||||
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.
|
||||
; There are alternative names for some calls.
|
||||
|
||||
k_cint = $ff81
|
||||
k_ioinit = $ff84
|
||||
k_ramtas = $ff87
|
||||
k_restor = $ff8a
|
||||
k_vector = $ff8d
|
||||
k_setmsg = $ff90
|
||||
k_secnd = $ff93
|
||||
k_tksa = $ff96
|
||||
k_memtop = $ff99
|
||||
k_membot = $ff9c
|
||||
k_key = $ff9f
|
||||
k_settmo = $ffa2
|
||||
k_iecin = $ffa5:k_acptr = $ffa5
|
||||
k_iecout = $ffa8:k_ciout = $ffa8
|
||||
k_untalk = $ffab:k_untlk = $ffab
|
||||
k_unlisten = $ffae:k_unlsn = $ffae
|
||||
k_listen = $ffb1:k_listn = $ffb1
|
||||
k_talk = $ffb4
|
||||
k_readss = $ffb7
|
||||
k_setlfs = $ffba
|
||||
k_setnam = $ffbd ; A is length, X is ptr-low, Y is ptr-high
|
||||
k_open = $ffc0
|
||||
k_close = $ffc3:k_close_A = $ffc3
|
||||
k_chkin = $ffc6:k_chkin_X = $ffc6
|
||||
k_chkout = $ffc9:k_chkout_X = $ffc9:k_ckout = $ffc9
|
||||
k_clrchn = $ffcc:k_clrch = $ffcc
|
||||
k_chrin = $ffcf:k_basin = $ffcf
|
||||
k_chrout = $ffd2:k_basout = $ffd2:k_bsout = $ffd2
|
||||
k_load = $ffd5:k_load_AXY = $ffd5 ; A means verify, YYXX is desired load address (if channel == 0), returns end+1 in YYXX
|
||||
k_save = $ffd8:k_save_AXY = $ffd8 ; A is zp address of start ptr(!), YYXX is end address (+1)
|
||||
k_settim = $ffdb
|
||||
k_rdtim = $ffde
|
||||
k_stop = $ffe1
|
||||
k_getin = $ffe4:k_get = $ffe4
|
||||
k_clall = $ffe7
|
||||
k_udtim = $ffea
|
||||
k_scrorg = $ffed
|
||||
k_plot = $fff0 ; get/set cursor (to set, clear carry)
|
||||
k_iobase = $fff3
|
||||
!address {
|
||||
k_cint = $ff81
|
||||
k_ioinit = $ff84
|
||||
k_ramtas = $ff87
|
||||
k_restor = $ff8a
|
||||
k_vector = $ff8d
|
||||
k_setmsg = $ff90
|
||||
k_secnd = $ff93
|
||||
k_tksa = $ff96
|
||||
k_memtop = $ff99
|
||||
k_membot = $ff9c
|
||||
k_key = $ff9f
|
||||
k_settmo = $ffa2
|
||||
k_iecin = $ffa5:k_acptr = $ffa5
|
||||
k_iecout = $ffa8:k_ciout = $ffa8
|
||||
k_untalk = $ffab:k_untlk = $ffab
|
||||
k_unlisten = $ffae:k_unlsn = $ffae
|
||||
k_listen = $ffb1:k_listn = $ffb1
|
||||
k_talk = $ffb4
|
||||
k_readss = $ffb7
|
||||
k_setlfs = $ffba
|
||||
k_setnam = $ffbd ; A is length, X is ptr-low, Y is ptr-high
|
||||
k_open = $ffc0
|
||||
k_close = $ffc3:k_close_A = $ffc3
|
||||
k_chkin = $ffc6:k_chkin_X = $ffc6
|
||||
k_chkout = $ffc9:k_chkout_X = $ffc9:k_ckout = $ffc9
|
||||
k_clrchn = $ffcc:k_clrch = $ffcc
|
||||
k_chrin = $ffcf:k_basin = $ffcf
|
||||
k_chrout = $ffd2:k_basout = $ffd2:k_bsout = $ffd2
|
||||
k_load = $ffd5:k_load_AXY = $ffd5 ; A means verify, YYXX is desired load address (if channel == 0), returns end+1 in YYXX
|
||||
k_save = $ffd8:k_save_AXY = $ffd8 ; A is zp address of start ptr(!), YYXX is end address (+1)
|
||||
k_settim = $ffdb
|
||||
k_rdtim = $ffde
|
||||
k_stop = $ffe1
|
||||
k_getin = $ffe4:k_get = $ffe4
|
||||
k_clall = $ffe7
|
||||
k_udtim = $ffea
|
||||
k_scrorg = $ffed
|
||||
k_plot = $fff0 ; get/set cursor (to set, clear carry)
|
||||
k_iobase = $fff3
|
||||
}
|
||||
|
@ -412,9 +412,12 @@ Examples:
|
||||
Miscellaneous: The old syntax ("!for LABEL, END { BLOCK }" where
|
||||
START was always implied to be 1) is still fully
|
||||
supported, but gives a warning to get people to change
|
||||
to the new syntax. 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.
|
||||
to the new syntax. You can disable this warning using
|
||||
the "-Wno-old-for" switch, but then you will get
|
||||
warnings for using the *new* syntax.
|
||||
When migrating your sources, bear in mind that it is
|
||||
no longer possible to skip the block completely by
|
||||
specifying a loop count of zero.
|
||||
Also note that with the new algorithm, LABEL has a
|
||||
different value after the block than during the last
|
||||
loop cycle, while the old algorithm kept that last
|
||||
@ -811,6 +814,37 @@ Purpose: Assume short (8 bits) index registers. Only needed
|
||||
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)
|
||||
----------------------------------------------------------------------
|
||||
|
@ -12,6 +12,19 @@ platform used. There should be another help file in this archive
|
||||
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
|
||||
----------------------------------------------------------------------
|
||||
|
@ -55,9 +55,14 @@ Bug in ACME, code follows
|
||||
C-style "==" comparison detected.
|
||||
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
|
||||
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.
|
||||
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).
|
||||
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
|
||||
|
@ -105,6 +105,8 @@ ACME exists on several platforms, meaning you can easily exchange your
|
||||
sources with other people (preferring other OSes).
|
||||
ACME can convert its strings to PetSCII and screen code (Okay, this is
|
||||
C64-specific).
|
||||
ACME has a rudimentary type checking system to catch errors like
|
||||
missing '#' characters.
|
||||
Did I mention that it is fast?
|
||||
|
||||
|
||||
|
@ -21,7 +21,9 @@ Section: Example of what an ACME source code file looks like
|
||||
!to "tiny.o", cbm ; set output file and format
|
||||
* = $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:
|
||||
ldx #0
|
||||
beq + ; enter loop
|
||||
@ -46,8 +48,19 @@ Here's the same fragment again, now with some additional info:
|
||||
; respectively.
|
||||
* = $c000 ; set program counter
|
||||
; 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:
|
||||
ldx #0
|
||||
beq + ; enter loop
|
||||
@ -157,6 +170,9 @@ found in the file "AllPOs.txt". Here's just a short overview:
|
||||
!warn !error !serious
|
||||
...for generating warnings, errors and serious errors.
|
||||
|
||||
!addr
|
||||
...to mark labels as addresses, for the optional type check system.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Section: Command line arguments
|
||||
@ -180,13 +196,13 @@ Available options are:
|
||||
-l, --labeldump FILE select label dump file
|
||||
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
|
||||
This can be changed in the source code using the "!cpu" pseudo
|
||||
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
|
||||
This can also be given using the "!initmem" pseudo opcode.
|
||||
Defaults to zero.
|
||||
@ -200,22 +216,18 @@ Available options are:
|
||||
-vDIGIT set verbosity level
|
||||
Sets how much additional informational output is generated.
|
||||
Higher values mean more output:
|
||||
|
||||
acme -v0 source.a
|
||||
acme -v0 source.a
|
||||
This is the default: No additional output is generated,
|
||||
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
|
||||
file are displayed, along with its size (a CBM-style
|
||||
"load address" is *not* counted).
|
||||
|
||||
acme -v2 source.a
|
||||
acme -v2 source.a
|
||||
In addition to the "-v1" output, ACME will announce each
|
||||
pass, will show amount and offset of "!binary" loads, and
|
||||
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
|
||||
each source file.
|
||||
|
||||
@ -226,9 +238,14 @@ Available options are:
|
||||
(using conditional assembly in your source code file).
|
||||
|
||||
-W fine-tune amount and type of warnings
|
||||
Currently only sub-option is supported: "-Wno-label-indent"
|
||||
will switch off warnings about implicit label definitions not
|
||||
being in the leftmost column.
|
||||
-Wno-label-indent
|
||||
Disables warnings about implicit label definitions not
|
||||
being in the leftmost column.
|
||||
-Wno-old-for
|
||||
Disables warnings about the old "!for" syntax and at the
|
||||
same time enables warnings about the _new_ "!for" syntax.
|
||||
-Wtype-mismatch
|
||||
Enables type checking system (warns about wrong types).
|
||||
|
||||
--use-stdout fix for 'Relaunch64' IDE
|
||||
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 arccos(v) Inverse of cos()
|
||||
14 arctan(v) Inverse of tan()
|
||||
14 addr(v) Mark as address
|
||||
14 int(v) Convert to integer
|
||||
14 float(v) Convert to float
|
||||
13 ! v Complement of NOT
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94
|
||||
;ACME 0.95
|
||||
;!sl "ddrv.l"
|
||||
; Name DuoDriver
|
||||
; Purpose Input driver for mouse and joystick
|
||||
@ -26,6 +26,7 @@
|
||||
; 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.
|
||||
; 7 Apr 2013 Slightly reformatted.
|
||||
; 1 Jun 2014 Adjusted to experimental type system of ACME 0.95
|
||||
|
||||
; This source code file uses conditional assembly
|
||||
; to decide which version to produce (C64 or C128).
|
||||
@ -47,12 +48,12 @@
|
||||
!if SYSTEM = 64 {
|
||||
* = $c000
|
||||
!to "ddrv64.prg", cbm
|
||||
VIC_Base = $d000
|
||||
!addr VIC_Base = $d000
|
||||
}
|
||||
!if SYSTEM = 128 {
|
||||
* = $0c00
|
||||
!to "ddrv128.prg", cbm
|
||||
VIC_Base = $11d6 ; Location of mirror registers
|
||||
!addr VIC_Base = $11d6 ; Location of mirror registers
|
||||
}
|
||||
|
||||
; Pointer's maximum coordinates
|
||||
@ -78,11 +79,14 @@
|
||||
; Locations to store button states, $ff = pressed, $00 = not pressed.
|
||||
; Mouse uses both buttons, joystick only uses "LeftButton".
|
||||
; Location to store pointer's current character coordinates.
|
||||
!addr {
|
||||
!if SYSTEM = 64 {
|
||||
LeftButton = $a4
|
||||
RightButton = $a5
|
||||
CharX = $b3
|
||||
CharY = $b4
|
||||
tapebuf = $0340
|
||||
spr_ptrs = 2040
|
||||
}
|
||||
!if SYSTEM = 128 {
|
||||
LeftButton = $fa
|
||||
@ -96,7 +100,6 @@
|
||||
; x low, x high, y low, y high
|
||||
Coordinates = $fb ; $fb..$fe
|
||||
|
||||
|
||||
; --- System constants
|
||||
|
||||
; Interrupt vector
|
||||
@ -108,7 +111,7 @@
|
||||
cia1_prb = $dc01
|
||||
cia1_ddrb = $dc03
|
||||
mmu_cr = $ff00 ; c128 only
|
||||
|
||||
};addr
|
||||
|
||||
; --- Label definitions
|
||||
|
||||
@ -168,15 +171,15 @@ Init lda sys_iirq
|
||||
; Copy sprites to tape buffer
|
||||
ldx #127
|
||||
- lda Sprites, x
|
||||
sta $0340, x
|
||||
sta tapebuf, x
|
||||
dex
|
||||
bpl -
|
||||
lda #Sprites_Bitmask
|
||||
; Set sprite block pointers
|
||||
ldx #$0d
|
||||
stx 2040 + Sprite_A
|
||||
stx spr_ptrs + Sprite_A
|
||||
inx
|
||||
stx 2040 + Sprite_B
|
||||
stx spr_ptrs + Sprite_B
|
||||
; Activate pointer sprites
|
||||
ora 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
|
||||
; previous IRQ routine.
|
||||
mod16 = * + 1: jmp $ffff ; (self-modifying)
|
||||
mod16 = * + 1: jmp addr($ffff) ; (self-modifying)
|
||||
|
||||
; This table is for part 8.
|
||||
;OrTable !byte 0, 32, 64 ; VDC only
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
; ist der komplette Sourcecode von MacEdit
|
||||
; (80-Zeichen-Version)
|
||||
; Version 0.7
|
||||
@ -76,3 +76,5 @@ Spätere Änderungen am Source:
|
||||
Converted to UTF-8
|
||||
27 Jun 2013:
|
||||
Adjusted to change in library.
|
||||
1 Jun 2014:
|
||||
Adjusted to experimental type system of ACME 0.95
|
||||
|
@ -1,10 +1,10 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
; Konstanten:
|
||||
FALSE = 0 ; Das Programm verläßt sich an etlichen Stellen
|
||||
TRUE = $ff ; darauf, daß genau diese Werte zugewiesen wurden.
|
||||
MODIFIED8 = $ff ; Defaultwerte für
|
||||
MODIFIED16 = $ffff ; Selbstmodifikationen
|
||||
!addr MODIFIED16 = $ffff ; Selbstmodifikationen
|
||||
|
||||
Char_NUL = $00
|
||||
Char_STOP = $03
|
||||
@ -46,6 +46,7 @@
|
||||
lf = 8 ; Filenr. & Sek.-Addy
|
||||
|
||||
; Zeropage:
|
||||
!addr {
|
||||
D8502 = $00 ; Direction
|
||||
R8502 = $01 ; Register
|
||||
vvek = $83 ; Vektor auf LineVektor
|
||||
@ -91,3 +92,4 @@
|
||||
clrchn = $ffcc
|
||||
basin = $ffcf
|
||||
basout = $ffd2
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!zone
|
||||
F_info ldx #hWindow_InfoBox
|
||||
@ -483,7 +483,7 @@ swin !byte 0 ; Auch fuer 'lwin'
|
||||
bckgrnd = 26 ; screencolor-register
|
||||
flnmpos = 87 ; filenameposition
|
||||
wsstart = $0fd0 ; windowstack-start
|
||||
tcolor = $f2 ; attribute-buffer
|
||||
!addr tcolor = $f2 ; attribute-buffer
|
||||
|
||||
; Subs:
|
||||
!zone
|
||||
@ -505,11 +505,11 @@ init ldx repeatedtry ; first start ?
|
||||
stx fnbank ; filename-CR
|
||||
dex
|
||||
stx locks ; 'CBM-shift' off
|
||||
stx $0ac5 ; 'ASC/DIN' off
|
||||
stx addr($0ac5) ; 'ASC/DIN' off
|
||||
stx basic ; 'Basic-IRQ' off
|
||||
jsr crsrinit ; init crsr
|
||||
ldx #$0b ; VIC off
|
||||
stx $11e7
|
||||
stx addr($11e7)
|
||||
lda mode ; which mode ?
|
||||
bmi + ; if 40 then
|
||||
jsr kernel_switchmode ; switch mode
|
||||
@ -567,7 +567,7 @@ init ldx repeatedtry ; first start ?
|
||||
sta conreg + 1 ; full RAM
|
||||
ldx #$0b ; loop for new
|
||||
- lda keyb, x ; keyboard-tabs
|
||||
sta $033e, x
|
||||
sta addr($033e), x
|
||||
dex
|
||||
bpl -
|
||||
jsr handleid ; old ID ?
|
||||
@ -747,7 +747,7 @@ F_gosys +bank15
|
||||
jsr kernel_cls ; CLS
|
||||
lda #0 ; '0' for
|
||||
sta locks ; 'CBM-Shift' on
|
||||
sta $0ac5 ; 'ASC/DIN' on
|
||||
sta addr($0ac5) ; 'ASC/DIN' on
|
||||
sta basic ; 'Basic-IRQ' on
|
||||
lda nmibuf ; restore NMI
|
||||
ldx nmibuf + 1
|
||||
|
@ -8,7 +8,7 @@ RM = rm
|
||||
PROGS = acme
|
||||
BINDIR = /usr/local/bin
|
||||
USERBIN = $(HOME)/bin
|
||||
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o
|
||||
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)
|
||||
|
||||
@ -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
|
||||
|
||||
typesystem.o: config.h global.h typesystem.h typesystem.c
|
||||
|
||||
clean:
|
||||
-$(RM) -f *.o $(PROGS) *~ core
|
||||
|
||||
|
@ -8,7 +8,7 @@ RM = rm
|
||||
PROGS = acme
|
||||
#BINDIR = /usr/local/bin
|
||||
#USERBIN = $(HOME)/bin
|
||||
OBJS = acme.o alu.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o
|
||||
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)
|
||||
|
||||
@ -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
|
||||
|
||||
typesystem.o: config.h global.h typesystem.h typesystem.c
|
||||
|
||||
clean:
|
||||
del *.o
|
||||
# -$(RM) -f *.o $(PROGS) *~ core
|
||||
|
@ -15,8 +15,8 @@ USERBIN = $(HOME)/bin
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
acme.exe: acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o _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
|
||||
acme.exe: acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o_dos.o resource.res
|
||||
$(CC) $(LIBS) $(CFLAGS) -o acme acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o typesystem.o resource.res
|
||||
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
|
||||
|
||||
typesystem.o: config.h global.h typesystem.h typesystem.c
|
||||
|
||||
# _dos.o: _dos.h
|
||||
|
||||
win/resource.rc: acme.c
|
||||
|
@ -8,7 +8,7 @@ RM = rm
|
||||
PROGS = acme
|
||||
#BINDIR = /usr/local/bin
|
||||
#USERBIN = $(HOME)/bin
|
||||
OBJS = acme.o alu.o basics.o cliargs.o cpu.o dynabuf.o encoding.o flow.o global.o input.o label.o macro.o mnemo.o output.o platform.o section.o tree.o
|
||||
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)
|
||||
|
||||
@ -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
|
||||
|
||||
typesystem.o: config.h global.h typesystem.h typesystem.c
|
||||
|
||||
clean:
|
||||
wipe o.* ~c
|
||||
# -$(RM) -f *.o $(PROGS) *~ core
|
||||
|
16
src/acme.c
16
src/acme.c
@ -15,9 +15,9 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
#define RELEASE "0.94.12" // update before release (FIXME)
|
||||
#define CODENAME "Zarquon" // update before release
|
||||
#define CHANGE_DATE "31 May" // update before release
|
||||
#define RELEASE "0.95" // update before release (FIXME)
|
||||
#define CODENAME "Fenchurch" // update before release
|
||||
#define CHANGE_DATE "2 Jun" // update before release
|
||||
#define CHANGE_YEAR "2014" // update before release
|
||||
//#define HOME_PAGE "http://home.pages.de/~mac_bacon/smorbrod/acme/" // FIXME
|
||||
#define HOME_PAGE "http://sourceforge.net/p/acme-crossass/" // FIXME
|
||||
@ -64,6 +64,8 @@ static const char name_dumpfile[] = "label dump filename";
|
||||
#define OPTION_VERSION "version"
|
||||
// options for "-W"
|
||||
#define OPTIONWNO_LABEL_INDENT "no-label-indent"
|
||||
#define OPTIONWNO_OLD_FOR "no-old-for"
|
||||
#define OPTIONWTYPE_MISMATCH "type-mismatch"
|
||||
|
||||
|
||||
// variables
|
||||
@ -126,6 +128,8 @@ static void show_help_and_exit(void)
|
||||
// as long as there is only one -W option:
|
||||
#define OPTIONWNO_LABEL_INDENT "no-label-indent"
|
||||
" -W" OPTIONWNO_LABEL_INDENT " suppress warnings about indented labels\n"
|
||||
" -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:
|
||||
//" -W show warning level options\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) {
|
||||
warn_on_indented_labels = FALSE;
|
||||
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 {
|
||||
fprintf(stderr, "%sUnknown warning level.\n", cliargs_error);
|
||||
exit(EXIT_FAILURE);
|
||||
|
126
src/alu.c
126
src/alu.c
@ -48,6 +48,7 @@ enum operator_handle {
|
||||
OPHANDLE_END, // "reached end of expression"
|
||||
OPHANDLE_RETURN, // "return value to caller"
|
||||
// functions
|
||||
OPHANDLE_ADDR, // addr(v)
|
||||
OPHANDLE_INT, // int(v)
|
||||
OPHANDLE_FLOAT, // float(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_not = {OPHANDLE_NOT, 30}; // monadic
|
||||
// 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_float = {OPHANDLE_FLOAT, 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_list[] = {
|
||||
PREDEFNODE("addr", &ops_addr),
|
||||
PREDEFNODE("int", &ops_int),
|
||||
PREDEFNODE("float", &ops_float),
|
||||
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 LEFT_FPVAL (operand_stack[operand_sp-2].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_INTOPERAND(i, f) \
|
||||
#define PUSH_INTOPERAND(i, f, r) \
|
||||
do { \
|
||||
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)
|
||||
#define PUSH_FPOPERAND(fp, f) \
|
||||
do { \
|
||||
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)
|
||||
|
||||
|
||||
@ -353,7 +360,7 @@ static void parse_quoted_character(char closing_quote)
|
||||
Throw_error("There's more than one character.");
|
||||
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)
|
||||
}
|
||||
|
||||
@ -393,7 +400,7 @@ static void parse_binary_value(void) // Now GotByte = "%" or "b"
|
||||
flags |= MVALUE_FORCE16;
|
||||
}
|
||||
}
|
||||
PUSH_INTOPERAND(value, flags);
|
||||
PUSH_INTOPERAND(value, flags, 0);
|
||||
// Now GotByte = non-binary char
|
||||
}
|
||||
|
||||
@ -437,7 +444,7 @@ static void parse_hexadecimal_value(void) // Now GotByte = "$" or "x"
|
||||
flags |= MVALUE_FORCE16;
|
||||
}
|
||||
}
|
||||
PUSH_INTOPERAND(value, flags);
|
||||
PUSH_INTOPERAND(value, flags, 0);
|
||||
// Now GotByte = non-hexadecimal char
|
||||
}
|
||||
|
||||
@ -497,7 +504,7 @@ static void parse_decimal_value(void) // Now GotByte = first digit
|
||||
GetByte();
|
||||
parse_frac_part(intval);
|
||||
} else {
|
||||
PUSH_INTOPERAND(intval, MVALUE_GIVEN);
|
||||
PUSH_INTOPERAND(intval, MVALUE_GIVEN, 0);
|
||||
}
|
||||
// Now GotByte = non-decimal char
|
||||
}
|
||||
@ -527,7 +534,7 @@ static void parse_octal_value(void) // Now GotByte = "&"
|
||||
flags |= MVALUE_FORCE16;
|
||||
}
|
||||
}
|
||||
PUSH_INTOPERAND(value, flags);
|
||||
PUSH_INTOPERAND(value, flags, 0);
|
||||
// Now GotByte = non-octal char
|
||||
}
|
||||
|
||||
@ -535,11 +542,11 @@ static void parse_octal_value(void) // Now GotByte = "&"
|
||||
// Parse program counter ('*')
|
||||
static void parse_program_counter(void) // Now GotByte = "*"
|
||||
{
|
||||
struct result_int_t pc;
|
||||
struct result_t pc;
|
||||
|
||||
GetByte();
|
||||
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 {
|
||||
// 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
|
||||
if (operator_stack[operator_sp-1] == &ops_return) {
|
||||
PUSH_OPERATOR(&ops_end);
|
||||
@ -840,7 +847,7 @@ static void expect_dyadic_operator(void)
|
||||
//break; unreachable
|
||||
// end of expression or text version of dyadic operator
|
||||
default:
|
||||
// check string version of operators
|
||||
// check string versions of operators
|
||||
if (BYTEFLAGS(GotByte) & STARTS_KEYWORD) {
|
||||
Input_read_and_lower_keyword();
|
||||
// Now GotByte = illegal char
|
||||
@ -878,6 +885,7 @@ static void perform_fp(double (*fn)(double))
|
||||
RIGHT_FLAGS |= MVALUE_IS_FP;
|
||||
}
|
||||
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.");
|
||||
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_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.");
|
||||
}
|
||||
|
||||
@ -993,9 +1002,14 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
// functions
|
||||
case OPHANDLE_ADDR:
|
||||
RIGHT_ADDRREFS = 1; // result now is an address
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_INT:
|
||||
if (RIGHT_FLAGS & MVALUE_IS_FP)
|
||||
right_fp_to_int();
|
||||
RIGHT_ADDRREFS = 0; // result now is a non-address
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_FLOAT:
|
||||
@ -1004,30 +1018,31 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
RIGHT_FPVAL = RIGHT_INTVAL;
|
||||
RIGHT_FLAGS |= MVALUE_IS_FP;
|
||||
}
|
||||
RIGHT_ADDRREFS = 0; // result now is a non-address
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_SIN:
|
||||
perform_fp(sin);
|
||||
perform_fp(sin); // also zeroes addr_refs
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_COS:
|
||||
perform_fp(cos);
|
||||
perform_fp(cos); // also zeroes addr_refs
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_TAN:
|
||||
perform_fp(tan);
|
||||
perform_fp(tan); // also zeroes addr_refs
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_ARCSIN:
|
||||
perform_ranged_fp(asin);
|
||||
perform_ranged_fp(asin); // also zeroes addr_refs
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_ARCCOS:
|
||||
perform_ranged_fp(acos);
|
||||
perform_ranged_fp(acos); // also zeroes addr_refs
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_ARCTAN:
|
||||
perform_fp(atan);
|
||||
perform_fp(atan); // also zeroes addr_refs
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
// monadic operators
|
||||
@ -1055,6 +1070,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
RIGHT_INTVAL = (RIGHT_INTVAL) & 255;
|
||||
RIGHT_FLAGS |= MVALUE_ISBYTE;
|
||||
RIGHT_FLAGS &= ~MVALUE_FORCEBITS;
|
||||
RIGHT_ADDRREFS = 0; // result now is a non-address
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_HIGHBYTEOF:
|
||||
@ -1064,6 +1080,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
RIGHT_INTVAL = ((RIGHT_INTVAL) >> 8) & 255;
|
||||
RIGHT_FLAGS |= MVALUE_ISBYTE;
|
||||
RIGHT_FLAGS &= ~MVALUE_FORCEBITS;
|
||||
RIGHT_ADDRREFS = 0; // result now is a non-address
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
case OPHANDLE_BANKBYTEOF:
|
||||
@ -1073,6 +1090,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
RIGHT_INTVAL = ((RIGHT_INTVAL) >> 16) & 255;
|
||||
RIGHT_FLAGS |= MVALUE_ISBYTE;
|
||||
RIGHT_FLAGS &= ~MVALUE_FORCEBITS;
|
||||
RIGHT_ADDRREFS = 0; // result now is a non-address
|
||||
goto remove_next_to_last_operator;
|
||||
|
||||
// dyadic operators
|
||||
@ -1080,6 +1098,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP) {
|
||||
both_ensure_fp();
|
||||
LEFT_FPVAL = pow(LEFT_FPVAL, RIGHT_FPVAL);
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
}
|
||||
|
||||
@ -1090,6 +1109,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
Throw_error("Exponent is negative.");
|
||||
LEFT_INTVAL = 0;
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_MULTIPLY:
|
||||
@ -1099,6 +1119,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
} else {
|
||||
LEFT_INTVAL *= RIGHT_INTVAL;
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_DIVIDE:
|
||||
@ -1120,6 +1141,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
LEFT_INTVAL = 0;
|
||||
}
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_INTDIV:
|
||||
@ -1142,6 +1164,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
LEFT_INTVAL = 0;
|
||||
}
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_MODULO:
|
||||
@ -1154,6 +1177,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
Throw_error(exception_div_by_zero);
|
||||
LEFT_INTVAL = 0;
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_ADD:
|
||||
@ -1163,6 +1187,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
} else {
|
||||
LEFT_INTVAL += RIGHT_INTVAL;
|
||||
}
|
||||
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_SUBTRACT:
|
||||
@ -1172,6 +1197,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
} else {
|
||||
LEFT_INTVAL -= RIGHT_INTVAL;
|
||||
}
|
||||
LEFT_ADDRREFS -= RIGHT_ADDRREFS; // subtract address references
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_SL:
|
||||
@ -1181,6 +1207,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
LEFT_FPVAL *= pow(2.0, RIGHT_INTVAL);
|
||||
else
|
||||
LEFT_INTVAL <<= RIGHT_INTVAL;
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_ASR:
|
||||
@ -1190,6 +1217,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
LEFT_FPVAL /= (1 << RIGHT_INTVAL);
|
||||
else
|
||||
LEFT_INTVAL = my_asr(LEFT_INTVAL, RIGHT_INTVAL);
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_LSR:
|
||||
@ -1197,6 +1225,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
|
||||
both_ensure_int(TRUE);
|
||||
LEFT_INTVAL = ((uintval_t) LEFT_INTVAL) >> RIGHT_INTVAL;
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_LE:
|
||||
@ -1206,6 +1235,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
} else {
|
||||
LEFT_INTVAL = (LEFT_INTVAL <= RIGHT_INTVAL);
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_LESSTHAN:
|
||||
@ -1215,6 +1245,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
} else {
|
||||
LEFT_INTVAL = (LEFT_INTVAL < RIGHT_INTVAL);
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_GE:
|
||||
@ -1224,6 +1255,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
} else {
|
||||
LEFT_INTVAL = (LEFT_INTVAL >= RIGHT_INTVAL);
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_GREATERTHAN:
|
||||
@ -1233,6 +1265,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
} else {
|
||||
LEFT_INTVAL = (LEFT_INTVAL > RIGHT_INTVAL);
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_NOTEQUAL:
|
||||
@ -1242,6 +1275,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
} else {
|
||||
LEFT_INTVAL = (LEFT_INTVAL != RIGHT_INTVAL);
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_EQUALS:
|
||||
@ -1251,6 +1285,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
} else {
|
||||
LEFT_INTVAL = (LEFT_INTVAL == RIGHT_INTVAL);
|
||||
}
|
||||
LEFT_ADDRREFS = 0; // result now is a non-address
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_AND:
|
||||
@ -1258,6 +1293,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
|
||||
both_ensure_int(TRUE);
|
||||
LEFT_INTVAL &= RIGHT_INTVAL;
|
||||
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_EOR:
|
||||
@ -1268,6 +1304,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
|
||||
both_ensure_int(TRUE);
|
||||
LEFT_INTVAL ^= RIGHT_INTVAL;
|
||||
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
case OPHANDLE_OR:
|
||||
@ -1275,6 +1312,7 @@ static void try_to_reduce_stacks(int *open_parentheses)
|
||||
if ((RIGHT_FLAGS | LEFT_FLAGS) & MVALUE_IS_FP)
|
||||
both_ensure_int(TRUE);
|
||||
LEFT_INTVAL |= RIGHT_INTVAL;
|
||||
LEFT_ADDRREFS += RIGHT_ADDRREFS; // add address references
|
||||
goto handle_flags_and_dec_stacks;
|
||||
|
||||
default:
|
||||
@ -1389,8 +1427,7 @@ static int parse_expression(struct result_t *result)
|
||||
}
|
||||
|
||||
|
||||
// These functions handle numerical expressions. There are operators for
|
||||
// arithmetic, logic, shift and comparison operations.
|
||||
// These functions handle numerical expressions.
|
||||
// There are several different ways to call the core function:
|
||||
// intval_t ALU_any_int(void);
|
||||
// returns int value (0 if result was undefined)
|
||||
@ -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
|
||||
// error.
|
||||
// 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(&result))
|
||||
if (parse_expression(intresult))
|
||||
Throw_error(exception_paren_open);
|
||||
if ((result.flags & MVALUE_EXISTS) == 0)
|
||||
Throw_error(exception_no_value);
|
||||
else if ((result.flags & MVALUE_DEFINED) == 0)
|
||||
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;
|
||||
// make sure result is not float
|
||||
if (intresult->flags & MVALUE_IS_FP) {
|
||||
intresult->val.intval = intresult->val.fpval;
|
||||
intresult->flags &= ~MVALUE_IS_FP;
|
||||
}
|
||||
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
|
||||
// addressing modes where internal indices have to be possible. Returns number
|
||||
// of parentheses still open (either 0 or 1).
|
||||
int ALU_liberal_int(struct result_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) {
|
||||
parentheses_still_open = 0;
|
||||
Throw_error(exception_paren_open);
|
||||
}
|
||||
if ((result.flags & MVALUE_EXISTS)
|
||||
&& ((result.flags & MVALUE_DEFINED) == 0))
|
||||
if ((intresult->flags & MVALUE_EXISTS)
|
||||
&& ((intresult->flags & MVALUE_DEFINED) == 0))
|
||||
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;
|
||||
}
|
||||
|
||||
|
10
src/alu.h
10
src/alu.h
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816 code.
|
||||
// Copyright (C) 1998-2009 Marco Baye
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// ALU stuff (the expression parser)
|
||||
@ -12,9 +12,9 @@
|
||||
|
||||
// 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)
|
||||
// floating point value (never set in result_int_t)
|
||||
// floating point value
|
||||
#define MVALUE_INDIRECT (1u << 7)
|
||||
// needless parentheses indicate use of indirect addressing modes
|
||||
#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.
|
||||
extern int ALU_optional_defined_int(intval_t *);
|
||||
// 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)
|
||||
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)
|
||||
extern void ALU_any_result(struct result_t *);
|
||||
|
||||
|
16
src/basics.c
16
src/basics.c
@ -14,6 +14,7 @@
|
||||
#include "global.h"
|
||||
#include "output.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
|
||||
|
||||
// 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
|
||||
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("fi", PO_fill),
|
||||
PREDEFNODE("fill", PO_fill),
|
||||
PREDEFNODE("addr", PO_addr),
|
||||
PREDEFNODE("address", PO_addr),
|
||||
// PREDEFNODE("debug", PO_debug),
|
||||
// PREDEFNODE("info", PO_info),
|
||||
// PREDEFNODE("print", PO_print),
|
||||
|
@ -18,11 +18,7 @@ struct result_t { // either int or float
|
||||
intval_t intval; // integer value
|
||||
double fpval; // floating point value
|
||||
} val; // Expression value
|
||||
};
|
||||
// result structure type definition for int
|
||||
struct result_int_t {
|
||||
int flags; // expression flags
|
||||
intval_t intval; // expression value
|
||||
int addr_refs; // address reference count (only look at this if value is DEFINED)
|
||||
};
|
||||
|
||||
|
||||
|
@ -75,7 +75,7 @@ static enum eos PO_align(void)
|
||||
intval_t and,
|
||||
equal,
|
||||
fill,
|
||||
test = CPU_state.pc.intval;
|
||||
test = CPU_state.pc.val.intval;
|
||||
|
||||
// make sure PC is defined.
|
||||
if ((CPU_state.pc.flags & MVALUE_DEFINED) == 0) {
|
||||
@ -152,13 +152,13 @@ static enum eos PO_pseudopc(void)
|
||||
|
||||
// set new
|
||||
new_pc = ALU_defined_int(); // FIXME - allow for undefined!
|
||||
new_offset = (new_pc - CPU_state.pc.intval) & 0xffff;
|
||||
CPU_state.pc.intval = new_pc;
|
||||
new_offset = (new_pc - CPU_state.pc.val.intval) & 0xffff;
|
||||
CPU_state.pc.val.intval = new_pc;
|
||||
CPU_state.pc.flags |= MVALUE_DEFINED; // FIXME - remove when allowing undefined!
|
||||
// if there's a block, parse that and then restore old value!
|
||||
if (Parse_optional_block()) {
|
||||
// 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;
|
||||
} else {
|
||||
// not using a block is no longer allowed
|
||||
|
@ -209,12 +209,15 @@ static enum eos PO_for(void) // Now GotByte = illegal char
|
||||
first_arg = ALU_defined_int();
|
||||
if (Input_accept_comma()) {
|
||||
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_last = ALU_defined_int(); // read second argument
|
||||
counter_increment = (counter_last < counter_first) ? -1 : 1;
|
||||
} else {
|
||||
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)
|
||||
Throw_serious_error("Loop count is negative.");
|
||||
counter_first = 0; // CAUTION - old algo pre-increments and therefore starts with 1!
|
||||
|
@ -5,6 +5,7 @@
|
||||
// Global stuff - things that are needed by several modules
|
||||
// 4 Oct 2006 Fixed a typo in a comment
|
||||
// 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 "platform.h"
|
||||
#include "acme.h"
|
||||
@ -17,6 +18,7 @@
|
||||
#include "output.h"
|
||||
#include "section.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
|
||||
|
||||
// constants
|
||||
@ -55,7 +57,7 @@ const char exception_syntax[] = "Syntax error.";
|
||||
// ...4.... special character for input syntax: 0x00 TAB LF CR SPC : ; }
|
||||
// ....3... preceding sequence of '-' characters is anonymous backward
|
||||
// label. Currently only set for ')', ',' and CHAR_EOS.
|
||||
// .....210 unused
|
||||
// .....210 currently unused
|
||||
const char Byte_flags[256] = {
|
||||
/*$00*/ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// control characters
|
||||
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)
|
||||
int Process_verbosity = 0; // Level of additional output
|
||||
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
|
||||
int pass_undefined_count; // "NeedValue" type errors
|
||||
int pass_real_errors; // Errors yet
|
||||
@ -256,9 +260,10 @@ void Parse_until_eob_or_eof(void)
|
||||
while ((GotByte != CHAR_EOB) && (GotByte != CHAR_EOF)) {
|
||||
// process one statement
|
||||
statement_flags = 0; // no "label = pc" definition yet
|
||||
typesystem_force_address_statement(FALSE);
|
||||
// Parse until end of statement. Only loops if statement
|
||||
// contains "label = pc" definition and something else; or
|
||||
// if "!ifdef" is true.
|
||||
// if "!ifdef" is true, or if "!addr" is used without block.
|
||||
do {
|
||||
switch (GotByte) {
|
||||
case CHAR_EOS: // end of statement
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ACME - a crossassembler for producing 6502/65c02/65816 code.
|
||||
// Copyright (C) 1998-2009 Marco Baye
|
||||
// Copyright (C) 1998-2014 Marco Baye
|
||||
// Have a look at "acme.c" for further info
|
||||
//
|
||||
// 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(!)
|
||||
#define BYTEIS_SYNTAX (1u << 4) // special character for input syntax
|
||||
#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
|
||||
@ -64,6 +64,8 @@ enum eos {
|
||||
extern int pass_count;
|
||||
extern int Process_verbosity; // Level of additional output
|
||||
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)
|
||||
// Global counters
|
||||
extern int pass_undefined_count; // "NeedValue" type errors in current pass
|
||||
|
16
src/label.c
16
src/label.c
@ -17,6 +17,7 @@
|
||||
#include "platform.h"
|
||||
#include "section.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
|
||||
|
||||
// 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.
|
||||
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));
|
||||
// Finish empty label item
|
||||
label->result.flags = flags;
|
||||
label->result.addr_refs = 0;
|
||||
if (flags & MVALUE_IS_FP)
|
||||
label->result.val.fpval = 0;
|
||||
else
|
||||
@ -206,9 +208,9 @@ static struct node_t pseudo_opcodes[] = {
|
||||
// GlobalDynaBuf holds the label name.
|
||||
void Label_implicit_definition(zone_t zone, int stat_flags, int force_bit, int change)
|
||||
{
|
||||
struct result_int_t pc;
|
||||
struct result_t result;
|
||||
struct label *label;
|
||||
struct result_t pc,
|
||||
result;
|
||||
struct label *label;
|
||||
|
||||
label = Label_find(zone, force_bit);
|
||||
// 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.");
|
||||
vcpu_read_pc(&pc);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -236,6 +239,9 @@ void Label_parse_definition(zone_t zone, int stat_flags)
|
||||
// label = parsed value
|
||||
GetByte(); // skip '='
|
||||
ALU_any_result(&result);
|
||||
// if wanted, mark as address reference
|
||||
if (typesystem_says_address())
|
||||
result.addr_refs = 1;
|
||||
Label_set_value(label, &result, FALSE);
|
||||
Input_ensure_EOS();
|
||||
} else {
|
||||
|
72
src/mnemo.c
72
src/mnemo.c
@ -11,6 +11,7 @@
|
||||
#include "input.h"
|
||||
#include "output.h"
|
||||
#include "tree.h"
|
||||
#include "typesystem.h"
|
||||
|
||||
|
||||
// Constants
|
||||
@ -395,9 +396,9 @@ static int get_index(int next)
|
||||
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.
|
||||
static int get_argument(struct result_int_t *result)
|
||||
static int get_argument(struct result_t *result)
|
||||
{
|
||||
int open_paren,
|
||||
addressing_mode = HAM_ABS;
|
||||
@ -407,6 +408,7 @@ static int get_argument(struct result_int_t *result)
|
||||
case '[':
|
||||
GetByte(); // proceed with next char
|
||||
ALU_int_result(result);
|
||||
typesystem_want_addr(result);
|
||||
if (GotByte == ']')
|
||||
addressing_mode |= HAM_LIND | get_index(TRUE);
|
||||
else
|
||||
@ -416,10 +418,12 @@ static int get_argument(struct result_int_t *result)
|
||||
GetByte(); // proceed with next char
|
||||
addressing_mode |= HAM_IMM;
|
||||
ALU_int_result(result);
|
||||
typesystem_want_imm(result);
|
||||
break;
|
||||
default:
|
||||
// liberal, to allow for "(...,"
|
||||
open_paren = ALU_liberal_int(result);
|
||||
typesystem_want_addr(result);
|
||||
// check for implied addressing
|
||||
if ((result->flags & MVALUE_EXISTS) == 0)
|
||||
addressing_mode |= HAM_IMP;
|
||||
@ -447,7 +451,7 @@ static int get_argument(struct result_int_t *result)
|
||||
|
||||
// Helper function for calc_arg_size()
|
||||
// Only call with "size_bit = MVALUE_FORCE16" or "size_bit = MVALUE_FORCE24"
|
||||
static int check_oversize(int size_bit, struct result_int_t *argument)
|
||||
static int check_oversize(int size_bit, struct result_t *argument)
|
||||
{
|
||||
// only check if value is *defined*
|
||||
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
|
||||
if (size_bit == MVALUE_FORCE16) {
|
||||
// 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);
|
||||
} else {
|
||||
// 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);
|
||||
}
|
||||
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
|
||||
// addressing_modes adressing modes (8b, 16b, 24b or any combination)
|
||||
// Return value = force bit for number of parameter bytes to send (0 = error)
|
||||
static int calc_arg_size(int force_bit, struct result_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 (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
|
||||
// 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.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Value is positive or zero. Check size ranges
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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).
|
||||
static void group_only_relative8_addressing(int opcode)
|
||||
{
|
||||
struct result_int_t target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
struct result_t target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
|
||||
ALU_int_result(&target);
|
||||
typesystem_want_addr(&target);
|
||||
// FIXME - read pc via function call instead!
|
||||
if (CPU_state.pc.flags & target.flags & MVALUE_DEFINED) {
|
||||
if ((target.intval | 0xffff) != 0xffff) {
|
||||
not_in_bank(target.intval);
|
||||
if ((target.val.intval | 0xffff) != 0xffff) {
|
||||
not_in_bank(target.val.intval);
|
||||
} 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
|
||||
if (offset & 0x8000)
|
||||
offset -= 0x10000;
|
||||
@ -618,16 +623,17 @@ static void group_only_relative8_addressing(int opcode)
|
||||
// Mnemonics using only 16bit relative addressing (BRL and PER).
|
||||
static void group_only_relative16_addressing(int opcode)
|
||||
{
|
||||
struct result_int_t target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
struct result_t target;
|
||||
intval_t offset = 0; // dummy value, to not throw more errors than necessary
|
||||
|
||||
ALU_int_result(&target);
|
||||
typesystem_want_addr(&target);
|
||||
// FIXME - read pc via function call instead!
|
||||
if (CPU_state.pc.flags & target.flags & MVALUE_DEFINED) {
|
||||
if ((target.intval | 0xffff) != 0xffff) {
|
||||
not_in_bank(target.intval);
|
||||
if ((target.val.intval | 0xffff) != 0xffff) {
|
||||
not_in_bank(target.val.intval);
|
||||
} 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
|
||||
}
|
||||
}
|
||||
@ -638,7 +644,7 @@ static void group_only_relative16_addressing(int opcode)
|
||||
|
||||
// set addressing mode bits depending on which opcodes exist, then calculate
|
||||
// argument size and output both opcode and argument
|
||||
static void make_command(int force_bit, struct result_int_t *result, unsigned long opcodes)
|
||||
static void make_command(int force_bit, struct result_t *result, unsigned long opcodes)
|
||||
{
|
||||
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)) {
|
||||
case MVALUE_FORCE08:
|
||||
Output_byte(opcodes & 255);
|
||||
Output_8b(result->intval);
|
||||
Output_8b(result->val.intval);
|
||||
break;
|
||||
case MVALUE_FORCE16:
|
||||
Output_byte((opcodes >> 8) & 255);
|
||||
Output_16b(result->intval);
|
||||
Output_16b(result->val.intval);
|
||||
break;
|
||||
case MVALUE_FORCE24:
|
||||
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.
|
||||
static void group_main(int index, int imm_flag)
|
||||
{
|
||||
unsigned long imm_opcodes;
|
||||
struct result_int_t result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
unsigned long imm_opcodes;
|
||||
struct result_t result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_argument(&result)) {
|
||||
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.
|
||||
static void group_misc(int index, int imm_flag)
|
||||
{
|
||||
unsigned long imm_opcodes;
|
||||
struct result_int_t result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
unsigned long imm_opcodes;
|
||||
struct result_t result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_argument(&result)) {
|
||||
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);
|
||||
// check whether to warn about 6510's unstable LXA
|
||||
if ((imm_opcodes == 0xab)
|
||||
&& ((result.intval & 0xff) != 0x00)
|
||||
&& ((result.val.intval & 0xff) != 0x00)
|
||||
&& (result.flags & MVALUE_DEFINED)
|
||||
&& (CPU_state.type->flags & CPUFLAG_AB_NEEDS_0_ARG))
|
||||
Throw_warning("Assembling unstable LXA #NONZERO instruction");
|
||||
@ -796,8 +802,8 @@ static void group_move(int opcode)
|
||||
// The jump instructions.
|
||||
static void group_jump(int index)
|
||||
{
|
||||
struct result_int_t result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
struct result_t result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_argument(&result)) {
|
||||
case HAM_ABS: // absolute16 or absolute24
|
||||
@ -806,7 +812,7 @@ static void group_jump(int index)
|
||||
case HAM_IND: // ($ffff)
|
||||
make_command(force_bit, &result, jump_ind[index]);
|
||||
// check whether to warn about 6502's JMP() bug
|
||||
if (((result.intval & 0xff) == 0xff)
|
||||
if (((result.val.intval & 0xff) == 0xff)
|
||||
&& (result.flags & MVALUE_DEFINED)
|
||||
&& (CPU_state.type->flags & CPUFLAG_INDIRECTJMPBUGGY))
|
||||
Throw_warning("Assembling buggy JMP($xxff) instruction");
|
||||
|
11
src/output.c
11
src/output.c
@ -485,7 +485,7 @@ void Output_passinit(void)
|
||||
|
||||
//vcpu stuff:
|
||||
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.a_is_long = FALSE; // short accu
|
||||
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;
|
||||
|
||||
new_offset = (new_pc - CPU_state.pc.intval) & 0xffff;
|
||||
CPU_state.pc.intval = new_pc;
|
||||
new_offset = (new_pc - CPU_state.pc.val.intval) & 0xffff;
|
||||
CPU_state.pc.val.intval = new_pc;
|
||||
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
|
||||
Output_start_segment(new_offset, segment_flags);
|
||||
}
|
||||
@ -614,7 +615,7 @@ void PO_setpc(void)
|
||||
|
||||
|
||||
// get program counter
|
||||
void vcpu_read_pc(struct result_int_t *target)
|
||||
void vcpu_read_pc(struct result_t *target)
|
||||
{
|
||||
*target = CPU_state.pc;
|
||||
}
|
||||
@ -630,6 +631,6 @@ int vcpu_get_statement_size(void)
|
||||
// adjust program counter (called at end of each statement)
|
||||
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;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
// FIXME - move struct definition to .c file and change other .c files' accesses to fn calls
|
||||
struct vcpu {
|
||||
const struct cpu_type *type; // current CPU type (default 6502) (FIXME - move out of struct again?)
|
||||
struct result_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 a_is_long;
|
||||
int xy_are_long;
|
||||
@ -65,7 +65,7 @@ extern void Output_end_segment(void);
|
||||
// set program counter to defined value (FIXME - allow undefined!)
|
||||
extern void vcpu_set_pc(intval_t new_pc, int flags);
|
||||
// get program counter
|
||||
extern void vcpu_read_pc(struct result_int_t *target);
|
||||
extern void vcpu_read_pc(struct result_t *target);
|
||||
// get size of current statement (until now) - needed for "!bin" verbose output
|
||||
extern int vcpu_get_statement_size(void);
|
||||
// adjust program counter (called at end of each statement)
|
||||
|
53
src/typesystem.c
Normal file
53
src/typesystem.c
Normal 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
25
src/typesystem.h
Normal 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
|
Loading…
Reference in New Issue
Block a user