calc: generate calculators
[m6w6/ext-psi] / src / calc / bin.h
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #include "php_psi_stdinc.h"
27 #include <assert.h>
28
29 #include "token.h"
30
31 static inline token_t psi_calc_bin_lshift(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
32 {
33 impl_val i1, i2;
34
35 switch (t1) {
36 case PSI_T_INT8:
37 i1.u64 = v1->i8;
38 break;
39
40 case PSI_T_UINT8:
41 i1.u64 = v1->u8;
42 break;
43
44 case PSI_T_INT16:
45 i1.u64 = v1->i16;
46 break;
47
48 case PSI_T_UINT16:
49 i1.u64 = v1->u16;
50 break;
51
52 case PSI_T_INT32:
53 i1.u64 = v1->i32;
54 break;
55
56 case PSI_T_UINT32:
57 i1.u64 = v1->u32;
58 break;
59
60 case PSI_T_INT64:
61 i1.u64 = v1->i64;
62 break;
63
64 case PSI_T_UINT64:
65 i1.u64 = v1->u64;
66 break;
67
68 case PSI_T_FLOAT:
69 i1.u64 = v1->fval;
70 break;
71
72 case PSI_T_DOUBLE:
73 i1.u64 = v1->dval;
74 break;
75
76 #if HAVE_LONG_DOUBLE
77 case PSI_T_LONG_DOUBLE:
78 i1.u64 = v1->ldval;
79 break;
80
81 #endif
82
83 default:
84 assert(0);
85 break;
86 }
87
88 switch (t2) {
89 case PSI_T_INT8:
90 i2.u64 = v2->i8;
91 break;
92 case PSI_T_UINT8:
93 i2.u64 = v2->u8;
94 break;
95 case PSI_T_INT16:
96 i2.u64 = v2->i16;
97 break;
98 case PSI_T_UINT16:
99 i2.u64 = v2->u16;
100 break;
101 case PSI_T_INT32:
102 i2.u64 = v2->i32;
103 break;
104 case PSI_T_UINT32:
105 i2.u64 = v2->u32;
106 break;
107 case PSI_T_INT64:
108 i2.u64 = v2->i64;
109 break;
110 case PSI_T_UINT64:
111 i2.u64 = v2->u64;
112 break;
113 case PSI_T_FLOAT:
114 i2.u64 = v2->fval;
115 break;
116 case PSI_T_DOUBLE:
117 i2.u64 = v2->dval;
118 break;
119 #if HAVE_LONG_DOUBLE
120 case PSI_T_LONG_DOUBLE:
121 i2.u64 = v2->ldval;
122 break;
123 #endif
124
125 default:
126 assert(0);
127 break;
128 }
129
130 res->u64 = i1.u64 << i2.u64;
131 return PSI_T_UINT64;
132 }
133
134 static inline token_t psi_calc_bin_rshift(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
135 {
136 impl_val i1, i2;
137
138 switch (t1) {
139 case PSI_T_INT8:
140 i1.u64 = v1->i8;
141 break;
142
143 case PSI_T_UINT8:
144 i1.u64 = v1->u8;
145 break;
146
147 case PSI_T_INT16:
148 i1.u64 = v1->i16;
149 break;
150
151 case PSI_T_UINT16:
152 i1.u64 = v1->u16;
153 break;
154
155 case PSI_T_INT32:
156 i1.u64 = v1->i32;
157 break;
158
159 case PSI_T_UINT32:
160 i1.u64 = v1->u32;
161 break;
162
163 case PSI_T_INT64:
164 i1.u64 = v1->i64;
165 break;
166
167 case PSI_T_UINT64:
168 i1.u64 = v1->u64;
169 break;
170
171 case PSI_T_FLOAT:
172 i1.u64 = v1->fval;
173 break;
174
175 case PSI_T_DOUBLE:
176 i1.u64 = v1->dval;
177 break;
178
179 #if HAVE_LONG_DOUBLE
180 case PSI_T_LONG_DOUBLE:
181 i1.u64 = v1->ldval;
182 break;
183
184 #endif
185
186 default:
187 assert(0);
188 break;
189 }
190
191 switch (t2) {
192 case PSI_T_INT8:
193 i2.u64 = v2->i8;
194 break;
195 case PSI_T_UINT8:
196 i2.u64 = v2->u8;
197 break;
198 case PSI_T_INT16:
199 i2.u64 = v2->i16;
200 break;
201 case PSI_T_UINT16:
202 i2.u64 = v2->u16;
203 break;
204 case PSI_T_INT32:
205 i2.u64 = v2->i32;
206 break;
207 case PSI_T_UINT32:
208 i2.u64 = v2->u32;
209 break;
210 case PSI_T_INT64:
211 i2.u64 = v2->i64;
212 break;
213 case PSI_T_UINT64:
214 i2.u64 = v2->u64;
215 break;
216 case PSI_T_FLOAT:
217 i2.u64 = v2->fval;
218 break;
219 case PSI_T_DOUBLE:
220 i2.u64 = v2->dval;
221 break;
222 #if HAVE_LONG_DOUBLE
223 case PSI_T_LONG_DOUBLE:
224 i2.u64 = v2->ldval;
225 break;
226 #endif
227
228 default:
229 assert(0);
230 break;
231 }
232
233 res->u64 = i1.u64 >> i2.u64;
234 return PSI_T_UINT64;
235 }
236
237 static inline token_t psi_calc_bin_and(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
238 {
239 impl_val i1, i2;
240
241 switch (t1) {
242 case PSI_T_INT8:
243 i1.u64 = v1->i8;
244 break;
245
246 case PSI_T_UINT8:
247 i1.u64 = v1->u8;
248 break;
249
250 case PSI_T_INT16:
251 i1.u64 = v1->i16;
252 break;
253
254 case PSI_T_UINT16:
255 i1.u64 = v1->u16;
256 break;
257
258 case PSI_T_INT32:
259 i1.u64 = v1->i32;
260 break;
261
262 case PSI_T_UINT32:
263 i1.u64 = v1->u32;
264 break;
265
266 case PSI_T_INT64:
267 i1.u64 = v1->i64;
268 break;
269
270 case PSI_T_UINT64:
271 i1.u64 = v1->u64;
272 break;
273
274 case PSI_T_FLOAT:
275 i1.u64 = v1->fval;
276 break;
277
278 case PSI_T_DOUBLE:
279 i1.u64 = v1->dval;
280 break;
281
282 #if HAVE_LONG_DOUBLE
283 case PSI_T_LONG_DOUBLE:
284 i1.u64 = v1->ldval;
285 break;
286
287 #endif
288
289 default:
290 assert(0);
291 break;
292 }
293
294 switch (t2) {
295 case PSI_T_INT8:
296 i2.u64 = v2->i8;
297 break;
298 case PSI_T_UINT8:
299 i2.u64 = v2->u8;
300 break;
301 case PSI_T_INT16:
302 i2.u64 = v2->i16;
303 break;
304 case PSI_T_UINT16:
305 i2.u64 = v2->u16;
306 break;
307 case PSI_T_INT32:
308 i2.u64 = v2->i32;
309 break;
310 case PSI_T_UINT32:
311 i2.u64 = v2->u32;
312 break;
313 case PSI_T_INT64:
314 i2.u64 = v2->i64;
315 break;
316 case PSI_T_UINT64:
317 i2.u64 = v2->u64;
318 break;
319 case PSI_T_FLOAT:
320 i2.u64 = v2->fval;
321 break;
322 case PSI_T_DOUBLE:
323 i2.u64 = v2->dval;
324 break;
325 #if HAVE_LONG_DOUBLE
326 case PSI_T_LONG_DOUBLE:
327 i2.u64 = v2->ldval;
328 break;
329 #endif
330
331 default:
332 assert(0);
333 break;
334 }
335
336 res->u64 = i1.u64 & i2.u64;
337 return PSI_T_UINT64;
338 }
339
340 static inline token_t psi_calc_bin_xor(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
341 {
342 impl_val i1, i2;
343
344 switch (t1) {
345 case PSI_T_INT8:
346 i1.u64 = v1->i8;
347 break;
348
349 case PSI_T_UINT8:
350 i1.u64 = v1->u8;
351 break;
352
353 case PSI_T_INT16:
354 i1.u64 = v1->i16;
355 break;
356
357 case PSI_T_UINT16:
358 i1.u64 = v1->u16;
359 break;
360
361 case PSI_T_INT32:
362 i1.u64 = v1->i32;
363 break;
364
365 case PSI_T_UINT32:
366 i1.u64 = v1->u32;
367 break;
368
369 case PSI_T_INT64:
370 i1.u64 = v1->i64;
371 break;
372
373 case PSI_T_UINT64:
374 i1.u64 = v1->u64;
375 break;
376
377 case PSI_T_FLOAT:
378 i1.u64 = v1->fval;
379 break;
380
381 case PSI_T_DOUBLE:
382 i1.u64 = v1->dval;
383 break;
384
385 #if HAVE_LONG_DOUBLE
386 case PSI_T_LONG_DOUBLE:
387 i1.u64 = v1->ldval;
388 break;
389
390 #endif
391
392 default:
393 assert(0);
394 break;
395 }
396
397 switch (t2) {
398 case PSI_T_INT8:
399 i2.u64 = v2->i8;
400 break;
401 case PSI_T_UINT8:
402 i2.u64 = v2->u8;
403 break;
404 case PSI_T_INT16:
405 i2.u64 = v2->i16;
406 break;
407 case PSI_T_UINT16:
408 i2.u64 = v2->u16;
409 break;
410 case PSI_T_INT32:
411 i2.u64 = v2->i32;
412 break;
413 case PSI_T_UINT32:
414 i2.u64 = v2->u32;
415 break;
416 case PSI_T_INT64:
417 i2.u64 = v2->i64;
418 break;
419 case PSI_T_UINT64:
420 i2.u64 = v2->u64;
421 break;
422 case PSI_T_FLOAT:
423 i2.u64 = v2->fval;
424 break;
425 case PSI_T_DOUBLE:
426 i2.u64 = v2->dval;
427 break;
428 #if HAVE_LONG_DOUBLE
429 case PSI_T_LONG_DOUBLE:
430 i2.u64 = v2->ldval;
431 break;
432 #endif
433
434 default:
435 assert(0);
436 break;
437 }
438
439 res->u64 = i1.u64 ^ i2.u64;
440 return PSI_T_UINT64;
441 }
442
443 static inline token_t psi_calc_bin_or(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
444 {
445 impl_val i1, i2;
446
447 switch (t1) {
448 case PSI_T_INT8:
449 i1.u64 = v1->i8;
450 break;
451
452 case PSI_T_UINT8:
453 i1.u64 = v1->u8;
454 break;
455
456 case PSI_T_INT16:
457 i1.u64 = v1->i16;
458 break;
459
460 case PSI_T_UINT16:
461 i1.u64 = v1->u16;
462 break;
463
464 case PSI_T_INT32:
465 i1.u64 = v1->i32;
466 break;
467
468 case PSI_T_UINT32:
469 i1.u64 = v1->u32;
470 break;
471
472 case PSI_T_INT64:
473 i1.u64 = v1->i64;
474 break;
475
476 case PSI_T_UINT64:
477 i1.u64 = v1->u64;
478 break;
479
480 case PSI_T_FLOAT:
481 i1.u64 = v1->fval;
482 break;
483
484 case PSI_T_DOUBLE:
485 i1.u64 = v1->dval;
486 break;
487
488 #if HAVE_LONG_DOUBLE
489 case PSI_T_LONG_DOUBLE:
490 i1.u64 = v1->ldval;
491 break;
492
493 #endif
494
495 default:
496 assert(0);
497 break;
498 }
499
500 switch (t2) {
501 case PSI_T_INT8:
502 i2.u64 = v2->i8;
503 break;
504 case PSI_T_UINT8:
505 i2.u64 = v2->u8;
506 break;
507 case PSI_T_INT16:
508 i2.u64 = v2->i16;
509 break;
510 case PSI_T_UINT16:
511 i2.u64 = v2->u16;
512 break;
513 case PSI_T_INT32:
514 i2.u64 = v2->i32;
515 break;
516 case PSI_T_UINT32:
517 i2.u64 = v2->u32;
518 break;
519 case PSI_T_INT64:
520 i2.u64 = v2->i64;
521 break;
522 case PSI_T_UINT64:
523 i2.u64 = v2->u64;
524 break;
525 case PSI_T_FLOAT:
526 i2.u64 = v2->fval;
527 break;
528 case PSI_T_DOUBLE:
529 i2.u64 = v2->dval;
530 break;
531 #if HAVE_LONG_DOUBLE
532 case PSI_T_LONG_DOUBLE:
533 i2.u64 = v2->ldval;
534 break;
535 #endif
536
537 default:
538 assert(0);
539 break;
540 }
541
542 res->u64 = i1.u64 | i2.u64;
543 return PSI_T_UINT64;
544 }
545
546 static inline token_t psi_calc_bin_not(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res)
547 {
548 impl_val i1;
549
550 (void) t2;
551 (void) v2;
552
553 switch (t1) {
554 case PSI_T_INT8:
555 i1.u64 = v1->i8;
556 break;
557
558 case PSI_T_UINT8:
559 i1.u64 = v1->u8;
560 break;
561
562 case PSI_T_INT16:
563 i1.u64 = v1->i16;
564 break;
565
566 case PSI_T_UINT16:
567 i1.u64 = v1->u16;
568 break;
569
570 case PSI_T_INT32:
571 i1.u64 = v1->i32;
572 break;
573
574 case PSI_T_UINT32:
575 i1.u64 = v1->u32;
576 break;
577
578 case PSI_T_INT64:
579 i1.u64 = v1->i64;
580 break;
581
582 case PSI_T_UINT64:
583 i1.u64 = v1->u64;
584 break;
585
586 case PSI_T_FLOAT:
587 i1.u64 = v1->fval;
588 break;
589
590 case PSI_T_DOUBLE:
591 i1.u64 = v1->dval;
592 break;
593
594 #if HAVE_LONG_DOUBLE
595 case PSI_T_LONG_DOUBLE:
596 i1.u64 = v1->ldval;
597 break;
598
599 #endif
600
601 default:
602 assert(0);
603 break;
604 }
605
606 res->u64 = ~i1.u64;
607 return PSI_T_UINT64;
608 }