Pristine Ack-5.5
[Ack-5.5.git] / mach / sparc / ce / ce.src / ms_reg.c
1 /* catch register messages. BEWARE: code uses plain printf's (fprint's)
2  * to generate code. This is not compatible with the usual procedure
3  * used in the EM_table
4  */
5
6 #define CODE_EXPANDER
7 #include <em.h>
8 #include <em_reg.h>
9 #include <em_mes.h>
10 #include <stb.h>
11 #include "mach.h"
12 #include "push_pop.h"
13 #include <stdio.h>
14
15 #define MAX_NR_REGS 12
16 #define MAX_NR_FLTS MAX_NR_FLT_REGS     /* depends on using float or doubles */
17
18 #define RM_OFFSET 0
19 #define RM_SIZE 1
20 #define RM_TYPE 2
21 #define RM_COUNT 3
22
23 typedef struct reg_info {
24         int offset;
25         int size;       /* 4 or 8 */
26         int pri;
27         reg_t reg, reg2;        /* reg2 used for doubles only */
28 } reg_info;
29
30 static reg_info reg_dat[MAX_NR_REGS], flt_dat[MAX_NR_FLTS];
31
32 static int current_reg_mes[RM_COUNT+4];
33
34 static int in_reg_mes = 0;      /* boolean */
35 static int reg_mes_nr;
36 static int db_mes = 0;
37 static int db_kind = 0;
38 static int db_str = 0;
39 static int db_nul = 0;          /* boolean */
40
41 static int worst_reg_pri, worst_flt_pri; /* reset by C_prolog (to some large number) */
42 static int nr_reg_vars, nr_flt_vars;            /* dito  (both to 0) */
43
44 init_reg_man()
45 {
46   worst_reg_pri = worst_flt_pri = (unsigned)-1/2;
47   nr_reg_vars = nr_flt_vars = 0;
48 }
49
50 static reg_t my_alloc_reg(pri,loc)
51 int pri, *loc;
52 {
53         reg_t S1;
54         int i;
55
56         if ((S1 = alloc_reg_var()) == NULL)
57                 if (current_reg_mes[RM_COUNT] > worst_reg_pri) {
58                         for (i = 0; i < nr_reg_vars; i++)
59                                 if (reg_dat[i].pri <= worst_reg_pri) {
60                                         *loc = i;
61                                         S1 = reg_dat[i].reg;
62                                         break;
63                                 }
64                         worst_reg_pri = (unsigned)-1/2;
65                         for (i = 0; i < nr_reg_vars; i++)
66                                 if (reg_dat[i].pri <= worst_reg_pri)
67                                         worst_reg_pri = reg_dat[i].pri;
68                 } else
69                         return NULL;    /* SORRY, FULL HOUSE! */
70         else
71                 *loc = nr_reg_vars++;
72
73         return S1;
74 }
75
76 static reg_t my_alloc_double(pri,loc,r2)
77 int pri, *loc;
78 reg_t *r2;
79 /* implementation note: my_alloc_double only reclaims other doubles
80  * when a better candidate is given. It never reclaims floats, even if
81  * the current double is a mich better candidate.
82  */
83 {
84         reg_t S1;
85         int i;
86
87         if ((S1 = alloc_double_var(r2)) == NULL)
88                 if (current_reg_mes[RM_COUNT] > worst_flt_pri) {
89                         for (i = 0; i < nr_flt_vars; i++)
90                                 if (flt_dat[i].pri <= worst_flt_pri &&
91                                                 flt_dat[i].size == EM_DSIZE) {
92                                         *loc = i;
93                                         S1 = flt_dat[i].reg;
94                                         *r2 = flt_dat[i].reg2;
95                                         break;
96                                 }
97                         worst_flt_pri = (unsigned)-1/2;
98                         for (i = 0; i < nr_flt_vars; i++)
99                                 if (flt_dat[i].pri < worst_flt_pri)
100                                         worst_flt_pri = flt_dat[i].pri;
101                 } else
102                         return NULL;    /* SORRY, FULL HOUSE! */
103         else
104                 *loc = nr_flt_vars++;
105
106         return S1;
107 }
108
109 static reg_t my_alloc_float(pri,loc)
110 int pri, *loc;
111 /* just as for my_alloc_double, my_alloc_float never reclaims a double,
112  * even though this me be useful and easy. Sorry.
113  */
114 {
115         reg_t S1;
116         int i;
117
118         if ((S1 = alloc_float_var()) == NULL)
119                 if (current_reg_mes[RM_COUNT] > worst_flt_pri) {
120                         for (i = 0; i < nr_flt_vars; i++)
121                                 if (flt_dat[i].pri <= worst_flt_pri &&
122                                                 flt_dat[i].size == EM_WSIZE) {
123                                         *loc = i;
124                                         S1 = flt_dat[i].reg;
125                                         break;
126                                 }
127                         worst_flt_pri = (unsigned)-1/2;
128                         for (i = 0; i < nr_flt_vars; i++)
129                                 if (flt_dat[i].pri <= worst_flt_pri)
130                                         worst_flt_pri = flt_dat[i].pri;
131                 } else
132                         return NULL;    /* SORRY, FULL HOUSE! */
133         else
134                 *loc = nr_flt_vars++;
135
136         return S1;
137 }
138
139 free_all_reg_vars()
140 {
141   int i;
142
143   for (i = 0; i < nr_reg_vars; i++)
144         free_reg(reg_dat[i].reg);
145   for (i = 0; i < nr_flt_vars; i++)
146         switch (flt_dat[i].size) {
147         case EM_WSIZE: free_reg(flt_dat[i].reg); break;
148         case EM_DSIZE: free_double_reg(flt_dat[i].reg); break;
149         }
150   check_cache();
151 }
152
153 alloc_all_reg_vars()
154 {
155   int i;
156
157   for (i = 0; i < nr_reg_vars; i++)
158         forced_alloc_reg(reg_dat[i].reg);
159   for (i = 0; i < nr_flt_vars; i++)
160         switch (flt_dat[i].size) {
161         case EM_WSIZE: forced_alloc_reg(flt_dat[i].reg); break;
162         case EM_DSIZE:
163                 forced_alloc_reg(flt_dat[i].reg);
164                 forced_alloc_reg(flt_dat[i].reg2);
165                 break;
166         }
167   check_cache();
168 }
169
170 static params_to_regs()         /* copy required parameters to registers */
171 {
172   int i, j;
173
174   for (i = 0; i < nr_flt_vars; i++)
175         if (flt_dat[i].offset >= 4092) {
176                 fprint(codefile, "set   %d, %%l2\n",
177                         flt_dat[i].offset);
178                 fprint(codefile, "ld    [%%l1+%%l2], %s\n",
179                         flt_dat[i].reg);
180                 if (flt_dat[i].size == EM_DSIZE) {
181                         fprint(codefile, "set   %d, %%l2\n",
182                                 flt_dat[i].offset+4);
183                         fprint(codefile, "ld    [%%l1+%%l2], %s\n",
184                                 flt_dat[i].reg2);
185                 }
186         }
187         else if (flt_dat[i].offset > 0)
188         {
189                 fprint(codefile, "ld    [%%l1+%d], %s\n",
190                   flt_dat[i].offset, flt_dat[i].reg);
191                 if (flt_dat[i].size == EM_DSIZE)
192                         fprint(codefile, "ld    [%%l1+%d], %s\n",
193                           flt_dat[i].offset + 4, flt_dat[i].reg2);
194         }
195
196   for (i = 0; i < nr_reg_vars; i++)
197         if (reg_dat[i].offset >= 4096) {
198                 fprint(codefile, "set   %d, %s\n",
199                         reg_dat[i].offset, reg_dat[i].reg);
200                 fprint(codefile, "ld    [%%l1+%s], %s\n",
201                         reg_dat[i].reg, reg_dat[i].reg);
202         }
203         else if (reg_dat[i].offset > 0)
204                 fprint(codefile, "ld    [%%l1+%d], %s\n",
205                         reg_dat[i].offset, reg_dat[i].reg);
206 }
207
208 static cmp_flt_dat(e1, e2)
209 reg_info *e1, *e2;
210 {
211   return (e1->offset - e2->offset);
212 }
213
214 static int even(s)
215 char *s;
216 {
217   int l = strlen(s);
218   /* Assume ASCII, where even-numbered characters (0,2,4,6,8) are even. */
219   return ! (s[l-1] & 1);
220 }
221
222 static save_float_regs()
223 {
224   int i;
225   int offset;
226
227   qsort(flt_dat, nr_flt_vars, sizeof(flt_dat[0]), cmp_flt_dat);
228   for (i = 0, offset= 0; i < nr_flt_vars; i++, offset += 8)
229         if ((i+1 < nr_flt_vars &&
230                 flt_dat[i].offset == flt_dat[i+1].offset-4 &&
231                 even(flt_dat[i].reg) &&
232                 flt_dat[i].size == EM_FSIZE &&
233                 flt_dat[i+1].size == EM_FSIZE)
234                 || (flt_dat[i].size == EM_DSIZE)) {
235                 fprint(codefile, "std   %s, [%%fp + %d]\n",
236                                 flt_dat[i].reg, FLTSAV_OFFSET + offset);
237                 if (flt_dat[i].size != EM_DSIZE)
238                         ++i;
239         } else
240                 fprint(codefile, "st    %s, [%%fp + %d]\n",
241                                 flt_dat[i].reg, FLTSAV_OFFSET + offset);
242 }
243
244 load_float_regs()
245 {
246   int i;
247   int offset;
248
249   for (i = 0, offset= 0; i < nr_flt_vars; i++, offset += 8)
250         if ((i+1 < nr_flt_vars &&
251                 flt_dat[i].offset == flt_dat[i+1].offset-4 &&
252                 even(flt_dat[i].reg) &&
253                 flt_dat[i].size == EM_FSIZE &&
254                 flt_dat[i+1].size == EM_FSIZE)
255                 || (flt_dat[i].size == EM_DSIZE)) {
256                 fprint(codefile, "ldd   [%%fp + %d], %s\n",
257                                 FLTSAV_OFFSET + offset, flt_dat[i].reg);
258                 if (flt_dat[i].size != EM_DSIZE)
259                         ++i;
260         } else
261                 fprint(codefile, "ld    [%%fp + %d], %s\n",
262                                 FLTSAV_OFFSET + offset, flt_dat[i].reg);
263
264 }
265
266 void
267 C_mes_begin( ms)
268 int ms;
269 {
270 #ifdef __solaris__
271         static int inits;
272 #endif
273
274         reg_mes_nr = 0;
275         in_reg_mes = (ms == ms_reg);
276         if (ms == ms_gto) {
277                 free_all_reg_vars();
278                 nr_reg_vars = 0; nr_flt_vars = 0;
279                 fprint(codefile, "ta    3\n");
280         }
281         db_mes = (ms == ms_stb || ms == ms_std) ? ms : 0;
282 #ifdef __solaris__
283         if (db_mes && ! inits) {
284                 fprint(codefile, ".pushsection \".text\"\nBtext.text:\n.popsection\n");
285                 fprint(codefile, ".pushsection \".data\"\nBdata.data:\n.popsection\n");
286                 fprint(codefile, ".pushsection \".bss\"\nBbss.bss:\n.popsection\n");
287                 inits = 1;
288         }
289 #endif
290 }
291
292 static dump_reg_tabs();
293
294 #ifdef __solaris__
295 extern char *B_procnam;
296 #endif
297
298 void
299 C_mes_end()
300 {
301         int pos;
302         reg_t S1, S2;
303
304         if (db_mes) {
305                 db_nul = 0;
306 #ifdef __solaris__
307                 if (db_mes == ms_std) {
308                         if (db_str == 2) {
309                                 fprint(codefile, ",1f\n1:\n");
310                         }
311                         else {
312                                 fprint(codefile, ",1f-%s\n1:\n", B_procnam);
313                         }
314                 }
315 #else
316                 if (db_mes == ms_std && db_str == 2) fprint(codefile,",1f\n1:\n");
317 #endif
318                 else fprint(codefile, "\n");
319                 db_str = 0;
320                 db_mes = 0;
321                 db_kind = 0;
322         }
323         if (!in_reg_mes)        /* end of some other mes */
324                 return;
325         if (reg_mes_nr == 0) {  /* end of reg_mes's */
326                 save_float_regs();
327                 params_to_regs();
328                 if (debug)
329                         dump_reg_tabs(codefile);
330                 return;
331         }
332         if (current_reg_mes[RM_COUNT] == 0)     /* never used, so ignore */
333                 return;
334         if (current_reg_mes[RM_OFFSET] >= 0)
335                 current_reg_mes[RM_OFFSET] += EM_BSIZE;
336         if (debug)
337                 fprint(codefile, "\t\t! Got reg_mes: %d %d %d %d\n",
338                         current_reg_mes[0], current_reg_mes[1],
339                 current_reg_mes[2], current_reg_mes[3]);
340         if (current_reg_mes[RM_TYPE] == reg_float) {
341                 switch(current_reg_mes[RM_SIZE]) {
342                 case EM_WSIZE :
343                         if ((S1 = my_alloc_float(current_reg_mes[RM_COUNT], &pos))
344                                                                         == NULL)
345                                 return;
346                         break;
347                 case EM_DSIZE:
348                         if ((S1 = my_alloc_double(current_reg_mes[RM_COUNT], &pos, &S2))
349                                                                         == NULL)
350                                 return;
351                         flt_dat[pos].reg2 = S2;
352                 default: break;
353                 }
354                 flt_dat[pos].offset = current_reg_mes[RM_OFFSET];
355                 flt_dat[pos].size = current_reg_mes[RM_SIZE];
356                 flt_dat[pos].pri = current_reg_mes[RM_COUNT];
357                 flt_dat[pos].reg = S1;
358         } else {
359                 if (current_reg_mes[RM_SIZE] != EM_WSIZE)
360                         return;         /* IGNORE THESE */
361                 if ((S1 = my_alloc_reg(current_reg_mes[RM_COUNT], &pos)) == NULL)
362                         return;         /* SORRY, FULL HOUSE! */
363
364                 reg_dat[pos].offset = current_reg_mes[RM_OFFSET];
365                 reg_dat[pos].size = current_reg_mes[RM_SIZE];
366                 reg_dat[pos].pri = current_reg_mes[RM_COUNT];
367                 reg_dat[pos].reg = S1;
368         }
369 }
370
371 extern int __gdb_flag;
372
373 void
374 C_cst( l)
375 arith l;
376 {
377         static int correct_offset;
378
379         if (db_mes) {
380                 if (! db_kind) db_kind = l;
381                 if (! db_str) {
382                         switchseg( SEGTXT);
383                         if (l == N_SLINE && ! __gdb_flag) {
384                                 flush_cache();
385 #ifdef __solaris__
386                                 fprint(codefile, "call $__uX_LiB\nnop\n");
387 #else
388                                 fprint(codefile, "call ___uX_LiB\nnop\n");
389 #endif
390                         }
391 #ifdef __solaris__
392                         fprint(codefile, ".stabn 0x%lx,0", (long) l);
393 #else
394                         if (db_mes == ms_std) {
395                                 fprint(codefile, ".stabd 0x%lx,0", (long) l);
396                         }
397                         else    fprint(codefile, ".stabn 0x%lx,0", (long) l);
398 #endif
399                         db_str = 1;
400                         db_nul = 1;
401                 }
402                 else {
403                         if (correct_offset++ == -1) {
404                                 l += EM_BSIZE;
405                         }
406                         fprint(codefile, ",0x%lx", (long) l);
407                 }
408                 if (! db_nul) {
409                         correct_offset = 0;
410                         if (l == N_PSYM && __gdb_flag) {
411                                 correct_offset = -2;
412                         }
413                         fprint(codefile, ",0");
414                         db_nul = 1;
415                 }
416         }
417         if (in_reg_mes)
418                 current_reg_mes[reg_mes_nr++] = l;
419 }
420
421 void
422 C_scon(s, l)
423 register char *s;
424 register arith l;
425 {
426         if (db_mes) {
427                 fprint(codefile, ".stabs \"");
428                 while (--l) {
429                         register int c = *s++;
430
431                         if (isprint(c) && c != '"' && c != '\\')
432                                 fprint(codefile, "%c", c);
433                         else
434                                 fprint(codefile, "\\%03o", c);
435                 }
436                 fprint(codefile, "\"");
437                 db_str = 2;
438         }
439 }
440
441 void
442 C_dlb(l, off)
443 label l;
444 arith off;
445 {
446         if (db_mes) {
447                 fprint(codefile,",");
448                 fprint(codefile, DLB_FMT, (long) l);
449                 if (off) fprint(codefile,"+%ld", (long) off);
450 #ifdef __solaris__
451                 switch(db_kind) {
452                 case N_LCSYM:
453                         fprint(codefile, "-Bbss.bss");
454                         break;
455                 case N_STSYM:
456                         fprint(codefile, "-Bdata.data");
457                         break;
458                 }
459 #endif
460         }
461 }
462
463 void
464 C_dnam(l, off)
465 char *l;
466 arith off;
467 {
468         if (db_mes) {
469                 fprint(codefile,",");
470                 fprint(codefile, DNAM_FMT, l);
471                 if (off) fprint(codefile,"+%ld", (long) off);
472 #ifdef __solaris__
473                 switch(db_kind) {
474                 case N_LCSYM:
475                         fprint(codefile, "-Bbss.bss");
476                         break;
477                 case N_STSYM:
478                         fprint(codefile, "-Bdata.data");
479                         break;
480                 }
481 #endif
482         }
483 }
484
485 extern int B_procno;
486
487 void
488 C_ilb(l)
489 label l;
490 {
491         if (db_mes) {
492                 fprint(codefile,",");
493                 fprint(codefile, ILB_FMT, B_procno, (long)l);
494 #ifdef __solaris__
495                 fprint(codefile, "-Btext.text");
496 #endif
497         }
498 }
499
500 void
501 C_pnam(s)
502 char *s;
503 {
504         if (db_mes) {
505                 fprint(codefile,",");
506                 fprint(codefile, NAME_FMT, s);
507 #ifdef __solaris__
508                 fprint(codefile, "-Btext.text");
509 #endif
510         }
511 }
512
513 static
514 dump_reg_tabs(stream)
515 FILE *stream;
516 {
517   int i;
518
519   fprint(stream, "!offset\tsize\tname (%d regvars)\n", nr_reg_vars);
520   for (i = 0; i < nr_reg_vars; i++)
521         fprint(stream, "! %d\t%d\t%s\n", reg_dat[i].offset, reg_dat[i].size,
522                         reg_dat[i].reg);
523
524   fprint(stream, "!offset\tsize\tname (%d fltvars)\n", nr_flt_vars);
525   for (i = 0; i < nr_flt_vars; i++)
526         fprint(stream, "! %d\t%d\t%s\n", flt_dat[i].offset, flt_dat[i].size,
527                         flt_dat[i].reg);
528 }
529
530 reg_t find_local(offset, reg2)  /* WARNING: no size checking here! */
531 int offset;
532 reg_t *reg2;
533 {
534   int i;
535
536   if (reg2)
537         *reg2 = NULL;
538   for (i = 0; i < nr_reg_vars; i++)
539         if (reg_dat[i].offset == offset)
540                 return reg_dat[i].reg;
541
542   for (i = 0; i < nr_flt_vars; i++)
543         if (flt_dat[i].offset == offset) {
544                 if (flt_dat[i].size == EM_DSIZE)
545                         if (reg2)
546                                 *reg2 = flt_dat[i].reg2;
547                 return flt_dat[i].reg;
548         }
549   return NULL;
550 }