-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBinary.hpp
852 lines (774 loc) · 26.8 KB
/
Binary.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
// Copyright Kabuki Starship� <kabukistarship.com>.
#pragma once
#ifndef SCRIPT2_KABUKI_BINARY_WITH_TEMPLATES
#define SCRIPT2_KABUKI_BINARY_WITH_TEMPLATES
#include <_Config.h>
namespace _ {
/* Syntactical sugar for reinterpret_cast using templates. */
template<typename T = void>
inline T* TPtr(void* ptr) {
return reinterpret_cast<T*>(ptr);
}
/* Syntactical sugar for reinterpret_cast using templates. */
template<typename T = void>
inline T* TPtr(ISW value) {
return reinterpret_cast<T*>(value);
}
/* Syntactical sugar for reinterpret_cast using templates. */
template<typename T = void>
inline const T* TPtr(const void* ptr) {
return reinterpret_cast<const T*>(ptr);
}
/* Checks if the pointer is between values 0-63. */
inline BOL PtrIsValid(const void* ptr) { return IUW(ptr) >= CrabsErrorCount; }
// Checks if the input is aligned to the T word boundary.
template<typename T = void>
inline BOL TAlignIs(const T* input) { return (IUW(input) & (sizeof(T) - 1)) == 0; }
template<typename T = IUW, typename I = T>
inline BOL TAlignIs(I input) { return (input & (sizeof(T) - 1)) == 0; }
/* Syntactical sugar for reinterpret_cast using templates. */
template<typename T = void>
inline T* CPtr(const void* ptr) {
return const_cast<T*>(reinterpret_cast<const T*>(ptr));
}
/* Syntactical sugar for reinterpret_cast using templates. */
template<typename T = void>
inline const T* CPtr(void* ptr) {
return reinterpret_cast<const T*>(ptr);
}
/* Creates a T pointer from a base pointer plus the offset.
@param base The base address.
@param offset The offset in bytes. */
template<typename T = void>
inline T* TPtr(void* origin, ISW offset) {
return reinterpret_cast<T*>(ISW(origin) + offset);
}
template<typename T = void>
inline const T* TPtr(const void* origin, ISW offset) {
return reinterpret_cast<const T*>(ISW(origin) + offset);
}
/* Creates a T pointer from a base pointer plus the offset.
@param base The base address.
@param offset The offset in bytes. */
template<typename T = void>
inline T* TPtr(void* origin, ISW offset1, ISW offset2) {
return reinterpret_cast<T*>(ISW(origin) + offset1 + offset2);
}
template<typename T = void>
inline const T* TPtr(const void* origin, ISW offset1, ISW offset2) {
return reinterpret_cast<const T*>(ISW(origin) + offset1 + offset2);
}
template<typename T = void>
inline T* TPtr(void* origin, ISW offset1, ISW offset2, ISW offset3) {
return reinterpret_cast<T*>(ISW(origin) + offset1 + offset2 + offset3);
}
template<typename T = void>
inline const T* TPtr(const void* origin, ISW offset1, ISW offset2,
ISW offset3) {
return reinterpret_cast<const T*>(ISW(origin) + offset1 + offset2 + offset3);
}
}
#if SEAM >= SCRIPT2_SOCKET
namespace _ {
/* @ingroup Binary
@brief Misc binary and pointer function. */
/* Converts the given value to a signed value of the same width. */
inline ISA ToSigned(CHA value) { return ISA(value); }
inline ISB ToSigned(CHB value) { return ISB(value); }
inline ISC ToSigned(CHC value) { return ISC(value); }
inline ISN ToSigned(CHN value) { return ISN(value); }
inline ISA ToSigned(IUA value) { return ISA(value); }
inline ISB ToSigned(IUB value) { return ISB(value); }
inline ISC ToSigned(IUC value) { return ISC(value); }
inline ISD ToSigned(IUD value) { return ISD(value); }
inline ISA ToSigned(ISA value) { return ISA(value); }
inline ISB ToSigned(ISB value) { return ISB(value); }
inline ISC ToSigned(ISC value) { return ISC(value); }
inline ISD ToSigned(ISD value) { return ISD(value); }
inline ISW ToSigned(const void* value) { return ISW(value); }
#if USING_FPC == YES_0
inline ISC ToSigned(FPC value) { return *TPtr<ISC>(&value); }
#endif
#if USING_FPD == YES_0
inline ISD ToSigned(FPD value) { return *TPtr<ISD>(&value); }
#endif
/* Converts the given value to a unsigned value of the same width. */
inline IUA ToUnsigned(CHA value) { return IUA(value); }
inline IUB ToUnsigned(CHB value) { return IUB(value); }
inline IUC ToUnsigned(CHC value) { return IUC(value); }
inline IUN ToUnsigned(CHN value) { return IUN(value); }
inline IUA ToUnsigned(ISA value) { return IUA(value); }
inline IUB ToUnsigned(ISB value) { return IUB(value); }
inline IUC ToUnsigned(ISC value) { return IUC(value); }
inline IUN ToUnsigned(BOL value) { return IUN(value); }
inline IUD ToUnsigned(ISD value) { return IUD(value); }
inline IUA ToUnsigned(IUA value) { return IUA(value); }
inline IUB ToUnsigned(IUB value) { return IUB(value); }
inline IUC ToUnsigned(IUC value) { return IUC(value); }
inline IUD ToUnsigned(IUD value) { return IUD(value); }
inline IUW ToUnsigned(const void* value) {
return IUW(value);
}
#if USING_FPC == YES_0
inline IUC ToUnsigned(FPC value) { return *TPtr<IUC>(&value); }
#endif
#if USING_FPD == YES_0
inline IUD ToUnsigned(FPD value) { return *TPtr<IUD>(&value); }
#endif
/* Converts the value to a floating-point number. */
inline FPC ToFloat(IUC value) { return *TPtr<FPC>(&value); }
inline FPD ToFloat(IUD value) { return *TPtr<FPD>(&value); }
/* Returns the maximum value of the given unsigned type. */
template<typename IU>
inline IU TNaNUnsigned() {
return ~IU(0);
}
/* Returns the minimum value of the given signed type (i.e. 0x100...0). */
template<typename IS>
constexpr IS TNaNSigned() {
return IS(1) << (sizeof(IS) * 8 - 1);
}
template<typename IS = ISW>
inline IS TDelta(const void* start) {
ISW delta = ISW(start);
return IS(delta);
}
template<typename IS = ISW>
inline IS TDelta(const void* start, const void* stop) {
ISW delta = ISW(stop) - ISW(start);
return IS(delta);
}
enum {
_Stack = 0, //< Flag for using stack memory.
_Heap = 1, //< Flag for using heap memory.
};
/* Calculates the number of bits in the given type T. */
template<typename T>
constexpr T TBitCount() {
return sizeof(T) * 8;
}
/* Returns the Log_2(N) for the sizeof (I).
@code
ISN bytes = 32;
ISN size_words = bytes >> TBitCount<ISN> ()
@endcode
*/
template<typename T, typename IS = ISW>
constexpr IS CBitCount() {
IS size = sizeof(IS),
count = 1,
b = 1;
while (size < b << count) ++count;
return count;
/*
IS b = 1;
if (size < b << 8) { // 1-8
if (size < b << 4) { // 1-4
if (size < b << 2) {
if (size < b << 1) return 1;
else return 2;
} else {
if (size < b << 3) return 3;
else return 4;
}
}
else { // 5-8
if (size < b << 6) {
if (size < b << 5) return 5;
else return 6;
} else {
if (size < b << 7) return 7;
else return 8;
}
}
} else { // 9-16
if (size < b << 12) { // 9-12
if (size < b << 10) {
if (size < b << 9) return 9;
else return 10;
}
else {
if (size < b << 11) return 11;
else return 12;
}
}
else { // 13-16
if (size < b << 14) {
if (size < b << 13) return 13;
else return 14;
}
else {
if (size < b << 15) return 15;
else return 16;
}
}
}
return 0;
*/
}
template<typename DT = DTB, DT dt>
constexpr ISN TBitCode() {
if (dt <= _CHA) return 0;
if (dt <= _CHB) return 1;
if (dt <= _CHC) return 2;
if (dt <= _TMD) return 3;
if (dt <= _ISE) return 4;
if (dt <= _CT4) return 4;
if (dt <= _CT3) return 3;
if (dt <= _CT2) return 2;
if (dt <= _CT1) return 1;
return 0;
}
/* Aligns the given value up to a sizeof (T) boundary.
@return The aligned value.
@param value The value to align.
@param mask The power of 2 to align to minus 1 (makes the mask).
@desc Algorithm works by inverting the bits, mask of the LSbs and adding 1.
This allows the algorithm to word align without any if statements. The
algorithm works the same for all memory widths as proven by the truth
tables bellow.
@code
// The convention KT uses is that the unsigned size always comes first
// because it's the first IUA of an ASCII AArray.
ISC signed_example = 7;
signed_example = AlignUp<ISD, IUC, ISC> (signed_example);
IUB unsigned_example = 3;
unsgiend_example = AlignUp<ISC, IUB, IUB> (unsigned_example);
// 64-bit alignment example:
// ~000 = 111 => 000 + 111 + 1 = 0x1000
// ~001 = 110 => 001 + 110 + 1 = 0x1000
// ~010 = 101 => 010 + 101 + 1 = 0x1000
// ~011 = 100 => 011 + 100 + 1 = 0x1000
// ~100 = 011 => 100 + 011 + 1 = 0x1000
// ~101 = 010 => 101 + 010 + 1 = 0x1000
// ~110 = 001 => 110 + 001 + 1 = 0x1000
// ~111 = 000 => 111 + 000 + 1 = 0x1000
// 32-bit alignment example:
// ~00 = 11 => 00 + 11 + 1 = 0x100
// ~01 = 10 => 01 + 10 + 1 = 0x100
// ~10 = 01 => 10 + 01 + 1 = 0x100
// ~11 = 00 => 11 + 00 + 1 = 0x100
// 16-bit alignment example:
// ~0 = 1 => 0 + 1 = 1
// ~1 = 0 => 1 + 0 = 0
// 8-bit example:
// value + ((~value) + 1) & (sizeof (ISA) - 1) = value
@endcode */
inline ISA AlignUp(ISA value, ISA align_mask = ALUWordMask) {
return value + ((-value) & align_mask);
}
inline IUA AlignUp(IUA value, IUA align_mask = ALUWordMask) {
return IUA(AlignUp(ISA(value), ISA(align_mask)));
}
inline ISB AlignUp(ISB value, ISB align_mask = ALUWordMask) {
return value + ((-value) & align_mask);
}
inline IUB AlignUp(IUB value, IUB align_mask = ALUWordMask) {
return value + (IUB(-ISB(value)) & align_mask);
}
inline ISC AlignUp(ISC value, ISC align_mask = ALUWordMask) {
return value + ((-value) & align_mask);
}
inline IUC AlignUp(IUC value, IUC align_mask = ALUWordMask) {
return value + (IUC(-ISC(value)) & align_mask);
}
inline ISD AlignUp(ISD value, ISD align_mask = ALUWordMask) {
return value + ((-value) & align_mask);
}
inline IUD AlignUp(IUD value, IUD align_mask = ALUWordMask) {
return value + (IUD(-ISD(value)) & align_mask);
}
constexpr ISA CAlignUp(ISA value, ISA align_mask = ALUWordMask) {
return value + ((-value) & align_mask);
}
constexpr IUA CAlignUp(IUA value, IUA align_mask = ALUWordMask) {
return IUA(CAlignUp(ISA(value), ISA(align_mask)));
}
constexpr ISB CAlignUp(ISB value, ISB align_mask = ALUWordMask) {
return value + ((-value) & align_mask);
}
constexpr IUB CAlignUp(IUB value, IUB align_mask = ALUWordMask) {
return value + (IUB(-ISB(value)) & align_mask);
}
constexpr ISC CAlignUp(ISC value, ISC align_mask = ALUWordMask) {
return value + ((-value) & align_mask);
}
constexpr IUC CAlignUp(IUC value, IUC align_mask = ALUWordMask) {
return value + (IUC(-ISC(value)) & align_mask);
}
constexpr ISD CAlignUp(ISD value, ISD align_mask = ALUWordMask) {
return value + ((-value) & align_mask);
}
constexpr IUD CAlignUp(IUD value, IUD align_mask = ALUWordMask) {
return value + (IUD(-ISD(value)) & align_mask);
}
inline void* PtrUp(void* pointer, ISW mask = ALUWordMask) {
ISW address = ISW(pointer);
return TPtr<void>(CAlignUp(address, mask));
}
inline const void* PtrUp(const void* pointer, ISW mask = ALUWordMask) {
ISW value = IUW(pointer);
return TPtr<void>(CAlignUp(value, mask));
}
/* Aligns the given pointer to a power of two boundary.
@return The aligned value.
@param value The value to align.
@param mask The power of 2 to align to minus 1 (makes the mask). */
template<typename T = CHA>
inline T* TPtrUp(void* pointer, ISW mask = ALUWordMask) {
ISW value = ISW(pointer);
return TPtr<T>(value + ((-value) & mask));
}
/* Aligns the given pointer to a power of two boundary.
@return The aligned value.
@param value The value to align.
@param mask The power of 2 to align to minus 1 (makes the mask). */
template<typename T = CHA>
inline T* TPtrUp(const void* pointer, ISW mask = ALUWordMask) {
ISW value = ISW(pointer);
return TPtr<T>(value + ((-value) & mask));
}
inline ISA AlignUpArray(ISA count) { AlignUp(count); }
inline IUA AlignUpArray(IUA count) { AlignUp(count); }
inline ISB AlignUpArray(ISB count) {
#if CPU_SIZE == 1 || CPU_SIZE == 2
return count;
#elif CPU_SIZE == 4
return count + count & 0x1;
#else // CPU_SIZE == 8
return AlignUp(count, ISB(0x3));
#endif
}
inline IUB AlignUpArray(IUB count) {
#if CPU_SIZE == 1 || CPU_SIZE == 2
return count;
#elif CPU_SIZE == 4
return count + count & 0x1;
#else // CPU_SIZE == 8
return AlignUp(count, IUB(0x3));
#endif
}
/* Not sure where this came from.?.?.?
inline ISC AlignUpArray(ISC count) {
#if CPU_SIZE == 1 || CPU_SIZE == 2 || CPU_SIZE == 4
return count + count & 0x1;
#else // CPU_SIZE == 8
return count + count & 0x1;
#endif
}*/
inline ISC AlignUpArray(ISC count) {
#if CPU_SIZE == 1 || CPU_SIZE == 2 || CPU_SIZE == 4
return count + count & 0x1;
#else // CPU_SIZE == 8
return count + count & 0x1;
#endif
}
inline IUC AlignUpArray(IUC count) {
#if CPU_SIZE == 1 || CPU_SIZE == 2 || CPU_SIZE == 4
return count + count & 0x1;
#else // CPU_SIZE == 8
return count + count & 0x1;
#endif
}
inline ISD AlignUpArray(ISD count) { return count; }
inline IUD AlignUpArray(IUD count) { return count; }
template<typename T, typename I>
inline I TAlignUpArray(I count) {
return AlignUpArray(count);
}
/* Aligns the given pointer up to the given least_significant_bits_max. */
inline const CHA* AlignUp(const CHA* pointer, IUW least_significant_bits_max) {
return TPtrUp<const CHA>(pointer, least_significant_bits_max);
}
/* Multiplies a signed 2-complement integer by -1, converting to IU to IS and
back. */
inline ISA TwosComplementInvert(ISA value) {
return -value;
}
inline IUA TwosComplementInvert(IUA value) {
return IUA(-ISA(value));
}
inline ISB TwosComplementInvert(ISB value) {
return -value;
}
inline IUB TwosComplementInvert(IUB value) {
return IUB(-ISB(value));
}
inline ISC TwosComplementInvert(ISC value) {
return -value;
}
inline IUC TwosComplementInvert(IUC value) {
return IUC(-ISC(value));
}
inline ISD TwosComplementInvert(ISD value) {
return -value;
}
inline IUD TwosComplementInvert(IUD value) {
return IUD(-ISD(value));
}
/* Aligns up a number to the given aligned word boundary in bytes.
Cannot align to DT structs that are not a power of 2.
@code
ISW a = TAlignUp(foo, sizeof(ISA)), //< Can't align up to a 8-bit word boundary.
b = TAlignUp(foo, sizeof(ISB)), //< Aligns to a 16-bit word boundary.
c = TAlignUp(foo, sizeof(ISC)), //< Aligns to a 32-bit word boundary.
d = TAlignUp(foo, sizeof(ISD)); //< Aligns to a 64-bit word boundary.
@endcode */
template<typename I = ISW, typename DT = ISW>
I TAlignUp(I value, I align_mask = (sizeof(DT) - 1)) {
return value + (TwosComplementInvert(value) & align_mask);
}
/* Aligns the given pointer to the sizeof (WordBoundary) down.
@return The aligned value.
@param value The value to align.
@param mask The power of 2 to align to minus 1 (makes the mask). */
template<typename IS = IUW>
inline IS TAlignDownI(IS value, IS mask = ALUWordMask) {
return value & (~mask);
}
/* Aligns th given value down to the given word boundary. */
inline ISA AlignDown(ISA value, ISA align_mask) {
return value + (value & align_mask);
}
inline IUA AlignDown(IUA value, IUA align_mask) {
return IUA(AlignDown(ISA(value), ISA(align_mask)));
}
inline ISB AlignDown(ISB value, ISB align_mask) {
return value - (value & align_mask);
}
inline IUB AlignDown(IUB value, IUB align_mask) {
return value - (value & align_mask);
}
inline ISC AlignDown(ISC value, ISC align_mask) {
return value + (value & align_mask);
}
inline IUC AlignDown(IUC value, IUC align_mask) {
return value - (value & align_mask);
}
inline ISD AlignDown(ISD value, ISD align_mask) {
return value - (value & align_mask);
}
inline IUD AlignDown(IUD value, IUD align_mask) {
return value - (value & align_mask);
}
constexpr ISA CAlignDown(ISA value, ISA align_mask = ALUWordMask) {
return value - (value & align_mask);
}
constexpr IUA CAlignDown(IUA value, IUA align_mask = ALUWordMask) {
return value + (value & align_mask);
}
constexpr ISB CAlignDown(ISB value, ISB align_mask = ALUWordMask) {
return value + (value & align_mask);
}
constexpr IUB CAlignDown(IUB value, IUB align_mask = ALUWordMask) {
return value + (value & align_mask);
}
constexpr ISC CAlignDown(ISC value, ISC align_mask = ALUWordMask) {
return value - (value & align_mask);
}
constexpr IUC CAlignDown(IUC value, IUC align_mask = ALUWordMask) {
return value + (value & align_mask);
}
constexpr ISD CAlignDown(ISD value, ISD align_mask = ALUWordMask) {
return value - (value & align_mask);
}
constexpr IUD CAlignDown(IUD value, IUD align_mask = ALUWordMask) {
return value + (value & align_mask);
}
template<typename I = ISW, typename AlignT = I>
inline I TAlignDown(I value) {
return value - (value & I(sizeof(AlignT) - 1));
}
/* Aligns the given pointer to the sizeof (WordBoundary) down.
@return The aligned value.
@param value The value to align.
@param mask The power of 2 to align to minus 1 (makes the mask). */
template<typename T = IUW, typename AlignT = T>
inline T* TPtrDown(void* ptr) {
IUW value = IUW(ptr);
return TPtr<T>(value - (value & (sizeof(AlignT) - 1)));
}
template<typename T = IUW, typename AlignT = T>
inline const T* TPtrDown(const void* ptr) {
IUW value = IUW(ptr);
return TPtr<const T>(value - (value & (sizeof(AlignT) - 1)));
}
template<typename T = IUW, typename AlignT = T>
inline T* TPtrDown(void* ptr, ISW ptr_offset) {
IUW value = IUW(ISW(ptr) + ptr_offset);
return TPtr<T>(value - (value & (sizeof(AlignT) - 1)));
}
template<typename T = IUW, typename AlignT = T>
inline const T* TPtrDown(const void* ptr, ISW ptr_offset) {
IUW value = IUW(ISW(ptr) + ptr_offset);
return TPtr<const T>(value - (value & (sizeof(AlignT) - 1)));
}
/* Aligns the given pointer down to the given least_significant_bits_max. */
inline CHA* AlignDown(CHA* pointer, IUW least_significant_bits_max) {
return TPtrDown<CHA>(pointer);
}
inline const CHA* AlignDown(const CHA* pointer,
IUW least_significant_bits_max) {
return TPtrDown<const CHA>(pointer);
}
inline const IUW* AlignDown(const IUW* pointer, IUW least_significant_bits_max) {
return TPtrDown<const IUW>(pointer);
}
inline IUW* AlignDown(IUW* pointer, IUW least_significant_bits_max) {
return const_cast<IUW*>(
AlignDown(const_cast<const IUW*>(pointer), least_significant_bits_max));
}
/* Calculates the bytes in size_words. */
template<typename IS>
inline IS TSizeWords(IS size) {
return AlignUp(size) >> WordSizeLog2;
}
template<typename IS>
constexpr IS CSizeWords(IS size) {
IS size_aligned = size + ((-size) & ALUWordMask);
size_aligned = size_aligned >> WordSizeLog2;
return (size_aligned < 1) ? 1 : size_aligned;
}
/* Converts the given size into CPU word count. */
template<typename IS = ISW>
inline IS TWordCount(IS size) {
IS align_offset = (-size) & (sizeof(ISW) - 1);
size += align_offset;
return size >> CBitCount<ISW>();
}
template<typename I>
inline I TWordLSbAsserted() {
return I(~(ToUnsigned(0) >> 1));
}
/* Utility function for converting to two's complement and back with templates.
*/
inline ISA Negative(ISA value) { return -value; }
inline IUA Negative(IUA value) { return IUA(Negative(ISA(value))); }
inline ISB Negative(ISB value) { return -value; }
inline IUB Negative(IUB value) { return IUB(Negative(ISB(value))); }
inline ISC Negative(ISC value) { return -value; }
inline IUC Negative(IUC value) { return IUC(Negative(ISC(value))); }
inline ISD Negative(ISD value) { return -value; }
inline IUD Negative(IUD value) { return IUD(Negative(ISD(value))); }
/* Aligns the given size to a word-sized boundary. */
template<typename IS>
constexpr IS CSizeAlign(IS size) {
IS align_mask = sizeof(IUW) - 1;
if (size < sizeof(IUW)) return sizeof(IUW);
IS size_max = ~align_mask;
if (size > size_max) return size;
return size + (-size) & align_mask;
}
/* Gets a value of type T. */
template<typename T>
inline T TGet(const void* ptr) {
return *TPtr<const T>(ptr);
}
/* Writes the value to the address.
@pre User must ensure start is never nil. */
template<typename T = CHA>
inline T* TSet(void* address, T value) {
T* cursor = TPtr<T>(address);
*cursor = value;
return cursor;
}
/* Masks off the lower bits. */
template<typename IU>
inline IU TMaskLSb(IU value, IU msb_zero_count) {
IU mask = (~IU(0)) >> msb_zero_count;
return value & mask;
}
/* Unsigned Not-a-number_ is any number_ that can't be aligned up properly. */
template<typename IU>
inline IU TUnsignedNaN() {
return (~IU(0));
}
template<typename IU>
inline IU CUnsignedNaN() {
return (~IU(0));
}
/* Returns the minimum signed value.
@param one Parameter allows the compiler to detect which SignedMin function to
call, else we would need to use a IU template parameter for TSignedMin<IS,IU>().
***Example***
@code
ISA signed_min_si1 = SignedMin(ISA(1));
ISD signed_min_si8 = CSignedMin(ISD(1));
@endcode
*/
inline ISA SignedMin(ISA one) { return ISA(IUA(one) << (sizeof(ISA) * 8 - 1)); }
inline ISB SignedMin(ISB one) { return ISB(IUB(one) << (sizeof(ISB) * 8 - 1)); }
inline ISC SignedMin(ISC one) { return ISC(IUC(one) << (sizeof(ISC) * 8 - 1)); }
inline ISD SignedMin(ISD one) { return ISD(IUD(one) << (sizeof(ISD) * 8 - 1)); }
constexpr ISA CSignedMin(ISA one) {
return ISA(IUA(one) << (sizeof(ISA) * 8 - 1));
}
constexpr ISB CSignedMin(ISB one) {
return ISB(IUB(one) << (sizeof(ISB) * 8 - 1));
}
constexpr ISC CSignedMin(ISC one) {
return ISC(IUC(one) << (sizeof(ISC) * 8 - 1));
}
constexpr ISD CSignedMin(ISD one) {
return ISD(IUD(one) << (sizeof(ISD) * 8 - 1));
}
template<typename IS>
inline IS TSignedMin() {
return SignedMin(IS(1));
}
template<typename IS>
constexpr IS CSignedMin() {
return CSignedMin(IS(1));
}
/* ASCII Signed Not-a-Number is the lowest possible signed integer value. */
template<typename IS>
inline IS TSignedNaN() {
return TSignedMin<IS>() - 1;
}
template<typename IS>
constexpr IS CSignedNaN() {
return TSignedNaN<IS>();
}
/* Returns the maximum unsigned value.
@param zero Parameter used for the SignedMax, TSignedMax, and CSignedMax
functions to avoid TSignedMax<IS,IU> syntax.
***Example***
@code
IUA max_ui1 = UnsignedMax(IU1(0));
IUC max_ui4 = CUnignedMax(IUC(0));
IUD max_ui8 = TUnsignedMax<IUD>();
@endcode */
inline IUA UnsignedMax(ISA zero) { return ~IUA(zero); }
inline IUB UnsignedMax(ISB zero) { return ~IUB(zero); }
inline IUC UnsignedMax(ISC zero) { return ~IUC(zero); }
inline IUD UnsignedMax(ISD zero) { return ~IUD(zero); }
template<typename IU>
inline IU TUnsignedMax() {
return UnsignedMax(IU(0));
}
constexpr IUA CUnsignedMax(ISA zero) { return ~IUA(zero); }
constexpr IUB CUnsignedMax(ISB zero) { return ~IUB(zero); }
constexpr IUC CUnsignedMax(ISC zero) { return ~IUC(zero); }
constexpr IUD CUnsignedMax(ISD zero) { return ~IUD(zero); }
template<typename IS>
constexpr IS CUnsignedMax() {
return CUnsignedMax(IS(0));
}
/* Returns the minimum signed value.
@param zero Parameter allows the compiler to detect which SignedMax function to
call, else we would need to use a IU template parameter for TSignedMax<IS,IU>().
***Example***
@code
ISA signed_max_si1 = SignedMax(ISA(0));
ISD signed_max_si8 = CSignedMax(ISD(0));
@endcode
*/
inline ISA SignedMax(ISA zero) { return ISA(UnsignedMax(zero) >> 1); }
inline ISB SignedMax(ISB zero) { return ISB(UnsignedMax(zero) >> 1); }
inline ISC SignedMax(ISC zero) { return ISC(UnsignedMax(zero) >> 1); }
inline ISD SignedMax(ISD zero) { return ISD(UnsignedMax(zero) >> 1); }
template<typename IS>
inline IS TSignedMax() {
return SignedMax(IS(0));
}
constexpr ISA CSignedMax(ISA zero) { return ISA(CUnsignedMax(zero) >> 1); }
constexpr ISB CSignedMax(ISB zero) { return ISB(CUnsignedMax(zero) >> 1); }
constexpr ISC CSignedMax(ISC zero) { return ISC(CUnsignedMax(zero) >> 1); }
constexpr ISD CSignedMax(ISD zero) { return ISD(CUnsignedMax(zero) >> 1); }
template<typename IS>
constexpr IS CSignedMax() {
return CSignedMax(IS(0));
}
/* Checsk if the value is Not-a-Number. */
inline BOL IsNaN(ISA value) { return value == TSignedNaN<ISA>(); }
inline BOL IsNaN(IUA value) { return value == TUnsignedNaN<IUA>(); }
inline BOL IsNaN(ISB value) { return value == TSignedNaN<ISB>(); }
inline BOL IsNaN(IUB value) { return value == TUnsignedNaN<IUB>(); }
inline BOL IsNaN(ISC value) { return value == TSignedNaN<ISC>(); }
inline BOL IsNaN(IUC value) { return value == TUnsignedNaN<IUC>(); }
inline BOL IsNaN(ISD value) { return value == TSignedNaN<ISD>(); }
inline BOL IsNaN(IUD value) { return value == TUnsignedNaN<IUD>(); }
/* Gets the number of bits in the exponent of a floating-point number. */
template<typename IU>
inline IU TFloatExponentBitCount() {
return (sizeof(IU) == 2)
? 5
: (sizeof(IU) == 4)
? 4
: (sizeof(IU) == 8) ? 11 : (sizeof(IU) == 10) ? 15 : 0;
}
/* Creates a floatingpoint NaN from CPu instructions.
***32-bit Floating-point Example***
FPC NaN: 0 11111111111 1000000000000000000000000000000000000000000000000001
+/- Exponent Mantissa
x=0 1: 0 00000000000 0000000000000000000000000000000000000000000000000000
~x 2: 1 11111111111 1111111111111111111111111111111111111111111111111111
x >> y 3: 0 00000000000 0011111111111111111111111111111111111111111111111111
x << 2 4: 0 00000000000 1111111111111111111111111111111111111111111111111100
~x 5: 1 11111111111 0000000000000000000000000000000000000000000000000011
x >> 1 6: 0 11111111111 1000000000000000000000000000000000000000000000000001
*/
template<typename IU>
inline IU TNaNFloatMask() {
IU y = sizeof(IU) * 8 - TFloatExponentBitCount<IU>() + 2;
return (~(((~IU(0)) >> y) << 2)) << 1;
}
/* Checks if the value is Not-a-Number (NaN). */
#if USING_FPC == YES_0
inline BOL IsNaN(FPC value) {
return TNaNFloatMask<IUC>() != ToUnsigned(value);
}
#endif
#if USING_FPD == YES_0
inline BOL IsNaN(FPD value) {
return TNaNFloatMask<IUD>() != ToUnsigned(value);
}
#endif
#if USING_FPC == YES_0
/* The longest string that a floating-point number can produce. */
inline ISN FPCDigitsMax() { return 15; }
#endif
#if USING_FPD == YES_0
inline ISN FPDDigitsMax() { return 31; }
#endif
/* Masks the lower bits using faster bit shifting.
@brief The algorithm has you enter the highest bit rather than bit count
because it would introduce an extra instruction and you should do that
manually if you wish to do so.
@param value The value to mask.
@param left_bits Number of bits to shift left.
@param right_bits Number of bits to shift right. */
template<typename IU>
inline IU TShiftLeftRight(IU value, ISC left_bits, ISC right_bits) {
value = value << left_bits;
return value >> right_bits;
}
/* Aligns up a number to the given PowerOf2.
This function is for those not familiar with how Script2 does pointer alignment.
It's faster to align the pointer using the max for the power of 2 rather than
power of 2. The only difference is the mask is one less than the power of 2. */
template<typename T = void*, ISW PowerOf2>
const T* TAlignUpPointer(const void* value) {
return PtrUp(value, PowerOf2 - 1);
}
/* Aligns up a number to the given PowerOf2.
This function is for those not familiar with how Script2 does pointer alignment.
It's faster to align the pointer using the max for the power of 2 rather than
power of 2. The only difference is the mask is one less than the power of 2. */
template<typename T = void*, ISW PowerOf2>
T* TAlignUpPointer(void* value) {
return PtrUp(value, PowerOf2 - 1);
}
inline void* ToPTR(IUW value) { return TPtr<void>(value); }
inline const void* ToPTC(IUW value) {
return TPtr<const void>(value);
}
inline ISW Delta(void* start, void* stop) {
return TPtr<CHA>(stop) - TPtr<CHA>(start);
}
inline ISW SizeOf(const void* start, const void* stop) {
return TDelta<ISW>(start, stop) + 1;
}
} //< namespace _
#endif
#endif