Mike Keitz says:
...There are two situations where "paging" of the program memory is an issue. For CALL or GOTO, the pages are 800h instructions long [on the more advanced PIC processors]. Most short programs don't need to be concerned with them. [HOWEVER] For writing to PCL, the pages are only 100h instructions long. So [any] 256-value table definitely crosses one of those pages. And the program will crash when the index into the table gets large enough if your table-access code doesn't set up PCLATH properly.[Here is some code that sets up PCLATH correctly]
movlw high (TABLE_START) movwf pclath movf index,w addlw TABLE_START skpnc incf pclath,f movwf pcl TABLE_START retlw ...If the table is called such that W is the index:
addlw TABLE_START movwf temp rlf known_zero,w addlw high(TABLE_START) movwf pclath movf temp,w movwf pcl TABLE_START retlw ...
Andrew Warren of Fast Forward Engineering - San Diego, California https://geocities.restorativland.org/SiliconValley/2499/ says:
...write table-lookup code [with] automatic page-crossing checks built in.I generally do it like this:
ADDWF PCL TABLE1: DT "Test" IF ((HIGH ($)) != (HIGH (TABLE1))) ERROR "TABLE1 CROSSES PAGE BOUNDARY!" ENDIFP.S. By the way, another common way that a newly-inserted CALL can screw up previously-working code is if the called routine changes the PCLATH register... Or if your previously-working code expected the W register or STATUS flags to remain unchanged across the portion of the program where you inserted your CALL.
Rich Leggitt says:
...something like this should work for arbitrary table of any length located anywhere in the program space.... movlw high string ; point to a string movwf look_hi ; in reality, a macro... movlw low string movwf look_lo call process ; go process it ... ; subroutine to process string at look_hi/look_lo process call lookup ; get a byte (this is the magic) ; here, do something with byte in W ; also, return if end of string ; otherwise... goto process ; do it again ; Jump to address in look_hi/look_lo, which presumably is an RETLW. ; Note pointer post increment. ; Equivalent to: W=*look_ptr++ lookup movf look_hi,w ; set PCLATH movwf PCLATH movf look_lo,w ; and get PCL incf look_lo,f ; but post inc skpnz incf look_hi,f movwf PCL ; ok, now jump
See Also:
Interested: