Pristine Ack-5.5
[Ack-5.5.git] / util / int / stack.c
1 /*
2         Stack manipulation
3 */
4
5 /* $Id: stack.c,v 2.5 1994/06/24 10:49:09 ceriel Exp $ */
6
7 #include        <stdio.h>
8
9 #include        <em_abs.h>
10 #include        "logging.h"
11 #include        "nofloat.h"
12 #include        "global.h"
13 #include        "log.h"
14 #include        "warn.h"
15 #include        "trap.h"
16 #include        "alloc.h"
17 #include        "memdirect.h"
18 #include        "mem.h"
19 #include        "shadow.h"
20 #include        "rsb.h"
21
22 #define STACKSIZE       1000L           /* initial stack size */
23
24 extern size maxstack;                   /* from main.c */
25
26 #ifdef  LOGGING
27 char *stack_sh;                         /* stadowbytes */
28 char *stackML_sh;                       /* speed up access of stadowbytes */
29 #endif  /* LOGGING */
30
31 PRIVATE warn_stbits();
32
33 init_stack() {
34         ML = max_addr;                  /* set Memory Limit */
35         SP = ML + 1;                    /* initialize Stack Pointer */
36         SL = ML + 1;                    /* initialize Stack Limit */
37         LB = ML + 1;                    /* initialize Local Base */
38         AB = ML + 1;                    /* initialize Actual Base */
39
40         SL = ML + 1 - STACKSIZE;        /* initialize Stack Limit */
41         stack = Malloc(STACKSIZE, "stack space");
42         stackML = stack + ML;
43 #ifdef  LOGGING
44         stack_sh = Malloc(STACKSIZE, "shadowspace for stack");
45         stackML_sh = stack_sh + ML;
46         st_clear_area(ML, SL);
47 #endif  /* LOGGING */
48 }
49
50
51 /************************************************************************
52  *      EM-register division.                                           *
53  ************************************************************************
54  *                                                                      *
55  *      newSP(p)        - check and adjust StackPointer.                *
56  *      incSP(n)        - increment stack pointer. n already checked    *
57  *      decSP(n)        - decrement stack pointer. n already checked    *
58  *      newLB(p)        - check and adjust Local Base and Actual Base   *
59  *                                                                      *
60  ************************************************************************/
61
62 newSP(ap)
63         ptr ap;
64 {
65         register ptr p = ap;
66         
67         LOG(("@s6 newSP(%lu), ML = %lu, SP = %lu", p, ML, SP));
68         if (LB < p) {
69                 wtrap(WSPGTLB, ESTACK);
70         }
71         if (!is_wordaligned(p)) {
72                 wtrap(WSPODD, ESTACK);
73         }
74         if (p < SP) {
75                 if (p < HP) {
76                         wtrap(WSPINHEAP, ESTACK);
77                 }
78                 if (maxstack) {
79                         /* more than allowed on command line */
80                         if (ML - p > maxstack) {
81                                 warning(WESTACK);
82                                 trap(ESTACK);
83                         }
84                 }
85                 if (p < SL) {
86                         /* extend stack space */
87                         register size stacksize = ML + 1 - p;
88
89                         stacksize = allocfrac(stacksize);
90                         SL = ML + 1 - stacksize;
91                         stack = Realloc(stack, (size)(stacksize), "stack space");
92                         stackML = stack + ML;
93 #ifdef  LOGGING
94                         stack_sh = Realloc(stack_sh, (size)(stacksize),
95                                                 "shadowspace for stack");
96                         stackML_sh = stack_sh + ML;
97 #endif  /* LOGGING */
98                 }
99
100 #ifdef  LOGGING
101                 st_clear_area(SP - 1, p);
102 #endif  /* LOGGING */
103         }
104         SP = p;
105 }
106
107 incSP(n)
108 #ifdef LOGGING
109         register
110 #endif
111         size n;
112 {
113         register ptr p = SP - n;
114         
115         if (p < HP || maxstack || p < SL) newSP(p);
116         else {
117                 LOG(("@s6 newSP(%lu), ML = %lu, SP = %lu", p, ML, SP));
118 #ifdef LOGGING
119                 /* inline version of st_clear_area.
120                 */
121                 SP = p;
122                 {
123                         while (n--) {
124                                 st_undef(p);
125                                 p++;
126                         }
127                 }
128 #endif
129         }
130 }
131
132 decSP(n)
133         size n;
134 {
135         register ptr p = SP + n;
136         
137         if (LB < p) newSP(p);
138         else {
139                 LOG(("@s6 newSP(%lu), ML = %lu, SP = %lu", p, ML, SP));
140                 SP = p;
141         }
142 }
143
144 newLB(p)
145         ptr p;
146 {
147         if (!in_stack(p)) {
148                 wtrap(WLBOUT, ESTACK);
149         }
150         if (!is_wordaligned(p)) {
151                 wtrap(WLBODD, ESTACK);
152         }
153         if (!is_LB(p)) {
154                 wtrap(WLBRSB, ESTACK);
155         }
156         LB = p;
157         AB = LB + rsbsize;
158 }
159
160
161 /************************************************************************
162  *      Stack store division.                                           *
163  ************************************************************************
164  *                                                                      *
165  *      st_stdp(addr, p)        - STore Data Pointer.                   *
166  *      st_stip(addr, p)        - STore Instruction Pointer.            *
167  *      st_stn(addr, l, n)      - STore N byte integer.                 *
168  *      st_stw(addr, l)         - STore wordsize integer.               *
169  *      st_stf(addr, f, n)      - STore Floating point number.          *
170  *                                                                      *
171  ************************************************************************/
172
173 st_stdp(addr, ap)
174         register ptr addr;
175         ptr ap;
176 {
177         register int i;
178         register long p = (long) ap;
179
180         LOG(("@s6 st_stdp(%lu, %lu)", addr, p));
181         ch_in_stack(addr, psize);
182         ch_wordaligned(addr);
183         for (i = (int) psize; i > 0; i--, addr++) {
184                 ch_st_prot(addr);
185                 stack_loc(addr) = (char) (p);
186                 st_dp(addr);
187                 p = p>>8;
188         }
189
190 }
191
192 st_stip(addr, ap)
193         register ptr addr;
194         ptr ap;
195 {
196         register int i;
197         register long p = (long) ap;
198
199         LOG(("@s6 st_stip(%lu, %lu)", addr, p));
200         ch_in_stack(addr, psize);
201         ch_wordaligned(addr);
202         for (i = (int) psize; i > 0; i--, addr++) {
203                 ch_st_prot(addr);
204                 stack_loc(addr) = (char) (p);
205                 st_ip(addr);
206                 p = p>>8;
207         }
208 }
209
210 st_stn(addr, al, n)
211         register ptr addr;
212         long al;
213         size n;
214 {
215         register int i;
216         register long l = al;
217 #ifdef LOGGING
218         /* a psize zero is ambiguous */
219         int sh_flags = (l == 0 && n == psize) ? (SH_INT|SH_DATAP) : SH_INT;
220 #endif
221
222         LOG(("@s6 st_stn(%lu, %ld, %lu)", addr, l, n));
223         ch_in_stack(addr, n);
224         ch_aligned(addr, n);
225
226         /* store the bytes */
227         for (i = (int) n; i > 0; i--, addr++) {
228                 ch_st_prot(addr);
229                 stack_loc(addr) = (char) l;
230 #ifdef  LOGGING
231                 st_sh(addr) = sh_flags;
232 #endif  /* LOGGING */
233                 l = l>>8;
234         }
235 }
236
237 st_stw(addr, al)
238         register ptr addr;
239         long al;
240 {
241         register int i;
242         register long l = al;
243 #ifdef LOGGING
244         /* a psize zero is ambiguous */
245         int sh_flags = (l == 0 && wsize == psize) ? (SH_INT|SH_DATAP) : SH_INT;
246 #endif
247
248         LOG(("@s6 st_stw(%lu, %ld)", addr, l));
249         ch_w_in_stack(addr);
250         ch_wordaligned(addr);
251
252         /* store the bytes */
253         for (i = (int) wsize; i > 0; i--, addr++) {
254                 ch_st_prot(addr);
255                 stack_loc(addr) = (char) l;
256 #ifdef  LOGGING
257                 st_sh(addr) = sh_flags;
258 #endif  /* LOGGING */
259                 l = l>>8;
260         }
261 }
262
263 #ifndef NOFLOAT
264 st_stf(addr, f, n)
265         register ptr addr;
266         double f;
267         size n;
268 {
269         register char *cp = (char *) &f;
270         float fl;
271         register int i;
272
273         LOG(("@s6 st_stf(%lu, %g, %lu)", addr, f, n));
274         ch_in_stack(addr, n);
275         ch_wordaligned(addr);
276         if ((int) n == 4) {
277                 fl = f;
278                 cp = (char *) &fl;
279         }
280         for (i = (int) n; i > 0; i--, addr++) {
281                 ch_st_prot(addr);
282                 stack_loc(addr) = *(cp++);
283                 st_fl(addr);
284         }
285 }
286 #endif  /* NOFLOAT */
287
288 /************************************************************************
289  *      Stack load division.                                            *
290  ************************************************************************
291  *                                                                      *
292  *      st_lddp(addr)   - LoaD Data Pointer from stack.                 *
293  *      st_ldip(addr)   - LoaD Instruction Pointer from stack.          *
294  *      st_ldu(addr, n) - LoaD n Unsigned bytes from stack.             *
295  *      st_lduw(addr)   - LoaD wsize Unsigned bytes from stack.         *
296  *      st_lds(addr, n) - LoaD n Signed bytes from stack.               *
297  *      st_ldsw(addr)   - LoaD wsize Signed bytes from stack.           *
298  *      st_ldf(addr, n) - LoaD Floating point number from stack.        *
299  *                                                                      *
300  ************************************************************************/
301
302 ptr st_lddp(addr)
303         register ptr addr;
304 {
305         register ptr p;
306
307         LOG(("@s6 st_lddp(%lu)", addr));
308
309         ch_in_stack(addr, psize);
310         ch_wordaligned(addr);
311 #ifdef  LOGGING
312         if (!is_st_set(addr, psize, SH_DATAP)) {
313                 warning(WLDPEXP);
314                 warn_stbits(addr, psize);
315         }
316 #endif  /* LOGGING */
317
318         p = p_in_stack(addr);
319         LOG(("@s6 st_lddp() returns %lu", p));
320         return (p);
321 }
322
323 ptr st_ldip(addr)
324         register ptr addr;
325 {
326         register ptr p;
327
328         LOG(("@s6 st_ldip(%lu)", addr));
329
330         ch_in_stack(addr, psize);
331         ch_wordaligned(addr);
332 #ifdef  LOGGING
333         if (!is_st_set(addr, psize, SH_INSP)) {
334                 warning(WLIPEXP);
335                 warn_stbits(addr, psize);
336         }
337 #endif  /* LOGGING */
338
339         p = p_in_stack(addr);
340         LOG(("@s6 st_ldip() returns %lu", p));
341         return (p);
342 }
343
344 unsigned long st_ldu(addr, n)
345         register ptr addr;
346         size n;
347 {
348         register int i;
349         register unsigned long u = 0;
350
351         LOG(("@s6 st_ldu(%lu, %lu)", addr, n));
352
353         ch_in_stack(addr, n);
354         ch_aligned(addr, n);
355 #ifdef  LOGGING
356         if (!is_st_set(addr, n, SH_INT)) {
357                 warning(n == 1 ? WLCEXP : WLIEXP);
358                 warn_stbits(addr, n);
359         }
360 #endif  /* LOGGING */
361
362         addr += n-1;
363         for (i = (int) n-1; i >= 0; i--, addr--) {
364                 u = (u<<8) | (btou(stack_loc(addr)));
365         }
366         LOG(("@s6 st_ldu() returns %ld", u));
367         return (u);
368 }
369
370 unsigned long st_lduw(addr)
371         register ptr addr;
372 {
373         register int i;
374         register unsigned long u = 0;
375
376         LOG(("@s6 st_lduw(%lu)", addr));
377
378         ch_w_in_stack(addr);
379         ch_wordaligned(addr);
380 #ifdef  LOGGING
381         if (!is_st_set(addr, wsize, SH_INT)) {
382                 warning(WLIEXP);
383                 warn_stbits(addr, wsize);
384         }
385 #endif  /* LOGGING */
386
387         addr += wsize - 1;
388         for (i = (int) wsize-1; i >= 0; i--, addr--) {
389                 u = (u<<8) | (btou(stack_loc(addr)));
390         }
391         LOG(("@s6 st_lduw() returns %ld", u));
392         return (u);
393 }
394
395 long st_lds(addr, n)
396         register ptr addr;
397         size n;
398 {
399         register int i;
400         register long l;
401
402         LOG(("@s6 st_lds(%lu, %lu)", addr, n));
403
404         ch_in_stack(addr, n);
405         ch_aligned(addr, n);
406 #ifdef  LOGGING
407         if (!is_st_set(addr, n, SH_INT)) {
408                 warning(n == 1 ? WLCEXP : WLIEXP);
409                 warn_stbits(addr, n);
410         }
411 #endif  /* LOGGING */
412
413         addr += n - 2;
414         l = btos(stack_loc(addr + 1));
415         for (i = n - 2; i >= 0; i--, addr--) {
416                 l = (l<<8) | btol(stack_loc(addr));
417         }
418         LOG(("@s6 st_lds() returns %ld", l));
419         return (l);
420 }
421
422 long st_ldsw(addr)
423         register ptr addr;
424 {
425         register int i;
426         register long l;
427
428         LOG(("@s6 st_ldsw(%lu)", addr));
429
430         ch_w_in_stack(addr);
431         ch_wordaligned(addr);
432 #ifdef  LOGGING
433         if (!is_st_set(addr, wsize, SH_INT)) {
434                 warning(WLIEXP);
435                 warn_stbits(addr, wsize);
436         }
437 #endif  /* LOGGING */
438
439         addr += wsize - 2;
440         l = btos(stack_loc(addr+1));
441         for (i = wsize - 2; i >= 0; i--, addr--) {
442                 l = (l<<8) | btol(stack_loc(addr));
443         }
444         LOG(("@s6 st_ldsw() returns %ld", l));
445         return (l);
446 }
447
448 #ifndef NOFLOAT
449 double st_ldf(addr, n)
450         register ptr addr;
451         size n;
452 {
453         double f;
454         float fl;
455         register char *cp;
456         register int i;
457
458         LOG(("@s6 st_ldf(%lu, %lu)", addr, n));
459
460         if ((int)n == 4) {
461                 cp = (char *) &fl;
462         }
463         else {
464                 cp = (char *) &f;
465         }
466         ch_in_stack(addr, n);
467         ch_wordaligned(addr);
468 #ifdef  LOGGING
469         if (!is_st_set(addr, n, SH_FLOAT)) {
470                 warning(WLFEXP);
471                 warn_stbits(addr, n);
472         }
473 #endif  /* LOGGING */
474
475         for (i = (int) n; i > 0; i--, addr++) {
476                 *(cp++) = stack_loc(addr);
477         }
478         if ((int)n == 4) {
479                 f = fl;
480         }
481         return (f);
482 }
483 #endif  /* NOFLOAT */
484
485 /************************************************************************
486  *      Stack move division                                             *
487  ************************************************************************
488  *                                                                      *
489  *      st_mvs(s2, s1, n) - Move n bytes in stack from s1 to s2.        *
490  *      st_mvd(s, d, n) - Move n bytes from d in data to s in stack.    *
491  *                                                                      *
492  *      st_mvs(): The intention is to copy the contents of addresses    *
493  *      s1, s1+1....s1-(n-1) to addresses s2, s2+1....s2+(n-1).         *
494  *      All addresses are expected to be in the stack. This condition   *
495  *      is checked for. The shadow bytes of the bytes to be filled in,  *
496  *      are marked identical to the source-shadow bytes.                *
497  *                                                                      *
498  *      st_mvd(), dt_mvd() and dt_mvs() act identically (see data.c).   *
499  *                                                                      *
500  ************************************************************************/
501
502 st_mvs(s2, s1, n)                       /* s1 -> s2 */
503         register ptr s2, s1;
504         size n;
505 {
506         register int i;
507
508         ch_in_stack(s1, n);
509         ch_wordaligned(s1);
510         ch_in_stack(s2, n);
511         ch_wordaligned(s2);
512
513         for (i = (int) n; i > 0; i--, s1++, s2++) {
514                 ch_st_prot(s2);
515                 ch_st_prot(s1);
516                 stack_loc(s2) = stack_loc(s1);
517 #ifdef  LOGGING
518                 st_sh(s2) = st_sh(s1) & ~SH_PROT;
519 #endif  /* LOGGING */
520         }
521 }
522
523 st_mvd(s, d, n)                         /* d -> s */
524         register ptr s, d;
525         size n;
526 {
527         register int i;
528
529         ch_in_data(d, n);
530         ch_wordaligned(d);
531         ch_in_stack(s, n);
532         ch_wordaligned(s);
533
534         for (i = (int) n; i > 0; i--, s++, d++) {
535                 ch_st_prot(s);
536                 stack_loc(s) = data_loc(d);
537 #ifdef  LOGGING
538                 st_sh(s) = dt_sh(d) & ~SH_PROT;
539 #endif  /* LOGGING */
540         }
541 }
542
543 /************************************************************************
544  *      Stack pop division.                                             *
545  ************************************************************************
546  *                                                                      *
547  *      dppop()         - pop a data ptr, return a ptr.                 *
548  *      upop(n)         - pop n unsigned bytes, return a long.          *
549  *      uwpop()         - pop wsize unsigned bytes, return a long.      *
550  *      spop(n)         - pop n signed bytes, return a long.            *
551  *      swpop()         - pop wsize signed bytes, return a long.        *
552  *      pop_dt(d, n)    - pop n bytes, store at address d in data.      *
553  *      popw_dt(d)      - pop wsize bytes, store at address d in data.  *
554  *      pop_st(s, n)    - pop n bytes, store at address s in stack.     *
555  *      popw_st(s)      - pop wsize bytes, store at address s in stack. *
556  *      fpop()          - pop a floating point number.                  *
557  *      wpop()          - pop a signed word, don't care about any type. *
558  *                                                                      *
559  ************************************************************************/
560
561 ptr dppop()
562 {
563         register ptr p;
564
565         p = st_lddp(SP);
566         decSP(psize);
567         LOG(("@s7 dppop(), return: %lu", p));
568         return (p);
569 }
570
571 unsigned long upop(n)
572         size n;
573 {
574         register unsigned long l;
575
576         l = st_ldu(SP, n);
577         decSP(max(n, wsize));
578         LOG(("@s7 upop(), return: %lu", l));
579         return (l);
580 }
581
582 unsigned long uwpop()
583 {
584         register unsigned long l;
585
586         l = st_lduw(SP);
587         decSP(wsize);
588         LOG(("@s7 uwpop(), return: %lu", l));
589         return (l);
590 }
591
592 long spop(n)
593         size n;
594 {
595         register long l;
596
597         l = st_lds(SP, n);
598         decSP(max(n, wsize));
599         LOG(("@s7 spop(), return: %ld", l));
600         return (l);
601 }
602
603 long swpop()
604 {
605         register long l;
606
607         l = st_ldsw(SP);
608         decSP(wsize);
609         LOG(("@s7 swpop(), return: %ld", l));
610         return (l);
611 }
612
613 pop_dt(d, n)
614         ptr d;
615         size n;
616 {
617         if (n < wsize)
618                 dt_stn(d, (long) upop(n), n);
619         else {
620                 dt_mvs(d, SP, n);
621                 decSP(n);
622         }
623 }
624
625 popw_dt(d)
626         ptr d;
627 {
628         dt_mvs(d, SP, wsize);
629         decSP(wsize);
630 }
631
632 pop_st(s, n)
633         ptr s;
634         size n;
635 {
636         if (n < wsize)
637                 st_stn(s, (long) upop(n), n);
638         else {
639                 st_mvs(s, SP, n);
640                 decSP(n);
641         }
642 }
643
644 popw_st(s)
645         ptr s;
646 {
647         st_mvs(s, SP, wsize);
648         decSP(wsize);
649 }
650
651 #ifndef NOFLOAT
652 double fpop(n)
653         size n;
654 {
655         double d;
656
657         d = st_ldf(SP, n);
658         decSP(n);
659         return (d);
660 }
661 #endif  /* NOFLOAT */
662
663 long wpop()
664 {
665         register long l;
666         
667         l = w_in_stack(SP);
668         decSP(wsize);
669         return (l);
670 }
671
672 /************************************************************************
673  *      Stack push division.                                            *
674  ************************************************************************
675  *                                                                      *
676  *      dppush(p)       - push a data ptr, load from p.                 *
677  *      wpush(l)        - push a word, load from l.                     *
678  *      npush(l, n)     - push n bytes, load from l.                    *
679  *      push_dt(d, n)   - push n bytes, load from address d in data.    *
680  *      pushw_dt(d)     - push wsize bytes, load from address d in data.*
681  *      push_st(s, n)   - push n bytes, load from address s in stack.   *
682  *      pushw_st(s)     - push wsize bytes, load from address s in stack.*
683  *      fpush(f, n)     - push a floating point number, of size n.      *
684  *                                                                      *
685  ************************************************************************/
686
687 dppush(p)
688         ptr p;
689 {
690         incSP(psize);
691         st_stdp(SP, p);
692 }
693
694 wpush(l)
695         long l;
696 {
697         incSP(wsize);
698         st_stw(SP, l);
699 }
700
701 npush(l, n)
702         register long l;
703         register size n;
704 {
705         if (n <= wsize) {
706                 incSP(wsize);
707                 if (n == 1) l &= MASK1;
708                 else if (n == 2) l &= MASK2;
709                 st_stw(SP, l);
710         }
711         else {
712                 incSP(n);
713                 st_stn(SP, l, n);
714         }
715 }
716
717 push_dt(d, n)
718         ptr d;
719         size n;
720 {
721         if (n < wsize) {
722                 npush((long) dt_ldu(d, n), n);
723         }
724         else {
725                 incSP(n);
726                 st_mvd(SP, d, n);
727         }
728 }
729
730 pushw_dt(d)
731         ptr d;
732 {
733         incSP(wsize);
734         st_mvd(SP, d, wsize);
735 }
736
737 push_st(s, n)
738         ptr s;
739         size n;
740 {
741         if (n < wsize) {
742                 npush((long) st_ldu(s, n), n);
743         }
744         else {
745                 incSP(n);
746                 st_mvs(SP, s, n);
747         }
748 }
749
750 pushw_st(s)
751         ptr s;
752 {
753         incSP(wsize);
754         st_mvs(SP, s, wsize);
755 }
756
757 #ifndef NOFLOAT
758 fpush(f, n)
759         double f;
760         size n;
761 {
762         incSP(n);
763         st_stf(SP, f, n);
764 }
765 #endif  /* NOFLOAT */
766
767 #ifdef  LOGGING
768
769 PRIVATE warn_stbits(addr, n)
770         register ptr addr;
771         register size n;
772 {
773         register int or_bits = 0;
774         register int and_bits = 0xff;
775
776         while (n--) {
777                 or_bits |= st_sh(addr);
778                 and_bits &= st_sh(addr);
779                 addr++;
780         }
781
782         if (or_bits != and_bits) {
783                 /* no use trying to diagnose */
784                 warningcont(WWASMISC);
785                 return;
786         }
787         if (or_bits == 0)
788                 warningcont(WWASUND);
789         if (or_bits & SH_INT)
790                 warningcont(WWASINT);
791         if (or_bits & SH_FLOAT)
792                 warningcont(WWASFLOAT);
793         if (or_bits & SH_DATAP)
794                 warningcont(WWASDATAP);
795         if (or_bits & SH_INSP)
796                 warningcont(WWASINSP);
797 }
798
799 #endif  /* LOGGING */
800