1 module zua.vm.std.bit32;
2 import zua.vm.engine;
3 import zua.vm.reflection;
4 import std.typecons;
5
6 private uint lbit32_arshift(uint x, long disp) {
7 if (disp < 0) return x << -disp;
8 return cast(uint)(cast(int)x >> disp);
9 }
10
11 private uint lbit32_band(uint[] op...) {
12 uint res = 0xFFFFFFFF;
13 foreach (i; op) {
14 res &= i;
15 }
16 return res;
17 }
18
19 private uint lbit32_bnot(uint x) {
20 return ~x;
21 }
22
23 private uint lbit32_bor(uint[] op...) {
24 uint res = 0;
25 foreach (i; op) {
26 res |= i;
27 }
28 return res;
29 }
30
31 private bool lbit32_btest(uint[] op...) {
32 uint res = 0xFFFFFFFF;
33 foreach (i; op) {
34 res &= i;
35 }
36 return res != 0;
37 }
38
39 private uint lbit32_bxor(uint[] op...) {
40 uint res = 0;
41 foreach (i; op) {
42 res ^= i;
43 }
44 return res;
45 }
46
47 private uint lbit32_extract(uint x, long start, long width = 1) {
48 if (start < 0) {
49 throw new Exception("bad argument #2 to 'extract' (field cannot be negative)");
50 }
51 else if (width < 1) {
52 throw new Exception("bad argument #3 to 'extract' (width must be positive)");
53 }
54 else if (start + width > 32) {
55 throw new Exception("trying to access non-existent bits");
56 }
57 else if (width == 32) {
58 return x;
59 }
60
61 return (x >> start) & (1 << width) - 1;
62 }
63
64 private uint lbit32_replace(uint x, uint v, long start, long width = 1) {
65 if (start < 0) {
66 throw new Exception("bad argument #2 to 'replace' (field cannot be negative)");
67 }
68 else if (width < 1) {
69 throw new Exception("bad argument #3 to 'replace' (width must be positive)");
70 }
71 else if (start + width > 32) {
72 throw new Exception("trying to access non-existent bits");
73 }
74 else if (width == 32) {
75 return v;
76 }
77
78 uint zeroed = x & ~((1 << width) - 1 << start);
79 return zeroed | ((v & (1 << width) - 1) << start);
80 }
81
82 private uint lbit32_lrotate(uint x, long disp) {
83 disp %= 32;
84 if (disp < 0) disp += 32;
85 return (x << disp) | (x >> (32 - disp));
86 }
87
88 private uint lbit32_lshift(uint x, long disp) {
89 if (disp >= 32 || disp <= -32) return 0;
90 if (disp < 0) return x >> -disp;
91 return x << disp;
92 }
93
94 private uint lbit32_rrotate(uint x, long disp) {
95 disp %= 32;
96 if (disp < 0) disp += 32;
97 return (x >> disp) | (x << (32 - disp));
98 }
99
100 private uint lbit32_rshift(uint x, long disp) {
101 if (disp >= 32 || disp <= -32) return 0;
102 if (disp < 0) return x << -disp;
103 return x >> disp;
104 }
105
106 /** Get bit32 library */
107 Value bit32lib() {
108 TableValue res = new TableValue;
109 res.set(Value("arshift"), exposeFunction!(lbit32_arshift, "arshift"));
110 res.set(Value("band"), exposeFunction!(lbit32_band, "band"));
111 res.set(Value("bnot"), exposeFunction!(lbit32_bnot, "bnot"));
112 res.set(Value("bor"), exposeFunction!(lbit32_bor, "bor"));
113 res.set(Value("btest"), exposeFunction!(lbit32_btest, "btest"));
114 res.set(Value("bxor"), exposeFunction!(lbit32_bxor, "bxor"));
115 res.set(Value("extract"), exposeFunction!(lbit32_extract, "extract"));
116 res.set(Value("replace"), exposeFunction!(lbit32_replace, "replace"));
117 res.set(Value("lrotate"), exposeFunction!(lbit32_lrotate, "lrotate"));
118 res.set(Value("lshift"), exposeFunction!(lbit32_lshift, "lshift"));
119 res.set(Value("rrotate"), exposeFunction!(lbit32_rrotate, "rrotate"));
120 res.set(Value("rshift"), exposeFunction!(lbit32_rshift, "rshift"));
121 return Value(res);
122 }