Table Reads Using MOVIW (SOLVED)

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
MCU: Enhanced mid-range
Language: MPASM
Development: MPLAB 8.92

Cold wet day with time to waste, so was trying out an idea for table reads to avoid setting FSRxH/L. It doesn't work, but I do not understand exactly why. The "conventional" version setting FSRxH/L works like a charm.

Code:
;A: DOES NOT WORK (i.e., only returns 173 despite FSR0 increment)
AltTbl
     clrf      FSR0L      
     clrf      FSR0H
     bsf       FSR0H,7
_AltTbl
     call      AltLUT
     movwf     temp
;    more code here  
     bra       _AltTbl    
AltLUT
     moviw     FSR0++      
     dt   173,0,37,3,1,34,131        
     dt   1,31,67,2,27,99,3
;*************************************************************    
;B: WORKS (i.e.,rotates through the table)
  
AltTbl
     movlw     low AltLUT
     movwf     FSR0L          ;first register in LUT
     movlw     high AltLUT
     movwf     FSR0H          ;sets FSR0H,7
    
_AltTbl    
     moviw     FSR0++
     movwf     temp
;    more code here  
     bra       _AltTbl  
AltLUT
     dt   173,0,37,3,1,34,131      
     dt   1,31,67,2,27,99,3
If "A" returned nothing, I could see that. But, it returns the first element in the table and only that element, regardless of the value of FSR0. Why does the instruction "moviw FSRO++" appear to be ignored?

Regards, John
 

MMcLaren

Joined Feb 14, 2010
861
Hey, John. After executing the moviw instruction (line 13), won't you fall through to the retlw instruction (the first dt entry on line 14)?
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
Hi Mike,

(written pre-epiphany) That is like I intended, but maybe I am too close to it to see the problem.

My understanding is that in the working version, moviw grabs the register from the correct PCL . No return is needed, but I need to include the table offset in setting the FSRxL. It also works using dtm instead of the dt directive (as expected).

In the non-working version, my plan (failed) was to avoid setting the offset by moving the moviw to the table's PCL that is called. Then, I relied on the retlw to return and clear the stack.

Ah, ha. Now that I write that out, I think I see the problem. FSR's only get registers, not any associated instruction. I was trying to make it into a branch. The program simply followed the next instruction after moviw, which was the retlw. Makes more sense now. Not completely comfortable as to why only the first value in the table was returned, regardless of the FSR0 value.

I truly appreciate your clear vision. Anyway, the other method works great. The cost of doing it that way is not too bad, about 3 instructions versus setting up a simple counter and using brw.

Regards, John

EDIT: Now I see it. FSRx is set to 0, so it effectively goes nowhere and/or tries to move register 0/program memory 0 to WREG. Then the next instruction (RETLW) puts the first value of the table into WREG and returns. Quite easy to see once I got away from it for awhile. Again, thanks for the guidance. A lunch break helps.
 
Last edited:

BobaMosfet

Joined Jul 1, 2009
2,113
Hi Mike,

(written pre-epiphany) That is like I intended, but maybe I am too close to it to see the problem.

My understanding is that in the working version, moviw grabs the register from the correct PCL . No return is needed, but I need to include the table offset in setting the FSRxL. It also works using dtm instead of the dt directive (as expected).

In the non-working version, my plan (failed) was to avoid setting the offset by moving the moviw to the table's PCL that is called. Then, I relied on the retlw to return and clear the stack.

Ah, ha. Now that I write that out, I think I see the problem. FSR's only get registers, not any associated instruction. I was trying to make it into a branch. The program simply followed the next instruction after moviw, which was the retlw. Makes more sense now. Not completely comfortable as to why only the first value in the table was returned, regardless of the FSR0 value.

I truly appreciate your clear vision. Anyway, the other method works great. The cost of doing it that way is not too bad, about 3 instructions versus setting up a simple counter and using brw.

Regards, John

EDIT: Now I see it. FSRx is set to 0, so it effectively goes nowhere and/or tries to move register 0/program memory 0 to WREG. Then the next instruction (RETLW) puts the first value of the table into WREG and returns. Quite easy to see once I got away from it for awhile. Again, thanks for the guidance. A lunch break helps.
:p There's an amazing tool for finding this stuff-- it's called a flow chart. Works every single time so long as you actually flow what is coded, not what you think is coded. It also offers one more absolutely incredible feature- it gets stuff out of your head and on to paper, so your mind isn't wasting cycles holding onto things, it's crunching on what it needs. Plus, you can run every possible iteration on paper, find every flaw, and sometimes see a better way so you wind up with an exceedingly tight, bulletproof algorithm.
 

Thread Starter

jpanhalt

Joined Jan 18, 2008
11,087
1) I actually do a flow chart as a working document. Been doing that for decades as part of my day job.
2) The problem was that I was trying to use the FSR as a relative branch. I know that it isn't. I have known that for years. An hour or so away from the problem, and it all cleared up. In fact, I am embarrassed by the post. Just call it an oldtimer's moment (aka cerebral flatulence).
 
Top