1 /*
2     SuperCollider real time audio synthesis system
3     Copyright (c) 2002 James McCartney. All rights reserved.
4     http://www.audiosynth.com
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19 */
20 
21 #include <math.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "Opcodes.h"
26 #include "PyrInterpreter.h"
27 #include "PyrPrimitive.h"
28 #include "PyrPrimitiveProto.h"
29 #include "PyrMathPrim.h"
30 #include "PyrKernel.h"
31 #include "PyrMessage.h"
32 #include "PyrParseNode.h"
33 #include "PyrSignal.h"
34 #include "PyrSched.h"
35 #include "PyrSymbol.h"
36 #include "SC_InlineUnaryOp.h"
37 #include "SC_InlineBinaryOp.h"
38 #include "MiscInlineMath.h"
39 #include "PyrKernelProto.h"
40 
41 #include <limits>
42 
43 double hypotx(double x, double y);
44 
45 #define IS_BINARY_BOOL_OP(op) ((op) >= opEQ && (op) <= opGE)
46 
doSpecialUnaryArithMsg(VMGlobals * g,int numArgsPushed)47 int doSpecialUnaryArithMsg(VMGlobals* g, int numArgsPushed) {
48     PyrSlot* a;
49     PyrSymbol* msg;
50     int opcode = g->primitiveIndex;
51 
52     a = g->sp;
53 
54     switch (GetTag(a)) {
55     case tagInt:
56         switch (opcode) {
57         case opNeg:
58             SetRaw(a, -slotRawInt(a));
59             break;
60         // case opNot : goto send_normal_1;
61         case opIsNil:
62             SetFalse(a);
63             break;
64         case opNotNil:
65             SetTrue(a);
66             break;
67         case opBitNot:
68             SetRaw(a, ~slotRawInt(a));
69             break;
70         case opAbs:
71             SetRaw(a, sc_abs(slotRawInt(a)));
72             break;
73         case opAsFloat:
74             SetFloat(a, (double)slotRawInt(a));
75             break;
76         case opAsInteger:
77             SetRaw(a, (int)slotRawInt(a));
78             break;
79         case opCeil:
80             SetRaw(a, slotRawInt(a));
81             break;
82         case opFloor:
83             SetRaw(a, slotRawInt(a));
84             break;
85         case opFrac:
86             SetRaw(a, 0);
87             break;
88         case opSign:
89             SetRaw(a, slotRawInt(a) > 0 ? 1 : (slotRawInt(a) == 0 ? 0 : -1));
90             break;
91         case opSquared:
92             SetRaw(a, slotRawInt(a) * slotRawInt(a));
93             break;
94         case opCubed:
95             SetRaw(a, slotRawInt(a) * slotRawInt(a) * slotRawInt(a));
96             break;
97         case opSqrt:
98             SetFloat(a, sqrt((double)slotRawInt(a)));
99             break;
100         case opExp:
101             SetFloat(a, exp((double)slotRawInt(a)));
102             break;
103         case opRecip:
104             SetFloat(a, 1. / slotRawInt(a));
105             break;
106         case opMIDICPS:
107             SetFloat(a, sc_midicps((double)slotRawInt(a)));
108             break;
109         case opCPSMIDI:
110             SetFloat(a, sc_cpsmidi((double)slotRawInt(a)));
111             break;
112         case opMIDIRatio:
113             SetFloat(a, sc_midiratio((double)slotRawInt(a)));
114             break;
115         case opRatioMIDI:
116             SetFloat(a, sc_ratiomidi((double)slotRawInt(a)));
117             break;
118         case opAmpDb:
119             SetFloat(a, sc_ampdb((double)slotRawInt(a)));
120             break;
121         case opDbAmp:
122             SetFloat(a, sc_dbamp((double)slotRawInt(a)));
123             break;
124         case opOctCPS:
125             SetFloat(a, sc_octcps((double)slotRawInt(a)));
126             break;
127         case opCPSOct:
128             SetFloat(a, sc_cpsoct((double)slotRawInt(a)));
129             break;
130         case opLog:
131             SetFloat(a, log((double)slotRawInt(a)));
132             break;
133         case opLog2:
134             SetFloat(a, sc_log2((double)slotRawInt(a)));
135             break;
136         case opLog10:
137             SetFloat(a, log10((double)slotRawInt(a)));
138             break;
139         case opSin:
140             SetFloat(a, sin((double)slotRawInt(a)));
141             break;
142         case opCos:
143             SetFloat(a, cos((double)slotRawInt(a)));
144             break;
145         case opTan:
146             SetFloat(a, tan((double)slotRawInt(a)));
147             break;
148         case opArcSin:
149             SetFloat(a, asin((double)slotRawInt(a)));
150             break;
151         case opArcCos:
152             SetFloat(a, acos((double)slotRawInt(a)));
153             break;
154         case opArcTan:
155             SetFloat(a, atan((double)slotRawInt(a)));
156             break;
157         case opSinH:
158             SetFloat(a, sinh((double)slotRawInt(a)));
159             break;
160         case opCosH:
161             SetFloat(a, cosh((double)slotRawInt(a)));
162             break;
163         case opTanH:
164             SetFloat(a, tanh((double)slotRawInt(a)));
165             break;
166         case opRand:
167             SetRaw(a, g->rgen->irand(slotRawInt(a)));
168             break;
169         case opRand2:
170             SetRaw(a, g->rgen->irand2(slotRawInt(a)));
171             break;
172         case opLinRand:
173             SetRaw(a, g->rgen->ilinrand(slotRawInt(a)));
174             break;
175         case opBiLinRand:
176             SetRaw(a, g->rgen->ibilinrand(slotRawInt(a)));
177             break;
178 
179             //				case opExpRand : SetFloat(a, g->rgen->exprand(slotRawInt(a))); break;
180             //				case opBiExpRand : SetFloat(a, g->rgen->biexprand(slotRawInt(a))); break;
181         case opSum3Rand:
182             SetFloat(a, g->rgen->sum3rand(slotRawInt(a)));
183             break;
184 
185             //				case opGammaRand : SetFloat(a, g->rgen->gammarand(slotRawInt(a))); break;
186             //				case opGaussRand : SetFloat(a, g->rgen->gaussrand(slotRawInt(a))); break;
187             //				case opPoiRand : SetFloat(a, g->rgen->poirand(slotRawInt(a))); break;
188 
189         case opDistort:
190             SetFloat(a, sc_distort((double)slotRawInt(a)));
191             break;
192         case opSoftClip:
193             SetFloat(a, sc_softclip((double)slotRawInt(a)));
194             break;
195         case opCoin:
196             SetBool(a, (slotRawInt(a)));
197             break;
198         case opRectWindow:
199             SetFloat(a, sc_rectwindow((double)slotRawInt(a)));
200             break;
201         case opHanWindow:
202             SetFloat(a, sc_hanwindow((double)slotRawInt(a)));
203             break;
204         case opWelchWindow:
205             SetFloat(a, sc_welwindow((double)slotRawInt(a)));
206             break;
207         case opTriWindow:
208             SetFloat(a, sc_triwindow((double)slotRawInt(a)));
209             break;
210         case opSCurve:
211             SetFloat(a, sc_scurve((double)slotRawInt(a)));
212             break;
213         case opRamp:
214             SetFloat(a, sc_ramp((double)slotRawInt(a)));
215             break;
216         default:
217             goto send_normal_1;
218         }
219         break;
220     case tagChar:
221         switch (opcode) {
222         // case opNot : goto send_normal_1;
223         case opIsNil:
224             SetFalse(a);
225             break;
226         case opNotNil:
227             SetTrue(a);
228             break;
229         case opAsInteger:
230             SetTagRaw(a, tagInt);
231             break;
232         case opDigitValue:
233             if (slotRawInt(a) >= '0' && slotRawInt(a) <= '9')
234                 SetInt(a, slotRawInt(a) - '0');
235             else if (slotRawInt(a) >= 'A' && slotRawInt(a) <= 'Z')
236                 SetInt(a, slotRawInt(a) - 'A');
237             else if (slotRawInt(a) >= 'a' && slotRawInt(a) <= 'z')
238                 SetInt(a, slotRawInt(a) - 'a');
239             else
240                 SetInt(a, 0);
241             break;
242         default:
243             goto send_normal_1;
244         }
245         break;
246     case tagPtr:
247         switch (opcode) {
248         case opIsNil:
249             SetFalse(a);
250             break;
251         case opNotNil:
252             SetTrue(a);
253             break;
254         default:
255             goto send_normal_1;
256         }
257         break;
258     case tagNil:
259         switch (opcode) {
260         case opIsNil:
261             SetTrue(a);
262             break;
263         case opNotNil:
264             SetFalse(a);
265             break;
266         default:
267             goto send_normal_1;
268         }
269         break;
270     case tagFalse:
271         switch (opcode) {
272         case opNot:
273             SetTrue(a);
274             break;
275         case opIsNil: /*SetFalse(a);*/
276             break;
277         case opNotNil:
278             SetTrue(a);
279             break;
280         default:
281             goto send_normal_1;
282         }
283         break;
284     case tagTrue:
285         switch (opcode) {
286         case opNot:
287             SetFalse(a);
288             break;
289         case opIsNil:
290             SetFalse(a);
291             break;
292         case opNotNil: /*SetTrue(a);*/
293             break;
294         default:
295             goto send_normal_1;
296         }
297         break;
298     case tagSym:
299         switch (opcode) {
300         case opAsFloat:
301         case opAsInteger:
302             goto send_normal_1;
303         case opIsNil:
304             SetFalse(a);
305             break;
306         case opNotNil:
307             SetTrue(a);
308             break;
309         default: /* SetSymbol(a, slotRawSymbol(a)); */
310             break;
311         }
312         break;
313     case tagObj:
314         if (isKindOf(slotRawObject(a), class_signal)) {
315             switch (opcode) {
316             case opNeg:
317                 SetRaw(a, signal_invert(g, slotRawObject(a)));
318                 break;
319             case opIsNil:
320                 SetFalse(a);
321                 break;
322             case opNotNil:
323                 SetTrue(a);
324                 break;
325             case opAbs:
326                 SetRaw(a, signal_abs(g, slotRawObject(a)));
327                 break;
328             case opSign:
329                 SetRaw(a, signal_sign(g, slotRawObject(a)));
330                 break;
331             case opSquared:
332                 SetRaw(a, signal_squared(g, slotRawObject(a)));
333                 break;
334             case opCubed:
335                 SetRaw(a, signal_cubed(g, slotRawObject(a)));
336                 break;
337             case opSqrt:
338                 SetRaw(a, signal_sqrt(g, slotRawObject(a)));
339                 break;
340             case opExp:
341                 SetRaw(a, signal_exp(g, slotRawObject(a)));
342                 break;
343             case opRecip:
344                 SetRaw(a, signal_recip(g, slotRawObject(a)));
345                 break;
346             case opLog:
347                 SetRaw(a, signal_log(g, slotRawObject(a)));
348                 break;
349             case opLog2:
350                 SetRaw(a, signal_log2(g, slotRawObject(a)));
351                 break;
352             case opLog10:
353                 SetRaw(a, signal_log10(g, slotRawObject(a)));
354                 break;
355             case opSin:
356                 SetRaw(a, signal_sin(g, slotRawObject(a)));
357                 break;
358             // case opSin : SetRaw(a, signal_fsin(g, slotRawObject(a))); break;
359             case opCos:
360                 SetRaw(a, signal_cos(g, slotRawObject(a)));
361                 break;
362             case opTan:
363                 SetRaw(a, signal_tan(g, slotRawObject(a)));
364                 break;
365             case opArcSin:
366                 SetRaw(a, signal_asin(g, slotRawObject(a)));
367                 break;
368             case opArcCos:
369                 SetRaw(a, signal_acos(g, slotRawObject(a)));
370                 break;
371             case opArcTan:
372                 SetRaw(a, signal_atan(g, slotRawObject(a)));
373                 break;
374             case opSinH:
375                 SetRaw(a, signal_sinh(g, slotRawObject(a)));
376                 break;
377             case opCosH:
378                 SetRaw(a, signal_cosh(g, slotRawObject(a)));
379                 break;
380             case opTanH:
381                 SetRaw(a, signal_tanh(g, slotRawObject(a)));
382                 break;
383             case opDistort:
384                 SetRaw(a, signal_distort(g, slotRawObject(a)));
385                 break;
386             case opSoftClip:
387                 SetRaw(a, signal_softclip(g, slotRawObject(a)));
388                 break;
389             default:
390                 goto send_normal_1;
391             }
392         } else {
393             goto send_normal_1;
394         }
395         break;
396     default: // double
397         switch (opcode) {
398         case opNeg:
399             SetRaw(a, -slotRawFloat(a));
400             break;
401         case opIsNil:
402             SetFalse(a);
403             break;
404         case opNotNil:
405             SetTrue(a);
406             break;
407         case opBitNot:
408             SetRaw(a, ~(int)slotRawFloat(a));
409             break;
410         case opAbs:
411             SetRaw(a, sc_abs(slotRawFloat(a)));
412             break;
413         case opAsFloat:
414             SetRaw(a, (double)slotRawFloat(a));
415             break;
416         case opAsInteger: {
417             double val = slotRawFloat(a);
418             if (val == std::numeric_limits<double>::infinity())
419                 SetInt(a, std::numeric_limits<int>::max());
420             else
421                 SetInt(a, (int)val);
422             break;
423         }
424         case opCeil:
425             SetRaw(a, ceil(slotRawFloat(a)));
426             break;
427         case opFloor:
428             SetRaw(a, floor(slotRawFloat(a)));
429             break;
430         case opFrac:
431             SetRaw(a, sc_frac(slotRawFloat(a)));
432             break;
433         case opSign:
434             SetRaw(a, slotRawFloat(a) > 0. ? 1.0 : (slotRawFloat(a) == 0 ? 0.0 : -1.0));
435             break;
436         case opSquared:
437             SetRaw(a, slotRawFloat(a) * slotRawFloat(a));
438             break;
439         case opCubed:
440             SetRaw(a, slotRawFloat(a) * slotRawFloat(a) * slotRawFloat(a));
441             break;
442         case opSqrt:
443             SetRaw(a, sqrt(slotRawFloat(a)));
444             break;
445         case opExp:
446             SetRaw(a, exp(slotRawFloat(a)));
447             break;
448         case opRecip:
449             SetRaw(a, 1. / slotRawFloat(a));
450             break;
451         case opMIDICPS:
452             SetRaw(a, sc_midicps(slotRawFloat(a)));
453             break;
454         case opCPSMIDI:
455             SetRaw(a, sc_cpsmidi(slotRawFloat(a)));
456             break;
457         case opMIDIRatio:
458             SetRaw(a, sc_midiratio((double)slotRawFloat(a)));
459             break;
460         case opRatioMIDI:
461             SetRaw(a, sc_ratiomidi((double)slotRawFloat(a)));
462             break;
463         case opAmpDb:
464             SetRaw(a, sc_ampdb(slotRawFloat(a)));
465             break;
466         case opDbAmp:
467             SetRaw(a, sc_dbamp(slotRawFloat(a)));
468             break;
469         case opOctCPS:
470             SetRaw(a, sc_octcps(slotRawFloat(a)));
471             break;
472         case opCPSOct:
473             SetRaw(a, sc_cpsoct(slotRawFloat(a)));
474             break;
475         case opLog:
476             SetRaw(a, log(slotRawFloat(a)));
477             break;
478         case opLog2:
479             SetRaw(a, sc_log2(slotRawFloat(a)));
480             break;
481         case opLog10:
482             SetRaw(a, log10(slotRawFloat(a)));
483             break;
484         case opSin:
485             SetRaw(a, sin(slotRawFloat(a)));
486             break;
487         case opCos:
488             SetRaw(a, cos(slotRawFloat(a)));
489             break;
490         case opTan:
491             SetRaw(a, tan(slotRawFloat(a)));
492             break;
493         case opArcSin:
494             SetRaw(a, asin(slotRawFloat(a)));
495             break;
496         case opArcCos:
497             SetRaw(a, acos(slotRawFloat(a)));
498             break;
499         case opArcTan:
500             SetRaw(a, atan(slotRawFloat(a)));
501             break;
502         case opSinH:
503             SetRaw(a, sinh(slotRawFloat(a)));
504             break;
505         case opCosH:
506             SetRaw(a, cosh(slotRawFloat(a)));
507             break;
508         case opTanH:
509             SetRaw(a, tanh(slotRawFloat(a)));
510             break;
511         case opRand:
512             SetRaw(a, g->rgen->frand() * slotRawFloat(a));
513             break;
514         case opRand2:
515             SetRaw(a, g->rgen->frand2() * slotRawFloat(a));
516             break;
517         case opLinRand:
518             SetRaw(a, g->rgen->linrand(slotRawFloat(a)));
519             break;
520         case opBiLinRand:
521             SetRaw(a, g->rgen->bilinrand(slotRawFloat(a)));
522             break;
523 
524             //				case opExpRand   : SetRaw(a, g->rgen->exprand(slotRawFloat(a))); break;
525             //				case opBiExpRand : SetRaw(a, g->rgen->biexprand(slotRawFloat(a))); break;
526         case opSum3Rand:
527             SetRaw(a, g->rgen->sum3rand(slotRawFloat(a)));
528             break;
529 
530             //				case opGammaRand : SetRaw(a, g->rgen->gammarand(slotRawFloat(a))); break;
531             //				case opGaussRand : SetRaw(a, g->rgen->gaussrand(slotRawFloat(a))); break;
532             //				case opPoiRand   : SetRaw(a, g->rgen->poirand(slotRawFloat(a))); break;
533 
534         case opDistort:
535             SetRaw(a, sc_distort(slotRawFloat(a)));
536             break;
537         case opSoftClip:
538             SetRaw(a, sc_softclip(slotRawFloat(a)));
539             break;
540         case opCoin:
541             SetBool(a, g->rgen->frand() < slotRawFloat(a));
542             break;
543         case opRectWindow:
544             SetRaw(a, sc_rectwindow(slotRawFloat(a)));
545             break;
546         case opHanWindow:
547             SetRaw(a, sc_hanwindow(slotRawFloat(a)));
548             break;
549         case opWelchWindow:
550             SetRaw(a, sc_welwindow(slotRawFloat(a)));
551             break;
552         case opTriWindow:
553             SetRaw(a, sc_triwindow(slotRawFloat(a)));
554             break;
555         case opSCurve:
556             SetRaw(a, sc_scurve(slotRawFloat(a)));
557             break;
558         case opRamp:
559             SetRaw(a, sc_ramp(slotRawFloat(a)));
560             break;
561         default:
562             goto send_normal_1;
563         }
564         break;
565     }
566 
567 #if TAILCALLOPTIMIZE
568     g->tailCall = 0;
569 #endif
570     return errNone;
571 
572 send_normal_1:
573     if (numArgsPushed != -1) // special case flag meaning it is a primitive
574         return errFailed;
575 
576     msg = gSpecialUnarySelectors[opcode];
577     sendMessage(g, msg, 1);
578 
579     return errNone;
580 }
581 
prSpecialBinaryArithMsg(VMGlobals * g,int numArgsPushed)582 int prSpecialBinaryArithMsg(VMGlobals* g, int numArgsPushed) { return doSpecialBinaryArithMsg(g, numArgsPushed, true); }
583 
doSpecialBinaryArithMsg(VMGlobals * g,int numArgsPushed,bool isPrimitive)584 int doSpecialBinaryArithMsg(VMGlobals* g, int numArgsPushed, bool isPrimitive) {
585     PyrSlot *a, *b;
586     PyrSymbol* msg;
587     int opcode = g->primitiveIndex;
588 
589     a = g->sp - (numArgsPushed - 1);
590     b = a + 1;
591 
592     switch (GetTag(a)) {
593     case tagInt: {
594         switch (GetTag(b)) {
595         case tagInt:
596             switch (opcode) {
597             case opAdd:
598                 SetRaw(a, slotRawInt(a) + slotRawInt(b));
599                 break;
600             case opSub:
601                 SetRaw(a, slotRawInt(a) - slotRawInt(b));
602                 break;
603             case opMul:
604                 SetRaw(a, slotRawInt(a) * slotRawInt(b));
605                 break;
606             case opIDiv:
607                 SetRaw(a, sc_div(slotRawInt(a), slotRawInt(b)));
608                 break;
609             case opFDiv:
610                 SetFloat(a, (double)slotRawInt(a) / (double)slotRawInt(b));
611                 break;
612             case opMod:
613                 SetRaw(a, sc_mod((int)slotRawInt(a), (int)slotRawInt(b)));
614                 break;
615             case opEQ:
616                 SetBool(a, slotRawInt(a) == slotRawInt(b));
617                 break;
618             case opNE:
619                 SetBool(a, slotRawInt(a) != slotRawInt(b));
620                 break;
621             case opLT:
622                 SetBool(a, slotRawInt(a) < slotRawInt(b));
623                 break;
624             case opGT:
625                 SetBool(a, slotRawInt(a) > slotRawInt(b));
626                 break;
627             case opLE:
628                 SetBool(a, slotRawInt(a) <= slotRawInt(b));
629                 break;
630             case opGE:
631                 SetBool(a, slotRawInt(a) >= slotRawInt(b));
632                 break;
633             // case opIdentical : SetBool(a, slotRawInt(a) == slotRawInt(b)); break;
634             // case opNotIdentical : SetBool(a, slotRawInt(a) != slotRawInt(b)); break;
635             case opMin:
636                 SetRaw(a, sc_min(slotRawInt(a), slotRawInt(b)));
637                 break;
638             case opMax:
639                 SetRaw(a, sc_max(slotRawInt(a), slotRawInt(b)));
640                 break;
641             case opBitAnd:
642                 SetRaw(a, slotRawInt(a) & slotRawInt(b));
643                 break;
644             case opBitOr:
645                 SetRaw(a, slotRawInt(a) | slotRawInt(b));
646                 break;
647             case opBitXor:
648                 SetRaw(a, slotRawInt(a) ^ slotRawInt(b));
649                 break;
650             case opLCM:
651                 SetRaw(a, sc_lcm((long)slotRawInt(a), (long)slotRawInt(b)));
652                 break;
653             case opGCD:
654                 SetRaw(a, sc_gcd((long)slotRawInt(a), (long)slotRawInt(b)));
655                 break;
656             case opRound:
657                 SetRaw(a, sc_round((int)slotRawInt(a), (int)slotRawInt(b)));
658                 break;
659             case opRoundUp:
660                 SetRaw(a, sc_roundUp((int)slotRawInt(a), (int)slotRawInt(b)));
661                 break;
662             case opTrunc:
663                 SetRaw(a, sc_trunc((int)slotRawInt(a), (int)slotRawInt(b)));
664                 break;
665             case opAtan2:
666                 SetFloat(a, atan2((double)slotRawInt(a), (double)slotRawInt(b)));
667                 break;
668             case opHypot:
669                 SetFloat(a, hypot((double)slotRawInt(a), (double)slotRawInt(b)));
670                 break;
671             case opHypotx:
672                 SetFloat(a, hypotx((double)slotRawInt(a), (double)slotRawInt(b)));
673                 break;
674             case opPow:
675                 SetFloat(a, pow((double)slotRawInt(a), (double)slotRawInt(b)));
676                 break;
677             case opShiftLeft: {
678                 long ia = slotRawInt(a);
679                 long ib = slotRawInt(b);
680                 if (ib > 0)
681                     ia <<= ib;
682                 else if (ib < 0)
683                     ia >>= -ib;
684                 SetRaw(a, ia);
685             } break;
686             case opShiftRight: {
687                 long ia = slotRawInt(a);
688                 long ib = slotRawInt(b);
689                 if (ib > 0)
690                     ia >>= ib;
691                 else if (ib < 0)
692                     ia <<= -ib;
693                 SetRaw(a, ia);
694             } break;
695             case opUnsignedShift: {
696                 unsigned long ia = slotRawInt(a);
697                 long ib = slotRawInt(b);
698                 if (ib > 0)
699                     ia >>= ib;
700                 else if (ib < 0)
701                     ia <<= -ib;
702                 SetRaw(a, (long)ia);
703             } break;
704             case opRing1:
705                 SetRaw(a, sc_ring1(slotRawInt(a), slotRawInt(b)));
706                 break;
707             case opRing2:
708                 SetRaw(a, sc_ring2(slotRawInt(a), slotRawInt(b)));
709                 break;
710             case opRing3:
711                 SetRaw(a, sc_ring3(slotRawInt(a), slotRawInt(b)));
712                 break;
713             case opRing4:
714                 SetRaw(a, sc_ring4(slotRawInt(a), slotRawInt(b)));
715                 break;
716             case opDifSqr:
717                 SetRaw(a, sc_difsqr(slotRawInt(a), slotRawInt(b)));
718                 break;
719             case opSumSqr:
720                 SetRaw(a, sc_sumsqr(slotRawInt(a), slotRawInt(b)));
721                 break;
722             case opSqrSum:
723                 SetRaw(a, sc_sqrsum(slotRawInt(a), slotRawInt(b)));
724                 break;
725             case opSqrDif:
726                 SetRaw(a, sc_sqrdif(slotRawInt(a), slotRawInt(b)));
727                 break;
728             case opAbsDif:
729                 SetRaw(a, sc_abs(slotRawInt(a) - slotRawInt(b)));
730                 break;
731             case opThresh:
732                 SetRaw(a, sc_thresh(slotRawInt(a), slotRawInt(b)));
733                 break;
734             case opAMClip:
735                 SetRaw(a, sc_amclip(slotRawInt(a), slotRawInt(b)));
736                 break;
737             case opScaleNeg:
738                 SetRaw(a, sc_scaleneg(slotRawInt(a), slotRawInt(b)));
739                 break;
740             case opClip2:
741                 SetRaw(a, sc_clip2(slotRawInt(a), slotRawInt(b)));
742                 break;
743             case opFold2:
744                 SetRaw(a, sc_fold2(slotRawInt(a), slotRawInt(b)));
745                 break;
746             case opWrap2:
747                 SetRaw(a, sc_wrap2(slotRawInt(a), slotRawInt(b)));
748                 break;
749             case opExcess:
750                 SetRaw(a, sc_excess(slotRawInt(a), slotRawInt(b)));
751                 break;
752             case opFirstArg:
753                 SetRaw(a, slotRawInt(a));
754                 break;
755             case opRandRange:
756                 SetRaw(a,
757                        slotRawInt(b) > slotRawInt(a)
758                            ? slotRawInt(a) + g->rgen->irand(slotRawInt(b) - slotRawInt(a) + 1)
759                            : slotRawInt(b) + g->rgen->irand(slotRawInt(a) - slotRawInt(b) + 1));
760                 break;
761             case opExpRandRange:
762                 SetFloat(a, g->rgen->exprandrng(slotRawInt(a), slotRawInt(b)));
763                 break;
764             default:
765                 goto send_normal_2;
766             }
767             break;
768         case tagChar:
769         case tagPtr:
770         case tagNil:
771         case tagFalse:
772         case tagTrue:
773             goto send_normal_2;
774         case tagSym:
775             if (IS_BINARY_BOOL_OP(opcode))
776                 SetBool(a, opcode == opNE);
777             else
778                 SetSymbol(a, slotRawSymbol(b));
779             break;
780         case tagObj:
781             if (isKindOf(slotRawObject(b), class_signal)) {
782                 switch (opcode) {
783                 case opAdd:
784                     SetObject(a, signal_add_xf(g, slotRawObject(b), slotRawInt(a)));
785                     break;
786                 case opSub:
787                     SetObject(a, signal_sub_fx(g, slotRawInt(a), slotRawObject(b)));
788                     break;
789                 case opMul:
790                     SetObject(a, signal_mul_xf(g, slotRawObject(b), slotRawInt(a)));
791                     break;
792                 case opIDiv:
793                     SetObject(a, signal_div_fx(g, slotRawInt(a), slotRawObject(b)));
794                     break;
795                 case opFDiv:
796                     SetObject(a, signal_div_fx(g, slotRawInt(a), slotRawObject(b)));
797                     break;
798                 case opEQ:
799                     SetFalse(a);
800                     break;
801                 case opNE:
802                     SetTrue(a);
803                     break;
804                 case opMin:
805                     SetObject(a, signal_min_xf(g, slotRawObject(b), slotRawInt(a)));
806                     break;
807                 case opMax:
808                     SetObject(a, signal_max_xf(g, slotRawObject(b), slotRawInt(a)));
809                     break;
810                 case opRing1:
811                     SetObject(a, signal_ring1_fx(g, slotRawInt(a), slotRawObject(b)));
812                     break;
813                 case opRing2:
814                     SetObject(a, signal_ring2_fx(g, slotRawInt(a), slotRawObject(b)));
815                     break;
816                 case opRing3:
817                     SetObject(a, signal_ring3_fx(g, slotRawInt(a), slotRawObject(b)));
818                     break;
819                 case opRing4:
820                     SetObject(a, signal_ring4_fx(g, slotRawInt(a), slotRawObject(b)));
821                     break;
822                 case opDifSqr:
823                     SetObject(a, signal_difsqr_fx(g, slotRawInt(a), slotRawObject(b)));
824                     break;
825                 case opSumSqr:
826                     SetObject(a, signal_sumsqr_fx(g, slotRawInt(a), slotRawObject(b)));
827                     break;
828                 case opSqrSum:
829                     SetObject(a, signal_sqrsum_fx(g, slotRawInt(a), slotRawObject(b)));
830                     break;
831                 case opSqrDif:
832                     SetObject(a, signal_sqrdif_fx(g, slotRawInt(a), slotRawObject(b)));
833                     break;
834                 case opAbsDif:
835                     SetObject(a, signal_absdif_fx(g, slotRawInt(a), slotRawObject(b)));
836                     break;
837                 case opThresh:
838                     SetObject(a, signal_thresh_fx(g, slotRawInt(a), slotRawObject(b)));
839                     break;
840                 case opAMClip:
841                     SetObject(a, signal_amclip_fx(g, slotRawInt(a), slotRawObject(b)));
842                     break;
843                 case opScaleNeg:
844                     SetObject(a, signal_scaleneg_fx(g, slotRawInt(a), slotRawObject(b)));
845                     break;
846                 case opClip2:
847                     SetObject(a, signal_clip2_fx(g, slotRawInt(a), slotRawObject(b)));
848                     break;
849                 case opFold2:
850                     SetObject(a, signal_fold2_fx(g, slotRawInt(a), slotRawObject(b)));
851                     break;
852                 case opWrap2:
853                     SetObject(a, signal_wrap2_fx(g, slotRawInt(a), slotRawObject(b)));
854                     break;
855                 case opExcess:
856                     SetObject(a, signal_excess_fx(g, slotRawInt(a), slotRawObject(b)));
857                     break;
858                 case opFirstArg:
859                     SetObject(a, slotRawObject(a));
860                     break;
861                 default:
862                     goto send_normal_2;
863                 }
864             } else {
865                 goto send_normal_2;
866             }
867             break;
868         default:
869             switch (opcode) {
870             case opAdd:
871                 SetFloat(a, slotRawInt(a) + slotRawFloat(b));
872                 break;
873             case opSub:
874                 SetFloat(a, slotRawInt(a) - slotRawFloat(b));
875                 break;
876             case opMul:
877                 SetFloat(a, slotRawInt(a) * slotRawFloat(b));
878                 break;
879             case opIDiv:
880                 SetRaw(a, (long)floor(slotRawInt(a) / slotRawFloat(b)));
881                 break;
882             case opFDiv:
883                 SetFloat(a, slotRawInt(a) / slotRawFloat(b));
884                 break;
885             case opMod:
886                 SetFloat(a, sc_mod((double)slotRawInt(a), slotRawFloat(b)));
887                 break;
888             case opEQ:
889                 SetBool(a, slotRawInt(a) == slotRawFloat(b));
890                 break;
891             case opNE:
892                 SetBool(a, slotRawInt(a) != slotRawFloat(b));
893                 break;
894             case opLT:
895                 SetBool(a, slotRawInt(a) < slotRawFloat(b));
896                 break;
897             case opGT:
898                 SetBool(a, slotRawInt(a) > slotRawFloat(b));
899                 break;
900             case opLE:
901                 SetBool(a, slotRawInt(a) <= slotRawFloat(b));
902                 break;
903             case opGE:
904                 SetBool(a, slotRawInt(a) >= slotRawFloat(b));
905                 break;
906             // case opIdentical : SetFalse(a); break;
907             // case opNotIdentical : SetTrue(a); break;
908             case opMin:
909                 SetFloat(a, sc_min((double)slotRawInt(a), slotRawFloat(b)));
910                 break;
911             case opMax:
912                 SetFloat(a, sc_max((double)slotRawInt(a), slotRawFloat(b)));
913                 break;
914             case opRound:
915                 SetFloat(a, sc_round((double)slotRawInt(a), slotRawFloat(b)));
916                 break;
917             case opRoundUp:
918                 SetFloat(a, sc_roundUp((double)slotRawInt(a), slotRawFloat(b)));
919                 break;
920             case opTrunc:
921                 SetFloat(a, sc_trunc((double)slotRawInt(a), slotRawFloat(b)));
922                 break;
923             case opAtan2:
924                 SetFloat(a, atan2(slotRawInt(a), slotRawFloat(b)));
925                 break;
926             case opHypot:
927                 SetFloat(a, hypot(slotRawInt(a), slotRawFloat(b)));
928                 break;
929             case opHypotx:
930                 SetFloat(a, hypotx(slotRawInt(a), slotRawFloat(b)));
931                 break;
932             case opPow:
933                 SetFloat(a, pow((double)slotRawInt(a), slotRawFloat(b)));
934                 break;
935             case opRing1:
936                 SetFloat(a, sc_ring1((double)slotRawInt(a), slotRawFloat(b)));
937                 break;
938             case opRing2:
939                 SetFloat(a, sc_ring2((double)slotRawInt(a), slotRawFloat(b)));
940                 break;
941             case opRing3:
942                 SetFloat(a, sc_ring3((double)slotRawInt(a), slotRawFloat(b)));
943                 break;
944             case opRing4:
945                 SetFloat(a, sc_ring4((double)slotRawInt(a), slotRawFloat(b)));
946                 break;
947             case opDifSqr:
948                 SetFloat(a, sc_difsqr((double)slotRawInt(a), slotRawFloat(b)));
949                 break;
950             case opSumSqr:
951                 SetFloat(a, sc_sumsqr((double)slotRawInt(a), slotRawFloat(b)));
952                 break;
953             case opSqrSum:
954                 SetFloat(a, sc_sqrsum((double)slotRawInt(a), slotRawFloat(b)));
955                 break;
956             case opSqrDif:
957                 SetFloat(a, sc_sqrdif((double)slotRawInt(a), slotRawFloat(b)));
958                 break;
959             case opAbsDif:
960                 SetFloat(a, sc_abs(slotRawInt(a) - slotRawFloat(b)));
961                 break;
962             case opThresh:
963                 SetRaw(a, sc_thresh(slotRawInt(a), slotRawFloat(b)));
964                 break;
965             case opAMClip:
966                 SetFloat(a, sc_amclip((double)slotRawInt(a), slotRawFloat(b)));
967                 break;
968             case opScaleNeg:
969                 SetFloat(a, sc_scaleneg((double)slotRawInt(a), slotRawFloat(b)));
970                 break;
971             case opClip2:
972                 SetFloat(a, sc_clip2((double)slotRawInt(a), slotRawFloat(b)));
973                 break;
974             case opFold2:
975                 SetFloat(a, sc_fold2((double)slotRawInt(a), slotRawFloat(b)));
976                 break;
977             case opWrap2:
978                 SetFloat(a, sc_wrap2((double)slotRawInt(a), -slotRawFloat(b)));
979                 break;
980             case opExcess:
981                 SetFloat(a, sc_excess((double)slotRawInt(a), slotRawFloat(b)));
982                 break;
983             case opFirstArg:
984                 SetInt(a, slotRawInt(a));
985                 break;
986             case opRandRange:
987                 SetFloat(a, slotRawInt(a) + g->rgen->frand() * (slotRawFloat(b) - slotRawInt(a)));
988                 break;
989             case opExpRandRange:
990                 SetFloat(a, g->rgen->exprandrng(slotRawInt(a), slotRawFloat(b)));
991                 break;
992             default:
993                 goto send_normal_2;
994             }
995             break;
996         }
997     } break;
998     case tagChar: {
999         if (IsChar(b)) {
1000             switch (opcode) {
1001             case opEQ:
1002                 SetBool(a, slotRawChar(a) == slotRawChar(b));
1003                 break;
1004             case opNE:
1005                 SetBool(a, slotRawChar(a) != slotRawChar(b));
1006                 break;
1007             case opLT:
1008                 SetBool(a, slotRawChar(a) < slotRawChar(b));
1009                 break;
1010             case opGT:
1011                 SetBool(a, slotRawChar(a) > slotRawChar(b));
1012                 break;
1013             case opLE:
1014                 SetBool(a, slotRawChar(a) <= slotRawChar(b));
1015                 break;
1016             case opGE:
1017                 SetBool(a, slotRawChar(a) >= slotRawChar(b));
1018                 break;
1019             // case opIdentical : SetBool(a, slotRawChar(a) == slotRawChar(b)); break;
1020             // case opNotIdentical : SetBool(a, slotRawChar(a) != slotRawChar(b)); break;
1021             case opMin:
1022                 SetRawChar(a, sc_min(slotRawChar(a), slotRawChar(b)));
1023                 break;
1024             case opMax:
1025                 SetRawChar(a, sc_max(slotRawChar(a), slotRawChar(b)));
1026                 break;
1027             default:
1028                 goto send_normal_2;
1029             }
1030         } else {
1031             goto send_normal_2;
1032         }
1033     } break;
1034     case tagPtr:
1035     case tagNil:
1036     case tagFalse:
1037     case tagTrue:
1038         goto send_normal_2;
1039     case tagSym:
1040         if (IsSym(b)) {
1041             switch (opcode) {
1042             case opEQ:
1043                 SetBool(a, slotRawSymbol(a) == slotRawSymbol(b));
1044                 break;
1045             case opNE:
1046                 SetBool(a, slotRawSymbol(a) != slotRawSymbol(b));
1047                 break;
1048             case opLT:
1049                 SetBool(a, strcmp(slotRawSymbol(a)->name, slotRawSymbol(b)->name) < 0);
1050                 break;
1051             case opGT:
1052                 SetBool(a, strcmp(slotRawSymbol(a)->name, slotRawSymbol(b)->name) > 0);
1053                 break;
1054             case opLE:
1055                 SetBool(a, strcmp(slotRawSymbol(a)->name, slotRawSymbol(b)->name) <= 0);
1056                 break;
1057             case opGE:
1058                 SetBool(a, strcmp(slotRawSymbol(a)->name, slotRawSymbol(b)->name) >= 0);
1059                 break;
1060                 // default : leave first operand on stack
1061             }
1062         } else {
1063             if (IS_BINARY_BOOL_OP(opcode))
1064                 SetBool(a, opcode == opNE);
1065         }
1066         break;
1067     case tagObj: {
1068         if (isKindOf(slotRawObject(a), class_signal)) {
1069             switch (GetTag(b)) {
1070             case tagInt:
1071                 switch (opcode) {
1072                 case opAdd:
1073                     SetRaw(a, signal_add_xf(g, slotRawObject(a), slotRawInt(b)));
1074                     break;
1075                 case opSub:
1076                     SetRaw(a, signal_sub_xf(g, slotRawObject(a), slotRawInt(b)));
1077                     break;
1078                 case opMul:
1079                     SetRaw(a, signal_mul_xf(g, slotRawObject(a), slotRawInt(b)));
1080                     break;
1081                 case opIDiv:
1082                     SetRaw(a, signal_div_xf(g, slotRawObject(a), slotRawInt(b)));
1083                     break;
1084                 case opFDiv:
1085                     SetRaw(a, signal_div_xf(g, slotRawObject(a), slotRawInt(b)));
1086                     break;
1087                 case opEQ:
1088                     SetFalse(a);
1089                     break;
1090                 case opNE:
1091                     SetTrue(a);
1092                     break;
1093                 case opMin:
1094                     SetRaw(a, signal_min_xf(g, slotRawObject(a), slotRawInt(b)));
1095                     break;
1096                 case opMax:
1097                     SetRaw(a, signal_max_xf(g, slotRawObject(a), slotRawInt(b)));
1098                     break;
1099                 case opFill:
1100                     SetRaw(a, signal_fill(slotRawObject(a), slotRawInt(b)));
1101                     break;
1102                 case opRing1:
1103                     SetRaw(a, signal_ring1_xf(g, slotRawObject(a), slotRawInt(b)));
1104                     break;
1105                 case opRing2:
1106                     SetRaw(a, signal_ring2_xf(g, slotRawObject(a), slotRawInt(b)));
1107                     break;
1108                 case opRing3:
1109                     SetRaw(a, signal_ring3_xf(g, slotRawObject(a), slotRawInt(b)));
1110                     break;
1111                 case opRing4:
1112                     SetRaw(a, signal_ring4_xf(g, slotRawObject(a), slotRawInt(b)));
1113                     break;
1114                 case opDifSqr:
1115                     SetRaw(a, signal_difsqr_xf(g, slotRawObject(a), slotRawInt(b)));
1116                     break;
1117                 case opSumSqr:
1118                     SetRaw(a, signal_sumsqr_xf(g, slotRawObject(a), slotRawInt(b)));
1119                     break;
1120                 case opSqrSum:
1121                     SetRaw(a, signal_sqrsum_xf(g, slotRawObject(a), slotRawInt(b)));
1122                     break;
1123                 case opSqrDif:
1124                     SetRaw(a, signal_sqrdif_xf(g, slotRawObject(a), slotRawInt(b)));
1125                     break;
1126                 case opAbsDif:
1127                     SetRaw(a, signal_absdif_xf(g, slotRawObject(a), slotRawInt(b)));
1128                     break;
1129                 case opThresh:
1130                     SetRaw(a, signal_thresh_xf(g, slotRawObject(a), slotRawInt(b)));
1131                     break;
1132                 case opAMClip:
1133                     SetRaw(a, signal_amclip_xf(g, slotRawObject(a), slotRawInt(b)));
1134                     break;
1135                 case opScaleNeg:
1136                     SetRaw(a, signal_scaleneg_xf(g, slotRawObject(a), slotRawInt(b)));
1137                     break;
1138                 case opClip2:
1139                     SetRaw(a, signal_clip2_xf(g, slotRawObject(a), slotRawInt(b)));
1140                     break;
1141                 case opFold2:
1142                     SetRaw(a, signal_fold2_xf(g, slotRawObject(a), slotRawInt(b)));
1143                     break;
1144                 case opWrap2:
1145                     SetRaw(a, signal_wrap2_xf(g, slotRawObject(a), slotRawInt(b)));
1146                     break;
1147                 case opExcess:
1148                     SetRaw(a, signal_excess_xf(g, slotRawObject(a), slotRawInt(b)));
1149                     break;
1150                 case opFirstArg:
1151                     SetRaw(a, slotRawObject(a));
1152                     break;
1153                 default:
1154                     goto send_normal_2;
1155                 }
1156                 break;
1157             case tagChar:
1158             case tagPtr:
1159             case tagNil:
1160             case tagFalse:
1161             case tagTrue:
1162                 goto send_normal_2;
1163             case tagSym:
1164                 if (IS_BINARY_BOOL_OP(opcode))
1165                     SetBool(a, opcode == opNE);
1166                 else
1167                     SetSymbol(a, slotRawSymbol(b));
1168                 break;
1169             case tagObj:
1170                 if (isKindOf(slotRawObject(b), class_signal)) {
1171                     switch (opcode) {
1172                     case opAdd:
1173                         SetRaw(a, signal_add_xx(g, slotRawObject(a), slotRawObject(b)));
1174                         break;
1175                     case opSub:
1176                         SetRaw(a, signal_sub_xx(g, slotRawObject(a), slotRawObject(b)));
1177                         break;
1178                     case opMul:
1179                         SetRaw(a, signal_mul_xx(g, slotRawObject(a), slotRawObject(b)));
1180                         break;
1181                     case opIDiv:
1182                         SetRaw(a, signal_div_xx(g, slotRawObject(a), slotRawObject(b)));
1183                         break;
1184                     case opFDiv:
1185                         SetRaw(a, signal_div_xx(g, slotRawObject(a), slotRawObject(b)));
1186                         break;
1187                     case opEQ:
1188                         SetBool(a, signal_equal_xx(g, slotRawObject(a), slotRawObject(b)));
1189                         break;
1190                     case opNE:
1191                         SetBool(a, !signal_equal_xx(g, slotRawObject(a), slotRawObject(b)));
1192                         break;
1193                     case opMin:
1194                         SetRaw(a, signal_min_xx(g, slotRawObject(a), slotRawObject(b)));
1195                         break;
1196                     case opMax:
1197                         SetRaw(a, signal_max_xx(g, slotRawObject(a), slotRawObject(b)));
1198                         break;
1199                     case opRing1:
1200                         SetRaw(a, signal_ring1_xx(g, slotRawObject(a), slotRawObject(b)));
1201                         break;
1202                     case opRing2:
1203                         SetRaw(a, signal_ring2_xx(g, slotRawObject(a), slotRawObject(b)));
1204                         break;
1205                     case opRing3:
1206                         SetRaw(a, signal_ring3_xx(g, slotRawObject(a), slotRawObject(b)));
1207                         break;
1208                     case opRing4:
1209                         SetRaw(a, signal_ring4_xx(g, slotRawObject(a), slotRawObject(b)));
1210                         break;
1211                     case opDifSqr:
1212                         SetRaw(a, signal_difsqr_xx(g, slotRawObject(a), slotRawObject(b)));
1213                         break;
1214                     case opSumSqr:
1215                         SetRaw(a, signal_sumsqr_xx(g, slotRawObject(a), slotRawObject(b)));
1216                         break;
1217                     case opSqrSum:
1218                         SetRaw(a, signal_sqrsum_xx(g, slotRawObject(a), slotRawObject(b)));
1219                         break;
1220                     case opSqrDif:
1221                         SetRaw(a, signal_sqrdif_xx(g, slotRawObject(a), slotRawObject(b)));
1222                         break;
1223                     case opAbsDif:
1224                         SetRaw(a, signal_absdif_xx(g, slotRawObject(a), slotRawObject(b)));
1225                         break;
1226                     case opThresh:
1227                         SetRaw(a, signal_thresh_xx(g, slotRawObject(a), slotRawObject(b)));
1228                         break;
1229                     case opAMClip:
1230                         SetRaw(a, signal_amclip_xx(g, slotRawObject(a), slotRawObject(b)));
1231                         break;
1232                     case opScaleNeg:
1233                         SetRaw(a, signal_scaleneg_xx(g, slotRawObject(a), slotRawObject(b)));
1234                         break;
1235                     case opClip2:
1236                         SetRaw(a, signal_clip2_xx(g, slotRawObject(a), slotRawObject(b)));
1237                         break;
1238                     case opFold2:
1239                         SetRaw(a, signal_fold2_xx(g, slotRawObject(a), slotRawObject(b)));
1240                         break;
1241                     case opWrap2:
1242                         SetRaw(a, signal_wrap2_xx(g, slotRawObject(a), slotRawObject(b)));
1243                         break;
1244                     case opExcess:
1245                         SetRaw(a, signal_excess_xx(g, slotRawObject(a), slotRawObject(b)));
1246                         break;
1247                     case opFirstArg:
1248                         SetRaw(a, slotRawObject(a));
1249                         break;
1250                     default:
1251                         goto send_normal_2;
1252                     }
1253                 } else
1254                     goto send_normal_2;
1255                 break;
1256             default: // double
1257                 switch (opcode) {
1258                 case opAdd:
1259                     SetRaw(a, signal_add_xf(g, slotRawObject(a), slotRawFloat(b)));
1260                     break;
1261                 case opSub:
1262                     SetRaw(a, signal_sub_xf(g, slotRawObject(a), slotRawFloat(b)));
1263                     break;
1264                 case opMul:
1265                     SetRaw(a, signal_mul_xf(g, slotRawObject(a), slotRawFloat(b)));
1266                     break;
1267                 case opIDiv:
1268                     SetRaw(a, signal_div_xf(g, slotRawObject(a), slotRawFloat(b)));
1269                     break;
1270                 case opFDiv:
1271                     SetRaw(a, signal_div_xf(g, slotRawObject(a), slotRawFloat(b)));
1272                     break;
1273                 case opEQ:
1274                     SetFalse(a);
1275                     break;
1276                 case opNE:
1277                     SetTrue(a);
1278                     break;
1279                 case opMin:
1280                     SetRaw(a, signal_min_xf(g, slotRawObject(a), slotRawFloat(b)));
1281                     break;
1282                 case opMax:
1283                     SetRaw(a, signal_max_xf(g, slotRawObject(a), slotRawFloat(b)));
1284                     break;
1285                 case opFill:
1286                     SetRaw(a, signal_fill(slotRawObject(a), slotRawFloat(b)));
1287                     break;
1288                 case opRing1:
1289                     SetRaw(a, signal_ring1_xf(g, slotRawObject(a), slotRawFloat(b)));
1290                     break;
1291                 case opRing2:
1292                     SetRaw(a, signal_ring2_xf(g, slotRawObject(a), slotRawFloat(b)));
1293                     break;
1294                 case opRing3:
1295                     SetRaw(a, signal_ring3_xf(g, slotRawObject(a), slotRawFloat(b)));
1296                     break;
1297                 case opRing4:
1298                     SetRaw(a, signal_ring4_xf(g, slotRawObject(a), slotRawFloat(b)));
1299                     break;
1300                 case opDifSqr:
1301                     SetRaw(a, signal_difsqr_xf(g, slotRawObject(a), slotRawFloat(b)));
1302                     break;
1303                 case opSumSqr:
1304                     SetRaw(a, signal_sumsqr_xf(g, slotRawObject(a), slotRawFloat(b)));
1305                     break;
1306                 case opSqrSum:
1307                     SetRaw(a, signal_sqrsum_xf(g, slotRawObject(a), slotRawFloat(b)));
1308                     break;
1309                 case opSqrDif:
1310                     SetRaw(a, signal_sqrdif_xf(g, slotRawObject(a), slotRawFloat(b)));
1311                     break;
1312                 case opAbsDif:
1313                     SetRaw(a, signal_absdif_xf(g, slotRawObject(a), slotRawFloat(b)));
1314                     break;
1315                 case opThresh:
1316                     SetRaw(a, signal_thresh_xf(g, slotRawObject(a), slotRawFloat(b)));
1317                     break;
1318                 case opAMClip:
1319                     SetRaw(a, signal_amclip_xf(g, slotRawObject(a), slotRawFloat(b)));
1320                     break;
1321                 case opScaleNeg:
1322                     SetRaw(a, signal_scaleneg_xf(g, slotRawObject(a), slotRawFloat(b)));
1323                     break;
1324                 case opClip2:
1325                     SetRaw(a, signal_clip2_xf(g, slotRawObject(a), slotRawFloat(b)));
1326                     break;
1327                 case opFold2:
1328                     SetRaw(a, signal_fold2_xf(g, slotRawObject(a), slotRawFloat(b)));
1329                     break;
1330                 case opWrap2:
1331                     SetRaw(a, signal_wrap2_xf(g, slotRawObject(a), slotRawFloat(b)));
1332                     break;
1333                 case opExcess:
1334                     SetRaw(a, signal_excess_xf(g, slotRawObject(a), slotRawFloat(b)));
1335                     break;
1336                 case opFirstArg:
1337                     SetRaw(a, slotRawObject(a));
1338                     break;
1339                 default:
1340                     goto send_normal_2;
1341                 }
1342                 break;
1343             }
1344         } else {
1345             goto send_normal_2;
1346         }
1347     } break;
1348     default: { // double
1349         switch (GetTag(b)) {
1350         case tagInt:
1351             switch (opcode) {
1352             case opAdd:
1353                 SetRaw(a, slotRawFloat(a) + slotRawInt(b));
1354                 break;
1355             case opSub:
1356                 SetRaw(a, slotRawFloat(a) - slotRawInt(b));
1357                 break;
1358             case opMul:
1359                 SetRaw(a, slotRawFloat(a) * slotRawInt(b));
1360                 break;
1361             case opIDiv:
1362                 SetInt(a, (long)floor(slotRawFloat(a) / slotRawInt(b)));
1363                 break;
1364             case opFDiv:
1365                 SetRaw(a, slotRawFloat(a) / slotRawInt(b));
1366                 break;
1367             case opMod:
1368                 SetRaw(a, sc_mod(slotRawFloat(a), (double)slotRawInt(b)));
1369                 break;
1370             case opEQ:
1371                 SetBool(a, slotRawFloat(a) == slotRawInt(b));
1372                 break;
1373             case opNE:
1374                 SetBool(a, slotRawFloat(a) != slotRawInt(b));
1375                 break;
1376             case opLT:
1377                 SetBool(a, slotRawFloat(a) < slotRawInt(b));
1378                 break;
1379             case opGT:
1380                 SetBool(a, slotRawFloat(a) > slotRawInt(b));
1381                 break;
1382             case opLE:
1383                 SetBool(a, slotRawFloat(a) <= slotRawInt(b));
1384                 break;
1385             case opGE:
1386                 SetBool(a, slotRawFloat(a) >= slotRawInt(b));
1387                 break;
1388             // case opIdentical : SetFalse(a); break;
1389             // case opNotIdentical : SetTrue(a); break;
1390             case opMin:
1391                 SetRaw(a, sc_min(slotRawFloat(a), (double)slotRawInt(b)));
1392                 break;
1393             case opMax:
1394                 SetRaw(a, sc_max(slotRawFloat(a), (double)slotRawInt(b)));
1395                 break;
1396             case opRound:
1397                 SetRaw(a, sc_round(slotRawFloat(a), (double)slotRawInt(b)));
1398                 break;
1399             case opRoundUp:
1400                 SetRaw(a, sc_roundUp(slotRawFloat(a), (double)slotRawInt(b)));
1401                 break;
1402             case opTrunc:
1403                 SetRaw(a, sc_trunc(slotRawFloat(a), (double)slotRawInt(b)));
1404                 break;
1405             case opAtan2:
1406                 SetRaw(a, atan2(slotRawFloat(a), slotRawInt(b)));
1407                 break;
1408             case opHypot:
1409                 SetRaw(a, hypot(slotRawFloat(a), slotRawInt(b)));
1410                 break;
1411             case opHypotx:
1412                 SetRaw(a, hypotx(slotRawFloat(a), slotRawInt(b)));
1413                 break;
1414             case opPow:
1415                 SetRaw(a, pow(slotRawFloat(a), (double)slotRawInt(b)));
1416                 break;
1417             case opRing1:
1418                 SetRaw(a, sc_ring1(slotRawFloat(a), (double)slotRawInt(b)));
1419                 break;
1420             case opRing2:
1421                 SetRaw(a, sc_ring2(slotRawFloat(a), (double)slotRawInt(b)));
1422                 break;
1423             case opRing3:
1424                 SetRaw(a, sc_ring3(slotRawFloat(a), (double)slotRawInt(b)));
1425                 break;
1426             case opRing4:
1427                 SetRaw(a, sc_ring4(slotRawFloat(a), (double)slotRawInt(b)));
1428                 break;
1429             case opDifSqr:
1430                 SetRaw(a, sc_difsqr(slotRawFloat(a), (double)slotRawInt(b)));
1431                 break;
1432             case opSumSqr:
1433                 SetRaw(a, sc_sumsqr(slotRawFloat(a), (double)slotRawInt(b)));
1434                 break;
1435             case opSqrSum:
1436                 SetRaw(a, sc_sqrsum(slotRawFloat(a), (double)slotRawInt(b)));
1437                 break;
1438             case opSqrDif:
1439                 SetRaw(a, sc_sqrdif(slotRawFloat(a), (double)slotRawInt(b)));
1440                 break;
1441             case opAbsDif:
1442                 SetRaw(a, sc_abs(slotRawFloat(a) - slotRawInt(b)));
1443                 break;
1444             case opThresh:
1445                 SetRaw(a, sc_thresh(slotRawFloat(a), slotRawInt(b)));
1446                 break;
1447             case opAMClip:
1448                 SetRaw(a, sc_amclip(slotRawFloat(a), (double)slotRawInt(b)));
1449                 break;
1450             case opScaleNeg:
1451                 SetRaw(a, sc_scaleneg(slotRawFloat(a), (double)slotRawInt(b)));
1452                 break;
1453             case opClip2:
1454                 SetRaw(a, sc_clip2(slotRawFloat(a), (double)slotRawInt(b)));
1455                 break;
1456             case opFold2:
1457                 SetRaw(a, sc_fold2(slotRawFloat(a), (double)slotRawInt(b)));
1458                 break;
1459             case opWrap2:
1460                 SetRaw(a, sc_wrap2(slotRawFloat(a), (double)slotRawInt(b)));
1461                 break;
1462             case opExcess:
1463                 SetRaw(a, sc_excess(slotRawFloat(a), (double)slotRawInt(b)));
1464                 break;
1465             case opFirstArg:
1466                 SetRaw(a, slotRawFloat(a));
1467                 break;
1468             case opRandRange:
1469                 SetRaw(a, slotRawFloat(a) + g->rgen->frand() * (slotRawInt(b) - slotRawFloat(a)));
1470                 break;
1471             case opExpRandRange:
1472                 SetRaw(a, g->rgen->exprandrng(slotRawFloat(a), slotRawInt(b)));
1473                 break;
1474             default:
1475                 goto send_normal_2;
1476             }
1477             break;
1478         case tagChar:
1479         case tagPtr:
1480         case tagNil:
1481         case tagFalse:
1482         case tagTrue:
1483             goto send_normal_2;
1484         case tagSym:
1485             if (IS_BINARY_BOOL_OP(opcode))
1486                 SetBool(a, opcode == opNE);
1487             else
1488                 SetSymbol(a, slotRawSymbol(b));
1489             break;
1490         case tagObj:
1491             if (isKindOf(slotRawObject(b), class_signal)) {
1492                 switch (opcode) {
1493                 case opAdd:
1494                     SetObject(a, signal_add_xf(g, slotRawObject(b), slotRawFloat(a)));
1495                     break;
1496                 case opSub:
1497                     SetObject(a, signal_sub_fx(g, slotRawFloat(a), slotRawObject(b)));
1498                     break;
1499                 case opMul:
1500                     SetObject(a, signal_mul_xf(g, slotRawObject(b), slotRawFloat(a)));
1501                     break;
1502                 case opIDiv:
1503                     SetObject(a, signal_div_fx(g, slotRawFloat(a), slotRawObject(b)));
1504                     break;
1505                 case opFDiv:
1506                     SetObject(a, signal_div_fx(g, slotRawFloat(a), slotRawObject(b)));
1507                     break;
1508                 case opEQ:
1509                     SetFalse(a);
1510                     break;
1511                 case opNE:
1512                     SetTrue(a);
1513                     break;
1514                 case opMin:
1515                     SetObject(a, signal_min_xf(g, slotRawObject(b), slotRawFloat(a)));
1516                     break;
1517                 case opMax:
1518                     SetObject(a, signal_max_xf(g, slotRawObject(b), slotRawFloat(a)));
1519                     break;
1520                 case opRing1:
1521                     SetObject(a, signal_ring1_fx(g, slotRawFloat(a), slotRawObject(b)));
1522                     break;
1523                 case opRing2:
1524                     SetObject(a, signal_ring2_fx(g, slotRawFloat(a), slotRawObject(b)));
1525                     break;
1526                 case opRing3:
1527                     SetObject(a, signal_ring3_fx(g, slotRawFloat(a), slotRawObject(b)));
1528                     break;
1529                 case opRing4:
1530                     SetObject(a, signal_ring4_fx(g, slotRawFloat(a), slotRawObject(b)));
1531                     break;
1532                 case opDifSqr:
1533                     SetObject(a, signal_difsqr_fx(g, slotRawFloat(a), slotRawObject(b)));
1534                     break;
1535                 case opSumSqr:
1536                     SetObject(a, signal_sumsqr_fx(g, slotRawFloat(a), slotRawObject(b)));
1537                     break;
1538                 case opSqrSum:
1539                     SetObject(a, signal_sqrsum_fx(g, slotRawFloat(a), slotRawObject(b)));
1540                     break;
1541                 case opSqrDif:
1542                     SetObject(a, signal_sqrdif_fx(g, slotRawFloat(a), slotRawObject(b)));
1543                     break;
1544                 case opAbsDif:
1545                     SetObject(a, signal_absdif_fx(g, slotRawFloat(a), slotRawObject(b)));
1546                     break;
1547                 case opThresh:
1548                     SetObject(a, signal_thresh_fx(g, slotRawFloat(a), slotRawObject(b)));
1549                     break;
1550                 case opAMClip:
1551                     SetObject(a, signal_amclip_fx(g, slotRawFloat(a), slotRawObject(b)));
1552                     break;
1553                 case opScaleNeg:
1554                     SetObject(a, signal_scaleneg_fx(g, slotRawFloat(a), slotRawObject(b)));
1555                     break;
1556                 case opClip2:
1557                     SetObject(a, signal_clip2_fx(g, slotRawFloat(a), slotRawObject(b)));
1558                     break;
1559                 case opFold2:
1560                     SetObject(a, signal_fold2_fx(g, slotRawFloat(a), slotRawObject(b)));
1561                     break;
1562                 case opWrap2:
1563                     SetObject(a, signal_wrap2_fx(g, slotRawFloat(a), slotRawObject(b)));
1564                     break;
1565                 case opExcess:
1566                     SetObject(a, signal_excess_fx(g, slotRawFloat(a), slotRawObject(b)));
1567                     break;
1568                 case opFirstArg:
1569                     SetObject(a, slotRawObject(a));
1570                     break;
1571                 default:
1572                     goto send_normal_2;
1573                 }
1574             } else
1575                 goto send_normal_2;
1576             break;
1577         default: // double
1578             switch (opcode) {
1579             case opAdd:
1580                 SetRaw(a, slotRawFloat(a) + slotRawFloat(b));
1581                 break;
1582             case opSub:
1583                 SetRaw(a, slotRawFloat(a) - slotRawFloat(b));
1584                 break;
1585             case opMul:
1586                 SetRaw(a, slotRawFloat(a) * slotRawFloat(b));
1587                 break;
1588             case opIDiv:
1589                 SetInt(a, (long)floor(slotRawFloat(a) / slotRawFloat(b)));
1590                 break;
1591             case opFDiv:
1592                 SetRaw(a, slotRawFloat(a) / slotRawFloat(b));
1593                 break;
1594             case opMod:
1595                 SetRaw(a, sc_mod(slotRawFloat(a), slotRawFloat(b)));
1596                 break;
1597             case opEQ:
1598                 SetBool(a, slotRawFloat(a) == slotRawFloat(b));
1599                 break;
1600             case opNE:
1601                 SetBool(a, slotRawFloat(a) != slotRawFloat(b));
1602                 break;
1603             case opLT:
1604                 SetBool(a, slotRawFloat(a) < slotRawFloat(b));
1605                 break;
1606             case opGT:
1607                 SetBool(a, slotRawFloat(a) > slotRawFloat(b));
1608                 break;
1609             case opLE:
1610                 SetBool(a, slotRawFloat(a) <= slotRawFloat(b));
1611                 break;
1612             case opGE:
1613                 SetBool(a, slotRawFloat(a) >= slotRawFloat(b));
1614                 break;
1615             // case opIdentical  : SetBool(a, slotRawFloat(a) == slotRawFloat(b)); break;
1616             // case opNotIdentical  : SetBool(a, slotRawFloat(a) != slotRawFloat(b)); break;
1617             case opMin:
1618                 SetRaw(a, sc_min(slotRawFloat(a), slotRawFloat(b)));
1619                 break;
1620             case opMax:
1621                 SetRaw(a, sc_max(slotRawFloat(a), slotRawFloat(b)));
1622                 break;
1623             case opRound:
1624                 SetRaw(a, sc_round(slotRawFloat(a), slotRawFloat(b)));
1625                 break;
1626             case opRoundUp:
1627                 SetRaw(a, sc_roundUp(slotRawFloat(a), slotRawFloat(b)));
1628                 break;
1629             case opTrunc:
1630                 SetRaw(a, sc_trunc(slotRawFloat(a), slotRawFloat(b)));
1631                 break;
1632             case opAtan2:
1633                 SetRaw(a, atan2(slotRawFloat(a), slotRawFloat(b)));
1634                 break;
1635             case opHypot:
1636                 SetRaw(a, hypot(slotRawFloat(a), slotRawFloat(b)));
1637                 break;
1638             case opHypotx:
1639                 SetRaw(a, hypotx(slotRawFloat(a), slotRawFloat(b)));
1640                 break;
1641             case opPow:
1642                 SetRaw(a, pow(slotRawFloat(a), slotRawFloat(b)));
1643                 break;
1644             case opRing1:
1645                 SetRaw(a, sc_ring1(slotRawFloat(a), slotRawFloat(b)));
1646                 break;
1647             case opRing2:
1648                 SetRaw(a, sc_ring2(slotRawFloat(a), slotRawFloat(b)));
1649                 break;
1650             case opRing3:
1651                 SetRaw(a, sc_ring3(slotRawFloat(a), slotRawFloat(b)));
1652                 break;
1653             case opRing4:
1654                 SetRaw(a, sc_ring4(slotRawFloat(a), slotRawFloat(b)));
1655                 break;
1656             case opDifSqr:
1657                 SetRaw(a, sc_difsqr(slotRawFloat(a), slotRawFloat(b)));
1658                 break;
1659             case opSumSqr:
1660                 SetRaw(a, sc_sumsqr(slotRawFloat(a), slotRawFloat(b)));
1661                 break;
1662             case opSqrSum:
1663                 SetRaw(a, sc_sqrsum(slotRawFloat(a), slotRawFloat(b)));
1664                 break;
1665             case opSqrDif:
1666                 SetRaw(a, sc_sqrdif(slotRawFloat(a), slotRawFloat(b)));
1667                 break;
1668             case opAbsDif:
1669                 SetRaw(a, sc_abs(slotRawFloat(a) - slotRawFloat(b)));
1670                 break;
1671             case opThresh:
1672                 SetRaw(a, sc_thresh(slotRawFloat(a), slotRawFloat(b)));
1673                 break;
1674             case opAMClip:
1675                 SetRaw(a, sc_amclip(slotRawFloat(a), slotRawFloat(b)));
1676                 break;
1677             case opScaleNeg:
1678                 SetRaw(a, sc_scaleneg(slotRawFloat(a), slotRawFloat(b)));
1679                 break;
1680             case opClip2:
1681                 SetRaw(a, sc_clip2(slotRawFloat(a), slotRawFloat(b)));
1682                 break;
1683             case opFold2:
1684                 SetRaw(a, sc_fold2(slotRawFloat(a), slotRawFloat(b)));
1685                 break;
1686             case opWrap2:
1687                 SetRaw(a, sc_wrap2(slotRawFloat(a), slotRawFloat(b)));
1688                 break;
1689             case opExcess:
1690                 SetRaw(a, sc_excess(slotRawFloat(a), slotRawFloat(b)));
1691                 break;
1692             case opFirstArg:
1693                 SetRaw(a, slotRawFloat(a));
1694                 break;
1695             case opRandRange:
1696                 SetRaw(a, slotRawFloat(a) + g->rgen->frand() * (slotRawFloat(b) - slotRawFloat(a)));
1697                 break;
1698             case opExpRandRange:
1699                 SetRaw(a, g->rgen->exprandrng(slotRawFloat(a), slotRawFloat(b)));
1700                 break;
1701             default:
1702                 goto send_normal_2;
1703             }
1704             break;
1705         }
1706     } break;
1707     }
1708     g->sp = a; // drop
1709     g->numpop = 0;
1710 #if TAILCALLOPTIMIZE
1711     g->tailCall = 0;
1712 #endif
1713     return errNone;
1714 
1715 send_normal_2:
1716     if (isPrimitive) // special case flag meaning it is a primitive
1717         return errFailed; // arguments remain on the stack
1718 
1719     msg = gSpecialBinarySelectors[opcode];
1720     sendMessage(g, msg, numArgsPushed);
1721     return errNone;
1722 }
1723