Pristine Ack-5.5
[Ack-5.5.git] / mach / vax4 / cg / mach.c
1 #include <stb.h>
2
3 #ifndef lint
4 static char rcsid[] = "$Id: mach.c,v 1.9 1994/06/24 13:41:44 ceriel Exp $";
5 #endif /* lint */
6 /*
7  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
8  * See the copyright notice in the ACK home directory, in the file "Copyright".
9  *
10  */
11
12 /*
13  * Machine dependent back end routines for the VAX using 4-byte words
14  */
15
16 /*
17  * Byte order: |  3  |  2  |  1  |  0  |
18  */
19 con_part(sz, w)
20         register int    sz;
21         word            w;
22 {
23         /*
24          * Align new bytes on boundary of its on size.
25          */
26         while (part_size % sz) part_size++;
27
28         if (part_size == TEM_WSIZE)
29                 part_flush();
30         if (sz == 1 || sz == 2) {
31                 /* Smaller than a machineword. */
32                 w &= (sz == 1 ? 0xFF : 0xFFFF);
33                 w <<= 8 * part_size;
34                 part_word |= w;
35         } else {
36                 assert(sz == 4);
37                 part_word = w;
38         }
39         part_size += sz;
40 }
41
42 con_mult(sz)
43         word    sz;
44 {
45         if (sz != 4)
46                 fatal("bad icon/ucon size");
47         fprintf(codefile,".data4\t%s\n",str);
48 }
49
50 #ifdef MACH_OPTIONS
51 static int gdb_flag = 0;
52
53 mach_option(s)
54         char *s;
55 {
56         if (! strcmp(s, "-gdb")) {
57                 gdb_flag = 1;
58         }
59         else {
60                 error("Unknown flag %s", s);
61         }
62 }
63 #endif /* MACH_OPTIONS */
64
65 mes(mesno)
66         word    mesno;
67 {
68         int argt, a1, a2 ;
69
70         switch ( (int)mesno ) {
71         case ms_ext :
72                 for (;;) {
73                         switch ( argt=getarg(
74                             ptyp(sp_cend)|ptyp(sp_pnam)|sym_ptyp) ) {
75                         case sp_cend :
76                                 return ;
77                         default:
78                                 strarg(argt) ;
79                                 fprintf(codefile,".define %s\n",argstr) ;
80                                 break ;
81                         }
82                 }
83         case ms_stb:
84                 argt = getarg(str_ptyp | cst_ptyp);
85                 if (argt == sp_cstx)
86                         fputs(".symb \"\", ", codefile);
87                 else {
88                         fprintf(codefile, ".symb \"%s\", ", str);
89                         argt = getarg(cst_ptyp);
90                 }
91                 a1 = argval;
92                 argt = getarg(cst_ptyp);
93                 a2 = argval;
94                 argt = getarg(cst_ptyp|nof_ptyp|sof_ptyp|ilb_ptyp|pro_ptyp);
95 #ifdef MACH_OPTIONS
96                 if (gdb_flag) {
97                         if (a1 == N_PSYM) {
98                                 /* Change offset from AB into offset from
99                                    the frame pointer (ab).
100                                 */
101                                 argval += 4;
102                         }
103                 }
104 #endif
105                 fprintf(codefile, "%s, 0x%x, %d\n", strarg(argt), a1, a2);
106                 argt = getarg(end_ptyp);
107                 break;
108         case ms_std:
109                 argt = getarg(str_ptyp | cst_ptyp);
110                 if (argt == sp_cstx)
111                         str[0] = '\0';
112                 else {
113                         argt = getarg(cst_ptyp);
114                 }
115                 swtxt();
116                 if (argval == N_SLINE
117 #ifdef MACH_OPTIONS
118                     && ! gdb_flag
119 #endif
120                 ) {
121                         fputs("calls $0,___u_LiB\n", codefile);
122                         cleanregs();    /* debugger might change variables */
123                 }
124                 fprintf(codefile, ".symd \"%s\", 0x%x,", str, (int) argval);
125                 argt = getarg(cst_ptyp);
126                 fprintf(codefile, "%d\n", (int) argval);
127                 argt = getarg(end_ptyp);
128                 break;
129         default :
130                 while ( getarg(any_ptyp) != sp_cend ) ;
131                 break ;
132         }
133 }
134
135 #define PDPFLOAT
136 #define CODE_GENERATOR
137 #include <con_float>
138
139 #ifndef REGVARS
140 prolog(nlocals)
141         full    nlocals;
142 {
143         fprintf(codefile,".data2 00\n");
144         if (nlocals == 0)
145                 return;
146         if (nlocals == 4)
147                 fprintf(codefile,"\tclrl\t-(sp)\n");
148         else if (nlocals == 8)
149                 fprintf(codefile,"\tclrq\t-(sp)\n");
150         else
151                 fprintf(codefile,"\tsubl2\t$%ld,sp\n",nlocals);
152 }
153
154 #endif /* not REGVARS */
155
156 char    *segname[] = {
157         ".sect .text",  /* SEGTXT */
158         ".sect .data",  /* SEGCON */
159         ".sect .rom",   /* SEGROM */
160         ".sect .bss"    /* SEGBSS */
161 };
162
163 #ifdef REGVARS
164 static full     nlocals;        /* Number of local variables. */
165
166 #define NR_REG          8       /* Number of registers. */
167 #define FIRST_REG       4
168 #define LAST_REG        (FIRST_REG + NR_REG - 1)
169
170 /*
171  * Save number of locals.
172  */
173 prolog(n)
174 {
175         nlocals = n;
176 }
177
178 /*
179  * Structure to store information about the registers to be stored.
180  */
181 static struct s_reg {
182         char    *sr_str;        /* Name of register used. */
183         long    sr_off;         /* Offset from LB. */
184         int     sr_size;        /* Size in bytes. */
185 } a_reg[NR_REG + 1], *p_reg;
186
187 /*
188  * Initialize saving of registers.
189  */
190 i_regsave()
191 {
192         p_reg = a_reg;
193 }
194
195 /*
196  * Called for each register to be saved.
197  * Save the parameters in the struct.
198  */
199 regsave(str, off, size)
200         char    *str;
201         long    off;
202         int     size;
203 {
204         p_reg->sr_str = str;
205         p_reg->sr_off = off;
206         (p_reg++)->sr_size = size;
207         fprintf(codefile,
208                 "\t! Local %ld, size %d, to register %s\n",
209                 off, size, str
210         );
211 }
212
213 /*
214  * Generate code to save the registers.
215  */
216 f_regsave()
217 {
218         register struct s_reg   *p;
219         register int    mask;
220         register int    i;
221         register int    count;
222
223         mask = 0;
224         count = p_reg - a_reg;
225         /*
226          * For each register to be saved, set a bit in the
227          * mask corresponding to its number.
228          */
229         for (p = a_reg; p < p_reg; p++) {
230                 i = atoi(p->sr_str + 1);
231                 if (p->sr_size <= 4)
232                         mask |= (1 << i);
233                 else {
234                         mask |= (3 << i);
235                         count++;
236                 }
237         }
238         /*
239          * Now generate code to save registers.
240          */
241         fprintf(codefile, ".data2 0%o\n", mask);
242         /*
243          * Emit code to initialize parameters in registers.
244          */
245         for (p = a_reg; p < p_reg; p++)
246                 if (p->sr_off >= 0)
247                         fprintf(codefile,
248                                 "mov%c\t%ld(ap), %s\n",
249                                 p->sr_size == 4 ? 'l' : 'q',
250                                 p->sr_off,
251                                 p->sr_str
252                         );
253
254         /*
255          * Generate room for locals.
256          */
257         if (nlocals == 0)
258                 return;
259         if (nlocals == 4)
260                 fprintf(codefile,"clrl\t-(sp)\n");
261         else if (nlocals == 8)
262                 fprintf(codefile,"clrq\t-(sp)\n");
263         else
264                 fprintf(codefile,"subl2\t$%ld,sp\n",nlocals);
265
266 }
267
268 regreturn() { }
269
270 regscore(off, size, typ, score, totyp)
271         long    off;
272         int     size, typ, totyp, score;
273 {
274         register int    i = score;
275
276         /*
277          * If the offset doesn't fit in a byte, word-offset is used,
278          * which is one byte more expensive.
279          */
280         if (off > 127 || off < -128) i *= 2;
281         /*
282          * Compute cost of initialization for parameters.
283          */
284         if (off > 127) i -= 5;
285         else if (off >= 0) i -= 4;
286         /*
287          * Storing a pointer in a register sometimes saves an instruction.
288          */
289         if (typ == reg_pointer) i += score;
290         else if (typ == reg_loop) i += 5;
291         /*
292          * Now adjust for the saving of the register.
293          * But this costs no space at all.
294          */
295         return i - 1;
296 }
297
298 #endif /* REGVARS */