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
));
114 /* These vectors turn a register number into an offset from the vars
116 short pj_si_vars_offset_vec
[FIRST_PSEUDO_REGISTER
];
117 short pj_di_vars_offset_vec
[FIRST_PSEUDO_REGISTER
];
118 short pj_debugreg_renumber_vec
[FIRST_PSEUDO_REGISTER
];
120 /* Number of fake registers in the frame, used by prologue and epilogue
124 /* Whether anything has been printed to the current assembly output
126 int pj_stuff_on_line
;
128 /* Initialize the GCC target structure. */
130 struct gcc_target targetm
= TARGET_INITIALIZER
;
132 /* printf to the asm_out_file, with special format control characters
133 for decoding operands.
136 %d,%x,%c,%s - as printf
137 %X - address constant.
138 %<alpha><digit> - operand <digit> passed to pj_print_operand with code <alpha>. */
141 pj_printf
VPARAMS ((const char *template, ...))
147 VA_OPEN (argptr
, template);
148 VA_FIXEDARG (argptr
, const char *, template);
150 while ((c
= *template++))
152 int was_stuff_on_line
= pj_stuff_on_line
;
153 pj_stuff_on_line
= 1;
157 putc (c
, asm_out_file
);
158 pj_stuff_on_line
= 0;
161 putc (c
, asm_out_file
);
168 putc ('%', asm_out_file
);
170 pj_stuff_on_line
= 1;
173 /* Marks start of opcode, tab out. */
174 if (was_stuff_on_line
)
175 fprintf (asm_out_file
, "; ");
180 fprintf (asm_out_file
, "%d", va_arg (argptr
, int));
184 fprintf (asm_out_file
, "%x", va_arg (argptr
, int));
188 fprintf (asm_out_file
, "%c", va_arg (argptr
, int));
192 fputs (va_arg (argptr
, const char *), asm_out_file
);
196 output_addr_const (asm_out_file
, va_arg (argptr
, rtx
));
203 if (ISALPHA (*template))
205 if (ISDIGIT (*template))
207 int num
= atoi (template);
209 while (ops_read
<= num
)
210 operands
[ops_read
++] = va_arg (argptr
, rtx
);
211 send
= operands
[num
];
214 send
= va_arg (argptr
, rtx
);
216 /* A null means leave the word on the stack, so there's
217 no need to do anything for that. */
220 pj_print_operand (asm_out_file
, send
, code
);
229 /* Output code to efficiently push a single word integer constant onto
233 pj_output_push_int (val
)
236 int low
= ((val
& 0x8000) ? ~0xffff : 0) | (val
& 0xffff);
239 pj_printf ("%*iconst_m1");
240 else if (low
>= 0 && low
<= 5)
241 pj_printf ("%*iconst_%d", low
);
242 else if (low
>= -128 && low
< 128)
243 pj_printf ("%*bipush %d", low
);
245 pj_printf ("%*sipush %d", low
);
247 if ((low
& 0xffff0000) != (val
& 0xffff0000))
248 pj_printf ("%*sethi 0x%x", (val
>> 16) & 0xffff);
251 /* Output code to add a constant to the value on the top of the
255 pj_output_print_add_k (int size
)
259 pj_output_push_int (size
);
260 pj_printf ("%*iadd");
264 pj_output_push_int (-size
);
265 pj_printf ("%*isub");
269 /* Output code to load the value pointed to by the top of stack onto
273 pj_output_load (mode
, uns
)
274 enum machine_mode mode
;
278 switch (GET_MODE_SIZE (mode
))
281 pj_printf (uns
? "%*load_ubyte" : "%*load_byte");
284 pj_printf (uns
? "%*load_char" : "%*load_short");
287 if (TARGET_TM_EXTENSIONS
)
289 pj_printf ("%*tm_load_long");
294 for (i
= GET_MODE_SIZE (mode
); i
> 4; i
-= 4)
297 pj_output_print_add_k (i
- 4);
298 pj_printf ("%*load_word");
299 pj_printf ("%*swap");
301 pj_printf ("%*load_word");
305 /* Output code to increment the provided lval operand. */
308 pj_output_inc (op
, size
)
312 if (STACK_REG_RTX_P (op
))
313 pj_printf ("%*iinc %d,%d", pj_si_vars_offset_vec
[REGNO (op
)], size
);
316 pj_output_rval (op
, SImode
, 0);
317 pj_output_push_int (size
);
318 pj_printf ("%*iadd");
319 pj_output_store_into_lval (SImode
, op
);
323 /* Output the text for a conversion operator. */
326 pj_output_cnv_op (e
, op
)
330 pj_printf ((const char *) insn_data
[(int) e
].output
, 0, XEXP (op
, 0));
333 /* Turn a machine_mode into an opcode modifier chararacter. */
337 enum machine_mode mode
;
360 /* Output an index off the var register. If we're moving an 8 byte
361 value then reduce the index, since the picoJava instruction loading
362 the value uses the index of the highest part of the register as
366 pj_output_varidx (mode
, do_store
, idx
)
367 enum machine_mode mode
;
371 pj_printf ("%*%c%s%c%d",
373 do_store
? "store" : "load",
374 (GET_MODE_SIZE (mode
) == 4 || GET_MODE_SIZE (mode
) == 8)
375 && idx
<= 3 ? '_' : ' ', idx
);
378 /* Output an rvalue expression. */
381 pj_output_rval (op
, mode
, outer_op
)
383 enum machine_mode mode
;
386 enum rtx_code code
= GET_CODE (op
);
390 if (code
== DIV
&& GET_MODE_CLASS (mode
) == MODE_INT
)
393 tab
= code_to_optab
[code
];
397 pj_output_rval (XEXP (op
, 0), mode
, op
);
398 pj_output_rval (XEXP (op
, 1), mode
, op
);
399 pj_printf ("%*%cadd", mode_to_char (mode
));
401 else if (tab
&& tab
->handlers
[mode
].insn_code
!= CODE_FOR_nothing
)
403 const char *const template =
404 (const char *) insn_data
[tab
->handlers
[mode
].insn_code
].output
;
406 pj_printf (template, 0, XEXP (op
, 0));
408 pj_printf (template, 0, XEXP (op
, 0), XEXP (op
, 1));
411 switch (GET_CODE (op
))
414 fprintf (asm_out_file
, " pc ");
418 pj_output_rval (XEXP (op
, 0), mode
, op
);
422 pj_output_rval (XEXP (op
, 0), Pmode
, op
);
423 pj_output_load (mode
, 0);
427 pj_printf ("%*ipush %X", op
);
437 if (pj_si_vars_offset_vec
[REGNO (op
)] >= 0)
438 pj_output_varidx (mode
, 0, pj_si_vars_offset_vec
[REGNO (op
)]);
440 pj_printf ("%*read_%s", reg_names
[REGNO (op
)]);
444 if (pj_di_vars_offset_vec
[REGNO (op
)] >= 0)
445 pj_output_varidx (mode
, 0, pj_di_vars_offset_vec
[REGNO (op
)]);
450 pj_printf ("%*read_global2");
451 pj_printf ("%*read_global1");
454 /* A 64 bit read of global0 gives global0 and
457 pj_printf ("%*read_optop");
458 pj_printf ("%*read_global0");
471 pj_printf (pj_standard_float_constant (op
));
475 if (mode
== SImode
|| mode
== HImode
|| mode
== QImode
)
476 pj_output_push_int (INTVAL (op
));
477 else if (mode
== DImode
)
481 pj_printf ("%*lconst_1", 0);
483 pj_printf ("%*lconst_0", 0);
486 rtx hi
= GEN_INT (v
< 0 ? -1 : 0);
488 pj_output_rval (TARGET_LITTLE_ENDIAN
? hi
: lo
, SImode
, op
);
489 pj_output_rval (TARGET_LITTLE_ENDIAN
? lo
: hi
, SImode
, op
);
497 pj_printf ("%S0%*d2f", XEXP (op
, 0));
500 pj_printf ("%*ipush %X", XEXP (op
, 0));
504 pj_output_rval (alter_subreg (op
), mode
, outer_op
);
508 pj_output_rval (XEXP (op
, 0), mode
, op
);
509 pj_output_inc (XEXP (op
, 0), GET_MODE_SIZE (GET_MODE (outer_op
)));
513 pj_output_rval (XEXP (op
, 0), mode
, op
);
514 pj_output_inc (XEXP (op
, 0), -GET_MODE_SIZE (GET_MODE (outer_op
)));
518 pj_output_inc (XEXP (op
, 0), GET_MODE_SIZE (GET_MODE (outer_op
)));
519 pj_output_rval (XEXP (op
, 0), mode
, op
);
523 if (OPTOP_REG_RTX_P (XEXP (op
, 0)))
524 pj_output_rval (XEXP (op
, 0), mode
, op
);
525 else if (STACK_REG_RTX_P (XEXP (op
, 0)))
527 pj_output_inc (XEXP (op
, 0),
528 -GET_MODE_SIZE (GET_MODE (outer_op
)));
529 pj_output_rval (XEXP (op
, 0), mode
, op
);
533 pj_printf ("%S0", XEXP (op
, 0));
534 pj_output_print_add_k (-GET_MODE_SIZE (GET_MODE (outer_op
)));
535 pj_printf ("%*dup%R0", XEXP (op
, 0));
540 pj_output_cnv_op (fixtrunctab
[GET_MODE (XEXP (op
, 0))][mode
][0], op
);
544 if (mode
== DFmode
&& GET_CODE (XEXP (op
, 0)) == CONST_INT
)
545 pj_output_cnv_op (floattab
[mode
][SImode
][0], op
);
547 pj_output_cnv_op (floattab
[mode
][GET_MODE (XEXP (op
, 0))][0], op
);
552 /* Sign extending from a memop to register is automatic. */
553 if (mode
== SImode
&& GET_CODE (XEXP (op
, 0)) == MEM
)
554 pj_output_rval (XEXP (op
, 0), GET_MODE (XEXP (op
, 0)), op
);
556 pj_output_cnv_op (extendtab
[mode
][GET_MODE (XEXP (op
, 0))][0], op
);
560 pj_output_cnv_op (extendtab
[mode
][GET_MODE (XEXP (op
, 0))][1], op
);
569 /* Store the top of stack into the lval operand OP. */
572 pj_output_store_into_lval (mode
, op
)
573 enum machine_mode mode
;
576 if (GET_CODE (op
) == REG
)
580 /* Outgoing values are left on the stack and not written
582 if (!OUTGOING_REG_RTX_P (op
))
584 switch (GET_MODE (op
))
590 if (pj_si_vars_offset_vec
[rn
] >= 0)
591 pj_output_varidx (mode
, 1, pj_si_vars_offset_vec
[rn
]);
593 pj_printf ("%*write_%s", reg_names
[rn
]);
597 if (pj_di_vars_offset_vec
[rn
] >= 0)
598 pj_output_varidx (mode
, 1, pj_di_vars_offset_vec
[rn
]);
603 pj_printf ("%*write_global1");
604 pj_printf ("%*write_global2");
617 pj_output_rval (XEXP (op
, 0), Pmode
, op
);
619 switch (GET_MODE_SIZE (mode
))
622 pj_printf ("%*store_byte", 0);
625 pj_printf ("%*store_short", 0);
628 if (TARGET_TM_EXTENSIONS
)
630 pj_printf ("%*tm_store_long");
637 for (i
= GET_MODE_SIZE (mode
); i
> 4; i
-= 4)
639 pj_printf ("%*dup_x1", 0);
640 pj_printf ("%*store_word", 0);
641 pj_printf ("%*iconst_4", 0);
642 pj_printf ("%*iadd", 0);
645 pj_printf ("%*store_word", 0);
651 /* Print a condition, unsigned and signed have the same text because
652 the unsigned operands have been run through icmp first. */
661 fputs ("eq", asm_out_file
);
664 fputs ("ne", asm_out_file
);
668 fputs ("gt", asm_out_file
);
672 fputs ("ge", asm_out_file
);
676 fputs ("lt", asm_out_file
);
680 fputs ("le", asm_out_file
);
686 /* Print operand X (an rtx) in assembler syntax to file STREAM
687 according to modifier CODE.
689 C emit the first part of a Check_call pseudop.
690 D emit operand, if no mode, assume DImode.
691 E emit the second part of a check_call pseudop.
692 I print the XEXP (X, 0) Inside of the operand.
693 J print Just the integer or register part of an operand, for iinc.
694 P emit source is SI padded to DI with 0, used for unsigned mod and divide.
695 R emit the operand as an lval Result.
696 S emit Source operand, if no mode, assume SImode.
697 X nan choice suffix for floating point comparision.
698 Y condition name from op.
700 * marks start of opcode. */
703 pj_print_operand (stream
, x
, code
)
708 static int last_call_known
;
712 if (GET_CODE (x
) == SYMBOL_REF
)
715 pj_printf ("%*.check_call %0", x
);
723 GET_MODE (x
) == VOIDmode
? DImode
: GET_MODE (x
),
729 pj_printf (",%d", INTVAL (x
));
733 pj_output_rval (XEXP (x
, 0), GET_MODE (XEXP (x
, 0)), NULL_RTX
);
737 if (GET_CODE (x
) == CONST_INT
)
738 pj_printf ("%d", INTVAL (x
));
739 else if (GET_CODE (x
) == REG
)
740 pj_printf ("%d", pj_si_vars_offset_vec
[REGNO (x
)]);
746 if (TARGET_LITTLE_ENDIAN
)
747 pj_printf ("%*iconst_0", 0);
749 GET_MODE (x
) == VOIDmode
? SImode
: GET_MODE (x
),
751 if (!TARGET_LITTLE_ENDIAN
)
752 pj_printf ("%*iconst_0", 0);
756 pj_output_store_into_lval (GET_MODE (x
), x
);
761 GET_MODE (x
) == VOIDmode
? SImode
: GET_MODE (x
),
766 fputc (GET_CODE (x
) == LT
|| GET_CODE (x
) == LE
? 'g' : 'l', stream
);
770 pj_print_cond (GET_CODE (x
));
774 pj_print_cond (reverse_condition (GET_CODE (x
)));
782 output_addr_const (stream
, x
);
787 /* Return in an rtx the number of words pushed onto the optop to be
788 used as the word count in a call insn. (NEXT_ARG_REG is NULL when
789 called from expand_builtin_apply). */
792 pj_workout_arg_words (stack_size
, next_arg_reg
)
793 rtx stack_size ATTRIBUTE_UNUSED
;
796 return GEN_INT ((next_arg_reg
? REGNO (next_arg_reg
) - O0_REG
: 0) + 2);
799 /* Handle the INCOMING_FUNCTION_ARG macro.
800 Determine where to put an argument to a function.
801 Value is zero to push the argument on the stack,
802 or a hard register in which to store the argument.
804 CUM is a variable of type CUMULATIVE_ARGS which gives info about
805 the preceding args and about the function being called.
806 MODE is the argument's machine mode.
807 TYPE is the data type of the argument (as a tree).
808 This is null for libcalls where that information may
810 NAMED is nonzero if this argument is a named parameter
811 (otherwise it is an extra parameter matching an ellipsis). */
814 pj_function_incoming_arg (cum
, mode
, passed_type
, named_arg
)
815 CUMULATIVE_ARGS
*cum
;
816 enum machine_mode mode
;
817 tree passed_type ATTRIBUTE_UNUSED
;
818 int named_arg ATTRIBUTE_UNUSED
;
820 int arg_words
= PJ_ARG_WORDS (mode
);
822 /* If the whole argument will fit into registers, return the first
823 register needed. Also fill in the arg_adjust information so that
824 we can work out the right offset to use when looking at the
825 insides of a DI or DF value. */
827 if (cum
->total_words
+ arg_words
<= ARGS_IN_REGS
)
830 if (mode
== DImode
|| mode
== DFmode
)
832 cum
->arg_adjust
[cum
->total_words
+ 0] = +1;
833 cum
->arg_adjust
[cum
->total_words
+ 1] = -1;
836 for (i
= 0; i
< arg_words
; i
++)
837 cum
->arg_adjust
[cum
->total_words
+ i
] = 0;
839 return gen_rtx (REG
, mode
, I0_REG
+ cum
->total_words
);
844 /* Output code to add two SImode values. Deals carefully with the the common
845 case of moving the optop. */
848 pj_output_addsi3 (operands
)
851 if (OPTOP_REG_RTX_P (operands
[0]) && OPTOP_REG_RTX_P (operands
[1])
852 && GET_CODE (operands
[2]) == CONST_INT
853 && INTVAL (operands
[2]) >= -32 && INTVAL (operands
[2]) <= 32)
863 { "lconst_0", "iconst_0"}
865 int size
= INTVAL (operands
[2]);
874 for (; size
>= 8; size
-= 8)
875 output_asm_insn (name
[d
].two
, 0);
879 output_asm_insn (name
[d
].one
, 0);
884 if (STACK_REG_RTX_P (operands
[0])
885 && rtx_equal_p (operands
[0], operands
[1])
886 && GET_CODE (operands
[2]) == CONST_INT
887 && INTVAL (operands
[2]) >= -128 && INTVAL (operands
[2]) <= 127)
889 return "iinc %J0,%J2";
892 return "%S1%S2%*iadd%R0";
895 /* Generate rtl for the prologue of the current function. */
898 pj_expand_prologue ()
902 int arg_words
= current_function_args_info
.named_words
;
904 memset (pj_si_vars_offset_vec
, -1, sizeof (pj_si_vars_offset_vec
));
905 memset (pj_di_vars_offset_vec
, -1, sizeof (pj_di_vars_offset_vec
));
907 /* Work out the register numbers of the named arguments. */
908 for (i
= 0; i
< current_function_args_info
.named_words
; i
++)
910 pj_debugreg_renumber_vec
[I0_REG
+ i
]
911 = off
+ R0_REG
+ current_function_args_info
.arg_adjust
[i
];
912 pj_si_vars_offset_vec
[I0_REG
+ i
]
913 = off
+ current_function_args_info
.arg_adjust
[i
];
914 pj_di_vars_offset_vec
[I0_REG
+ i
] = off
;
918 if (current_function_varargs
|| current_function_stdarg
)
920 /* If the function is varadic we need to call the vhelper
921 function. vhelper pops off the unnamed argument words from
922 the opstack and puts them onto the the aggregate stack. The
923 unnamed words are replacedwith two extra arguments, a pointer
924 to the aggreagate stack for the first vararg and the original
927 emit_insn (gen_varargs (GEN_INT (arg_words
* 4)));
928 pj_si_vars_offset_vec
[VA_REG
] = off
++;
933 /* Skip over the return pc and old vars in the frame. */
936 /* Work out the register numbers and offsets from the var pointer
937 for the normal registers. */
940 for (i
= LAST_I_REG
; i
>= R0_REG
; i
--)
941 if (regs_ever_live
[i
] && pj_si_vars_offset_vec
[i
] == -1)
944 pj_si_vars_offset_vec
[i
] = off
;
945 pj_di_vars_offset_vec
[i
] = off
- 1;
946 pj_debugreg_renumber_vec
[i
] = off
+ R0_REG
;
952 fprintf (asm_out_file
, "\n\t! args %d, size %d, fakes %d\n",
954 get_frame_size () / 4,
957 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
958 if (pj_si_vars_offset_vec
[i
] >= 0)
959 fprintf (asm_out_file
, "\t!vars - %d %d: %s\n",
960 pj_si_vars_offset_vec
[i
],
961 pj_di_vars_offset_vec
[i
],
965 /* Make room on the opstack for the fake registers. */
966 if (TARGET_TM_EXTENSIONS
)
967 RTX_FRAME_RELATED_P (emit_insn (gen_tm_frame (GEN_INT (arg_words
),
968 GEN_INT (nfakes
)))) = 1;
970 RTX_FRAME_RELATED_P (emit_insn
972 (gen_rtx_REG (SImode
, OPTOP_REG
),
973 gen_rtx_REG (SImode
, OPTOP_REG
),
974 GEN_INT (-nfakes
* 4)))) = 1;
977 if (frame_pointer_needed
)
978 emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
980 if (get_frame_size ())
981 RTX_FRAME_RELATED_P (emit_insn (gen_addsi3 (stack_pointer_rtx
,
984 (-get_frame_size ())))) = 1;
986 emit_insn (gen_rtx_USE (VOIDmode
, gen_rtx_REG (SImode
, OPTOP_REG
)));
989 /* Generate rtl for the epilogue of the current function. */
992 pj_expand_epilogue ()
994 if (frame_pointer_needed
)
995 emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
996 else if (get_frame_size ())
997 emit_insn (gen_addsi3 (stack_pointer_rtx
,
998 stack_pointer_rtx
, GEN_INT (get_frame_size ())));
1000 emit_insn (gen_addsi3 (gen_rtx_REG (SImode
, OPTOP_REG
),
1001 gen_rtx_REG (SImode
, OPTOP_REG
),
1002 GEN_INT (nfakes
* 4)));
1005 /* If this is a varargs function, then global0 is stashed away on
1006 the top of the optop stack as the last secret argument by the
1007 __vhelper. Pop off the va pointer provided too. */
1009 if (current_function_varargs
|| current_function_stdarg
)
1010 emit_insn (gen_varargs_finish
1011 (GEN_INT (current_function_args_info
.named_words
+ 1)));
1013 emit_insn (gen_rtx_USE (VOIDmode
, gen_rtx_REG (SImode
, OPTOP_REG
)));
1016 /* Return the opcode name for an instruction to load a standard
1017 floating point constant, or NULL. */
1020 pj_standard_float_constant (op
)
1024 enum machine_mode mode
= GET_MODE (op
);
1026 if (GET_CODE (op
) != CONST_DOUBLE
|| (mode
!= DFmode
&& mode
!= SFmode
))
1029 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
1031 if (REAL_VALUES_EQUAL (r
, dconst0
) && !REAL_VALUE_MINUS_ZERO (r
))
1032 return mode
== DFmode
? "%*dconst_0" : "%*fconst_0";
1034 if (REAL_VALUES_EQUAL (r
, dconst1
))
1035 return mode
== DFmode
? "%*dconst_1" : "%*fconst_1";
1037 if (REAL_VALUES_EQUAL (r
, dconst2
))
1038 return mode
== DFmode
? 0 : "%*fconst_2";
1043 /* Read the value at the current address, and decrement by the size.
1044 The function is interesting because we're reading from high memory to low memory
1045 and have to adjust the addresses of reads of 8 byte values
1049 pj_expand_builtin_va_arg (valist
, type
)
1054 HOST_WIDE_INT align
;
1055 HOST_WIDE_INT rounded_size
;
1058 /* Compute the rounded size of the type. */
1059 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
1060 rounded_size
= (((int_size_in_bytes (type
) + align
- 1) / align
) * align
);
1064 addr
= expand_expr (addr_tree
, NULL_RTX
, Pmode
, EXPAND_NORMAL
);
1065 addr
= copy_to_reg (addr
);
1067 /* Aggregates and large scalars are passed by reference. */
1068 if (AGGREGATE_TYPE_P (type
) || rounded_size
> 8)
1070 addr
= gen_rtx_MEM (Pmode
, addr
);
1074 /* adjust address to cope with double word sizes */
1075 if (rounded_size
> 4)
1076 addr
= gen_rtx_PLUS (Pmode
, addr
, GEN_INT (-4));
1078 /* Compute new value for AP; AP = AP - SIZE */
1079 t
= build (MODIFY_EXPR
, TREE_TYPE (valist
), valist
,
1080 build (MINUS_EXPR
, TREE_TYPE (valist
), valist
,
1081 build_int_2 (rounded_size
, 0)));
1083 TREE_SIDE_EFFECTS (t
) = 1;
1085 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
1090 /* Return nonzero if the operand is valid as a source operand; it's
1091 general and it's not an outgoing argument register. */
1094 pj_source_operand (op
, mode
)
1096 enum machine_mode mode
;
1098 return !OUTGOING_REG_RTX_P (op
) && general_operand (op
, mode
);
1101 /* Return nonzero if the operator is a signed compare. */
1104 pj_signed_comparison_operator (op
, mode
)
1106 enum machine_mode mode
;
1108 if (mode
!= GET_MODE (op
))
1111 switch (GET_CODE (op
))
1125 /* Return nonzero if the operator is an unsigned compare. */
1128 pj_unsigned_comparison_operator (op
, mode
)
1130 enum machine_mode mode ATTRIBUTE_UNUSED
;
1132 if (mode
!= GET_MODE (op
))
1135 switch (GET_CODE (op
))
1147 /* Helper function for pj_machine_dependent_reorg. Find the one
1148 instance of register OP in the source part of PAT. If there are no
1149 copies return NULL, if there are more than one, return NOT_UNIQUE. */
1151 #define NOT_UNIQUE (&const0_rtx)
1154 unique_src_operand (pat
, reg
)
1158 register rtx
*result
= 0;
1159 register const char *fmt
;
1163 if (GET_CODE (*pat
) == SET
)
1165 if (GET_CODE (XEXP (*pat
, 0)) == MEM
)
1166 result
= unique_src_operand (&XEXP (SET_DEST (*pat
), 0), reg
);
1167 pat
= &SET_SRC (*pat
);
1170 if (GET_CODE (*pat
) == REG
&& REGNO (*pat
) == REGNO (reg
))
1173 fmt
= GET_RTX_FORMAT (GET_CODE (*pat
));
1174 for (i
= GET_RTX_LENGTH (GET_CODE (*pat
)) - 1; i
>= 0; i
--)
1178 rtx
*new_result
= unique_src_operand (&XEXP (*pat
, i
), reg
);
1184 result
= new_result
;
1187 else if (fmt
[i
] == 'E')
1189 for (j
= XVECLEN (*pat
, i
) - 1; j
>= 0; j
--)
1192 unique_src_operand (&XVECEXP (*pat
, i
, j
), reg
);
1198 result
= new_result
;
1206 /* Clean up the instructions to remove unneeded loads and stores.
1208 For example, rewrite
1210 iload a; iload b; iadd; istore z
1211 iload z; iload c; iadd; istore z
1215 iload a; iload b; iadd ; iload c; iadd; istore z
1217 This function moves a cursor over each instruction, inspecting the
1218 LOG_LINKS. Each of the cursor's LOG_LINK incoming instructions are
1219 inspected, any which have a simple register destination which is
1220 also used as a source in the cursor instruction, and aren't used
1221 again between the the incoming instruction and the cursor, and
1222 which become dead or set after the cursor get their sources
1223 substituted into the position of the source register in the cursor
1227 pj_machine_dependent_reorg (insns
)
1232 if (!optimize
|| !TARGET_REORG
)
1235 for (cursor
= insns
; cursor
; cursor
= NEXT_INSN (cursor
))
1240 /* We only care about INSNs, JUMP_INSNs. Ignore any special USE insns. */
1242 if ((GET_CODE (cursor
) != INSN
&& GET_CODE (cursor
) != JUMP_INSN
)
1243 || GET_CODE (cursor_pat
= PATTERN (cursor
)) == USE
1244 || GET_CODE (cursor_pat
) == CLOBBER
1245 || GET_CODE (cursor_pat
) == ADDR_VEC
1246 || GET_CODE (cursor_pat
) == ADDR_DIFF_VEC
)
1249 for (links
= LOG_LINKS (cursor
); links
; links
= XEXP (links
, 1))
1251 rtx prev
= XEXP (links
, 0);
1257 if (GET_CODE (prev
) == INSN
1258 && GET_CODE (prev_pat
= PATTERN (prev
)) == SET
1259 && GET_CODE (prev_dest
= SET_DEST (prev_pat
)) == REG
1260 && dead_or_set_p (cursor
, prev_dest
)
1261 && !reg_used_between_p (prev_dest
, prev
, cursor
)
1262 && no_labels_between_p (prev
, cursor
)
1263 && no_jumps_between_p (prev
, cursor
)
1264 && !modified_between_p ((prev_src
= SET_SRC (prev_pat
)), prev
,
1266 && (dst_place
= unique_src_operand (&cursor_pat
, prev_dest
))
1267 && dst_place
!= NOT_UNIQUE
1268 && REGNO (prev_dest
) != OPTOP_REG
1269 && GET_MODE (prev_dest
) != XFmode
1270 && GET_MODE (*dst_place
) == GET_MODE (SET_DEST (prev_pat
)))
1272 *dst_place
= SET_SRC (prev_pat
);
1273 PUT_CODE (prev
, NOTE
);
1274 NOTE_LINE_NUMBER (prev
) = NOTE_INSN_DELETED
;