Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / 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 1.6 1994/06/27 07:58:25 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 #define LocalIntVar()   NewLocal(int_size, int_align, reg_any, REGISTER)
24 #endif /* STB */
25
26 /*      Because EM does not support the loading and storing of
27         objects having other sizes than word fragment and multiple,
28         we need to have a way of transferring these objects, whereby
29         we simulate "loi" and "sti": the address of the source resp.
30         destination is located on top of stack and a call is done
31         to load_block() resp. store_block().
32         ===============================================================
33         # Loadblock() works on the stack as follows: ([ ] indicates the
34         # position of the stackpointer)
35         # lower address--->
36         # 1)    | &object
37         # 2)    | ... ATW(sz) bytes ... | sz | &stack_block | &object
38         # 3)    | ... ATW(sz) bytes ...
39         ===============================================================
40         Loadblock() pushes ATW(sz) bytes directly onto the stack!
41
42         Store_block() works on the stack as follows:
43         lower address--->
44         1)      | ... ATW(sz) bytes ... | &object
45         2)      | ... ATW(sz) bytes ... | &object | &stack_block | sz
46         3)      <empty>
47
48         If sz is a legal argument for "loi" or "sti", just one EM
49         instruction is generated.
50         In the other cases, the notion of alignment is taken into account:
51         we only push an object of the size accepted by EM onto the stack,
52         while we need a loop to store the stack block into a memory object.
53 */
54
55 suitable_sz(sz, al)
56         arith sz;
57         int al;
58 {
59         return  ((int)sz % (int)word_size == 0 && al % word_align == 0) ||
60                 (
61                         word_size % sz == 0 &&
62                         (al >= (int)sz || al >= word_align)
63                 /* Lots of Irritating Stupid Parentheses */
64                 );
65 }
66
67 store_block(sz, al)
68         arith sz;
69         int al;
70 {
71         if (suitable_sz(sz, al))
72                 C_sti(sz);
73         else {
74 #ifndef STB
75                 arith src, dst;
76
77                 /* allocate two pointer temporaries */
78                 src = LocalPtrVar();
79                 dst = LocalPtrVar();
80
81                 /* load the addresses */
82                 StoreLocal(dst, pointer_size);
83                 C_lor((arith)1);        /* push current sp */
84                 StoreLocal(src, pointer_size);
85                 copy_loop(sz, src, dst);
86                 C_asp(ATW(sz));
87                 FreeLocal(dst);
88                 FreeLocal(src);
89 #else /* STB */
90                 /*      address of destination lies on the stack        */
91
92                 /*      push address of first byte of block on stack onto
93                         the stack by computing it from the current stack
94                         pointer position
95                 */
96                 C_lor((arith)1);        /* push current sp              */
97                 C_adp(pointer_size);    /* set & to 1st byte of block   */
98                 C_loc(sz);              /* number of bytes to transfer  */
99                 C_cal("__stb");         /* call transfer routine        */
100                 C_asp(pointer_size + pointer_size + int_size + ATW(sz));
101 #endif /* STB */
102         }
103 }
104
105 load_block(sz, al)
106         arith sz;
107         int al;
108 {
109
110         if (suitable_sz(sz, al))
111                 C_loi(sz);
112         else {
113 #ifndef STB
114                 arith src, dst;
115
116                 /* allocate two pointer temporaries */
117                 src = LocalPtrVar();
118                 dst = LocalPtrVar();
119
120                 StoreLocal(src, pointer_size);
121                 C_asp(-ATW(sz));        /* allocate stack block */
122                 C_lor((arith)1);        /* push & of stack block as dst */
123                 StoreLocal(dst, pointer_size);
124                 copy_loop(sz, src, dst);
125                 FreeLocal(dst);
126                 FreeLocal(src);
127 #else /* STB */
128                 arith esz = ATW(sz) - pointer_size;
129                 C_asp(-esz);            /* allocate stack block */
130                 C_lor((arith)1);        /* push & of stack block as dst */
131                 C_dup(pointer_size);            /* fetch source address */
132                 C_adp(esz);
133                 C_loi(pointer_size);
134                 C_loc(sz);                      /* # bytes to copy      */
135                 C_cal("__stb");                 /* library copy routine */
136                 C_asp(int_size + pointer_size + pointer_size);
137 #endif /* STB */
138         }
139 }
140
141 copy_block(sz, al)
142         arith sz;
143         int al;
144 {
145
146         if (suitable_sz(sz, al))
147                 C_blm(sz);
148         else {
149 #ifndef STB
150                 arith src, dst;
151
152                 /* allocate two pointer temporaries */
153                 src = LocalPtrVar();
154                 dst = LocalPtrVar();
155
156                 StoreLocal(dst, pointer_size);
157                 StoreLocal(src, pointer_size);
158                 copy_loop(sz, src, dst);
159                 FreeLocal(dst);
160                 FreeLocal(src);
161 #else /* STB */
162                 C_loc(sz);                      /* # bytes to copy      */
163                 C_cal("__stb");                 /* library copy routine */
164                 C_asp(int_size + pointer_size + pointer_size);
165 #endif /* STB */
166         }
167 }
168
169 #ifndef STB
170 copy_loop(sz, src, dst)
171         arith sz, src, dst;
172 {
173         /* generate inline byte-copy loop */
174         label l_cont = text_label(), l_stop = text_label();
175         arith tmp_sz = LocalIntVar();
176
177         C_loc(sz);              /* amount of bytes */
178         StoreLocal(tmp_sz, int_size);
179         C_df_ilb(l_cont);
180         LoadLocal(tmp_sz, int_size);
181         C_zle(l_stop);
182         C_del(tmp_sz);
183         LoadLocal(src, pointer_size);
184         C_dup(pointer_size);
185         C_adp((arith)1);
186         StoreLocal(src, pointer_size);
187         C_loi((arith)1);
188         LoadLocal(dst, pointer_size);
189         C_dup(pointer_size);
190         C_adp((arith)1);
191         StoreLocal(dst, pointer_size);
192         C_sti((arith)1);
193         C_bra(l_cont);
194         C_df_ilb(l_stop);
195         FreeLocal(tmp_sz);
196 }
197 #endif /* STB */
198
199 #endif  /* LINT */
200