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
|
||||
|
||||
!address {
|
||||
cpu_nmi = $fffa
|
||||
cpu_reset = $fffc
|
||||
cpu_irq = $fffe
|
||||
}
|
||||
|
||||
; skip byte
|
||||
!macro bit8 {
|
||||
|
@ -1,10 +1,11 @@
|
||||
;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
|
||||
|
||||
!address {
|
||||
cpu_e_cop = $fff4
|
||||
cpu_e_abort = $fff8
|
||||
cpu_e_nmi = $fffa
|
||||
@ -16,6 +17,7 @@ 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,6 +6,7 @@ lib_cbm_c128_kernel_a = 1
|
||||
; Taken from the web.
|
||||
; Sorry, I can't give credit because I don't have the URL anymore.
|
||||
|
||||
!address {
|
||||
k_spin_spout = $ff47
|
||||
k_close_all = $ff4a
|
||||
k_c64mode = $ff4d
|
||||
@ -26,7 +27,10 @@ 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)
|
||||
!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,6 +8,7 @@ lib_cbm_c128_mmu_a = 1
|
||||
|
||||
; registers in i/o area (i/o needs to be enabled to access these):
|
||||
|
||||
!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)
|
||||
@ -15,6 +16,7 @@ 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 = %........
|
||||
@ -64,8 +66,10 @@ mmu_pcr_d = $d504 ; c128 kernel default is $41 (all system roms, with ram 1)
|
||||
; IFROM means internal function ROM (socket U36)
|
||||
; EFROM means external function ROM (socket in a REU, for example)
|
||||
|
||||
!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 :)
|
||||
@ -75,8 +79,10 @@ mmu_mcr = $d505
|
||||
mmu_MCR_UNUSED = %.....##. ; always set
|
||||
mmu_MCR_8502MODE = %.......# ; setting this to zero switches to Z80 cpu
|
||||
|
||||
!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 = %........
|
||||
@ -101,11 +107,13 @@ mmu_rcr = $d506
|
||||
mmu_RCR_SHARESIZE_8K = %......#.
|
||||
mmu_RCR_SHARESIZE_16K = %......##
|
||||
|
||||
!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 = %....##..
|
||||
@ -120,15 +128,19 @@ mmu_p1high = $d50a ; page 1 pointer high (a16..a19), default $00 (on an unmodifi
|
||||
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
|
||||
|
||||
; reading addresses up until $d5ff returns $ff
|
||||
|
||||
|
||||
; these registers are always available (in *every* memory configuration) unless C64 mode is entered:
|
||||
|
||||
!address {
|
||||
; configuration register
|
||||
mmu_cr = $ff00 ; always use this instead of $d500
|
||||
; load configuration registers:
|
||||
@ -143,3 +155,4 @@ mmu_lcr_d = $ff04 ; c128 kernel default is $41 (all system roms, with ram 1)
|
||||
; 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
|
||||
|
||||
|
||||
!address {
|
||||
; direct registers
|
||||
vdc_state = $d600 ; READING this location yields status flags:
|
||||
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)
|
||||
vdc_reg = $d600 ; WRITING this location selects an indirect register
|
||||
vdc_data = $d601 ; data of selected indirect register
|
||||
|
||||
|
||||
; indirect registers (default value, see $e179 in C128 kernal)
|
||||
@ -219,6 +222,7 @@ vdcr_sync_polarity = $25 ; -- only in VDC 8568
|
||||
vdcr_HSYNC_POLARITY = %#.......
|
||||
vdcr_VSYNC_POLARITY = %.#......
|
||||
|
||||
!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)
|
||||
@ -227,3 +231,4 @@ vdcr_sync_polarity = $25 ; -- only in VDC 8568
|
||||
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,10 +1,11 @@
|
||||
;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
|
||||
|
||||
!address {
|
||||
; registers only present in the C128 variant of this chip:
|
||||
vic_keyboard = $d02f
|
||||
vic_clock = $d030
|
||||
@ -15,3 +16,4 @@ vic_clock = $d030
|
||||
; 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
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c128_zeropage_a !eof
|
||||
lib_cbm_c128_zeropage_a = 1
|
||||
@ -17,6 +17,7 @@ lib_cbm_c128_zeropage_a = 1
|
||||
; z_bitmsk, given as $da and $116d
|
||||
; z_dejavu, given as $0a02 and $1221
|
||||
|
||||
!address {
|
||||
z_d8502 = $00
|
||||
z_d6510 = $00
|
||||
z_r8502 = $01
|
||||
@ -290,7 +291,7 @@ z_lfor = $0135
|
||||
z_endfd = $0136
|
||||
z_sysstk = $0137
|
||||
z_buf = $0200
|
||||
; the following block is omitted in the german C128 manual
|
||||
; this block is not in the german C128 manual:
|
||||
z_fetch = $02a2
|
||||
z_fetchvec = $02aa
|
||||
z_stash = $02af
|
||||
@ -326,7 +327,7 @@ z_iclall = $032c
|
||||
z_exmon = $032e
|
||||
z_iload = $0330
|
||||
z_isave = $0332
|
||||
; the following block is omitted in the german C128 manual
|
||||
; this block is not in the german C128 manual:
|
||||
z_ctlvec = $0334
|
||||
z_shfvec = $0336
|
||||
z_escvec = $0338
|
||||
@ -414,7 +415,7 @@ z_palcnt = $0a36
|
||||
z_speed = $0a37
|
||||
z_sprites = $0a38
|
||||
z_blanking = $0a39
|
||||
; the following block is omitted in the german C128 manual
|
||||
; this block is not in the german C128 manual:
|
||||
z_hold_off = $0a3a
|
||||
z_ldtbi_sa = $0a3b
|
||||
z_clr_ea_lo = $0a3c
|
||||
@ -521,7 +522,7 @@ z_adray1 = $117a
|
||||
z_adray2 = $117c
|
||||
z_sprite_data = $117e
|
||||
z_vic_save = $11d6
|
||||
; the following block is omitted in the german C128 manual
|
||||
; this block is not in the german C128 manual:
|
||||
z_upper_lower = $11eb
|
||||
z_upper_graphic = $11ec
|
||||
z_oldlin = $1200
|
||||
@ -603,6 +604,7 @@ z_savram = $12b7
|
||||
z_defmod = $12fa
|
||||
z_lincnt = $12fb
|
||||
z_sprite_number = $12fc
|
||||
; the following block is omitted in the german C128 manual
|
||||
; this block is not in the german C128 manual:
|
||||
z_irq_wrap_flag = $12fd
|
||||
z_rambot = $1c00
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_cia1_a !eof
|
||||
lib_cbm_c64_cia1_a = 1
|
||||
|
||||
!address {
|
||||
cia1_pra = $dc00
|
||||
cia1_prb = $dc01
|
||||
cia1_ddra = $dc02
|
||||
@ -19,3 +20,4 @@ cia1_sdr = $dc0c
|
||||
cia1_icr = $dc0d
|
||||
cia1_cra = $dc0e
|
||||
cia1_crb = $dc0f
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_cia2_a !eof
|
||||
lib_cbm_c64_cia2_a = 1
|
||||
|
||||
!address {
|
||||
cia2_pra = $dd00
|
||||
cia2_prb = $dd01
|
||||
cia2_ddra = $dd02
|
||||
@ -19,3 +20,4 @@ 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:
|
||||
!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,6 +47,7 @@ fac2_base = $69 ; base address of floating-point accumulator 2
|
||||
lda .adr + 1
|
||||
}
|
||||
|
||||
!address {
|
||||
; constants in five-byte "mflpt" format
|
||||
mflpt_pi = $aea8 ; 3.1415926...
|
||||
mflpt_minus32768 = $b1a5 ; -32768
|
||||
@ -111,3 +114,4 @@ 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.
|
||||
|
||||
!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,15 +8,19 @@ 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.
|
||||
|
||||
!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 = %..#.....
|
||||
@ -29,6 +33,7 @@ rec_command = $df01
|
||||
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
|
||||
@ -46,10 +51,13 @@ 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,8 +1,9 @@
|
||||
;ACME 0.94.4
|
||||
;ACME 0.95
|
||||
|
||||
!ifdef lib_cbm_c64_sid_a !eof
|
||||
lib_cbm_c64_sid_a = 1
|
||||
|
||||
!address {
|
||||
; write-only registers:
|
||||
; voice 1:
|
||||
sid_v1_freq_lo = $d400
|
||||
@ -28,6 +29,7 @@ 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 = %.#......
|
||||
@ -37,6 +39,7 @@ sid_v3_sustain_release = $d414 ; hi-nibble: sustain volumne, low-nibble: release
|
||||
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
|
||||
@ -47,6 +50,6 @@ 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,
|
||||
}
|
||||
; 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,6 +21,7 @@ viccolor_LGREEN = $d
|
||||
viccolor_LBLUE = $e
|
||||
viccolor_GRAY3 = $f
|
||||
|
||||
!address {
|
||||
; register addresses
|
||||
vic_xs0 = $d000
|
||||
vic_ys0 = $d001
|
||||
@ -54,7 +55,6 @@ 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
|
||||
@ -72,7 +72,7 @@ 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,6 +7,7 @@ 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.
|
||||
|
||||
!address {
|
||||
k_cint = $ff81
|
||||
k_ioinit = $ff84
|
||||
k_ramtas = $ff87
|
||||
@ -46,3 +47,4 @@ 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,21 +216,17 @@ Available options are:
|
||||
-vDIGIT set verbosity level
|
||||
Sets how much additional informational output is generated.
|
||||
Higher values mean more output:
|
||||
|
||||
acme -v0 source.a
|
||||
This is the default: No additional output is generated,
|
||||
ACME will only display warnings and errors.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
-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);
|
||||
|
124
src/alu.c
124
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;
|
||||
|
||||
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
|
||||
|
14
src/label.c
14
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,8 +208,8 @@ 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 result_t pc,
|
||||
result;
|
||||
struct label *label;
|
||||
|
||||
label = Label_find(zone, force_bit);
|
||||
@ -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 {
|
||||
|
58
src/mnemo.c
58
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;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -689,7 +695,7 @@ static unsigned int imm_ops(int *force_bit, unsigned char opcode, int imm_flag)
|
||||
static void group_main(int index, int imm_flag)
|
||||
{
|
||||
unsigned long imm_opcodes;
|
||||
struct result_int_t result;
|
||||
struct result_t result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_argument(&result)) {
|
||||
@ -738,7 +744,7 @@ static void group_main(int index, int imm_flag)
|
||||
static void group_misc(int index, int imm_flag)
|
||||
{
|
||||
unsigned long imm_opcodes;
|
||||
struct result_int_t result;
|
||||
struct result_t result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_argument(&result)) {
|
||||
@ -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,7 +802,7 @@ static void group_move(int opcode)
|
||||
// The jump instructions.
|
||||
static void group_jump(int index)
|
||||
{
|
||||
struct result_int_t result;
|
||||
struct result_t result;
|
||||
int force_bit = Input_get_force_bit(); // skips spaces after
|
||||
|
||||
switch (get_argument(&result)) {
|
||||
@ -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