|
|
1.1 root 1: /* Subroutines for insn-output.c for MIL-STD-1750.
2: Copyright (C) 1994 Free Software Foundation, Inc.
3: Contributed by O.M.Kellogg, DASA ([email protected]).
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 1, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21: #ifndef FILE
22: #include <stdio.h>
23: #endif
24:
25: #define __datalbl
26: #include "config.h"
27: #include "rtl.h"
28: #include "tree.h"
29: #include "expr.h"
30: #define HAVE_cc0
31: #include "conditions.h"
32: #include "real.h"
33:
34: struct datalabel_array datalbl[DATALBL_ARRSIZ];
35: int datalbl_ndx = -1;
36: struct jumplabel_array jmplbl[JMPLBL_ARRSIZ];
37: int jmplbl_ndx = -1;
38: int label_pending = 0, program_counter = 0;
39: enum section current_section = Normal;
40: char *sectname[4] =
41: {"Normal", "Init", "Konst", "Static"};
42:
43: int
44: notice_update_cc (exp)
45: rtx exp;
46: {
47: if (GET_CODE (exp) == SET)
48: {
49: enum rtx_code src_code = GET_CODE (SET_SRC (exp));
50: /* Jumps do not alter the cc's. */
51: if (SET_DEST (exp) == pc_rtx)
52: return;
53: /* Moving register into memory doesn't alter the cc's.
54: It may invalidate the RTX's which we remember the cc's came from. */
55: if (GET_CODE (SET_DEST (exp)) == MEM)
56: {
57: if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
58: cc_status.value1 = 0;
59: if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
60: cc_status.value2 = 0;
61: return;
62: }
63: /* Function calls clobber the cc's. */
64: else if (src_code == CALL)
65: {
66: CC_STATUS_INIT;
67: return;
68: }
69: /* Emulated longword bit-ops leave cc's incorrect */
70: else if (GET_MODE (SET_DEST (exp)) == HImode ?
71: src_code == AND || src_code == IOR ||
72: src_code == XOR || src_code == NOT : 0)
73: {
74: CC_STATUS_INIT;
75: return;
76: }
77: /* Tests and compares set the cc's in predictable ways. */
78: else if (SET_DEST (exp) == cc0_rtx)
79: {
80: CC_STATUS_INIT;
81: cc_status.value1 = SET_SRC (exp);
82: return;
83: }
84: /* Anything that lands in a reg will set cc_status. */
85: else if (REG_P (SET_DEST (exp)))
86: {
87: cc_status.flags = CC_NO_OVERFLOW;
88: cc_status.value1 = SET_SRC (exp);
89: cc_status.value2 = SET_DEST (exp);
90: return;
91: }
92: else
93: {
94: CC_STATUS_INIT;
95: }
96: }
97: else if (GET_CODE (exp) == PARALLEL
98: && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
99: {
100: if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
101: return;
102: if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
103: {
104: CC_STATUS_INIT;
105: cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
106: return;
107: }
108: CC_STATUS_INIT;
109: }
110: else
111: {
112: CC_STATUS_INIT;
113: }
114: }
115:
116:
117: rtx
118: function_arg (cum, mode, type, named)
119: int cum;
120: enum machine_mode mode;
121: tree type;
122: int named;
123: {
124: int size;
125: rtx result;
126:
127: if (MUST_PASS_IN_STACK (mode, type))
128: return (rtx) 0;
129: if (mode == BLKmode)
130: size = int_size_in_bytes (type);
131: else
132: size = GET_MODE_SIZE (mode);
133: if (cum + size < 12)
134: return gen_rtx (REG, mode, cum);
135: else
136: return (rtx) 0;
137: }
138:
139:
140: #ifndef STRDUP
141: char *
142: strdup (str)
143: char *str;
144: {
145: char *p;
146: if (str == NULL)
147: return NULL;
148: if ((p = (char *) malloc (strlen (str) + 1)) == NULL)
149: {
150: fprintf (stderr, "dynamic memory exhausted");
151: abort ();
152: }
153: return strcpy (p, str);
154: }
155:
156: #endif
157:
158:
159: double
160: get_double (x)
161: rtx x;
162: {
163: union
164: {
165: double d;
166: long i[2];
167: }
168: du;
169:
170: du.i[0] = CONST_DOUBLE_LOW (x);
171: du.i[1] = CONST_DOUBLE_HIGH (x);
172: return du.d;
173: }
174:
175: char *
176: float_label (code, value)
177: char code;
178: double value;
179: {
180: int i = 1;
181: static char label[32];
182: char *p;
183:
184: label[0] = code;
185: p = label + 1;
186: sprintf (p, "%lf", value);
187: while (*p)
188: {
189: *p = (*p == '+') ? 'p' :
190: (*p == '-') ? 'm' : *p;
191: p++;
192: }
193: return strdup (label);
194: }
195:
196:
197: char *
198: movcnt_regno_adjust (rtx * op)
199: {
200: static char outstr[40];
201: int cntreg = REGNO (op[2]), cntreg_1750 = REGNO (op[0]) + 1;
202: int dstreg = REGNO (op[0]), srcreg = REGNO (op[1]);
203:
204: if (cntreg == cntreg_1750)
205: sprintf (outstr, "mov r%%0,r%%1");
206: else if (dstreg + 1 == srcreg && srcreg == cntreg + 2)
207: sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", cntreg, dstreg);
208: else if (dstreg + 1 == srcreg && srcreg < cntreg)
209: sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, cntreg);
210: else if (srcreg + 1 == cntreg && dstreg > cntreg)
211: sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, dstreg);
212: else
213: sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,%%1\n\txwr r%d,r%d",
214: cntreg, cntreg_1750, cntreg_1750, cntreg);
215: return outstr;
216: }
217:
218: char *
219: mod_regno_adjust (char *instr, rtx * op)
220: {
221: static char outstr[40];
222: char *r = (!strncmp (instr, "dvr", 3) ? "r" : "");
223: int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1;
224:
225: if (modregno_gcc == modregno_1750)
226: sprintf (outstr, "%s r%%0,%s%%2", instr, r);
227: else
228: sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
229: modregno_gcc, modregno_1750, instr, r, modregno_1750, modregno_gcc);
230: return outstr;
231: }
232:
233:
234: /* Auxiliary to `nonindirect_operand':
235: Check if op is a valid memory operand for 1750A arith./logic (non-move)
236: instructions. */
237: int
238: memop_valid (register rtx op)
239: {
240: if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode)
241: return 0;
242: switch (GET_CODE (op))
243: {
244: case MEM:
245: case MINUS:
246: case MULT:
247: case DIV:
248: return 0;
249: case PLUS:
250: if (!memop_valid (XEXP (op, 0)))
251: return 0;
252: return memop_valid (XEXP (op, 1));
253: case REG:
254: if (REGNO (op) > 0)
255: return 1;
256: return 0;
257: case CONST:
258: case CONST_INT:
259: case SYMBOL_REF:
260: case SUBREG:
261: return 1;
262: default:
263: printf ("memop_valid: code=%d\n", (int) GET_CODE (op));
264: return 1;
265: }
266: }
267:
268: /* extra predicate for recog: */
269: int
270: nonindirect_operand (register rtx op, enum machine_mode mode)
271: {
272: int retval;
273:
274: switch (GET_CODE (op))
275: {
276: case MEM:
277: retval = memop_valid (XEXP (op, 0));
278: return retval;
279: case REG:
280: return 1;
281: default:
282: if (!CONSTANT_P (op))
283: return 0;
284: }
285: return 1;
286: }
287:
288: /* predicate for the STC instruction: */
289: int
290: small_nonneg_const (register rtx op, enum machine_mode mode)
291: {
292: if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
293: return 1;
294: return 0;
295: }
296:
297: /* Decide whether to output a conditional jump as a "Jump Conditional"
298: or as a "Branch Conditional": */
299:
300: int
301: find_jmplbl (int labelnum)
302: {
303: int i, found = 0;
304:
305: for (i = 0; i <= jmplbl_ndx; i++)
306: if (labelnum == jmplbl[i].num)
307: {
308: found = 1;
309: break;
310: }
311: if (found)
312: return i;
313: return -1;
314: }
315:
316: char *
317: branch_or_jump (char *condition, int targetlabel_number)
318: {
319: static char buf[30];
320: int index;
321:
322: if ((index = find_jmplbl (targetlabel_number)) >= 0)
323: if (program_counter - jmplbl[index].pc < 128)
324: {
325: sprintf (buf, "b%s %%l0", condition);
326: return buf;
327: }
328: sprintf (buf, "jc %s,%%l0", condition);
329: return buf;
330: }
331:
332:
333:
334: /* The PRINT_OPERAND and PRINT_OPERAND_ADDRESS macros have been
335: made functions: */
336:
337: print_operand (file, x, kode)
338: FILE *file;
339: rtx x;
340: enum rtx_code kode;
341: {
342: switch (GET_CODE (x))
343: {
344: case REG:
345: fprintf (file, "%d", REGNO (x));
346: break;
347: case SYMBOL_REF:
348: fprintf (file, "%s", XSTR (x, 0));
349: break;
350: case LABEL_REF:
351: case CONST:
352: case MEM:
353: output_address (XEXP (x, 0));
354: break;
355: case CONST_DOUBLE:
356: /* {
357: double value = get_double (x);
358: char fltstr[32];
359: sprintf (fltstr, "%lf", value);
360:
361: if (kode == 'D' || kode == 'E')
362: {
363: int i, found = 0;
364: for (i = 0; i <= datalbl_ndx; i++)
365: if (strcmp (fltstr, datalbl[i].value) == 0)
366: {
367: found = 1;
368: break;
369: }
370: if (!found)
371: {
372: strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
373: datalbl[i].name = float_label (kode, value);
374: datalbl[i].size = (kode == 'E') ? 3 : 2;
375: check_section (Konst);
376: fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
377: (kode == 'E' ? "ef" : "f"), fltstr);
378: check_section (Normal);
379: }
380: }
381: else if (kode == 'F' || kode == 'G')
382: {
383: int i, found = 0;
384: for (i = 0; i <= datalbl_ndx; i++)
385: if (strcmp (fltstr, datalbl[i].value) == 0)
386: {
387: found = 1;
388: break;
389: }
390: if (!found)
391: {
392: fprintf (stderr,
393: "float value %lfnot found upon label reference\n", value);
394: strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
395: datalbl[i].name = float_label (kode, value);
396: datalbl[i].size = (kode == 'G') ? 3 : 2;
397: check_section (Konst);
398: fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
399: (kode == 'G' ? "ef" : "f"), fltstr);
400: check_section (Normal);
401: }
402: fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
403: }
404: else
405: fprintf (file, " %s ;P_O cst_dbl ", fltstr);
406: }
407: */
408: fprintf (file, "%lf", get_double (x));
409: break;
410: case CONST_INT:
411: if (kode == 'J')
412: fprintf (file, "%d", -INTVAL (x));
413: else if (INTVAL (x) > 0x7FFF)
414: fprintf (file, "%d ; range correction (val>0x7FFF) applied",
415: INTVAL (x) - 0x10000);
416: else
417: fprintf (file, "%d", INTVAL (x));
418: break;
419: case CODE_LABEL:
420: fprintf (file, "L%d", XINT (x, 3));
421: break;
422: case CALL:
423: fprintf (file, "CALL nargs=%d, func is either '%s' or '%s'",
424: XEXP (x, 1), XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1));
425: break;
426: case PLUS:
427: {
428: rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1);
429: int op0code = GET_CODE (op0), op1code = GET_CODE (op1);
430: if (op1code == CONST_INT)
431: switch (op0code)
432: {
433: case REG:
434: fprintf (file, "%d,r%d ; p_o_PLUS for REG and CONST",
435: INTVAL (op1), REGNO (op0));
436: break;
437: case SYMBOL_REF:
438: fprintf (file, "%d+%s", INTVAL (op1), XSTR (op0, 0));
439: break;
440: case MEM:
441: fprintf (file, "%d,[mem:", INTVAL (op1));
442: output_address (XEXP (op0, 0));
443: fprintf (file, "] ;P_O plus");
444: break;
445: default:
446: fprintf (file, "p_o_PLUS UFO, code=%d, with CONST=%d",
447: (int) op0code, INTVAL (op1));
448: }
449: else if (op1code == SYMBOL_REF && op0code == REG)
450: fprintf (file, "%s,r%d ; P_O: (plus reg sym)",
451: XSTR (op1, 0), REGNO (op0));
452: else
453: fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
454: }
455: break;
456: default:
457: fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
458: }
459: }
460:
461: print_operand_address (file, addr)
462: FILE *file;
463: rtx addr;
464: {
465: switch (GET_CODE (addr))
466: {
467: case REG:
468: fprintf (file, "0,r%d ; P_O_A", REGNO (addr));
469: break;
470: case PLUS:
471: {
472: register rtx x = XEXP (addr, 0), y = XEXP (addr, 1);
473: switch (GET_CODE (x))
474: {
475: case REG:
476: switch (GET_CODE (y))
477: {
478: case CONST:
479: output_address (XEXP (y, 0));
480: fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
481: break;
482: case CONST_INT:
483: fprintf (file, "%d,r%d", INTVAL (y), REGNO (x));
484: break;
485: case SYMBOL_REF:
486: fprintf (file, "%s,r%d ; P_O_A reg + sym",
487: XSTR (y, 0), REGNO (x));
488: break;
489: default:
490: fprintf (file, "[P_O_A reg%d+UFO code=%d]",
491: REGNO (x), GET_CODE (y));
492: }
493: break;
494: case LABEL_REF:
495: case SYMBOL_REF:
496: switch (GET_CODE (y))
497: {
498: case CONST_INT:
499: fprintf (file, "%d+%s", INTVAL (y), XSTR (x, 0));
500: break;
501: case REG:
502: fprintf (file, "%s,r%d ;P_O_A sym + reg",
503: XSTR (x, 0), REGNO (y));
504: break;
505: default:
506: fprintf (file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]",
507: XSTR (x, 0), GET_CODE (y));
508: }
509: break;
510: case CONST:
511: output_address (XEXP (x, 0));
512: if (GET_CODE (y) == REG)
513: fprintf (file, ",r%d ;P_O_A const + reg", REGNO (x));
514: else
515: fprintf (file, "P_O_A const+UFO code(y)=%d]", GET_CODE (y));
516: break;
517: case MEM:
518: output_address (y);
519: fprintf (file, ",[mem:");
520: output_address (XEXP (x, 0));
521: fprintf (file, "] ;P_O_A plus");
522: break;
523: default:
524: fprintf (file, "P_O_A plus op1_UFO[code1=%d,code2=%d]",
525: GET_CODE (x), GET_CODE (y));
526: }
527: }
528: break;
529: case CONST_INT:
530: if (INTVAL (addr) < 0x10000 && INTVAL (addr) >= -0x10000)
531: fprintf (file, "%d ; p_o_a const addr?!", INTVAL (addr));
532: else
533: {
534: fprintf (file, "[p_o_a=ILLEGAL_CONST]");
535: output_addr_const (file, addr);
536: }
537: break;
538: case LABEL_REF:
539: case SYMBOL_REF:
540: fprintf (file, "%s", XSTR (addr, 0));
541: break;
542: case MEM:
543: fprintf (file, "[memUFO:");
544: output_address (XEXP (addr, 0));
545: fprintf (file, "]");
546: break;
547: case CONST:
548: output_address (XEXP (addr, 0));
549: fprintf (file, " ;P_O_A const");
550: break;
551: default:
552: fprintf (file, " p_o_a UFO, code=%d val=0x%x",
553: (int) GET_CODE (addr), INTVAL (addr));
554: break;
555: }
556: }
557:
558:
559: /*
560: ASM_FILE_END(file)
561: FILE *file;
562: {
563: if (datalbl_ndx >= 0) {
564: int i, cum_size=0;
565: fprintf(file,"\n\tstatic\ninit_srel\n");
566: for (i = 0; i <= datalbl_ndx; i++) {
567: if (datalbl[i].name == NULL)
568: {
569: fprintf (stderr, "asm_file_end intern err (datalbl)\n");
570: exit (0);
571: }
572: fprintf(file,"%s\t block %d\n",
573: datalbl[i].name,datalbl[i].size);
574: cum_size += datalbl[i].size;
575: }
576: fprintf(file,"\n\tinit\n");
577: fprintf(file,"\tLIM R0,init_srel ;dst\n");
578: fprintf(file,"\tLIM R1,%d ;cnt\n",cum_size);
579: fprintf(file,"\tLIM R2,K%s ;src\n",datalbl[0].name);
580: fprintf(file,"\tMOV R0,R2\n");
581: fprintf(file,"\n\tnormal\n");
582: datalbl_ndx = -1;
583: for (i = 0; i < DATALBL_ARRSIZ; i++)
584: datalbl[i].size = 0;
585: }
586: fprintf(file,"\n\tend\n");
587: }
588: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.