-
Notifications
You must be signed in to change notification settings - Fork 7k
PowerPC: Add SPE floating point min/max instructions (efsmax, efsmin) #8828
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
PowerPC: Add SPE floating point min/max instructions (efsmax, efsmin) #8828
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for two SPE (Signal Processing Engine) floating-point instructions for PowerPC processors: efsmax (floating-point maximum) and efsmin (floating-point minimum). These instructions operate on single-precision floating-point values stored in the lower 32-bit word of 64-bit registers.
Key Changes:
- Implementation of
efsmaxinstruction (opcode 0x2B0) that selects the maximum of two single-precision floats - Implementation of
efsmininstruction (opcode 0x2B1) that selects the minimum of two single-precision floats
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| :efsmax D,A,B is OP=4 & D & A & B & XOP_0_10=0x2B0 | ||
| { | ||
| local result:4; | ||
| if ( A:4 f>= B:4 ) goto <use_a>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We try to avoid using unnecessary gotos for these kind of operations. The slightly more preferred way to do it is to have a conditional assignment:
local cond:1 = A:4 f>= B:4;
result = (zext(cond) * A:4) + (zext(!cond) * B:4);
Although I don't have a binary to test and demonstrate this on.
EDIT: Also as good practice, we should avoid doing multiple reads of the input registers as well, so here's what it might look like with that change too:
:efsmax D,A,B is OP=4 & D & A & B & XOP_0_10=0x2B0
{
local inA:4 = A:4;
local inB:4 = B:4;
local cond:1 = inA f>= inB;
local result:4 = (zext(cond) * inA) + (zext(!cond) * inB);
# assign to lower word of D
D = ( D & 0xFFFFFFFF00000000 ) | zext( result );
setFPRF( result );
setSummaryFPSCR();
}
| :efsmin D,A,B is OP=4 & D & A & B & XOP_0_10=0x2B1 | ||
| { | ||
| local result:4; | ||
| if ( A:4 f<= B:4 ) goto <use_a>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly here
local cond:1 = A:4 f<= B:4;
result = (zext(cond) * A:4) + (zext(!cond) * B:4);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
#6863 (partial)
Adds support for SPE floating-point min/max instructions (from e200z759CRM):
Example:
Assembly:
efsmin r5,r3,r4 # r5 = min(r3, r4)
efsmax r5,r3,r4 # r5 = max(r3, r4)
Decompiles to:
// efsmin
result = fA;
if (fB < fA) {
result = fB;
}
// efsmax
result = fA;
if (fA < fB) {
result = fB;
}