Conditional Execution Encoding
devin122
Posts: 8
Im writing a Propeller Emulator, and I was looking for a way to quickly decode the conditional field of the opcode. This is what I have so far using standard c syntax . The conditional bits in the opcode are called x_0 through x_3 where x_0 is the least significant bit. C and Z Should be obvious
A = (x_3 & (C & Z)) | (x_2 & (C & !Z)) | (x_1 & (!C & Z)) | (x_0 & (!C & !Z))
If A is true then the instruction is executed, otherwise it is not. I've checked this over and it should work. Any input? Anyone have any simpler solutions?
A = (x_3 & (C & Z)) | (x_2 & (C & !Z)) | (x_1 & (!C & Z)) | (x_0 & (!C & !Z))
If A is true then the instruction is executed, otherwise it is not. I've checked this over and it should work. Any input? Anyone have any simpler solutions?
Comments
Nick
Bitwise logical operators don't necessarily make it faster. In bitwise, the complete expression has to be evaluated. In logical, short-cut evaluation is allowed and might be faster.
Nick
4 condition bits + Carry + Zero flag = 6 address inputs. The returned value must only be a bit (True/Flase) so only 64 bits are necessary (64 bytes may be faster).
Andy
If it must be fast, I'd still start with a clear, readable and most of all working program.
Then I'd consult the profiler, see where inlining could work and look for bottlenecks.
Nick
What is more clear and readable? This
or this
Andy
This:
A = x || C || Z;
Nick
That doesn't give the correct results.
Ah! I was confused by the 64 (2^6) entries the "short and clear" table should have had but didn't.
Nick
(x_3 && (C && Z)) || (x_2 && (C && !Z)) || (x_1 && (!C && Z)) || (x_0 && (!C && !Z))
should be:
(x_3 && C && Z) || (x_2 && C && !Z) || (X_1 && !C && Z) || (x_0 && !C && !Z)
further simplified:
(((x_3 && Z) || (x_2 && !Z)) && C) || (((X_1 && Z) || X_0 & !Z)) && !C)
This can be speed up:
if (C)
A = (x_3 && Z) || (x_2 && !Z);
else
A = (X_1 && Z) || X_0 & !Z);
Nick
That's a valid assumption. Hopefully, he doesn't use TRUE and FALSE to set the operands. That's why I prefer the logical operators (not knowing what other shortcuts the OP took to "make it fast").
First, a program has to be readable and maintainable. After that, you can comment out the initial algorithm and replace it with hard to read code if one prefers.
Nick
To add some fun, any instruction becomes a nop when the next instruction is being fetched from address 0 (and no, it's not limited to location $1FF).
I feel so embarrassed. What I meant to say is that the PC must be at $1FF while the instruction is executed. While this means that the next fetch could come from #0 (but could theoretically come from anywhere else) the reverse isn't true as any jmp #0 will fetch from #0.
SRSLY? That's kooky.
How do you arrange it so an arbitrary instruction is followed by one fetched from 0?
Exactly how many undocumented features does that code use? Is there a document that documents undocumented features?
Dave
If you ask me then I'd say one (undocumented feature). Which is the abort behaviour. I figure it's to do with the hand-over sequence for a coginit just before it executes user code. Anyway, I keep collecting stuff like this in the Propeller Tricks & Traps thread.
Kuroneko, you are kurazy!
What about jmp #0? Where's the next instruction fetched from in that case?
I don't quite follow. If it's just a jmp #0 then the next fetch is from #1. Can you elaborate?
In case you refer to a phase jump $000:$000A then the first target is indeed #0 (2+2*(-1)) but as the PC is $1FF (2+3*(-1)) at this point it becomes a nop and is then executed again for real.
A preset 2, increment = 1 (frqx = -1)
Just for clarification, the fetch-from-0 isn't enough and in fact irrelevant. The cog must think it's at $1FF (which would normally lead to a fetch from #0). Apologies for the confusion.