1 /* Subroutines for assembler code output on the NS32000.
2 Copyright (C) 1988, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
4 This file is part of GNU CC.
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 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
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.
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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Some output-actions in ns32k.md need these. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "insn-flags.h"
32 #include "insn-attr.h"
35 int ns32k_num_files = 0;
42 fprintf (stderr, s, s1, s2);
45 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
48 hard_regno_mode_ok (regno, mode)
50 enum machine_mode mode;
61 if (regno < 8 || regno == 16 || regno == 17)
67 if (regno < 8 && (regno & 1) == 0)
112 /* Used to abort here, but simply saying "no" handles TImode
117 /* ADDRESS_COST calls this. This function is not optimal
118 for the 32032 & 32332, but it probably is better than
122 calc_address_cost (operand)
128 if (GET_CODE (operand) == MEM)
130 if (GET_CODE (operand) == MULT)
133 if (GET_CODE (operand) == REG)
134 cost += 1; /* not really, but the documentation
135 says different amount of registers
136 shouldn't return the same costs */
138 switch (GET_CODE (operand))
152 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
154 cost += calc_address_cost (XEXP (operand, i));
162 /* Return the register class of a scratch register needed to copy IN into
163 or out of a register in CLASS in MODE. If it can be done directly,
164 NO_REGS is returned. */
167 secondary_reload_class (class, mode, in)
168 enum reg_class class;
169 enum machine_mode mode;
172 int regno = true_regnum (in);
174 if (regno >= FIRST_PSEUDO_REGISTER)
177 /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
179 if (class == GENERAL_REGS || (regno >= 0 && regno < 8))
182 /* Constants, memory, and FP registers can go into FP registers. */
183 if ((regno == -1 || (regno >= 8 && regno < 16)) && (class == FLOAT_REGS))
186 #if 0 /* This isn't strictly true (can't move fp to sp or vice versa),
187 so it's cleaner to use PREFERRED_RELOAD_CLASS
188 to make the right things happen. */
189 if (regno >= 16 && class == GEN_AND_MEM_REGS)
193 /* Otherwise, we need GENERAL_REGS. */
196 /* Generate the rtx that comes from an address expression in the md file */
197 /* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
198 scale must be converted from an exponent (from ASHIFT) to a
199 multiplier (for MULT). */
201 gen_indexed_expr (base, index, scale)
202 rtx base, index, scale;
206 /* This generates an invalid addressing mode, if BASE is
207 fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
208 if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
209 base = gen_rtx (MEM, SImode, base);
210 addr = gen_rtx (MULT, SImode, index,
211 GEN_INT (1 << INTVAL (scale)));
212 addr = gen_rtx (PLUS, SImode, base, addr);
216 /* Return 1 if OP is a valid operand of mode MODE. This
217 predicate rejects operands which do not have a mode
218 (such as CONST_INT which are VOIDmode). */
220 reg_or_mem_operand (op, mode)
222 enum machine_mode mode;
224 return (GET_MODE (op) == mode
225 && (GET_CODE (op) == REG
226 || GET_CODE (op) == SUBREG
227 || GET_CODE (op) == MEM));
230 /* Split one or more DImode RTL references into pairs of SImode
231 references. The RTL can be REG, offsettable MEM, integer constant, or
232 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
233 split and "num" is its length. lo_half and hi_half are output arrays
234 that parallel "operands". */
237 split_di (operands, num, lo_half, hi_half)
240 rtx lo_half[], hi_half[];
244 if (GET_CODE (operands[num]) == REG)
246 lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
247 hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
249 else if (CONSTANT_P (operands[num]))
251 split_double (operands[num], &lo_half[num], &hi_half[num]);
253 else if (offsettable_memref_p (operands[num]))
255 lo_half[num] = operands[num];
256 hi_half[num] = adj_offsettable_operand (operands[num], 4);
263 /* Return the best assembler insn template
264 for moving operands[1] into operands[0] as a fullword. */
267 singlemove_string (operands)
270 if (GET_CODE (operands[1]) == CONST_INT
271 && INTVAL (operands[1]) <= 7
272 && INTVAL (operands[1]) >= -8)
273 return "movqd %1,%0";
278 output_move_double (operands)
281 enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1;
284 /* First classify both operands. */
286 if (REG_P (operands[0]))
288 else if (offsettable_memref_p (operands[0]))
290 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
295 if (REG_P (operands[1]))
297 else if (CONSTANT_P (operands[1])
298 || GET_CODE (operands[1]) == CONST_DOUBLE)
300 else if (offsettable_memref_p (operands[1]))
302 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
307 /* Check for the cases that the operand constraints are not
308 supposed to allow to happen. Abort if we get one,
309 because generating code for these cases is painful. */
311 if (optype0 == RNDOP || optype1 == RNDOP)
314 /* Ok, we can do one word at a time.
315 Normally we do the low-numbered word first,
316 but if either operand is autodecrementing then we
317 do the high-numbered word first.
319 In either case, set up in LATEHALF the operands to use
320 for the high-numbered word and in some cases alter the
321 operands in OPERANDS to be suitable for the low-numbered word. */
323 if (optype0 == REGOP)
324 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
325 else if (optype0 == OFFSOP)
326 latehalf[0] = adj_offsettable_operand (operands[0], 4);
328 latehalf[0] = operands[0];
330 if (optype1 == REGOP)
331 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
332 else if (optype1 == OFFSOP)
333 latehalf[1] = adj_offsettable_operand (operands[1], 4);
334 else if (optype1 == CNSTOP)
335 split_double (operands[1], &operands[1], &latehalf[1]);
337 latehalf[1] = operands[1];
339 /* If insn is effectively movd N(sp),tos then we will do the
340 high word first. We should use the adjusted operand 1 (which is N+4(sp))
341 for the low word as well, to compensate for the first decrement of sp.
342 Given this, it doesn't matter which half we do "first". */
343 if (optype0 == PUSHOP
344 && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
345 && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
346 operands[1] = latehalf[1];
348 /* If one or both operands autodecrementing,
349 do the two words, high-numbered first. */
350 else if (optype0 == PUSHOP || optype1 == PUSHOP)
352 output_asm_insn (singlemove_string (latehalf), latehalf);
353 return singlemove_string (operands);
356 /* If the first move would clobber the source of the second one,
357 do them in the other order. */
359 /* Overlapping registers. */
360 if (optype0 == REGOP && optype1 == REGOP
361 && REGNO (operands[0]) == REGNO (latehalf[1]))
364 output_asm_insn (singlemove_string (latehalf), latehalf);
365 /* Do low-numbered word. */
366 return singlemove_string (operands);
368 /* Loading into a register which overlaps a register used in the address. */
369 else if (optype0 == REGOP && optype1 != REGOP
370 && reg_overlap_mentioned_p (operands[0], operands[1]))
372 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
373 && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
375 /* If both halves of dest are used in the src memory address,
376 load the destination address into the low reg (operands[0]).
377 Then it works to load latehalf first. */
379 xops[0] = XEXP (operands[1], 0);
380 xops[1] = operands[0];
381 output_asm_insn ("addr %a0,%1", xops);
382 operands[1] = gen_rtx (MEM, DImode, operands[0]);
383 latehalf[1] = adj_offsettable_operand (operands[1], 4);
384 /* The first half has the overlap, Do the late half first. */
385 output_asm_insn (singlemove_string (latehalf), latehalf);
387 return singlemove_string (operands);
389 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
391 /* The first half has the overlap, Do the late half first. */
392 output_asm_insn (singlemove_string (latehalf), latehalf);
394 return singlemove_string (operands);
398 /* Normal case. Do the two words, low-numbered first. */
400 output_asm_insn (singlemove_string (operands), operands);
402 operands[0] = latehalf[0];
403 operands[1] = latehalf[1];
404 return singlemove_string (operands);
408 check_reg (oper, reg)
416 switch (GET_CODE(oper))
419 return (REGNO(oper) == reg) ? 1 : 0;
421 return check_reg(XEXP(oper, 0), reg);
424 return check_reg(XEXP(oper, 0), reg) || check_reg(XEXP(oper, 1), reg);
429 /* Returns 1 if OP contains a global symbol reference */
432 global_symbolic_reference_mentioned_p (op, f)
439 if (GET_CODE (op) == SYMBOL_REF)
441 if (! SYMBOL_REF_FLAG (op))
446 else if (f && GET_CODE (op) != CONST)
449 fmt = GET_RTX_FORMAT (GET_CODE (op));
450 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
456 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
457 if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0))
460 else if (fmt[i] == 'e'
461 && global_symbolic_reference_mentioned_p (XEXP (op, i), 0))
469 /* PRINT_OPERAND is defined to call this function,
470 which is easier to debug than putting all the code in
471 a macro definition in ns32k.h. */
474 print_operand (file, x, code)
480 PUT_IMMEDIATE_PREFIX (file);
481 else if (code == '?')
482 PUT_EXTERNAL_PREFIX (file);
483 else if (GET_CODE (x) == REG)
484 fprintf (file, "%s", reg_names[REGNO (x)]);
485 else if (GET_CODE (x) == MEM)
487 rtx tmp = XEXP (x, 0);
488 output_address (XEXP (x, 0));
490 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
492 if (GET_MODE (x) == DFmode)
494 union { double d; int i[2]; } u;
495 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
496 PUT_IMMEDIATE_PREFIX(file);
498 /* Sequent likes it's floating point constants as integers */
499 fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
502 fprintf (file, "0f%.20e", u.d);
504 fprintf (file, "0d%.20e", u.d);
510 union { double d; int i[2]; } u;
511 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
512 PUT_IMMEDIATE_PREFIX (file);
514 /* We have no way of winning if we can't get the bits
515 for a sequent floating point number. */
516 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
520 union { float f; long l; } uu;
522 fprintf (file, "0Fx%08x", uu.l);
525 fprintf (file, "0f%.20e", u.d);
531 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
532 if (GET_CODE (x) == CONST_INT)
534 PUT_IMMEDIATE_PREFIX (file);
535 output_addr_const (file, x);
539 /* PRINT_OPERAND_ADDRESS is defined to call this function,
540 which is easier to debug than putting all the code in
541 a macro definition in ns32k.h . */
543 /* Completely rewritten to get this to work with Gas for PC532 Mach.
544 This function didn't work and I just wasn't able (nor very willing) to
545 figure out how it worked.
546 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
548 print_operand_address (file, addr)
552 static char scales[] = { 'b', 'w', 'd', 0, 'q', };
553 rtx offset, base, indexexp, tmp;
557 if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
559 fprintf (file, "tos");
568 if (GET_CODE (addr) == PLUS)
570 if (GET_CODE (XEXP (addr, 0)) == PLUS)
572 tmp = XEXP (addr, 1);
573 addr = XEXP (addr, 0);
578 addr = XEXP (addr,1);
586 switch (GET_CODE (tmp))
620 if (flag_pic && ! CONSTANT_POOL_ADDRESS_P (tmp)
621 && ! SYMBOL_REF_FLAG (tmp))
633 if (flag_pic && GET_CODE (tmp) == CONST)
637 if (GET_CODE (tmp1) != PLUS)
641 if (GET_CODE (sym) != SYMBOL_REF)
648 if (GET_CODE (sym) == SYMBOL_REF)
650 if (GET_CODE (off) != CONST_INT)
653 if (CONSTANT_POOL_ADDRESS_P (sym)
654 || SYMBOL_REF_FLAG (sym))
656 SYMBOL_REF_FLAG (tmp) = 1;
680 offset = gen_rtx (PLUS, SImode, tmp, offset);
692 #ifndef INDEX_RATHER_THAN_BASE
693 && (flag_pic || TARGET_HIMEM)
694 && GET_CODE (base) != SYMBOL_REF
695 && GET_CODE (offset) != CONST_INT
697 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
699 && !indexexp && GET_CODE (base) == REG
700 && REG_OK_FOR_INDEX_P (base))
706 /* now, offset, base and indexexp are set */
707 #ifndef BASE_REG_NEEDED
710 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
711 if (GET_CODE (offset) == CONST_INT)
713 PUT_ABSOLUTE_PREFIX (file);
717 output_addr_const (file, offset);
718 if (base) /* base can be (REG ...) or (MEM ...) */
719 switch (GET_CODE (base))
721 /* now we must output base. Possible alternatives are:
725 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
726 (disp(fp)) (MEM ...) just before possible [rX:y]
731 fprintf (file, "(%s)", reg_names[REGNO (base)]);
738 output_addr_const (file, base);
739 fprintf (file, "(sb))");
747 if (GET_CODE (addr) == PLUS)
749 if (GET_CODE (XEXP (addr, 0)) == PLUS)
751 tmp = XEXP (addr, 1);
752 addr = XEXP (addr, 0);
756 tmp = XEXP (addr, 0);
757 addr = XEXP (addr, 1);
765 switch (GET_CODE (tmp))
775 offset = gen_rtx (PLUS, SImode, tmp, offset);
786 output_addr_const (file, offset);
788 fprintf (file, "(%s)", reg_names[REGNO (base)]);
790 fprintf (file, "(sb)");
799 else if (GET_CODE (offset) != CONST_INT)
800 fprintf (file, "(pc)");
801 #ifdef BASE_REG_NEEDED
803 fprintf (file, "(sb)");
807 #endif /* PC_RELATIVE */
809 /* now print index if we have one */
812 if (GET_CODE (indexexp) == MULT)
814 scale = INTVAL (XEXP (indexexp, 1)) >> 1;
815 indexexp = XEXP (indexexp, 0);
819 if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= 8)
823 fprintf (file, "[%c`%s]",
825 reg_names[REGNO (indexexp)]);
827 fprintf (file, "[%s:%c]",
828 reg_names[REGNO (indexexp)],
834 /* National 32032 shifting is so bad that we can get
835 better performance in many common cases by using other
838 output_shift_insn (operands)
841 if (GET_CODE (operands[2]) == CONST_INT
842 && INTVAL (operands[2]) > 0
843 && INTVAL (operands[2]) <= 3)
844 if (GET_CODE (operands[0]) == REG)
846 if (GET_CODE (operands[1]) == REG)
848 if (REGNO (operands[0]) == REGNO (operands[1]))
850 if (operands[2] == const1_rtx)
852 else if (INTVAL (operands[2]) == 2)
853 return "addd %0,%0\n\taddd %0,%0";
855 if (operands[2] == const1_rtx)
856 return "movd %1,%0\n\taddd %0,%0";
858 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
859 return "addr %a1,%0";
861 if (operands[2] == const1_rtx)
862 return "movd %1,%0\n\taddd %0,%0";
864 else if (GET_CODE (operands[1]) == REG)
866 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
867 return "addr %a1,%0";
869 else if (INTVAL (operands[2]) == 1
870 && GET_CODE (operands[1]) == MEM
871 && rtx_equal_p (operands [0], operands[1]))
873 rtx temp = XEXP (operands[1], 0);
875 if (GET_CODE (temp) == REG
876 || (GET_CODE (temp) == PLUS
877 && GET_CODE (XEXP (temp, 0)) == REG
878 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
881 else return "ashd %2,%0";
886 output_move_dconst (n, s)
893 strcpy (r, "movqd ");
894 else if (n > 0 && n < 256)
895 strcpy (r, "movzbd ");
896 else if (n > 0 && n < 65536)
897 strcpy (r, "movzwd ");
898 else if (n < 0 && n > -129)
899 strcpy (r, "movxbd ");
900 else if (n < 0 && n > -32769)
901 strcpy (r, "movxwd ");