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

Most upvoted comments

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 that BASEADDRESS is too wide. It sees that $1000 is too wide. It doesn’t know what "& $ff" will do. It does know what < will do.

Therefore, ca65 guesses that the first lda won’t be too wide. It guesses that the second one will be too wide.