Propeller Tricks & Traps (Last update 21 June 2007)

1246

Comments

  • hippyhippy Posts: 1,981
    edited 2007-11-20 - 19:54:21
    Glad you mentioned muxc ... Code to save and restore C and Z flags

    Th 'flags' variable must be zeroed before use ...

    mov       flags,#0
    
    
    



    To save C and Z ...

    muxc      flags,#1       ' Save C      : ---- ---- ---- ---C
    muxnz     flags,#2       ' save NZ     : ---- ---- ---- --N-
    
    
    



    To restore C and Z, 'flags' is left unaltered ...

    shr       flags,#1 WZ, WC, NR
      
    
    
  • hippyhippy Posts: 1,981
    edited 2007-12-27 - 03:29:00
    Trick or treat ? Both; depends on what you want or expect ...

    VAR
      long longVar
      word wordVar
    
    PRI First
      wordVar := $1234_5678
      longVar := wordVar
    
    PRI second
      longVar := ( wordVar := $1234_5678 )
    
    
    



    These two are not identical in functionality when variable size differs.

    Type-size truncation does not apply to assignments within expressions, so in First the resulting value in longVar is $0000_5678, in the Second it is $1234_5678
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,624
    edited 2007-12-27 - 05:15:37
    Hmm, interesting observation! If someone had asked what to expect, a priori, from second, I'd have had to flip a coin to answer. There are equally plausible explanations for either outcome.

    -Phil
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2007-12-27 - 08:48:04
    Now what if the value used was $1234_8765 ?
    Would in the first, the long get the value $8765 (positive) or the sign extended value (because word $8765 < 0)?
    I thought SPIN had no unsigned values but after reading page 263 of the manual it looks byte and word
    are unsigned.·Does that mean we always need to insert the·sign extend operator ~~ when
    comparing types of different sizes?

    regards peter
  • BaggersBaggers Posts: 2,965
    edited 2007-12-27 - 09:25:01
    Another one, be careful checking for <0 with words, when saving space by converting variables to words, or bytes.

    say you have a variable

    mydata16 word -1

    if you want to check for it being < -1 use

    if mydata16 == $ffff

    or if you want to check for it being <0

    if mydata16 & $8000

    same with bytes

    mydata8 byte -1

    checking for -1

    if mydata8 == $ff

    or for < 0

    if mydata8 & $80

    don't forget when using signed variables,
    mydata8 range is from -128 to 127 although it's actually 0 to 127, 128 to 255=-128 to -1
    mydata16 range is from -32768 to 32767 although it's actually 0-32767, 32768 to 65535 = -32768 to -1
  • CardboardGuruCardboardGuru Posts: 443
    edited 2007-12-27 - 09:52:21
    Peter,

    As you suspect, it'd hold the value $8765 (positive). But that doesn't imply that you always need to sign extend words when comparing with bytes. If you are storing a value as a word, you're probably doing it in the full knowledge that it isn't a signed quantity.

    Think of the 3 available types as
    signed long,
    unsigned word,
    unsigned byte
    and you only need to use sign extend (or any of baggers' shortcuts) when you are breaking that convention.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Help to build the Propeller wiki - propeller.wikispaces.com
    Play Defender - Propeller version of the classic game
    Prop Room Robotics - my web store for Roomba spare parts in the UK
  • deSilvadeSilva Posts: 2,967
    edited 2007-12-27 - 10:48:57
    Hmm... In fact I would not had to "toss a coin" as Phil put it smile.gif
    After I had understood that there are NO DATA TYPES or DATA STRUCTURES in SPIN,
    most things discussed here can be expected.
    Nevertheless they are deep traps!

    Using BYTE or WORD means nothing but that whenever storing or reading such a value,
    RD/WRBYTE/WORD is used, nothig else.

    So look at Hippy's exampla:
    longVar := ( wordVar := $1234_5678 )
    (a) $1234_5678 is put into a register
    (b) This is stored with WRWORD,
    (c) This is stored with WRLONG

    Two variations (not actually checked, as I have no Propeller here...):
    longVar := ( wordVar := $1234_5678 ) + 1
    (a) $1234_5678 is put into a register
    (b) This is stored with WRWORD
    (c) 1 is added
    (d) Then i$1234_5679 is stored to longVar

    Next variation
    longVar := ( wordVar += $1234_5678 )
    (a) wordVar is read by RDWORD (initially 0)
    (b) $1234_5678 is added
    (c) This is stored with WRWORD
    (d) This is stored with WRLONG

    Whether this is a feature or a bug depends on the documentation smile.gif
    Don't transfer any of your experiences with other languages unquestioned to SPIN!

    Post Edited (deSilva) : 12/27/2007 10:53:22 AM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,624
    edited 2007-12-27 - 20:28:59
    The point of my coin flip comment was that wordVar := $1234_5678, as an expression, could be interpreted in two different ways: the value of the expression before the assignment to wordVar or the value of wordVar after the assiignment. The manual states, "As with other assignment operators, the Variable Assignment operator can be used within expressions to assign intermediate results...". Although this vaguely implies that the assignment is a mere side effect that doesn't affect the expression's value, it doesn't say so explicitly.

    -Phil
  • deSilvadeSilva Posts: 2,967
    edited 2007-12-27 - 21:35:27
    True, Phil. However this "vague implication" together with "Chip's Razor"
    ("The size of any code should never be increased beyond the barest minimum!")
    should have given you all needed clues smile.gif
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,624
    edited 2007-12-27 - 21:53:43
    True enough. I suppose another argument for the extant behavior is that it doesn't paint us into a corner. At least now, if we want the expression to be the value of the assigned variable, we have the option of writing (wordVar := $1234_5678) & $FFFF. Conversely, had the expression evaluated to wordVar when what we wanted was the full 32 bits, we'd be out of luck.

    -Phil
  • hippyhippy Posts: 1,981
    edited 2007-12-28 - 03:01:33
    Here's something I don't see document in the Propeller manual, ranges in lookup ( and lookupz )...

    a := lookup( 3 : "A" .. "C", "D" .. "F" ) ' returns "C"

    is the same as ...

    a := lookup( 3 : "A", "B", "C", "D", "E", "F" )
    a := lookup( 3 : "ABCDEF" )

    They also work in reverse ...

    a := lookup( 3 : "C" .. "A", "F" .. "D" ) ' Returns "A"

    is the same as ...

    a := lookup( 3 : "C", "B", "A", "F", "E", "D" )
    a := lookup( 3 : "CBAFED" )

    One unusual but acceptable concoction ...

    a := lookup( 4 : "ABC" .. "A" ) ' Returns "B"

    is the same as ...

    a := lookup( 4 : "ABCBA" )

    One potential trap ...

    a := lookup( 4 : "CBA" .. "A", "X" ) ' Returns "X", not "A"

    The trap is only likely to bite if using CON defined constants and the range became reduced to zero gap, eg..

    a := lookup( b : MYMIN .. MYMAX, MYMAX_PLUS_1 )
  • deSilvadeSilva Posts: 2,967
    edited 2007-12-28 - 03:23:02
    Hippy, what are you doing all the day?????
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,624
    edited 2007-12-28 - 04:06:00
    Hippy,

    Given the syntax of Spin, your examples behave in the expected way, and I don't see anything particularly disturbing there. When you use the ellipsis operator, you just have to be careful.

    I'm actually more bothered that lookup and its kin allow things like "ABCD" as arguments to begin with. It's an exception to Spin's usual syntax that blurs the distinction between lists (ordered sets) and strings (atomic elements) in a way that could impede more generalized array and string constructors in future versions. (i.e. What is a comma? Is it a list separator here or a concatenation operator?) Although it saves keystrokes and space on the line, the casual observer is going to see "ABCD" as a single atom — as it should be — and not as a disjoint list of individual characters.

    -Phil
  • deSilvadeSilva Posts: 2,967
    edited 2007-12-28 - 04:42:30
    Ah, Phil, this is very good point! What the hell is a string literal in the first place?

    You wil notice that in MOST cases it is exactly so as Hippy found out:

    address := string("ABC")
    is the same as
    address := string("A","B","C")

    BYTE "ABC"
    ist the same as
    BYTE "A", "B", "C"
  • mirrormirror Posts: 322
    edited 2007-12-28 - 04:43:19
    From the manual:

    LOOKUP ( Index : ExpressionList )
    {blah blah}
    o ExpressionList is a {blah}. Quoted strings of characters are also allowed; they are treated as a comma-separated list of characters.

    Also:

    .. Range Indicator. Indicates a range from one expression to another. {blah blah}

    So:
    a := lookup( 4 : "CBA" .. "A", "X" )

    is the same as:
    a := lookup( 4 : "C", "B", "A".."A", "X" )

    Where the range from "A" to "A" includes only 1 element.

    It's all within what's specified in the manual.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,624
    edited 2007-12-28 - 05:36:15
    I can almost accept the comma as a sort of concatenation operator in string, since you're constructing something whole out of various-sized pieces. An explicit concatenation operator would be better though. But the comma doesn't work as well in lookup when you're deconstructing big pieces ("ABC") to imply a sequence of little ones ("A", "B", "C"). And the visual congruity breaks down entirely as soon as you throw an ellipsis into the mix. For example, when you look at something like lookup(4 : "121", "123" .. "126"), what's the first thing that comes to mind? If you're like me, it isn't lookup(4 : "1211232126")! smile.gif As a matter of programming self-discipline, I would avoid mixing an ellipsis with multi-character "chunks".

    -Phil
  • hippyhippy Posts: 1,981
    edited 2007-12-28 - 06:45:49
    mirror said...
    .. Range Indicator. Indicates a range from one expression to another. {blah blah}

    It's all within what's specified in the manual.

    But it's a bit disingenuous to put in {blah blah} when, in full, p312 actually says, ".. Range indicator: indicates a range from one expression to another for CASE
    statements or an I/O register index. See OUTA, OUTB on page 280, INA, INB on page 226, and DIRA, DIRB on page 212".

    No mention of ranges in lookup ( nor lookdown ) descriptions where it would be expected to be found, nor any indication it's even available for those commands.
    deSilva said...
    Hippy, what are you doing all the day?????

    Churning out my Spin Bytecode interpreter. Slowly working my way through the opcodes and having to match functionality with what the manual says. It's a bit of a surprise when there's an opcode but no mention of how it's used smile.gif
  • hippyhippy Posts: 1,981
    edited 2007-12-28 - 06:59:14
    A more interesting issue is what one would expect the following to return ...

    a := Lookdown( 200 : 1 .. 100, 200 .. 300 )

    Is 1..100 a single group with index 1, 200..300 a single group with index 2, or does 200 have index 101 ? The answer is the later (101). I personally would have expected the former taking the above being shorthand for -

    case 200
    1 .. 100 : a:= 1
    200 .. 300 : a := 2
    other : a := 0
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,624
    edited 2007-12-28 - 07:37:33
    I don't have a problem with the two meaning entirely different things. In the lookdown example, the ellipsis (range operator) is used to create (abstractly, at least) a single "flat" list, which is then searched. That much is consistent with range operators mixed with commas in other languages (e.g. Perl). In the case construct, multiple lists are created, each one possibly having a range of choices.

    What would be interesting would be for Spin to adopt real references, so something like the following could be equivalent to your case example:

    a := lookdown(200 : [noparse][[/noparse]1 .. 100], [noparse][[/noparse]200 .. 300])
    
    
    


    Here, the [noparse][[/noparse]] is a constructor for a reference to a list, allowing each referenced list to be an atom. This makes it possible to distinguish between "flattened" lists and structured lists of lists.

    -Phil
  • hippyhippy Posts: 1,981
    edited 2007-12-29 - 12:39:39
    To swap the contents of two Cog registers without using a temporary register for storage ...

     
                        What's left in a         What's left in b
    
      xor a,b           a ^ b                    b
      xor b,a           a ^ b                    b ^ a ^ b = a
      xor a,b           a ^ b ^ a = b            a
    
    
    
  • hippyhippy Posts: 1,981
    edited 2007-12-31 - 13:00:45
    Back to assignments within expressions, and here's a potential trap when using SPR bit ranges ...

    DIRA := $33
    a := ( DIRA |= $C0 )

    DIRA := $33
    a := ( DIRA[noparse][[/noparse]7..4] |= $C )


    In both cases DIRA is set as expected, $F3.

    In the first, 'a' result is $F3, in the second 'a' result is $0F.

    In the first it passes down the result of the |= operation in the second it passes down the operand sub expression (1) result of the |= operation.

    It makes sense for 'DIRB := DIRA |= $C0' and 'DIRB[noparse][[/noparse]7..4] := DIRA[noparse][[/noparse]7..4] |= $C', but 'DIRB := DIRA[noparse][[/noparse]7..4] |= $C' will not give what may be expected.

    Edit : (1) That makes sense now, as 'a : = DIRA[noparse][[/noparse]7..4] |= $C' can be taken as ...

    tmp := DIRA[noparse][[/noparse]7..4] | $C
    DIRA [noparse][[/noparse]7..4] := tmp
    a := tmp


    Post Edited (hippy) : 12/31/2007 1:49:49 PM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,624
    edited 2007-12-31 - 17:11:55
    Hippy,

    Those observations are consistent with the rule that you sniffed out earlier for mixed precision assignments, namely: "The expression value of an intermediate assignment is the value of the expression just before the actual assignment is performed", but with additional precision now as to what "just before" means.

    Pretty soon, you'll have to attach the letters "S.P.D." after your name! (That would be "Doctor of Spin Pathology".) smile.gif

    -Phil
  • deSilvadeSilva Posts: 2,967
    edited 2007-12-31 - 19:51:23
    Phil Pilgrim (PhiPi) said...
    Those observations are consistent with the rule that you sniffed out earlier for mixed precision assignments, namely: "The expression value of an intermediate assignment is the value of the expression just before the actual assignment is performed"

    Right, that can be validated by:
    DIRA[noparse][[/noparse]0] := 1
    a := (DIRA[noparse][[/noparse]0] ^= 3)

    smile.gif
  • ViktorViktor Posts: 2
    edited 2008-02-10 - 10:19:28
    Gooday
    As I'm enjoying learning spin from·propeller manual I find difficult exercise to
    sort out for me
    exercise 7 and 8 will not compile ,
    I'm attaching file with exercise also image of outcome after I peas F10 or
    11
    Please help me with sorting this problem
    Kind regards
    Viktor
  • Nick MuellerNick Mueller Posts: 815
    edited 2008-02-10 - 10:26:44
    > Please help me with sorting this problem

    No "while" statement in SPIN


    Nick

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Never use force, just go for a bigger hammer!

    The DIY Digital-Readout for mills, lathes etc.:
    YADRO
  • ViktorViktor Posts: 2
    edited 2008-02-10 - 10:47:12
    Check propeller manual v1.0 page 118 and 124
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 22,624
    edited 2008-02-10 - 10:51:21
    It's an indentation problem.
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-10 - 11:09:50
    As this is not really something for this more technical thread, the curt answers of Nick and Phil are understandable..

    You see: REPEAT and WHILE (or UNTIL) have to match in a rejecting loop, in the same way as IF and ELSE. The compiler does not mind when you shift it a little bit to the right but NEVER to the left.

    So indent your WHILE one space more and everything will be fne..
  • Nick MuellerNick Mueller Posts: 815
    edited 2008-02-10 - 11:24:45
    > So indent your WHILE one space more and everything will be fne..

    Not just that. smile.gif


    Nick

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Never use force, just go for a bigger hammer!

    The DIY Digital-Readout for mills, lathes etc.:
    YADRO
  • deSilvadeSilva Posts: 2,967
    edited 2008-02-10 - 11:46:48
    *sigh*
    Well, WAITCNT as well...
Sign In or Register to comment.