Shop OBEX P1 Docs P2 Docs Learn Events
mov difficulties — Parallax Forums

mov difficulties

william chanwilliam chan Posts: 1,326
edited 2008-10-07 12:39 in Propeller 1
I don't know why

CON led_pin = 1

DAT
mov   dira,  (|< led_pin & $1FF)




does not work.

Instead I have to use

CON led_pin = 1

DAT
mov   dira,led_mask

led_mask   long     |< led_pin




in the process wasting one long.

Any ideas?

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.fd.com.my
www.mercedes.com.my

Comments

  • tpw_mantpw_man Posts: 276
    edited 2008-10-06 00:54
    You must use mov dira, #(|< led_pin & $1FF). That puts an absolute value into dira. Your code basically tells the cog to move the contents of the register (|< led_pin & $1FF) (aka 2) into dira.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    I am 1011, so be surprised!


    Advertisement sponsored by dfletch:
    Come and join us on the Propeller IRC channel for fast and easy help!
    Channel: #propeller
    Server: irc.freenode.net or freenode.net
    If you don't want to bother installing an IRC client, use Mibbit. www.mibbit.com
    tongue.gif
  • william chanwilliam chan Posts: 1,326
    edited 2008-10-06 01:13
    if
    CON
    led_pin = 28
    
    



    then it wouldn't work right because of the $1FF limitation for mov with a literal as a source.

    How to go about it in such a case?

    Thanks.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.fd.com.my
    www.mercedes.com.my
  • potatoheadpotatohead Posts: 10,261
    edited 2008-10-06 02:04
    You have to use one of the longs then.

    It's not really wasting it, if you use that long for more than one thing. There are a coupla approaches to this.

    One is to dedicate a long for each purpose. If there are a lot of purposes, this can get costly in terms of longs. Having to balance total number of instructions with temp pointer storage is just what happens in PASM. This is the easiest, but most wasteful. If your PASM routine does not contain all that many instructions, do it! Wasted or not, you are running the whole COG either way, so why fight for the smallest space when it won't matter all that much?

    (there is a reason and that is overall program length. Doing this for a lot of PASM routines can consume lots of HUB memory that isn't getting used by SPIN or for holding working variables.)

    Another approach is to call out a few working longs as registers. Think of these like registers on more ordinary CPU's. On those kinds of chips, there are only so many of those and that leads to working through code such that they are used well.

    So:

    A long 0
    B long 0
    C long 0

    ...etc. I like to start with three, then add one if and only if I'm in a spot where I just have to have more than three temporary working longs.

    You then use these when you need temporary storage to perform an operation, hold a mask, point to a location in memory. Using the letters is short and sweet. If you need one temp, that's A. Two is B, three C and so on. As you are coding, you consume temps, reusing them as soon as you know their value is no longer important. Use the comments to note where a given long needs to remain untouched. One easy strategy is to list the temp longs consumed by a given subroutine, or block of code. Use the find function to track which are used where, if you are looking for one.

    Before dedicating more than three temps, walk through your code to make darn sure you can't reuse one first. This is also nice because it gets easy to see where working longs are being used. When you see a simple letter, instead of a descriptive label, then it's a throwaway long to be placed first on the list for re-use, should it come up.

    One other approach is to use your init (starting or setup) code for temp storage once the COG assembly routine is up and running. This one is nice because there is often some instructions that only get executed once per COGNEW. So, do that, and label them with the letters as above. Once you have got your init stuff done, they are then working variables and no longs are wasted.

    A mov destination, source
    B add operand1, $30
    ... etc.

    I like this one because it shifts the balance to more instructions. Very useful in a tight COG situation.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Wiki: Share the coolness!

    Chat in real time with other Propellerheads on IRC #propeller @ freenode.net

    Post Edited (potatohead) : 10/6/2008 2:14:44 AM GMT
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2008-10-06 02:11
    William,

    In the general case, the second example in your first post is the correct way. There's no way to shorten it if pins above A8 can be involved. So the long isn't really wasted. It's required as a consequence of the Propeller's architecture.

    -Phil

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    'Still some PropSTICK Kit bare PCBs left!
  • heaterheater Posts: 3,370
    edited 2008-10-06 07:13
    In general I would advice against using such short names, A, B, C or i, j, k etc for temporary variables.
    As potatohead said "walk through your code to make darn sure you can't reuse one first". This is much easier if you use longer meaning full names that you can search for with the edit->find.

    So use something like "temp_a" or reg_x" etc. This also reminds you later that these things are shared/temporary and should be treated carefully.

    Of course meaning full names should be used for all other variables as well.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • potatoheadpotatohead Posts: 10,261
    edited 2008-10-07 02:12
    Agreed. This is a throwback of mine, related to registers being letters on older CPU's. Just kind of used to it.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Wiki: Share the coolness!

    Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
  • william chanwilliam chan Posts: 1,326
    edited 2008-10-07 10:05
    I am disturbed about the Propeller not having any SET or CLR commands.

    I am also surprised that
    mov    outa, #0
    
    



    will only clear P0 to P8 but not the higher pins.

    Isn't there an easier way to clear or set some pins like the SX without using a LONG mask each time?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.fd.com.my
    www.mercedes.com.my
  • hippyhippy Posts: 1,981
    edited 2008-10-07 10:13
    "mov outa,#0" does clear all pins.

    You can set or clear some pins without using an extra long; when those pins are P0 to P8 the 'mask' can be held in the instruction. Example, "or outa,#$1FF" will set pins P0 to P8 inclusive, "andn outa,#$1FF" will clear P0 to P8.

    If your 'mask' needs to access pins P9 to P31 you either need to use a long containing the mask or calculate the mask at run-time.

    There are no explicit SET or CLR instructions but they can both be replicated using OR or ANDN.
  • hippyhippy Posts: 1,981
    edited 2008-10-07 10:23
    On the notion that the Propeller 'wastes longs' that's not entirely correct, but it can appear that way because they have to be explicitly defined in PASM.

    A traditional 8-bit microcontroller may have an instruction set which allows "MOV OUTA,#$FF" through to "MOV OUTA,#$FFFF_FFFF" but as the immediate operand cannot usually be stored in the opcode field itself ( usually 8-bits ), additional bytes are required to hold the operand. The difference there is that you do not need to explicitly allocate those bytes, whereas with PASM you do, and you cannot allocate single bytes, only 32-bit registers / cells / cog memory locations to hold the operand data.

    The 8-bit example is still allocating extra storage for the operand, in PASM you need to do that yourself with "an additional long".

    If this 8-bit example had two "MOV OUTA,#$FFFF_FFFF" instructions, it would have added 8 bytes for the operands in total, in PASM you only need one long ( 4 bytes ), so the way PASM does it is no worse, and often better than the alternative.

    Post Edited (hippy) : 10/7/2008 10:31:56 AM GMT
  • william chanwilliam chan Posts: 1,326
    edited 2008-10-07 12:04
    Hippy,

    Are you sure that

    "mov outa,#0"

    really clear all pins P0-P31 inclusive?
    How can that be since the source field can only store 9 bits?

    Is it better to

    "or outa,#$1FF"

    or

    "mov outa,#1FF"

    ?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    www.fd.com.my
    www.mercedes.com.my
  • hippyhippy Posts: 1,981
    edited 2008-10-07 12:39
    william chan said...
    Hippy,

    Are you sure that

    "mov outa,#0"

    really clear all pins P0-P31 inclusive?
    How can that be since the source field can only store 9 bits?

    Definitely sure. The operand is expanded to 32-bits before being applied. It works the same way on the Special Purpose Registers ( DIRA, OUTA etc ) as it would with any other other register.
    william chan said...

    Is it better to

    "or outa,#$1FF"

    or

    "mov outa,#1FF"

    ?

    They are not equivalent so there is no better. The OR will set only P0 to P8 leaving P9 to P31 as they were. The MOV will set P0 to P8 and clear P9 to P31.
Sign In or Register to comment.