Pristine Ack-5.5
[Ack-5.5.git] / util / ego / ca / ca_put.c
1 /* $Id: ca_put.c,v 1.8 1994/06/24 10:19:43 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 #include <stdio.h>
7 #include <em_spec.h>
8 #include <em_pseu.h>
9 #include <em_mnem.h>
10 #include <em_flag.h>
11 #include <em_mes.h>
12 #include "../share/types.h"
13 #include "ca.h"
14 #include "../share/debug.h"
15 #include "../share/def.h"
16 #include "../share/map.h"
17 #include "../share/alloc.h"
18
19 #define outbyte(b) putc(b,outfile)
20
21 FILE *outfile;
22
23 STATIC proc_p thispro;
24
25 STATIC outinst(m) {
26
27         outbyte( (byte) m );
28 }
29
30 STATIC coutshort(i) short i; {
31
32         outbyte( (byte) (i&BMASK) );
33         outbyte( (byte) (i>>8) );
34 }
35
36 STATIC coutint(i) short i; {
37
38         if (i>= -sp_zcst0 && i< sp_ncst0-sp_zcst0)
39                 outbyte( (byte) (i+sp_zcst0+sp_fcst0) );
40         else {
41                 outbyte( (byte) sp_cst2) ;
42                 coutshort(i);
43         }
44 }
45
46 STATIC coutoff(off) offset off; {
47
48         if ((short) off == off)
49                 coutint((short) off);
50         else {
51                 outbyte( (byte) sp_cst4) ;
52                 coutshort( (short) (off&0177777L) );
53                 coutshort( (short) (off>>16) );
54         }
55 }
56
57
58 STATIC outsym(s,t)
59         char *s;
60         int t;
61 {
62         register byte *p;
63         register unsigned num;
64
65         if (s[0] == '.') {
66                 num = atoi(&s[1]);
67                 if (num < 256) {
68                         outbyte( (byte) sp_dlb1) ;
69                         outbyte( (byte) (num) );
70                 } else {
71                         outbyte( (byte) sp_dlb2) ;
72                         coutshort((short) num);
73                 }
74         } else {
75                 p= s;
76                 while (*p && p < &s[IDL])
77                         p++;
78                 num = p - s;
79                 outbyte( (byte) t);
80                 coutint((short) num);
81                 p = s;
82                 while (num--)
83                         outbyte( (byte) *p++ );
84         }
85 }
86
87
88 STATIC outdsym(dbl)
89         dblock_p dbl;
90 {
91         if (dnames[dbl->d_id]) outsym(dnames[dbl->d_id],sp_dnam);
92 }
93
94
95 STATIC outpsym(p)
96         proc_p p;
97 {
98         outsym(pnames[p->p_id],sp_pnam);
99 }
100
101
102 STATIC outddef(id) short id; {
103
104         dblock_p dbl;
105
106         dbl = dmap[id];
107         dbl->d_flags2 |= DF_SYMOUT;
108         if (dbl->d_flags1 & DF_EXTERNAL) {
109                 outinst(ps_exa);
110                 outdsym(dbl);
111         }
112 }
113
114 STATIC outpdef(p) proc_p p; {
115         p->p_flags2 |= PF_SYMOUT;
116         if (p->p_flags1 & PF_EXTERNAL) {
117                 outinst(ps_exp);
118                 outpsym(p);
119         }
120 }
121
122
123 STATIC outdocc(obj) obj_p obj; {
124         dblock_p dbl;
125
126         dbl = obj->o_dblock;
127         if ((dbl->d_flags2 & DF_SYMOUT) == 0) {
128                 dbl->d_flags2 |= DF_SYMOUT;
129                 if (dnames[dbl->d_id] != 0 && 
130                     (dbl->d_flags1 & DF_EXTERNAL) == 0) {
131                         outinst(ps_ina);
132                         outdsym(dbl);
133                 }
134         }
135 }
136
137
138 STATIC outpocc(p) proc_p p; {
139         if ((p->p_flags2 & PF_SYMOUT) == 0) {
140                 p->p_flags2 |= PF_SYMOUT;
141                 if ((p->p_flags1 & PF_EXTERNAL) == 0) {
142                         outinst(ps_inp);
143                         outpsym(p);
144                 }
145         }
146 }
147
148
149 STATIC coutobject(obj)
150         obj_p obj;
151 {
152         /* In general, an object is defined by a global data
153          * label and an offset. There are two special cases:
154          * the label is omitted if the object is part of the current
155          * hol block; the offset is omitted if it is 0 and the label
156          * was not omitted.
157          */
158         if (dnames[obj->o_dblock->d_id] == 0) {
159                 coutoff(obj->o_off);
160         } else {
161                 if (obj->o_off == 0) {
162                         outdsym(obj->o_dblock);
163                 } else {
164                         outbyte((byte) sp_doff);
165                         outdsym(obj->o_dblock);
166                         coutoff(obj->o_off);
167                 }
168         }
169 }
170
171
172 STATIC cputstr(abp) register argb_p abp; {
173         register argb_p tbp;
174         register length;
175
176         length = 0;
177         tbp = abp;
178         while (tbp!= (argb_p) 0) {
179                 length += tbp->ab_index;
180                 tbp = tbp->ab_next;
181         }
182         coutint(length);
183         while (abp != (argb_p) 0) {
184                 for (length=0;length<abp->ab_index;length++)
185                         outbyte( (byte) abp->ab_contents[length] );
186                 abp = abp->ab_next;
187         }
188 }
189
190
191 STATIC outnum(n)
192         int n;
193 {
194         if (n < 256) {
195                 outbyte((byte) sp_ilb1);
196                 outbyte((byte) n);
197         } else {
198                 outbyte((byte) sp_ilb2);
199                 coutshort((short) n);
200         }
201 }
202
203
204 STATIC numlab(n)
205         int n;
206 {
207         if (n < sp_nilb0) {
208                 outbyte((byte) (n + sp_filb0));
209         } else {
210                 outnum(n);
211         }
212 }
213
214
215 STATIC cputargs(lnp)
216         line_p lnp;
217 {
218         register arg_p ap;
219         int cnt = 0;
220         ap = ARG(lnp);
221         while (ap != (arg_p) 0) {
222                 switch(ap->a_type) {
223                         case ARGOFF:
224                                 coutoff(ap->a_a.a_offset);
225                                 break;
226                         case ARGOBJECT:
227                                 coutobject(ap->a_a.a_obj);
228                                 break;
229                         case ARGPROC:
230                                 outpsym(ap->a_a.a_proc);
231                                 break;
232                         case ARGINSTRLAB:
233                                 outnum(ap->a_a.a_instrlab);
234                                 break;
235                         case ARGSTRING:
236                                 outbyte((byte) sp_scon);
237                                 cputstr(&ap->a_a.a_string);
238                                 break;
239                         case ARGICN:
240                                 outbyte((byte) sp_icon);
241                                 goto casecon;
242                         case ARGUCN:
243                                 outbyte((byte) sp_ucon);
244                                 goto casecon;
245                         case ARGFCN:
246                                 outbyte((byte) sp_fcon);
247                         casecon:
248                                 coutint(ap->a_a.a_con.ac_length);
249                                 cputstr(&ap->a_a.a_con.ac_con);
250                                 break;
251                         default:
252                                 assert(FALSE);
253                 }
254                 ap = ap->a_next;
255                 /* Avoid generating extremely long CON or ROM statements */
256                 if (cnt++ > 10 && ap != (arg_p) 0 && 
257                     (INSTR(lnp) == ps_con || INSTR(lnp) == ps_rom)) {
258                         cnt = 0;
259                         outbyte((byte) sp_cend);
260                         outinst(INSTR(lnp));
261                 }
262         }
263 }
264
265
266
267 STATIC outoperand(lnp)
268         line_p lnp;
269 {
270         /* Output the operand of instruction lnp */
271
272         switch(TYPE(lnp)) {
273                 case OPNO:
274                         if (INSTR(lnp) <= sp_lmnem &&
275                             (em_flag[INSTR(lnp)-sp_fmnem]&EM_PAR) != PAR_NO) {
276                                 outbyte((byte) sp_cend);
277                         }
278                         break;
279                 case OPSHORT:
280                         if (INSTR(lnp) == ps_sym) {
281                                 outsym(dnames[SHORT(lnp)],sp_dnam);
282                         } else {
283                                 coutint(SHORT(lnp));
284                         }
285                         break;
286                 case OPOFFSET:
287                         coutoff(OFFSET(lnp));
288                         break;
289                 case OPINSTRLAB:
290                         if (INSTR(lnp) == op_lab) {
291                                 numlab(INSTRLAB(lnp));
292                         } else {
293                                 if (INSTR(lnp) < sp_fpseu) {
294                                         coutint(INSTRLAB(lnp));
295                                 } else {
296                                         numlab(INSTRLAB(lnp));
297                                 }
298                         }
299                         break;
300                 case OPOBJECT:
301                         coutobject(OBJ(lnp));
302                         break;
303                 case OPPROC:
304                         outpsym(PROC(lnp));
305                         break;
306                 case OPLIST:
307                         cputargs(lnp);
308                         switch(INSTR(lnp)) {
309                                 case ps_con:
310                                 case ps_rom:
311                                 case ps_mes:
312                                         outbyte((byte) sp_cend);
313                                         /* list terminator */
314                                         break;
315                         }
316                         break;
317                 default:
318                         assert(FALSE);
319         }
320 }
321
322
323 STATIC outvisibility(lnp)
324         line_p lnp;
325 {
326         /* In EM names of datalabels and procedures can be made
327          * externally visible, so they can be used in other files.
328          * There are special EM pseudo-instructions to state
329          * explicitly that a certain identifier is externally
330          * visible (ps_exa,ps_exp) or invisible (ps_ina,ps_inp).
331          * If there is no such pseudo for a certain identifier,
332          * the identifier is external only if its first use
333          * in the current file is an applied occurrence.
334          * Unfortunately the global optimizer may change the
335          * order of defining and applied occurrences.
336          * In the first optimizer pass (ic) we record for each identifier
337          * whether it is external or not. If necessary we generate
338          * pseudo instructions here.
339          */
340
341          arg_p ap;
342          short instr;
343
344          instr = INSTR(lnp);
345          switch(TYPE(lnp)) {
346                 case OPOBJECT:
347                         outdocc(OBJ(lnp));
348                         /* applied occurrence of a data label */
349                         break;
350                 case OPSHORT:
351                         if (instr == ps_sym) {
352                                 outddef(SHORT(lnp));
353                                 /* defining occ. data label */
354                         }
355                         break;
356                 case OPPROC:
357                         if (instr == ps_pro) {
358                                 outpdef(PROC(lnp));
359                                 /* defining occ. procedure */
360                         } else {
361                                 outpocc(PROC(lnp));
362                         }
363                         break;
364                 case OPLIST:
365                         for (ap =  ARG(lnp); ap != (arg_p) 0; ap = ap->a_next) {
366                                 switch(ap->a_type) {
367                                         case ARGOBJECT:
368                                            outdocc(ap->a_a.a_obj);
369                                            break;
370                                         case ARGPROC:
371                                            outpocc(ap->a_a.a_proc);
372                                            break;
373                                 }
374                         }
375                         break;
376         }
377 }
378
379
380 cputlines(l,lf)
381         line_p l;
382         FILE *lf;
383 {
384         /* Output the lines in Campact assembly language
385          * format.
386          */
387
388         line_p next,lnp;
389
390         outfile = lf;
391         for (lnp = l; lnp != (line_p) 0; lnp = next) {
392                 next = lnp->l_next;
393                 outvisibility(lnp); /* take care of visibiltity rules */
394                 if (INSTR(lnp) != ps_sym && INSTR(lnp) != op_lab) {
395                         outinst(INSTR(lnp));
396                 }
397                 outoperand(lnp);
398                 switch(INSTR(lnp)) {
399                         case ps_pro:
400                                 thispro = PROC(lnp);
401                                 /* fall through ... */
402                         case ps_end:
403                                 coutoff(thispro->p_localbytes);
404                 }
405                 oldline(lnp);
406         }
407         if (lmap != (line_p *) 0) {
408                 oldmap(lmap,llength);
409                 lmap = (line_p *) 0;
410         }
411 }
412
413 cputmagic(lf)
414         FILE *lf;
415 {
416         /* write the magic number */
417
418         outfile = lf;
419         coutshort(sp_magic);
420 }