FindRegisterDefs.h

Go to the documentation of this file.
00001 #ifndef Rose_FindRegisterDefs_H
00002 #define Rose_FindRegisterDefs_H
00003 
00004 #include "x86InstructionSemantics.h"
00005 #include "integerOps.h"
00006 #include "Registers.h"
00007 
00012 namespace FindRegisterDefs {
00013 
00014 /******************************************************************************************************************************
00015  *                                      ValueType
00016  ******************************************************************************************************************************/
00017 
00018 template<size_t nBits>
00019 struct ValueType {
00020     uint64_t defbits;           
00023     ValueType(): defbits(0) {}
00024 
00026     ValueType(uint64_t n) /*implicit*/ {
00027         defbits = n & IntegerOps::GenMask<uint64_t, nBits>::value;
00028     }
00029 
00031     template<size_t Len>
00032     ValueType(const ValueType<Len> &other) {
00033         defbits = other.defbits & IntegerOps::GenMask<uint64_t, nBits>::value; // make sure high-order bits are zeroed out
00034     }
00035 
00037     static ValueType<nBits> defined() { return ValueType<nBits>((uint64_t)(-1)); }
00038 
00040     static ValueType<nBits> undefined() { return ValueType<nBits>(0); }
00041 
00043     bool is_defined() const {
00044         return 0 == (~defbits & IntegerOps::GenMask<uint64_t, nBits>::value);
00045     }
00046 
00048     bool is_undefined() const {
00049         return !is_defined();
00050     }
00051 
00054     uint64_t known_value() const {
00055         return defbits;
00056     }
00057 
00059     void print(std::ostream &o) const {
00060         if (is_defined()) {                     // all bits defined
00061             o <<"defined";
00062         } else if (0==defbits) {                // all bits undefined
00063             o <<"undefined";
00064         } else {                                // some defined, some undefined (show the mask)
00065             int nnibbles = (nBits+3)/4;
00066             char buf[128];
00067             snprintf(buf, sizeof buf, "0x%0*"PRIx64, nnibbles, defbits);
00068             o <<buf;
00069         }
00070     }
00071 };
00072 
00073 template<size_t nBits>
00074 std::ostream& operator<<(std::ostream &o, const ValueType<nBits> &e)
00075 {
00076     e.print(o);
00077     return o;
00078 }
00079 
00080 /******************************************************************************************************************************
00081  *                                      State
00082  ******************************************************************************************************************************/
00083 
00084 struct State {
00085     static const size_t n_gprs = 8;             
00086     static const size_t n_segregs = 6;          
00088     ValueType<32> ip;
00089     ValueType<32> gpr[n_gprs];
00090     ValueType<16> segreg[n_segregs];
00091     ValueType<32> flags;
00092 
00094     void clear() {
00095         *this = State();
00096     }
00097 
00099     void merge(const State&);
00100 
00102     bool equal_registers(const State&) const;
00103 
00106     void print(std::ostream&) const;
00107     friend std::ostream& operator<<(std::ostream &o, const State &state) {
00108         state.print(o);
00109         return o;
00110     }
00112 };
00113 
00114 /******************************************************************************************************************************
00115  *                                      Policy
00116  ******************************************************************************************************************************/
00117 
00118 class Policy {
00119 private:
00120     SgAsmInstruction *cur_insn;
00121     State cur_state;                            
00122     mutable State rdundef;                      
00123     size_t ninsns;
00124     const RegisterDictionary *regdict;
00125 
00126 public:
00127     struct Exception {
00128         Exception(const std::string &mesg): mesg(mesg) {}
00129         friend std::ostream& operator<<(std::ostream &o, const Exception &e) {
00130             o <<"FindRegisterDefs exception: " <<e.mesg;
00131             return o;
00132         }
00133         std::string mesg;
00134     };
00135 
00136     Policy(): cur_insn(NULL), ninsns(0), regdict(NULL) {}
00137 
00139     const RegisterDictionary *get_register_dictionary() const {
00140         return regdict ? regdict : RegisterDictionary::dictionary_pentium4();
00141     }
00142 
00144     void set_register_dictionary(const RegisterDictionary *regdict) {
00145         this->regdict = regdict;
00146     }
00147 
00149     size_t get_ninsns() const {
00150         return ninsns;
00151     }
00152 
00155     void set_ninsns(size_t n) {
00156         ninsns = n;
00157     }
00158 
00160     SgAsmInstruction *get_insn() const {
00161         return cur_insn;
00162     }
00163 
00166     const State& get_state() const { return cur_state; }
00167     State& get_state() { return cur_state; }
00172     const State& get_rdundef_state() const { return rdundef; }
00173     State& get_rdundef_state() { return rdundef; }
00177     const ValueType<32>& get_ip() const { return cur_state.ip; }
00178 
00180     void merge(const Policy&);
00181 
00183     bool equal_states(const Policy&) const;
00184 
00187     void print(std::ostream&) const;
00188     friend std::ostream& operator<<(std::ostream &o, const Policy &p) {
00189         p.print(o);
00190         return o;
00191     }
00195     template<size_t FromLen, size_t ToLen>
00196     ValueType<ToLen> signExtend(const ValueType<FromLen> &a) const {
00197         return IntegerOps::signExtend<FromLen, ToLen>(a.defbits);
00198     }
00199 
00202     template <size_t BeginAt, size_t EndAt, size_t Len>
00203     ValueType<EndAt-BeginAt> extract(const ValueType<Len> &a) const {
00204         if (0==BeginAt) return ValueType<EndAt-BeginAt>(a);
00205         return (a.defbits >> BeginAt) & IntegerOps::GenMask<uint64_t, EndAt-BeginAt>::value;
00206     }
00207 
00210     template <size_t FromLen, size_t ToLen>
00211     ValueType<ToLen> unsignedExtend(const ValueType<FromLen> &a) const {
00212         uint64_t newbits = IntegerOps::GenMask<uint64_t, ToLen>::value & ~IntegerOps::GenMask<uint64_t, FromLen>::value;
00213         return a.defbits | newbits; // all new bits are defined (i.e., they would be set to zero if we were tracking values)
00214     }
00215 
00216     /*************************************************************************************************************************
00217      * Functions invoked by the X86InstructionSemantics class for every processed instruction or block
00218      *************************************************************************************************************************/
00219 
00220     /* Called at the beginning of X86InstructionSemantics::processInstruction() */
00221     void startInstruction(SgAsmInstruction *insn) {
00222         cur_state.ip = ValueType<32>::defined();
00223         cur_insn = insn;
00224     }
00225 
00226     /* Called at the end of X86InstructionSemantics::processInstruction() */
00227     void finishInstruction(SgAsmInstruction*) {
00228         cur_insn = NULL;
00229     }
00230 
00231     /* Called at the beginning of X86InstructionSemantics::processBlock() */
00232     void startBlock(rose_addr_t addr) {}
00233 
00234     /* Called at the end of X86InstructionSemantics::processBlock() */
00235     void finishBlock(rose_addr_t addr) {}
00236 
00237     /*************************************************************************************************************************
00238      * Functions invoked by the X86InstructionSemantics class to construct values
00239      *************************************************************************************************************************/
00240 
00242     ValueType<1> true_() const {
00243         return ValueType<1>::defined();
00244     }
00245 
00247     ValueType<1> false_() const {
00248         return ValueType<1>::defined();
00249     }
00250 
00252     ValueType<1> undefined_() const {
00253         return ValueType<1>::undefined();
00254     }
00255 
00257     template <size_t Len>
00258     ValueType<Len> number(uint64_t n) const {
00259         return ValueType<Len>::defined();
00260     }
00261 
00262     /*************************************************************************************************************************
00263      * Functions invoked by the X86InstructionSemantics class for individual instructions
00264      *************************************************************************************************************************/
00265 
00267     ValueType<32> filterCallTarget(const ValueType<32> &a) const {
00268         return a;
00269     }
00270 
00272     ValueType<32> filterReturnTarget(const ValueType<32> &a) const {
00273         return a;
00274     }
00275 
00277     ValueType<32> filterIndirectJumpTarget(const ValueType<32> &a) const {
00278         return a;
00279     }
00280 
00282     void hlt() {} // FIXME
00283 
00285     void cpuid() {} // FIXME
00286 
00288     ValueType<64> rdtsc() {
00289         return ValueType<64>::defined();
00290     }
00291 
00293     void interrupt(uint8_t num) {
00294         cur_state = State(); /*reset entire machine state*/
00295     }
00296 
00298     void sysenter() {
00299         cur_state = State(); /*reset entire machine state*/
00300     }
00301 
00302 
00303     /*************************************************************************************************************************
00304      * Functions invoked by the X86InstructionSemantics class for data access operations
00305      *************************************************************************************************************************/
00306 
00308     const RegisterDescriptor& findRegister(const std::string &regname, size_t nbits=0) {
00309         const RegisterDescriptor *reg = get_register_dictionary()->lookup(regname);
00310         if (!reg) {
00311             std::ostringstream ss;
00312             ss <<"Invalid register: \"" <<regname <<"\"";
00313             throw Exception(ss.str());
00314         }
00315         if (nbits>0 && reg->get_nbits()!=nbits) {
00316             std::ostringstream ss;
00317             ss <<"Invalid " <<nbits <<"-bit register: \"" <<regname <<"\" is "
00318                <<reg->get_nbits() <<" " <<(1==reg->get_nbits()?"byte":"bytes");
00319             throw Exception(ss.str());
00320         }
00321         return *reg;
00322     }
00323 
00325     template<size_t Len/*bits*/>
00326     ValueType<Len> readRegister(const char *regname) {
00327         return readRegister<Len>(findRegister(regname, Len));
00328     }
00329 
00331     template<size_t Len/*bits*/>
00332     void writeRegister(const char *regname, const ValueType<Len> &value) {
00333         writeRegister<Len>(findRegister(regname, Len), value);
00334     }
00335 
00337     template<size_t Len>
00338     ValueType<Len> readRegister(const RegisterDescriptor &reg) {
00339         switch (Len) {
00340             case 1: {
00341                 // Only FLAGS/EFLAGS bits have a size of one.  Other registers cannot be accessed at this granularity.
00342                 if (reg.get_major()!=x86_regclass_flags)
00343                     throw Exception("bit access only valid for FLAGS/EFLAGS register");
00344                 if (reg.get_minor()!=0 || reg.get_offset()>=32)
00345                     throw Exception("register not implemented in semantic policy");
00346                 if (reg.get_nbits()!=1)
00347                     throw Exception("semantic policy supports only single-bit flags");
00348                 uint64_t mask = (uint64_t)1 << reg.get_offset();
00349                 rdundef.flags.defbits |= ~cur_state.flags.defbits & mask;
00350                 uint64_t retval = (cur_state.flags.defbits & mask) >> reg.get_offset();
00351                 return retval;
00352             }
00353 
00354             case 8: {
00355                 // Only general-purpose registers can be accessed at a byte granularity, and we can access only the low-order
00356                 // byte or the next higher byte.  For instance, "al" and "ah" registers.
00357                 if (reg.get_major()!=x86_regclass_gpr)
00358                     throw Exception("byte access only valid for general purpose registers");
00359                 if (reg.get_minor()>=cur_state.n_gprs)
00360                     throw Exception("register not implemented in semantic policy");
00361                 assert(reg.get_nbits()==8); // we had better be asking for a one-byte register (e.g., "ah", not "ax")
00362                 switch (reg.get_offset()) {
00363                     case 0:
00364                         rdundef.gpr[reg.get_minor()].defbits |= ~cur_state.gpr[reg.get_minor()].defbits & 0x000000ff;
00365                         return extract<0, Len>(cur_state.gpr[reg.get_minor()]);
00366                     case 8:
00367                         rdundef.gpr[reg.get_minor()].defbits |= ~cur_state.gpr[reg.get_minor()].defbits & 0x0000ff00;
00368                         return extract<8, 8+Len>(cur_state.gpr[reg.get_minor()]);
00369                     default:
00370                         throw Exception("invalid one-byte access offset");
00371                 }
00372             }
00373 
00374             case 16: {
00375                 if (reg.get_nbits()!=16)
00376                     throw Exception("invalid 2-byte register");
00377                 if (reg.get_offset()!=0)
00378                     throw Exception("policy does not support non-zero offsets for word granularity register access");
00379                 switch (reg.get_major()) {
00380                     case x86_regclass_segment:
00381                         if (reg.get_minor()>=cur_state.n_segregs)
00382                             throw Exception("register not implemented in semantic policy");
00383                         rdundef.segreg[reg.get_minor()].defbits |= ~cur_state.segreg[reg.get_minor()].defbits & 0x0000ffff;
00384                         return unsignedExtend<16, Len>(cur_state.segreg[reg.get_minor()]);
00385                     case x86_regclass_gpr:
00386                         if (reg.get_minor()>=cur_state.n_gprs)
00387                             throw Exception("register not implemented in semantic policy");
00388                         rdundef.gpr[reg.get_minor()].defbits |= ~cur_state.gpr[reg.get_minor()].defbits & 0x0000ffff;
00389                         return extract<0, Len>(cur_state.gpr[reg.get_minor()]);
00390                     case x86_regclass_flags:
00391                         if (reg.get_minor()!=0)
00392                             throw Exception("register not implemented in semantic policy");
00393                         rdundef.flags.defbits |= ~cur_state.flags.defbits & 0x0000ffff;
00394                         return extract<0, Len>(cur_state.flags);
00395                     default:
00396                         throw Exception("word access not valid for this register type");
00397                 }
00398             }
00399 
00400             case 32: {
00401                 if (reg.get_offset()!=0)
00402                     throw Exception("policy does not support non-zero offsets for double word granularity register access");
00403                 switch (reg.get_major()) {
00404                     case x86_regclass_gpr:
00405                         if (reg.get_minor()>=cur_state.n_gprs)
00406                             throw Exception("register not implemented in semantic policy");
00407                         rdundef.gpr[reg.get_minor()].defbits |= ~cur_state.gpr[reg.get_minor()].defbits & 0xffffffff;
00408                         return unsignedExtend<32, Len>(cur_state.gpr[reg.get_minor()]);
00409                     case x86_regclass_ip:
00410                         if (reg.get_minor()!=0)
00411                             throw Exception("register not implemented in semantic policy");
00412                         rdundef.ip.defbits |= ~cur_state.ip.defbits & 0xffffffff;
00413                         return unsignedExtend<32, Len>(cur_state.ip.defbits);
00414                     case x86_regclass_segment:
00415                         if (reg.get_minor()>=cur_state.n_segregs || reg.get_nbits()!=16)
00416                             throw Exception("register not implemented in semantic policy");
00417                         rdundef.segreg[reg.get_minor()].defbits |= ~cur_state.segreg[reg.get_minor()].defbits & 0x0000ffff;
00418                         return unsignedExtend<16, Len>(cur_state.segreg[reg.get_minor()]);
00419                     case x86_regclass_flags: {
00420                         if (reg.get_minor()!=0)
00421                             throw Exception("register not implemented in semantic policy");
00422                         if (reg.get_nbits()!=32)
00423                             throw Exception("register is not 32 bits");
00424                         rdundef.flags.defbits |= ~cur_state.flags.defbits & 0xffffffff;
00425                         return cur_state.flags;
00426                     }
00427                     default:
00428                         throw Exception("double word access not valid for this register type");
00429                 }
00430             }
00431 
00432             default:
00433                 throw Exception("invalid register access width");
00434         }
00435     }
00436 
00438     template<size_t Len>
00439     void writeRegister(const RegisterDescriptor &reg, const ValueType<Len> &value) {
00440         switch (Len) {
00441             case 1: {
00442                 // Only FLAGS/EFLAGS bits have a size of one.  Other registers cannot be accessed at this granularity.
00443                 if (reg.get_major()!=x86_regclass_flags)
00444                     throw Exception("bit access only valid for FLAGS/EFLAGS register");
00445                 if (reg.get_minor()!=0 || reg.get_offset()>=32)
00446                     throw Exception("register not implemented in semantic policy");
00447                 if (reg.get_nbits()!=1)
00448                     throw Exception("semantic policy supports only single-bit flags");
00449                 uint64_t mask = (uint64_t)1 << reg.get_offset();
00450                 cur_state.flags.defbits &= ~mask;
00451                 cur_state.flags.defbits |= (value.defbits << reg.get_offset()) & mask;
00452                 break;
00453             }
00454 
00455             case 8: {
00456                 // Only general purpose registers can be accessed at byte granularity, and only for offsets 0 and 8.
00457                 if (reg.get_major()!=x86_regclass_gpr)
00458                     throw Exception("byte access only valid for general purpose registers.");
00459                 if (reg.get_minor()>=cur_state.n_gprs)
00460                     throw Exception("register not implemented in semantic policy");
00461                 assert(reg.get_nbits()==8); // we had better be asking for a one-byte register (e.g., "ah", not "ax")
00462                 switch (reg.get_offset()) {
00463                     case 0:
00464                         cur_state.gpr[reg.get_minor()] =
00465                             concat(signExtend<Len, 8>(value), extract<8, 32>(cur_state.gpr[reg.get_minor()])); // no-op extend
00466                         break;
00467                     case 8:
00468                         cur_state.gpr[reg.get_minor()] =
00469                             concat(extract<0, 8>(cur_state.gpr[reg.get_minor()]),
00470                                    concat(unsignedExtend<Len, 8>(value),
00471                                           extract<16, 32>(cur_state.gpr[reg.get_minor()])));
00472                         break;
00473                     default:
00474                         throw Exception("invalid byte access offset");
00475                 }
00476                 break;
00477             }
00478 
00479             case 16: {
00480                 if (reg.get_nbits()!=16)
00481                     throw Exception("invalid 2-byte register");
00482                 if (reg.get_offset()!=0)
00483                     throw Exception("policy does not support non-zero offsets for word granularity register access");
00484                 switch (reg.get_major()) {
00485                     case x86_regclass_segment:
00486                         if (reg.get_minor()>=cur_state.n_segregs)
00487                             throw Exception("register not implemented in semantic policy");
00488                         cur_state.segreg[reg.get_minor()] = unsignedExtend<Len, 16>(value);
00489                         break;
00490                     case x86_regclass_gpr:
00491                         if (reg.get_minor()>=cur_state.n_gprs)
00492                             throw Exception("register not implemented in semantic policy");
00493                         cur_state.gpr[reg.get_minor()] =
00494                             concat(unsignedExtend<Len, 16>(value),
00495                                    extract<16, 32>(cur_state.gpr[reg.get_minor()]));
00496                         break;
00497                     case x86_regclass_flags:
00498                         if (reg.get_minor()!=0)
00499                             throw Exception("register not implemented in semantic policy");
00500                         cur_state.flags = unsignedExtend<0, 16>(value);
00501                         break;
00502                     default:
00503                         throw Exception("word access not valid for this register type");
00504                 }
00505                 break;
00506             }
00507 
00508             case 32: {
00509                 if (reg.get_offset()!=0)
00510                     throw Exception("policy does not support non-zero offsets for double word granularity register access");
00511                 switch (reg.get_major()) {
00512                     case x86_regclass_gpr:
00513                         if (reg.get_minor()>=cur_state.n_gprs)
00514                             throw Exception("register not implemented in semantic policy");
00515                         cur_state.gpr[reg.get_minor()] = signExtend<Len, 32>(value);
00516                         break;
00517                     case x86_regclass_ip:
00518                         if (reg.get_minor()!=0)
00519                             throw Exception("register not implemented in semantic policy");
00520                         cur_state.ip = unsignedExtend<Len, 32>(value);
00521                         break;
00522                     case x86_regclass_flags:
00523                         if (reg.get_minor()!=0)
00524                             throw Exception("register not implemented in semantic policy");
00525                         if (reg.get_nbits()!=32)
00526                             throw Exception("register is not 32 bits");
00527                         cur_state.flags = unsignedExtend<Len, 32>(value);
00528                         break;
00529                     default:
00530                         throw Exception("double word access not valid for this register type");
00531                 }
00532                 break;
00533             }
00534 
00535             default:
00536                 throw Exception("invalid register access width");
00537         }
00538     }
00539 
00541     template <size_t Len> ValueType<Len>
00542     readMemory(X86SegmentRegister segreg, const ValueType<32> &addr, const ValueType<1> &cond) const {
00543         return ValueType<Len>::defined();
00544     }
00545 
00547     template <size_t Len> void
00548     writeMemory(X86SegmentRegister segreg, const ValueType<32> &addr, const ValueType<Len> &data, const ValueType<1> &cond) {
00549     }
00550 
00551     /*************************************************************************************************************************
00552      * Functions invoked by the X86InstructionSemantics class for arithmetic operations
00553      *************************************************************************************************************************/
00554 
00558     template <size_t Len>
00559     ValueType<Len> add(const ValueType<Len> &a, const ValueType<Len> &b) const {
00560         uint64_t defbits = 0;
00561         for (size_t i=0; i<Len && 0!=(a.defbits & ((uint64_t)1<<i)) && 0!=(b.defbits & ((uint64_t)1<<i)); ++i)
00562             defbits |= (uint64_t)1<<i;
00563         return defbits;
00564     }
00565 
00580     template <size_t Len>
00581     ValueType<Len> addWithCarries(const ValueType<Len> &a, const ValueType<Len> &b, const ValueType<1> &c,
00582                                   ValueType<Len> &carry_out) const {
00583         if (0==c.defbits)
00584             return carry_out = ValueType<Len>::undefined();
00585 
00586         ValueType<Len> retval = add(a, b);
00587         carry_out = (retval.defbits << 1);
00588         return retval;
00589     }
00590 
00592     template <size_t Len>
00593     ValueType<Len> and_(const ValueType<Len> &a, const ValueType<Len> &b) const {
00594         return a.defbits & b.defbits; // result defined where both a and b are defined
00595     }
00596 
00598     template <size_t Len>
00599     ValueType<1> equalToZero(const ValueType<Len> &a) const {
00600         return a.is_defined() ? ValueType<1>::defined() : ValueType<1>::undefined();
00601     }
00602 
00604     template <size_t Len>
00605     ValueType<Len> invert(const ValueType<Len> &a) const {
00606         return a; // no change in defined bits
00607     }
00608 
00611     template<size_t Len1, size_t Len2>
00612     ValueType<Len1+Len2> concat(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00613         return a.defbits | (b.defbits << Len1);
00614     }
00615 
00619     template <size_t Len>
00620     ValueType<Len> ite(const ValueType<1> &sel, const ValueType<Len> &ifTrue, const ValueType<Len> &ifFalse) const {
00621         return ifTrue.defbits & ifFalse.defbits;
00622     }
00623 
00627     template <size_t Len>
00628     ValueType<Len> leastSignificantSetBit(const ValueType<Len> &a) const {
00629         return a.is_defined() ? ValueType<Len>::defined() : ValueType<Len>::undefined();
00630     }
00631 
00633     template <size_t Len>
00634     ValueType<Len> mostSignificantSetBit(const ValueType<Len> &a) const {
00635         return a.is_defined() ? ValueType<Len>::defined() : ValueType<Len>::undefined();
00636     }
00637 
00639     template <size_t Len>
00640     ValueType<Len> negate(const ValueType<Len> &a) const {
00641         return add(invert(a), ValueType<Len>::defined());
00642     }
00643 
00646     template <size_t Len>
00647     ValueType<Len> or_(const ValueType<Len> &a, const ValueType<Len> &b) const {
00648         return a.defbits & b.defbits;
00649     }
00650 
00655     template <size_t Len, size_t SALen>
00656     ValueType<Len> rotateLeft(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00657         return a.is_defined() ? ValueType<Len>::defined() : ValueType<Len>::undefined();
00658     }
00659 
00661     template <size_t Len, size_t SALen>
00662     ValueType<Len> rotateRight(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00663         return a.is_defined() ? ValueType<Len>::defined() : ValueType<Len>::undefined();
00664     }
00665 
00669     template <size_t Len, size_t SALen>
00670     ValueType<Len> shiftLeft(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00671         uint64_t result = 0;
00672         for (size_t i=0; i<Len && 0!=(a.defbits & ((uint64_t)1<<i)); ++i)
00673             result |= (uint64_t)1 << i;
00674         return result;
00675     }
00676 
00680     template <size_t Len, size_t SALen>
00681     ValueType<Len> shiftRight(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00682         uint64_t result = 0;
00683         for (size_t i=Len+1; i>0 && 0!=(a.defbits & ((uint64_t)1<<(i-1))); --i)
00684             result |= (uint64_t)1 << (i-1);
00685         return result;
00686     }
00687 
00690     template <size_t Len, size_t SALen>
00691     ValueType<Len> shiftRightArithmetic(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00692         return shiftRight(a, sa);
00693     }
00694 
00696     template <size_t Len1, size_t Len2>
00697     ValueType<Len1> signedDivide(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00698         // FIXME: could be made more precise, like signedMultiply()
00699         return a.is_defined() && b.is_defined() ? ValueType<Len1>::defined() : ValueType<Len1>::undefined();
00700     }
00701 
00703     template <size_t Len1, size_t Len2>
00704     ValueType<Len2> signedModulo(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00705         return a.is_defined() && b.is_defined() ? ValueType<Len2>::defined() : ValueType<Len2>::undefined();
00706     }
00707 
00710     template <size_t Len1, size_t Len2>
00711     ValueType<Len1+Len2> signedMultiply(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00712         size_t a_ndef = 0;
00713         if (a.is_defined()) {
00714             a_ndef = Len1+Len2;
00715         } else {
00716             while (a_ndef<Len1 && 0!=(a.defbits & ((uint64_t)1<<a_ndef)))
00717                 ++a_ndef;
00718         }
00719 
00720         size_t b_ndef = 0;
00721         if (b.is_defined()) {
00722             b_ndef = Len1+Len2;
00723         } else {
00724             while (b_ndef<Len1 && 0!=(b.defbits & ((uint64_t)1<<b_ndef)))
00725                 ++b_ndef;
00726         }
00727 
00728         uint64_t result_ndef = std::min(a_ndef, b_ndef);
00729         uint64_t result = ((uint64_t)1 << result_ndef) - 1;
00730         return result;
00731     }
00732 
00734     template <size_t Len1, size_t Len2>
00735     ValueType<Len1> unsignedDivide(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00736         // FIXME: could be made more precise, like unsignedMultiply()
00737         return a.is_defined() && b.is_defined() ? ValueType<Len1>::defined() : ValueType<Len1>::undefined();
00738     }
00739 
00741     template <size_t Len1, size_t Len2>
00742     ValueType<Len2> unsignedModulo(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00743         return a.is_defined() && b.is_defined() ? ValueType<Len2>::defined() : ValueType<Len2>::undefined();
00744     }
00745 
00747     template <size_t Len1, size_t Len2>
00748     ValueType<Len1+Len2> unsignedMultiply(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00749         size_t a_ndef = 0;
00750         if (a.is_defined()) {
00751             a_ndef = Len1+Len2;
00752         } else {
00753             while (a_ndef<Len1 && 0!=(a.defbits & ((uint64_t)1<<a_ndef)))
00754                 ++a_ndef;
00755         }
00756 
00757         size_t b_ndef = 0;
00758         if (b.is_defined()) {
00759             b_ndef = Len1+Len2;
00760         } else {
00761             while (b_ndef<Len1 && 0!=(b.defbits & ((uint64_t)1<<b_ndef)))
00762                 ++b_ndef;
00763         }
00764 
00765         uint64_t result_ndef = std::min(a_ndef, b_ndef);
00766         uint64_t result = ((uint64_t)1 << result_ndef) - 1;
00767         return result;
00768     }
00769 
00771     template <size_t Len>
00772     ValueType<Len> xor_(const ValueType<Len> &a, const ValueType<Len> &b) const {
00773         return a.defbits & b.defbits;
00774     }
00775 };
00776 
00777 }; // namespace
00778 
00779 #endif

Generated on Wed May 16 06:18:10 2012 for ROSE by  doxygen 1.4.7