[PicForth] bug+workaround: code page switching

David McNab david at rebirthing.co.nz
Sun Nov 7 08:39:12 CET 2004


Hi,

While PicForth's heuristics make a noble effort to keep PCLATH set 
correctly at all times, there are some areas where it's getting it wrong.

After a few hours of chasing weird phenomena, I've found a bug with 
PicForth's handling of code page switching around loops.

Consider the code (from a simple test serial echo prog):

   main : main

       tty.init

       begin
         tty.getc
         tty.putc
       again
   ;

With tty.init, tty.getc and tty.putc in codepage0, and this main word in 
codepage1, we would expect PicForth to clear PCLATH before the tty.init, 
then to set PCLATH bit 3 before the 'again' (so the generated GOTO will 
actually end up at the 'begin'. But also, we need another clrf PCLATH 
just inside the begin.

Instead, what we see in the assembler is:

	; name: main
	; max return-stack depth: 1
0x0802	1683	bsf	0x03,5
0x0803	0186	clrf	0x06
0x0804	1283	bcf	0x03,5
0x0805	018A	clrf	0x0A
0x0806	2055	call	0x055	; tty.init
0x0807	2072	call	0x072	; tty.getc
0x0808	206C	call	0x06C	; tty.putc
0x0809	20E3	call	0x0E3	; getc-dummy
0x080A	20E4	call	0x0E4	; putc-dummy
0x080B	158A	bsf	0x0A,3
0x080C	2807	goto	0x007	; main + 0x005 (0x807)

What happens here is that after one round of the loop, we hit the 'goto 
0007', which takes us back to the top. However, when we hit the 'call 
tty.getc', PCLATH is still set for codepage1, so the 'call' goes off to 
Disneyland instead.

As a workaround, I seem to be getting away with 'no-cbank', which 
appears to tell PicForth to forget its PCLATH caching status.

Amending the above example:

main : main

     0 trisb !

    tty.init

     begin
         forth> no-cbank
         tty.getc                         ( ch )
         tty.putc                             ( ch+20 )
     again
;

This forces an additional 'clrf PCLATH' to go inside the begin, which 
keeps things on track.

Another possible attack is to hack the control-flow words, to add 
'no-cbank' statements. For example, a modified 'begin':

     : begin ( -- 0 baddr ) 0 backref no-cbank ;

This also forces an explicit PCLATH setting at the top of the loop, but 
could cause some unnecessary PCLATH setting code to be generated.

Anyone got any thoughts on all this?

-- 
Cheers
David


More information about the PicForth mailing list