1 /* Subroutines for assembler code output on the NS32000.
2 Copyright (C) 1988, 94, 95, 96, 97, 1998 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. */
25 #include "hard-reg-set.h"
27 #include "insn-config.h"
28 #include "conditions.h"
29 #include "insn-flags.h"
31 #include "insn-attr.h"
34 int ns32k_num_files
= 0;
41 fprintf (stderr
, s
, s1
, s2
);
44 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
47 hard_regno_mode_ok (regno
, mode
)
49 enum machine_mode mode
;
60 if (regno
< 8 || regno
== 16 || regno
== 17)
66 if (regno
< 8 && (regno
& 1) == 0)
111 /* Used to abort here, but simply saying "no" handles TImode
116 /* ADDRESS_COST calls this. This function is not optimal
117 for the 32032 & 32332, but it probably is better than
121 calc_address_cost (operand
)
127 if (GET_CODE (operand
) == MEM
)
129 if (GET_CODE (operand
) == MULT
)
132 if (GET_CODE (operand
) == REG
)
133 cost
+= 1; /* not really, but the documentation
134 says different amount of registers
135 shouldn't return the same costs */
137 switch (GET_CODE (operand
))
151 for (i
= 0; i
< GET_RTX_LENGTH (GET_CODE (operand
)); i
++)
153 cost
+= calc_address_cost (XEXP (operand
, i
));
161 /* Return the register class of a scratch register needed to copy IN into
162 or out of a register in CLASS in MODE. If it can be done directly,
163 NO_REGS is returned. */
166 secondary_reload_class (class, mode
, in
)
167 enum reg_class
class;
168 enum machine_mode mode
;
171 int regno
= true_regnum (in
);
173 if (regno
>= FIRST_PSEUDO_REGISTER
)
176 /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
178 if (class == GENERAL_REGS
|| (regno
>= 0 && regno
< 8))
181 /* Constants, memory, and FP registers can go into FP registers. */
182 if ((regno
== -1 || (regno
>= 8 && regno
< 16)) && (class == FLOAT_REGS
))
185 #if 0 /* This isn't strictly true (can't move fp to sp or vice versa),
186 so it's cleaner to use PREFERRED_RELOAD_CLASS
187 to make the right things happen. */
188 if (regno
>= 16 && class == GEN_AND_MEM_REGS
)
192 /* Otherwise, we need GENERAL_REGS. */
195 /* Generate the rtx that comes from an address expression in the md file */
196 /* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
197 scale must be converted from an exponent (from ASHIFT) to a
198 multiplier (for MULT). */
200 gen_indexed_expr (base
, index
, scale
)
201 rtx base
, index
, scale
;
205 /* This generates an invalid addressing mode, if BASE is
206 fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
207 if (GET_CODE (base
) != REG
&& GET_CODE (base
) != CONST_INT
)
208 base
= gen_rtx_MEM (SImode
, base
);
209 addr
= gen_rtx_MULT (SImode
, index
,
210 GEN_INT (1 << INTVAL (scale
)));
211 addr
= gen_rtx_PLUS (SImode
, base
, addr
);
215 /* Return 1 if OP is a valid operand of mode MODE. This
216 predicate rejects operands which do not have a mode
217 (such as CONST_INT which are VOIDmode). */
219 reg_or_mem_operand (op
, mode
)
221 enum machine_mode mode
;
223 return (GET_MODE (op
) == mode
224 && (GET_CODE (op
) == REG
225 || GET_CODE (op
) == SUBREG
226 || GET_CODE (op
) == MEM
));
229 /* Split one or more DImode RTL references into pairs of SImode
230 references. The RTL can be REG, offsettable MEM, integer constant, or
231 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
232 split and "num" is its length. lo_half and hi_half are output arrays
233 that parallel "operands". */
236 split_di (operands
, num
, lo_half
, hi_half
)
239 rtx lo_half
[], hi_half
[];
243 if (GET_CODE (operands
[num
]) == REG
)
245 lo_half
[num
] = gen_rtx_REG (SImode
, REGNO (operands
[num
]));
246 hi_half
[num
] = gen_rtx_REG (SImode
, REGNO (operands
[num
]) + 1);
248 else if (CONSTANT_P (operands
[num
]))
250 split_double (operands
[num
], &lo_half
[num
], &hi_half
[num
]);
252 else if (offsettable_memref_p (operands
[num
]))
254 lo_half
[num
] = operands
[num
];
255 hi_half
[num
] = adj_offsettable_operand (operands
[num
], 4);
262 /* Return the best assembler insn template
263 for moving operands[1] into operands[0] as a fullword. */
266 singlemove_string (operands
)
269 if (GET_CODE (operands
[1]) == CONST_INT
270 && INTVAL (operands
[1]) <= 7
271 && INTVAL (operands
[1]) >= -8)
272 return "movqd %1,%0";
277 output_move_double (operands
)
280 enum anon1
{ REGOP
, OFFSOP
, PUSHOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
283 /* First classify both operands. */
285 if (REG_P (operands
[0]))
287 else if (offsettable_memref_p (operands
[0]))
289 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
294 if (REG_P (operands
[1]))
296 else if (CONSTANT_P (operands
[1])
297 || GET_CODE (operands
[1]) == CONST_DOUBLE
)
299 else if (offsettable_memref_p (operands
[1]))
301 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
306 /* Check for the cases that the operand constraints are not
307 supposed to allow to happen. Abort if we get one,
308 because generating code for these cases is painful. */
310 if (optype0
== RNDOP
|| optype1
== RNDOP
)
313 /* Ok, we can do one word at a time.
314 Normally we do the low-numbered word first,
315 but if either operand is autodecrementing then we
316 do the high-numbered word first.
318 In either case, set up in LATEHALF the operands to use
319 for the high-numbered word and in some cases alter the
320 operands in OPERANDS to be suitable for the low-numbered word. */
322 if (optype0
== REGOP
)
323 latehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 1);
324 else if (optype0
== OFFSOP
)
325 latehalf
[0] = adj_offsettable_operand (operands
[0], 4);
327 latehalf
[0] = operands
[0];
329 if (optype1
== REGOP
)
330 latehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 1);
331 else if (optype1
== OFFSOP
)
332 latehalf
[1] = adj_offsettable_operand (operands
[1], 4);
333 else if (optype1
== CNSTOP
)
334 split_double (operands
[1], &operands
[1], &latehalf
[1]);
336 latehalf
[1] = operands
[1];
338 /* If insn is effectively movd N(sp),tos then we will do the
339 high word first. We should use the adjusted operand 1 (which is N+4(sp))
340 for the low word as well, to compensate for the first decrement of sp.
341 Given this, it doesn't matter which half we do "first". */
342 if (optype0
== PUSHOP
343 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
344 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
345 operands
[1] = latehalf
[1];
347 /* If one or both operands autodecrementing,
348 do the two words, high-numbered first. */
349 else if (optype0
== PUSHOP
|| optype1
== PUSHOP
)
351 output_asm_insn (singlemove_string (latehalf
), latehalf
);
352 return singlemove_string (operands
);
355 /* If the first move would clobber the source of the second one,
356 do them in the other order. */
358 /* Overlapping registers. */
359 if (optype0
== REGOP
&& optype1
== REGOP
360 && REGNO (operands
[0]) == REGNO (latehalf
[1]))
363 output_asm_insn (singlemove_string (latehalf
), latehalf
);
364 /* Do low-numbered word. */
365 return singlemove_string (operands
);
367 /* Loading into a register which overlaps a register used in the address. */
368 else if (optype0
== REGOP
&& optype1
!= REGOP
369 && reg_overlap_mentioned_p (operands
[0], operands
[1]))
371 if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0))
372 && reg_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
374 /* If both halves of dest are used in the src memory address,
375 load the destination address into the low reg (operands[0]).
376 Then it works to load latehalf first. */
378 xops
[0] = XEXP (operands
[1], 0);
379 xops
[1] = operands
[0];
380 output_asm_insn ("addr %a0,%1", xops
);
381 operands
[1] = gen_rtx_MEM (DImode
, operands
[0]);
382 latehalf
[1] = adj_offsettable_operand (operands
[1], 4);
383 /* The first half has the overlap, Do the late half first. */
384 output_asm_insn (singlemove_string (latehalf
), latehalf
);
386 return singlemove_string (operands
);
388 if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0)))
390 /* The first half has the overlap, Do the late half first. */
391 output_asm_insn (singlemove_string (latehalf
), latehalf
);
393 return singlemove_string (operands
);
397 /* Normal case. Do the two words, low-numbered first. */
399 output_asm_insn (singlemove_string (operands
), operands
);
401 operands
[0] = latehalf
[0];
402 operands
[1] = latehalf
[1];
403 return singlemove_string (operands
);
407 check_reg (oper
, reg
)
415 switch (GET_CODE(oper
))
418 return (REGNO(oper
) == reg
) ? 1 : 0;
420 return check_reg(XEXP(oper
, 0), reg
);
423 return check_reg(XEXP(oper
, 0), reg
) || check_reg(XEXP(oper
, 1), reg
);
428 /* Returns 1 if OP contains a global symbol reference */
431 global_symbolic_reference_mentioned_p (op
, f
)
438 if (GET_CODE (op
) == SYMBOL_REF
)
440 if (! SYMBOL_REF_FLAG (op
))
445 else if (f
&& GET_CODE (op
) != CONST
)
448 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
449 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
455 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
456 if (global_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
), 0))
459 else if (fmt
[i
] == 'e'
460 && global_symbolic_reference_mentioned_p (XEXP (op
, i
), 0))
468 /* PRINT_OPERAND is defined to call this function,
469 which is easier to debug than putting all the code in
470 a macro definition in ns32k.h. */
473 print_operand (file
, x
, code
)
479 PUT_IMMEDIATE_PREFIX (file
);
480 else if (code
== '?')
481 PUT_EXTERNAL_PREFIX (file
);
482 else if (GET_CODE (x
) == REG
)
483 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
484 else if (GET_CODE (x
) == MEM
)
486 rtx tmp
= XEXP (x
, 0);
487 output_address (XEXP (x
, 0));
489 else if (GET_CODE (x
) == CONST_DOUBLE
&& GET_MODE (x
) != VOIDmode
)
491 if (GET_MODE (x
) == DFmode
)
493 union { double d
; int i
[2]; } u
;
494 u
.i
[0] = CONST_DOUBLE_LOW (x
); u
.i
[1] = CONST_DOUBLE_HIGH (x
);
495 PUT_IMMEDIATE_PREFIX(file
);
497 /* Sequent likes its floating point constants as integers */
498 fprintf (file
, "0Dx%08x%08x", u
.i
[1], u
.i
[0]);
501 fprintf (file
, "0f%.20e", u
.d
);
503 fprintf (file
, "0d%.20e", u
.d
);
509 union { double d
; int i
[2]; } u
;
510 u
.i
[0] = CONST_DOUBLE_LOW (x
); u
.i
[1] = CONST_DOUBLE_HIGH (x
);
511 PUT_IMMEDIATE_PREFIX (file
);
513 /* We have no way of winning if we can't get the bits
514 for a sequent floating point number. */
515 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
519 union { float f
; long l
; } uu
;
521 fprintf (file
, "0Fx%08x", uu
.l
);
524 fprintf (file
, "0f%.20e", u
.d
);
530 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
531 if (GET_CODE (x
) == CONST_INT
)
533 PUT_IMMEDIATE_PREFIX (file
);
534 output_addr_const (file
, x
);
538 /* PRINT_OPERAND_ADDRESS is defined to call this function,
539 which is easier to debug than putting all the code in
540 a macro definition in ns32k.h . */
542 /* Completely rewritten to get this to work with Gas for PC532 Mach.
543 This function didn't work and I just wasn't able (nor very willing) to
544 figure out how it worked.
545 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
547 print_operand_address (file
, addr
)
551 static char scales
[] = { 'b', 'w', 'd', 0, 'q', };
552 rtx offset
, base
, indexexp
, tmp
;
556 if (GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_DEC
)
558 fprintf (file
, "tos");
567 if (GET_CODE (addr
) == PLUS
)
569 if (GET_CODE (XEXP (addr
, 0)) == PLUS
)
571 tmp
= XEXP (addr
, 1);
572 addr
= XEXP (addr
, 0);
577 addr
= XEXP (addr
,1);
585 switch (GET_CODE (tmp
))
619 if (flag_pic
&& ! CONSTANT_POOL_ADDRESS_P (tmp
)
620 && ! SYMBOL_REF_FLAG (tmp
))
632 if (flag_pic
&& GET_CODE (tmp
) == CONST
)
636 if (GET_CODE (tmp1
) != PLUS
)
640 if (GET_CODE (sym
) != SYMBOL_REF
)
647 if (GET_CODE (sym
) == SYMBOL_REF
)
649 if (GET_CODE (off
) != CONST_INT
)
652 if (CONSTANT_POOL_ADDRESS_P (sym
)
653 || SYMBOL_REF_FLAG (sym
))
655 SYMBOL_REF_FLAG (tmp
) = 1;
679 offset
= gen_rtx_PLUS (SImode
, tmp
, offset
);
691 #ifndef INDEX_RATHER_THAN_BASE
692 && (flag_pic
|| TARGET_HIMEM
)
693 && GET_CODE (base
) != SYMBOL_REF
694 && GET_CODE (offset
) != CONST_INT
696 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
698 && !indexexp
&& GET_CODE (base
) == REG
699 && REG_OK_FOR_INDEX_P (base
))
705 /* now, offset, base and indexexp are set */
706 #ifndef BASE_REG_NEEDED
709 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
710 if (GET_CODE (offset
) == CONST_INT
)
712 PUT_ABSOLUTE_PREFIX (file
);
716 output_addr_const (file
, offset
);
717 if (base
) /* base can be (REG ...) or (MEM ...) */
718 switch (GET_CODE (base
))
720 /* now we must output base. Possible alternatives are:
724 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
725 (disp(fp)) (MEM ...) just before possible [rX:y]
730 fprintf (file
, "(%s)", reg_names
[REGNO (base
)]);
737 output_addr_const (file
, base
);
738 fprintf (file
, "(sb))");
746 if (GET_CODE (addr
) == PLUS
)
748 if (GET_CODE (XEXP (addr
, 0)) == PLUS
)
750 tmp
= XEXP (addr
, 1);
751 addr
= XEXP (addr
, 0);
755 tmp
= XEXP (addr
, 0);
756 addr
= XEXP (addr
, 1);
764 switch (GET_CODE (tmp
))
774 offset
= gen_rtx_PLUS (SImode
, tmp
, offset
);
785 output_addr_const (file
, offset
);
787 fprintf (file
, "(%s)", reg_names
[REGNO (base
)]);
789 fprintf (file
, "(sb)");
798 else if (GET_CODE (offset
) != CONST_INT
)
799 fprintf (file
, "(pc)");
800 #ifdef BASE_REG_NEEDED
802 fprintf (file
, "(sb)");
806 #endif /* PC_RELATIVE */
808 /* now print index if we have one */
811 if (GET_CODE (indexexp
) == MULT
)
813 scale
= INTVAL (XEXP (indexexp
, 1)) >> 1;
814 indexexp
= XEXP (indexexp
, 0);
818 if (GET_CODE (indexexp
) != REG
|| REGNO (indexexp
) >= 8)
822 fprintf (file
, "[%c`%s]",
824 reg_names
[REGNO (indexexp
)]);
826 fprintf (file
, "[%s:%c]",
827 reg_names
[REGNO (indexexp
)],
833 /* National 32032 shifting is so bad that we can get
834 better performance in many common cases by using other
837 output_shift_insn (operands
)
840 if (GET_CODE (operands
[2]) == CONST_INT
841 && INTVAL (operands
[2]) > 0
842 && INTVAL (operands
[2]) <= 3)
843 if (GET_CODE (operands
[0]) == REG
)
845 if (GET_CODE (operands
[1]) == REG
)
847 if (REGNO (operands
[0]) == REGNO (operands
[1]))
849 if (operands
[2] == const1_rtx
)
851 else if (INTVAL (operands
[2]) == 2)
852 return "addd %0,%0\n\taddd %0,%0";
854 if (operands
[2] == const1_rtx
)
855 return "movd %1,%0\n\taddd %0,%0";
857 operands
[1] = gen_indexed_expr (const0_rtx
, operands
[1], operands
[2]);
858 return "addr %a1,%0";
860 if (operands
[2] == const1_rtx
)
861 return "movd %1,%0\n\taddd %0,%0";
863 else if (GET_CODE (operands
[1]) == REG
)
865 operands
[1] = gen_indexed_expr (const0_rtx
, operands
[1], operands
[2]);
866 return "addr %a1,%0";
868 else if (INTVAL (operands
[2]) == 1
869 && GET_CODE (operands
[1]) == MEM
870 && rtx_equal_p (operands
[0], operands
[1]))
872 rtx temp
= XEXP (operands
[1], 0);
874 if (GET_CODE (temp
) == REG
875 || (GET_CODE (temp
) == PLUS
876 && GET_CODE (XEXP (temp
, 0)) == REG
877 && GET_CODE (XEXP (temp
, 1)) == CONST_INT
))
880 else return "ashd %2,%0";
885 output_move_dconst (n
, s
)
892 strcpy (r
, "movqd ");
893 else if (n
> 0 && n
< 256)
894 strcpy (r
, "movzbd ");
895 else if (n
> 0 && n
< 65536)
896 strcpy (r
, "movzwd ");
897 else if (n
< 0 && n
> -129)
898 strcpy (r
, "movxbd ");
899 else if (n
< 0 && n
> -32769)
900 strcpy (r
, "movxwd ");