Interface FloatCompareBinOpGen<T extends JitFloatTestOp>

Type Parameters:
T - the class of p-code op node in the use-def graph
All Superinterfaces:
BinOpGen<T>, OpGen<T>
All Known Implementing Classes:
FloatEqualOpGen, FloatLessEqualOpGen, FloatLessOpGen, FloatNotEqualOpGen

public interface FloatCompareBinOpGen<T extends JitFloatTestOp> extends BinOpGen<T>
An extension for float comparison operators
  • Method Details

    • isSigned

      default boolean isSigned()
      Description copied from interface: BinOpGen
      Whether this operator is signed

      In many cases, the operator itself is not affected by the signedness of the operands; however, if size adjustments to the operands are needed, this can determine how those operands are extended.

      Specified by:
      isSigned in interface BinOpGen<T extends JitFloatTestOp>
      Returns:
      true for signed, false if not
    • opForFloatCmp

      <N2 extends Emitter.Next, N1 extends Emitter.Ent<N2, Types.TFloat>, N0 extends Emitter.Ent<N1, Types.TFloat>> Emitter<Emitter.Ent<N2,Types.TInt>> opForFloatCmp(Emitter<N0> em)
      Emit the JVM bytecode to perform the comparison with float operands on the stack.

      The result should be as defined by Comparator.compare(Object, Object).

      Type Parameters:
      N2 - the tail of the incoming stack
      N1 - the tail of the incoming stack including the right operand
      N0 - the incoming stack with the right and left operands on top
      Parameters:
      em - the emitter typed with the incoming stack
      Returns:
      the emitter typed with the resulting stack, i.e., the tail with the result pushed
    • opForDoubleCmp

      <N2 extends Emitter.Next, N1 extends Emitter.Ent<N2, Types.TDouble>, N0 extends Emitter.Ent<N1, Types.TDouble>> Emitter<Emitter.Ent<N2,Types.TInt>> opForDoubleCmp(Emitter<N0> em)
      Emit the JVM bytecode to perform the comparison with double operands on the stack.

      The result should be as defined by Comparator.compare(Object, Object).

      Type Parameters:
      N2 - the tail of the incoming stack
      N1 - the tail of the incoming stack including the right operand
      N0 - the incoming stack with the right and left operands on top
      Parameters:
      em - the emitter typed with the incoming stack
      Returns:
      the emitter typed with the resulting stack, i.e., the tail with the result pushed
    • opForCondJump

      <N1 extends Emitter.Next, N0 extends Emitter.Ent<N1, Types.TInt>> Lbl.LblEm<N1,N1> opForCondJump(Emitter<N0> em)
      Emit the JVM opcode to perform the conditional jump.

      The condition should correspond to the true case of the p-code operator.

      Type Parameters:
      N1 - the tail of the incoming stack
      N0 - the incoming stack including the comparison result
      Parameters:
      em - the emitter typed with the incoming stack
      Returns:
      the target label and emitter typed with the resulting stack, i.e., with the comparison result popped
    • genRun

      default <THIS extends JitCompiledPassage> OpGen.OpResult genRun(Emitter<Emitter.Bot> em, Local<Types.TRef<THIS>> localThis, Local<Types.TInt> localCtxmod, Methods.RetReq<Types.TRef<JitCompiledPassage.EntryPoint>> retReq, JitCodeGenerator<THIS> gen, T op, JitControlFlowModel.JitBlock block, Scope scope)
      Emit bytecode into the run method.

      This method must emit the code needed to load any input operands, convert them to the appropriate type, perform the actual operation, and then if applicable, store the output operand. The implementations should delegate to JitCodeGenerator.genReadToStack(Emitter, Local, JitVal, ghidra.pcode.emu.jit.analysis.JitType.SimpleJitType, Ext), JitCodeGenerator.genWriteFromStack(Emitter, Local, JitVar, ghidra.pcode.emu.jit.analysis.JitType.SimpleJitType, Ext, Scope) or similar for mp-int types.

      This implementation reduces the need to just a few opcodes: 1) the opcode for comparing in case of JVM float, 2) the opcode for comparing in the case of JVM double, and 3) the conditional jump on the result of that comparison. First, the comparison opcode is emitted. It should result in and int <0, ==0, or >0 on the stack, depending on whether L<R, L==R, or L>R, respectively. Then the conditional jump is emitted. We place labels in an if-else pattern to place either a 1 (true) or 0 (false) value of the appropriate p-code type on the stack.

      Specified by:
      genRun in interface OpGen<T extends JitFloatTestOp>
      Type Parameters:
      THIS - the type of the generated passage
      Parameters:
      em - the emitter typed with the empty stack
      localThis - a handle to the local holding the this reference
      localCtxmod - a handle to the local holding ctxmod
      retReq - an indication of what must be returned by this JitCompiledPassage.run(int) method.
      gen - the code generator
      op - the p-code op (use-def node) to translate
      block - the basic block containing the p-code op
      scope - a scope for generating temporary local storage
      Returns:
      the result of emitting the p-code op's bytecode
      Implementation Notes:
      This template is consistently generated by the Java compiler (Adoptium OpenJDK 21), despite there being possible branchless implementations. That could indicate one of a few things: 1) the HotSpot JIT knows how to optimize this pattern, perhaps using branchless native instructions, 2) branchless optimizations don't yield the speedup here we might expect, or 3) they didn't care to optimize. TODO: Investigate in case it's thing 3. We might like to see if branchless JVM bytecodes can improve performance.