Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / slof / prim.code
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12
13
14 //
15 // Copyright 2002,2003,2004  Segher Boessenkool  <segher@kernel.crashing.org>
16 //
17
18
19 #define NEXT00  goto *cfa->a
20 #define NEXT0   cfa = ip->a; NEXT00
21 #define NEXT    ip++; NEXT0
22
23 #define PRIM(name) code_##name: { \
24                    asm volatile ("#### " #name : : : "memory"); \
25                    void *w = (cfa = (++ip)->a)->a;
26 #define MIRP       goto *w; }
27
28
29
30         // start interpreting
31         NEXT0;
32
33
34
35 // These macros could be replaced to allow for TOS caching etc.
36 #define TOS (*dp)
37 #define NOS (*(dp-1))
38 #define POP dp--
39 #define PUSH dp++
40
41 #define RTOS (*rp)
42 #define RNOS (*(rp-1))
43 #define RPOP rp--
44 #define RPUSH rp++
45
46
47
48
49 // For terminal input.
50 PRIM(TIB) PUSH; TOS.a = the_tib; MIRP
51
52 // For pockets (temporary string buffers).
53 PRIM(POCKETS) PUSH; TOS.a = the_pockets; MIRP
54
55 // exception register area
56 PRIM(EREGS) PUSH; TOS.a = the_exception_frame; MIRP
57
58 // client register area
59 PRIM(CIREGS) PUSH; TOS.a = the_client_frame; MIRP
60
61 // Client stack
62 //      (According to the PowerPC ABI the stack-pointer points to the
63 //       lowest **USED** value.
64 //       I.e. it is decremented before a new element is stored on the
65 //       stack.)
66 PRIM(CISTACK) PUSH; TOS.a = the_client_stack
67                             + (sizeof(the_client_stack) / CELLSIZE); MIRP
68
69 // compile-in-interpret buffer
70 PRIM(COMP_X2d_BUFFER) PUSH; TOS.a = the_comp_buffer; MIRP
71
72 // Paflof base address
73 PRIM(PAFLOF_X2d_START) PUSH; TOS.a = _start_OF; MIRP
74
75 // Heap pointers
76 PRIM(HEAP_X2d_START) PUSH; TOS.a = the_heap_start; MIRP
77 PRIM(HEAP_X2d_END) PUSH; TOS.a = the_heap_end; MIRP
78
79 // FDT pointer
80 PRIM(FDT_X2d_START) PUSH; TOS.u = fdt_start; MIRP
81
82 // romfs-base
83 PRIM(ROMFS_X2d_BASE) PUSH; TOS.u = romfs_base; MIRP
84
85 // if the low level firmware is epapr compliant it will put the
86 // epapr magic into r6 before starting paflof
87 // epapr-magic is a copy of r6
88 PRIM(EPAPR_X2d_MAGIC) PUSH; TOS.u = epapr_magic; MIRP
89
90 // Initially mapped area size (for ePAPR compliant LLFW)
91 PRIM(EPAPR_X2d_IMA_X2d_SIZE) PUSH; TOS.u = epapr_ima_size; MIRP
92
93 // Codefields.
94 code_DOCOL:
95         {
96                 RPUSH; RTOS.a = ip;
97                 ip = cfa;
98                 NEXT;
99         }
100 code_DODOES:
101         {
102                 RPUSH; RTOS.a = ip;
103                 ip = (cfa + 1)->a;
104                 PUSH; TOS.a = cfa + 2;
105                 NEXT0;
106         }
107 code_DODEFER:
108         {
109                 cfa = (cfa + 1)->a;
110                 NEXT00;
111         }
112 code_DOALIAS:
113         {
114                 cfa = (cfa + 1)->a;
115                 NEXT00;
116         }
117 code_DOCON:
118         {
119                 PUSH;
120                 TOS = *(cfa + 1);
121                 NEXT;
122         }
123 code_DOVAL:
124         {
125                 PUSH;
126                 TOS = *(cfa + 1);
127                 NEXT;
128         }
129 code_DOFIELD:
130         {
131                 dp->n += (cfa + 1)->n;
132                 NEXT;
133         }
134 code_DOVAR:
135         {
136                 (++dp)->a = cfa + 1;
137                 NEXT;
138         }
139 code_DOBUFFER_X3a:
140         {
141                 (++dp)->a = cfa + 1;
142                 NEXT;
143         }
144
145
146
147
148
149 // branching
150 code_BRANCH:
151         {
152                 type_n dis = (++ip)->n;
153                 ip = (cell *)((type_u)ip + dis);
154                 NEXT;
155         }
156 code_0BRANCH:
157         {
158                 type_n dis = (++ip)->n;
159                 if (TOS.u == 0)
160                         ip = (cell *)((type_u)ip + dis);
161                 POP;
162                 NEXT;
163         }
164
165 // Jump to "defer BP"
166 code_BREAKPOINT:
167         {
168                 RPUSH; RTOS.a = ip;
169                 ip = (cell * ) xt_BP+2;
170                 NEXT;
171         }
172
173
174 // literals
175 code_LIT:
176         {
177                 PUSH;
178                 TOS = *++ip;
179                 NEXT;
180         }
181 code_DOTICK:
182         {
183                 PUSH;
184                 TOS = *++ip;
185                 NEXT;
186         }
187
188
189
190 // 1.1
191 PRIM(DUP) cell x = TOS; PUSH; TOS = x; MIRP
192 PRIM(OVER) cell x = NOS; PUSH; TOS = x; MIRP
193 PRIM(PICK) TOS = *(dp - TOS.n - 1); MIRP
194
195 // 1.2
196 PRIM(DROP) POP; MIRP
197
198 // 1.3
199 PRIM(SWAP) cell x = NOS; NOS = TOS; TOS = x; MIRP
200
201 // 1.4
202 PRIM(_X3e_R) RPUSH; RTOS = TOS; POP; MIRP
203 PRIM(R_X3e) PUSH; TOS = RTOS; RPOP; MIRP
204 PRIM(R_X40) PUSH; TOS = RTOS; MIRP
205
206 // 1.5
207 PRIM(DEPTH) PUSH; TOS.u = dp - the_data_stack; MIRP
208 PRIM(DEPTH_X21) dp = the_data_stack + TOS.u - 1; MIRP
209 PRIM(RDEPTH) PUSH; TOS.u = rp - the_return_stack + 1; MIRP
210 PRIM(RDEPTH_X21) rp = the_return_stack + TOS.u - 1; POP; MIRP
211 PRIM(RPICK) TOS = *(rp - TOS.n); MIRP
212
213 // 2.1
214 PRIM(_X2b) NOS.u += TOS.u; POP; MIRP
215 PRIM(_X2d) NOS.u -= TOS.u; POP; MIRP
216 PRIM(_X2a) NOS.u *= TOS.u; POP; MIRP
217
218 // 2.2
219 PRIM(LSHIFT) NOS.u <<= TOS.u; POP; MIRP
220 PRIM(RSHIFT) NOS.u >>= TOS.u; POP; MIRP
221 PRIM(ASHIFT) NOS.n >>= TOS.u; POP; MIRP
222 PRIM(AND) NOS.u &= TOS.u; POP; MIRP
223 PRIM(OR) NOS.u |= TOS.u; POP; MIRP
224 PRIM(XOR) NOS.u ^= TOS.u; POP; MIRP
225
226 // 3.1
227 #define GET_TYPE1(t) { \
228                 t *restrict a = (t *restrict)(TOS.a); \
229                 t b;
230
231 #define GET_TYPE2(t) \
232                 b = *a;
233
234 #define GET_TYPE3(t) \
235                 TOS.u = b; \
236 }
237
238 #define PUT_TYPE1(t) { \
239                 t *restrict a = TOS.a; \
240                 t b = NOS.u; \
241                 POP; \
242                 POP;
243
244 #define PUT_TYPE2(t) \
245                 *a = b; \
246 }
247
248 #define GET_CELL1 GET_TYPE1(type_u)
249 #define PUT_CELL1 PUT_TYPE1(type_u)
250 #define GET_CHAR1 GET_TYPE1(type_c)
251 #define PUT_CHAR1 PUT_TYPE1(type_c)
252 #define GET_WORD1 GET_TYPE1(type_w)
253 #define PUT_WORD1 PUT_TYPE1(type_w)
254 #define GET_LONG1 GET_TYPE1(type_l)
255 #define PUT_LONG1 PUT_TYPE1(type_l)
256 #define GET_XONG1 GET_TYPE1(type_u)
257 #define PUT_XONG1 PUT_TYPE1(type_u)
258
259 #define GET_CELL2 GET_TYPE2(type_u)
260 #define PUT_CELL2 PUT_TYPE2(type_u)
261 #define GET_CHAR2 GET_TYPE2(type_c)
262 #define PUT_CHAR2 PUT_TYPE2(type_c)
263 #define GET_WORD2 GET_TYPE2(type_w)
264 #define PUT_WORD2 PUT_TYPE2(type_w)
265 #define GET_LONG2 GET_TYPE2(type_l)
266 #define PUT_LONG2 PUT_TYPE2(type_l)
267 #define GET_XONG2 GET_TYPE2(type_u)
268 #define PUT_XONG2 PUT_TYPE2(type_u)
269
270 #define GET_CELL3 GET_TYPE3(type_u)
271 #define GET_CHAR3 GET_TYPE3(type_c)
272 #define GET_WORD3 GET_TYPE3(type_w)
273 #define GET_LONG3 GET_TYPE3(type_l)
274 #define GET_XONG3 GET_TYPE3(type_u)
275
276 #define GET_CELL GET_CELL1 GET_CELL2 GET_CELL3
277 #define PUT_CELL PUT_CELL1 PUT_CELL2
278 #define GET_CHAR GET_CHAR1 GET_CHAR2 GET_CHAR3
279 #define PUT_CHAR PUT_CHAR1 PUT_CHAR2
280 #define GET_WORD GET_WORD1 GET_WORD2 GET_WORD3
281 #define PUT_WORD PUT_WORD1 PUT_WORD2
282 #define GET_LONG GET_LONG1 GET_LONG2 GET_LONG3
283 #define PUT_LONG PUT_LONG1 PUT_LONG2
284 #define GET_XONG GET_XONG1 GET_XONG2 GET_XONG3
285 #define PUT_XONG PUT_XONG1 PUT_XONG2
286
287         PRIM(_X40)  GET_CELL; MIRP
288         PRIM(_X21)  PUT_CELL; MIRP
289         PRIM(C_X40) GET_CHAR; MIRP
290         PRIM(C_X21) PUT_CHAR; MIRP
291         PRIM(W_X40) GET_WORD; MIRP
292         PRIM(W_X21) PUT_WORD; MIRP
293         PRIM(L_X40) GET_LONG; MIRP
294         PRIM(L_X21) PUT_LONG; MIRP
295         PRIM(X_X40) GET_XONG; MIRP
296         PRIM(X_X21) PUT_XONG; MIRP
297
298
299 #define UGET_TYPE1(t) { \
300                 type_c *restrict a = (type_c *restrict)(TOS.a); \
301                 t b; \
302                 type_c *restrict c = (type_c *restrict)&b;
303
304 #define UGET_TYPE2(t) \
305                 *c++ = *a++; \
306                 *c++ = *a++;
307
308 #define UGET_TYPE3(t) \
309                 TOS.u = b; \
310 }
311
312 #define UPUT_TYPE1(t) { \
313                 type_c *restrict a = (type_c *restrict)(TOS.a); \
314                 t b = NOS.u; \
315                 type_c *restrict c = (type_c *restrict)&b; \
316                 POP; \
317                 POP;
318
319 #define UPUT_TYPE2(t) \
320                 *a++ = *c++; \
321                 *a++ = *c++;
322
323 #define UPUT_TYPE3(t) }
324
325 #define UGET_WORD1 UGET_TYPE1(type_w)
326 #define UPUT_WORD1 UPUT_TYPE1(type_w)
327 #define UGET_WORD2 UGET_TYPE2(type_w)
328 #define UPUT_WORD2 UPUT_TYPE2(type_w)
329 #define UGET_WORD3 UGET_TYPE3(type_w)
330 #define UPUT_WORD3 UPUT_TYPE3(type_w)
331 #define UGET_LONG1 UGET_TYPE1(type_l)
332 #define UPUT_LONG1 UPUT_TYPE1(type_l)
333 #define UGET_LONG2 UGET_TYPE2(type_l)
334 #define UPUT_LONG2 UPUT_TYPE2(type_l)
335 #define UGET_LONG3 UGET_TYPE3(type_l)
336 #define UPUT_LONG3 UPUT_TYPE3(type_l)
337
338 #define UGET_WORD UGET_WORD1 UGET_WORD2 UGET_WORD3
339 #define UPUT_WORD UPUT_WORD1 UPUT_WORD2 UPUT_WORD3
340 #define UGET_LONG UGET_LONG1 UGET_LONG2 UGET_LONG2 UGET_LONG3
341 #define UPUT_LONG UPUT_LONG1 UPUT_LONG2 UPUT_LONG2 UPUT_LONG3
342
343         PRIM(UNALIGNED_X2d_W_X40) UGET_WORD; MIRP
344         PRIM(UNALIGNED_X2d_W_X21) UPUT_WORD; MIRP
345         PRIM(UNALIGNED_X2d_L_X40) UGET_LONG; MIRP
346         PRIM(UNALIGNED_X2d_L_X21) UPUT_LONG; MIRP
347
348
349 // 6
350 PRIM(_X3c) NOS.n = -(NOS.n < TOS.n); POP; MIRP
351 PRIM(U_X3c) NOS.n = -(NOS.u < TOS.u); POP; MIRP
352 PRIM(0_X3c) TOS.n = -(TOS.n < 0); MIRP
353 PRIM(_X3d) NOS.n = -(NOS.u == TOS.u); POP; MIRP
354 PRIM(0_X3d) TOS.n = -(TOS.u == 0); MIRP
355
356
357
358
359
360
361 // 8.4
362 PRIM(DODO) RPUSH; RTOS = NOS; RPUSH; RTOS = TOS; POP; POP; MIRP
363 code_DO_X3f_DO:
364         {
365                 cell i = *dp--;
366                 cell n = *dp--;
367                 type_n dis = (++ip)->n;
368                 if (i.n == n.n)
369                         ip = (cell *restrict)((type_c *restrict)ip + dis);
370                 else {
371                         *(rp + 1) = n;
372                         *(rp += 2) = i;
373                 }
374                 NEXT;
375         }
376 code_DOLOOP:
377         {
378                 type_n dis = (++ip)->n;
379                 rp->n++;
380                 if (rp->n == (rp - 1)->n)
381                         rp -= 2;
382                 else
383                         ip = (cell *restrict)((type_c *restrict)ip + dis);
384                 NEXT;
385         }
386 code_DO_X2b_LOOP:
387         {
388                 type_u lo, hi;
389                 type_n inc;
390                 type_n dis = (++ip)->n;
391                 lo = rp->u;
392                 inc = (dp--)->n;
393                 rp->n += inc;
394                 if (inc >= 0)
395                         hi = rp->u;
396                 else {
397                         hi = lo;
398                         lo = rp->u;
399                 }
400                 if ((type_u)((rp - 1)->n - 1 - lo) < hi - lo)
401                         rp -= 2;
402                 else
403                         ip = (cell *restrict)((type_c *restrict)ip + dis);
404                 NEXT;
405         }
406 code_DOLEAVE:
407         {
408                 type_n dis = (++ip)->n;
409                 rp -= 2;
410                 ip = (cell *restrict)((type_c *restrict)ip + dis);
411                 NEXT;
412         }
413 code_DO_X3f_LEAVE:
414         {
415                 type_n dis = (++ip)->n;
416                 if ((dp--)->n) {
417                         rp -= 2;
418                         ip = (cell *restrict)((type_c *restrict)ip + dis);
419                 }
420                 NEXT;
421         }
422
423
424
425
426
427
428 // 8.5
429 code_EXIT:
430         {
431                 ip = (rp--)->a;
432                 NEXT;
433         }
434
435 code_SEMICOLON:
436         {
437                 ip = (rp--)->a;
438                 NEXT;
439         }
440
441 code_EXECUTE:   // don't need this as prim
442         {
443                 cfa = (dp--)->a;
444                 NEXT00;
445         }
446
447
448 PRIM(MOVE)
449         type_u n = TOS.u; POP;
450         unsigned char *q = TOS.a; POP;
451         unsigned char *p = TOS.a; POP;
452
453         _FASTMOVE(p, q, n);
454 MIRP
455
456 code_FILL:
457         {
458                 unsigned char c = (dp--)->u;
459                 type_n size = ((dp--)->n);
460                 unsigned char *d = (unsigned char *)((dp--)->u);
461                 type_u fill_v=c | c <<8;
462
463                 fill_v |= fill_v << 16;
464                 switch (((type_u)d | (type_u)size) & (sizeof(type_u)-1)) {
465                         case 0: {
466                                 type_u *up = (type_u *)d;
467 #if (__LONG_MAX__ > 2147483647L)
468                                 fill_v |= fill_v << 32;
469 #endif
470                                 while ((size-=sizeof(type_u)) >= 0)
471                                         *up++ = fill_v;
472                         }
473                         case sizeof(type_l): {
474                                 type_l *lp = (type_l *)d;
475
476                                 while ((size-=sizeof(type_l)) >= 0)
477                                         *lp++ = (type_l)fill_v;
478                         }
479                         case sizeof(type_w): {
480                                 type_w *wp = (type_w *)d;
481
482                                 while ((size-=sizeof(type_w)) >= 0)
483                                         *wp++ = (type_w)fill_v;
484                         }
485                         default:
486                                 while (size-- > 0)
487                                         *d++ = (unsigned char)c;
488                 }
489                 NEXT;
490         }
491
492 code_COMP:
493         {
494                 type_n len = ((dp--)->n);
495                 unsigned char *addr2 = (unsigned char *)((dp--)->u);
496                 unsigned char *addr1 = (unsigned char *)((dp--)->u);
497
498                 while (len-- > 0) {
499                         if (*addr1 > *addr2) {
500                                 (++dp)->n = 1;
501                                 NEXT;
502                         }
503                         else if (*addr1 < *addr2) {
504                                 (++dp)->n = -1;
505                                 NEXT;
506                         }
507                         addr1 += 1;
508                         addr2 += 1;
509                 }
510                 (++dp)->n = 0;
511                 NEXT;
512         }
513
514
515 PRIM(RMOVE)
516         type_u size = ((dp--)->u);
517         type_u *d = (type_u *)((dp--)->u);
518         type_u *s = (type_u *)((dp--)->u);
519         _FASTRMOVE(s, d, size);
520
521         MIRP
522
523
524 // String compare, case insensitive:
525 // : string=ci  ( str1 len1 str2 len2 -- equal? )
526 PRIM(STRING_X3d_CI)
527         type_u l2 = TOS.u; POP;
528         unsigned char *p2 = TOS.a; POP;
529         type_u l1 = TOS.u; POP;
530         unsigned char *p1 = TOS.a;
531
532         if (l1 == l2) {
533                 TOS.n = -1;             /* Default to TRUE */
534                 while (l1 > 0) {
535                         if (toupper(*p1) != toupper(*p2)) {
536                                 TOS.n = 0;
537                                 break;
538                         }
539                         ++p1;  ++p2;
540                         --l1;
541                 }
542         }
543         else {
544                 TOS.n = 0;
545         }
546 MIRP
547
548 // bool dependend pick
549 // ?PICK ( v1 v2 bool -- v1|v2 )
550 PRIM(_X3f_PICK)
551         type_u b = TOS.u; POP;
552         if (b) { NOS = TOS; }
553         POP;
554 MIRP
555
556 /* zcount ( zstr -- str len ) */
557 PRIM(ZCOUNT)
558         type_u len = strlen(TOS.a);
559         PUSH; TOS.u = len;
560 MIRP
561
562 PRIM(CLEAN_X2d_HASH)
563         memset(hash_table, 0, sizeof(hash_table));
564 MIRP
565
566 PRIM(HASH_X2d_TABLE)
567         PUSH;
568         TOS.a = hash_table;
569 MIRP
570
571 /* hash ( str len -- hash )
572  * this word is used in find-hash.fs to create
573  * a hash to accelerate word lookup */
574 PRIM(HASH)
575         type_u len = TOS.u; POP;
576         unsigned char *str = TOS.a;
577         type_u tmp = len;
578         type_u hash = 0;
579         while(len--) {
580                 hash <<= 1;
581                 hash ^= tolower(*str);
582                 hash ^= tmp;
583                 str++;
584         }
585         /* we only want hash values which size is smaller
586          * than HASHSIZE */
587         hash &= HASHSIZE - 1;
588         /* access the hash table in steps of CELLSIZE */
589         hash *= CELLSIZE;
590         /* return a pointer for this hash in the hash table */
591         TOS.a = hash_table + hash;
592 MIRP