From 2acc7d161c8061d203e00d00ea81706ef2f7149c Mon Sep 17 00:00:00 2001 From: clc5q <clc5q@git.zephyr-software.com> Date: Tue, 2 Sep 2014 14:55:40 +0000 Subject: [PATCH] Emit SPARK Ada loops. --- SMPFunction.cpp | 12 ++--- SMPInstr.cpp | 135 +++++++++++++++++++++++++++++++++++++++++++++++- SMPInstr.h | 1 + 3 files changed, 141 insertions(+), 7 deletions(-) diff --git a/SMPFunction.cpp b/SMPFunction.cpp index 3e532639..305faa12 100644 --- a/SMPFunction.cpp +++ b/SMPFunction.cpp @@ -3519,8 +3519,8 @@ bool SMPFunction::WritesAboveLocalFrame(op_t DestOp, bool OpNormalized, ea_t Ins || (EBPrelative && (SignedOffset > 0)); if (InArgWrite && OpNormalized && (0 == SignedOffset)) { - SMP_msg("DANGER: Write to saved return address detected at %lx in function that begins at %lx\n", - InstAddr, (unsigned long) this->FirstEA); + SMP_msg("DANGER: Write to saved return address detected at %llx in function that begins at %llx\n", + (unsigned long long) InstAddr, (unsigned long long) this->FirstEA); this->SetUnsafeForFastReturns(true, RETURN_ADDRESS_WRITE); } @@ -3560,13 +3560,13 @@ bool SMPFunction::AccessAboveLocalFrame(op_t StackOp, bool OpNormalized, ea_t In if (InArgAccess && OpNormalized && (0 == SignedOffset)) { if (WriteAccess) { - SMP_msg("DANGER: Write to saved return address detected at %lx in function that begins at %lx\n", - InstAddr, (unsigned long) this->FirstEA); + SMP_msg("DANGER: Write to saved return address detected at %llx in function that begins at %llx\n", + (unsigned long long) InstAddr, (unsigned long long) this->FirstEA); this->SetUnsafeForFastReturns(true, RETURN_ADDRESS_WRITE); } else { - SMP_msg("INFO: Read of saved return address detected at %lx in function that begins at %lx\n", - InstAddr, (unsigned long) this->FirstEA); + SMP_msg("INFO: Read of saved return address detected at %llx in function that begins at %llx\n", + (unsigned long long) InstAddr, (unsigned long long) this->FirstEA); this->SetUnsafeForFastReturns(true, RETURN_ADDRESS_READ); } } diff --git a/SMPInstr.cpp b/SMPInstr.cpp index 16785c0d..011a4b5f 100644 --- a/SMPInstr.cpp +++ b/SMPInstr.cpp @@ -1942,6 +1942,111 @@ void SMPInstr::PrintDeadRegs(FILE *OutputFile) { return; } // end of SMPInstr::PrintDeadRegs() +// Invert the condition of the current conditional branch and emit SPARK Ada equivalent. +void SMPInstr::MDEmitSPARKAdaInvertedCondition(FILE *OutFile) { + ushort opcode = this->SMPcmd.itype; + switch (opcode) { + NN_ja: // Jump if Above (CF=0 & ZF=0) + NN_jnbe: // Jump if Not Below or Equal (CF=0 & ZF=0) + SMP_fprintf(OutFile, "(CarryFlag or ZeroFlag)"); + break; + + NN_jae: // Jump if Above or Equal (CF=0) + NN_jnb: // Jump if Not Below (CF=0) + NN_jnc: // Jump if Not Carry (CF=0) + SMP_fprintf(OutFile, "(CarryFlag)"); + break; + + NN_jb: // Jump if Below (CF=1) + NN_jc: // Jump if Carry (CF=1) + NN_jnae: // Jump if Not Above or Equal (CF=1) + SMP_fprintf(OutFile, "(not CarryFlag)"); + break; + + NN_jbe: // Jump if Below or Equal (CF=1 | ZF=1) + NN_jna: // Jump if Not Above (CF=1 | ZF=1) + SMP_fprintf(OutFile, "(not (CarryFlag or ZeroFlag))"); + break; + + NN_jcxz: // Jump if CX is 0 + SMP_fprintf(OutFile, "(CX /= 0)"); + break; + + NN_jecxz: // Jump if ECX is 0 + SMP_fprintf(OutFile, "(ECX /= 0)"); + break; + + NN_jrcxz: // Jump if RCX is 0 + SMP_fprintf(OutFile, "(RCX /= 0)"); + break; + + NN_je: // Jump if Equal (ZF=1) + NN_jz: // Jump if Zero (ZF=1) + SMP_fprintf(OutFile, "(not ZeroFlag)"); + break; + + + NN_jg: // Jump if Greater (ZF=0 & SF=OF) + NN_jnle: // Jump if Not Less or Equal (ZF=0 & SF=OF) + SMP_fprintf(OutFile, "(ZeroFlag or (SignFlag \\= OverflowFlag))"); + break; + + NN_jge: // Jump if Greater or Equal (SF=OF) + NN_jnl: // Jump if Not Less (SF=OF) + SMP_fprintf(OutFile, "(SignFlag \\= OverflowFlag)"); + break; + + NN_jl: // Jump if Less (SF!=OF) + SMP_fprintf(OutFile, "(SignFlag = OverflowFlag)"); + break; + + NN_jle: // Jump if Less or Equal (ZF=1 | SF!=OF) + NN_jng: // Jump if Not Greater (ZF=1 | SF!=OF) + SMP_fprintf(OutFile, "((not Zeroflag) and (SignFlag = OverflowFlag))"); + break; + + NN_jne: // Jump if Not Equal (ZF=0) + NN_jnz: // Jump if Not Zero (ZF=0) + SMP_fprintf(OutFile, "(ZeroFlag)"); + break; + + NN_jnge: // Jump if Not Greater or Equal (ZF=1) + SMP_fprintf(OutFile, "(not ZeroFlag)"); + break; + + NN_jno: // Jump if Not Overflow (OF=0) + SMP_fprintf(OutFile, "(OverflowFlag)"); + break; + + NN_jnp: // Jump if Not Parity (PF=0) + NN_jpo: // Jump if Parity Odd (PF=0) + SMP_fprintf(OutFile, "(ParityFlag)"); + break; + + NN_jns: // Jump if Not Sign (SF=0) + SMP_fprintf(OutFile, "(SignFlag)"); + break; + + NN_jo: // Jump if Overflow (OF=1) + SMP_fprintf(OutFile, "(not OverflowFlag)"); + break; + + NN_jp: // Jump if Parity (PF=1) + NN_jpe: // Jump if Parity Even (PF=1) + SMP_fprintf(OutFile, "(not ParityFlag)"); + break; + + NN_js: // Jump if Sign (SF=1) + SMP_fprintf(OutFile, "(not SignFlag)"); + break; + + default: + SMP_fprintf(OutFile, "ERROR: Unknown conditional branch opcode at %llx %s\n", (unsigned long long) this->GetAddr(), this->GetDisasm()); + break; + } + return; +} // end of SMPInstr::MDEmitSPARKAdaInvertedCondition() + // Emit SPARK-Ada translation of instruction void SMPInstr::EmitSPARKAda(FILE *OutFile) { if (this->IsNop()) { @@ -1950,13 +2055,21 @@ void SMPInstr::EmitSPARKAda(FILE *OutFile) { // Print the disassembly as a comment before the SPARK translation. PrintSPARKIndentTabs(OutFile); - SMP_fprintf(OutFile, " -- %s\n", this->GetDisasm()); + SMP_fprintf(OutFile, " -- %lx %s\n", (unsigned long) this->GetAddr(), this->GetDisasm()); bool PrintOperands = false; SMPitype CurrDataFlowType = this->GetDataFlowType(); std::string FuncTarget; ea_t NextAddr; + // Detect start of a loop. + if (this->IsFirstInBlock() && this->GetBlock()->IsLoopHeaderBlock()) { + // We want to print "loop" and increase indentation. + PrintSPARKIndentTabs(OutFile); + SMP_fprintf(OutFile, "loop \n"); + ++STARS_SPARK_IndentCount; + } + switch (CurrDataFlowType) { case DEFAULT: case LABEL: @@ -1966,6 +2079,26 @@ void SMPInstr::EmitSPARKAda(FILE *OutFile) { case JUMP: case COND_BRANCH: + // Detect loop-related control flow first, then simple if-else control flow otherwise. + if (this->GetBlock()->IsLoopTailBlock()) { + // We must be looping back to the loop header. + if (JUMP == CurrDataFlowType) { // simple case + --STARS_SPARK_IndentCount; + PrintSPARKIndentTabs(OutFile); + SMP_fprintf(OutFile, "end loop;\n\n"); + } + else { // conditionally loops back, might fall out of loop if condition is false. + // We want to invert the condition and exit on the inverted condition, then fall through + // to an unconditional loop back (i.e. "end loop;") statement. + PrintSPARKIndentTabs(OutFile); + SMP_fprintf(OutFile, "exit when "); + this->MDEmitSPARKAdaInvertedCondition(OutFile); + SMP_fprintf(OutFile, ";\n"); + --STARS_SPARK_IndentCount; + PrintSPARKIndentTabs(OutFile); + SMP_fprintf(OutFile, "end loop;\n\n"); + } + } break; case INDIR_JUMP: diff --git a/SMPInstr.h b/SMPInstr.h index 89cb8381..022660e6 100644 --- a/SMPInstr.h +++ b/SMPInstr.h @@ -572,6 +572,7 @@ public: char *DestString(int OptType); void PrintDeadRegs(FILE *OutputFile); // print the registers that are dead right before this instruction. void Dump(void); // Complete debug print, with DEF/USE list, SSA #s, RTL + void MDEmitSPARKAdaInvertedCondition(FILE *OutFile); // Invert the condition of the current conditional branch and emit SPARK Ada equivalent. void EmitSPARKAda(FILE *OutFile); // Emit SPARK-Ada translation of instruction // Analysis methods -- GitLab