1 /* Output routines for GCC for picoJava II
2 Copyright (C) 2000, 2001 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 /* Contributed by Steve Chamberlain (sac@pobox.com), of Transmeta. */
23 /* The picoJava architecture doesn't have general registers, it has an
24 operand stack. Any of the first 256 words on the operand stack between
25 the locations indicated by the vars register and the optop register
26 are accessible with one instruction, almost as if they were registers.
27 The opstack isn't aliased into memory, so deferecencing address of
28 something on the opstack is impossible.
30 Small scalar incoming arguments to a function arrive on the operand
31 stack, large scalars and aggregates arrive in the `aggregate'
32 stack. The aggregate stack lives in normal memory.
35 just before a call after the call insn and frame setup.
53 This port generates code for a machine with 32 general purpose
54 registers, and on output changes the references to the fake registers
55 into offsets from the vars register. Because the opstack grows
56 downwards and all indexes are negated, some care has to be taken here
57 to deal with endian problems; for example after a call on a little endian
58 machine, an incoming DImode argument of value 0x1122334455667788 in
59 `register 0', would live on the opstack like this:
66 The picoJava instructon to read and put that onto the opstack as a
67 DImode value is `lload 0', yet the least significant word lives at
68 vars - 4, for which the instruction is `iload 1'. The incoming
69 argument code remembers which arguments arrive swapped in the
70 CUMULATIVE_ARGS structure. The information is used to fill in
71 pj_si_vars_offset_vec and pj_di_vars_offset_vec during the prologue
74 Outgoing arguments are collected in fake `outgoing' registers, or
75 in the aggregate stack. The emitted code to write into an outgoing
76 register does nothing, which leaves the expression to be written on
77 the top of the opstack. GCC always evaluates arguments in the right
78 order, so nothing more needs to be done. */
87 #include "hard-reg-set.h"
89 #include "insn-config.h"
90 #include "conditions.h"
92 #include "insn-attr.h"
100 #include "basic-block.h"
103 #include "target-def.h"
105 /* Compare insns in pj.md store the information needed to generate
106 branch instructions here. */
109 enum machine_mode pj_cmp_mode;
111 static void pj_output_rval PARAMS ((rtx, enum machine_mode, rtx));
112 static void pj_output_store_into_lval PARAMS ((enum machine_mode mode, rtx op));
113 static void pj_output_push_int PARAMS ((int));
114 static void pj_output_load PARAMS ((enum machine_mode, int));
115 static void pj_output_inc PARAMS ((rtx, int));
116 static void pj_output_cnv_op PARAMS ((enum insn_code, rtx));
117 static char mode_to_char PARAMS ((enum machine_mode));
118 static void pj_output_varidx PARAMS ((enum machine_mode, int, int));
119 static void pj_print_cond PARAMS ((enum rtx_code));
120 static rtx *unique_src_operand PARAMS ((rtx *, rtx));
122 /* These vectors turn a register number into an offset from the vars
124 short pj_si_vars_offset_vec[FIRST_PSEUDO_REGISTER];
125 short pj_di_vars_offset_vec[FIRST_PSEUDO_REGISTER];
126 short pj_debugreg_renumber_vec[FIRST_PSEUDO_REGISTER];
128 /* Number of fake registers in the frame, used by prologue and epilogue
132 /* Whether anything has been printed to the current assembly output
134 int pj_stuff_on_line;
136 /* Initialize the GCC target structure. */
138 struct gcc_target targetm = TARGET_INITIALIZER;
140 /* printf to the asm_out_file, with special format control characters
141 for decoding operands.
144 %d,%x,%c,%s - as printf
145 %X - address constant.
146 %<alpha><digit> - operand <digit> passed to pj_print_operand with code <alpha>. */
149 pj_printf VPARAMS ((const char *template, ...))
155 VA_OPEN (argptr, template);
156 VA_FIXEDARG (argptr, const char *, template);
158 while ((c = *template++))
160 int was_stuff_on_line = pj_stuff_on_line;
161 pj_stuff_on_line = 1;
165 putc (c, asm_out_file);
166 pj_stuff_on_line = 0;
169 putc (c, asm_out_file);
176 putc ('%', asm_out_file);
178 pj_stuff_on_line = 1;
181 /* Marks start of opcode, tab out. */
182 if (was_stuff_on_line)
183 fprintf (asm_out_file, "; ");
188 fprintf (asm_out_file, "%d", va_arg (argptr, int));
192 fprintf (asm_out_file, "%x", va_arg (argptr, int));
196 fprintf (asm_out_file, "%c", va_arg (argptr, int));
200 fputs (va_arg (argptr, const char *), asm_out_file);
204 output_addr_const (asm_out_file, va_arg (argptr, rtx));
211 if (ISALPHA (*template))
213 if (ISDIGIT (*template))
215 int num = atoi (template);
217 while (ops_read <= num)
218 operands[ops_read++] = va_arg (argptr, rtx);
219 send = operands[num];
222 send = va_arg (argptr, rtx);
224 /* A null means leave the word on the stack, so there's
225 no need to do anything for that. */
228 pj_print_operand (asm_out_file, send, code);
237 /* Output code to efficiently push a single word integer constant onto
241 pj_output_push_int (val)
244 int low = ((val & 0x8000) ? ~0xffff : 0) | (val & 0xffff);
247 pj_printf ("%*iconst_m1");
248 else if (low >= 0 && low <= 5)
249 pj_printf ("%*iconst_%d", low);
250 else if (low >= -128 && low < 128)
251 pj_printf ("%*bipush %d", low);
253 pj_printf ("%*sipush %d", low);
255 if ((low & 0xffff0000) != (val & 0xffff0000))
256 pj_printf ("%*sethi 0x%x", (val >> 16) & 0xffff);
259 /* Output code to add a constant to the value on the top of the
263 pj_output_print_add_k (int size)
267 pj_output_push_int (size);
268 pj_printf ("%*iadd");
272 pj_output_push_int (-size);
273 pj_printf ("%*isub");
277 /* Output code to load the value pointed to by the top of stack onto
281 pj_output_load (mode, uns)
282 enum machine_mode mode;
286 switch (GET_MODE_SIZE (mode))
289 pj_printf (uns ? "%*load_ubyte" : "%*load_byte");
292 pj_printf (uns ? "%*load_char" : "%*load_short");
295 if (TARGET_TM_EXTENSIONS)
297 pj_printf ("%*tm_load_long");
302 for (i = GET_MODE_SIZE (mode); i > 4; i -= 4)
305 pj_output_print_add_k (i - 4);
306 pj_printf ("%*load_word");
307 pj_printf ("%*swap");
309 pj_printf ("%*load_word");
313 /* Output code to increment the provided lval operand. */
316 pj_output_inc (op, size)
320 if (STACK_REG_RTX_P (op))
321 pj_printf ("%*iinc %d,%d", pj_si_vars_offset_vec[REGNO (op)], size);
324 pj_output_rval (op, SImode, 0);
325 pj_output_push_int (size);
326 pj_printf ("%*iadd");
327 pj_output_store_into_lval (SImode, op);
331 /* Output the text for a conversion operator. */
334 pj_output_cnv_op (e, op)
338 pj_printf ((const char *) insn_data[(int) e].output, 0, XEXP (op, 0));
341 /* Turn a machine_mode into an opcode modifier chararacter. */
345 enum machine_mode mode;
368 /* Output an index off the var register. If we're moving an 8 byte
369 value then reduce the index, since the picoJava instruction loading
370 the value uses the index of the highest part of the register as
374 pj_output_varidx (mode, do_store, idx)
375 enum machine_mode mode;
379 pj_printf ("%*%c%s%c%d",
381 do_store ? "store" : "load",
382 (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)
383 && idx <= 3 ? '_' : ' ', idx);
386 /* Output an rvalue expression. */
389 pj_output_rval (op, mode, outer_op)
391 enum machine_mode mode;
394 enum rtx_code code = GET_CODE (op);
398 if (code == DIV && GET_MODE_CLASS (mode) == MODE_INT)
401 tab = code_to_optab[code];
405 pj_output_rval (XEXP (op, 0), mode, op);
406 pj_output_rval (XEXP (op, 1), mode, op);
407 pj_printf ("%*%cadd", mode_to_char (mode));
409 else if (tab && tab->handlers[mode].insn_code != CODE_FOR_nothing)
411 const char *const template =
412 (const char *) insn_data[tab->handlers[mode].insn_code].output;
414 pj_printf (template, 0, XEXP (op, 0));
416 pj_printf (template, 0, XEXP (op, 0), XEXP (op, 1));
419 switch (GET_CODE (op))
422 fprintf (asm_out_file, " pc ");
426 pj_output_rval (XEXP (op, 0), mode, op);
430 pj_output_rval (XEXP (op, 0), Pmode, op);
431 pj_output_load (mode, 0);
435 pj_printf ("%*ipush %X", op);
445 if (pj_si_vars_offset_vec[REGNO (op)] >= 0)
446 pj_output_varidx (mode, 0, pj_si_vars_offset_vec[REGNO (op)]);
448 pj_printf ("%*read_%s", reg_names[REGNO (op)]);
452 if (pj_di_vars_offset_vec[REGNO (op)] >= 0)
453 pj_output_varidx (mode, 0, pj_di_vars_offset_vec[REGNO (op)]);
458 pj_printf ("%*read_global2");
459 pj_printf ("%*read_global1");
462 /* A 64 bit read of global0 gives global0 and
465 pj_printf ("%*read_optop");
466 pj_printf ("%*read_global0");
479 pj_printf (pj_standard_float_constant (op));
483 if (mode == SImode || mode == HImode || mode == QImode)
484 pj_output_push_int (INTVAL (op));
485 else if (mode == DImode)
489 pj_printf ("%*lconst_1", 0);
491 pj_printf ("%*lconst_0", 0);
494 rtx hi = GEN_INT (v < 0 ? -1 : 0);
496 pj_output_rval (TARGET_LITTLE_ENDIAN ? hi : lo, SImode, op);
497 pj_output_rval (TARGET_LITTLE_ENDIAN ? lo : hi, SImode, op);
505 pj_printf ("%S0%*d2f", XEXP (op, 0));
508 pj_printf ("%*ipush %X", XEXP (op, 0));
512 pj_output_rval (alter_subreg (op), mode, outer_op);
516 pj_output_rval (XEXP (op, 0), mode, op);
517 pj_output_inc (XEXP (op, 0), GET_MODE_SIZE (GET_MODE (outer_op)));
521 pj_output_rval (XEXP (op, 0), mode, op);
522 pj_output_inc (XEXP (op, 0), -GET_MODE_SIZE (GET_MODE (outer_op)));
526 pj_output_inc (XEXP (op, 0), GET_MODE_SIZE (GET_MODE (outer_op)));
527 pj_output_rval (XEXP (op, 0), mode, op);
531 if (OPTOP_REG_RTX_P (XEXP (op, 0)))
532 pj_output_rval (XEXP (op, 0), mode, op);
533 else if (STACK_REG_RTX_P (XEXP (op, 0)))
535 pj_output_inc (XEXP (op, 0),
536 -GET_MODE_SIZE (GET_MODE (outer_op)));
537 pj_output_rval (XEXP (op, 0), mode, op);
541 pj_printf ("%S0", XEXP (op, 0));
542 pj_output_print_add_k (-GET_MODE_SIZE (GET_MODE (outer_op)));
543 pj_printf ("%*dup%R0", XEXP (op, 0));
548 pj_output_cnv_op (fixtrunctab[GET_MODE (XEXP (op, 0))][mode][0], op);
552 if (mode == DFmode && GET_CODE (XEXP (op, 0)) == CONST_INT)
553 pj_output_cnv_op (floattab[mode][SImode][0], op);
555 pj_output_cnv_op (floattab[mode][GET_MODE (XEXP (op, 0))][0], op);
560 /* Sign extending from a memop to register is automatic. */
561 if (mode == SImode && GET_CODE (XEXP (op, 0)) == MEM)
562 pj_output_rval (XEXP (op, 0), GET_MODE (XEXP (op, 0)), op);
564 pj_output_cnv_op (extendtab[mode][GET_MODE (XEXP (op, 0))][0], op);
568 pj_output_cnv_op (extendtab[mode][GET_MODE (XEXP (op, 0))][1], op);
577 /* Store the top of stack into the lval operand OP. */
580 pj_output_store_into_lval (mode, op)
581 enum machine_mode mode;
584 if (GET_CODE (op) == REG)
588 /* Outgoing values are left on the stack and not written
590 if (!OUTGOING_REG_RTX_P (op))
592 switch (GET_MODE (op))
598 if (pj_si_vars_offset_vec[rn] >= 0)
599 pj_output_varidx (mode, 1, pj_si_vars_offset_vec[rn]);
601 pj_printf ("%*write_%s", reg_names[rn]);
605 if (pj_di_vars_offset_vec[rn] >= 0)
606 pj_output_varidx (mode, 1, pj_di_vars_offset_vec[rn]);
611 pj_printf ("%*write_global1");
612 pj_printf ("%*write_global2");
625 pj_output_rval (XEXP (op, 0), Pmode, op);
627 switch (GET_MODE_SIZE (mode))
630 pj_printf ("%*store_byte", 0);
633 pj_printf ("%*store_short", 0);
636 if (TARGET_TM_EXTENSIONS)
638 pj_printf ("%*tm_store_long");
645 for (i = GET_MODE_SIZE (mode); i > 4; i -= 4)
647 pj_printf ("%*dup_x1", 0);
648 pj_printf ("%*store_word", 0);
649 pj_printf ("%*iconst_4", 0);
650 pj_printf ("%*iadd", 0);
653 pj_printf ("%*store_word", 0);
659 /* Print a condition, unsigned and signed have the same text because
660 the unsigned operands have been run through icmp first. */
669 fputs ("eq", asm_out_file);
672 fputs ("ne", asm_out_file);
676 fputs ("gt", asm_out_file);
680 fputs ("ge", asm_out_file);
684 fputs ("lt", asm_out_file);
688 fputs ("le", asm_out_file);
694 /* Print operand X (an rtx) in assembler syntax to file STREAM
695 according to modifier CODE.
697 C emit the first part of a Check_call pseudop.
698 D emit operand, if no mode, assume DImode.
699 E emit the second part of a check_call pseudop.
700 I print the XEXP (X, 0) Inside of the operand.
701 J print Just the integer or register part of an operand, for iinc.
702 P emit source is SI padded to DI with 0, used for unsigned mod and divide.
703 R emit the operand as an lval Result.
704 S emit Source operand, if no mode, assume SImode.
705 X nan choice suffix for floating point comparision.
706 Y condition name from op.
708 * marks start of opcode. */
711 pj_print_operand (stream, x, code)
716 static int last_call_known;
720 if (GET_CODE (x) == SYMBOL_REF)
723 pj_printf ("%*.check_call %0", x);
731 GET_MODE (x) == VOIDmode ? DImode : GET_MODE (x),
737 pj_printf (",%d", INTVAL (x));
741 pj_output_rval (XEXP (x, 0), GET_MODE (XEXP (x, 0)), NULL_RTX);
745 if (GET_CODE (x) == CONST_INT)
746 pj_printf ("%d", INTVAL (x));
747 else if (GET_CODE (x) == REG)
748 pj_printf ("%d", pj_si_vars_offset_vec[REGNO (x)]);
754 if (TARGET_LITTLE_ENDIAN)
755 pj_printf ("%*iconst_0", 0);
757 GET_MODE (x) == VOIDmode ? SImode : GET_MODE (x),
759 if (!TARGET_LITTLE_ENDIAN)
760 pj_printf ("%*iconst_0", 0);
764 pj_output_store_into_lval (GET_MODE (x), x);
769 GET_MODE (x) == VOIDmode ? SImode : GET_MODE (x),
774 fputc (GET_CODE (x) == LT || GET_CODE (x) == LE ? 'g' : 'l', stream);
778 pj_print_cond (GET_CODE (x));
782 pj_print_cond (reverse_condition (GET_CODE (x)));
790 output_addr_const (stream, x);
795 /* Return in an rtx the number of words pushed onto the optop to be
796 used as the word count in a call insn. (NEXT_ARG_REG is NULL when
797 called from expand_builtin_apply). */
800 pj_workout_arg_words (stack_size, next_arg_reg)
801 rtx stack_size ATTRIBUTE_UNUSED;
804 return GEN_INT ((next_arg_reg ? REGNO (next_arg_reg) - O0_REG : 0) + 2);
807 /* Handle the INCOMING_FUNCTION_ARG macro.
808 Determine where to put an argument to a function.
809 Value is zero to push the argument on the stack,
810 or a hard register in which to store the argument.
812 CUM is a variable of type CUMULATIVE_ARGS which gives info about
813 the preceding args and about the function being called.
814 MODE is the argument's machine mode.
815 TYPE is the data type of the argument (as a tree).
816 This is null for libcalls where that information may
818 NAMED is nonzero if this argument is a named parameter
819 (otherwise it is an extra parameter matching an ellipsis). */
822 pj_function_incoming_arg (cum, mode, passed_type, named_arg)
823 CUMULATIVE_ARGS *cum;
824 enum machine_mode mode;
825 tree passed_type ATTRIBUTE_UNUSED;
826 int named_arg ATTRIBUTE_UNUSED;
828 int arg_words = PJ_ARG_WORDS (mode);
830 /* If the whole argument will fit into registers, return the first
831 register needed. Also fill in the arg_adjust information so that
832 we can work out the right offset to use when looking at the
833 insides of a DI or DF value. */
835 if (cum->total_words + arg_words <= ARGS_IN_REGS)
838 if (mode == DImode || mode == DFmode)
840 cum->arg_adjust[cum->total_words + 0] = 1;
841 cum->arg_adjust[cum->total_words + 1] = -1;
844 for (i = 0; i < arg_words; i++)
845 cum->arg_adjust[cum->total_words + i] = 0;
847 return gen_rtx (REG, mode, I0_REG + cum->total_words);
852 /* Output code to add two SImode values. Deals carefully with the the common
853 case of moving the optop. */
856 pj_output_addsi3 (operands)
859 if (OPTOP_REG_RTX_P (operands[0]) && OPTOP_REG_RTX_P (operands[1])
860 && GET_CODE (operands[2]) == CONST_INT
861 && INTVAL (operands[2]) >= -32 && INTVAL (operands[2]) <= 32)
871 { "lconst_0", "iconst_0"}
873 int size = INTVAL (operands[2]);
882 for (; size >= 8; size -= 8)
883 output_asm_insn (name[d].two, 0);
887 output_asm_insn (name[d].one, 0);
892 if (STACK_REG_RTX_P (operands[0])
893 && rtx_equal_p (operands[0], operands[1])
894 && GET_CODE (operands[2]) == CONST_INT
895 && INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) <= 127)
897 return "iinc %J0,%J2";
900 return "%S1%S2%*iadd%R0";
903 /* Generate rtl for the prologue of the current function. */
906 pj_expand_prologue ()
910 int arg_words = current_function_args_info.named_words;
912 memset (pj_si_vars_offset_vec, -1, sizeof (pj_si_vars_offset_vec));
913 memset (pj_di_vars_offset_vec, -1, sizeof (pj_di_vars_offset_vec));
915 /* Work out the register numbers of the named arguments. */
916 for (i = 0; i < current_function_args_info.named_words; i++)
918 pj_debugreg_renumber_vec[I0_REG + i]
919 = off + R0_REG + current_function_args_info.arg_adjust[i];
920 pj_si_vars_offset_vec[I0_REG + i]
921 = off + current_function_args_info.arg_adjust[i];
922 pj_di_vars_offset_vec[I0_REG + i] = off;
926 if (current_function_varargs || current_function_stdarg)
928 /* If the function is varadic we need to call the vhelper
929 function. vhelper pops off the unnamed argument words from
930 the opstack and puts them onto the the aggregate stack. The
931 unnamed words are replacedwith two extra arguments, a pointer
932 to the aggreagate stack for the first vararg and the original
935 emit_insn (gen_varargs (GEN_INT (arg_words * 4)));
936 pj_si_vars_offset_vec[VA_REG] = off++;
941 /* Skip over the return pc and old vars in the frame. */
944 /* Work out the register numbers and offsets from the var pointer
945 for the normal registers. */
948 for (i = LAST_I_REG; i >= R0_REG; i--)
949 if (regs_ever_live[i] && pj_si_vars_offset_vec[i] == -1)
952 pj_si_vars_offset_vec[i] = off;
953 pj_di_vars_offset_vec[i] = off - 1;
954 pj_debugreg_renumber_vec[i] = off + R0_REG;
960 fprintf (asm_out_file, "\n\t! args %d, size %d, fakes %d\n",
962 get_frame_size () / 4,
965 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
966 if (pj_si_vars_offset_vec[i] >= 0)
967 fprintf (asm_out_file, "\t!vars - %d %d: %s\n",
968 pj_si_vars_offset_vec[i],
969 pj_di_vars_offset_vec[i],
973 /* Make room on the opstack for the fake registers. */
974 if (TARGET_TM_EXTENSIONS)
975 RTX_FRAME_RELATED_P (emit_insn (gen_tm_frame (GEN_INT (arg_words),
976 GEN_INT (nfakes)))) = 1;
978 RTX_FRAME_RELATED_P (emit_insn
980 (gen_rtx_REG (SImode, OPTOP_REG),
981 gen_rtx_REG (SImode, OPTOP_REG),
982 GEN_INT (-nfakes * 4)))) = 1;
985 if (frame_pointer_needed)
986 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
988 if (get_frame_size ())
989 RTX_FRAME_RELATED_P (emit_insn (gen_addsi3 (stack_pointer_rtx,
992 (-get_frame_size ())))) = 1;
994 emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, OPTOP_REG)));
997 /* Generate rtl for the epilogue of the current function. */
1000 pj_expand_epilogue ()
1002 if (frame_pointer_needed)
1003 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
1004 else if (get_frame_size ())
1005 emit_insn (gen_addsi3 (stack_pointer_rtx,
1006 stack_pointer_rtx, GEN_INT (get_frame_size ())));
1008 emit_insn (gen_addsi3 (gen_rtx_REG (SImode, OPTOP_REG),
1009 gen_rtx_REG (SImode, OPTOP_REG),
1010 GEN_INT (nfakes * 4)));
1013 /* If this is a varargs function, then global0 is stashed away on
1014 the top of the optop stack as the last secret argument by the
1015 __vhelper. Pop off the va pointer provided too. */
1017 if (current_function_varargs || current_function_stdarg)
1018 emit_insn (gen_varargs_finish
1019 (GEN_INT (current_function_args_info.named_words + 1)));
1021 emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, OPTOP_REG)));
1024 /* Return the opcode name for an instruction to load a standard
1025 floating point constant, or NULL. */
1028 pj_standard_float_constant (op)
1032 enum machine_mode mode = GET_MODE (op);
1034 if (GET_CODE (op) != CONST_DOUBLE || (mode != DFmode && mode != SFmode))
1037 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1039 if (REAL_VALUES_EQUAL (r, dconst0) && !REAL_VALUE_MINUS_ZERO (r))
1040 return mode == DFmode ? "%*dconst_0" : "%*fconst_0";
1042 if (REAL_VALUES_EQUAL (r, dconst1))
1043 return mode == DFmode ? "%*dconst_1" : "%*fconst_1";
1045 if (REAL_VALUES_EQUAL (r, dconst2))
1046 return mode == DFmode ? 0 : "%*fconst_2";
1051 /* Read the value at the current address, and decrement by the size.
1052 The function is interesting because we're reading from high memory to low memory
1053 and have to adjust the addresses of reads of 8 byte values
1057 pj_expand_builtin_va_arg (valist, type)
1062 HOST_WIDE_INT align;
1063 HOST_WIDE_INT rounded_size;
1066 /* Compute the rounded size of the type. */
1067 align = PARM_BOUNDARY / BITS_PER_UNIT;
1068 rounded_size = (((int_size_in_bytes (type) + align - 1) / align) * align);
1072 addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
1073 addr = copy_to_reg (addr);
1075 /* Aggregates and large scalars are passed by reference. */
1076 if (AGGREGATE_TYPE_P (type) || rounded_size > 8)
1078 addr = gen_rtx_MEM (Pmode, addr);
1082 /* adjust address to cope with double word sizes */
1083 if (rounded_size > 4)
1084 addr = gen_rtx_PLUS (Pmode, addr, GEN_INT (-4));
1086 /* Compute new value for AP; AP = AP - SIZE */
1087 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
1088 build (MINUS_EXPR, TREE_TYPE (valist), valist,
1089 build_int_2 (rounded_size, 0)));
1091 TREE_SIDE_EFFECTS (t) = 1;
1093 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1098 /* Return nonzero if the operand is valid as a source operand; it's
1099 general and it's not an outgoing argument register. */
1102 pj_source_operand (op, mode)
1104 enum machine_mode mode;
1106 return !OUTGOING_REG_RTX_P (op) && general_operand (op, mode);
1109 /* Return nonzero if the operator is a signed compare. */
1112 pj_signed_comparison_operator (op, mode)
1114 enum machine_mode mode;
1116 if (mode != GET_MODE (op))
1119 switch (GET_CODE (op))
1133 /* Return nonzero if the operator is an unsigned compare. */
1136 pj_unsigned_comparison_operator (op, mode)
1138 enum machine_mode mode ATTRIBUTE_UNUSED;
1140 if (mode != GET_MODE (op))
1143 switch (GET_CODE (op))
1155 /* Helper function for pj_machine_dependent_reorg. Find the one
1156 instance of register OP in the source part of PAT. If there are no
1157 copies return NULL, if there are more than one, return NOT_UNIQUE. */
1159 #define NOT_UNIQUE (&const0_rtx)
1162 unique_src_operand (pat, reg)
1166 register rtx *result = 0;
1167 register const char *fmt;
1171 if (GET_CODE (*pat) == SET)
1173 if (GET_CODE (XEXP (*pat, 0)) == MEM)
1174 result = unique_src_operand (&XEXP (SET_DEST (*pat), 0), reg);
1175 pat = &SET_SRC (*pat);
1178 if (GET_CODE (*pat) == REG && REGNO (*pat) == REGNO (reg))
1181 fmt = GET_RTX_FORMAT (GET_CODE (*pat));
1182 for (i = GET_RTX_LENGTH (GET_CODE (*pat)) - 1; i >= 0; i--)
1186 rtx *new_result = unique_src_operand (&XEXP (*pat, i), reg);
1192 result = new_result;
1195 else if (fmt[i] == 'E')
1197 for (j = XVECLEN (*pat, i) - 1; j >= 0; j--)
1200 unique_src_operand (&XVECEXP (*pat, i, j), reg);
1206 result = new_result;
1214 /* Clean up the instructions to remove unneeded loads and stores.
1216 For example, rewrite
1218 iload a; iload b; iadd; istore z
1219 iload z; iload c; iadd; istore z
1223 iload a; iload b; iadd ; iload c; iadd; istore z
1225 This function moves a cursor over each instruction, inspecting the
1226 LOG_LINKS. Each of the cursor's LOG_LINK incoming instructions are
1227 inspected, any which have a simple register destination which is
1228 also used as a source in the cursor instruction, and aren't used
1229 again between the the incoming instruction and the cursor, and
1230 which become dead or set after the cursor get their sources
1231 substituted into the position of the source register in the cursor
1235 pj_machine_dependent_reorg (insns)
1240 if (!optimize || !TARGET_REORG)
1243 for (cursor = insns; cursor; cursor = NEXT_INSN (cursor))
1248 /* We only care about INSNs, JUMP_INSNs. Ignore any special USE insns. */
1250 if ((GET_CODE (cursor) != INSN && GET_CODE (cursor) != JUMP_INSN)
1251 || GET_CODE (cursor_pat = PATTERN (cursor)) == USE
1252 || GET_CODE (cursor_pat) == CLOBBER
1253 || GET_CODE (cursor_pat) == ADDR_VEC
1254 || GET_CODE (cursor_pat) == ADDR_DIFF_VEC)
1257 for (links = LOG_LINKS (cursor); links; links = XEXP (links, 1))
1259 rtx prev = XEXP (links, 0);
1265 if (GET_CODE (prev) == INSN
1266 && GET_CODE (prev_pat = PATTERN (prev)) == SET
1267 && GET_CODE (prev_dest = SET_DEST (prev_pat)) == REG
1268 && dead_or_set_p (cursor, prev_dest)
1269 && !reg_used_between_p (prev_dest, prev, cursor)
1270 && no_labels_between_p (prev, cursor)
1271 && no_jumps_between_p (prev, cursor)
1272 && !modified_between_p ((prev_src = SET_SRC (prev_pat)), prev,
1274 && (dst_place = unique_src_operand (&cursor_pat, prev_dest))
1275 && dst_place != NOT_UNIQUE
1276 && REGNO (prev_dest) != OPTOP_REG
1277 && GET_MODE (prev_dest) != XFmode
1278 && GET_MODE (*dst_place) == GET_MODE (SET_DEST (prev_pat)))
1280 *dst_place = SET_SRC (prev_pat);
1281 PUT_CODE (prev, NOTE);
1282 NOTE_LINE_NUMBER (prev) = NOTE_INSN_DELETED;