1 ////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // Nestopia - NES/Famicom emulator written in C++
4 //
5 // Copyright (C) 2003-2008 Martin Freij
6 //
7 // This file is part of Nestopia.
8 //
9 // Nestopia is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Nestopia is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Nestopia; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 //
23 ////////////////////////////////////////////////////////////////////////////////////////
24 
25 #ifndef NST_CORE_H
26 #define NST_CORE_H
27 
28 #include <cstddef>
29 
30 #ifndef NST_BASE_H
31 #include "NstBase.hpp"
32 #endif
33 
34 #ifdef NST_PRAGMA_ONCE
35 #pragma once
36 #endif
37 
38 #if defined(_WIN32) || defined(WIN32) || defined(__WIN32__)
39 #define NST_WIN32
40 #endif
41 
42 #if NST_MSVC
43 
44  #pragma warning( disable : 4018 4100 4127 4244 4245 4308 4309 4310 4512 4800 4996 )
45 
46  #if NST_MSVC >= 800
47 
48   #ifdef NST_WIN32
49   #define NST_FASTCALL __fastcall
50   #define NST_REGCALL NST_FASTCALL
51   #endif
52 
53   #if NST_MSVC >= 1200
54 
55    #ifndef NST_FASTDELEGATE
56    #define NST_FASTDELEGATE
57    #endif
58 
59    #ifndef _DEBUG
60    #define NST_MSVC_OPTIMIZE
61    #define NST_FORCE_INLINE __forceinline
62    #pragma inline_depth( 255 )
63    #pragma inline_recursion( on )
64    #endif
65 
66    #define NST_SINGLE_CALL __forceinline
67 
68    #if NST_MSVC >= 1300
69 
70 	#ifndef NST_NO_INLINE
71 	#define NST_NO_INLINE __declspec(noinline)
72 	#endif
73 
74 	#ifndef NST_ASSUME
75 	#define NST_ASSUME(x_) __assume(x_)
76 	#endif
77 
78 	#ifndef NST_DEBUG
79 	#define NST_UNREACHABLE() __assume(0)
80 	#endif
81 
82 	#if !defined(NST_MM_INTRINSICS) && defined(NST_WIN32) && defined(_M_IX86)
83 	#define NST_MM_INTRINSICS
84 	#endif
85 
86 	#define NST_NO_VTABLE __declspec(novtable)
87 
88 	#if NST_MSVC >= 1400
89 
90      #ifndef NST_RESTRICT
91      #define NST_RESTRICT __restrict
92      #endif
93 
94      #pragma warning( default : 4191 4263 4287 4289 4296 4350 4545 4546 4547 4549 4555 4557 4686 4836 4905 4906 4928 4946 )
95 
96      #if 0
97      #pragma warning( default : 4820 ) // byte padding on structs
98      #pragma warning( default : 4710 ) // function not inlined
99      #pragma warning( default : 4711 ) // function auto inlined
100      #pragma warning( default : 4100 ) // unreferenced parameter
101      #endif
102 
103 	#endif
104 
105    #endif
106 
107   #endif
108 
109  #endif
110 
111 #elif NST_GCC
112 
113  #if NST_GCC >= 291
114 
115   #ifndef NST_RESTRICT
116   #define NST_RESTRICT __restrict__
117   #endif
118 
119   #if NST_GCC >= 301
120 
121    #ifndef NST_NO_INLINE
122    #define NST_NO_INLINE __attribute__((noinline))
123    #endif
124 
125 //	Commenting this fixes a lot of warnings on newer versions of GCC
126 //   #define NST_SINGLE_CALL __attribute__((always_inline))
127 
128    #if (NST_GCC >= 304) && defined(__i386__)
129    #define NST_REGCALL __attribute__((regparm(2)))
130    #endif
131 
132   #endif
133 
134  #endif
135 
136 #endif
137 
138 #if NST_ICC
139 
140  #pragma warning( disable : 11 69 304 373 383 444 810 869 981 1418 1572 1599 1786 )
141 
142  #if !defined(NST_RESTRICT) && NST_ICC >= 810
143  #define NST_RESTRICT restrict
144  #endif
145 
146 #endif
147 
148 #define NST_NOP() ((void)0)
149 
150 #ifndef NST_FORCE_INLINE
151 #define NST_FORCE_INLINE inline
152 #endif
153 
154 #ifndef NST_SINGLE_CALL
155 #define NST_SINGLE_CALL NST_FORCE_INLINE
156 #endif
157 
158 #ifndef NST_NO_INLINE
159 #define NST_NO_INLINE
160 #endif
161 
162 #ifndef NST_ASSUME
163 #define NST_ASSUME(x_) NST_NOP()
164 #endif
165 
166 #ifndef NST_NO_VTABLE
167 #define NST_NO_VTABLE
168 #endif
169 
170 #ifndef NST_RESTRICT
171 #define NST_RESTRICT
172 #endif
173 
174 #ifndef NST_UNREACHABLE
175 #define NST_UNREACHABLE() NST_ASSERT(0)
176 #endif
177 
178 #ifndef NST_FASTCALL
179 #define NST_FASTCALL
180 #endif
181 
182 #ifndef NST_REGCALL
183 #define NST_REGCALL
184 #endif
185 
186 #define NST_MIN(x_,y_) ((x_) < (y_) ? (x_) : (y_))
187 #define NST_MAX(x_,y_) ((x_) < (y_) ? (y_) : (x_))
188 
189 #define NST_COMMA ,
190 
191 #define NST_CAT_NEXT(x_,y_) x_##y_
192 #define NST_CAT(x_,y_) NST_CAT_NEXT(x_,y_)
193 
194 #define NST_COMPILE_ASSERT(expr_) typedef char NST_CAT(Nestopia_assertion_at_line_,__LINE__)[(expr_) ? 1 : -1]
195 
196 namespace Nes
197 {
198 	namespace Core
199 	{
200 		typedef const char* cstring;
201 		typedef const wchar_t* wcstring;
202 		typedef uint ibool;
203 		typedef uint Data;
204 		typedef uint Address;
205 		typedef dword Cycle;
206 
207 		template<typename T,dword N>
208 		char(& array(T(&)[N]))[N];
209 
210 		namespace Helper
211 		{
212 			template<ulong W> struct CountBits
213 			{
214 				enum { VALUE = 1 + CountBits<W / 2>::VALUE };
215 			};
216 
217 			template<> struct CountBits<1UL>
218 			{
219 				enum { VALUE = 1 };
220 			};
221 
222 			template<> struct CountBits<0UL>
223 			{
224 				enum { VALUE = 0 };
225 			};
226 
227 			template<typename T,bool>
228 			struct ShiftSigned
229 			{
LeftNes::Core::Helper::ShiftSigned230 				static long Left(T v,uint c)
231 				{
232 					return v << c;
233 				}
234 
RightNes::Core::Helper::ShiftSigned235 				static long Right(T v,uint c)
236 				{
237 					return v >> c;
238 				}
239 			};
240 
241 			template<typename T>
242 			struct ShiftSigned<T,false>
243 			{
LeftNes::Core::Helper::ShiftSigned244 				static long Left(T v,uint c)
245 				{
246 					return (v >= 0) ? +long(ulong(v) << c) : -long(ulong(-v) << c);
247 				}
248 
RightNes::Core::Helper::ShiftSigned249 				static long Right(T v,uint c)
250 				{
251 					return (v >= 0) ? +long(ulong(v) >> c) : -long(ulong(-v) >> c);
252 				}
253 			};
254 
255 			template<typename T,bool>
256 			struct SignExtend8
257 			{
ConvertNes::Core::Helper::SignExtend8258 				static T Convert(T v)
259 				{
260 					return schar(v);
261 				}
262 			};
263 
264 			template<typename T>
265 			struct SignExtend8<T,false>
266 			{
ConvertNes::Core::Helper::SignExtend8267 				static T Convert(T v)
268 				{
269 					return (v & 1U << 7) ? (v | ~0UL << 7) : v;
270 				}
271 			};
272 		}
273 
274 		template<ulong V> struct ValueBits
275 		{
276 			enum { VALUE = Helper::CountBits<V>::VALUE };
277 		};
278 
279 		template<typename T>
signed_shl(T v,uint c)280 		inline long signed_shl(T v,uint c)
281 		{
282 			enum {NATIVE = -(T(7) << 1) == -14};
283 			return Helper::ShiftSigned<T,NATIVE>::Left( v, c );
284 		}
285 
286 		template<typename T>
signed_shr(T v,uint c)287 		inline long signed_shr(T v,uint c)
288 		{
289 			enum {NATIVE = -(T(7) >> 1) == -4 || -(T(7) >> 1) == -3};
290 			return Helper::ShiftSigned<T,NATIVE>::Right( v, c );
291 		}
292 
293 		template<typename T>
sign_extend_8(T v)294 		inline T sign_extend_8(T v)
295 		{
296 			enum {NATIVE = CHAR_BIT == 8 && UCHAR_MAX == 0xFF && SCHAR_MIN == -128 && SCHAR_MAX == 127 && T(-2) == T(~1UL)};
297 			return Helper::SignExtend8<T,NATIVE>::Convert( v );
298 		}
299 
300 		template<idword Min,idword Max>
Clamp(idword value)301 		inline idword Clamp(idword value)
302 		{
303 			return (value <= Max) ? (value >= Min) ? value : Min : Max;
304 		}
305 
306 		enum
307 		{
308 			SIZE_1K     = 0x400,
309 			SIZE_2K     = 0x800,
310 			SIZE_4K     = 0x1000,
311 			SIZE_5K     = 0x1400,
312 			SIZE_6K     = 0x1800,
313 			SIZE_8K     = 0x2000,
314 			SIZE_16K    = 0x4000,
315 			SIZE_32K    = 0x8000,
316 			SIZE_40K    = 0xA000,
317 			SIZE_64K    = 0x10000,
318 			SIZE_128K   = 0x20000,
319 			SIZE_256K   = 0x40000,
320 			SIZE_512K   = 0x80000,
321 			SIZE_1024K  = 0x100000,
322 			SIZE_2048K  = 0x200000,
323 			SIZE_3072K  = 0x300000,
324 			SIZE_4096K  = 0x400000,
325 			SIZE_8192K  = 0x800000,
326 			SIZE_16384K = 0x1000000
327 		};
328 
329 		template<char T>
330 		struct Ascii
331 		{
332 			enum
333 			{
334 				V = ( T >= 'a' && T <= 'z') ? T - 'a' + 0x61 :
335 					( T >= 'A' && T <= 'Z') ? T - 'A' + 0x41 :
336 					( T >= '0' && T <= '9') ? T - '0' + 0x30 :
337 					( T == '\0' ) ? 0x00 :
338 					( T == ' '  ) ? 0x20 :
339 					( T == '!'  ) ? 0x21 :
340 					( T == '#'  ) ? 0x23 :
341 					( T == '%'  ) ? 0x25 :
342 					( T == '^'  ) ? 0x5E :
343 					( T == '&'  ) ? 0x26 :
344 					( T == '*'  ) ? 0x2A :
345 					( T == '('  ) ? 0x28 :
346 					( T == ')'  ) ? 0x29 :
347 					( T == '-'  ) ? 0x2D :
348 					( T == '_'  ) ? 0x5F :
349 					( T == '+'  ) ? 0x2B :
350 					( T == '='  ) ? 0x3D :
351 					( T == '~'  ) ? 0x7E :
352 					( T == '['  ) ? 0x5B :
353 					( T == ']'  ) ? 0x5D :
354 					( T == '\\' ) ? 0x5C :
355 					( T == '|'  ) ? 0x7C :
356 					( T == ';'  ) ? 0x3B :
357 					( T == ':'  ) ? 0x3A :
358 					( T == '\'' ) ? 0x27 :
359 					( T == '\"' ) ? 0x22 :
360 					( T == '{'  ) ? 0x7B :
361 					( T == '}'  ) ? 0x7D :
362 					( T == ','  ) ? 0x2C :
363 					( T == '.'  ) ? 0x2E :
364 					( T == '<'  ) ? 0x3C :
365 					( T == '>'  ) ? 0x3E :
366 					( T == '/'  ) ? 0x2F :
367 					( T == '?'  ) ? 0x3F :
368 					( T == '\a' ) ? 0x07 :
369 					( T == '\b' ) ? 0x08 :
370 					( T == '\t' ) ? 0x09 :
371 					( T == '\v' ) ? 0x0B :
372 					( T == '\n' ) ? 0x0A :
373 					( T == '\r' ) ? 0x0D :
374 					( T == '\f' ) ? 0x0C : 0xFF
375 			};
376 
377 			NST_COMPILE_ASSERT( V != 0xFF );
378 		};
379 
380 		template<char A,char B,char C=0,char D=0>
381 		struct AsciiId
382 		{
383 			enum
384 			{
385 				V =
386 				(
387 					dword( Ascii<A>::V ) <<  0 |
388 					dword( Ascii<B>::V ) <<  8 |
389 					dword( Ascii<C>::V ) << 16 |
390 					dword( Ascii<D>::V ) << 24
391 				)
392 			};
393 
RNes::Core::AsciiId394 			static dword R(byte a,byte b=0,byte c=0,byte d=0)
395 			{
396 				return
397 				(
398 					dword( Ascii<A>::V + a ) <<  0 |
399 					dword( Ascii<B>::V + b ) <<  8 |
400 					dword( Ascii<C>::V + c ) << 16 |
401 					dword( Ascii<D>::V + d ) << 24
402 				);
403 			}
404 		};
405 
406 		template<typename T,typename U>
StringCompare(const T * a,const U * b)407 		int StringCompare(const T* a,const U* b)
408 		{
409 			do
410 			{
411 				const wchar_t v[] =
412 				{
413 					(*a < L'a' || *a > L'z') ? *a : (L'A' + (*a - L'a')),
414 					(*b < L'a' || *b > L'z') ? *b : (L'A' + (*b - L'a'))
415 				};
416 
417 				if (v[0] < v[1])
418 					return -1;
419 
420 				if (v[0] > v[1])
421 					return +1;
422 			}
423 			while (++b, *a++);
424 
425 			return 0;
426 		}
427 
428 		template<typename T,typename U>
StringCompare(const T * a,const U * b,uint l)429 		int StringCompare(const T* a,const U* b,uint l)
430 		{
431 			for (; l--; ++a, ++b)
432 			{
433 				const wchar_t v[] =
434 				{
435 					(*a < L'a' || *a > L'z') ? *a : (L'A' + (*a - L'a')),
436 					(*b < L'a' || *b > L'z') ? *b : (L'A' + (*b - L'a'))
437 				};
438 
439 				if (v[0] < v[1])
440 					return -1;
441 
442 				if (v[0] > v[1])
443 					return +1;
444 
445 				if (!v[0])
446 					return 0;
447 			}
448 
449 			return 0;
450 		}
451 	}
452 
453 #ifdef NST_U64
454 
455 	typedef NST_U64 qaword;
456 	#define NST_NATIVE_QWORD
457 
458 #elif (ULONG_MAX > 0xFFFFFFFF) && (ULONG_MAX / 0xFFFFFFFF - 1 > 0xFFFFFFFF)
459 
460 	typedef unsigned long qaword;
461 	#define NST_NATIVE_QWORD
462 
463 #elif (defined(ULLONG_MAX) && (ULLONG_MAX > 0xFFFFFFFF) && (ULLONG_MAX / 0xFFFFFFFF - 1 > 0xFFFFFFFF)) || (NST_GCC >= 300)
464 
465 	#if NST_GCC
466 	__extension__ typedef unsigned long long qaword;
467 	#else
468 	typedef unsigned long long qaword;
469 	#endif
470 	#define NST_NATIVE_QWORD
471 
472 #elif defined(_UI64_MAX) && (NST_MSVC >= 900 || NST_BCB >= 0x530)
473 
474 	typedef unsigned __int64 qaword;
475 	#define NST_NATIVE_QWORD
476 
477 #else
478 
479 	class qaword
480 	{
481 		void Multiply(qaword);
482 		static void Divide(qaword&,const qaword,bool);
483 		void Shl(uint);
484 		void Shr(uint);
485 
486 		enum
487 		{
488 			LO_MASK = 0xFFFFFFFF,
489 			LO_MSB  = 0x80000000
490 		};
491 
492 		dword lo;
493 		dword hi;
494 
495 	public:
496 
qaword()497 		qaword() {}
498 
qaword(dword v)499 		qaword(dword v)
500 		: lo(v), hi(0) {}
501 
qaword(dword msdw,dword lsdw)502 		qaword(dword msdw,dword lsdw)
503 		: lo(lsdw), hi(msdw) {}
504 
qaword(const qaword & v)505 		qaword(const qaword& v)
506 		: lo(v.lo), hi(v.hi) {}
507 
508 		template<typename V>
operator =(const V & v)509 		qaword& operator = (const V& v)
510 		{
511 			lo = v;
512 			hi = 0;
513 			return *this;
514 		}
515 
operator =(const qaword & v)516 		qaword& operator = (const qaword& v)
517 		{
518 			lo = v.lo;
519 			hi = v.hi;
520 			return *this;
521 		}
522 
523 		template<typename V>
operator +=(const V & v)524 		qaword& operator += (const V& v)
525 		{
526 			dword t = lo;
527 			lo = (lo + v) & LO_MASK;
528 			hi = (hi + (t > lo)) & LO_MASK;
529 			return *this;
530 		}
531 
532 		template<typename V>
operator -=(const V & v)533 		qaword& operator -= (const V& v)
534 		{
535 			dword t = lo;
536 			lo = (lo - v) & LO_MASK;
537 			hi = (hi - (t < lo)) & LO_MASK;
538 			return *this;
539 		}
540 
operator ++(int)541 		qaword operator ++ (int)
542 		{
543 			qaword t;
544 			t.lo = lo;
545 			lo = (lo + 1) & LO_MASK;
546 			t.hi = hi;
547 			hi = (hi + (t.lo > lo)) & LO_MASK;
548 			return t;
549 		}
550 
operator ++()551 		qaword& operator ++ ()
552 		{
553 			dword t = lo;
554 			lo = (lo + 1) & LO_MASK;
555 			hi = (hi + (t > lo)) & LO_MASK;
556 			return *this;
557 		}
558 
operator --(int)559 		qaword operator -- (int)
560 		{
561 			qaword t;
562 			t.lo = lo;
563 			lo = (lo - 1) & LO_MASK;
564 			t.hi = hi;
565 			hi = (hi - (t.lo < lo)) & LO_MASK;
566 			return t;
567 		}
568 
operator --()569 		qaword& operator -- ()
570 		{
571 			dword t = lo;
572 			lo = (lo - 1) & LO_MASK;
573 			hi = (hi - (t < lo)) & LO_MASK;
574 			return *this;
575 		}
576 
577 		template<typename V>
operator *=(const V & v)578 		qaword& operator *= (const V& v)
579 		{
580 			if (!(((lo | v) & 0xFFFF0000) | hi))
581 				lo = (lo * v) & LO_MASK;
582 			else
583 				Multiply( qaword(v) );
584 
585 			return *this;
586 		}
587 
588 		template<typename V>
operator /=(const V & v)589 		qaword& operator /= (const V& v)
590 		{
591 			if (!hi)
592 				lo /= v;
593 			else
594 				Divide( *this, qaword(v), false );
595 
596 			return *this;
597 		}
598 
599 		template<typename V>
operator %=(const V & v)600 		qaword& operator %= (const V& v)
601 		{
602 			if (!hi)
603 				lo %= v;
604 			else
605 				Divide( *this, qaword(v), true );
606 
607 			return *this;
608 		}
609 
operator +(const V & v) const610 		template<typename V> qaword operator + (const V& v) const { return qaword(*this) += v; }
operator -(const V & v) const611 		template<typename V> qaword operator - (const V& v) const { return qaword(*this) -= v; }
operator *(const V & v) const612 		template<typename V> qaword operator * (const V& v) const { return qaword(*this) *= v; }
operator /(const V & v) const613 		template<typename V> qaword operator / (const V& v) const { return qaword(*this) /= v; }
operator %(const V & v) const614 		template<typename V> qaword operator % (const V& v) const { return qaword(*this) %= v; }
615 
operator |=(const V & v)616 		template<typename V> qaword& operator |= (const V& v) { lo |= v;         return *this; }
operator &=(const V & v)617 		template<typename V> qaword& operator &= (const V& v) { lo &= v; hi = 0; return *this; }
operator ^=(const V & v)618 		template<typename V> qaword& operator ^= (const V& v) { lo ^= v;         return *this; }
619 
operator |(const V & v) const620 		template<typename V> qaword operator | (const V& v) const { return qaword( hi, lo | v ); }
operator &(const V & v) const621 		template<typename V> qaword operator & (const V& v) const { return qaword(     lo & v ); }
operator ^(const V & v) const622 		template<typename V> qaword operator ^ (const V& v) const { return qaword( hi, lo ^ v ); }
623 
operator >>=(const V & v)624 		template<typename V> qaword& operator >>= (const V& v) { Shr(v); return *this; }
operator <<=(const V & v)625 		template<typename V> qaword& operator <<= (const V& v) { Shl(v); return *this; }
626 
operator >>(const V & v) const627 		template<typename V> qaword operator >> (const V& v) const { return qaword(*this) >>= v; }
operator <<(const V & v) const628 		template<typename V> qaword operator << (const V& v) const { return qaword(*this) <<= v; }
629 
operator ~() const630 		qaword operator ~() const
631 		{
632 			return qaword( hi ^ LO_MASK, lo ^ LO_MASK );
633 		}
634 
635 		template<typename V>
operator ==(const V & v) const636 		bool operator == (const V& v) const
637 		{
638 			return !((lo - v) | hi);
639 		}
640 
641 		template<typename V>
operator <(const V & v) const642 		bool operator < (const V& v) const
643 		{
644 			return (lo < v && !hi);
645 		}
646 
647 		template<typename V>
operator <=(const V & v) const648 		bool operator <= (const V& v) const
649 		{
650 			return (lo <= v && !hi);
651 		}
652 
653 		template<typename V>
operator !=(const V & v) const654 		bool operator != (const V& v) const
655 		{
656 			return !(*this == v);
657 		}
658 
659 		template<typename V>
operator >(const V & v) const660 		bool operator > (const V& v) const
661 		{
662 			return !(*this <= v);
663 		}
664 
665 		template<typename V>
operator >=(const V & v) const666 		bool operator >= (const V& v) const
667 		{
668 			return !(*this < v);
669 		}
670 
operator !() const671 		bool operator !() const
672 		{
673 			return !(lo|hi);
674 		}
675 
operator bool() const676 		operator bool() const
677 		{
678 			return (lo|hi);
679 		}
680 
operator int() const681 		operator int    () const { return lo; }
operator uint() const682 		operator uint   () const { return lo; }
operator char() const683 		operator char   () const { return lo; }
operator schar() const684 		operator schar  () const { return lo; }
operator uchar() const685 		operator uchar  () const { return lo; }
operator short() const686 		operator short  () const { return lo; }
operator ushort() const687 		operator ushort () const { return lo; }
operator long() const688 		operator long   () const { return lo; }
operator ulong() const689 		operator ulong  () const { return lo; }
690 	};
691 
692 	template<>
operator +=(const qaword & v)693 	inline qaword& qaword::operator += (const qaword& v)
694 	{
695 		dword t = lo;
696 		lo = (lo + v.lo) & LO_MASK;
697 		hi = (hi + (t > lo) + v.hi) & LO_MASK;
698 		return *this;
699 	}
700 
701 	template<>
operator -=(const qaword & v)702 	inline qaword& qaword::operator -= (const qaword& v)
703 	{
704 		dword t = lo;
705 		lo = (lo - v.lo) & LO_MASK;
706 		hi = (hi - ((t < lo) + v.hi)) & LO_MASK;
707 		return *this;
708 	}
709 
710 	template<>
operator *=(const qaword & v)711 	inline qaword& qaword::operator *= (const qaword& v)
712 	{
713 		Multiply( v );
714 		return *this;
715 	}
716 
717 	template<>
operator /=(const qaword & v)718 	inline qaword& qaword::operator /= (const qaword& v)
719 	{
720 		if (hi | v.hi)
721 			Divide( *this, v, false );
722 		else
723 			lo /= v.lo;
724 
725 		return *this;
726 	}
727 
728 	template<>
operator %=(const qaword & v)729 	inline qaword& qaword::operator %= (const qaword& v)
730 	{
731 		Divide( *this, v, true );
732 		return *this;
733 	}
734 
operator |=(const qaword & v)735 	template<> inline qaword& qaword::operator |= (const qaword& v) { lo |= v.lo; hi |= v.hi; return *this; }
operator &=(const qaword & v)736 	template<> inline qaword& qaword::operator &= (const qaword& v) { lo &= v.lo; hi &= v.hi; return *this; }
operator ^=(const qaword & v)737 	template<> inline qaword& qaword::operator ^= (const qaword& v) { lo ^= v.lo; hi ^= v.hi; return *this; }
738 
operator |(const qaword & v) const739 	template<> inline qaword qaword::operator | (const qaword& v) const { return qaword( hi | v.hi, lo | v.lo ); }
operator &(const qaword & v) const740 	template<> inline qaword qaword::operator & (const qaword& v) const { return qaword( hi & v.hi, lo & v.lo ); }
operator ^(const qaword & v) const741 	template<> inline qaword qaword::operator ^ (const qaword& v) const { return qaword( hi ^ v.hi, lo ^ v.lo ); }
742 
743 	template<>
operator ==(const qaword & v) const744 	inline bool qaword::operator == (const qaword& v) const
745 	{
746 		return !((lo - v.lo) | (hi - v.hi));
747 	}
748 
749 	template<>
operator <(const qaword & v) const750 	inline bool qaword::operator < (const qaword& v) const
751 	{
752 		return (hi < v.hi) || (lo < v.lo && hi == v.hi);
753 	}
754 
755 	template<>
operator <=(const qaword & v) const756 	inline bool qaword::operator <= (const qaword& v) const
757 	{
758 		return (hi < v.hi) || (hi == v.hi ? (lo <= v.lo) : false);
759 	}
760 
761 #endif
762 }
763 
764 #endif
765