Menu

Pagesel restores and goto subs

Frank
2010-07-07
2013-05-30
  • Frank

    Frank - 2010-07-07

    On long programs that have gone over the page boundary there is a problem where the page isn't restored correctly after a call to a sub that ends in a goto some other sub - the original call may be on the same page as the calling code so the compiler doesn't add a 'pagesel $' but if there is a goto some other sub at the end the actual return will be from whatever page that other sub is on.

    I took a stab at writing a fix in the AddPageCommands sub of GCBASIC.BAS changing this section of code -

                'Alter call to correct instruction/s
                If ModePIC Then
                    If ChipFamily = 12 Or ChipFamily = 14 Or ChipFamily = 15 Then
                        CurrLine = LinkedListDelete(CurrLine)
                        If CalledSubPage = ThisSubPage Then
                            CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
                        Else
                            CurrLine = LinkedListInsert(CurrLine, " pagesel " + CallTarget)
                            CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
                            If RestorePage Then
                                CurrLine = LinkedListInsert(CurrLine, " pagesel $")
                            End If
                        End If
                    End If
                ElseIf ModeZ8 Then
                    CurrLine = LinkedListDelete(CurrLine)
                    CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
                End If
    

    to this -

                'Alter call to correct instruction/s
                If ModePIC Then
                    If ChipFamily = 12 Or ChipFamily = 14 Or ChipFamily = 15 Then
                        CurrLine = LinkedListDelete(CurrLine)
                        If CalledSubPage = ThisSubPage Then
                            CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
                        Else
                            CurrLine = LinkedListInsert(CurrLine, " pagesel " + CallTarget)
                            CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
                        End If
                        If RestorePage And (CalledSubPage <> ThisSubPage Or Subroutine(CalledSub)->NoReturn) Then
                            CurrLine = LinkedListInsert(CurrLine, " pagesel $")
                        End If
                    End If
                ElseIf ModeZ8 Then
                    CurrLine = LinkedListDelete(CurrLine)
                    CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
                End If
    

    It should stick a pagesel $ in the code if the next line isn't another call to a different page and either the called sub page is different from the current page or the called sub doesn't appear to have a return. It relies on the NoReturn flag being a good indicator that there is a goto some other sub rather than a return at the end which looks true enough for the program I'm working on.

    Originally I wrote something more complicated that retrieved the name of the goto sub and looked at whether that ended in a return or a goto and looped around until it reached a return but then realised that if any of the chain of goto subs had an 'exit sub' instruction (or two or three) there would be other return points maybe from other pages so the final return page was no more useful than the called sub page. At that point subtlety was abandoned and the brute force and ignorance approach above looked much more appealing.

    The modified compiler added 9 extra pagesel's to the 173 that were already there in the program I'd been working on and it started working properly again. I reckon 8 of those pagesels were needed to restore the page properly so the mod doesn't seem to add too many pointless pagesels although its probably program dependant.

    Frank

     
  • Frank

    Frank - 2010-07-07

    Sorry - should have taken the tabs out

    I took a stab at writing a fix in the AddPageCommands sub of GCBASIC.BAS changing this section of code -

    'Alter call to correct instruction/s
    If ModePIC Then
        If ChipFamily = 12 Or ChipFamily = 14 Or ChipFamily = 15 Then
            CurrLine = LinkedListDelete(CurrLine)
            If CalledSubPage = ThisSubPage Then
                CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
            Else
                CurrLine = LinkedListInsert(CurrLine, " pagesel " + CallTarget)
                CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
                If RestorePage Then
                    CurrLine = LinkedListInsert(CurrLine, " pagesel $")
                End If
            End If
        End If
    ElseIf ModeZ8 Then
        CurrLine = LinkedListDelete(CurrLine)
        CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
    End If
    

    to this -

    'Alter call to correct instruction/s
    If ModePIC Then
        If ChipFamily = 12 Or ChipFamily = 14 Or ChipFamily = 15 Then
            CurrLine = LinkedListDelete(CurrLine)
            If CalledSubPage = ThisSubPage Then
                CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
            Else
                CurrLine = LinkedListInsert(CurrLine, " pagesel " + CallTarget)
                CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
            End If
            If RestorePage And (CalledSubPage <> ThisSubPage Or Subroutine(CalledSub)->NoReturn) Then
                CurrLine = LinkedListInsert(CurrLine, " pagesel $")
            End If
        End If
    ElseIf ModeZ8 Then
        CurrLine = LinkedListDelete(CurrLine)
        CurrLine = LinkedListInsert(CurrLine, " call " + CallTarget)
    End If
    
     
  • Hugh Considine

    Hugh Considine - 2010-07-08

    Well spotted! Your fix is heading in the right direction, but can be made more efficient with some more tweaks.

    NoReturn is also used for lookup table subs, and for interrupt handlers. A bit neater solution is to add another flag to the subroutine type (SubType), which is set by the code that replaces the last call with a goto (the AsmOptimiser function in assembly.bi). This was pretty easy to do, and also allows the target of the goto to be stored for later checking.

    I've made a few other changes to the version of GCBASIC I have here. I've altered the AddPageCommands sub in a similar way, but have added a bit of code to set the RestorePage flag properly. This code works similarly to how you describe your initial code working - it follows the chain of gotos. If it gets to the end of the chain without finding any subs outside of the same page as the original caller, it doesn't restore the page. If it comes to a subroutine in another page, it stops searching and adds the pagesel $ to restore the page. This should get around any problems with exit subs - I think they can only make trouble if somewhere along the line there's a goto  instruction?

    The subroutine size measuring code will also need a tweak (the CalcLineSize function), otherwise the page allocation code won't take into account the added size of the program from the extra page restorations when allocating program memory, and will probably end up overfilling pages.

    Could you please email me your program so that I can run it through the altered version of the compiler and check its behaviour? My w_cholmondeley at users dot sourceforge dot net account would be the best one. (If it's too hard to send, I can send you the altered compiler source, but it's barely tested at this stage!)

     
  • Frank

    Frank - 2010-07-13

    Hi Hugh,

    I emailed the program to your sourceforge address - did you receive it ok?

     
  • Mauried

    Mauried - 2010-07-22

    Would the above issue cause a failure of interrupts when the Compiler locates the Interrupt code in the 2nd page.
    Having a problem with a big program that goes over the page boundary  of a 16F88 which uses a very simple Interrupt using Timer1 to increment a counter every second.
    Program runs fine when the Compiler locates the Interrupt code in the 1st page, but not when it gets located in the 2nd page.
    The 2nd page also holds subroutines.
    Getting the Compiler to put the interrupt code in the first page is tricky, but I can sometimes fool it by adding lines of code that dont do anything, like Nops thats simply change the programs size.
    Program also runs fine if I disable the Interrupts altogether regardless of where anything is located.
    Thanks

     
  • Frank

    Frank - 2010-07-23

    If you're interrupt code makes any calls to subs that end in a goto another sub then it could be.

    Or alternatively it might be that the sub or subs that are forced to move into 2nd page when you move the interrupt code into the first page either end in a goto another sub or are the targets for subs that end in goto and the program works when they are in the 2nd page. That seems less likely as you say the program works alright if interrupts are disabled.

    Hugh is working on a fix at the moment that looks promising.

    You could look through the assembly for any of your own subs that are ending in a goto another sub and try to rearrange the gcbasic code or add a bit dummy code so that the final basic statement in the sub isn't another subroutine - that should get rid of the goto's and pin down whether it is the problem.

     
  • Mauried

    Mauried - 2010-07-23

    Thanks for responding.
    interrupt code is very simple and just keeps time.
    its this

    Sub IncCounter 
    TMR1L = 0
    TMR1H = 11 
    TMR1L = 219 
    'Increment the counter 
    QSeconds += 1
    if Qseconds = 4 then
    Qseconds=0
    tickb += 1
    tick2 += 1
    second += 1
    end if
    end sub

    There are however subs which do call other subs, and they get shuffled around a lot
    depending on how big they are , as well as how big the main prog is .
    Currently ive managed to get the compiler to put the interrupt code in the first page and all is working fine.
    Ill examine carefully what is now in the 2nd page , and see what gets shifted around.

     
  • Mauried

    Mauried - 2010-08-23

    I moved my big program to a bigger Pic  16F886 to see if the page problems dissapeared and they didnt.
    The I implemented you patch to Gcbasic and all problems solved.
    Looks like the gotos in the subs are the issue.
    Fantastic.
    Thanks for the fix.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.