Pristine Ack-5.5
[Ack-5.5.git] / util / opt / putline.c
1 #ifndef NORCSID
2 static char rcsid[] = "$Id: putline.c,v 2.7 1994/06/24 10:40:51 ceriel Exp $";
3 #endif
4
5 #include "param.h"
6 #include "types.h"
7 #include "tes.h"
8 #include "assert.h"
9 #include <em_spec.h>
10 #include <em_pseu.h>
11 #include <em_mnem.h>
12 #include <em_flag.h>
13 #include "alloc.h"
14 #include "line.h"
15 #include "lookup.h"
16 #include "proinf.h"
17 #include "optim.h"
18 #include "ext.h"
19
20 /*
21  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
22  * See the copyright notice in the ACK home directory, in the file "Copyright".
23  *
24  * Author: Hans van Staveren
25  */
26
27 #define outbyte(b) putc(b,outfile)
28
29 putlines(lnp) register line_p lnp; {
30         register arg_p ap;
31         line_p temp;
32         register instr;
33         short curlin= -2;
34         short thislin;
35
36         while ( lnp != (line_p) 0) {
37                 instr = lnp->l_instr&BMASK;
38                 switch(lnp->l_optyp) {
39                 case OPSYMBOL:
40                         if ((lnp->l_instr&BMASK) == ps_sym)
41                                 outdef(lnp->l_a.la_sp);
42                         else
43                                 outocc(lnp->l_a.la_sp);
44                         break;
45                 case OPSVAL:
46                         outocc(lnp->l_a.la_sval.lasv_sp);
47                         break;
48 #ifdef LONGOFF
49                 case OPLVAL:
50                         outocc(lnp->l_a.la_lval.lalv_sp);
51                         break;
52 #endif
53                 case OPLIST:
54                         ap = lnp->l_a.la_arg;
55                         while (ap != (arg_p) 0) {
56                                 switch(ap->a_typ) {
57                                 case ARGSYM:
58                                         outocc(ap->a_a.a_sp);
59                                         break;
60                                 case ARGVAL:
61                                         outocc(ap->a_a.a_val.av_sp);
62                                         break;
63                                 }
64                                 ap = ap->a_next;
65                         }
66                         break;
67                 }
68
69                 /*
70                  * global symbols now taken care of
71                  */
72
73
74                 switch(instr) {
75                 case ps_sym:
76                         break;
77                 case op_lni:
78                         if (curlin != -2)
79                                 curlin++;
80                         outinst(instr);
81                         break;
82                 case op_lin:
83                         switch(lnp->l_optyp) {
84                         case OPNO:
85                         case OPOFFSET:
86                         case OPNUMLAB:
87                         case OPSYMBOL:
88                         case OPSVAL:
89                         case OPLVAL:
90                         case OPLIST:
91                                 outinst(instr);
92                                 goto processoperand;
93                         case OPSHORT:
94                                 thislin = lnp->l_a.la_short;
95                                 break;
96                         default:
97                                 thislin = (lnp->l_optyp&BMASK)-Z_OPMINI;
98                                 break;
99                         }
100                         if (thislin == curlin && !nflag) {
101                                 temp = lnp->l_next;
102                                 oldline(lnp);
103                                 lnp = temp;
104                                 OPTIM(O_LINGONE);
105                                 continue;
106                         } else if (thislin == curlin+1 && !nflag) {
107                                 instr = op_lni;
108                                 outinst(instr);
109                                 temp = lnp->l_next;
110                                 oldline(lnp);
111                                 OPTIM(O_LINLNI);
112                                 lnp = newline(OPNO);
113                                 lnp->l_next = temp;
114                                 lnp->l_instr = instr;
115                         } else {
116                                 outinst(instr);
117                         }
118                         curlin = thislin;
119                         break;
120                 case op_lab:
121                         curlin = -2;
122                         break;
123                 default:
124                         if ((em_flag[instr-sp_fmnem]&EM_FLO)==FLO_P)
125                                 curlin = -2;
126                         outinst(instr);
127                 }
128 processoperand:
129                 switch(lnp->l_optyp) {
130                 case OPNO:
131                         if ((em_flag[instr-sp_fmnem]&EM_PAR)!=PAR_NO)
132                                 outbyte( (byte) sp_cend) ;
133                         break;
134                 default:
135                         outint((lnp->l_optyp&BMASK)-Z_OPMINI);
136                         break;
137                 case OPSHORT:
138                         outint(lnp->l_a.la_short);
139                         break;
140 #ifdef LONGOFF
141                 case OPOFFSET:
142                         outoff(lnp->l_a.la_offset);
143                         break;
144 #endif
145                 case OPNUMLAB:
146                         if (instr == op_lab)
147                                 numlab(lnp->l_a.la_np->n_repl);
148                         else if (instr < sp_fpseu) /* plain instruction */
149                                 outint((short) lnp->l_a.la_np->n_repl->n_number);
150                         else
151                                 outnum(lnp->l_a.la_np->n_repl);
152                         break;
153                 case OPSYMBOL:
154                         outsym(lnp->l_a.la_sp);
155                         break;
156                 case OPSVAL:
157                         outbyte( (byte) sp_doff) ;
158                         outsym(lnp->l_a.la_sval.lasv_sp);
159                         outint(lnp->l_a.la_sval.lasv_short);
160                         break;
161 #ifdef LONGOFF
162                 case OPLVAL:
163                         outbyte( (byte) sp_doff) ;
164                         outsym(lnp->l_a.la_lval.lalv_sp);
165                         outoff(lnp->l_a.la_lval.lalv_offset);
166                         break;
167 #endif
168                 case OPLIST:
169                         putargs(lnp->l_a.la_arg);
170                         switch(instr) {
171                         case ps_con:
172                         case ps_rom:
173                         case ps_mes:
174                                 outbyte( (byte) sp_cend) ;
175                         }
176                 }
177                 /*
178                  * instruction is output now.
179                  * remove its useless body
180                  */
181
182                 temp = lnp->l_next;
183                 oldline(lnp);
184                 lnp = temp;
185                 if (ferror(outfile))
186                         error("write error");
187         }
188 }
189
190 putargs(ap) register arg_p ap; {
191
192         while (ap != (arg_p) 0) {
193                 switch(ap->a_typ) {
194                 default:
195                         assert(FALSE);
196                 case ARGOFF:
197                         outoff(ap->a_a.a_offset);
198                         break;
199                 case ARGNUM:
200                         outnum(ap->a_a.a_np->n_repl);
201                         break;
202                 case ARGSYM:
203                         outsym(ap->a_a.a_sp);
204                         break;
205                 case ARGVAL:
206                         outbyte( (byte) sp_doff) ;
207                         outsym(ap->a_a.a_val.av_sp);
208                         outoff(ap->a_a.a_val.av_offset);
209                         break;
210                 case ARGSTR:
211                         outbyte( (byte) sp_scon) ;
212                         putstr(&ap->a_a.a_string);
213                         break;
214                 case ARGICN:
215                         outbyte( (byte) sp_icon) ;
216                         goto casecon;
217                 case ARGUCN:
218                         outbyte( (byte) sp_ucon) ;
219                         goto casecon;
220                 case ARGFCN:
221                         outbyte( (byte) sp_fcon) ;
222                 casecon:
223                         outint(ap->a_a.a_con.ac_length);
224                         putstr(&ap->a_a.a_con.ac_con);
225                         break;
226                 }
227                 ap = ap->a_next;
228         }
229 }
230
231 putstr(abp) register argb_p abp; {
232         register argb_p tbp;
233         register length;
234
235         length = 0;
236         tbp = abp;
237         while (tbp!= (argb_p) 0) {
238                 length += tbp->ab_index;
239                 tbp = tbp->ab_next;
240         }
241         outint(length);
242         while (abp != (argb_p) 0) {
243                 for (length=0;length<abp->ab_index;length++)
244                         outbyte( (byte) abp->ab_contents[length] );
245                 abp = abp->ab_next;
246         }
247 }
248
249 outdef(sp) register sym_p sp; {
250
251         /*
252          * The surrounding If statement is removed to be friendly
253          * to Backend writers having to deal with assemblers
254          * not following our conventions.
255         if ((sp->s_flags&SYMOUT)==0) {
256          */
257                 sp->s_flags |= SYMOUT;
258                 if (sp->s_flags&SYMGLOBAL) {
259                         outinst(sp->s_flags&SYMPRO ? ps_exp : ps_exa);
260                         outsym(sp);
261                 }
262         /*
263         }
264          */
265 }
266
267 outocc(sp) register sym_p sp; {
268
269         if ((sp->s_flags&SYMOUT)==0) {
270                 sp->s_flags |= SYMOUT;
271                 if ((sp->s_flags&SYMGLOBAL)==0) {
272                         outinst(sp->s_flags&SYMPRO ? ps_inp : ps_ina);
273                         outsym(sp);
274                 }
275         }
276 }
277
278 outpro() {
279
280         outdef(curpro.symbol);
281         outinst(ps_pro);
282         outsym(curpro.symbol);
283         outoff(curpro.localbytes);
284 }
285
286 outend() {
287
288         outinst(ps_end);
289         outoff(curpro.localbytes);
290 }
291
292 outinst(m) {
293
294         outbyte( (byte) m );
295 }
296
297 outoff(off) offset off; {
298
299 #ifdef LONGOFF
300         if ((short) off == off)
301 #endif
302                 outint((short) off);
303 #ifdef LONGOFF
304         else {
305                 outbyte( (byte) sp_cst4) ;
306                 outshort( (short) (off&0177777L) );
307                 outshort( (short) (off>>16) );
308         }
309 #endif
310 }
311
312 outint(i) short i; {
313
314         if (i>= -sp_zcst0 && i< sp_ncst0-sp_zcst0)
315                 outbyte( (byte) (i+sp_zcst0+sp_fcst0) );
316         else {
317                 outbyte( (byte) sp_cst2) ;
318                 outshort(i);
319         }
320 }
321
322 outshort(i) short i; {
323
324         outbyte( (byte) (i&BMASK) );
325         outbyte( (byte) (i>>8) );
326 }
327
328 numlab(np) register num_p np; {
329
330         if (np->n_number < sp_nilb0)
331                 outbyte( (byte) (np->n_number + sp_filb0) );
332         else
333                 outnum(np);
334 }
335
336 outnum(np) register num_p np; {
337
338         if(np->n_number<256) {
339                 outbyte( (byte) sp_ilb1) ;
340                 outbyte( (byte) (np->n_number) );
341         } else {
342                 outbyte( (byte) sp_ilb2) ;
343                 outshort((short) np->n_number);
344         }
345 }
346
347 outsym(sp) register sym_p sp; {
348         register byte *p;
349         register unsigned num;
350
351         if (sp->s_name[0] == '.') {
352                 num = atoi(&sp->s_name[1]);
353                 if (num < 256) {
354                         outbyte( (byte) sp_dlb1) ;
355                         outbyte( (byte) (num) );
356                 } else {
357                         outbyte( (byte) sp_dlb2) ;
358                         outshort((short) num);
359                 }
360         } else {
361                 p= sp->s_name;
362                 while (*p && p < &sp->s_name[IDL])
363                         p++;
364                 num = p - sp->s_name;
365                 outbyte( (byte) (sp->s_flags&SYMPRO ? sp_pnam : sp_dnam) );
366                 outint((short) num);
367                 p = sp->s_name;
368                 while (num--)
369                         outbyte( (byte) *p++ );
370         }
371 }