Shop OBEX P1 Docs P2 Docs Learn Events
Removing rust my mind on Propeller Assembly subroutine call and ret — Parallax Forums

Removing rust my mind on Propeller Assembly subroutine call and ret

Timothy D. SwieterTimothy D. Swieter Posts: 1,613
edited 2014-09-29 00:55 in Propeller 1
Hi guys -

Long time since I've been around here. Still love the Propeller, just not many projects recently with it so my Propeller assembly part of my mind has rusted over, I think.

I'm patching and updating code that I created for a client. Below is the snippet. Up till now one case was handled for processing data and it was inline with the whole program. But there are now two cases, so I thought it best to break it out to two subroutines. You can see in my example below the general structure of the program. What I am going for is either 'call #Case1Process' or ''call #Case2Process' is executed and when done it returns to ':Addone' line. The structure I have, I believe, doesn't exactly accomplish this, true? That and c and z aren't preserved through sub-routine calls.

When 'call #Case1Process' is executed, the ret is then to the 'call #Case2Process', correct?

I'm looking for suggestions to how this should be structured such that at the end of Case1Process or Case2Process it returns to the same point in the program.

Thanks - Tim
...........
                                                'Two cases of on/off pairs are handled.
                                                '  Case 1 - on value is less than or equal to off value
                                                '  Case 2 - on value is greater than off value
              cmp       cdON,   cdOFF      wc, wz
    if_c_or_z call      #Case1Process
 if_nc_and_nz call      #Case2Process


:AddOne       add       COGtbl, #1              'Add one to the COG table location (long)


........


theroutine_ret ret                              'Sub-routine complete


'-----------------------------------------------------------------------------------------------------
'Sub-routine to process Case 1 of on/off pair.  On <= Off.
'-----------------------------------------------------------------------------------------------------
Case1Process

........


Case1Process_ret ret                            'Sub-routine execution complete


'-----------------------------------------------------------------------------------------------------
'Sub-routine to process Case 2 of on/off pair.  On > Off.
'-----------------------------------------------------------------------------------------------------
Case2Process


.............


Case2Process_ret ret                            'Sub-routine execution complete

Comments

  • ChrisGaddChrisGadd Posts: 310
    edited 2014-09-26 20:14
    The first solution that occurs to me is to move the compare to inside the called code.
                            call      #CaseProcess
    :AddOne                 add       CPGtbl,#1
    
    '--------------------------------------------------
    CaseProcess
                            cmp       cdON, cdOFF       wc,wz
              if_c_or_z     jmp       #Case1Process
    Case2Process
    '.........
                            jmp       CaseProcess_Ret
    Case1Process
    '.........
    Case1Process_Ret                                           
    Case2Process_Ret                                             
    CaseProcess_Ret          ret                                            
    
    All three of those ret labels are at the same address, which allows you to make calls to the Case1 or Case2 subroutines directly if some other part of the code needs it.
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-09-26 20:33
    It took me a couple tries, but then it dawned on me that adding another compare fixes up C and Z
    cmp     cdON, cdOFF             wc, wz
            if_be           call    #Case1Process
    
                            cmp     cdON, cdOFF             wc, wz   
            if_a            call    #Case2Process
    
  • kuronekokuroneko Posts: 3,623
    edited 2014-09-26 20:38
    As the sub-routines destroy the flags anyway you can get away with this:
    cmp     cdOFF, cdON wc          ' carry set for On > Off
            if_nc   call    #Case1
            if_c    call    #Case2
    
    :AddOne         add     COGtbl, #1              ' Add one to the COG table location (long)
    
    '-----------------------------------------------------------------------------------------------------
    'Sub-routine to process Case 1 of on/off pair.  On <= Off.
    '-----------------------------------------------------------------------------------------------------
    Case1                                           ' called with carry clear
                    ...
    
    Case1_ret       jmpret  $, #0-0 wc,nr           ' Sub-routine execution complete, clear carry
    
    Case1 is called with carry clear so we make sure carry stays clear when this sub-routine returns so Case2 isn't called.
  • localrogerlocalroger Posts: 3,451
    edited 2014-09-28 06:44
    PASM doesn't really have a call; what happens is that the assembler assembles RET as JMP #0-0 and the CALL as JMPRET sub-ret, #sub-loc. JMPRET always writes PC+1 to the sub-ret, but you can manually write anything you want there:
                    cmp     cdOFF, cdON wc          ' carry set for On > Off
                    movs    Case1_ret,#:skip2    'write real return to s-field of RET
            if_nc   jmp     #Case1
                    call    #Case2      'no need for condition here 
    :skip2
    
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2014-09-29 00:55
    Thanks Guys for the reply. In this case, more than one way to skin a cat.

    I appreciate all the responses. It was helping my mind get back into PASM mode. localroger's response makes complete sense to me now that I've reviewed those sections of the PASM manual.
Sign In or Register to comment.