Shop OBEX P1 Docs P2 Docs Learn Events
Call Assembly from Spin - How? — Parallax Forums

Call Assembly from Spin - How?

PropNewbiePropNewbie Posts: 10
edited 2008-05-28 21:51 in Propeller 1
Could some kind person please post an example of how an assembly routine can be called from spin. By this I mean a simple call with·long parameters and return with a value rather than starting a new cog. What I would like is to·implement an unsigned comparison of longs. Apparently spin cannot do this natively - I have seen a passing reference on this forum indicating that it would be pretty easy to do. I have dug around (probably missed something obvious) but try as I might I cannot figure out how it·can be done.

Here's my pseudo code

DAT
·· ORG 0
UnsignedCompare:
· <assembly code here>

PUB TestCompareCall (val1, val2)
······· return UnsignedCompare(val1, val2)

All advice and assistance would be much appreciated.

·

Comments

  • allanlane5allanlane5 Posts: 3,815
    edited 2008-05-26 18:10
    I don't think you can.

    When the Propeller starts up, it loads the "Spin" interpreter into Cog-zero. The "Spin" interpreter then runs out of Cog zero, reading "Main Memory" for the Spin tokens.

    Now, Spin has a facility for starting an assembly program in another Cog. That's where you put the assembly code in a DAT section, and the COGNEW code in a "PUB start(Start_Addr, Parm_Addr)" section. The "COGNEW" call downloads the assembly section (from Main Memory, that's where "Spin" is reading tokens) into another COG. That COG then starts executing the downloaded assembly.

    Now, the downloaded assembly CAN access the "PAR" register -- which holds the second parameter of the "COGNEW" call. This is so you can pass a 'shared memory' space in Main Memory that both the Spin code and the Assembly code will know about.

    Also typically, in your assembly object, you'd put a few interface methods to set the variables that assembly would be watching for. When they're set, the assembly (which has been in a 'wait' cycle for them to be set) will run and put the result in yet another variable. The 'high-level' code can then return the value of that variable.

    There's only 512 longs of memory in a 'Cog', so I think you MUST use an additional cog for your "math library".

    Note any "Spin" methods in your assembly object (ie NOT in the "DAT" section) will remain located in Main Memory, so that Spin code can call them.
  • Mike GreenMike Green Posts: 23,101
    edited 2008-05-26 18:39
    It's helpful to remember that the 8 cogs are separate computers with shared peripherals (like memory and I/O pins). When you start up an assembly routine, you're starting up a separate computer with its own program. You're not really "calling" a subroutine although that's how the program is started. In Spin, any attempt to return from that "main" subroutine resets and stops that cog. In assembly, there is no return at all because subroutine calls work differently.
  • hippyhippy Posts: 1,981
    edited 2008-05-27 02:28
    Untested ...

    CON
      A_LT_B = -1
      A_EQ_B =  0
      A_GT_B = +1
      
    PUB UnsignedCompareAwithB(a,b)
      if a == b
        result := A_EQ_B
      else
        if a => 0                   ' A B
          if b => 0                 
            if a > b                ' + +
              result := A_GT_B
            else
              result := A_LT_B
          else
            result := A_LT_B        ' + -
        else
          if b => 0
            result := A_GT_B        ' - +
          else
            if a > b                ' - -
              result := A_GT_B
            else
              result := A_LT_B
    
    PUB IfAltB(a,b)
      result := UnsignedCompareAwithB(a,b) == A_LT_B
    
    PUB IfAleB(a,b)
      result := UnsignedCompareAwithB(a,b) =< A_EQ_B
    
    PUB IfAeqB(a,b)
      result := UnsignedCompareAwithB(a,b) == A_ET_B
      
    PUB IfAneB(a,b)
      result := UnsignedCompareAwithB(a,b) <> A_EQ_B
    
    PUB IfAgeB(a,b)
      result := UnsignedCompareAwithB(a,b) => A_EQ_B
    
    PUB IfAgtB(a,b)
      result := UnsignedCompareAwithB(a,b) == A_GT_B
    
    
    

    Post Edited (hippy) : 5/27/2008 2:35:03 AM GMT
  • Agent420Agent420 Posts: 439
    edited 2008-05-27 16:53
    I never gave this thought until I saw this thread...· I always assumed you could somehow apply inline asm calls ·into Spin.·· Seems a little odd that would not be the case.
  • Mike GreenMike Green Posts: 23,101
    edited 2008-05-27 17:47
    From an assembly language standpoint, each cog has only 512 words for data and instructions and the shared 32K bytes of memory (hub memory) works much like an I/O device ... you can't execute instructions there. To execute instructions "in-line" in Spin, the instructions would have to be copied into the cog's memory somewhere. The Spin interpreter is very tight on room and, rather than giving up some other feature, there was no capability added to execute assembly instructions "in-line". The "Large Memory Model" interpreter used with ImageCraft's C compiler actually copies one instruction at a time into cog memory to execute it and does this in a pretty efficient way.
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-05-28 21:51
    Agent420 said...
    · Seems a little odd that would not be the case.

    If you think about it a bit it makes perfect sense.

    First Spin is an interpreted language, besides emulators assembly execution is never done (that Im aware of) in an interpreted language. All those languages you think of that have inline assembly support are compiled languages, where your code is distilled into assembly code, so it makes it rather easy to toss some additional user written assembly in there. Interpreters operate on byte code, not assembly. Unless you create byte codes for assembly instructions (which is counterproductive) the interpretor would have no clue what to do with them.

    Second, the spin interpreter resides in the memory of a cog (has to in order to be executed). There are exectly 496 locations for all instructions·and data·within a·cog. This means that the code that is executed for each and every Spin instruction must be in cog memory, not to mention the interpretor engine. Now look at the number of instructions Spin supports, it's well over 100 supported instructions. Thats an average of·less than 5 assembly instructions per supported spin instruction. This is not providing any room for the interpreter engine and some complex instructions such as multiply take·more than than·5 instructions to implement. If you looked at the code for the spin interpreter you would see instructions averaged 2-4 memory locations per supported spin instruction. IOW every single memory location is used by the Spin interpretor, and there simple is no room to "sneak" some user assembly onto the cog.


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.

    Post Edited (Paul Baker (Parallax)) : 5/28/2008 9:57:52 PM GMT
Sign In or Register to comment.