x86InstructionSemantics.h

Go to the documentation of this file.
00001 #ifndef ROSE_X86INSTRUCTIONSEMANTICS_H
00002 #define ROSE_X86INSTRUCTIONSEMANTICS_H
00003 
00004 /* See tests/roseTests/binaryTests/SemanticVerification for ideas about how to test your work here. Note that the test is not
00005  * run automatically because it depends on setting up a slave machine who's architecture is what is being simulated by the
00006  * instruction semantics (not necessarily the same architecture that's running ROSE). */
00007 
00008 #include "semanticsModule.h"
00009 #include <cassert>
00010 #include <cstdio>
00011 #include <iostream>
00012 #include "integerOps.h"
00013 #include "AsmUnparser_compat.h" /* for unparseInstructionWithAddress() */
00014 
00015 /* Returns the segment register corresponding to the specified register reference address expression. */
00016 static inline X86SegmentRegister getSegregFromMemoryReference(SgAsmMemoryReferenceExpression* mr) {
00017     X86SegmentRegister segreg = x86_segreg_none;
00018     SgAsmx86RegisterReferenceExpression* seg = isSgAsmx86RegisterReferenceExpression(mr->get_segment());
00019     if (seg) {
00020         ROSE_ASSERT(seg->get_descriptor().get_major() == x86_regclass_segment);
00021         segreg = (X86SegmentRegister)(seg->get_descriptor().get_minor());
00022     } else {
00023         ROSE_ASSERT(!"Bad segment expr");
00024     }
00025     if (segreg == x86_segreg_none) segreg = x86_segreg_ds;
00026     return segreg;
00027 }
00028 
00029 namespace BinaryAnalysis {
00030     namespace InstructionSemantics {
00031 
00036 template <typename Policy, template <size_t> class WordType>
00037 struct X86InstructionSemantics {
00038 #   ifdef Word
00039 #       error "Having a macro called \"Word\" conflicts with x86InstructionSemantics.h"
00040 #   else
00041 #       define Word(Len) WordType<(Len)>
00042 #   endif
00043 
00044     struct Exception {
00045         Exception(const std::string &mesg, SgAsmInstruction *insn): mesg(mesg), insn(insn) {}
00046         friend std::ostream& operator<<(std::ostream &o, const Exception &e) {
00047             o <<"instruction semantics: " <<e.mesg;
00048             if (e.insn) o <<" [" <<unparseInstructionWithAddress(e.insn) <<"]";
00049             return o;
00050         }
00051         std::string mesg;
00052         SgAsmInstruction *insn;
00053     };
00054 
00055     Policy& policy;
00056     SgAsmInstruction *current_instruction;
00057     Word(32) orig_eip; // set at the top of translate()
00058 
00059     /* Registers used explicitly by this class. */
00060     RegisterDescriptor REG_EAX, REG_EBX, REG_ECX, REG_EDX, REG_EDI, REG_EIP, REG_ESI, REG_ESP, REG_EBP;
00061     RegisterDescriptor REG_AX, REG_CX, REG_DX, REG_AL, REG_AH;
00062     RegisterDescriptor REG_EFLAGS, REG_AF, REG_CF, REG_DF, REG_OF, REG_PF, REG_SF, REG_ZF;
00063 
00064     X86InstructionSemantics(Policy& policy)
00065         : policy(policy), current_instruction(NULL), orig_eip(policy.readRegister<32>(policy.findRegister("eip"))) {
00066         REG_EAX = policy.findRegister("eax", 32);
00067         REG_EBX = policy.findRegister("ebx", 32);
00068         REG_ECX = policy.findRegister("ecx", 32);
00069         REG_EDX = policy.findRegister("edx", 32);
00070         REG_EDI = policy.findRegister("edi", 32);
00071         REG_EIP = policy.findRegister("eip", 32);
00072         REG_ESI = policy.findRegister("esi", 32);
00073         REG_ESP = policy.findRegister("esp", 32);
00074         REG_EBP = policy.findRegister("ebp", 32);
00075 
00076         REG_AX  = policy.findRegister("ax", 16);
00077         REG_CX  = policy.findRegister("cx", 16);
00078         REG_DX  = policy.findRegister("dx", 16);
00079 
00080         REG_AL  = policy.findRegister("al", 8);
00081         REG_AH  = policy.findRegister("ah", 8);
00082 
00083         REG_EFLAGS=policy.findRegister("eflags", 32);
00084         REG_AF  = policy.findRegister("af", 1);
00085         REG_CF  = policy.findRegister("cf", 1);
00086         REG_DF  = policy.findRegister("df", 1);
00087         REG_OF  = policy.findRegister("of", 1);
00088         REG_PF  = policy.findRegister("pf", 1);
00089         REG_SF  = policy.findRegister("sf", 1);
00090         REG_ZF  = policy.findRegister("zf", 1);
00091     }
00092     virtual ~X86InstructionSemantics() {}
00093 
00096     WordType<1> rep_enter() {
00097         return policy.invert(policy.equalToZero(readRegister<32>(REG_ECX)));
00098     }
00099 
00104     void rep_repeat(SgAsmx86Instruction *insn, WordType<1> repeat, WordType<1> cond) {
00105         WordType<32> new_cx = policy.add(readRegister<32>(REG_ECX),
00106                                          policy.ite(cond,
00107                                                     number<32>(-1),
00108                                                     number<32>(0)));
00109         writeRegister(REG_ECX, new_cx);
00110         repeat = policy.and_(repeat, policy.invert(policy.equalToZero(new_cx)));
00111         writeRegister(REG_EIP,
00112                       policy.ite(policy.and_(cond, repeat),
00113                                  orig_eip,    /* repeat */
00114                                  readRegister<32>(REG_EIP)));                    /* exit */
00115     }
00116 
00118     template<size_t N>
00119     WordType<8*N> stringop_load_si(SgAsmx86Instruction *insn, WordType<1> cond) {
00120         return readMemory<8*N>((insn->get_segmentOverride() == x86_segreg_none ? x86_segreg_ds : insn->get_segmentOverride()),
00121                                readRegister<32>(REG_ESI),
00122                                cond);
00123     }
00124 
00126     template<size_t N>
00127     WordType<8*N> stringop_load_di(WordType<1> cond) {
00128         return readMemory<8*N>(x86_segreg_es, readRegister<32>(REG_EDI), cond);
00129     }
00130 
00133     template<size_t N>
00134     void stos_semantics(SgAsmx86Instruction *insn, WordType<1> cond) {
00135         const SgAsmExpressionPtrList& operands = insn->get_operandList()->get_operands();
00136         if (operands.size()!=0)
00137             throw Exception("instruction must have no operands", insn);
00138         if (insn->get_addressSize()!=x86_insnsize_32)
00139             throw Exception("address size must be 32 bits", insn);
00140 
00141         /* Fill memory pointed to by ES:[DI] with contents of AX. */
00142         policy.writeMemory(x86_segreg_es,
00143                            readRegister<32>(REG_EDI),
00144                            extract<0, 8*N>(readRegister<32>(REG_EAX)),
00145                            cond);
00146 
00147         /* Update DI */
00148         writeRegister(REG_EDI,
00149                       policy.ite(cond,
00150                                  policy.add(readRegister<32>(REG_EDI),
00151                                             policy.ite(readRegister<1>(REG_DF), number<32>(-N), number<32>(N))),
00152                                  readRegister<32>(REG_EDI)));
00153     }
00154 
00157     template<size_t N>
00158     void rep_stos_semantics(SgAsmx86Instruction *insn) {
00159         WordType<1> in_loop = rep_enter();
00160         stos_semantics<N>(insn, in_loop);
00161         rep_repeat(insn, policy.true_(), in_loop);
00162     }
00163 
00166     template<size_t N>
00167     void movs_semantics(SgAsmx86Instruction *insn, WordType<1> cond) {
00168         const SgAsmExpressionPtrList &operands = insn->get_operandList()->get_operands();
00169         if (operands.size()!=0)
00170             throw Exception("instruction must have no operands", insn);
00171         if (insn->get_addressSize() != x86_insnsize_32)
00172             throw Exception("size not implemented", insn);
00173 
00174         policy.writeMemory(x86_segreg_es,
00175                            readRegister<32>(REG_EDI),
00176                            stringop_load_si<N>(insn, cond),
00177                            cond);
00178         writeRegister(REG_ESI,
00179                       policy.add(readRegister<32>(REG_ESI),
00180                                  policy.ite(cond,
00181                                             policy.ite(readRegister<1>(REG_DF),
00182                                                        number<32>(-(N)),
00183                                                        number<32>(N)),
00184                                             number<32>(0))));
00185         writeRegister(REG_EDI,
00186                       policy.add(readRegister<32>(REG_EDI),
00187                                  policy.ite(cond,
00188                                             policy.ite(readRegister<1>(REG_DF),
00189                                                        number<32>(-(N)),
00190                                                        number<32>(N)),
00191                                             number<32>(0))));
00192     }
00193 
00196     template<size_t N>
00197     void rep_movs_semantics(SgAsmx86Instruction *insn) {
00198         WordType<1> in_loop = rep_enter();
00199         movs_semantics<N>(insn, in_loop);
00200         rep_repeat(insn, policy.true_(), in_loop);
00201     }
00202 
00205     template<size_t N>
00206     void cmps_semantics(SgAsmx86Instruction *insn, WordType<1> cond) {
00207         const SgAsmExpressionPtrList &operands = insn->get_operandList()->get_operands();
00208         if (operands.size()!=0)
00209             throw Exception("instruction must have no operands", insn);
00210         if (insn->get_addressSize() != x86_insnsize_32)
00211             throw Exception("size not implemented", insn);
00212         doAddOperation<8*N>(stringop_load_si<N>(insn, cond),
00213                             policy.invert(stringop_load_di<N>(cond)),
00214                             true,
00215                             policy.false_(),
00216                             cond);
00217         writeRegister(REG_ESI,
00218                       policy.ite(cond,
00219                                  policy.add(readRegister<32>(REG_ESI),
00220                                             policy.ite(readRegister<1>(REG_DF), number<32>(-N), number<32>(N))),
00221                                  readRegister<32>(REG_ESI)));
00222         writeRegister(REG_EDI,
00223                       policy.ite(cond,
00224                                  policy.add(readRegister<32>(REG_EDI),
00225                                             policy.ite(readRegister<1>(REG_DF), number<32>(-N), number<32>(N))),
00226                                  readRegister<32>(REG_EDI)));
00227     }
00228 
00230     template<size_t N>
00231     void repe_cmps_semantics(SgAsmx86Instruction *insn) {
00232         WordType<1> in_loop = rep_enter();
00233         cmps_semantics<N>(insn, in_loop);
00234         WordType<1> repeat = readRegister<1>(REG_ZF);
00235         rep_repeat(insn, repeat, in_loop);
00236     }
00237 
00239     template<size_t N>
00240     void repne_cmps_semantics(SgAsmx86Instruction *insn) {
00241         WordType<1> in_loop = rep_enter();
00242         cmps_semantics<N>(insn, in_loop);
00243         WordType<1> repeat = policy.invert(readRegister<1>(REG_ZF));
00244         rep_repeat(insn, repeat, in_loop);
00245     }
00246 
00249     template<size_t N>
00250     void scas_semantics(SgAsmx86Instruction *insn, WordType<1> cond) {
00251         const SgAsmExpressionPtrList &operands = insn->get_operandList()->get_operands();
00252         if (operands.size()!=0)
00253             throw Exception("instruction must have no operands", insn);
00254         if (insn->get_addressSize() != x86_insnsize_32)
00255             throw Exception("size not implemented", insn);
00256         doAddOperation<8*N>(extract<0, 8*N>(readRegister<32>(REG_EAX)),
00257                             policy.invert(stringop_load_di<N>(cond)),
00258                             true,
00259                             policy.false_(),
00260                             cond);
00261         writeRegister(REG_EDI,
00262                       policy.ite(cond,
00263                                  policy.add(readRegister<32>(REG_EDI),
00264                                             policy.ite(readRegister<1>(REG_DF), number<32>(-N), number<32>(N))),
00265                                  readRegister<32>(REG_EDI)));
00266     }
00267 
00269     template<size_t N>
00270     void repe_scas_semantics(SgAsmx86Instruction *insn) {
00271         WordType<1> in_loop = rep_enter();
00272         scas_semantics<N>(insn, in_loop);
00273         WordType<1> repeat = readRegister<1>(REG_ZF);
00274         rep_repeat(insn, repeat, in_loop);
00275     }
00276 
00278     template<size_t N>
00279     void repne_scas_semantics(SgAsmx86Instruction *insn) {
00280         WordType<1> in_loop = rep_enter();
00281         scas_semantics<N>(insn, in_loop);
00282         WordType<1> repeat = policy.invert(readRegister<1>(REG_ZF));
00283         rep_repeat(insn, repeat, in_loop);
00284     }
00285 
00287     void lods_semantics_regupdate(WordType<8> v) {
00288         writeRegister(REG_AL, v);
00289     }
00290 
00292     void lods_semantics_regupdate(WordType<16> v) {
00293         writeRegister(REG_AX, v);
00294     }
00295 
00297     void lods_semantics_regupdate(WordType<32> v) {
00298         writeRegister(REG_EAX, v);
00299     }
00300         
00302     template<size_t N>
00303     void lods_semantics(SgAsmx86Instruction *insn) {
00304         const SgAsmExpressionPtrList &operands = insn->get_operandList()->get_operands();
00305         if (operands.size()!=0)
00306             throw Exception("instruction must have no operands", insn);
00307         if (insn->get_addressSize() != x86_insnsize_32)
00308             throw Exception("size not implemented", insn);
00309         lods_semantics_regupdate(stringop_load_si<N>(insn, policy.true_()));
00310         writeRegister(REG_ESI,
00311                       policy.add(readRegister<32>(REG_ESI),
00312                                  policy.ite(readRegister<1>(REG_DF), number<32>(-N), number<32>(N))));
00313     }
00314 
00319     template<size_t operandBits, size_t shiftSignificantBits>
00320     WordType<operandBits> shift_semantics(X86InstructionKind kind, const WordType<operandBits> &operand,
00321                                           const WordType<8> &total_shift) {
00322         assert(x86_shr==kind || x86_sar==kind || x86_shl==kind);
00323 
00324         // The 8086 does not mask the shift count; processors starting with the 80286 (including virtual-8086 mode) do
00325         // mask.  The effect (other than timing) is the same either way.
00326         WordType<shiftSignificantBits> maskedShiftCount = extract<0, shiftSignificantBits>(total_shift);
00327         WordType<1> isZeroShiftCount = policy.equalToZero(maskedShiftCount);
00328 
00329         // Do the actual shift, according to instruction kind.
00330         WordType<operandBits> retval;
00331         switch (kind) {
00332             case x86_shr:
00333                 retval = policy.shiftRight(operand, maskedShiftCount);
00334                 break;
00335             case x86_sar:
00336                 retval = policy.shiftRightArithmetic(operand, maskedShiftCount);
00337                 break;
00338             case x86_shl:
00339                 retval = policy.shiftLeft(operand, maskedShiftCount);
00340                 break;
00341             default:
00342                 abort();
00343         }
00344 
00345         // AF is undefined if the shift count is non-zero, otherwise unchanged.  The Intel manual is not clear
00346         // whether the determination is by original count or masked count.  We assume the latter.
00347         writeRegister(REG_AF, policy.ite(isZeroShiftCount, readRegister<1>(REG_AF), policy.undefined_()));
00348 
00349         // What is the last bit shifted off the operand?  If we're right shifting by N bits, then the original operand N-1 bit
00350         // is what should make it into the final CF; if we're left shifting by N bits then we need bit operandBits-N.
00351         uintmax_t m = ((uintmax_t)1 << shiftSignificantBits) - 1;
00352         WordType<shiftSignificantBits> mask = number<shiftSignificantBits>(m); // -1 in modulo arithmetic
00353         WordType<shiftSignificantBits> bitPosition;
00354         if (x86_shr==kind || x86_sar==kind) {
00355             bitPosition = policy.add(maskedShiftCount, mask);
00356         } else {
00357             bitPosition = policy.add(number<shiftSignificantBits>(operandBits & m), // probably zero in modulo arithmetic
00358                                      policy.add(policy.invert(maskedShiftCount),
00359                                                 number<shiftSignificantBits>(1)));
00360         }
00361         WordType<1> shifted_off = extract<0, 1>(policy.shiftRight(operand, bitPosition));
00362 
00363         // isLargeShift is true if the (unmasked) amount by which to shift is greater than or equal to the size in
00364         // bits of the destination operand.
00365         assert(shiftSignificantBits<8);
00366         WordType<1> isLargeShift = policy.invert(policy.equalToZero(extract<shiftSignificantBits, 8>(total_shift)));
00367 
00368         // isOneBitShift is true if the (masked) amount by which to shift is equal to one.
00369         WordType<1> isOneBitShift = policy.equalToZero(policy.add(maskedShiftCount, mask));
00370 
00371         // New carry flag value.  From the Intel manual, the CF flag is "undefined for SHL and SHR [and SAL] instructions where
00372         // the count is greater than or equal to the size (in bits) of the destination operand", and "if the count is 0, the
00373         // flags are not affected."  The manual is silent about the value of CF for large SAR shifts, so we use the original
00374         // sign bit, matching the pseudo-code in the manual.
00375         WordType<1> newCF = policy.ite(isZeroShiftCount,
00376                                         readRegister<1>(REG_CF), // preserve current value
00377                                         policy.ite(isLargeShift,
00378                                                    (x86_sar==kind ?
00379                                                     extract<operandBits-1, operandBits>(operand) : // original sign bit
00380                                                     policy.undefined_()),
00381                                                    shifted_off));
00382         writeRegister(REG_CF, newCF);
00383 
00384         // Ajust the overflow flag.  From the Intel manual, "The OF flag is affected only on 1-bit shifts.  For left shifts,
00385         // the OF flag is set to 0 if the most-significant bit of the result is the same as the CF flag (that is, the top two
00386         // bits of the original operand were the same); otherwise, it is set to 1.  For the SAR instruction, the OF flag is
00387         // cleared for all 1-bit shifts.  For the SHR instruction, the OF flag is set to the most-significant bit of the
00388         // original operand.
00389         WordType<1> newOF;
00390         switch (kind) {
00391             case x86_shr:
00392                 newOF = policy.ite(isOneBitShift,
00393                                    extract<operandBits-1, operandBits>(operand),
00394                                    readRegister<1>(REG_OF));
00395                 break;
00396             case x86_sar:
00397                 newOF = policy.ite(isOneBitShift,
00398                                    policy.false_(),
00399                                    readRegister<1>(REG_OF));
00400                 break;
00401             case x86_shl:
00402                 newOF = policy.ite(isOneBitShift,
00403                                    policy.xor_(newCF, extract<operandBits-1, operandBits>(retval)),
00404                                    readRegister<1>(REG_OF));
00405                 break;
00406             default: // to shut up compiler warnings even though we would have aborted by now.
00407                 abort();
00408         }
00409         writeRegister(REG_OF, newOF);
00410 
00411         // Result flags SF, ZF, and PF are set according to the result, but are unchanged if the shift count is zero.
00412         setFlagsForResult<operandBits>(retval, policy.invert(isZeroShiftCount));
00413         return retval;
00414     }
00415 
00416     template <size_t Len>
00417     Word(Len) invertMaybe(const Word(Len)& w, bool inv) {
00418         if (inv) {
00419             return policy.invert(w);
00420         } else {
00421             return w;
00422         }
00423     }
00424 
00425     template <size_t Len>
00426     Word(Len) number(uintmax_t v) {
00427         return policy.template number<Len>(v);
00428     }
00429 
00430     template <size_t From, size_t To, size_t Len>
00431         Word(To - From) extract(Word(Len) w) {
00432         return policy.template extract<From, To>(w);
00433     }
00434 
00435     template <size_t From, size_t To>
00436         Word(To) signExtend(Word(From) w) {
00437         return policy.template signExtend<From, To>(w);
00438     }
00439 
00441     template<size_t Len>
00442     Word(Len) readRegister(const RegisterDescriptor &reg) {
00443         return policy.template readRegister<Len>(reg);
00444     }
00445 
00447     template<size_t Len>
00448     void writeRegister(const RegisterDescriptor &reg, const Word(Len) &value) {
00449         policy.template writeRegister<Len>(reg, value);
00450     }
00451 
00452     template <size_t Len>
00453     Word(1) greaterOrEqualToTen(Word(Len) w) {
00454         Word(Len) carries = number<Len>(0);
00455         policy.addWithCarries(w, number<Len>(6), policy.false_(), carries);
00456         return extract<Len - 1, Len>(carries);
00457     }
00458 
00459     template <size_t Len/*bits*/>
00460     Word(Len) readMemory(X86SegmentRegister segreg, const Word(32)& addr, Word(1) cond) {
00461         return policy.template readMemory<Len>(segreg, addr, cond);
00462     }
00463 
00464     Word(32) readEffectiveAddress(SgAsmExpression* expr) {
00465         assert (isSgAsmMemoryReferenceExpression(expr));
00466         return read32(isSgAsmMemoryReferenceExpression(expr)->get_address());
00467     }
00468 
00469     /* Returns an eight-bit value desribed by an instruction operand. */
00470     Word(8) read8(SgAsmExpression* e) {
00471         switch (e->variantT()) {
00472             case V_SgAsmx86RegisterReferenceExpression: {
00473                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
00474                 return policy.readRegister<8>(rre->get_descriptor());
00475             }
00476             case V_SgAsmBinaryAdd: {
00477                 return policy.add(read8(isSgAsmBinaryAdd(e)->get_lhs()), read8(isSgAsmBinaryAdd(e)->get_rhs()));
00478             }
00479             case V_SgAsmBinaryMultiply: {
00480                 SgAsmByteValueExpression* rhs = isSgAsmByteValueExpression(isSgAsmBinaryMultiply(e)->get_rhs());
00481                 if (!rhs)
00482                     throw Exception("byte value expression expected", current_instruction);
00483                 SgAsmExpression* lhs = isSgAsmBinaryMultiply(e)->get_lhs();
00484                 return extract<0, 8>(policy.unsignedMultiply(read8(lhs), read8(rhs)));
00485             }
00486             case V_SgAsmMemoryReferenceExpression: {
00487                 return readMemory<8>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
00488                                      readEffectiveAddress(e), policy.true_());
00489             }
00490             case V_SgAsmByteValueExpression:
00491             case V_SgAsmWordValueExpression:
00492             case V_SgAsmDoubleWordValueExpression:
00493             case V_SgAsmQuadWordValueExpression: {
00494                 uint64_t val = SageInterface::getAsmSignedConstant(isSgAsmValueExpression(e));
00495                 return number<8>(val & 0xFFU);
00496             }
00497             default: {
00498                 fprintf(stderr, "Bad variant %s in read8\n", e->class_name().c_str());
00499                 abort();
00500             }
00501         }
00502     }
00503 
00504     /* Returns a 16-bit value described by an instruction operand. */
00505     Word(16) read16(SgAsmExpression* e) {
00506         switch (e->variantT()) {
00507             case V_SgAsmx86RegisterReferenceExpression: {
00508                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
00509                 return policy.readRegister<16>(rre->get_descriptor());
00510             }
00511             case V_SgAsmBinaryAdd: {
00512                 return policy.add(read16(isSgAsmBinaryAdd(e)->get_lhs()), read16(isSgAsmBinaryAdd(e)->get_rhs()));
00513             }
00514             case V_SgAsmBinaryMultiply: {
00515                 SgAsmByteValueExpression* rhs = isSgAsmByteValueExpression(isSgAsmBinaryMultiply(e)->get_rhs());
00516                 if (!rhs)
00517                     throw Exception("byte value expression expected", current_instruction);
00518                 SgAsmExpression* lhs = isSgAsmBinaryMultiply(e)->get_lhs();
00519                 return extract<0, 16>(policy.unsignedMultiply(read16(lhs), read8(rhs)));
00520             }
00521             case V_SgAsmMemoryReferenceExpression: {
00522                 return readMemory<16>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
00523                                       readEffectiveAddress(e), policy.true_());
00524             }
00525             case V_SgAsmByteValueExpression:
00526             case V_SgAsmWordValueExpression:
00527             case V_SgAsmDoubleWordValueExpression:
00528             case V_SgAsmQuadWordValueExpression: {
00529                 uint64_t val = SageInterface::getAsmSignedConstant(isSgAsmValueExpression(e));
00530                 return number<16>(val & 0xFFFFU);
00531             }
00532             default: {
00533                 fprintf(stderr, "Bad variant %s in read16\n", e->class_name().c_str());
00534                 abort();
00535             }
00536         }
00537     }
00538 
00539     /* Returns a 32-bit value described by an instruction operand. */
00540     Word(32) read32(SgAsmExpression* e) {
00541         switch (e->variantT()) {
00542             case V_SgAsmx86RegisterReferenceExpression: {
00543                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
00544                 return policy.readRegister<32>(rre->get_descriptor());
00545             }
00546             case V_SgAsmBinaryAdd: {
00547                 return policy.add(read32(isSgAsmBinaryAdd(e)->get_lhs()), read32(isSgAsmBinaryAdd(e)->get_rhs()));
00548             }
00549             case V_SgAsmBinaryMultiply: {
00550                 SgAsmByteValueExpression* rhs = isSgAsmByteValueExpression(isSgAsmBinaryMultiply(e)->get_rhs());
00551                 if (!rhs)
00552                     throw Exception("byte value expression expected", current_instruction);
00553                 SgAsmExpression* lhs = isSgAsmBinaryMultiply(e)->get_lhs();
00554                 return extract<0, 32>(policy.unsignedMultiply(read32(lhs), read8(rhs)));
00555             }
00556             case V_SgAsmMemoryReferenceExpression: {
00557                 return readMemory<32>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
00558                                       readEffectiveAddress(e), policy.true_());
00559             }
00560             case V_SgAsmByteValueExpression:
00561             case V_SgAsmWordValueExpression:
00562             case V_SgAsmDoubleWordValueExpression:
00563             case V_SgAsmQuadWordValueExpression: {
00564                 uint64_t val = SageInterface::getAsmSignedConstant(isSgAsmValueExpression(e));
00565                 return number<32>(val & 0xFFFFFFFFU);
00566             }
00567             default: {
00568                 fprintf(stderr, "Bad variant %s in read32\n", e->class_name().c_str());
00569                 abort();
00570             }
00571         }
00572     }
00573 
00574     /* Writes the specified eight-bit value to the location specified by an instruction operand. */
00575     void write8(SgAsmExpression* e, const Word(8)& value) {
00576         switch (e->variantT()) {
00577             case V_SgAsmx86RegisterReferenceExpression: {
00578                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
00579                 policy.writeRegister(rre->get_descriptor(), value);
00580                 break;
00581             }
00582             case V_SgAsmMemoryReferenceExpression: {
00583                 policy.writeMemory(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
00584                                    readEffectiveAddress(e), value, policy.true_());
00585                 break;
00586             }
00587             default: {
00588                 fprintf(stderr, "Bad variant %s in write8\n", e->class_name().c_str());
00589                 abort();
00590             }
00591         }
00592     }
00593 
00594     /* Writes the specified 16-bit value to the location specified by an instruction operand. */
00595     void write16(SgAsmExpression* e, const Word(16)& value) {
00596         switch (e->variantT()) {
00597             case V_SgAsmx86RegisterReferenceExpression: {
00598                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
00599                 policy.writeRegister(rre->get_descriptor(), value);
00600                 break;
00601             }
00602             case V_SgAsmMemoryReferenceExpression: {
00603                 policy.writeMemory(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
00604                                    readEffectiveAddress(e), value, policy.true_());
00605                 break;
00606             }
00607             default: {
00608                 fprintf(stderr, "Bad variant %s in write16\n", e->class_name().c_str());
00609                 abort();
00610             }
00611         }
00612     }
00613 
00614     /* Writes the specified 32-bit value to the location specified by an instruction operand. */
00615     void write32(SgAsmExpression* e, const Word(32)& value) {
00616         switch (e->variantT()) {
00617             case V_SgAsmx86RegisterReferenceExpression: {
00618                 SgAsmx86RegisterReferenceExpression* rre = isSgAsmx86RegisterReferenceExpression(e);
00619                 policy.writeRegister(rre->get_descriptor(), value);
00620                 break;
00621             }
00622             case V_SgAsmMemoryReferenceExpression: {
00623                 policy.writeMemory(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(e)),
00624                                    readEffectiveAddress(e), value, policy.true_());
00625                 break;
00626             }
00627             default: {
00628                 fprintf(stderr, "Bad variant %s in write32\n", e->class_name().c_str());
00629                 abort();
00630             }
00631         }
00632     }
00633 
00634     /* Returns true if W has an even number of bits set; false for an odd number */
00635     Word(1) parity(Word(8) w) {
00636         Word(1) p01 = policy.xor_(extract<0, 1>(w), extract<1, 2>(w));
00637         Word(1) p23 = policy.xor_(extract<2, 3>(w), extract<3, 4>(w));
00638         Word(1) p45 = policy.xor_(extract<4, 5>(w), extract<5, 6>(w));
00639         Word(1) p67 = policy.xor_(extract<6, 7>(w), extract<7, 8>(w));
00640         Word(1) p0123 = policy.xor_(p01, p23);
00641         Word(1) p4567 = policy.xor_(p45, p67);
00642         return policy.invert(policy.xor_(p0123, p4567));
00643     }
00644 
00645     /* Sets flags: parity, sign, and zero */
00646     template <size_t Len>
00647     void setFlagsForResult(const Word(Len)& result) {
00648         writeRegister(REG_PF, parity(extract<0, 8>(result)));
00649         writeRegister(REG_SF, extract<Len - 1, Len>(result));
00650         writeRegister(REG_ZF, policy.equalToZero(result));
00651     }
00652 
00653     /* Sets flags conditionally. Sets parity, sign, and zero flags if COND is true. */
00654     template <size_t Len>
00655     void setFlagsForResult(const Word(Len)& result, Word(1) cond) {
00656         writeRegister(REG_PF, policy.ite(cond, parity(extract<0, 8>(result)), readRegister<1>(REG_PF)));
00657         writeRegister(REG_SF, policy.ite(cond, extract<Len - 1, Len>(result), readRegister<1>(REG_SF)));
00658         writeRegister(REG_ZF, policy.ite(cond, policy.equalToZero(result), readRegister<1>(REG_ZF)));
00659     }
00660 
00661     /* Adds A and B and adjusts condition flags. Can be used for subtraction if B is two's complement and invertCarries is set. */
00662     template <size_t Len>
00663     Word(Len) doAddOperation(const Word(Len)& a, const Word(Len)& b, bool invertCarries, Word(1) carryIn) {
00664         Word(Len) carries = number<Len>(0);
00665         Word(Len) result = policy.addWithCarries(a, b, invertMaybe(carryIn, invertCarries), carries/*out*/);
00666         setFlagsForResult<Len>(result);
00667         writeRegister(REG_AF, invertMaybe(extract<3, 4>(carries), invertCarries));
00668         writeRegister(REG_CF, invertMaybe(extract<Len - 1, Len>(carries), invertCarries));
00669         writeRegister(REG_OF, policy.xor_(extract<Len - 1, Len>(carries), extract<Len - 2, Len - 1>(carries)));
00670         return result;
00671     }
00672 
00673     /* Conditionally adds A and B and adjusts condition flags. Can be used for subtraction if B is two's complement and
00674      * invertCarries is set. Does nothing if COND is false. */ 
00675     template <size_t Len>
00676     Word(Len) doAddOperation(const Word(Len)& a, const Word(Len)& b, bool invertCarries, Word(1) carryIn, Word(1) cond) {
00677         Word(Len) carries = number<Len>(0);
00678         Word(Len) result = policy.addWithCarries(a, b, invertMaybe(carryIn, invertCarries), carries/*out*/);
00679         setFlagsForResult<Len>(result, cond);
00680         writeRegister(REG_AF,
00681                       policy.ite(cond,
00682                                  invertMaybe(extract<3, 4>(carries), invertCarries),
00683                                  readRegister<1>(REG_AF)));
00684         writeRegister(REG_CF,
00685                       policy.ite(cond,
00686                                  invertMaybe(extract<Len - 1, Len>(carries), invertCarries),
00687                                  readRegister<1>(REG_CF)));
00688         writeRegister(REG_OF,
00689                       policy.ite(cond,
00690                                  policy.xor_(extract<Len - 1, Len>(carries), extract<Len - 2, Len - 1>(carries)),
00691                                  readRegister<1>(REG_OF)));
00692         return result;
00693     }
00694 
00695     /* Does increment (decrement with DEC set), and adjusts condition flags. */
00696     template <size_t Len>
00697     Word(Len) doIncOperation(const Word(Len)& a, bool dec, bool setCarry) {
00698         Word(Len) carries = number<Len>(0);
00699         Word(Len) result = policy.addWithCarries(a, number<Len>(dec ? -1 : 1), policy.false_(), carries/*out*/);
00700         setFlagsForResult<Len>(result);
00701         writeRegister(REG_AF, invertMaybe(extract<3, 4>(carries), dec));
00702         writeRegister(REG_OF, policy.xor_(extract<Len - 1, Len>(carries), extract<Len - 2, Len - 1>(carries)));
00703         if (setCarry)
00704             writeRegister(REG_CF, invertMaybe(extract<Len - 1, Len>(carries), dec));
00705         return result;
00706     }
00707 
00708     /* Virtual so that we can subclass X86InstructionSemantics and have an opportunity to override the translation of any
00709      * instruction. */
00710 #if _MSC_VER
00711         // tps (02/01/2010) : fixme : Commented this out for Windows - there is a problem with the try:
00712         // error C2590: 'translate' : only a constructor can have a base/member initializer list
00713     virtual void translate(SgAsmx86Instruction* insn)  {
00714         }
00715 #else
00716     virtual void translate(SgAsmx86Instruction* insn) try {
00717         orig_eip = readRegister<32>(REG_EIP);
00718         writeRegister(REG_EIP, policy.add(orig_eip, policy.number<32>(insn->get_size())));
00719         X86InstructionKind kind = insn->get_kind();
00720         const SgAsmExpressionPtrList& operands = insn->get_operandList()->get_operands();
00721         switch (kind) {
00722 
00723             case x86_mov: {
00724                 if (operands.size()!=2)
00725                     throw Exception("instruction must have two operands", insn);
00726                 switch (numBytesInAsmType(operands[0]->get_type())) {
00727                     case 1: write8(operands[0], read8(operands[1])); break;
00728                     case 2: write16(operands[0], read16(operands[1])); break;
00729                     case 4: write32(operands[0], read32(operands[1])); break;
00730                     default: throw Exception("size not implemented", insn); break;
00731                 }
00732                 break;
00733             }
00734 
00735             case x86_xchg: {
00736                 if (operands.size()!=2)
00737                     throw Exception("instruction must have two operands", insn);
00738                 switch (numBytesInAsmType(operands[0]->get_type())) {
00739                     case 1: {
00740                         Word(8) temp = read8(operands[1]);
00741                         write8(operands[1], read8(operands[0]));
00742                         write8(operands[0], temp);
00743                         break;
00744                     }
00745                     case 2: {
00746                         Word(16) temp = read16(operands[1]);
00747                         write16(operands[1], read16(operands[0]));
00748                         write16(operands[0], temp);
00749                         break;
00750                     }
00751                     case 4: {
00752                         Word(32) temp = read32(operands[1]);
00753                         write32(operands[1], read32(operands[0]));
00754                         write32(operands[0], temp);
00755                         break;
00756                     }
00757                     default:
00758                         throw Exception("size not implemented", insn);
00759                         break;
00760                 }
00761                 break;
00762             }
00763 
00764             case x86_movzx: {
00765                 if (operands.size()!=2)
00766                     throw Exception("instruction must have two operands", insn);
00767                 switch (numBytesInAsmType(operands[0]->get_type())) {
00768                     case 2: {
00769                         write16(operands[0], policy.concat(read8(operands[1]), number<8>(0)));
00770                         break;
00771                     }
00772                     case 4: {
00773                         switch (numBytesInAsmType(operands[1]->get_type())) {
00774                             case 1: write32(operands[0], policy.concat(read8(operands[1]), number<24>(0))); break;
00775                             case 2: write32(operands[0], policy.concat(read16(operands[1]), number<16>(0))); break;
00776                             default: throw Exception("size not implemented", insn);
00777 
00778                         }
00779                         break;
00780                     }
00781                     default:
00782                         throw Exception("size not implemented", insn);
00783                         break;
00784                 }
00785                 break;
00786             }
00787 
00788             case x86_movsx: {
00789                 if (operands.size()!=2)
00790                     throw Exception("instruction must have two operands", insn);
00791                 switch (numBytesInAsmType(operands[0]->get_type())) {
00792                     case 2: {
00793                         Word(8) op1 = read8(operands[1]);
00794                         Word(16) result = signExtend<8, 16>(op1);
00795                         write16(operands[0], result);
00796                         break;
00797                     }
00798                     case 4: {
00799                         switch (numBytesInAsmType(operands[1]->get_type())) {
00800                             case 1: {
00801                                 Word(8) op1 = read8(operands[1]);
00802                                 Word(32) result = signExtend<8, 32>(op1);
00803                                 write32(operands[0], result);
00804                                 break;
00805                             }
00806                             case 2: {
00807                                 Word(16) op1 = read16(operands[1]);
00808                                 Word(32) result = signExtend<16, 32>(op1);
00809                                 write32(operands[0], result);
00810                                 break;
00811                             }
00812                             default:
00813                                 throw Exception("size not implemented", insn);
00814                         }
00815                         break;
00816                     }
00817                     default:
00818                         throw Exception("size not implemented", insn);
00819                         break;
00820                 }
00821                 break;
00822             }
00823 
00824             case x86_cbw: {
00825                 if (operands.size()!=0)
00826                     throw Exception("instruction must have no operands", insn);
00827                 writeRegister(REG_AX, signExtend<8, 16>(readRegister<8>(REG_AL)));
00828                 break;
00829             }
00830 
00831             case x86_cwde: {
00832                 if (operands.size()!=0)
00833                     throw Exception("instruction must have no operands", insn);
00834                 writeRegister(REG_EAX, signExtend<16, 32>(readRegister<16>(REG_AX))); 
00835                 break;
00836             }
00837 
00838             case x86_cwd: {
00839                 if (operands.size()!=0)
00840                     throw Exception("instruction must have no operands", insn);
00841                 writeRegister(REG_DX, extract<16, 32>(signExtend<16, 32>(readRegister<16>(REG_AX))));
00842                 break;
00843             }
00844 
00845             case x86_cdq: {
00846                 if (operands.size()!=0)
00847                     throw Exception("instruction must have no operands", insn);
00848                 writeRegister(REG_EDX, extract<32, 64>(signExtend<32, 64>(readRegister<32>(REG_AX))));
00849                 break;
00850             }
00851 
00852             case x86_lea: {
00853                 if (operands.size()!=2)
00854                     throw Exception("instruction must have two operands", insn);
00855                 write32(operands[0], readEffectiveAddress(operands[1]));
00856                 break;
00857             }
00858 
00859             case x86_and: {
00860                 if (operands.size()!=2)
00861                     throw Exception("instruction must have two operands", insn);
00862                 switch (numBytesInAsmType(operands[0]->get_type())) {
00863                     case 1: {
00864                         Word(8) result = policy.and_(read8(operands[0]), read8(operands[1]));
00865                         setFlagsForResult<8>(result);
00866                         write8(operands[0], result);
00867                         break;
00868                     }
00869                     case 2: {
00870                         Word(16) result = policy.and_(read16(operands[0]), read16(operands[1]));
00871                         setFlagsForResult<16>(result);
00872                         write16(operands[0], result);
00873                         break;
00874                     }
00875                     case 4: {
00876                         Word(32) result = policy.and_(read32(operands[0]), read32(operands[1]));
00877                         setFlagsForResult<32>(result);
00878                         write32(operands[0], result);
00879                         break;
00880                     }
00881                     default:
00882                         throw Exception("size not implemented", insn);
00883                         break;
00884                 }
00885                 writeRegister(REG_OF, policy.false_());
00886                 writeRegister(REG_AF, policy.undefined_());
00887                 writeRegister(REG_CF, policy.false_());
00888                 break;
00889             }
00890 
00891             case x86_or: {
00892                 if (operands.size()!=2)
00893                     throw Exception("instruction must have two operands", insn);
00894                 switch (numBytesInAsmType(operands[0]->get_type())) {
00895                     case 1: {
00896                         Word(8) result = policy.or_(read8(operands[0]), read8(operands[1]));
00897                         setFlagsForResult<8>(result);
00898                         write8(operands[0], result);
00899                         break;
00900                     }
00901                     case 2: {
00902                         Word(16) result = policy.or_(read16(operands[0]), read16(operands[1]));
00903                         setFlagsForResult<16>(result);
00904                         write16(operands[0], result);
00905                         break;
00906                     }
00907                     case 4: {
00908                         Word(32) result = policy.or_(read32(operands[0]), read32(operands[1]));
00909                         setFlagsForResult<32>(result);
00910                         write32(operands[0], result);
00911                         break;
00912                     }
00913                     default:
00914                         throw Exception("size not implemented", insn);
00915                         break;
00916                 }
00917                 writeRegister(REG_OF, policy.false_());
00918                 writeRegister(REG_AF, policy.undefined_());
00919                 writeRegister(REG_CF, policy.false_());
00920                 break;
00921             }
00922 
00923             case x86_test: {
00924                 if (operands.size()!=2)
00925                     throw Exception("instruction must have two operands", insn);
00926                 switch (numBytesInAsmType(operands[0]->get_type())) {
00927                     case 1: {
00928                         Word(8) result = policy.and_(read8(operands[0]), read8(operands[1]));
00929                         setFlagsForResult<8>(result);
00930                         break;
00931                     }
00932                     case 2: {
00933                         Word(16) result = policy.and_(read16(operands[0]), read16(operands[1]));
00934                         setFlagsForResult<16>(result);
00935                         break;
00936                     }
00937                     case 4: {
00938                         Word(32) result = policy.and_(read32(operands[0]), read32(operands[1]));
00939                         setFlagsForResult<32>(result);
00940                         break;
00941                     }
00942                     default:
00943                         throw Exception("size not implemented", insn);
00944                         break;
00945                 }
00946                 writeRegister(REG_OF, policy.false_());
00947                 writeRegister(REG_AF, policy.undefined_());
00948                 writeRegister(REG_CF, policy.false_());
00949                 break;
00950             }
00951 
00952             case x86_xor: {
00953                 if (operands.size()!=2)
00954                     throw Exception("instruction must have two operands", insn);
00955                 switch (numBytesInAsmType(operands[0]->get_type())) {
00956                     case 1: {
00957                         Word(8) result = policy.xor_(read8(operands[0]), read8(operands[1]));
00958                         setFlagsForResult<8>(result);
00959                         write8(operands[0], result);
00960                         break;
00961                     }
00962                     case 2: {
00963                         Word(16) result = policy.xor_(read16(operands[0]), read16(operands[1]));
00964                         setFlagsForResult<16>(result);
00965                         write16(operands[0], result);
00966                         break;
00967                     }
00968                     case 4: {
00969                         Word(32) result = policy.xor_(read32(operands[0]), read32(operands[1]));
00970                         setFlagsForResult<32>(result);
00971                         write32(operands[0], result);
00972                         break;
00973                     }
00974                     default:
00975                         throw Exception("size not implemented", insn);
00976                         break;
00977                 }
00978                 writeRegister(REG_OF, policy.false_());
00979                 writeRegister(REG_AF, policy.undefined_());
00980                 writeRegister(REG_CF, policy.false_());
00981                 break;
00982             }
00983 
00984             case x86_not: {
00985                 if (operands.size()!=1)
00986                     throw Exception("instruction must have one operand", insn);
00987                 switch (numBytesInAsmType(operands[0]->get_type())) {
00988                     case 1: {
00989                         Word(8) result = policy.invert(read8(operands[0]));
00990                         write8(operands[0], result);
00991                         break;
00992                     }
00993                     case 2: {
00994                         Word(16) result = policy.invert(read16(operands[0]));
00995                         write16(operands[0], result);
00996                         break;
00997                     }
00998                     case 4: {
00999                         Word(32) result = policy.invert(read32(operands[0]));
01000                         write32(operands[0], result);
01001                         break;
01002                     }
01003                     default:
01004                         throw Exception("size not implemented", insn);
01005                         break;
01006                 }
01007                 break;
01008             }
01009 
01010             case x86_xadd: {
01011                 if (operands.size()!=2)
01012                     throw Exception("instruction must have two operands", insn);
01013                 switch (numBytesInAsmType(operands[0]->get_type())) {
01014                     case 1: {
01015                         Word(8) result = doAddOperation<8>(read8(operands[0]), read8(operands[1]), false, policy.false_());
01016                         write8(operands[1], read8(operands[0]));
01017                         write8(operands[0], result);
01018                         break;
01019                     }
01020                     case 2: {
01021                         Word(16) result = doAddOperation<16>(read16(operands[0]), read16(operands[1]), false, policy.false_());
01022                         write16(operands[1], read16(operands[0]));
01023                         write16(operands[0], result);
01024                         break;
01025                     }
01026                     case 4: {
01027                         Word(32) result = doAddOperation<32>(read32(operands[0]), read32(operands[1]), false, policy.false_());
01028                         write32(operands[1], read32(operands[0]));
01029                         write32(operands[0], result);
01030                         break;
01031                     }
01032                     default:
01033                         throw Exception("size not implemented", insn);
01034                         break;
01035                 }
01036                 break;
01037             }
01038 
01039             case x86_add: {
01040                 if (operands.size()!=2)
01041                     throw Exception("instruction must have two operands", insn);
01042                 switch (numBytesInAsmType(operands[0]->get_type())) {
01043                     case 1: {
01044                         Word(8) result = doAddOperation<8>(read8(operands[0]), read8(operands[1]), false, policy.false_());
01045                         write8(operands[0], result);
01046                         break;
01047                     }
01048                     case 2: {
01049                         Word(16) result = doAddOperation<16>(read16(operands[0]), read16(operands[1]), false, policy.false_());
01050                         write16(operands[0], result);
01051                         break;
01052                     }
01053                     case 4: {
01054                         Word(32) result = doAddOperation<32>(read32(operands[0]), read32(operands[1]), false, policy.false_());
01055                         write32(operands[0], result);
01056                         break;
01057                     }
01058                     default:
01059                         throw Exception("size not implemented", insn);
01060                         break;
01061                 }
01062                 break;
01063             }
01064 
01065             case x86_adc: {
01066                 if (operands.size()!=2)
01067                     throw Exception("instruction must have two operands", insn);
01068                 switch (numBytesInAsmType(operands[0]->get_type())) {
01069                     case 1: {
01070                         Word(8) result = doAddOperation<8>(read8(operands[0]), read8(operands[1]), false,
01071                                                            readRegister<1>(REG_CF));
01072                         write8(operands[0], result);
01073                         break;
01074                     }
01075                     case 2: {
01076                         Word(16) result = doAddOperation<16>(read16(operands[0]), read16(operands[1]), false,
01077                                                              readRegister<1>(REG_CF));
01078                         write16(operands[0], result);
01079                         break;
01080                     }
01081                     case 4: {
01082                         Word(32) result = doAddOperation<32>(read32(operands[0]), read32(operands[1]), false,
01083                                                              readRegister<1>(REG_CF));
01084                         write32(operands[0], result);
01085                         break;
01086                     }
01087                     default:
01088                         throw Exception("size not implemented", insn);
01089                         break;
01090                 }
01091                 break;
01092             }
01093 
01094             case x86_sub: {
01095                 if (operands.size()!=2)
01096                     throw Exception("instruction must have two operands", insn);
01097                 switch (numBytesInAsmType(operands[0]->get_type())) {
01098                     case 1: {
01099                         Word(8) result = doAddOperation<8>(read8(operands[0]), policy.invert(read8(operands[1])), true,
01100                                                            policy.false_());
01101                         write8(operands[0], result);
01102                         break;
01103                     }
01104                     case 2: {
01105                         Word(16) result = doAddOperation<16>(read16(operands[0]), policy.invert(read16(operands[1])), true,
01106                                                              policy.false_());
01107                         write16(operands[0], result);
01108                         break;
01109                     }
01110                     case 4: {
01111                         Word(32) result = doAddOperation<32>(read32(operands[0]), policy.invert(read32(operands[1])), true,
01112                                                              policy.false_());
01113                         write32(operands[0], result);
01114                         break;
01115                     }
01116                     default:
01117                         throw Exception("size not implemented", insn);
01118                         break;
01119                 }
01120                 break;
01121             }
01122 
01123             case x86_sbb: {
01124                 if (operands.size()!=2)
01125                     throw Exception("instruction must have two operands", insn);
01126                 switch (numBytesInAsmType(operands[0]->get_type())) {
01127                     case 1: {
01128                         Word(8) result = doAddOperation<8>(read8(operands[0]), policy.invert(read8(operands[1])), true,
01129                                                            readRegister<1>(REG_CF));
01130                         write8(operands[0], result);
01131                         break;
01132                     }
01133                     case 2: {
01134                         Word(16) result = doAddOperation<16>(read16(operands[0]), policy.invert(read16(operands[1])), true,
01135                                                              readRegister<1>(REG_CF));
01136                         write16(operands[0], result);
01137                         break;
01138                     }
01139                     case 4: {
01140                         Word(32) result = doAddOperation<32>(read32(operands[0]), policy.invert(read32(operands[1])), true,
01141                                                              readRegister<1>(REG_CF));
01142                         write32(operands[0], result);
01143                         break;
01144                     }
01145                     default:
01146                         throw Exception("size not implemented", insn);
01147                         break;
01148                 }
01149                 break;
01150             }
01151 
01152             case x86_cmp: {
01153                 if (operands.size()!=2)
01154                     throw Exception("instruction must have two operands", insn);
01155                 switch (numBytesInAsmType(operands[0]->get_type())) {
01156                     case 1: {
01157                         doAddOperation<8>(read8(operands[0]), policy.invert(read8(operands[1])), true, policy.false_());
01158                         break;
01159                     }
01160                     case 2: {
01161                         doAddOperation<16>(read16(operands[0]), policy.invert(read16(operands[1])), true, policy.false_());
01162                         break;
01163                     }
01164                     case 4: {
01165                         doAddOperation<32>(read32(operands[0]), policy.invert(read32(operands[1])), true, policy.false_());
01166                         break;
01167                     }
01168                     default:
01169                         throw Exception("size not implemented", insn);
01170                         break;
01171                 }
01172                 break;
01173             }
01174 
01175             case x86_neg: {
01176                 if (operands.size()!=1)
01177                     throw Exception("instruction must have one operand", insn);
01178                 switch (numBytesInAsmType(operands[0]->get_type())) {
01179                     case 1: {
01180                         Word(8) result = doAddOperation<8>(number<8>(0), policy.invert(read8(operands[0])), true,
01181                                                            policy.false_());
01182                         write8(operands[0], result);
01183                         break;
01184                     }
01185                     case 2: {
01186                         Word(16) result = doAddOperation<16>(number<16>(0), policy.invert(read16(operands[0])), true,
01187                                                              policy.false_());
01188                         write16(operands[0], result);
01189                         break;
01190                     }
01191                     case 4: {
01192                         Word(32) result = doAddOperation<32>(number<32>(0), policy.invert(read32(operands[0])), true,
01193                                                              policy.false_());
01194                         write32(operands[0], result);
01195                         break;
01196                     }
01197                     default:
01198                         throw Exception("size not implemented", insn);
01199                         break;
01200                 }
01201                 break;
01202             }
01203 
01204             case x86_inc: {
01205                 if (operands.size()!=1)
01206                     throw Exception("instruction must have one operand", insn);
01207                 switch (numBytesInAsmType(operands[0]->get_type())) {
01208                     case 1: {
01209                         Word(8) result = doIncOperation<8>(read8(operands[0]), false, false);
01210                         write8(operands[0], result);
01211                         break;
01212                     }
01213                     case 2: {
01214                         Word(16) result = doIncOperation<16>(read16(operands[0]), false, false);
01215                         write16(operands[0], result);
01216                         break;
01217                     }
01218                     case 4: {
01219                         Word(32) result = doIncOperation<32>(read32(operands[0]), false, false);
01220                         write32(operands[0], result);
01221                         break;
01222                     }
01223                     default:
01224                         throw Exception("size not implemented", insn);
01225                         break;
01226                 }
01227                 break;
01228             }
01229 
01230             case x86_dec: {
01231                 if (operands.size()!=1)
01232                     throw Exception("instruction must have one operand", insn);
01233                 switch (numBytesInAsmType(operands[0]->get_type())) {
01234                     case 1: {
01235                         Word(8) result = doIncOperation<8>(read8(operands[0]), true, false);
01236                         write8(operands[0], result);
01237                         break;
01238                     }
01239                     case 2: {
01240                         Word(16) result = doIncOperation<16>(read16(operands[0]), true, false);
01241                         write16(operands[0], result);
01242                         break;
01243                     }
01244                     case 4: {
01245                         Word(32) result = doIncOperation<32>(read32(operands[0]), true, false);
01246                         write32(operands[0], result);
01247                         break;
01248                     }
01249                     default:
01250                         throw Exception("size not implemented", insn);
01251                         break;
01252                 }
01253                 break;
01254             }
01255 
01256             case x86_cmpxchg: {
01257                 if (operands.size()!=2)
01258                     throw Exception("instruction must have two operands", insn);
01259                 switch (numBytesInAsmType(operands[0]->get_type())) {
01260                     case 1: {
01261                         Word(8) op0 = read8(operands[0]);
01262                         Word(8) oldAx = readRegister<8>(REG_AL);
01263                         doAddOperation<8>(oldAx, policy.invert(op0), true, policy.false_());
01264                         write8(operands[0], policy.ite(readRegister<1>(REG_ZF), read8(operands[1]), op0));
01265                         writeRegister(REG_AL, policy.ite(readRegister<1>(REG_ZF), oldAx, op0));
01266                         break;
01267                     }
01268                     case 2: {
01269                         Word(16) op0 = read16(operands[0]);
01270                         Word(16) oldAx = readRegister<16>(REG_AX);
01271                         doAddOperation<16>(oldAx, policy.invert(op0), true, policy.false_());
01272                         write16(operands[0], policy.ite(readRegister<1>(REG_ZF), read16(operands[1]), op0));
01273                         writeRegister(REG_AX, policy.ite(readRegister<1>(REG_ZF), oldAx, op0));
01274                         break;
01275                     }
01276                     case 4: {
01277                         Word(32) op0 = read32(operands[0]);
01278                         Word(32) oldAx = readRegister<32>(REG_EAX);
01279                         doAddOperation<32>(oldAx, policy.invert(op0), true, policy.false_());
01280                         write32(operands[0], policy.ite(readRegister<1>(REG_ZF), read32(operands[1]), op0));
01281                         writeRegister(REG_EAX, policy.ite(readRegister<1>(REG_ZF), oldAx, op0));
01282                         break;
01283                     }
01284                     default:
01285                         throw Exception("size not implemented", insn);
01286                         break;
01287                 }
01288                 break;
01289             }
01290 
01291             case x86_shl:       // fall through
01292             case x86_sar:       // fall through
01293             case x86_shr: {
01294                 switch (numBytesInAsmType(operands[0]->get_type())) {
01295                     case 1: {
01296                         WordType<8> output = shift_semantics<8, 5>(kind, read8(operands[0]), read8(operands[1]));
01297                         write8(operands[0], output);
01298                         break;
01299                     }
01300                     case 2: {
01301                         WordType<16> output = shift_semantics<16, 5>(kind, read16(operands[0]), read8(operands[1]));
01302                         write16(operands[0], output);
01303                         break;
01304                     }
01305                     case 4: {
01306                         WordType<32> output = shift_semantics<32, 5>(kind, read32(operands[0]), read8(operands[1]));
01307                         write32(operands[0], output);
01308                         break;
01309                     }
01310                     default:
01311                         throw Exception("size not implemented", insn);
01312                 }
01313                 break;
01314             }
01315 
01316             case x86_rol: {
01317                 switch (numBytesInAsmType(operands[0]->get_type())) {
01318                     case 1: {
01319                         Word(8) op = read8(operands[0]);
01320                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
01321                         Word(8) output = policy.rotateLeft(op, shiftCount);
01322                         writeRegister(REG_CF, policy.ite(policy.equalToZero(shiftCount),
01323                                                        readRegister<1>(REG_CF),
01324                                                        extract<0, 1>(output)));
01325                         writeRegister(REG_OF, policy.ite(policy.equalToZero(shiftCount),
01326                                                        readRegister<1>(REG_OF),
01327                                                        policy.xor_(extract<0, 1>(output), extract<7, 8>(output))));
01328                         write8(operands[0], output);
01329                         break;
01330                     }
01331                     case 2: {
01332                         Word(16) op = read16(operands[0]);
01333                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
01334                         Word(16) output = policy.rotateLeft(op, shiftCount);
01335                         writeRegister(REG_CF, policy.ite(policy.equalToZero(shiftCount),
01336                                                        readRegister<1>(REG_CF),
01337                                                        extract<0, 1>(output)));
01338                         writeRegister(REG_OF, policy.ite(policy.equalToZero(shiftCount),
01339                                                        readRegister<1>(REG_OF),
01340                                                        policy.xor_(extract<0, 1>(output), extract<15, 16>(output))));
01341                         write16(operands[0], output);
01342                         break;
01343                     }
01344                     case 4: {
01345                         Word(32) op = read32(operands[0]);
01346                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
01347                         Word(32) output = policy.rotateLeft(op, shiftCount);
01348                         writeRegister(REG_CF, policy.ite(policy.equalToZero(shiftCount),
01349                                                        readRegister<1>(REG_CF),
01350                                                        extract<0, 1>(output)));
01351                         writeRegister(REG_OF, policy.ite(policy.equalToZero(shiftCount),
01352                                                        readRegister<1>(REG_OF),
01353                                                        policy.xor_(extract<0, 1>(output), extract<31, 32>(output))));
01354                         write32(operands[0], output);
01355                         break;
01356                     }
01357                     default:
01358                         throw Exception("size not implemented", insn);
01359                 }
01360                 break;
01361             }
01362 
01363             case x86_ror: {
01364                 switch (numBytesInAsmType(operands[0]->get_type())) {
01365                     case 1: {
01366                         Word(8) op = read8(operands[0]);
01367                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
01368                         Word(8) output = policy.rotateRight(op, shiftCount);
01369                         writeRegister(REG_CF, policy.ite(policy.equalToZero(shiftCount),
01370                                                        readRegister<1>(REG_CF),
01371                                                        extract<7, 8>(output)));
01372                         writeRegister(REG_OF, policy.ite(policy.equalToZero(shiftCount),
01373                                                        readRegister<1>(REG_OF),
01374                                                        policy.xor_(extract<6, 7>(output), extract<7, 8>(output))));
01375                         write8(operands[0], output);
01376                         break;
01377                     }
01378                     case 2: {
01379                         Word(16) op = read16(operands[0]);
01380                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
01381                         Word(16) output = policy.rotateRight(op, shiftCount);
01382                         writeRegister(REG_CF, policy.ite(policy.equalToZero(shiftCount),
01383                                                        readRegister<1>(REG_CF),
01384                                                        extract<15, 16>(output)));
01385                         writeRegister(REG_OF, policy.ite(policy.equalToZero(shiftCount),
01386                                                        readRegister<1>(REG_OF),
01387                                                        policy.xor_(extract<14, 15>(output), extract<15, 16>(output))));
01388                         write16(operands[0], output);
01389                         break;
01390                     }
01391                     case 4: {
01392                         Word(32) op = read32(operands[0]);
01393                         Word(5) shiftCount = extract<0, 5>(read8(operands[1]));
01394                         Word(32) output = policy.rotateRight(op, shiftCount);
01395                         writeRegister(REG_CF, policy.ite(policy.equalToZero(shiftCount),
01396                                                        readRegister<1>(REG_CF),
01397                                                        extract<31, 32>(output)));
01398                         writeRegister(REG_OF, policy.ite(policy.equalToZero(shiftCount),
01399                                                        readRegister<1>(REG_OF),
01400                                                        policy.xor_(extract<30, 31>(output), extract<31, 32>(output))));
01401                         write32(operands[0], output);
01402                         break;
01403                     }
01404                     default:
01405                         throw Exception("size not implemented", insn);
01406                 }
01407                 break;
01408             }
01409 
01410             case x86_shld: {
01411                 Word(5) shiftCount = extract<0, 5>(read8(operands[2]));
01412                 switch (numBytesInAsmType(operands[0]->get_type())) {
01413                     case 2: {
01414                         Word(16) op1 = read16(operands[0]);
01415                         Word(16) op2 = read16(operands[1]);
01416                         Word(16) output1 = policy.shiftLeft(op1, shiftCount);
01417                         Word(16) output2 = policy.ite(policy.equalToZero(shiftCount),
01418                                                       number<16>(0),
01419                                                       policy.shiftRight(op2, policy.negate(shiftCount)));
01420                         Word(16) output = policy.or_(output1, output2);
01421                         Word(1) newCf = policy.ite(policy.equalToZero(shiftCount),
01422                                                    readRegister<1>(REG_CF),
01423                                                    extract<15, 16>(policy.shiftLeft(op1, policy.add(shiftCount, number<5>(15)))));
01424                         writeRegister(REG_CF, newCf);
01425                         Word(1) newOf = policy.ite(policy.equalToZero(shiftCount),
01426                                                    readRegister<1>(REG_OF), 
01427                                                    policy.xor_(extract<15, 16>(output), newCf));
01428                         writeRegister(REG_OF, newOf);
01429                         write16(operands[0], output);
01430                         setFlagsForResult<16>(output);
01431                         writeRegister(REG_AF, policy.ite(policy.equalToZero(shiftCount),
01432                                                        readRegister<1>(REG_AF),
01433                                                        policy.undefined_()));
01434                         break;
01435                     }
01436                     case 4: {
01437                         Word(32) op1 = read32(operands[0]);
01438                         Word(32) op2 = read32(operands[1]);
01439                         Word(5) shiftCount = extract<0, 5>(read8(operands[2]));
01440                         Word(32) output1 = policy.shiftLeft(op1, shiftCount);
01441                         Word(32) output2 = policy.ite(policy.equalToZero(shiftCount),
01442                                                       number<32>(0),
01443                                                       policy.shiftRight(op2, policy.negate(shiftCount)));
01444                         Word(32) output = policy.or_(output1, output2);
01445                         Word(1) newCf = policy.ite(policy.equalToZero(shiftCount),
01446                                                    readRegister<1>(REG_CF),
01447                                                    extract<31, 32>(policy.shiftLeft(op1, policy.add(shiftCount, number<5>(31)))));
01448                         writeRegister(REG_CF, newCf);
01449                         Word(1) newOf = policy.ite(policy.equalToZero(shiftCount),
01450                                                    readRegister<1>(REG_OF), 
01451                                                    policy.xor_(extract<31, 32>(output), newCf));
01452                         writeRegister(REG_OF, newOf);
01453                         write32(operands[0], output);
01454                         setFlagsForResult<32>(output);
01455                         writeRegister(REG_AF, policy.ite(policy.equalToZero(shiftCount),
01456                                                        readRegister<1>(REG_AF),
01457                                                        policy.undefined_()));
01458                         break;
01459                     }
01460                     default:
01461                         throw Exception("size not implemented", insn);
01462                 }
01463                 break;
01464             }
01465 
01466             case x86_shrd: {
01467                 Word(5) shiftCount = extract<0, 5>(read8(operands[2]));
01468                 switch (numBytesInAsmType(operands[0]->get_type())) {
01469                     case 2: {
01470                         Word(16) op1 = read16(operands[0]);
01471                         Word(16) op2 = read16(operands[1]);
01472                         Word(16) output1 = policy.shiftRight(op1, shiftCount);
01473                         Word(16) output2 = policy.ite(policy.equalToZero(shiftCount),
01474                                                       number<16>(0),
01475                                                       policy.shiftLeft(op2, policy.negate(shiftCount)));
01476                         Word(16) output = policy.or_(output1, output2);
01477                         Word(1) newCf = policy.ite(policy.equalToZero(shiftCount),
01478                                                    readRegister<1>(REG_CF),
01479                                                    extract<0, 1>(policy.shiftRight(op1, policy.add(shiftCount, number<5>(15)))));
01480                         writeRegister(REG_CF, newCf);
01481                         Word(1) newOf = policy.ite(policy.equalToZero(shiftCount),
01482                                                    readRegister<1>(REG_OF), 
01483                                                    policy.xor_(extract<15, 16>(output),
01484                                                                extract<15, 16>(op1)));
01485                         writeRegister(REG_OF, newOf);
01486                         write16(operands[0], output);
01487                         setFlagsForResult<16>(output);
01488                         writeRegister(REG_AF, policy.ite(policy.equalToZero(shiftCount),
01489                                                        readRegister<1>(REG_AF),
01490                                                        policy.undefined_()));
01491                         break;
01492                     }
01493                     case 4: {
01494                         Word(32) op1 = read32(operands[0]);
01495                         Word(32) op2 = read32(operands[1]);
01496                         Word(32) output1 = policy.shiftRight(op1, shiftCount);
01497                         Word(32) output2 = policy.ite(policy.equalToZero(shiftCount),
01498                                                       number<32>(0),
01499                                                       policy.shiftLeft(op2, policy.negate(shiftCount)));
01500                         Word(32) output = policy.or_(output1, output2);
01501                         Word(1) newCf = policy.ite(policy.equalToZero(shiftCount),
01502                                                    readRegister<1>(REG_CF),
01503                                                    extract<0, 1>(policy.shiftRight(op1, policy.add(shiftCount, number<5>(31)))));
01504                         writeRegister(REG_CF, newCf);
01505                         Word(1) newOf = policy.ite(policy.equalToZero(shiftCount),
01506                                                    readRegister<1>(REG_OF), 
01507                                                    policy.xor_(extract<31, 32>(output),
01508                                                                extract<31, 32>(op1)));
01509                         writeRegister(REG_OF, newOf);
01510                         write32(operands[0], output);
01511                         setFlagsForResult<32>(output);
01512                         writeRegister(REG_AF, policy.ite(policy.equalToZero(shiftCount),
01513                                                        readRegister<1>(REG_AF),
01514                                                        policy.undefined_()));
01515                         break;
01516                     }
01517                     default:
01518                         throw Exception("size not implemented", insn);
01519                 }
01520                 break;
01521             }
01522 
01523             case x86_bsf: {
01524                 writeRegister(REG_OF, policy.undefined_());
01525                 writeRegister(REG_SF, policy.undefined_());
01526                 writeRegister(REG_AF, policy.undefined_());
01527                 writeRegister(REG_PF, policy.undefined_());
01528                 writeRegister(REG_CF, policy.undefined_());
01529                 switch (numBytesInAsmType(operands[0]->get_type())) {
01530                     case 2: {
01531                         Word(16) op = read16(operands[1]);
01532                         writeRegister(REG_ZF, policy.equalToZero(op));
01533                         Word(16) result = policy.ite(readRegister<1>(REG_ZF),
01534                                                      read16(operands[0]),
01535                                                      policy.leastSignificantSetBit(op));
01536                         write16(operands[0], result);
01537                         break;
01538                     }
01539                     case 4: {
01540                         Word(32) op = read32(operands[1]);
01541                         writeRegister(REG_ZF, policy.equalToZero(op));
01542                         Word(32) result = policy.ite(readRegister<1>(REG_ZF),
01543                                                      read32(operands[0]),
01544                                                      policy.leastSignificantSetBit(op));
01545                         write32(operands[0], result);
01546                         break;
01547                     }
01548                     default:
01549                         throw Exception("size not implemented", insn);
01550                 }
01551                 break;
01552             }
01553 
01554             case x86_bsr: {
01555                 writeRegister(REG_OF, policy.undefined_());
01556                 writeRegister(REG_SF, policy.undefined_());
01557                 writeRegister(REG_AF, policy.undefined_());
01558                 writeRegister(REG_PF, policy.undefined_());
01559                 writeRegister(REG_CF, policy.undefined_());
01560                 switch (numBytesInAsmType(operands[0]->get_type())) {
01561                     case 2: {
01562                         Word(16) op = read16(operands[1]);
01563                         writeRegister(REG_ZF, policy.equalToZero(op));
01564                         Word(16) result = policy.ite(readRegister<1>(REG_ZF),
01565                                                      read16(operands[0]),
01566                                                      policy.mostSignificantSetBit(op));
01567                         write16(operands[0], result);
01568                         break;
01569                     }
01570                     case 4: {
01571                         Word(32) op = read32(operands[1]);
01572                         writeRegister(REG_ZF, policy.equalToZero(op));
01573                         Word(32) result = policy.ite(readRegister<1>(REG_ZF),
01574                                                      read32(operands[0]),
01575                                                      policy.mostSignificantSetBit(op));
01576                         write32(operands[0], result);
01577                         break;
01578                     }
01579                     default:
01580                         throw Exception("size not implemented", insn);
01581                 }
01582                 break;
01583             }
01584 
01585             case x86_bt: {              /* Bit test */
01586                 if (operands.size()!=2)
01587                     throw Exception("instruction must have two operands", insn);
01588                 
01589                 /* All flags except CF are undefined */
01590                 writeRegister(REG_OF, policy.undefined_());
01591                 writeRegister(REG_SF, policy.undefined_());
01592                 writeRegister(REG_ZF, policy.undefined_());
01593                 writeRegister(REG_AF, policy.undefined_());
01594                 writeRegister(REG_PF, policy.undefined_());
01595                 
01596                 if (isSgAsmMemoryReferenceExpression(operands[0]) && isSgAsmx86RegisterReferenceExpression(operands[1])) {
01597                     /* Special case allowing multi-word offsets into memory */
01598                     Word(32) addr = readEffectiveAddress(operands[0]);
01599                     int numBytes = numBytesInAsmType(operands[1]->get_type());
01600                     Word(32) bitnum = numBytes == 2 ? signExtend<16, 32>(read16(operands[1])) : read32(operands[1]);
01601                     Word(32) adjustedAddr = policy.add(addr, signExtend<29, 32>(extract<3, 32>(bitnum)));
01602                     Word(8) val = readMemory<8>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(operands[0])),
01603                                                 adjustedAddr, policy.true_());
01604                     Word(1) bitval = extract<0, 1>(policy.rotateRight(val, extract<0, 3>(bitnum)));
01605                     writeRegister(REG_CF, bitval);
01606                 } else {
01607                     /* Simple case */
01608                     switch (numBytesInAsmType(operands[0]->get_type())) {
01609                         case 2: {
01610                             Word(16) op0 = read16(operands[0]);
01611                             Word(4) bitnum = extract<0, 4>(read16(operands[1]));
01612                             Word(1) bitval = extract<0, 1>(policy.rotateRight(op0, bitnum));
01613                             writeRegister(REG_CF, bitval);
01614                             break;
01615                         }
01616                         case 4: {
01617                             Word(32) op0 = read32(operands[0]);
01618                             Word(5) bitnum = extract<0, 5>(read32(operands[1]));
01619                             Word(1) bitval = extract<0, 1>(policy.rotateRight(op0, bitnum));
01620                             writeRegister(REG_CF, bitval);
01621                             break;
01622                         }
01623                         default:
01624                             throw Exception("size not implemented", insn);
01625                     }
01626                 }
01627                 break;
01628             }
01629                 
01630             case x86_btr: {             /* Bit test and reset */
01631                 if (operands.size()!=2)
01632                     throw Exception("instruction must have two operands", insn);
01633                 
01634                 /* All flags except CF are undefined */
01635                 writeRegister(REG_OF, policy.undefined_());
01636                 writeRegister(REG_SF, policy.undefined_());
01637                 writeRegister(REG_ZF, policy.undefined_());
01638                 writeRegister(REG_AF, policy.undefined_());
01639                 writeRegister(REG_PF, policy.undefined_());
01640                 
01641                 if (isSgAsmMemoryReferenceExpression(operands[0]) && isSgAsmx86RegisterReferenceExpression(operands[1])) {
01642                     /* Special case allowing multi-word offsets into memory */
01643                     Word(32) addr = readEffectiveAddress(operands[0]);
01644                     int numBytes = numBytesInAsmType(operands[1]->get_type());
01645                     Word(32) bitnum = numBytes == 2 ? signExtend<16, 32>(read16(operands[1])) : read32(operands[1]);
01646                     Word(32) adjustedAddr = policy.add(addr, signExtend<29, 32>(extract<3, 32>(bitnum)));
01647                     Word(8) val = readMemory<8>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(operands[0])),
01648                                                 adjustedAddr, policy.true_());
01649                     Word(1) bitval = extract<0, 1>(policy.rotateRight(val, extract<0, 3>(bitnum)));
01650                     Word(8) result = policy.and_(val,
01651                                                  policy.invert(policy.rotateLeft(number<8>(1),
01652                                                                                  extract<0, 3>(bitnum))));
01653                     writeRegister(REG_CF, bitval);
01654                     policy.writeMemory(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(operands[0])),
01655                                        adjustedAddr, result, policy.true_());
01656                 } else {
01657                     /* Simple case */
01658                     switch (numBytesInAsmType(operands[0]->get_type())) {
01659                         case 2: {
01660                             Word(16) op0 = read16(operands[0]);
01661                             Word(4) bitnum = extract<0, 4>(read16(operands[1]));
01662                             Word(1) bitval = extract<0, 1>(policy.rotateRight(op0, bitnum));
01663                             Word(16) result = policy.and_(op0, policy.invert(policy.rotateLeft(number<16>(1), bitnum)));
01664                             writeRegister(REG_CF, bitval);
01665                             write16(operands[0], result);
01666                             break;
01667                         }
01668                         case 4: {
01669                             Word(32) op0 = read32(operands[0]);
01670                             Word(5) bitnum = extract<0, 5>(read32(operands[1]));
01671                             Word(1) bitval = extract<0, 1>(policy.rotateRight(op0, bitnum));
01672                             Word(32) result = policy.and_(op0, policy.invert(policy.rotateLeft(number<32>(1), bitnum)));
01673                             writeRegister(REG_CF, bitval);
01674                             write32(operands[0], result);
01675                             break;
01676                         }
01677                         default:
01678                             throw Exception("size not implemented", insn);
01679                     }
01680                 }
01681                 break;
01682             }
01683 
01684             case x86_bts: {             /* bit test and set */
01685                 if (operands.size()!=2)
01686                     throw Exception("instruction must have two operands", insn);
01687                 
01688                 /* All flags except CF are undefined */
01689                 writeRegister(REG_OF, policy.undefined_());
01690                 writeRegister(REG_SF, policy.undefined_());
01691                 writeRegister(REG_ZF, policy.undefined_());
01692                 writeRegister(REG_AF, policy.undefined_());
01693                 writeRegister(REG_PF, policy.undefined_());
01694                 
01695                 if (isSgAsmMemoryReferenceExpression(operands[0]) && isSgAsmx86RegisterReferenceExpression(operands[1])) {
01696                     /* Special case allowing multi-word offsets into memory */
01697                     Word(32) addr = readEffectiveAddress(operands[0]);
01698                     int numBytes = numBytesInAsmType(operands[1]->get_type());
01699                     Word(32) bitnum = numBytes == 2 ? signExtend<16, 32>(read16(operands[1])) : read32(operands[1]);
01700                     Word(32) adjustedAddr = policy.add(addr, signExtend<29, 32>(extract<3, 32>(bitnum)));
01701                     Word(8) val = readMemory<8>(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(operands[0])),
01702                                                 adjustedAddr, policy.true_());
01703                     Word(1) bitval = extract<0, 1>(policy.rotateRight(val, extract<0, 3>(bitnum)));
01704                     Word(8) result = policy.or_(val, policy.rotateLeft(number<8>(1), extract<0, 3>(bitnum)));
01705                     writeRegister(REG_CF, bitval);
01706                     policy.writeMemory(getSegregFromMemoryReference(isSgAsmMemoryReferenceExpression(operands[0])),
01707                                        adjustedAddr, result, policy.true_());
01708                 } else {
01709                     /* Simple case */
01710                     switch (numBytesInAsmType(operands[0]->get_type())) {
01711                         case 2: {
01712                             Word(16) op0 = read16(operands[0]);
01713                             Word(4) bitnum = extract<0, 4>(read16(operands[1]));
01714                             Word(1) bitval = extract<0, 1>(policy.rotateRight(op0, bitnum));
01715                             Word(16) result = policy.or_(op0, policy.rotateLeft(number<16>(1), bitnum));
01716                             writeRegister(REG_CF, bitval);
01717                             write16(operands[0], result);
01718                             break;
01719                         }
01720                         case 4: {
01721                             Word(32) op0 = read32(operands[0]);
01722                             Word(5) bitnum = extract<0, 5>(read32(operands[1]));
01723                             Word(1) bitval = extract<0, 1>(policy.rotateRight(op0, bitnum));
01724                             Word(32) result = policy.or_(op0, policy.rotateLeft(number<32>(1), bitnum));
01725                             writeRegister(REG_CF, bitval);
01726                             write32(operands[0], result);
01727                             break;
01728                         }
01729                         default:
01730                             throw Exception("size not implemented", insn);
01731                     }
01732                 }
01733                 break;
01734             }
01735 
01736             case x86_imul: {
01737                 switch (numBytesInAsmType(operands[0]->get_type())) {
01738                     case 1: {
01739                         Word(8) op0 = readRegister<8>(REG_AL);
01740                         Word(8) op1 = read8(operands[0]);
01741                         Word(16) mulResult = policy.signedMultiply(op0, op1);
01742                         writeRegister(REG_AX, mulResult);
01743                         Word(1) carry = policy.invert(policy.or_(policy.equalToZero(policy.invert(extract<7, 16>(mulResult))),
01744                                                                  policy.equalToZero(extract<7, 16>(mulResult))));
01745                         writeRegister(REG_CF, carry);
01746                         writeRegister(REG_OF, carry);
01747                         break;
01748                     }
01749                     case 2: {
01750                         Word(16) op0 = operands.size() == 1 ?
01751                                        readRegister<16>(REG_AX) :
01752                                        read16(operands[operands.size() - 2]);
01753                         Word(16) op1 = read16(operands[operands.size() - 1]);
01754                         Word(32) mulResult = policy.signedMultiply(op0, op1);
01755                         if (operands.size() == 1) {
01756                             writeRegister(REG_AX, extract<0, 16>(mulResult));
01757                             writeRegister(REG_DX, extract<16, 32>(mulResult));
01758                         } else {
01759                             write16(operands[0], extract<0, 16>(mulResult));
01760                         }
01761                         Word(1) carry = policy.invert(policy.or_(policy.equalToZero(policy.invert(extract<7, 32>(mulResult))),
01762                                                                  policy.equalToZero(extract<7, 32>(mulResult))));
01763                         writeRegister(REG_CF, carry);
01764                         writeRegister(REG_OF, carry);
01765                         break;
01766                     }
01767                     case 4: {
01768                         Word(32) op0 = operands.size() == 1 ?
01769                                        readRegister<32>(REG_EAX) :
01770                                        read32(operands[operands.size() - 2]);
01771                         Word(32) op1 = read32(operands[operands.size() - 1]);
01772                         Word(64) mulResult = policy.signedMultiply(op0, op1);
01773                         if (operands.size() == 1) {
01774                             writeRegister(REG_EAX, extract<0, 32>(mulResult));
01775                             writeRegister(REG_EDX, extract<32, 64>(mulResult));
01776                         } else {
01777                             write32(operands[0], extract<0, 32>(mulResult));
01778                         }
01779                         Word(1) carry = policy.invert(policy.or_(policy.equalToZero(policy.invert(extract<7, 64>(mulResult))),
01780                                                                  policy.equalToZero(extract<7, 64>(mulResult))));
01781                         writeRegister(REG_CF, carry);
01782                         writeRegister(REG_OF, carry);
01783                         break;
01784                     }
01785                     default:
01786                         throw Exception("size not implemented", insn);
01787                 }
01788                 writeRegister(REG_SF, policy.undefined_());
01789                 writeRegister(REG_ZF, policy.undefined_());
01790                 writeRegister(REG_AF, policy.undefined_());
01791                 writeRegister(REG_PF, policy.undefined_());
01792                 break;
01793             }
01794 
01795             case x86_mul: {
01796                 switch (numBytesInAsmType(operands[0]->get_type())) {
01797                     case 1: {
01798                         Word(8) op0 = readRegister<8>(REG_AL);
01799                         Word(8) op1 = read8(operands[0]);
01800                         Word(16) mulResult = policy.unsignedMultiply(op0, op1);
01801                         writeRegister(REG_AX, mulResult);
01802                         Word(1) carry = policy.invert(policy.equalToZero(extract<8, 16>(mulResult)));
01803                         writeRegister(REG_CF, carry);
01804                         writeRegister(REG_OF, carry);
01805                         break;
01806                     }
01807                     case 2: {
01808                         Word(16) op0 = readRegister<16>(REG_AX);
01809                         Word(16) op1 = read16(operands[0]);
01810                         Word(32) mulResult = policy.unsignedMultiply(op0, op1);
01811                         writeRegister(REG_AX, extract<0, 16>(mulResult));
01812                         writeRegister(REG_DX, extract<16, 32>(mulResult));
01813                         Word(1) carry = policy.invert(policy.equalToZero(extract<16, 32>(mulResult)));
01814                         writeRegister(REG_CF, carry);
01815                         writeRegister(REG_OF, carry);
01816                         break;
01817                     }
01818                     case 4: {
01819                         Word(32) op0 = readRegister<32>(REG_EAX);
01820                         Word(32) op1 = read32(operands[0]);
01821                         Word(64) mulResult = policy.unsignedMultiply(op0, op1);
01822                         writeRegister(REG_EAX, extract<0, 32>(mulResult));
01823                         writeRegister(REG_EDX, extract<32, 64>(mulResult));
01824                         Word(1) carry = policy.invert(policy.equalToZero(extract<32, 64>(mulResult)));
01825                         writeRegister(REG_CF, carry);
01826                         writeRegister(REG_OF, carry);
01827                         break;
01828                     }
01829                     default:
01830                         throw Exception("size not implemented", insn);
01831                 }
01832                 writeRegister(REG_SF, policy.undefined_());
01833                 writeRegister(REG_ZF, policy.undefined_());
01834                 writeRegister(REG_AF, policy.undefined_());
01835                 writeRegister(REG_PF, policy.undefined_());
01836                 break;
01837             }
01838 
01839             case x86_idiv: {
01840                 switch (numBytesInAsmType(operands[0]->get_type())) {
01841                     case 1: {
01842                         Word(16) op0 = readRegister<16>(REG_AX);
01843                         Word(8) op1 = read8(operands[0]);
01844                         /* if op1 == 0, we should trap */
01845                         Word(16) divResult = policy.signedDivide(op0, op1);
01846                         Word(8) modResult = policy.signedModulo(op0, op1);
01847                         /* if result overflows, we should trap */
01848                         writeRegister(REG_AX, policy.concat(extract<0, 8>(divResult), modResult));
01849                         break;
01850                     }
01851                     case 2: {
01852                         Word(32) op0 = policy.concat(readRegister<16>(REG_AX), readRegister<16>(REG_DX));
01853                         Word(16) op1 = read16(operands[0]);
01854                         /* if op1 == 0, we should trap */
01855                         Word(32) divResult = policy.signedDivide(op0, op1);
01856                         Word(16) modResult = policy.signedModulo(op0, op1);
01857                         /* if result overflows, we should trap */
01858                         writeRegister(REG_AX, extract<0, 16>(divResult));
01859                         writeRegister(REG_DX, modResult);
01860                         break;
01861                     }
01862                     case 4: {
01863                         Word(64) op0 = policy.concat(readRegister<32>(REG_EAX), readRegister<32>(REG_EDX));
01864                         Word(32) op1 = read32(operands[0]);
01865                         /* if op1 == 0, we should trap */
01866                         Word(64) divResult = policy.signedDivide(op0, op1);
01867                         Word(32) modResult = policy.signedModulo(op0, op1);
01868                         /* if result overflows, we should trap */
01869                         writeRegister(REG_EAX, extract<0, 32>(divResult));
01870                         writeRegister(REG_EDX, modResult);
01871                         break;
01872                     }
01873                     default:
01874                         throw Exception("size not implemented", insn);
01875                 }
01876                 writeRegister(REG_SF, policy.undefined_());
01877                 writeRegister(REG_ZF, policy.undefined_());
01878                 writeRegister(REG_AF, policy.undefined_());
01879                 writeRegister(REG_PF, policy.undefined_());
01880                 writeRegister(REG_CF, policy.undefined_());
01881                 writeRegister(REG_OF, policy.undefined_());
01882                 break;
01883             }
01884 
01885             case x86_div: {
01886                 switch (numBytesInAsmType(operands[0]->get_type())) {
01887                     case 1: {
01888                         Word(16) op0 = readRegister<16>(REG_AX);
01889                         Word(8) op1 = read8(operands[0]);
01890                         /* if op1 == 0, we should trap */
01891                         Word(16) divResult = policy.unsignedDivide(op0, op1);
01892                         Word(8) modResult = policy.unsignedModulo(op0, op1);
01893                         /* if extract<8, 16> of divResult is non-zero (overflow), we should trap */
01894                         writeRegister(REG_AX, policy.concat(extract<0, 8>(divResult), modResult));
01895                         break;
01896                     }
01897                     case 2: {
01898                         Word(32) op0 = policy.concat(readRegister<16>(REG_AX), readRegister<16>(REG_DX));
01899                         Word(16) op1 = read16(operands[0]);
01900                         /* if op1 == 0, we should trap */
01901                         Word(32) divResult = policy.unsignedDivide(op0, op1);
01902                         Word(16) modResult = policy.unsignedModulo(op0, op1);
01903                         /* if extract<16, 32> of divResult is non-zero (overflow), we should trap */
01904                         writeRegister(REG_AX, extract<0, 16>(divResult));
01905                         writeRegister(REG_DX, modResult);
01906                         break;
01907                     }
01908                     case 4: {
01909                         Word(64) op0 = policy.concat(readRegister<32>(REG_EAX), readRegister<32>(REG_EDX));
01910                         Word(32) op1 = read32(operands[0]);
01911                         /* if op1 == 0, we should trap */
01912                         Word(64) divResult = policy.unsignedDivide(op0, op1);
01913                         Word(32) modResult = policy.unsignedModulo(op0, op1);
01914                         /* if extract<32, 64> of divResult is non-zero (overflow), we should trap */
01915                         writeRegister(REG_EAX, extract<0, 32>(divResult));
01916                         writeRegister(REG_EDX, modResult);
01917                         break;
01918                     }
01919                     default:
01920                         throw Exception("size not implemented", insn);
01921                 }
01922                 writeRegister(REG_SF, policy.undefined_());
01923                 writeRegister(REG_ZF, policy.undefined_());
01924                 writeRegister(REG_AF, policy.undefined_());
01925                 writeRegister(REG_PF, policy.undefined_());
01926                 writeRegister(REG_CF, policy.undefined_());
01927                 writeRegister(REG_OF, policy.undefined_());
01928                 break;
01929             }
01930 
01931             case x86_aaa: {
01932                 if (operands.size()!=0)
01933                     throw Exception("instruction must have no operands", insn);
01934                 Word(1) incAh = policy.or_(readRegister<1>(REG_AF),
01935                                            greaterOrEqualToTen(extract<0, 4>(readRegister<8>(REG_AL))));
01936                 writeRegister(REG_AX, 
01937                               policy.concat(policy.add(policy.ite(incAh, number<4>(6), number<4>(0)),
01938                                                        extract<0, 4>(readRegister<8>(REG_AL))),
01939                                             policy.concat(number<4>(0),
01940                                                           policy.add(policy.ite(incAh, number<8>(1), number<8>(0)),
01941                                                                      readRegister<8>(REG_AH)))));
01942                 writeRegister(REG_OF, policy.undefined_());
01943                 writeRegister(REG_SF, policy.undefined_());
01944                 writeRegister(REG_ZF, policy.undefined_());
01945                 writeRegister(REG_PF, policy.undefined_());
01946                 writeRegister(REG_AF, incAh);
01947                 writeRegister(REG_CF, incAh);
01948                 break;
01949             }
01950 
01951             case x86_aas: {
01952                 if (operands.size()!=0)
01953                     throw Exception("instruction must have no operands", insn);
01954                 Word(1) decAh = policy.or_(readRegister<1>(REG_AF),
01955                                            greaterOrEqualToTen(extract<0, 4>(readRegister<8>(REG_AL))));
01956                 writeRegister(REG_AX, 
01957                               policy.concat(policy.add(policy.ite(decAh, number<4>(-6), number<4>(0)),
01958                                                        extract<0, 4>(readRegister<8>(REG_AL))),
01959                                             policy.concat(number<4>(0),
01960                                                           policy.add(policy.ite(decAh, number<8>(-1), number<8>(0)),
01961                                                                      readRegister<8>(REG_AH)))));
01962                 writeRegister(REG_OF, policy.undefined_());
01963                 writeRegister(REG_SF, policy.undefined_());
01964                 writeRegister(REG_ZF, policy.undefined_());
01965                 writeRegister(REG_PF, policy.undefined_());
01966                 writeRegister(REG_AF, decAh);
01967                 writeRegister(REG_CF, decAh);
01968                 break;
01969             }
01970 
01971             case x86_aam: {
01972                 if (operands.size()!=1)
01973                     throw Exception("instruction must have one operand", insn);
01974                 Word(8) al = readRegister<8>(REG_AL);
01975                 Word(8) divisor = read8(operands[0]);
01976                 Word(8) newAh = policy.unsignedDivide(al, divisor);
01977                 Word(8) newAl = policy.unsignedModulo(al, divisor);
01978                 writeRegister(REG_AX, policy.concat(newAl, newAh));
01979                 writeRegister(REG_OF, policy.undefined_());
01980                 writeRegister(REG_AF, policy.undefined_());
01981                 writeRegister(REG_CF, policy.undefined_());
01982                 setFlagsForResult<8>(newAl);
01983                 break;
01984             }
01985 
01986             case x86_aad: {
01987                 if (operands.size()!=1)
01988                     throw Exception("instruction must have one operand", insn);
01989                 Word(8) al = readRegister<8>(REG_AL);
01990                 Word(8) ah = readRegister<8>(REG_AH);
01991                 Word(8) divisor = read8(operands[0]);
01992                 Word(8) newAl = policy.add(al, extract<0, 8>(policy.unsignedMultiply(ah, divisor)));
01993                 writeRegister(REG_AX, policy.concat(newAl, number<8>(0)));
01994                 writeRegister(REG_OF, policy.undefined_());
01995                 writeRegister(REG_AF, policy.undefined_());
01996                 writeRegister(REG_CF, policy.undefined_());
01997                 setFlagsForResult<8>(newAl);
01998                 break;
01999             }
02000 
02001             case x86_bswap: {
02002                 if (operands.size()!=1)
02003                     throw Exception("instruction must have one operand", insn);
02004                 Word(32) oldVal = read32(operands[0]);
02005                 Word(32) newVal = policy.concat(extract<24, 32>(oldVal),
02006                                                 policy.concat(extract<16, 24>(oldVal),
02007                                                               policy.concat(extract<8, 16>(oldVal),
02008                                                                             extract<0, 8>(oldVal))));
02009                 write32(operands[0], newVal);
02010                 break;
02011             }
02012 
02013             case x86_push: {
02014                 if (operands.size()!=1)
02015                     throw Exception("instruction must have one operand", insn);
02016                 if (insn->get_addressSize() != x86_insnsize_32 || insn->get_operandSize() != x86_insnsize_32)
02017                         throw Exception("size not implemented", insn);
02018                 Word(32) oldSp = readRegister<32>(REG_ESP);
02019                 Word(32) newSp = policy.add(oldSp, number<32>(-4));
02020                 policy.writeMemory(x86_segreg_ss, newSp, read32(operands[0]), policy.true_());
02021                 writeRegister(REG_ESP, newSp);
02022                 break;
02023             }
02024 
02025             case x86_pushad: {
02026                 if (operands.size()!=0)
02027                     throw Exception("instruction must have no operands", insn);
02028                 if (insn->get_addressSize() != x86_insnsize_32)
02029                     throw Exception("size not implemented", insn);
02030                 Word(32) oldSp = readRegister<32>(REG_ESP);
02031                 Word(32) newSp = policy.add(oldSp, number<32>(-32));
02032                 policy.writeMemory(x86_segreg_ss, newSp,
02033                                    readRegister<32>(REG_EDI), policy.true_());
02034                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(4)),
02035                                    readRegister<32>(REG_ESI), policy.true_());
02036                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(8)),
02037                                    readRegister<32>(REG_EBP), policy.true_());
02038                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(12)),
02039                                    oldSp, policy.true_());
02040                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(16)),
02041                                    readRegister<32>(REG_EBX), policy.true_());
02042                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(20)),
02043                                    readRegister<32>(REG_EDX), policy.true_());
02044                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(24)),
02045                                    readRegister<32>(REG_ECX), policy.true_());
02046                 policy.writeMemory(x86_segreg_ss, policy.add(newSp, number<32>(28)),
02047                                    readRegister<32>(REG_EAX), policy.true_());
02048                 writeRegister(REG_ESP, newSp);
02049                 break;
02050             }
02051 
02052             case x86_pushfd: {
02053                 if (operands.size()!=0)
02054                     throw Exception("instruction must have no operands", insn);
02055                 if (insn->get_addressSize() != x86_insnsize_32)
02056                     throw Exception("size not implemented", insn);
02057                 Word(32) oldSp = readRegister<32>(REG_ESP);
02058                 Word(32) newSp = policy.add(oldSp, number<32>(-4));
02059                 policy.writeMemory(x86_segreg_ss, newSp, readRegister<32>(REG_EFLAGS), policy.true_());
02060                 writeRegister(REG_ESP, newSp);
02061                 break;
02062             }
02063 
02064             case x86_pop: {
02065                 if (operands.size()!=1)
02066                     throw Exception("instruction must have one operand", insn);
02067                 if (insn->get_addressSize() != x86_insnsize_32 || insn->get_operandSize() != x86_insnsize_32)
02068                     throw Exception("size not implemented", insn);
02069                 Word(32) oldSp = readRegister<32>(REG_ESP);
02070                 Word(32) newSp = policy.add(oldSp, number<32>(4));
02071                 writeRegister(REG_ESP, newSp);
02072                 write32(operands[0], readMemory<32>(x86_segreg_ss, oldSp, policy.true_()));
02073                 break;
02074             }
02075 
02076             case x86_popad: {
02077                 if (operands.size()!=0)
02078                     throw Exception("instruction must have no operands", insn);
02079                 if (insn->get_addressSize() != x86_insnsize_32)
02080                     throw Exception("size not implemented", insn);
02081                 Word(32) oldSp = readRegister<32>(REG_ESP);
02082                 Word(32) newSp = policy.add(oldSp, number<32>(32));
02083                 writeRegister(REG_EDI, readMemory<32>(x86_segreg_ss, oldSp, policy.true_()));
02084                 writeRegister(REG_ESI, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(4)), policy.true_()));
02085                 writeRegister(REG_EBP, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(8)), policy.true_()));
02086                 writeRegister(REG_EBX, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(16)), policy.true_()));
02087                 writeRegister(REG_EDX, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(20)), policy.true_()));
02088                 writeRegister(REG_ECX, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(24)), policy.true_()));
02089                 writeRegister(REG_EAX, readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(28)), policy.true_()));
02090                 readMemory<32>(x86_segreg_ss, policy.add(oldSp, number<32>(12)), policy.true_());
02091                 writeRegister(REG_ESP, newSp);
02092                 break;
02093             }
02094 
02095             case x86_leave: {
02096                 if (operands.size()!=0)
02097                     throw Exception("instruction must have no operands", insn);
02098                 writeRegister(REG_ESP, readRegister<32>(REG_EBP));
02099                 if (insn->get_addressSize() != x86_insnsize_32 || insn->get_operandSize() != x86_insnsize_32)
02100                     throw Exception("size not implemented", insn);
02101                 Word(32) oldSp = readRegister<32>(REG_ESP);
02102                 Word(32) newSp = policy.add(oldSp, number<32>(4));
02103                 writeRegister(REG_EBP, readMemory<32>(x86_segreg_ss, oldSp, policy.true_()));
02104                 writeRegister(REG_ESP, newSp);
02105                 break;
02106             }
02107 
02108             case x86_call: {
02109                 if (operands.size()!=1)
02110                     throw Exception("instruction must have one operand", insn);
02111                 if (insn->get_addressSize() != x86_insnsize_32 || insn->get_operandSize() != x86_insnsize_32)
02112                     throw Exception("size not implemented", insn);
02113                 Word(32) oldSp = readRegister<32>(REG_ESP);
02114                 Word(32) newSp = policy.add(oldSp, number<32>(-4));
02115                 policy.writeMemory(x86_segreg_ss, newSp, readRegister<32>(REG_EIP), policy.true_());
02116                 writeRegister(REG_EIP, policy.filterCallTarget(read32(operands[0])));
02117                 writeRegister(REG_ESP, newSp);
02118                 break;
02119             }
02120 
02121             case x86_ret: {
02122                 if (operands.size()>1)
02123                     throw Exception("instruction must have zero or one operand", insn);
02124                 if (insn->get_addressSize() != x86_insnsize_32 || insn->get_operandSize() != x86_insnsize_32)
02125                     throw Exception("size not implemented", insn);
02126                 Word(32) extraBytes = (operands.size() == 1 ? read32(operands[0]) : number<32>(0));
02127                 Word(32) oldSp = readRegister<32>(REG_ESP);
02128                 Word(32) newSp = policy.add(oldSp, policy.add(number<32>(4), extraBytes));
02129                 writeRegister(REG_EIP, policy.filterReturnTarget(readMemory<32>(x86_segreg_ss, oldSp, policy.true_())));
02130                 writeRegister(REG_ESP, newSp);
02131                 break;
02132             }
02133 
02134             case x86_loop: {
02135                 if (operands.size()!=1)
02136                     throw Exception("instruction must have one operand", insn);
02137                 if (insn->get_addressSize() != x86_insnsize_32 || insn->get_operandSize() != x86_insnsize_32)
02138                     throw Exception("size not implemented", insn);
02139                 Word(32) oldCx = readRegister<32>(REG_ECX);
02140                 Word(32) newCx = policy.add(number<32>(-1), oldCx);
02141                 writeRegister(REG_ECX, newCx);
02142                 Word(1) doLoop = policy.invert(policy.equalToZero(newCx));
02143                 writeRegister(REG_EIP, policy.ite(doLoop, read32(operands[0]), readRegister<32>(REG_EIP)));
02144                 break;
02145             }
02146             case x86_loopz: {
02147                 if (operands.size()!=1)
02148                     throw Exception("instruction must have one operand", insn);
02149                 if (insn->get_addressSize() != x86_insnsize_32 || insn->get_operandSize() != x86_insnsize_32)
02150                     throw Exception("size not implemented", insn);
02151                 Word(32) oldCx = readRegister<32>(REG_ECX);
02152                 Word(32) newCx = policy.add(number<32>(-1), oldCx);
02153                 writeRegister(REG_ECX, newCx);
02154                 Word(1) doLoop = policy.and_(policy.invert(policy.equalToZero(newCx)), readRegister<1>(REG_ZF));
02155                 writeRegister(REG_EIP, policy.ite(doLoop, read32(operands[0]), readRegister<32>(REG_EIP)));
02156                 break;
02157             }
02158             case x86_loopnz: {
02159                 if (operands.size()!=1)
02160                     throw Exception("instruction must have one operand", insn);
02161                 if (insn->get_addressSize() != x86_insnsize_32 || insn->get_operandSize() != x86_insnsize_32)
02162                     throw Exception("size not implemented", insn);
02163                 Word(32) oldCx = readRegister<32>(REG_ECX);
02164                 Word(32) newCx = policy.add(number<32>(-1), oldCx);
02165                 writeRegister(REG_ECX, newCx);
02166                 Word(1) doLoop = policy.and_(policy.invert(policy.equalToZero(newCx)),
02167                                              policy.invert(readRegister<1>(REG_ZF)));
02168                 writeRegister(REG_EIP, policy.ite(doLoop, read32(operands[0]), readRegister<32>(REG_EIP)));
02169                 break;
02170             }
02171 
02172             case x86_jmp: {
02173                 if (operands.size()!=1)
02174                     throw Exception("instruction must have one operand", insn);
02175                 writeRegister(REG_EIP, policy.filterIndirectJumpTarget(read32(operands[0])));
02176                 break;
02177             }
02178 
02179 
02180             /* Flag expressions that must be true for a conditional jump to occur. */
02181 #           define FLAGCOMBO_ne    policy.invert(readRegister<1>(REG_ZF))
02182 #           define FLAGCOMBO_e     readRegister<1>(REG_ZF)
02183 #           define FLAGCOMBO_no    policy.invert(readRegister<1>(REG_OF))
02184 #           define FLAGCOMBO_o     readRegister<1>(REG_OF)
02185 #           define FLAGCOMBO_ns    policy.invert(readRegister<1>(REG_SF))
02186 #           define FLAGCOMBO_s     readRegister<1>(REG_SF)
02187 #           define FLAGCOMBO_po    policy.invert(readRegister<1>(REG_PF))
02188 #           define FLAGCOMBO_pe    readRegister<1>(REG_PF)
02189 #           define FLAGCOMBO_ae    policy.invert(readRegister<1>(REG_CF))
02190 #           define FLAGCOMBO_b     readRegister<1>(REG_CF)
02191 #           define FLAGCOMBO_be    policy.or_(FLAGCOMBO_b, FLAGCOMBO_e)
02192 #           define FLAGCOMBO_a     policy.and_(FLAGCOMBO_ae, FLAGCOMBO_ne)
02193 #           define FLAGCOMBO_l     policy.xor_(readRegister<1>(REG_SF), readRegister<1>(REG_OF))
02194 #           define FLAGCOMBO_ge    policy.invert(policy.xor_(readRegister<1>(REG_SF), readRegister<1>(REG_OF)))
02195 #           define FLAGCOMBO_le    policy.or_(FLAGCOMBO_e, FLAGCOMBO_l)
02196 #           define FLAGCOMBO_g     policy.and_(FLAGCOMBO_ge, FLAGCOMBO_ne)
02197 #           define FLAGCOMBO_cxz   policy.equalToZero(readRegister<16>(REG_CX))
02198 #           define FLAGCOMBO_ecxz  policy.equalToZero(readRegister<32>(REG_ECX))
02199 
02200 #           define JUMP(tag) {                                                                                                 \
02201                 if (operands.size()!=1)                                                                                        \
02202                     throw Exception("instruction must have one operand", insn);                                                \
02203                 writeRegister(REG_EIP, policy.ite(FLAGCOMBO_##tag,                                                        \
02204                                                 read32(operands[0]),                                                           \
02205                                                 readRegister<32>(REG_EIP)));                                                     \
02206             }
02207             case x86_jne:   JUMP(ne);   break;
02208             case x86_je:    JUMP(e);    break;
02209             case x86_jno:   JUMP(no);   break;
02210             case x86_jo:    JUMP(o);    break;
02211             case x86_jpo:   JUMP(po);   break;
02212             case x86_jpe:   JUMP(pe);   break;
02213             case x86_jns:   JUMP(ns);   break;
02214             case x86_js:    JUMP(s);    break;
02215             case x86_jae:   JUMP(ae);   break;
02216             case x86_jb:    JUMP(b);    break;
02217             case x86_jbe:   JUMP(be);   break;
02218             case x86_ja:    JUMP(a);    break;
02219             case x86_jle:   JUMP(le);   break;
02220             case x86_jg:    JUMP(g);    break;
02221             case x86_jge:   JUMP(ge);   break;
02222             case x86_jl:    JUMP(l);    break;
02223             case x86_jcxz:  JUMP(cxz);  break;
02224             case x86_jecxz: JUMP(ecxz); break;
02225 #           undef JUMP
02226 
02227 #           define SET(tag) {                                                                                                  \
02228                 if (operands.size()!=1)                                                                                        \
02229                     throw Exception("instruction must have one operand", insn);                                                \
02230                 write8(operands[0], policy.concat(FLAGCOMBO_##tag, number<7>(0)));                                             \
02231             }
02232             case x86_setne: SET(ne); break;
02233             case x86_sete:  SET(e);  break;
02234             case x86_setno: SET(no); break;
02235             case x86_seto:  SET(o);  break;
02236             case x86_setpo: SET(po); break;
02237             case x86_setpe: SET(pe); break;
02238             case x86_setns: SET(ns); break;
02239             case x86_sets:  SET(s);  break;
02240             case x86_setae: SET(ae); break;
02241             case x86_setb:  SET(b);  break;
02242             case x86_setbe: SET(be); break;
02243             case x86_seta:  SET(a);  break;
02244             case x86_setle: SET(le); break;
02245             case x86_setg:  SET(g);  break;
02246             case x86_setge: SET(ge); break;
02247             case x86_setl:  SET(l);  break;
02248 #           undef SET
02249                 
02250 #           define CMOV(tag) {                                                                                                 \
02251                 if (operands.size()!=2)                                                                                        \
02252                     throw Exception("instruction must have two operands", insn);                                               \
02253                 switch (numBytesInAsmType(operands[0]->get_type())) {                                                          \
02254                     case 2: write16(operands[0], policy.ite(FLAGCOMBO_##tag, read16(operands[1]), read16(operands[0]))); break; \
02255                     case 4: write32(operands[0], policy.ite(FLAGCOMBO_##tag, read32(operands[1]), read32(operands[0]))); break; \
02256                     default: throw Exception("size not implemented", insn);                                                    \
02257                                                                                                                                \
02258                 }                                                                                                              \
02259             }
02260             case x86_cmovne:    CMOV(ne);       break;
02261             case x86_cmove:     CMOV(e);        break;
02262             case x86_cmovno:    CMOV(no);       break;
02263             case x86_cmovo:     CMOV(o);        break;
02264             case x86_cmovpo:    CMOV(po);       break;
02265             case x86_cmovpe:    CMOV(pe);       break;
02266             case x86_cmovns:    CMOV(ns);       break;
02267             case x86_cmovs:     CMOV(s);        break;
02268             case x86_cmovae:    CMOV(ae);       break;
02269             case x86_cmovb:     CMOV(b);        break;
02270             case x86_cmovbe:    CMOV(be);       break;
02271             case x86_cmova:     CMOV(a);        break;
02272             case x86_cmovle:    CMOV(le);       break;
02273             case x86_cmovg:     CMOV(g);        break;
02274             case x86_cmovge:    CMOV(ge);       break;
02275             case x86_cmovl:     CMOV(l);        break;
02276 #           undef CMOV
02277 
02278             /* The flag expressions are no longer needed */
02279 #           undef FLAGCOMBO_ne
02280 #           undef FLAGCOMBO_e
02281 #           undef FLAGCOMBO_ns
02282 #           undef FLAGCOMBO_s
02283 #           undef FLAGCOMBO_ae
02284 #           undef FLAGCOMBO_b
02285 #           undef FLAGCOMBO_be
02286 #           undef FLAGCOMBO_a
02287 #           undef FLAGCOMBO_l
02288 #           undef FLAGCOMBO_ge
02289 #           undef FLAGCOMBO_le
02290 #           undef FLAGCOMBO_g
02291 #           undef FLAGCOMBO_cxz
02292 #           undef FLAGCOMBO_ecxz
02293 
02294             case x86_cld: {
02295                 if (operands.size()!=0)
02296                     throw Exception("instruction must have no operands", insn);
02297                 writeRegister(REG_DF, policy.false_());
02298                 break;
02299             }
02300 
02301             case x86_std: {
02302                 if (operands.size()!=0)
02303                     throw Exception("instruction must have no operands", insn);
02304                 writeRegister(REG_DF, policy.true_());
02305                 break;
02306             }
02307 
02308             case x86_clc: {
02309                 if (operands.size()!=0)
02310                     throw Exception("instruction must have no operands", insn);
02311                 writeRegister(REG_CF, policy.false_());
02312                 break;
02313             }
02314 
02315             case x86_stc: {
02316                 if (operands.size()!=0)
02317                     throw Exception("instruction must have no operands", insn);
02318                 writeRegister(REG_CF, policy.true_());
02319                 break;
02320             }
02321 
02322             case x86_cmc: {
02323                 if (operands.size()!=0)
02324                     throw Exception("instruction must have no operands", insn);
02325                 writeRegister(REG_CF, policy.invert(readRegister<1>(REG_CF)));
02326                 break;
02327             }
02328 
02329             case x86_nop:
02330                 break;
02331 
02332 
02333             case x86_repne_scasb: repne_scas_semantics<1>(insn); break;
02334             case x86_repne_scasw: repne_scas_semantics<2>(insn); break;
02335             case x86_repne_scasd: repne_scas_semantics<4>(insn); break;
02336             case x86_repe_scasb:  repe_scas_semantics<1>(insn);  break;
02337             case x86_repe_scasw:  repe_scas_semantics<2>(insn);  break;
02338             case x86_repe_scasd:  repe_scas_semantics<4>(insn);  break;
02339 
02340             case x86_scasb: scas_semantics<1>(insn, policy.true_()); break;
02341             case x86_scasw: scas_semantics<2>(insn, policy.true_()); break;
02342             case x86_scasd: scas_semantics<4>(insn, policy.true_()); break;
02343 
02344             case x86_repne_cmpsb: repne_cmps_semantics<1>(insn); break;
02345             case x86_repne_cmpsw: repne_cmps_semantics<2>(insn); break;
02346             case x86_repne_cmpsd: repne_cmps_semantics<4>(insn); break;
02347             case x86_repe_cmpsb:  repe_cmps_semantics<1>(insn);  break;
02348             case x86_repe_cmpsw:  repe_cmps_semantics<2>(insn);  break;
02349             case x86_repe_cmpsd:  repe_cmps_semantics<4>(insn);  break;
02350 
02351             case x86_cmpsb: cmps_semantics<1>(insn, policy.true_()); break;
02352             case x86_cmpsw: cmps_semantics<2>(insn, policy.true_()); break;
02353             case x86_cmpsd:
02354                 /* This mnemonic, CMPSD, refers to two instructions: opcode A7 compares registers SI and DI (16-, 32-, or
02355                  * 64-bits) and sets the status flags. Opcode "F2 0F C2 /r ib" takes three arguments (an MMX register, an MMX
02356                  * or 64-bit register, and an 8-bit immediate) and compares floating point values.  The instruction semantics
02357                  * layer doesn't handle floating point instructions yet and reports them as "Bad instruction". */
02358                 if (0==operands.size()) {
02359                     cmps_semantics<4>(insn, policy.true_()); break;
02360                 } else {
02361                     /* Floating point instructions are not handled yet. */
02362                     throw Exception("instruction not implemented", insn);
02363                 }
02364                 break;
02365 
02366             case x86_movsb: movs_semantics<1>(insn, policy.true_()); break;
02367             case x86_movsw: movs_semantics<2>(insn, policy.true_()); break;
02368             case x86_movsd: movs_semantics<4>(insn, policy.true_()); break;
02369                 
02370             case x86_rep_movsb: rep_movs_semantics<1>(insn); break;
02371             case x86_rep_movsw: rep_movs_semantics<2>(insn); break;
02372             case x86_rep_movsd: rep_movs_semantics<4>(insn); break;
02373 
02374             case x86_stosb: stos_semantics<1>(insn, policy.true_()); break;
02375             case x86_stosw: stos_semantics<2>(insn, policy.true_()); break;
02376             case x86_stosd: stos_semantics<4>(insn, policy.true_()); break;
02377 
02378             case x86_rep_stosb: rep_stos_semantics<1>(insn); break;
02379             case x86_rep_stosw: rep_stos_semantics<2>(insn); break;
02380             case x86_rep_stosd: rep_stos_semantics<4>(insn); break;
02381 
02382             case x86_lodsb: lods_semantics<1>(insn); break;
02383             case x86_lodsw: lods_semantics<2>(insn); break;
02384             case x86_lodsd: lods_semantics<4>(insn);  break;
02385 
02386             case x86_hlt: {
02387                 if (operands.size()!=0)
02388                     throw Exception("instruction must have no operands", insn);
02389                 policy.hlt();
02390                 writeRegister(REG_EIP, orig_eip);
02391                 break;
02392             }
02393 
02394             case x86_cpuid: {
02395                 if (operands.size()!=0)
02396                     throw Exception("instruction must have no operands", insn);
02397                 policy.cpuid();
02398                 break;
02399             }
02400 
02401             case x86_rdtsc: {
02402                 if (operands.size()!=0)
02403                     throw Exception("instruction must have no operands", insn);
02404                 Word(64) tsc = policy.rdtsc();
02405                 writeRegister(REG_EAX, extract<0, 32>(tsc));
02406                 writeRegister(REG_EDX, extract<32, 64>(tsc));
02407                 break;
02408             }
02409 
02410             case x86_int: {
02411                 if (operands.size()!=1)
02412                     throw Exception("instruction must have one operand", insn);
02413                 SgAsmByteValueExpression* bv = isSgAsmByteValueExpression(operands[0]);
02414                 if (!bv)
02415                     throw Exception("operand must be a byte value expression", insn);
02416                 policy.interrupt(bv->get_value());
02417                 break;
02418             }
02419 
02420                 /* This is a dummy version that should be replaced later FIXME */
02421             case x86_fnstcw: {
02422                 if (operands.size()!=1)
02423                     throw Exception("instruction must have one operand", insn);
02424                 write16(operands[0], number<16>(0x37f));
02425                 break;
02426             }
02427 
02428             case x86_fldcw: {
02429                 if (operands.size()!=1)
02430                     throw Exception("instruction must have one operand", insn);
02431                 read16(operands[0]); /* To catch access control violations */
02432                 break;
02433             }
02434 
02435             case x86_sysenter: {
02436                 if (operands.size()!=0)
02437                     throw Exception("instruction must have no operands", insn);
02438                 policy.sysenter();
02439                 break;
02440             }
02441 
02442             default: {
02443                 throw Exception("instruction not implemented", insn);
02444                 break;
02445             }
02446         }
02447     } catch(Exception e) {
02448         if (!e.insn)
02449             e.insn = insn;
02450         throw e;
02451     }
02452 #endif
02453 
02454     void processInstruction(SgAsmx86Instruction* insn) {
02455         ROSE_ASSERT(insn);
02456         current_instruction = insn;
02457         policy.startInstruction(insn);
02458         translate(insn);
02459         policy.finishInstruction(insn);
02460     }
02461 
02462     void processBlock(const SgAsmStatementPtrList& stmts, size_t begin, size_t end) {
02463         if (begin == end) return;
02464         policy.startBlock(stmts[begin]->get_address());
02465         for (size_t i = begin; i < end; ++i) {
02466             processInstruction(isSgAsmx86Instruction(stmts[i]));
02467         }
02468         policy.finishBlock(stmts[begin]->get_address());
02469     }
02470 
02471     static bool isRepeatedStringOp(SgAsmStatement* s) {
02472         SgAsmx86Instruction* insn = isSgAsmx86Instruction(s);
02473         if (!insn) return false;
02474         switch (insn->get_kind()) {
02475             case x86_repe_cmpsb: return true;
02476             case x86_repe_cmpsd: return true;
02477             case x86_repe_cmpsq: return true;
02478             case x86_repe_cmpsw: return true;
02479             case x86_repe_scasb: return true;
02480             case x86_repe_scasd: return true;
02481             case x86_repe_scasq: return true;
02482             case x86_repe_scasw: return true;
02483             case x86_rep_insb: return true;
02484             case x86_rep_insd: return true;
02485             case x86_rep_insw: return true;
02486             case x86_rep_lodsb: return true;
02487             case x86_rep_lodsd: return true;
02488             case x86_rep_lodsq: return true;
02489             case x86_rep_lodsw: return true;
02490             case x86_rep_movsb: return true;
02491             case x86_rep_movsd: return true;
02492             case x86_rep_movsq: return true;
02493             case x86_rep_movsw: return true;
02494             case x86_repne_cmpsb: return true;
02495             case x86_repne_cmpsd: return true;
02496             case x86_repne_cmpsq: return true;
02497             case x86_repne_cmpsw: return true;
02498             case x86_repne_scasb: return true;
02499             case x86_repne_scasd: return true;
02500             case x86_repne_scasq: return true;
02501             case x86_repne_scasw: return true;
02502             case x86_rep_outsb: return true;
02503             case x86_rep_outsd: return true;
02504             case x86_rep_outsw: return true;
02505             case x86_rep_stosb: return true;
02506             case x86_rep_stosd: return true;
02507             case x86_rep_stosq: return true;
02508             case x86_rep_stosw: return true;
02509             default: return false;
02510         }
02511     }
02512 
02513     static bool isHltOrInt(SgAsmStatement* s) {
02514         SgAsmx86Instruction* insn = isSgAsmx86Instruction(s);
02515         if (!insn) return false;
02516         switch (insn->get_kind()) {
02517             case x86_hlt: return true;
02518             case x86_int: return true;
02519             default: return false;
02520         }
02521     }
02522 
02523     void processBlock(SgAsmBlock* b) {
02524         const SgAsmStatementPtrList& stmts = b->get_statementList();
02525         if (stmts.empty()) return;
02526         if (!isSgAsmInstruction(stmts[0])) return; /* A block containing functions or something */
02527         size_t i = 0;
02528         while (i < stmts.size()) {
02529             size_t oldI = i;
02530             /* Advance until either i points to a repeated string op or it is just after a hlt or int */
02531             while (i < stmts.size() && !isRepeatedStringOp(stmts[i]) && (i == oldI || !isHltOrInt(stmts[i - 1]))) ++i;
02532             processBlock(stmts, oldI, i);
02533             if (i >= stmts.size()) break;
02534             if (isRepeatedStringOp(stmts[i])) {
02535                 processBlock(stmts, i, i + 1);
02536                 ++i;
02537             }
02538             ROSE_ASSERT(i != oldI);
02539         }
02540     }
02541 
02542 };
02543 
02544 #undef Word
02545         
02546     } /*namespace*/
02547 } /*namespace*/
02548 #endif /* ROSE_X86INSTRUCTIONSEMANTICS_H */

Generated on Sat May 19 00:53:07 2012 for ROSE by  doxygen 1.4.7