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
00016
00017
00018 template<size_t nBits>
00019 struct ValueType {
00020 uint64_t defbits;
00023 ValueType(): defbits(0) {}
00024
00026 ValueType(uint64_t n) {
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;
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()) {
00061 o <<"defined";
00062 } else if (0==defbits) {
00063 o <<"undefined";
00064 } else {
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
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
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;
00214 }
00215
00216
00217
00218
00219
00220
00221 void startInstruction(SgAsmInstruction *insn) {
00222 cur_state.ip = ValueType<32>::defined();
00223 cur_insn = insn;
00224 }
00225
00226
00227 void finishInstruction(SgAsmInstruction*) {
00228 cur_insn = NULL;
00229 }
00230
00231
00232 void startBlock(rose_addr_t addr) {}
00233
00234
00235 void finishBlock(rose_addr_t addr) {}
00236
00237
00238
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
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() {}
00283
00285 void cpuid() {}
00286
00288 ValueType<64> rdtsc() {
00289 return ValueType<64>::defined();
00290 }
00291
00293 void interrupt(uint8_t num) {
00294 cur_state = State();
00295 }
00296
00298 void sysenter() {
00299 cur_state = State();
00300 }
00301
00302
00303
00304
00305
00306
00308 const RegisterDescriptor& findRegister(const std::string ®name, 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>
00326 ValueType<Len> readRegister(const char *regname) {
00327 return readRegister<Len>(findRegister(regname, Len));
00328 }
00329
00331 template<size_t Len>
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 ®) {
00339 switch (Len) {
00340 case 1: {
00341
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
00356
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);
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 ®, const ValueType<Len> &value) {
00440 switch (Len) {
00441 case 1: {
00442
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
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);
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()]));
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
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;
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;
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
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
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 };
00778
00779 #endif