diff --git a/include/base/SMPInstr.h b/include/base/SMPInstr.h index a099b9db63645448243f194bf79b0e2a7dbd0b2f..0963c9875c8a236bdf30465fbcdd0b032bad7407 100644 --- a/include/base/SMPInstr.h +++ b/include/base/SMPInstr.h @@ -217,6 +217,9 @@ void PrintSPARKAdaOperator(SMPoperator Oper, std::string &OutString, bool &Prefi // Print current indentation level using tabs. void PrintSPARKIndentTabs(FILE *OutFile); +// Produce string such as "Unsigned32" or "Unsigned64" based on OpndByteWidth of 4 or 8, e.g. +void GetSPARKWidthCastString(std::size_t OpndByteWidth, char *CastString); + struct RTLoperator { SMPoperator oper; SMPOperandType type; diff --git a/src/base/SMPBasicBlock.cpp b/src/base/SMPBasicBlock.cpp index 9d4035a3103511e0e8871ffd26b13c5c548fe0d8..df947ea60800b0afcf6ace9c54fd3a61719cc1ab 100644 --- a/src/base/SMPBasicBlock.cpp +++ b/src/base/SMPBasicBlock.cpp @@ -629,6 +629,8 @@ void SMPBasicBlock::EmitSPARKAdaForExpression(FILE *BodyFile) { // First, set up iterators and pointers. std::vector<SMPInstr *>::const_reverse_iterator RevInstIter = GetRevInstCBegin(); SMPInstr *LastInst = (*RevInstIter); + bool UnsignedBranchOpcode = LastInst->MDIsUnsignedBranch(); + // CompareInst might be in this block or in a previous block. STARS_ea_t CompareAddr = CompareInst->GetAddr(); SMPBasicBlock *CompareBlock; @@ -645,6 +647,15 @@ void SMPBasicBlock::EmitSPARKAdaForExpression(FILE *BodyFile) { assert(RevInstIter != CompareBlock->GetRevInstCEnd()); STARSOpndTypePtr LeftOp = CompareRT->GetLeftOperand(); + // If signed compare opcode followed by unsigned branch opcode, cast the operands as (unsigned). + bool TypeCastNeeded = (SignedCompareCase && UnsignedBranchOpcode); + uint16_t LeftByteWidth = LeftOp->GetByteWidth(); + char CastString[12] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; + if (TypeCastNeeded) { + GetSPARKWidthCastString(LeftByteWidth, CastString); + SMP_fprintf(BodyFile, "%s(", CastString); + } + if (LeftOp->IsImmedOp() || HeaderBlock) { if (!LeftOp->IsImmedOp()) { // Might need to unnormalize reg or memory @@ -666,8 +677,11 @@ void SMPBasicBlock::EmitSPARKAdaForExpression(FILE *BodyFile) { SMP_fprintf(BodyFile, "ERROR in compare operand\n"); } } + if (TypeCastNeeded) { + SMP_fprintf(BodyFile, ")"); + } - if (SignedCompareCase) { + if (!UnsignedBranchOpcode) { // Emit the signed comparison operator based on the conditional branch opcode LastInst->MDEmitSPARKAdaExprCompare(BodyFile); } @@ -681,6 +695,9 @@ void SMPBasicBlock::EmitSPARKAdaForExpression(FILE *BodyFile) { SMP_fprintf(BodyFile, " 0 "); // AND with self is comparison to zero, set flags } else { + if (TypeCastNeeded) { + SMP_fprintf(BodyFile, "%s(", CastString); + } STARSOpndTypePtr RightOp = CompareRT->GetRightOperand(); if (RightOp->IsImmedOp() || HeaderBlock) { if (!RightOp->IsImmedOp()) { @@ -703,6 +720,9 @@ void SMPBasicBlock::EmitSPARKAdaForExpression(FILE *BodyFile) { SMP_fprintf(BodyFile, "ERROR in compare operand\n"); } } + if (TypeCastNeeded) { + SMP_fprintf(BodyFile, ")"); + } } // Mark all instructions in the single-expr block as translated. diff --git a/src/base/SMPInstr.cpp b/src/base/SMPInstr.cpp index 26d6fe2038b625fa0aecf299a19abb774352f7a8..3cdbd16c4d160c0ce805e066c14b6e66d52f17df 100644 --- a/src/base/SMPInstr.cpp +++ b/src/base/SMPInstr.cpp @@ -6673,22 +6673,30 @@ void SMPInstr::MDEmitSPARKAdaExprTest(FILE *OutFile) { SMP_fprintf(OutFile, " = "); break; + case STARS_NN_ja: // Jump if above (CF=0 & ZF=0) + case STARS_NN_jnbe: // Jump if not below or equal (CF=0 & ZF=0) case STARS_NN_jg: // Jump if Greater (ZF=0 & SF=OF) case STARS_NN_jnle: // Jump if Not Less or Equal (ZF=0 & SF=OF) SMP_fprintf(OutFile, " > "); break; + case STARS_NN_jae: // Jump if above or equal (CF=0) + case STARS_NN_jnb: // Jump if not below (CF=0) case STARS_NN_jge: // Jump if Greater or Equal (SF=OF) case STARS_NN_jnl: // Jump if Not Less (SF=OF) SMP_fprintf(OutFile, " >= "); break; + case STARS_NN_jb: // Jump if below (CF=1) + case STARS_NN_jnae: // Jump if not above or equal (CF=1) case STARS_NN_jl: // Jump if Less (SF!=OF) case STARS_NN_jnge: // Jump if Not Greater or Equal (SF!=OF) SMP_fprintf(OutFile, " < "); break; + case STARS_NN_jbe: // Jump if below or equal (CF=1 | ZF=1) case STARS_NN_jle: // Jump if Less or Equal (ZF=1 | SF!=OF) + case STARS_NN_jna: // Jump if not above (CF=1 | ZF=1) case STARS_NN_jng: // Jump if Not Greater (ZF=1 | SF!=OF) SMP_fprintf(OutFile, " <= "); break;