Shop OBEX P1 Docs P2 Docs Learn Events
C after CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX - Page 2 — Parallax Forums

C after CMPS/CMPSX/ADDS/ADDSX/SUBS/SUBSX

2456

Comments

  • TonyB_TonyB_ Posts: 2,105
    edited 2017-10-04 22:39
    deleted
  • Could we just get some hardware done, please? There's always *something* that could be improved. I have to suggest that the fact that nobody raised the issue during the lifetime of the P1 indicates that the exact behavior of C after ADDS/SUBS really isn't a very big deal. I suspect this is because virtually everyone dealing with multi-word numbers uses the unsigned version of the instructions, and maintains a separate sign bit. That's certainly what the IEEE double libraries in PropGCC do.

    (Sorry to come across as snide, I do understand the desire to make everything as good as possible... but at some point we do have to say "enough is enough".)

    Eric
  • cgraceycgracey Posts: 14,133
    Eric, we are waiting for OnSemi to get back to us about when the synthesis can begin. At this moment, we have everything ready to go for them. I'm spending my time on the interpreter code, as it's part of the tool we'll provide. That's where we're at, right now.
  • TonyB_TonyB_ Posts: 2,105
    edited 2017-10-04 22:39
    deleted
  • msrobots wrote: »
    @TonyB

    finally I got it. I read the document, pointed to by @Rayman, but still struggled with the idea. Hmm English is my third language, I am quite bad at it.

    Yes, I like it and if I find some more longs in BigInt-Pasm I will use it. Having different sized Operants is part of BigInts and I was looking for some way to notify when out of bounds.

    I still think that distinguishing signed and not signed operations should be enough to zero or sign extend values. I do not see the need for extra instructions to do this.

    maybe I am wrong there too, so please correct me if you have time...

    Mike

    Mike,

    I think the question you are asking is why do the P1 & P2 have two sets of arithmetic instructions, one for signed values and another for unsigned values? The answer is the P1 & P2 have only two flags and it is not possible for two flags to indicate zero, carry and overflow at the same time.

    The only difference between ADD and ADDS, for example, is what the flags indicate - the adding logic is identical for both. ADD flags zero and carry, while ADDS flags zero and overflow (or zero and sign and overflow if my idea is accepted).

    Other microprocessors have only one set of add/subtract/compare instructions because they have more than two flags: zero, carry, overflow, sign, parity, etc.
  • cgraceycgracey Posts: 14,133
    TonyB_,

    One thing that I've been thinking about regarding your idea is that to know for sure if you have a 'zero' result, you cannot rely on Z, alone. You must affect C and Z. It is very common when doing range comparisons that you only want C to indicate 'borrow', as Z might be used for some other purpose within the code sequence. I've been writing a lot of code like this, lately. I like that one flag will have my answer and I can use the other for some other purpose, intertwined through the sequence. I think this kind of usage is more important than sensing underflow/overflow, which is what that otherwise-nonsensical C/Z combo would indicate. For that reason, I'm not really wanting to make this change. I think it is very clever, but in the case of the Prop2, it would be an inhibitor to super-efficient programming.
  • I stumbled also over this. I often carefully preserve the actual flag state over a couple of instructions, or a loop.then later on act on it.

    Sometimes I even need to 'preserve' the flags temporary in some location and restore them after a call into some subroutine. I did check BigInts, but think I will just put a overflow flag in there.

    As longer I look at your Interpreter-examples, as more they look to me like conditional execute on steroids. What I do no really like is the use of the comment area to visualize what happens. It works, but it is a ugly kludge. And "to use it to auto generate the needed bitmask" is IMHO a felony.

    Basically that information belongs between labels and conditions, we need just one tab column more. It does NOT belong into the comment section

    instead of
    mov_fil		popa	y		'	a b c d e f	pop src/val		a: BYTEMOVE
    		popa	z		'	a b c d e f	pop dst			b: WORDMOVE
    					'						c: LONGMOVE
    		tjz	x,#.exit	'	a b c d e f	if cnt=0, exit
    					'						d: BYTEFILL
    		shl	x,#1		'	| b | | e |	if word, cnt*2		e: WORDFILL
    		shl	x,#2		'	| | c | | f	if long, cnt*4		f: LONGFILL
    
    		cmp	y,z	wc	'	a b c | | |	reverse move?
    	if_c	add	y,x		'	a b c | | |
    	if_c	add	z,x		'	a b c | | |
    
    something like
    mov_fil abcdef          popa y          '                       pop src/val             a: BYTEMOVE
            abcdef          popa z          '                       pop dst                 b: WORDMOVE
                                            '                                               c: LONGMOVE
            abcdef          tjz x,#.exit    '                       if cnt=0, exit
                                            '                                               d: BYTEFILL
            |b||e|          shl x,#1        '                       if word, cnt*2          e: WORDFILL
            ||c||f          shl x,#2        '                       if long, cnt*4          f: LONGFILL
    
            abc|||          cmp y,z wc      '                       reverse move?
            abc|||  if_c    add y,x         '       
            abc|||  if_c    add z,x         '      
    

    making visible conditionals out of it, gives the opportunity for a smarter IDE to either generate/change/highlight the conditional-labels when given a bitmask or create the bitmasks when given the labels.

    As seen in all you examples this needs to be typed in anyways to follow the execution flow, so make it part of the language, not the comments.

    Enjoy!

    Mike


  • TonyB_TonyB_ Posts: 2,105
    edited 2017-10-04 22:38
    Chip, I respect and accept your decision, whatever it maybe.

    It's not clear to me where we are now with these signed instructions. For range comparisons, wouldn't you use CMPS/CMPSX? Overflow is irrelevant here as the result is discarded, so Z really means zero, C means less than/negative (i.e. sign flag) and C & Z never occurs.

    If C & Z for overflow/underflow in ADDS/ADDSX/SUBS/SUBSX is considered to be a waste of a flag, a point of view I understand completely, then surely C by itself must indicate overflow?

    EDIT
    ADDS/ADDSX/SUBS/SUBSX in v21 are fine. Please see this later post:
    http://forums.parallax.com/discussion/comment/1421463/#Comment_1421463
  • jmgjmg Posts: 15,140
    msrobots wrote: »
    ... What I do no really like is the use of the comment area to visualize what happens. It works, but it is a ugly kludge.
    And "to use it to auto generate the needed bitmask" is IMHO a felony.

    Basically that information belongs between labels and conditions, we need just one tab column more. It does NOT belong into the comment section

    making visible conditionals out of it, gives the opportunity for a smarter IDE to either generate/change/highlight the conditional-labels when given a bitmask or create the bitmasks when given the labels.

    As seen in all you examples this needs to be typed in anyways to follow the execution flow, so make it part of the language, not the comments.

    I don't follow "to use it to auto generate the needed bitmask" is IMHO a felony. as you then say "a smarter IDE to .. create the bitmasks when given the labels." ?
    That's the same thing ?

    It does not really matter to an assembler WHERE the columns line up, the user will tell the ASM which columns to use, and it does the rest, in a vertical scan
    (TABS may be a pain here..)
    If you place them in the active code area, you complicate the normal parser, and require a new assembler is created before you can code anything.
    The comment approach Chip used, allows today's assembler to be used, and allows future coders to use their own comment style.
    It probably allows GCC/AS to be used, with a simple pre-parser that "creates the bitmasks when given the labels"
    I'm also guessing some will like spaced, and some will like compressed columns.



  • I simply think it does not belong into the comments, and letting a IDE use comments to generate things is just wrong.

    Mike

  • jmgjmg Posts: 15,140
    msrobots wrote: »
    I simply think it does not belong into the comments, and letting a IDE use comments to generate things is just wrong.

    Pragmas are comments, and they are widely used.

    If you pull too much into code, the added complexity makes it less portable.
    eg You CAN use a macro Assembler now, for P1/P2, but I'm not sure your example can be managed with a standard macro assembler (or AS) ?
  • jmg wrote: »
    msrobots wrote: »
    I simply think it does not belong into the comments, and letting a IDE use comments to generate things is just wrong.

    Pragmas are comments, and they are widely used.

    If you pull too much into code, the added complexity makes it less portable.
    eg You CAN use a macro Assembler now, for P1/P2, but I'm not sure your example can be managed with a standard macro assembler (or AS) ?

    Exactly, I also think that Pragmas are a felony, language wise. (Decades ago, in the last century I was once a student of N. Wirth, Modula2 might has damaged my brain.)

    On the other hand I agree with you that usual assembler do not do that. FASM/FASMG maybe could.

    On the third hand I still love COBOL having weird rules about sources, compared to later languages.

    Mike
  • TorTor Posts: 2,010
    I've never used #pragma in any C program I've ever written.. my gut says "No" very strongly.
    But then again there's never ever been anything I really needed it for anyay. After a great many years of writing C for a living.
  • jmgjmg Posts: 15,140
    msrobots wrote: »
    On the other hand I agree with you that usual assembler do not do that. FASM/FASMG maybe could.
    FASMG might, as it can do almost anything, but the work I did on FASMG shows it is powerful, but not that easy to wield, and the more complex your opcode macros/scripts are, the harder it is to maintain, and the slower it runs....
    I do not expect many coders to use Chip's shared opcode packing tricks... but they are nifty, and suited to ASM/kernal code, where you do not mind taking weeks to save a few bytes, knowing thousands of users will benefit.
    Normal production coding, is nothing like that space.

  • My FASMG comment was more meant as a joke, since it is not that portable. But the work you did showed that it would do the job.

    I am just fine with PASM2 as is, and agree with you that 'shared byte code packing' is suited for special cases, maybe not often used. But like people miss- (or re-) used a lot of P1 features, say video out for fast SPI, I guess that way more uses for it will pop up besides byte code interpreters.

    Mike
  • TonyB_TonyB_ Posts: 2,105
    edited 2017-10-04 22:32
    deleted
  • cgraceycgracey Posts: 14,133
    edited 2017-09-29 07:17
    TonyB, sorry I haven't responded, yet. I'm just thinking about it.
  • TonyB_TonyB_ Posts: 2,105
    edited 2017-10-04 22:31
    deleted
  • TonyB_ wrote: »
    Could somebody please test the following code on

    1. P2 v20 or earlier or P1
    2. P2 v21

    and report the 1a/1b/1c, 2a/2b/2c results?
    'declare reg1,reg2
    	mov	reg1,#$8000_0000		'-2147483648
    	adds	reg1,reg1	wc wz	'What are the flags? (a)
    	mov	reg1,#$7FFF_FFFF		'+2147483647
    	mov	reg2,#$FFFF_FFFF		'-1
    	cmps	reg1,reg2	wc wz	'What are the flags? (b)
    	subs	reg1,reg2	wc wz	'What are the flags? (c)
    

    I expect the following results (S = sign flag, V = overflow flag):
    P1
    1(a)  C=1,Z=1	C is V	overflow detected  	Right
    1(b)  C=1,Z=0	C is S  +2147483647 < -1  	WRONG!!!
    1(c)  C=1,Z=0	C is V  overflow detected  	Right
    
    P2 v21
    2(a)  C=0,Z=1	C is S  result is zero   	WRONG!!!
    2(b)  C=1,Z=0	C is S  +2147483647 < -1   	WRONG!!!
    2(c)  C=1,Z=0	C is S  result is -2147483648   WRONG!!!
    

    * * * * * * * * * * * * * * * * * * * *

    If C & Z used for overflow, could have shared code for unsigned and signed values with only the compare instruction changing:
    ' if overflow possible
    		cmp d,s		wcz	' replace with cmps d,s for signed
    if_c_and_z	jmp #overflow		' branch can never occur with cmp
    ' c set if d < s
    ...
    
    ' if overflow not possible
    		cmp d,s		wc	' replace with cmps d,s for signed
    ' c set if d < s
    ...
    
  • evanhevanh Posts: 15,126
    edited 2017-09-30 08:22
    I've just been trying to work out how a signed multi-word addition should be managed. I've realised that only the most significant word of the number is actually signed. All lesser significant words of the number are inherently unsigned. Meaning that an overflow can only be valid if there is no further carrying up through the number.

    Funnily I do remember someone stating this very point a very long time ago, but its vitality was lost on me at the time.


    EDIT: punctuation
  • evanhevanh Posts: 15,126
    edited 2017-09-30 09:08
    So, there is no such thing as a "signed carry".
  • cgraceycgracey Posts: 14,133
    evanh wrote: »
    So, there is no such thing as a "signed carry".

    Well, what do you call C after:

    CMPS D,S WC

    ...when it indicates that signed D was less than signed S?

    It is a signed version of what:

    CMP D,S WC

    ...would return in C, indicating that unsigned D was less than unsigned S.
  • evanhevanh Posts: 15,126
    That depends on your logic doesn't it. :D

    I'm reading my old 68K manual and it uses 5 flags! Although one flag is effectively a duplicate carry. So, the meaning of those four (Zero, Carry, Negative, Overflow) flags is not going to be completely matched with only the two in the propeller. The 68K doesn't have any explicit signed instructions, it's all done with branching on the flags.

    I'm scanning some pages right now ...
  • evanhevanh Posts: 15,126
    Attached. See page 3 for branching treatment of flags. Page 1 and 2 shows how the flags are set.

    pdf
    608K
    cc.pdf 608.2K
  • evanhevanh Posts: 15,126
    edited 2017-09-30 12:28
    Dang, the CMP instruction doesn't say which way round the comparison is. By reading page 2 and 3 details it looks like it's an "if destination GT/LT source" which seems to be backward for 68k nomenclature.

    Take an example of 128 - 1 = 127. If treating it as unsigned 8-bit word size that would be a HI condition from the C and Z flags. If treating it as signed 8-bit word size that would be a LT condition from the N and V flags.

    PS: One thing that caught my attention from reading pages 1 and 2 is the carry for the ADD/SUB instructions is generated from each high bit of the three ALU ports rather than as an extended bit in the result port. But I guess that's just writing out the equivalent of what an extra result bit would be.
  • evanhevanh Posts: 15,126
    edited 2017-09-30 13:19
    TonyB_ wrote: »
    and report the 1a/1b/1c, 2a/2b/2c results?
    'declare reg1,reg2
    	mov	reg1,#$8000_0000		'-2147483648
    	adds	reg1,reg1	wc wz	'What are the flags? (a)
    	mov	reg1,#$7FFF_FFFF		'+2147483647
    	mov	reg2,#$FFFF_FFFF		'-1
    	cmps	reg1,reg2	wc wz	'What are the flags? (b)
    	subs	reg1,reg2	wc wz	'What are the flags? (c)
    
    Results for #2, P2 v21b:
    Collected flags: 00000030
    a-flags: C = 1, Z = 1
    b-flags: C = 0, Z = 0
    c-flags: C = 0, Z = 0

    Actual flag collecting code:
    		mov     reg1, ##$8000_0000
    		adds    reg1, reg1        wcz
    		rczl    flags
    		mov     reg1, ##$7FFF_FFFF
    		mov     reg2, ##$FFFF_FFFF
    		cmps    reg1, reg2        wcz
    		rczl    flags
    		subs    reg1, reg2        wcz
    		rczl    flags
    
  • TonyB_TonyB_ Posts: 2,105
    edited 2017-09-30 13:43
    Thanks Evan for correcting the code and testing it. The separate cmps and subs are there for the P1 or P2 v20 and earlier. On v21 they act the same.

    The flag results are not what I expected. What is in reg1 after the subs?

  • evanhevanh Posts: 15,126
    edited 2017-09-30 13:53
    Subtract result = 80000000
    Collected flags = 00000030
    a-flags: C = 1, Z = 1
    b-flags: C = 0, Z = 0
    c-flags: C = 0, Z = 0

    Here's a little more of the code also showing where the numerical terminal output is executed (just added the middle portion):
    		mov     reg1, ##$8000_0000
    		adds    reg1, reg1       wcz
    		rczl    flags
    		mov     reg1, ##$7FFF_FFFF
    		mov     reg2, ##$FFFF_FFFF
    		cmps    reg1, reg2       wcz
    		rczl    flags
    		subs    reg1, reg2       wcz
    		rczl    flags
    
    		mov     parm, ##str_subres
    		call    #puts
    		mov     parm, reg1
    		call    #itoa
    		call    #putnl
    
    		mov     parm, ##str_flags
    		call    #puts
    		mov     parm, flags
    		call    #itoa
    		call    #putnl
    
  • Evan, could you try my test code on P2 v20 or earlier, or P1? Latter would need code changes.
  • evanhevanh Posts: 15,126
    Prop2 v20 comes back with:
    Subtract result = 80000000
    Collected flags = 00000032
    a-flags: C = 1, Z = 1
    b-flags: C = 0, Z = 0
    c-flags: C = 1, Z = 0
Sign In or Register to comment.