Skip to content

Conversation

@daskey
Copy link

@daskey daskey commented Dec 25, 2025

#6863 (partial)

Adds support for SPE floating-point min/max instructions (from e200z759CRM):

  • efsmax: Floating-Point Single-Precision Maximum
  • efsmin: Floating-Point Single-Precision Minimum

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;
}

Copilot AI review requested due to automatic review settings December 25, 2025 20:04
Copy link

Copilot AI left a 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 efsmax instruction (opcode 0x2B0) that selects the maximum of two single-precision floats
  • Implementation of efsmin instruction (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>;
Copy link
Collaborator

@GhidorahRex GhidorahRex Dec 29, 2025

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>;
Copy link
Collaborator

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);

@daskey daskey requested a review from Copilot December 30, 2025 04:56
@daskey daskey marked this pull request as draft December 30, 2025 04:57
Copy link

Copilot AI left a 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants