cc65: another unexpected error with .bank directive
minimal example:
.define BASEADDRESS $123456
.define BANKNR $12
; this works always
;offset = (BASEADDRESS + (BANKNR * $1000))
; none of these work with the second LDA
offset = (BASEADDRESS + ((<.bank(banksym)) * $1000))
;offset = (BASEADDRESS + (<(.bank(banksym) * $1000)))
;offset = (BASEADDRESS + ((.bank(banksym) * $1000)&$ffff))
banksym:
lda #<(offset >> 0) & $ff ; working
lda #(offset >> 0) & $ff ; range error ?
in the real code, offset will be a 25 bit address. there are 4 LDA like above shifting by 0/8/16/24 and then masking with $ff. this works fine with the first expression that does not use .bank - as soon as i use .bank in it, i need to prefix the shift with a < operator as in the example, else i get a range error. i dont quite understand why, as the & $ff should reduce the expression to 8 bit either way. i’d expect both to work, regardless of the .bank directive being used.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 18 (17 by maintainers)
Commits related to this issue
- special case for evaluating the AND operator, this should fix the problems described in issue #1538 — committed to mrdudz/cc65 by mrdudz 2 years ago
- special case for evaluating the AND operator, this should fix the problems described in issue #1538 — committed to mrdudz/cc65 by mrdudz 2 years ago
In some ways, ca65 is a strange animal. It’s more like a compiler than other assemblers are. Expressions carry a data width.
ca65 cannot know what value
.bank()will have – it must pass the entire expression to ld65. It doesn’t know what the final width will be, but it does make some guesses. It sees thatBASEADDRESSis too wide. It sees that$1000is too wide. It doesn’t know what"& $ff"will do. It does know what<will do.Therefore, ca65 guesses that the first
ldawon’t be too wide. It guesses that the second one will be too wide.