Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom / blocks.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: blocks.c,v 3.12 1994/06/24 12:02:14 ceriel Exp $ */
6 /*      B L O C K   S T O R I N G   A N D   L O A D I N G       */
7
8 #include        "lint.h"
9 #ifndef LINT
10
11 #include <em.h>
12 #include <em_reg.h>
13 #include "arith.h"
14 #include "sizes.h"
15 #include "atw.h"
16 #include "align.h"
17 #ifndef STB
18 #include "label.h"
19 #include "stack.h"
20 #include "Lpars.h"
21 extern arith NewLocal();
22 #define LocalPtrVar()   NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
23 #endif /* STB */
24
25 /*      Because EM does not support the loading and storing of
26         objects having other sizes than word fragment and multiple,
27         we need to have a way of transferring these objects, whereby
28         we simulate "loi" and "sti": the address of the source resp.
29         destination is located on top of stack and a call is done
30         to load_block() resp. store_block().
31         ===============================================================
32         # Loadblock() works on the stack as follows: ([ ] indicates the
33         # position of the stackpointer)
34         # lower address--->
35         # 1)    | &object
36         # 2)    | ... ATW(sz) bytes ... | sz | &stack_block | &object
37         # 3)    | ... ATW(sz) bytes ...
38         ===============================================================
39         Loadblock() pushes ATW(sz) bytes directly onto the stack!
40
41         Store_block() works on the stack as follows:
42         lower address--->
43         1)      | ... ATW(sz) bytes ... | &object
44         2)      | ... ATW(sz) bytes ... | &object | &stack_block | sz
45         3)      <empty>
46
47         If sz is a legal argument for "loi" or "sti", just one EM
48         instruction is generated.
49         In the other cases, the notion of alignment is taken into account:
50         we only push an object of the size accepted by EM onto the stack,
51         while we need a loop to store the stack block into a memory object.
52 */
53 store_block(sz, al)
54         arith sz;
55         int al;
56 {
57         if (
58                 ((sz == al) && (word_align % al == 0)) ||
59                 (
60                         (sz % word_size == 0 || word_size % sz == 0) &&
61                         (al % word_align == 0)
62                 )
63         )       /* Lots of Irritating Stupid Parentheses */
64                 C_sti(sz);
65         else {
66 #ifndef STB
67                 arith src, dst;
68
69                 /* allocate two pointer temporaries */
70                 src = LocalPtrVar();
71                 dst = LocalPtrVar();
72
73                 /* load the addresses */
74                 StoreLocal(dst, pointer_size);
75                 C_lor((arith)1);        /* push current sp */
76                 StoreLocal(src, pointer_size);
77                 copy_loop(sz, src, dst);
78                 C_asp(ATW(sz));
79                 FreeLocal(dst);
80                 FreeLocal(src);
81 #else /* STB *?
82                 /*      address of destination lies on the stack        */
83
84                 /*      push address of first byte of block on stack onto
85                         the stack by computing it from the current stack
86                         pointer position
87                 */
88                 C_lor((arith)1);        /* push current sp              */
89                 C_adp(pointer_size);    /* set & to 1st byte of block   */
90                 C_loc(sz);              /* number of bytes to transfer  */
91                 C_cal("__stb");         /* call transfer routine        */
92                 C_asp(pointer_size + pointer_size + int_size + ATW(sz));
93 #endif /* STB */
94         }
95 }
96
97 load_block(sz, al)
98         arith sz;
99         int al;
100 {
101         arith esz = ATW(sz);    /* effective size == actual # pushed bytes */
102
103         if (
104                 ((sz == al) && (word_align % al == 0)) ||
105                 (
106                         (sz % word_size == 0 || word_size % sz == 0) &&
107                         (al % word_align == 0)
108                 )
109         )       /* Lots of Irritating Stupid Parentheses */
110                 C_loi(sz);
111         else {
112 #ifndef STB
113                 arith src, dst;
114
115                 /* allocate two pointer temporaries */
116                 src = LocalPtrVar();
117                 dst = LocalPtrVar();
118
119                 StoreLocal(src, pointer_size);
120                 C_asp(-esz);            /* allocate stack block */
121                 C_lor((arith)1);        /* push & of stack block as dst */
122                 StoreLocal(dst, pointer_size);
123                 copy_loop(sz, src, dst);
124                 FreeLocal(dst);
125                 FreeLocal(src);
126 #else /* STB */
127                 C_asp(-(esz - pointer_size));   /* allocate stack block */
128                 C_lor((arith)1);        /* push & of stack block as dst */
129                 C_dup(pointer_size);            /* fetch source address */
130                 C_adp(esz - pointer_size);
131                 C_loi(pointer_size);
132                 C_loc(sz);                      /* # bytes to copy      */
133                 C_cal("__stb");                 /* library copy routine */
134                 C_asp(int_size + pointer_size + pointer_size);
135 #endif /* STB */
136         }
137 }
138
139 #ifndef STB
140 copy_loop(sz, src, dst)
141         arith sz, src, dst;
142 {
143         /* generate inline byte-copy loop */
144         label l_cont = text_label(), l_stop = text_label();
145
146         C_loc(sz);              /* amount of bytes */
147         C_df_ilb(l_cont);
148         C_dup(word_size);
149         C_zle(l_stop);
150         C_dec();
151         LoadLocal(src, pointer_size);
152         C_dup(pointer_size);
153         C_adp((arith)1);
154         StoreLocal(src, pointer_size);
155         C_loi((arith)1);
156         LoadLocal(dst, pointer_size);
157         C_dup(pointer_size);
158         C_adp((arith)1);
159         StoreLocal(dst, pointer_size);
160         C_sti((arith)1);
161         C_bra(l_cont);
162         C_df_ilb(l_stop);
163         C_asp(word_size);
164 }
165 #endif /* STB */
166
167 #endif  /* LINT */
168