1 /* Subroutines for assembler code output on the NS32000.
2 Copyright (C) 1988 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Some output-actions in ns32k.md need these. */
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 illegal 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_rtx (CONST_INT, VOIDmode, 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 /* Return the best assembler insn template
230 for moving operands[1] into operands[0] as a fullword. */
233 singlemove_string (operands)
236 if (GET_CODE (operands[1]) == CONST_INT
237 && INTVAL (operands[1]) <= 7
238 && INTVAL (operands[1]) >= -8)
239 return "movqd %1,%0";
244 output_move_double (operands)
247 enum anon1 { REGOP, OFFSOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
250 /* First classify both operands. */
252 if (REG_P (operands[0]))
254 else if (offsettable_memref_p (operands[0]))
256 else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
261 if (REG_P (operands[1]))
263 else if (CONSTANT_ADDRESS_P (operands[1])
264 || GET_CODE (operands[1]) == CONST_DOUBLE)
266 else if (offsettable_memref_p (operands[1]))
268 else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
273 /* Check for the cases that the operand constraints are not
274 supposed to allow to happen. Abort if we get one,
275 because generating code for these cases is painful. */
277 if (optype0 == RNDOP || optype1 == RNDOP)
280 /* Ok, we can do one word at a time.
281 Normally we do the low-numbered word first,
282 but if either operand is autodecrementing then we
283 do the high-numbered word first.
285 In either case, set up in LATEHALF the operands to use
286 for the high-numbered word and in some cases alter the
287 operands in OPERANDS to be suitable for the low-numbered word. */
289 if (optype0 == REGOP)
290 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
291 else if (optype0 == OFFSOP)
292 latehalf[0] = adj_offsettable_operand (operands[0], 4);
294 latehalf[0] = operands[0];
296 if (optype1 == REGOP)
297 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
298 else if (optype1 == OFFSOP)
299 latehalf[1] = adj_offsettable_operand (operands[1], 4);
300 else if (optype1 == CNSTOP)
302 if (CONSTANT_ADDRESS_P (operands[1]))
303 latehalf[1] = const0_rtx;
304 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
305 split_double (operands[1], &operands[1], &latehalf[1]);
308 latehalf[1] = operands[1];
310 /* If one or both operands autodecrementing,
311 do the two words, high-numbered first. */
313 if (optype0 == POPOP || optype1 == POPOP)
315 output_asm_insn (singlemove_string (latehalf), latehalf);
316 return singlemove_string (operands);
319 /* If the first move would clobber the source of the second one,
320 do them in the other order. */
322 /* Overlapping registers. */
323 if (optype0 == REGOP && optype1 == REGOP
324 && REGNO (op0) == REGNO (latehalf[1]))
327 output_asm_insn (singlemove_string (latehalf), latehalf);
328 /* Do low-numbered word. */
329 return singlemove_string (operands);
331 /* Loading into a register which overlaps a register used in the address. */
332 else if (optype0 == REGOP && optype1 != REGOP
333 && reg_overlap_mentioned_p (op0, op1))
335 if (reg_mentioned_p (op0, XEXP (op1, 0))
336 && reg_mentioned_p (latehalf[0], XEXP (op1, 0)))
338 /* If both halves of dest are used in the src memory address,
339 add the two regs and put them in the low reg (op0).
340 Then it works to load latehalf first. */
342 xops[0] = latehalf[0];
344 output_asm_insn ("addd %0,%1", xops);
345 operands[1] = gen_rtx (MEM, DImode, op0);
346 latehalf[1] = adj_offsettable_operand (operands[1], 4);
348 /* Do the late half first. */
349 output_asm_insn (singlemove_string (latehalf), latehalf);
351 return singlemove_string (operands);
354 /* Normal case. Do the two words, low-numbered first. */
356 output_asm_insn (singlemove_string (operands), operands);
358 operands[0] = latehalf[0];
359 operands[1] = latehalf[1];
360 return singlemove_string (operands);
364 check_reg (oper, reg)
372 switch (GET_CODE(oper))
375 return (REGNO(oper) == reg) ? 1 : 0;
377 return check_reg(XEXP(oper, 0), reg);
380 return check_reg(XEXP(oper, 0), reg) || check_reg(XEXP(oper, 1), reg);
385 /* PRINT_OPERAND is defined to call this function,
386 which is easier to debug than putting all the code in
387 a macro definition in ns32k.h. */
390 print_operand (file, x, code)
396 PUT_IMMEDIATE_PREFIX (file);
397 else if (code == '?')
398 PUT_EXTERNAL_PREFIX (file);
399 else if (GET_CODE (x) == REG)
400 fprintf (file, "%s", reg_names[REGNO (x)]);
401 else if (GET_CODE (x) == MEM)
403 rtx tmp = XEXP (x, 0);
404 #if ! (defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC))
405 if (GET_CODE (tmp) != CONST_INT)
407 char *out = XSTR (tmp, 0);
410 PUT_ABSOLUTE_PREFIX (file);
411 fprintf (file, "%s", &out[1]);
414 ASM_OUTPUT_LABELREF (file, out);
418 output_address (XEXP (x, 0));
420 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode)
422 if (GET_MODE (x) == DFmode)
424 union { double d; int i[2]; } u;
425 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
426 PUT_IMMEDIATE_PREFIX(file);
428 /* Sequent likes it's floating point constants as integers */
429 fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
432 fprintf (file, "0f%.20e", u.d);
434 fprintf (file, "0d%.20e", u.d);
440 union { double d; int i[2]; } u;
441 u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
442 PUT_IMMEDIATE_PREFIX (file);
444 /* We have no way of winning if we can't get the bits
445 for a sequent floating point number. */
446 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
450 union { float f; long l; } uu;
452 fprintf (file, "0Fx%08x", uu.l);
455 fprintf (file, "0f%.20e", u.d);
461 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
462 if (GET_CODE (x) == CONST_INT)
464 PUT_IMMEDIATE_PREFIX (file);
465 output_addr_const (file, x);
469 /* PRINT_OPERAND_ADDRESS 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 . */
473 /* Completely rewritten to get this to work with Gas for PC532 Mach.
474 This function didn't work and I just wasn't able (nor very willing) to
475 figure out how it worked.
476 90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
478 print_operand_address (file, addr)
482 static char scales[] = { 'b', 'w', 'd', 0, 'q', };
483 rtx offset, base, indexexp, tmp;
486 if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
488 fprintf (file, "tos");
497 if (GET_CODE (addr) == PLUS)
499 if (GET_CODE (XEXP (addr, 0)) == PLUS)
501 tmp = XEXP (addr, 1);
502 addr = XEXP (addr, 0);
507 addr = XEXP (addr,1);
515 switch (GET_CODE (tmp))
553 offset = gen_rtx (PLUS, SImode, tmp, offset);
564 #ifdef INDEX_RATHER_THAN_BASE
565 /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix. */
566 if (base && !indexexp && GET_CODE (base) == REG
567 && REG_OK_FOR_INDEX_P (base))
574 /* now, offset, base and indexexp are set */
577 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
578 if (GET_CODE (offset) == CONST_INT)
579 /* if (! (GET_CODE (offset) == LABEL_REF
580 || GET_CODE (offset) == SYMBOL_REF)) */
582 PUT_ABSOLUTE_PREFIX (file);
585 output_addr_const (file, offset);
586 if (base) /* base can be (REG ...) or (MEM ...) */
587 switch (GET_CODE (base))
589 /* now we must output base. Possible alternatives are:
593 (pc) (REG ...) used for SYMBOL_REF and LABEL_REF, output
594 (disp(fp)) (MEM ...) just before possible [rX:y]
599 fprintf (file, "(%s)", reg_names[REGNO (base)]);
607 if (GET_CODE (addr) == PLUS)
609 if (GET_CODE (XEXP (addr, 0)) == PLUS)
611 tmp = XEXP (addr, 1);
612 addr = XEXP (addr, 0);
616 tmp = XEXP (addr, 0);
617 addr = XEXP (addr, 1);
625 switch (GET_CODE (tmp))
635 offset = gen_rtx (PLUS, SImode, tmp, offset);
646 output_addr_const (file, offset);
648 fprintf (file, "(%s)", reg_names[REGNO (base)]);
649 #ifdef BASE_REG_NEEDED
651 fprintf (file, "(sb)");
663 if (GET_CODE (offset) == LABEL_REF || GET_CODE (offset) == SYMBOL_REF)
664 fprintf (file, "(pc)");
666 #ifdef BASE_REG_NEEDED /* this is defined if the assembler always
667 needs a base register */
669 fprintf (file, "(sb)");
673 /* now print index if we have one */
676 if (GET_CODE (indexexp) == MULT)
678 scale = INTVAL (XEXP (indexexp, 1)) >> 1;
679 indexexp = XEXP (indexexp, 0);
683 if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= 8)
687 fprintf (file, "[%c`%s]",
689 reg_names[REGNO (indexexp)]);
691 fprintf (file, "[%s:%c]",
692 reg_names[REGNO (indexexp)],
698 /* National 32032 shifting is so bad that we can get
699 better performance in many common cases by using other
702 output_shift_insn (operands)
705 if (GET_CODE (operands[2]) == CONST_INT
706 && INTVAL (operands[2]) > 0
707 && INTVAL (operands[2]) <= 3)
708 if (GET_CODE (operands[0]) == REG)
710 if (GET_CODE (operands[1]) == REG)
712 if (REGNO (operands[0]) == REGNO (operands[1]))
714 if (operands[2] == const1_rtx)
716 else if (INTVAL (operands[2]) == 2)
717 return "addd %0,%0\n\taddd %0,%0";
719 if (operands[2] == const1_rtx)
720 return "movd %1,%0\n\taddd %0,%0";
722 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
723 return "addr %a1,%0";
725 if (operands[2] == const1_rtx)
726 return "movd %1,%0\n\taddd %0,%0";
728 else if (GET_CODE (operands[1]) == REG)
730 operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
731 return "addr %a1,%0";
733 else if (INTVAL (operands[2]) == 1
734 && GET_CODE (operands[1]) == MEM
735 && rtx_equal_p (operands [0], operands[1]))
737 rtx temp = XEXP (operands[1], 0);
739 if (GET_CODE (temp) == REG
740 || (GET_CODE (temp) == PLUS
741 && GET_CODE (XEXP (temp, 0)) == REG
742 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
745 else return "ashd %2,%0";