1 typedef enum
2 {
3 LODI,
4 STO,
5 ADDI,
6 ADD,
7 SUBI,
8 SUB,
9 MULI,
10 MUL,
11 DIVI,
12 DIV,
13 INC,
14 DEC
15 } INSN;
16
f(pc)17 f (pc)
18 short *pc;
19 {
20 long long stack[16], *sp = &stack[16], acc = 0;
21
22 for (;;)
23 {
24 switch ((INSN)*pc++)
25 {
26 case LODI:
27 *--sp = acc;
28 acc = ((long long)*pc++) << 32;
29 break;
30 case STO:
31 return (acc >> 32) + (((((unsigned long long) acc) & 0xffffffff) & (1 << 31)) != 0);
32 break;
33 case ADDI:
34 acc += ((long long)*pc++) << 32;
35 break;
36 case ADD:
37 acc = *sp++ + acc;
38 break;
39 case SUBI:
40 acc -= ((long long)*pc++) << 32;
41 break;
42 case SUB:
43 acc = *sp++ - acc;
44 break;
45 case MULI:
46 acc *= *pc++;
47 break;
48 case MUL:
49 {
50 long long aux;
51 unsigned char minus;
52
53 minus = 0;
54 aux = *sp++;
55 if (aux < 0)
56 {
57 minus = ~minus;
58 aux = -aux;
59 }
60 if (acc < 0)
61 {
62 minus = ~minus;
63 acc = -acc;
64 }
65 acc = ((((((unsigned long long) acc) & 0xffffffff) * (((unsigned long long) aux) & 0xffffffff)) >> 32)
66 + ((((unsigned long long) acc) >> 32) * (((unsigned long long) aux) & 0xffffffff) + (((unsigned long long) acc) & 0xffffffff) + (((unsigned long long) aux) >> 32))
67 + (((((unsigned long long) acc) >> 32) * (((unsigned long long) aux) >> 32)) << 32));
68 if (minus)
69 acc = -acc;
70 }
71 break;
72 case DIVI:
73 {
74 short aux;
75
76 aux = *pc++;
77 acc = (acc + aux / 2) / aux;
78 }
79 break;
80 case DIV:
81 {
82 long long aux;
83 unsigned char minus;
84
85 minus = 0;
86 aux = *sp++;
87 if (aux < 0)
88 {
89 minus = ~minus;
90 aux = -aux;
91 }
92 if (acc < 0)
93 {
94 minus = ~minus;
95 acc = -acc;
96 }
97
98 if (((unsigned long long)acc) == 0)
99 acc = (unsigned long long)-1 / 2;
100 else if ((((unsigned long long) ((unsigned long long)acc)) & 0xffffffff) == 0)
101 acc = ((unsigned long long)aux) / (((unsigned long long) ((unsigned long long)acc)) >> 32);
102 else if ((((unsigned long long) ((unsigned long long)acc)) >> 32) == 0)
103 acc = ((((unsigned long long)aux) / ((unsigned long long)acc)) << 32)
104 + ((((unsigned long long)aux) % ((unsigned long long)acc)) << 32) / ((unsigned long long)acc);
105 else
106 {
107 unsigned char shift;
108 unsigned long hi;
109
110 shift = 32;
111 hi = (((unsigned long long) ((unsigned long long)acc)) >> 32);
112 do {
113 if (hi & ((unsigned long)1 << (shift - 1)))
114 break;
115 } while (--shift != 0);
116 printf("shift = %d\n", shift);
117 acc = ((((unsigned long long)aux) / ((unsigned long long)acc)) << 32)
118 + (((((unsigned long long)aux) % ((unsigned long long)acc)) << (32 - shift)) + ((((unsigned long long)acc) >> shift) / 2)) / (((unsigned long long)acc) >> shift);
119 }
120
121 if (minus)
122 acc = -acc;
123 }
124 break;
125 case INC:
126 acc += 1;
127 break;
128 case DEC:
129 acc -= 1;
130 break;
131 }
132 printf("%08lx.%08lx\n", (long)(((unsigned long long) acc) >> 32) , (long)(((unsigned long long) acc) & 0xffffffff));
133 }
134 }
135