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, 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.
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.
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.
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?
... 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.
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) ?
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.
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.
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.
'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
...
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.
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.
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.
Comments
(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
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.
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.
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 something like
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
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
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.
Mike
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
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.
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.
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
I expect the following results (S = sign flag, V = overflow flag):
* * * * * * * * * * * * * * * * * * * *
If C & Z used for overflow, could have shared code for unsigned and signed values with only the compare instruction changing:
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
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.
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 ...
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.
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:
The flag results are not what I expected. What is in reg1 after the subs?
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):
Subtract result = 80000000
Collected flags = 00000032
a-flags: C = 1, Z = 1
b-flags: C = 0, Z = 0
c-flags: C = 1, Z = 0