Shop OBEX P1 Docs P2 Docs Learn Events
SFUNC question - Page 5 — Parallax Forums

SFUNC question

1235713

Comments

  • jmgjmg Posts: 15,173
    cgracey wrote: »
    These new instructions take about the same number of gates as the old ones did.

    Wow... really, Wahoo !!!!!
    I was worried these may carry a cost...

    This change will free a lot of COG memory, which is the most constrained resource in P2.
    It also makes PLC type control operations easier to code, and smaller and faster...
    cgracey wrote: »
    I figured we could use "\" to separate the register and bit number for bit addresses. This allows a comma to separate the flag operand.
    That reads like it could be an operation, but I can understand multiple commas is less than ideal.

    If you want a separator, why not just use the existing convention, which is a decimal point ?
    (This also follows HLL conventions for record extraction)

    ie Register.BitNumber is the common way this detail is managed on 8051 & others, and usually Boolean Vars are declared
    like this
    RED_LED_P12     BIT     P1.2    
    RED_LED_P12     BIT     BitAdrReg.Number    
    
    and then that clear single boolean name is used, as in
    MOVB    CF, RED_LED_P12
    
    so there is usually no separator visible in the code, but this is also legal in P2
    MOVB    CF, INB.12
    MOVB    CF, INB.BitPointer
    


  • RaymanRayman Posts: 14,643
    Maybe use _C and _NC instead of CF and !CF?
  • We're already using \ to signal absolute/relative jumps (unless you've taken the suggestion that different mnemonics be used for those)? Could we find something else to separate the D and S, like forward slash or colon? Or even writing D[#1] (which would kind of follow the OUTA[] syntax)?
  • jmgjmg Posts: 15,173
    edited 2017-05-01 20:25
    ersmith wrote: »
    We're already using \ to signal absolute/relative jumps (unless you've taken the suggestion that different mnemonics be used for those)? Could we find something else to separate the D and S, like forward slash or colon? Or even writing D[#1] (which would kind of follow the OUTA[] syntax)?
    I'm lukewarm on \ too, but understand Chip's desire to avoid comma, see my post above (when it arrives via the forum queue...)
    The existing convention out there, is a decimal point separator, easiest to just use that.

  • jmgjmg Posts: 15,173
    Rayman wrote: »
    Maybe use _C and _NC instead of CF and !CF?
    Some have an aversion to _, and it does need multiple fingers...

    I'm fine with the simple C and Z, as they are going to be used a lot, and I recall a Prof, who marked down anyone who used single-variable letters as names.... :)

    Also note, the form is not just not-carry, but not-bit is allowed too, which requires some 'not prefix'.

    !CF is also fine, tho if I were writing the assembler, I'd also include the likely candidates of ~BitName and NOT Bitname
    NOT will likely already be supported in boolean expression evaluation in HLL

  • jmg wrote: »
    TonyB wrote: »
    Some of those instructions looks overcomplicated to me. How about:
    Err, no...
    The B suffix operators are ALL BOOLEAN ones, that take a BIT variable
    CF and ZF are simply reserved special case boolean locations.

    Far from being 'overcomplicated', this is actually a very simple subgroup.

    ADDC on the other hand, ADDs a 32b operand with carry, and includes the carry flag in the operator.
    ie Very different, and it would be confusing to try to merge the two semantics.

    This will all be clearer when Chip adds the operation equations to the mnemonics.


    Yes, The fact that these are bit operations is more important and relevant
    jmg wrote: »
    cgracey wrote: »
    These new instructions take about the same number of gates as the old ones did.

    Wow... really, Wahoo !!!!!
    I was worried these may carry a cost...

    This change will free a lot of COG memory, which is the most constrained resource in P2.
    It also makes PLC type control operations easier to code, and smaller and faster...
    cgracey wrote: »
    I figured we could use "\" to separate the register and bit number for bit addresses. This allows a comma to separate the flag operand.
    That reads like it could be an operation, but I can understand multiple commas is less than ideal.

    If you want a separator, why not just use the existing convention, which is a decimal point ?
    (This also follows HLL conventions for record extraction)

    ie Register.BitNumber is the common way this detail is managed on 8051 & others, and usually Boolean Vars are declared
    like this
    RED_LED_P12     BIT     P1.2    
    RED_LED_P12     BIT     BitAdrReg.Number    
    
    and then that clear single boolean name is used, as in
    MOVB    CF, RED_LED_P12
    
    so there is usually no separator visible in the code, but this is also legal in P2
    MOVB    CF, INB.12
    MOVB    CF, INB.BitPointer
    


    I think the decimal convention should be followed here; it's common practice elsewhere and there's no chance of it being confused for a float operation.

    For the toolset, it might be worth considering a simple method of packing multiple bit variables into a single long without the programmer making the bit allocations directly.
  • jmgjmg Posts: 15,173
    AJL wrote: »
    ...
    For the toolset, it might be worth considering a simple method of packing multiple bit variables into a single long without the programmer making the bit allocations directly.
    Yes, that's a good idea, so I checked what the 8051 Assembler here allows, this format seems ok
                                    dseg at 0020h
    0020            BBa0:           ds      1        ; Bits 0..7
    0021            VComCtr:        ds      1        ; Bits 8..f
                    ;OneMore:        ds      1       ; check bseg moves ?
    0022            BifFieldsBase:  ds      1        ; Start of Boolean base
    B 00            Reverse         BIT     BBa0.0
                   
                    ;                bseg at (BifFieldsBase-20H)*8   ; Works, for correct 10h,11h
                                    bseg at BifFieldsBase.0   ; cleaner, 10h,11h correct
    0010            bseg_f:   dbit      1
    0011            bseg_s:   dbit      1
    0012            bseg_t:   dbit      1
    0157  D2 10             SETB    bseg_f
    0159  B2 11             CPL     bseg_s
    
    Seems that can "pack multiple bit variables into a multiple bytes single long without the programmer making the bit allocations directly".

    Pushing it further with this more complex test ....
                    ;                bseg at (BifFieldsBase-20H)*8   ; Works, for correct 10h,11h
                                    bseg at BifFieldsBase.0   ; cleaner, 10h,11h correct
    0010            bseg_f:    dbit      1
    0011            bseg_s:    dbit      2
    0013            bseg_t:    dbit      3
    0016            bseg_o6:   dbit      1
    0017            bseg_o7:   dbit      1
    0018            bseg_o8:   dbit      1
    0019            bseg_o9:   dbit      1
                                    dseg
    0023            AddByte:       ds      1  ; ideally, this should bump to 24h, as we've allocated more than 8bits
                                    bseg   ; back to BIT level
    001A            bseg_oA:    dbit      1  ;does go back and fill in bseg bits..
    
    
    It's not quite clever enough to auto-preserve a gap across booleans, for the next ds byte, but 8051 users typically code dseg clear of the boolean fields, as in the 8051 this is just a small subset of the memory map.
    P2 is this on steroids, and allows ANY register to be boolean field, so it is more likely to mix long/boolean allocates.

    This manual workaround does work, at keeping differing sizes correctly bumped..
    0019            bseg_o9:   dbit      1
    = 19            last_bit  SET  bseg_o9
                                    dseg at 20H+((last_bit OR 0x7)+1)/8  ;Manually round UP to next Free Byte
    0024            AddByte:       ds      1   ; now bumps to 24h
                                    bseg   ; back to BIT level
    001A            bseg_oA:    dbit      1  ; back-fills with no ORG 
    

    This flow back-fills free booleans, if someone did want to avoid that, because they were also operating on whole longs, they can add packers.
  • TonyBTonyB Posts: 73
    edited 2017-05-02 00:13
    I much prefer "." to "\".

    If C and Z and NC and NZ cannot be reserved words, could NCF and NZF be used instead of !CF and !ZF? This would avoid an annoying key shift and besides it's if_nc_ and if_nz_ and djnz, not if_!c_ and if_!z_ and dj!z.

    Nobody's mentioned the unused instruction:
    CCCC 0101110 CZI DDDDDDDDD SSSSSSSSS        ANYB    D,S/#       {WC,WZ}
    CCCC 0101111 CZI DDDDDDDDD SSSSSSSSS        <empty> D,S/#       {WC,WZ}
    

    The option of last-resort:
    CCCC 0101110 CZI DDDDDDDDD SSSSSSSSS        ANYBZ   D,S/#       {WC,WZ}
    CCCC 0101111 CZI DDDDDDDDD SSSSSSSSS        ANYBNZ  D,S/#       {WC,WZ}
    
  • cgraceycgracey Posts: 14,152
    edited 2017-05-02 00:51
    We can use "." instead of "\". I like "." better, too, but I was worried about the parser seeing something like 100.100 (being register 100). I think it ignores "." for PASM.

    Check this out. This is all the Verilog it took to realize all the register.bit/flag instructions:
    // clrb/setb/notb/rndb / movb/andb/orb/xorb
    
    wire [31:0] bit_m	= 32'b1 << s[4:0];
    
    wire bit_in		= |(d & bit_m);
    
    wire bit_d		= i[i0] ? i[wc] ? z : c
    				: bit_in;
    
    wire bit_s		= (i[i0] ? bit_in
    				 : i[wc] ? z : c) ^ i[wz];
    
    wire [3:0] bit_una	= { rnd,	// rndb
    			    !bit_in,	// notb
    			    1'b1,	// setb
    			    1'b0 };	// clrb
    
    wire [3:0] bit_bin	= { bit_d ^  bit_s,	// xorb
    			    bit_d || bit_s,	// orb
    			    bit_d && bit_s,	// andb
    			    bit_s };		// movb
    
    wire bit_out		= i[i3] ? bit_bin[i[i2:i1]]
    				: bit_una[{i[i0], i[wz]}];
    
    wire [33:0] bit_czr	= {bit_out, bit_out, d & ~bit_m | {32{bit_out}} & bit_m};
    

    Because the logic here mainly deals with one bit, instead of 32, the resource usage is very low. Maybe only two LE's more than before.
  • jmgjmg Posts: 15,173
    cgracey wrote: »
    We can use "." instead of "\". I like "." better, too, but I was worried about the parser seeing something like 100.100 (being register 100). I think it ignores "." for PASM..
    Cool, the context can be managed fine I think...
    cgracey wrote: »
    Check this out. This is all the Verilog it took to realize all the register.bit/flag instructions:
    // clrb/setb/notb/rndb / movb/andb/orb/xorb
    
    wire [31:0] bit_m	= 32'b1 << s[4:0];
    
    wire bit_in		= |(d & bit_m);
    
    wire bit_d		= i[i0] ? i[wc] ? z : c
    				: bit_in;
    
    wire bit_s		= (i[i0] ? bit_in
    				 : i[wc] ? z : c) ^ i[wz];
    
    wire [3:0] bit_una	= { rnd,	// rndb
    			    !bit_in	// notb
    			    1'b1,	// setb
    			    1'b0 };	// clrb
    
    wire [3:0] bit_bin	= { bit_d ^  bit_s,	// xorb
    			    bit_d || bit_s,	// orb
    			    bit_d && bit_s,	// andb
    			    bit_s };		// movb
    
    wire bit_out		= i[i3] ? bit_bin
    				: bit_una;
    
    wire [33:0] bit_czr	= {bit_out, bit_out, d & ~bit_m | {32{bit_out}} & bit_m};
    

    Because the logic here mainly deals with one bit, instead of 32, the resource usage is very low. Maybe only two LE's more than before.

    Wow :)
    Easier to code than it is to explain, and compact as a bonus ! Whodathunk...?

  • jmgjmg Posts: 15,173
    TonyB wrote: »

    If C and Z and NC and NZ cannot be reserved words, could NCF and NZF be used instead of !CF and !ZF? This would avoid an annoying key shift and besides it's if_nc_ and if_nz_ and djnz, not if_!c_ and if_!z_ and dj!z.
    A problem with that, is there is also !BitName to support. The NOT operator is not just not-zero or not-carry.

    I'd be fine with
    MOVB BitName, NOT C
    MOVB C, NOT BitName
    as an alias to
    MOVB BitName, !C
    MOVB C, !BitName


    The NOT-BIT case is used rather infrequently in most code, so does not need to be super compact. C,Z are much more commonly used.
  • cgraceycgracey Posts: 14,152
    I had an error in the Verilog above. I had forgotten the selectors on the 'bit_out' logic:
    wire bit_out		= i[i3] ? bit_bin[i[i2:i1]]
    				: bit_una[{i[i0], i[wz]}];
    
  • jmg wrote: »
    TonyB wrote: »

    If C and Z and NC and NZ cannot be reserved words, could NCF and NZF be used instead of !CF and !ZF? This would avoid an annoying key shift and besides it's if_nc_ and if_nz_ and djnz, not if_!c_ and if_!z_ and dj!z.
    A problem with that, is there is also !BitName to support. The NOT operator is not just not-zero or not-carry.

    I'd be fine with
    MOVB BitName, NOT C
    MOVB C, NOT BitName
    as an alias to
    MOVB BitName, !C
    MOVB C, !BitName

    The NOT-BIT case is used rather infrequently in most code, so does not need to be super compact. C,Z are much more commonly used.

    Must use CF if C not reserved. NOT CF instead of NCF would be plain silly, thus:

    MOVB BitName, NCF
    MOVB CF, NOT BitName

    although

    MOVB BitName, NC
    MOVB C, NOT BitName

    looks so much nicer. And no !'s.



  • jmgjmg Posts: 15,173
    TonyB wrote: »
    ...
    although

    MOVB BitName, NC
    MOVB C, NOT BitName

    looks so much nicer. And no !'s.
    Oh, yes, NC could be an alias for NOT C (likewise for NZ equiv to NOT Z ), where valid to use.

  • cgracey wrote: »
    I forgot to mention that there are other intra-flag operations like:
    XORB    CF,!ZF
    ANDB    ZF,CF
    NOTB    CF
    

    A few questions:

    Isn't it either CF or ZF but never both together?
    How do CLRB/SETB/NOTB/RNDB affect C? (They can't affect Z.)
    Is RNDB a random bit?
  • jmgjmg Posts: 15,173
    TonyB wrote: »
    cgracey wrote: »
    I forgot to mention that there are other intra-flag operations like:
    XORB    CF,!ZF
    ANDB    ZF,CF
    NOTB    CF
    

    A few questions:

    Isn't it either CF or ZF but never both together?
    What do you mean 'never both together' ?
    All the above is valid code
    TonyB wrote: »
    How do CLRB/SETB/NOTB/RNDB affect C? (They can't affect Z.)
    They can affect Z, when Z is a destination ;)
    Boolean OPs are atomic, they have no effect on C, unless C is the explicit destination.

    TonyB wrote: »
    Is RNDB a random bit?
    AFAIK, yes.

  • cgraceycgracey Posts: 14,152
    edited 2017-05-02 02:07
    What about using these for the flags?
    CFLAG
    ZFLAG
    

    Those are unmistakable.

    I kind of like the "!", though:
    MOVB    reg.#bit, !CFLAG"
    

    No, that's not great, either.

    The big problem is that a source operand may be NOT'd. Spelling out NOT is kind of ugly, and "!" isn't much better. The destination operand cannot be NOT'd.

    We could handle this like AND/ANDN and TEST/TESTN, where the N signifies that the source operand is NOT'd. Then, we have no need for NOT/! and we can get by with CF, ZF, and REG.{#}BIT:
    MOVB    CF, ZF
    MOVBN   CF, ZF
    ANDBN   reg.#bit, CF
    XORBN   ZF, reg.bit
    

    How would that be?

    Or, using big names:
    MOVB    CFLAG, ZFLAG
    MOVBN   CFLAG, ZFLAG
    ANDBN   reg.#bit, CFLAG
    XORBN   ZFLAG, reg.bit
    

  • cgracey wrote: »
    MOVB    CF, ZF
    MOVBN   CF, ZF
    ANDBN   reg.#bit, CF
    XORBN   ZF, reg.bit
    
    I like this one the best.
  • cgraceycgracey Posts: 14,152
    ozpropdev wrote: »
    cgracey wrote: »
    MOVB    CF, ZF
    MOVBN   CF, ZF
    ANDBN   reg.#bit, CF
    XORBN   ZF, reg.bit
    
    I like this one the best.

    It keeps the syntax sane.
  • Agreed. I've no problem with "!", btw
  • jmgjmg Posts: 15,173
    edited 2017-05-02 02:26
    cgracey wrote: »

    We could handle this like AND/ANDN and TEST/TESTN, where the N signifies that the source operand is NOT'd. Then, we have no need for NOT/! and we can get by with CF, ZF, and REG.{#}BIT:
    MOVB    CF, ZF
    MOVBN   CF, ZF
    ANDBN   reg.#bit, CF
    XORBN   ZF, reg.bit
    

    How would that be?

    yeah, I played with that, but the problem here is which boolean does the NOT apply to, and when is the NOT applied ?
    ie it could mean any of these... :(
    CF = NOT(BitVar AND CF)
    or
    CF = BitVar AND NOT CF
    or
    CF = (NOT BitVar) AND CF
    A trip to the manual is required each time..
    cgracey wrote: »
    What about using these for the flags?
    CFLAG
    ZFLAG
    

    Those are unmistakable.
    Yes, true, but they are also quite long...

    To me, long names 'say' user-generated, and very short ones like C and Z 'say' system reserved.

    I guess users can always do something like this to alias the names....
    C BIT CFLAG
    Z BIT ZFLAG

    this should be legal in the tools... ?
    cgracey wrote: »
    The big problem is that a source operand may be NOT'd. Spelling out NOT is kind of ugly, and "!" isn't much better. The destination operand cannot be NOT'd.
    I don't mind NOT, as it is common in HLL's, and your eye scans it quickly.
    Support a choice of either ! or NOT symbols should keep those who hate typing, and like glyphs happy, and NOT for those more used to reading English...?

    There is also NC as natural alias of NOT C, !C (& NZ) as was suggested above, which makes NOT, ! really apply only to BitVar inversion.. ie pushing to rarer cases.
    Someone should be allowed to use NOT C, even if NC is allowed.



  • potatohead wrote: »
    I've no problem with "!", btw
    +1
    ! ties in with SPIN too.

  • cgraceycgracey Posts: 14,152
    Jmg,

    The TEST/TESTN instructions vary by an internally-NOT'd S. Same with AND/ANDN. Do you think those are reasonable?
  • jmgjmg Posts: 15,173
    edited 2017-05-02 02:30
    cgracey wrote: »
    ozpropdev wrote: »
    cgracey wrote: »
    MOVB    CF, ZF
    MOVBN   CF, ZF
    ANDBN   reg.#bit, CF
    XORBN   ZF, reg.bit
    
    I like this one the best.

    It keeps the syntax sane.
    Not really, see my post above..
    It reads literally as AND BIT NOT DestBit, SourceBit, so is actually quite confusing

  • ozpropdev wrote: »
    potatohead wrote: »
    I've no problem with "!", btw
    +1
    ! ties in with SPIN too.

    yup, and given they are one thing basically, it's important we keep perspective on that.

    I totally vote for "!" being NOT. It's not like people are gonna type that a bazillion times.

  • jmgjmg Posts: 15,173
    cgracey wrote: »
    Jmg,

    The TEST/TESTN instructions vary by an internally-NOT'd S. Same with AND/ANDN. Do you think those are reasonable?

    To me they are sub-optimal, as the detail of which operand is inverted, & when, is not visible from simply reading the source.

    The benefit of the clear and explicit !,NOT is anyone can read code, and know what is being applied when.

    Programmers coming from FreeBASIC & variants, all the Wirth Languages, and PLC IEC 61131 will be used to scanning NOT in their source code.
  • Cluso99Cluso99 Posts: 18,069
    IMHO, ! Isn't assembler syntax.

    I don't mind CF & ZF or C & Z for that matter or NC & NZ either.

    If it's MOVBN, ANDBN etc MOVNB, ANDNB, etc makes more sense to me.

    But its not that important now. The instructions are there which is the main part.

    A lot has been added. Hope this isn't the last straw !?!?

  • jmgjmg Posts: 15,173
    edited 2017-05-02 04:24
    As reference, here is how a C compiler with BIT support, handles things on a MCU with Boolean Opcodes
                LED0 = !LED0;        //   P2 Version?         Alternate P2 code?
    00000041:   CPL     P1.4              NOTB    OUTA.4
     79             LED0 = ~LED0;
    00000043:   CPL     P1.4
     80             LED1 = LED2 & !LED1;
    00000045:   MOV     C, P1.6           MOVB    C,INA.6 
    00000047:   ANL     C, /P1.5          ANDB    C,!INA.5 
    00000049:   MOV     P1.5, C           MOVB    OUTA.5,C    OUTC    OUTA.5
     81             LED2 = LED2 | !LED1;
    0000004b:   MOV     C, P1.6           MOVB    C,INA.6 
    0000004d:   ORL     C, /P1.5          ORB     C,~INA.5    ORB     C,NOT INA.5 
    0000004f:   MOV     P1.6, C           MOVB    OUTA.6,C
    
    
    (added P2 syntax columns)

    Notice
    * The compiler tolerates both ! and ~ forms here
    * The code uses the BIT operators in all cases, including
    * NOT bit is managed with a char prefix, on the source char, in ASM.
    The / is intel's choice (decades ago), I would have chosen ! or ~ in 2017

  • jmgjmg Posts: 15,173
    Cluso99 wrote: »
    But its not that important now. The instructions are there which is the main part.
    Yes.
    Cluso99 wrote: »
    A lot has been added. Hope this isn't the last straw !?!?
    Chip said this
    "Because the logic here mainly deals with one bit, instead of 32, the resource usage is very low. Maybe only two LE's more than before."
    so it seems a lot of flexibility came, at very low cost.

    There seems to be some overlap now, with OUTxx, DIRxx opcodes and new.improved MOVB/SETB/CLRB/NOTB as they can have OUT and DIR as destinations ?
    (tho the former also update C,Z with INA, that seems a rare use ? )
  • cgraceycgracey Posts: 14,152
    That overlap is superficial, since the OUTx/DIRx instructions automatically index between port A and B. In other words, you only need the pin number.
Sign In or Register to comment.