|
|
1.1 root 1: /* Subroutines for insn-output.c for Motorola 68000 family.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
1.1.1.7 ! root 6: GNU CC is free software; you can redistribute it and/or modify
! 7: it under the terms of the GNU General Public License as published by
! 8: the Free Software Foundation; either version 1, or (at your option)
! 9: any later version.
! 10:
1.1 root 11: GNU CC is distributed in the hope that it will be useful,
1.1.1.7 ! root 12: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 14: GNU General Public License for more details.
! 15:
! 16: You should have received a copy of the GNU General Public License
! 17: along with GNU CC; see the file COPYING. If not, write to
! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
1.1 root 19:
20:
21: /* Some output-actions in m68k.md need these. */
22: #include <stdio.h>
23: extern FILE *asm_out_file;
24:
1.1.1.2 root 25: /* Index into this array by (register number >> 3) to find the
26: smallest class which contains that register. */
27: enum reg_class regno_reg_class[]
28: = { DATA_REGS, ADDR_REGS, FP_REGS,
29: LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
30:
1.1 root 31: static rtx find_addr_reg ();
32:
33: char *
34: output_btst (operands, countop, dataop, insn, signpos)
35: rtx *operands;
36: rtx countop, dataop;
37: rtx insn;
38: int signpos;
39: {
40: operands[0] = countop;
41: operands[1] = dataop;
42: if (GET_CODE (countop) == CONST_INT)
43: {
44: register int count = INTVAL (countop);
45: if (count == signpos)
46: cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
47: else
48: cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
49:
50: if (count == 31
1.1.1.4 root 51: && next_insns_test_no_inequality (insn))
1.1 root 52: return "tst%.l %1";
53: if (count == 15
1.1.1.4 root 54: && next_insns_test_no_inequality (insn))
1.1 root 55: return "tst%.w %1";
56: if (count == 7
1.1.1.4 root 57: && next_insns_test_no_inequality (insn))
1.1 root 58: return "tst%.b %1";
59:
60: cc_status.flags = CC_NOT_NEGATIVE;
61: }
62: return "btst %0,%1";
63: }
64:
65: /* Return the best assembler insn template
66: for moving operands[1] into operands[0] as a fullword. */
67:
68: static char *
69: singlemove_string (operands)
70: rtx *operands;
71: {
1.1.1.2 root 72: if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
73: return "fpmoves %1,%0";
1.1 root 74: if (operands[1] != const0_rtx)
75: return "move%.l %1,%0";
76: if (! ADDRESS_REG_P (operands[0]))
77: return "clr%.l %0";
78: return "sub%.l %0,%0";
79: }
80:
81: /* Output assembler code to perform a doubleword move insn
82: with operands OPERANDS. */
83:
84: char *
85: output_move_double (operands)
86: rtx *operands;
87: {
88: enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
89: rtx latehalf[2];
90: rtx addreg0 = 0, addreg1 = 0;
91:
92: /* First classify both operands. */
93:
94: if (REG_P (operands[0]))
95: optype0 = REGOP;
96: else if (offsetable_memref_p (operands[0]))
97: optype0 = OFFSOP;
98: else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
99: optype0 = POPOP;
100: else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
101: optype0 = PUSHOP;
102: else if (GET_CODE (operands[0]) == MEM)
103: optype0 = MEMOP;
104: else
105: optype0 = RNDOP;
106:
107: if (REG_P (operands[1]))
108: optype1 = REGOP;
109: else if (CONSTANT_P (operands[1])
110: || GET_CODE (operands[1]) == CONST_DOUBLE)
111: optype1 = CNSTOP;
112: else if (offsetable_memref_p (operands[1]))
113: optype1 = OFFSOP;
114: else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
115: optype1 = POPOP;
116: else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
117: optype1 = PUSHOP;
118: else if (GET_CODE (operands[1]) == MEM)
119: optype1 = MEMOP;
120: else
121: optype1 = RNDOP;
122:
123: /* Check for the cases that the operand constraints are not
124: supposed to allow to happen. Abort if we get one,
125: because generating code for these cases is painful. */
126:
127: if (optype0 == RNDOP || optype1 == RNDOP)
128: abort ();
129:
130: /* If one operand is decrementing and one is incrementing
131: decrement the former register explicitly
132: and change that operand into ordinary indexing. */
133:
134: if (optype0 == PUSHOP && optype1 == POPOP)
135: {
136: operands[0] = XEXP (XEXP (operands[0], 0), 0);
137: output_asm_insn ("subq%.l %#8,%0", operands);
138: operands[0] = gen_rtx (MEM, DImode, operands[0]);
139: optype0 = OFFSOP;
140: }
141: if (optype0 == POPOP && optype1 == PUSHOP)
142: {
143: operands[1] = XEXP (XEXP (operands[1], 0), 0);
144: output_asm_insn ("subq%.l %#8,%1", operands);
145: operands[1] = gen_rtx (MEM, DImode, operands[1]);
146: optype1 = OFFSOP;
147: }
148:
149: /* If an operand is an unoffsettable memory ref, find a register
150: we can increment temporarily to make it refer to the second word. */
151:
152: if (optype0 == MEMOP)
153: addreg0 = find_addr_reg (operands[0]);
154:
155: if (optype1 == MEMOP)
156: addreg1 = find_addr_reg (operands[1]);
157:
158: /* Ok, we can do one word at a time.
159: Normally we do the low-numbered word first,
160: but if either operand is autodecrementing then we
161: do the high-numbered word first.
162:
163: In either case, set up in LATEHALF the operands to use
164: for the high-numbered word and in some cases alter the
165: operands in OPERANDS to be suitable for the low-numbered word. */
166:
167: if (optype0 == REGOP)
168: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
169: else if (optype0 == OFFSOP)
170: latehalf[0] = adj_offsetable_operand (operands[0], 4);
171: else
172: latehalf[0] = operands[0];
173:
174: if (optype1 == REGOP)
175: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
176: else if (optype1 == OFFSOP)
177: latehalf[1] = adj_offsetable_operand (operands[1], 4);
178: else if (optype1 == CNSTOP)
179: {
180: if (CONSTANT_P (operands[1]))
181: latehalf[1] = const0_rtx;
182: else if (GET_CODE (operands[1]) == CONST_DOUBLE)
183: {
1.1.1.6 root 184: latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
185: CONST_DOUBLE_HIGH (operands[1]));
186: operands[1] = gen_rtx (CONST_INT, VOIDmode,
187: CONST_DOUBLE_LOW (operands[1]));
1.1 root 188: }
189: }
190: else
191: latehalf[1] = operands[1];
192:
193: /* If insn is effectively movd N(sp),-(sp) then we will do the
194: high word first. We should use the adjusted operand 1 (which is N+4(sp))
195: for the low word as well, to compensate for the first decrement of sp. */
196: if (optype0 == PUSHOP
197: && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1.1.1.3 root 198: && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
1.1 root 199: operands[1] = latehalf[1];
200:
201: /* If one or both operands autodecrementing,
202: do the two words, high-numbered first. */
203:
204: /* Likewise, the first move would clobber the source of the second one,
205: do them in the other order. This happens only for registers;
206: such overlap can't happen in memory unless the user explicitly
207: sets it up, and that is an undefined circumstance. */
208:
209: if (optype0 == PUSHOP || optype1 == PUSHOP
210: || (optype0 == REGOP && optype1 == REGOP
211: && REGNO (operands[0]) == REGNO (latehalf[1])))
212: {
213: /* Make any unoffsetable addresses point at high-numbered word. */
214: if (addreg0)
215: output_asm_insn ("addql %#4,%0", &addreg0);
216: if (addreg1)
217: output_asm_insn ("addql %#4,%0", &addreg1);
218:
219: /* Do that word. */
220: output_asm_insn (singlemove_string (latehalf), latehalf);
221:
222: /* Undo the adds we just did. */
223: if (addreg0)
224: output_asm_insn ("subql %#4,%0", &addreg0);
225: if (addreg1)
226: output_asm_insn ("subql %#4,%0", &addreg1);
227:
228: /* Do low-numbered word. */
229: return singlemove_string (operands);
230: }
231:
232: /* Normal case: do the two words, low-numbered first. */
233:
234: output_asm_insn (singlemove_string (operands), operands);
235:
236: /* Make any unoffsetable addresses point at high-numbered word. */
237: if (addreg0)
238: output_asm_insn ("addql %#4,%0", &addreg0);
239: if (addreg1)
240: output_asm_insn ("addql %#4,%0", &addreg1);
241:
242: /* Do that word. */
243: output_asm_insn (singlemove_string (latehalf), latehalf);
244:
245: /* Undo the adds we just did. */
246: if (addreg0)
247: output_asm_insn ("subql %#4,%0", &addreg0);
248: if (addreg1)
249: output_asm_insn ("subql %#4,%0", &addreg1);
250:
251: return "";
252: }
253:
254: /* Return a REG that occurs in ADDR with coefficient 1.
255: ADDR can be effectively incremented by incrementing REG. */
256:
257: static rtx
258: find_addr_reg (addr)
259: rtx addr;
260: {
261: while (GET_CODE (addr) == PLUS)
262: {
263: if (GET_CODE (XEXP (addr, 0)) == REG)
264: addr = XEXP (addr, 0);
265: if (GET_CODE (XEXP (addr, 1)) == REG)
266: addr = XEXP (addr, 1);
267: if (CONSTANT_P (XEXP (addr, 0)))
268: addr = XEXP (addr, 1);
269: if (CONSTANT_P (XEXP (addr, 1)))
270: addr = XEXP (addr, 0);
271: }
272: if (GET_CODE (addr) == REG)
273: return addr;
274: return 0;
275: }
276:
277: char *
278: output_move_const_double (operands)
279: rtx *operands;
280: {
1.1.1.2 root 281: if (TARGET_FPA && FPA_REG_P(operands[0]))
282: {
1.1.1.5 root 283: int code = standard_sun_fpa_constant_p (operands[1]);
1.1 root 284:
1.1.1.2 root 285: if (code != 0)
286: {
287: static char buf[40];
288:
289: sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
290: return buf;
291: }
292: return "fpmove%.d %1,%0";
293: }
294: else
1.1 root 295: {
1.1.1.2 root 296: int code = standard_68881_constant_p (operands[1]);
1.1 root 297:
1.1.1.2 root 298: if (code != 0)
299: {
300: static char buf[40];
301:
302: sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
303: return buf;
304: }
305: return "fmove%.d %1,%0";
1.1 root 306: }
307: }
308:
309: char *
310: output_move_const_single (operands)
311: rtx *operands;
312: {
1.1.1.2 root 313: if (TARGET_FPA)
314: {
1.1.1.5 root 315: int code = standard_sun_fpa_constant_p (operands[1]);
1.1.1.2 root 316:
317: if (code != 0)
318: {
319: static char buf[40];
1.1 root 320:
1.1.1.5 root 321: sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
1.1.1.2 root 322: return buf;
323: }
324: return "fpmove%.s %1,%0";
325: }
326: else
1.1 root 327: {
1.1.1.2 root 328: int code = standard_68881_constant_p (operands[1]);
329:
330: if (code != 0)
331: {
332: static char buf[40];
1.1 root 333:
1.1.1.2 root 334: sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
335: return buf;
336: }
337: return "fmove%.s %f1,%0";
1.1 root 338: }
339: }
340:
341: /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
342: from the "fmovecr" instruction.
343: The value, anded with 0xff, gives the code to use in fmovecr
344: to get the desired constant. */
345:
346: int
347: standard_68881_constant_p (x)
348: rtx x;
349: {
350: union {double d; int i[2];} u;
351: register double d;
1.1.1.6 root 352: u.i[0] = CONST_DOUBLE_LOW (x);
353: u.i[1] = CONST_DOUBLE_HIGH (x);
1.1 root 354: d = u.d;
355:
356: if (d == 0)
357: return 0x0f;
358: /* Note: there are various other constants available
359: but it is a nuisance to put in their values here. */
360: if (d == 1)
361: return 0x32;
362: if (d == 10)
363: return 0x33;
364: if (d == 100)
365: return 0x34;
366: if (d == 10000)
367: return 0x35;
368: if (d == 1e8)
369: return 0x36;
370: if (GET_MODE (x) == SFmode)
371: return 0;
372: if (d == 1e16)
373: return 0x37;
374: /* larger powers of ten in the constants ram are not used
375: because they are not equal to a `double' C constant. */
376: return 0;
377: }
1.1.1.2 root 378:
379: /* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
380: from the Sun FPA's constant RAM.
381: The value returned, anded with 0x1ff, gives the code to use in fpmove
382: to get the desired constant. */
383: #define S_E (2.718281745910644531)
384: #define D_E (2.718281828459045091)
385: #define S_PI (3.141592741012573242)
386: #define D_PI (3.141592653589793116)
387: #define S_SQRT2 (1.414213538169860840)
388: #define D_SQRT2 (1.414213562373095145)
389: #define S_LOG2ofE (1.442695021629333496)
390: #define D_LOG2ofE (1.442695040888963387)
391: #define S_LOG2of10 (3.321928024291992188)
392: #define D_LOG2of10 (3.321928024887362182)
393: #define S_LOGEof2 (0.6931471824645996094)
394: #define D_LOGEof2 (0.6931471805599452862)
395: #define S_LOGEof10 (2.302585124969482442)
396: #define D_LOGEof10 (2.302585092994045901)
397: #define S_LOG10of2 (0.3010300099849700928)
398: #define D_LOG10of2 (0.3010299956639811980)
399: #define S_LOG10ofE (0.4342944920063018799)
400: #define D_LOG10ofE (0.4342944819032518167)
401:
402: int
1.1.1.5 root 403: standard_sun_fpa_constant_p (x)
1.1.1.2 root 404: rtx x;
405: {
406: union {double d; int i[2];} u;
407: register double d;
1.1.1.6 root 408: u.i[0] = CONST_DOUBLE_LOW (x);
409: u.i[1] = CONST_DOUBLE_HIGH (x);
1.1.1.2 root 410: d = u.d;
411:
412: if (d == 0.0)
413: return 0x200; /* 0 once 0x1ff is anded with it */
414: if (d == 1.0)
415: return 0xe;
416: if (d == 0.5)
417: return 0xf;
418: if (d == -1.0)
419: return 0x10;
420: if (d == 2.0)
421: return 0x11;
422: if (d == 3.0)
423: return 0xB1;
424: if (d == 4.0)
425: return 0x12;
426: if (d == 8.0)
427: return 0x13;
428: if (d == 0.25)
429: return 0x15;
430: if (d == 0.125)
431: return 0x16;
432: if (d == 10.0)
433: return 0x17;
434: if (d == -(1.0/2.0))
435: return 0x2E;
436:
437: /*
438: * Stuff that looks different if it's single or double
439: */
440: if (GET_MODE(x) == SFmode)
441: {
442: if (d == S_E)
443: return 0x8;
444: if (d == (2*S_PI))
445: return 0x9;
446: if (d == S_PI)
447: return 0xA;
448: if (d == (S_PI / 2.0))
449: return 0xB;
450: if (d == S_SQRT2)
451: return 0xC;
452: if (d == (1.0 / S_SQRT2))
453: return 0xD;
454: /* Large powers of 10 in the constant
455: ram are not used because they are
456: not equal to a C double constant */
457: if (d == -(S_PI / 2.0))
458: return 0x27;
459: if (d == S_LOG2ofE)
460: return 0x28;
461: if (d == S_LOG2of10)
462: return 0x29;
463: if (d == S_LOGEof2)
464: return 0x2A;
465: if (d == S_LOGEof10)
466: return 0x2B;
467: if (d == S_LOG10of2)
468: return 0x2C;
469: if (d == S_LOG10ofE)
470: return 0x2D;
471: }
472: else
473: {
474: if (d == D_E)
475: return 0x8;
476: if (d == (2*D_PI))
477: return 0x9;
478: if (d == D_PI)
479: return 0xA;
480: if (d == (D_PI / 2.0))
481: return 0xB;
482: if (d == D_SQRT2)
483: return 0xC;
484: if (d == (1.0 / D_SQRT2))
485: return 0xD;
486: /* Large powers of 10 in the constant
487: ram are not used because they are
488: not equal to a C double constant */
489: if (d == -(D_PI / 2.0))
490: return 0x27;
491: if (d == D_LOG2ofE)
492: return 0x28;
493: if (d == D_LOG2of10)
494: return 0x29;
495: if (d == D_LOGEof2)
496: return 0x2A;
497: if (d == D_LOGEof10)
498: return 0x2B;
499: if (d == D_LOG10of2)
500: return 0x2C;
501: if (d == D_LOG10ofE)
502: return 0x2D;
503: }
504: return 0x0;
505: }
506:
507: #undef S_E
508: #undef D_E
509: #undef S_PI
510: #undef D_PI
511: #undef S_SQRT2
512: #undef D_SQRT2
513: #undef S_LOG2ofE
514: #undef D_LOG2ofE
515: #undef S_LOG2of10
516: #undef D_LOG2of10
517: #undef S_LOGEof2
518: #undef D_LOGEof2
519: #undef S_LOGEof10
520: #undef D_LOGEof10
521: #undef S_LOG10of2
522: #undef D_LOG10of2
523: #undef S_LOG10ofE
524: #undef D_LOG10ofE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.