1 /* Subroutines used for code generation on transputer.
2 Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
4 Written by Øyvind Harboe <oyvind.harboe@zylin.com>
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
27 #include "coretypes.h"
34 #include "insn-config.h"
35 #include "insn-flags.h"
40 #include "hard-reg-set.h"
42 #include "insn-config.h"
43 #include "conditions.h"
45 #include "insn-attr.h"
49 #include "basic-block.h"
54 #include "target-def.h"
56 const char *zpu_board_name
;
60 static const int MAX_ADDSP
=15*4;
61 /* GCC's concept of registers and the ZPU's concept of registers sometimes,
62 * but not always refer to the same
64 * Hence we have a table of rtx expressions that redirect to the correct
67 static GTY(()) rtx reg
[R_NUM
];
68 static unsigned int regStackTop
;
70 static int regMapper
[R_NUM
-R_STACK_REG
];
71 static int debug_output
=0;
72 static rtx current_insn
;
73 static int stackOffset
; /* when the RTL references the SP, we need to track the offset */
75 #define missingOperand() \
77 fprintf(stderr, "Instruction emit failure:\n"); \
78 debug_rtx (current_insn); \
79 fprintf(stderr, "\n"); \
83 static int zpu_first_only_push(rtx x
, rtx find
);
84 static int loadstoresp_offset(rtx operand
, int *found
);
85 static void zpu_storesp(int offset
);
86 static int prevImmediate
;
87 static void zpu_asm(const char *format
, rtx
*operands
);
88 static void store_to_operand(rtx
*operand
);
89 static void zpu_loadsp(int offset
);
90 static const char *zpu_immediate(rtx
*operand
);
91 static int calcStackRegSize(void);
92 static int totalStackOffset(void);
94 static int stackSlotNum(int regNo
)
96 if (regMapper
[regNo
-R_STACK_REG
]==-1)
100 return regMapper
[regNo
-R_STACK_REG
];
103 /* sp + offset to stack register */
104 static int stackRegOffset(rtx operand
)
107 num
=stackSlotNum(REGNO(operand
));
108 return current_function_outgoing_args_size
+num
*4-totalStackOffset();
111 static int addSpRange(rtx operand
, int *found
)
115 if (current_function_calls_alloca
)
117 /* no way to know in this case */
121 if ((GET_CODE(operand
)==REG
)&&(REGNO(operand
)<R_NUM
))
123 if (GET_CODE(reg
[REGNO(operand
)])==MEM
)
125 return loadstoresp_offset(reg
[REGNO(operand
)], found
)-totalStackOffset();
128 if ((REGNO(operand
)>=R_STACK_REG
)&&
129 (REGNO(operand
)<=R_STACK_REG_LAST
))
132 return stackRegOffset(operand
);
137 return loadstoresp_offset(operand
, found
)-totalStackOffset();
142 static void pushRegAddress(rtx operand
)
144 /* painful handling of compatiblity with obscure case
145 * of alloca or dynamically sized objects on stack
151 num
=stackSlotNum(REGNO(operand
));
152 regAddr
=GEN_INT(REGNO(hard_frame_pointer_rtx
)*4);
153 zpu_asm("im %0", ®Addr
);
154 zpu_asm("load", NULL
);
155 offset
=GEN_INT(-(get_frame_size()+calcStackRegSize())+num
*4);
156 zpu_immediate(&offset
);
158 zpu_asm("add", NULL
);
162 static void pushreg(rtx operand
)
164 if (REGNO(operand
)<R_STACK_REG
)
166 if (REGNO(operand
)<R_NUM
)
169 addr
=GEN_INT(REGNO(operand
)*4);
170 zpu_asm("im %0", &addr
);
171 zpu_asm("load", &operand
);
176 } else if (REGNO(operand
)<R_NUM
)
178 if (current_function_calls_alloca
)
180 pushRegAddress(operand
);
181 zpu_asm("load", NULL
);
185 num
=stackSlotNum(REGNO(operand
));
186 zpu_loadsp(current_function_outgoing_args_size
+num
*4);
195 static void popreg(rtx operand
)
197 if (REGNO(operand
)<R_STACK_REG
)
199 if (REGNO(operand
)<R_NUM
)
202 addr
=GEN_INT(REGNO(operand
)*4);
203 zpu_asm("im %0", &addr
);
204 zpu_asm("store", &operand
);
206 } else if (REGNO(operand
)<R_NUM
)
208 if (current_function_calls_alloca
)
210 pushRegAddress(operand
);
211 zpu_asm("store", NULL
);
215 num
=stackSlotNum(REGNO(operand
));
216 zpu_storesp(current_function_outgoing_args_size
+num
*4);
225 /* returns true if both are registers and they are the same register*/
226 static int compareReg(rtx a
, rtx b
)
228 if (GET_CODE(a
)!=REG
)
232 if (GET_CODE(b
)!=REG
)
237 return REGNO(a
)==REGNO(b
);
240 static void comment(const char *format ATTRIBUTE_UNUSED
, rtx
*operands ATTRIBUTE_UNUSED
)
243 /* the testsuite chokes on this */
244 output_asm_insn(format
, operands
);
248 const char * zpu_asm_multi(const char *format
, rtx
*operands
, int byteCount ATTRIBUTE_UNUSED
)
251 /* imX, matches IM & IMPCREL */
252 im
=strncmp("im", format
, 2)==0;
254 if (im
&&prevImmediate
)
256 /* we need to break the pipe when two immediate instructions follow eachother */
257 output_asm_insn("nop", operands
);
259 output_asm_insn(format
, operands
);
265 static void zpu_asm(const char *format
, rtx
*operands
)
267 zpu_asm_multi(format
, operands
, 1);
272 struct RegStackEntry
GTY(())
274 rtx reg
; /* the current location of the register */
277 static GTY(()) struct RegStackEntry regStack
[R_NUM
*2];
278 static const unsigned int regStackSize
=sizeof(regStack
)/sizeof(*regStack
);
280 static rtx next_insn_saved
;
281 static rtx current_insn_saved
;
283 static void storeToReg(rtx newLocation
, rtx origReg
)
285 comment("; explicit pop", &newLocation
);
286 if (GET_CODE(newLocation
)==REG
)
292 int loadsp_offset
=loadstoresp_offset(newLocation
, &found
);
295 fprintf(stderr
, "\nZPU: corrupt regStack\n");
299 comment("; store to register on stack %0", &origReg
);
300 zpu_storesp(loadsp_offset
);
305 static void persistReg(rtx t
)
307 storeToReg(reg
[REGNO(t
)], t
);
312 static void discardRegStackTop(int persist
)
316 if ((regStackTop
>regStackSize
)||(regStackTop
<=0))
318 fprintf(stderr
, "ZPU: corrupt regStack\n");
322 /* this is where we pop the register to... */
323 newLocation
=gen_rtx_REG(SImode
, REGNO(regStack
[regStackTop
-1].reg
));
325 /* ...or is it still on the stack? */
326 for (i
=regStackTop
-2; i
>=0; i
--)
328 if (compareReg(regStack
[regStackTop
-1].reg
, regStack
[i
].reg
))
330 newLocation
=gen_rtx_MEM(SImode
,
331 gen_rtx_PLUS(SImode
, gen_rtx_REG(SImode
, R_SP
), GEN_INT(-(i
+1)*4)));
336 reg
[REGNO(regStack
[regStackTop
-1].reg
)]=newLocation
;
340 /* pop the register into the current location */
341 storeToReg(newLocation
, regStack
[regStackTop
-1].reg
);
347 static void popRegStack(void)
349 discardRegStackTop(1);
352 static void pushRegStack(rtx t
)
354 if (regStackTop
>=regStackSize
)
356 fprintf(stderr
, "ZPU: corrupt regStack\n");
360 regStack
[regStackTop
].reg
=t
;
363 /* GCC does not know that we are changing the stack pointer.
365 * Hence the saved registers are at a negative offset to GCC's concept of
368 reg
[REGNO(t
)]=gen_rtx_MEM(SImode
,
369 gen_rtx_PLUS(SImode
, gen_rtx_REG(SImode
, R_SP
), GEN_INT(-regStackTop
*4)));
373 static int zpu_noop_set(rtx insn
)
376 set
=single_set(insn
);
380 GET_CODE (SET_SRC (set
)) == REG
381 && GET_CODE (SET_DEST (set
)) == REG
382 && REGNO (SET_SRC (set
)) == REGNO (SET_DEST (set
));
387 static int zpu_can_be_split(rtx insn
)
390 set
=single_set(insn
);
393 return (GET_MODE(SET_SRC (set
)) != SImode
);
399 /* it is safe to err on the side of caution here and return 0
402 static rtx
zpu_next_insn(rtx insn
)
406 insn
= NEXT_INSN (insn
);
407 switch (GET_CODE(insn
))
413 if (zpu_noop_set(insn
))
415 /* DRAGONS! we must skip noop moves, because they
416 * are eliminated by the emitter
421 if (zpu_can_be_split(insn
))
433 /* we don't handle these */
441 static int stackPlusConst(rtx operand
, int *found
)
445 if(GET_CODE(operand
) != PLUS
)
449 op0
=XEXP (operand
, 0);
450 op1
=XEXP (operand
, 1);
451 if((GET_CODE(op0
)==REG
) &&(REGNO(op0
)==R_SP
)
452 && (GET_CODE(op1
)==CONST_INT
))
457 if((GET_CODE(op1
)==REG
) &&(REGNO(op1
)==R_SP
)
458 && (GET_CODE(op0
)==CONST_INT
))
466 static int loadstoresp_offset(rtx operand
, int *found
)
469 if (GET_MODE(operand
)!=SImode
)
473 if (GET_CODE(operand
)!=MEM
)
477 operand
=XEXP(operand
, 0);
479 if ((GET_CODE(operand
)==REG
)&&(REGNO(operand
)==R_SP
))
484 return stackPlusConst(operand
, found
);
489 int zpu_binary_operator (rtx op ATTRIBUTE_UNUSED
, enum machine_mode mode ATTRIBUTE_UNUSED
)
491 if (GET_MODE(op
)!=SImode
)
496 switch (GET_CODE(op
))
518 return TARGET_ASHIFTRT
;
520 return TARGET_LSHIFTRT
;
537 int zpu_unary_operator (rtx op ATTRIBUTE_UNUSED
, enum machine_mode mode ATTRIBUTE_UNUSED
)
539 if (GET_MODE(op
)!=SImode
)
544 switch (GET_CODE(op
))
558 static int opCheckTerminal(rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
, int strict
)
560 if (CONSTANT_P(op
)&&(GET_CODE(op
)!=CONST_DOUBLE
))
565 switch (GET_CODE(op
))
568 if ((REGNO(op
)<FIRST_PSEUDO_REGISTER
)||!strict
)
570 if ((REGNO(op
)!=R_PC
)&&(REGNO(op
)!=R_SP
))
585 /* This function is not about what the ZPU is capable of, but what
586 * the GCC & the backend wants/needs.
588 static int opCheck(rtx op
, enum machine_mode mode
, int strict
)
590 switch (GET_CODE(op
))
592 /* we support only *2,4,8 */
594 if (opCheckTerminal(XEXP(op
, 0), mode
, strict
))
596 if (GET_CODE(XEXP(op
, 1))==CONST_INT
)
598 int c
=INTVAL(XEXP(op
, 1));
599 if ((c
==2)||(c
==4)||(c
==8))
607 return opCheckTerminal(XEXP(op
, 0), mode
, strict
)&&
608 opCheckTerminal(XEXP(op
, 1), mode
, strict
);
611 if (REG_P(XEXP(op
, 0))&&(REGNO(XEXP(op
, 0))==R_SP
))
618 if (((mode
==DFmode
)||(mode
==DImode
))&&
620 (REGNO(XEXP(op
, 0))==R_SP
))
625 if ((mode
!=SImode
)&&(mode
!=HImode
)&&(mode
!=QImode
))
629 if (REG_P(XEXP(op
, 0))&&
630 ((REGNO(XEXP(op
, 0))<=R_SP
)
632 (!strict
&&(REGNO(XEXP(op
, 0))>=FIRST_PSEUDO_REGISTER
))
642 return opCheckTerminal(op
, mode
, strict
);
650 int zpu_legitimate_address(enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
, int strict ATTRIBUTE_UNUSED
)
654 if (opCheck(x
, SImode
, strict
))
656 return countReg
<MAX_REGS_PER_ADDRESS
;
661 void print_operand (FILE *file
, rtx op
, int letter
)
666 print_rtl (file
, op
);
670 switch (GET_CODE (op
))
673 print_operand(file
, XEXP(op
, 0), letter
);
675 print_operand(file
, XEXP(op
, 1), letter
);
680 fprintf(file
, "%d", REGNO(op
)*4);
683 fprintf(file
, "%s", reg_names
[REGNO (op
)]);
689 if (GET_MODE(op
)==SFmode
)
694 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
695 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
696 asm_fprintf (file
, "%I0x%lx", l
);
699 else if (GET_MODE(op
)==DFmode
)
704 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
705 REAL_VALUE_TO_TARGET_DOUBLE (r
, l
);
706 asm_fprintf (file
, "0x%08x%08x", l
[0], l
[1]);
711 output_addr_const(file
, op
);
716 fprintf(file
, "%d", (int)INTVAL (op
));
722 output_addr_const(file
, op
);
730 print_operand(file
, XEXP (op
, 0), letter
);
739 output_addr_const(file
, op
);
749 static void initGenerate(rtx insn ATTRIBUTE_UNUSED
)
753 if ((next_insn_saved
!=NULL
) && (current_insn
!=next_insn_saved
))
756 fprintf(stderr
, "ZPU: zpu_next_insn() broken\n");
758 debug_rtx(current_insn_saved
);
760 /* for debugging purposes it is useful to look this up again so as
761 * to be able to step through the code
763 t
=zpu_next_insn(current_insn_saved
);
771 static int totalStackOffset(void)
774 /* this is the absolute difference between the ZPU stack
775 * pointer and GCC's concept of a stack pointer
777 t
=stackOffset
-regStackTop
*4;
780 fprintf(stderr
, "ZPU: illegal stack offset %d\n", -t
);
786 static void zpu_pushspadd(int offset
)
789 if (TARGET_PUSHSPADD
)
791 t
=GEN_INT((offset
+4)/4);
792 zpu_asm("im %0", &t
);
793 zpu_asm("pushspadd", &t
);
797 zpu_asm("pushsp", &t
);
800 zpu_asm("im %0", &t
);
806 static void zpu_addsp(int offset
)
812 zpu_asm("addsp %0", &t
);
815 zpu_asm("pushsp", NULL
);
818 zpu_asm("im %0", &t
);
819 zpu_asm("add", NULL
);
821 zpu_asm("load", NULL
);
822 zpu_asm("add", NULL
);
826 static void zpu_coreloadsp(int offset
)
835 if (TARGET_LOADSP
&&(offset
/4<32))
837 zpu_asm("loadsp %0", &t
);
840 zpu_pushspadd(offset
);
847 static void zpu_loadsp(int offset
)
850 offset
-=totalStackOffset();
852 zpu_coreloadsp(offset
);
857 static void zpu_storesp(int offset
)
860 offset
-=totalStackOffset();
867 if (TARGET_STORESP
&&(offset
/4<32))
870 zpu_asm("storesp %0", &t
);
873 zpu_pushspadd(offset
);
874 zpu_asm("store", &t
);
880 static int zpu_stack_change(rtx x
)
886 rtx dest
=SET_DEST(set
);
887 rtx src
=SET_SRC(set
);
888 if ((GET_CODE(dest
)==REG
)&&(REGNO(dest
)==R_SP
))
893 if (GET_CODE(dest
)==MEM
)
895 if (GET_CODE(XEXP(dest
, 0))==PRE_DEC
)
897 if (REG_P(XEXP(XEXP(dest
, 0), 0))&®NO(XEXP(XEXP(dest
, 0), 0))==R_SP
)
903 if ((GET_CODE(dest
)==REG
)&&(REGNO(dest
)==R_SP
))
907 if (GET_CODE(src
)==MEM
)
909 if (GET_CODE(XEXP(src
, 0))==POST_INC
)
911 if (REG_P(XEXP(XEXP(src
, 0), 0))&®NO(XEXP(XEXP(src
, 0), 0))==R_SP
)
922 static int isInBasicBlock(rtx insn
)
928 if (GET_CODE(insn
)==INSN
)
930 if (!zpu_stack_change(insn
))
933 set
=single_set(insn
);
936 if (GET_CODE(SET_SRC(set
))!=ASM_OPERANDS
)
949 static void cleanupGenerate(void)
954 fprintf(stderr
, "ZPU: stackOffset %d\n", stackOffset
);
958 /* purge all dead registers off the stack */
959 while ((regStackTop
>0)&&find_regno_note(current_insn
, REG_DEAD
, REGNO(regStack
[regStackTop
-1].reg
)))
964 /* if we are at the end of the basic block, we must clean up
965 * any unpopped registers
967 t
=zpu_next_insn (current_insn
);
968 next_insn_saved
=NULL_RTX
;
969 current_insn_saved
=current_insn
;
971 if (isInBasicBlock(t
))
976 comment("; barrier, purge regstack", ¤t_insn
);
977 while (regStackTop
>0)
985 static void push_operand_address(rtx
*operand
);
986 static void push_operand_value(rtx
*operand
);
989 static const char *zpu_immediate(rtx
*operand
)
991 zpu_asm("im %0", operand
);
996 static void zpu_neg(rtx
*operand
)
1000 zpu_asm("neg", operand
);
1003 /* FIX!!! is this the right sequence? */
1004 zpu_asm("im 1", operand
);
1005 zpu_asm("add", operand
);
1006 zpu_asm("not", operand
);
1011 /* is "find" the first operand to be pushed in "x".
1013 * It is safe to err on the side of caution and say "no", it will
1014 * only potentially make the code ever so slightly less efficient.
1016 static int zpu_first_push(rtx x
, rtx find
)
1020 const char *format_ptr
;
1039 return zpu_first_push(SET_SRC(x
), find
);
1045 return zpu_first_push(XEXP(x
, 0), find
)||zpu_first_push(XEXP(x
, 1), find
);
1050 /* these are handled by the generic code below */
1055 /* err on the side of caution */
1060 format_ptr
= GET_RTX_FORMAT (code
);
1063 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
1065 switch (*format_ptr
++)
1068 return zpu_first_push (XEXP (x
, i
), find
);
1071 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1072 return zpu_first_push (XVECEXP (x
, i
, j
), find
);
1078 static void zpu_call_asm(void)
1082 zpu_asm("call", NULL
);
1086 zpu_asm("pushsp ; CALL insn - duplicate top of stack", NULL
);
1087 zpu_asm("load", NULL
);
1088 zpu_asm("im 6 ; post POPC address", NULL
);
1089 zpu_asm("pushpc", NULL
);
1090 zpu_asm("add", NULL
);
1091 zpu_asm("pushsp", NULL
);
1092 zpu_asm("im 4", NULL
);
1093 zpu_asm("add", NULL
);
1094 zpu_asm("store", NULL
);
1095 zpu_asm("poppc ; call function ", NULL
);
1101 static void zpu_gen_call(rtx
*operand
)
1103 comment("/* call %R0 */", operand
);
1105 if (GET_CODE(operand
[0])!=MEM
)
1110 if (TARGET_CALLPCREL
&&CONSTANT_P(XEXP(operand
[0], 0)))
1112 zpu_asm("impcrel %0", operand
);
1113 zpu_asm("callpcrel", operand
);
1116 /* address to call... */
1117 push_operand_address(operand
);
1121 fprintf(stderr
, "ZPU: regStackTop %d\n", regStackTop
);
1133 zpu_count_occurrences (rtx x
, rtx find
)
1137 const char *format_ptr
;
1152 if ((GET_CODE(x
) == REG
)&&(REGNO(x
)==REGNO(find
)))
1156 format_ptr
= GET_RTX_FORMAT (code
);
1159 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
1161 switch (*format_ptr
++)
1164 count
+= zpu_count_occurrences (XEXP (x
, i
), find
);
1168 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1169 count
+= zpu_count_occurrences (XVECEXP (x
, i
, j
), find
);
1176 /* we must err on the side of caution here. */
1177 static int zpu_first_only_push(rtx x
, rtx find
)
1180 if (zpu_first_push(x
, find
))
1189 if (zpu_count_occurrences(x
, find
)==1)
1203 * - the GCC-register is REG_DEAD or overwritten
1204 * - the GCC-register is on top of the stack
1205 * - the first push in the instruction is the GCC-register
1206 * - we only use the register once in the operation
1208 * then we can simply remove the instructions that pop/push
1210 static int dead_or_overwritten(rtx insn
, rtx op
)
1213 if (find_regno_note(insn
, REG_DEAD
, REGNO (op
)))
1218 rtx set
= single_set (insn
);
1221 if (SET_DEST(set
)==op
)
1231 /* Check if the operand on the regStack is one of the operands and
1234 static void push_assosiative(rtx operand
)
1236 if ((regStackTop
>0)&&compareReg(regStack
[regStackTop
-1].reg
, XEXP(operand
, 1)))
1238 push_operand_value(&XEXP(operand
, 1));
1239 push_operand_value(&XEXP(operand
, 0));
1242 /* either this is the other correct way, or it doesn't matter which way we
1245 push_operand_value(&XEXP(operand
, 0));
1246 push_operand_value(&XEXP(operand
, 1));
1251 static int isFreePopPush(rtx
*operand
)
1254 if ((GET_CODE(*operand
)==REG
)&&(REGNO(*operand
)<R_NUM
)&&(GET_CODE(reg
[REGNO(*operand
)])==MEM
))
1256 /* the GCC-register must be on top of the stack for a free push */
1261 fprintf(stderr
, "ZPU: regStack corrupted\n");
1265 if (dead_or_overwritten(current_insn
, *operand
))
1267 if (zpu_first_only_push(current_insn
, *operand
))
1269 comment("; stripping regstack until free pop&push is found %0", operand
);
1270 /* strip the regstack until we have a free pop */
1271 while (!compareReg(regStack
[regStackTop
-1].reg
, *operand
))
1280 comment("; eliminated pop&push %0", operand
);
1283 fprintf(stderr
, "ZPU: eliminated poppush!\n");
1284 debug_rtx (current_insn
);
1294 static int postIncMemSize
;
1295 static void push_operand_value(rtx
*operand
)
1297 if (CONSTANT_P(*operand
))
1299 zpu_immediate(operand
);
1304 if (GET_CODE(*operand
)==REG
)
1306 if (REGNO(*operand
)==R_PC
)
1308 zpu_asm("pushpc", operand
);
1310 } else if (REGNO(*operand
)==R_SP
)
1312 zpu_asm("pushsp", operand
);
1319 if (totalStackOffset()<0)
1321 rtx offset
=GEN_INT(-totalStackOffset());
1322 comment("; stack adjustment offset", &offset
);
1323 zpu_asm("im %0", &offset
);
1324 zpu_asm("add", operand
);
1328 } else if (REGNO(*operand
)<R_NUM
)
1330 /* push GCC-register */
1331 if (GET_CODE(reg
[REGNO(*operand
)])==MEM
)
1333 if (isFreePopPush(operand
))
1335 /* we pretend we pushed it into the stack and clear the top
1338 discardRegStackTop(0);
1342 comment("; referring to unpopped register %0", operand
);
1345 fprintf(stderr
, "ZPU: unpopped register\n");
1346 debug_rtx (reg
[REGNO(*operand
)]);
1348 push_operand_value(®
[REGNO(*operand
)]);
1360 } else if (GET_CODE (*operand
) == POST_INC
)
1364 reg
=XEXP (*operand
, 0);
1365 if (GET_CODE(reg
)!=REG
)
1370 if (REGNO(reg
)>=R_SP
)
1375 push_operand_value(®
);
1379 size
=GEN_INT(postIncMemSize
);
1380 zpu_asm("im %0", &size
);
1381 zpu_asm("add", operand
);
1383 /* we must not leave anything on the stack here */
1385 } else if (GET_CODE (*operand
) == MEM
)
1388 int loadsp_offset
=loadstoresp_offset(*operand
, &found
);
1389 if ((GET_CODE(XEXP (*operand
, 0))==POST_INC
)&&(GET_CODE(XEXP (XEXP (*operand
, 0), 0))==REG
)&&(REGNO(XEXP (XEXP (*operand
, 0), 0))==R_SP
))
1391 /* NOTE!!! We pop this off the stack even though it was placed there before we entered
1392 * this tree expansion. */
1396 zpu_loadsp(loadsp_offset
);
1399 postIncMemSize
=GET_MODE_SIZE(GET_MODE(*operand
));
1401 push_operand_value(&XEXP (*operand
, 0));
1402 switch (GET_MODE(*operand
))
1406 zpu_asm("load", operand
);
1411 zpu_asm("loadh", NULL
);
1414 zpu_asm("im _loadh", NULL
);
1421 zpu_asm("loadb", NULL
);
1424 zpu_asm("im _loadb", NULL
);
1430 fprintf(stderr
, "FIX!!!! miissing operand\n");
1431 print_rtl(stderr
, *operand
);
1432 fprintf(stderr
, "\n");
1436 } else if (GET_CODE(*operand
)==PLUS
)
1440 offset
=stackPlusConst(*operand
, &found
);
1441 if (found
&&((offset
%4)==0))
1443 offset
-=totalStackOffset();
1444 zpu_pushspadd(offset
);
1447 if (isFreePopPush(&XEXP(*operand
, 0))||isFreePopPush(&XEXP(*operand
, 1)))
1449 push_assosiative(*operand
);
1450 zpu_asm("add", operand
);
1454 offset
=addSpRange(XEXP(operand
[0], 0), &found
);
1455 if ((!found
)||((offset
+4)>MAX_ADDSP
))
1457 push_operand_value(&XEXP(operand
[0], 0));
1458 offset
=addSpRange(XEXP(operand
[0], 1), &found
);
1459 if (found
&&(offset
<=MAX_ADDSP
))
1464 push_operand_value(&XEXP(operand
[0], 1));
1465 zpu_asm("add", NULL
);
1470 push_operand_value(&XEXP(operand
[0], 1));
1471 zpu_addsp(offset
+4);
1474 } else if ((GET_CODE(*operand
)==COMPARE
)||(GET_CODE(*operand
)==MINUS
))
1476 push_operand_value(&XEXP (*operand
, 0));
1477 push_operand_value(&XEXP (*operand
, 1));
1478 zpu_asm("sub", operand
);
1480 } else if (GET_CODE(*operand
)==LABEL_REF
)
1482 zpu_immediate(operand
);
1483 } else if (GET_CODE(*operand
)==SYMBOL_REF
)
1485 zpu_immediate(operand
);
1486 } else if (GET_CODE(*operand
)==CODE_LABEL
)
1488 zpu_immediate(operand
);
1489 } else if (GET_CODE(*operand
)==XOR
)
1491 push_assosiative(*operand
);
1492 zpu_asm("xor", operand
);
1493 stackOffset
+=4; /* lost one */
1494 } else if (GET_CODE(*operand
)==AND
)
1496 push_assosiative(*operand
);
1497 zpu_asm("and", operand
);
1498 stackOffset
+=4; /* lost one */
1499 } else if (GET_CODE(*operand
)==IOR
)
1501 push_assosiative(*operand
);
1502 zpu_asm("or", operand
);
1503 stackOffset
+=4; /* lost one */
1504 } else if (GET_CODE(*operand
)==NOT
)
1506 push_operand_value(&XEXP (*operand
, 0));
1507 zpu_asm("not", operand
);
1508 } else if (GET_CODE(*operand
)==NEG
)
1510 push_operand_value(&XEXP (*operand
, 0));
1512 } else if ((GET_CODE(*operand
)==EQ
)||(GET_CODE(*operand
)==NE
))
1514 push_operand_value(&XEXP (*operand
, 0));
1515 push_operand_value(&XEXP (*operand
, 1));
1518 zpu_asm("eq", operand
);
1521 zpu_asm("im _eq", NULL
);
1524 if (GET_CODE(*operand
)==NE
)
1527 zpu_asm("not", operand
);
1528 zpu_asm("im 1", operand
);
1529 zpu_asm("and", operand
);
1531 stackOffset
+=4; /* lost one */
1532 } else if ((GET_CODE(*operand
)==LE
)||(GET_CODE(*operand
)==GE
)||
1533 (GET_CODE(*operand
)==LEU
)||(GET_CODE(*operand
)==GEU
)||
1534 (GET_CODE(*operand
)==GT
)||(GET_CODE(*operand
)==LT
)||
1535 (GET_CODE(*operand
)==GTU
)||(GET_CODE(*operand
)==LTU
))
1540 int code
=GET_CODE(*operand
);
1542 comment("/* %R0 */", operand
);
1544 /* 'less than' is the base case here and then we tweak it into the
1547 sign
=(code
==GE
) || (code
==LE
) || (code
==GT
) || (code
==LT
);
1548 flip_args
=(code
==GT
) || (code
==GE
) || (code
==GTU
) || (code
==GEU
);
1549 equal
=(code
==GE
) || (code
==LE
) || (code
==GEU
) || (code
==LEU
);
1551 push_operand_value(&XEXP (*operand
, flip_args
?0:1)); /* b */
1552 push_operand_value(&XEXP (*operand
, flip_args
?1:0)); /* a */
1560 zpu_asm("ulessthanorequal", operand
);
1563 zpu_asm("im _ulessthanorequal", NULL
);
1570 zpu_asm("ulessthan", operand
);
1573 zpu_asm("im _ulessthan", NULL
);
1583 zpu_asm("lessthanorequal", operand
);
1586 zpu_asm("im _lessthanorequal", NULL
);
1593 zpu_asm("lessthan", operand
);
1596 zpu_asm("im _lessthan", NULL
);
1602 stackOffset
+=4; /* lost one */
1603 } else if (GET_CODE(*operand
)==LSHIFTRT
)
1605 push_operand_value(&XEXP (*operand
, 0));
1606 push_operand_value(&XEXP (*operand
, 1));
1607 zpu_asm("lshiftright", operand
);
1608 stackOffset
+=4; /* lost one */
1609 } else if (GET_CODE(*operand
)==ASHIFTRT
)
1611 push_operand_value(&XEXP (*operand
, 0));
1612 push_operand_value(&XEXP (*operand
, 1));
1613 zpu_asm("ashiftright", operand
);
1614 stackOffset
+=4; /* lost one */
1615 } else if (GET_CODE(*operand
)==ASHIFT
)
1617 if ((GET_CODE(XEXP (*operand
, 1))==CONST_INT
)&&(INTVAL(XEXP (*operand
, 1))==1))
1619 push_operand_value(&XEXP (*operand
, 0));
1623 push_operand_value(&XEXP (*operand
, 0));
1624 push_operand_value(&XEXP (*operand
, 1));
1625 zpu_asm("ashiftleft", operand
);
1626 stackOffset
+=4; /* lost one */
1628 } else if (GET_CODE(operand
[0])==MULT
)
1631 /* NOTE! This is a most crucial optimisation as MULT is used in
1634 if ((GET_CODE(XEXP(*operand
, 1))==CONST_INT
))
1636 int c
=INTVAL(XEXP(*operand
, 1));
1642 if ((c
==2)||((optimize
&&!optimize_size
)&&((c
==4)||(c
==8))))
1645 push_operand_value(&XEXP (*operand
, 0));
1656 push_operand_value(&XEXP (*operand
, 0));
1657 push_operand_value(&XEXP (*operand
, 1));
1658 zpu_asm("mult", operand
);
1661 } else if (GET_CODE(operand
[0])==DIV
)
1663 push_operand_value(&XEXP (*operand
, 1));
1664 push_operand_value(&XEXP (*operand
, 0));
1665 zpu_asm("div", operand
);
1667 } else if (GET_CODE(operand
[0])==MOD
)
1669 push_operand_value(&XEXP (*operand
, 1));
1670 push_operand_value(&XEXP (*operand
, 0));
1671 zpu_asm("mod", operand
);
1673 } else if (GET_CODE(operand
[0])==ZERO_EXTEND
)
1675 push_operand_value(&XEXP (*operand
, 0));
1676 if (GET_CODE(XEXP (*operand
, 0))!=MEM
)
1678 switch (GET_MODE(XEXP (*operand
, 0)))
1681 /* its a bit silly to extend a VOIDmode, i.e. a constant,
1687 zpu_asm("im 0xff", operand
);
1688 zpu_asm("and", operand
);
1691 zpu_asm("im 0xffff", operand
);
1692 zpu_asm("and", operand
);
1700 print_rtl(stderr
, *operand
);
1709 /* even registers have addresses on a ZPU that we can push onto the stack */
1710 static void push_operand_address(rtx
*operand
)
1712 if (GET_CODE (*operand
) == MEM
)
1714 push_operand_value(&XEXP (*operand
, 0));
1715 } else if (GET_CODE(*operand
)==SYMBOL_REF
)
1717 zpu_immediate(operand
);
1718 } else if (GET_CODE (*operand
) == REG
)
1720 push_operand_value(operand
);
1728 static void store_to_operand(rtx
*operand
)
1730 if (GET_CODE(*operand
)==PC
)
1732 zpu_asm("poppc ; jump", operand
);
1734 } else if (GET_CODE(*operand
)==REG
)
1736 if (REGNO(*operand
)==R_SP
)
1738 zpu_asm("popsp", operand
);
1740 } else if (REGNO(*operand
)==R_PC
)
1742 zpu_asm("poppc ; jump", operand
);
1744 } else if (REGNO(*operand
)<R_NUM
)
1746 if (regStackTop
<regStackSize
)
1748 /* we always leave the value on the stack, if there is space
1750 * The cleanupGenerate() handles this case.
1752 comment("; left %0 on stack", operand
);
1753 pushRegStack(*operand
);
1757 comment("; regStack full", operand
);
1758 persistReg(*operand
);
1764 } else if (GET_CODE(operand
[0])==MEM
)
1767 int loadsp_offset
=loadstoresp_offset(*operand
, &found
);
1768 if ((GET_MODE(operand
[0])!=SFmode
)&&(GET_MODE(operand
[0])!=SImode
)&&(GET_MODE(operand
[0])!=HImode
)&&(GET_MODE(operand
[0])!=QImode
))
1770 fprintf(stderr
, "\nUnsupported dest\n");
1771 print_rtl (stderr
, *operand
);
1772 fprintf(stderr
, "\n");
1777 if (GET_CODE(XEXP (operand
[0], 0))==PRE_DEC
)
1779 rtx reg
=XEXP(XEXP(operand
[0], 0), 0);
1784 if (REGNO(reg
)==R_SP
)
1786 /* we've already pushed the result onto the stack. */
1787 /* we tell a small lie. We change the SP during tree expansion, but we intended to */
1795 zpu_storesp(loadsp_offset
);
1799 postIncMemSize
=GET_MODE_SIZE(GET_MODE(*operand
));
1801 push_operand_address(operand
);
1802 switch (GET_MODE(operand
[0]))
1806 zpu_asm("store", operand
);
1811 zpu_asm("storeh", NULL
);
1814 zpu_asm("im _storeh", NULL
);
1821 zpu_asm("storeb", NULL
);
1824 zpu_asm("im _storeb", NULL
);
1830 fprintf(stderr
, "FIX!!!! Missing operand\n");
1831 print_rtl(stderr
, *operand
);
1832 fprintf(stderr
, "\n");
1839 fprintf(stderr
, "\nUnsupported dest\n");
1840 print_rtl (stderr
, *operand
);
1841 fprintf(stderr
, "\n");
1850 const char *zpu_generate_move(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
1854 comment("/* move %R1, %R0 */", operands
);
1856 /* first we push the source onto the stack, then we figure out the
1859 push_operand_value(operands
+1);
1861 store_to_operand(operands
+0);
1868 const char *zpu_generate_set(rtx insn
)
1873 set
=single_set(insn
);
1874 comment("/* %R0 */", &set
);
1876 /* first we push the source onto the stack, then we figure out the
1879 push_operand_value(&SET_SRC(set
));
1881 store_to_operand(&SET_DEST(set
));
1888 static void zpu_neqbranch(rtx operand
)
1891 zpu_asm("impcrel %0", &operand
);
1892 if (TARGET_NEQBRANCH
)
1895 zpu_asm("neqbranch", NULL
);
1898 zpu_asm("im _neqbranch", NULL
);
1904 const char *zpu_generate_if_then_else(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
1908 comment("/* if_then_else %R0 */", operands
);
1910 /* evaluate boolean expression. this RTL contains the two suboperands */
1911 push_operand_value(&operands
[0]);
1915 fprintf(stderr
, "ZPU: regStackTop %d\n", regStackTop
);
1919 zpu_neqbranch(operands
[3]);
1929 const char *zpu_generate_if_not_zero_then_else(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
1931 if ((GET_CODE(operands
[2])!=CONST_INT
)||INTVAL(operands
[2])!=0)
1933 return zpu_generate_if_then_else(operands
, insn
);
1938 /* evaluate boolean expression. this RTL contains the two suboperands */
1939 push_operand_value(&operands
[0]);
1941 zpu_neqbranch(operands
[1]);
1951 static const char *zpu_jump_core(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
, int table
)
1954 comment("/* jump %R0 */", operands
);
1956 /* put address on stack */
1957 push_operand_value(operands
+0);
1961 comment("/* tablejump */", operands
);
1964 zpu_asm("poppc", operands
);
1972 const char *zpu_jump(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
1974 return zpu_jump_core(operands
, insn
, 0);
1977 const char *zpu_table_jump(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
1979 return zpu_jump_core(operands
, insn
, 1);
1983 const char *zpu_jump_pcrel(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
1989 fprintf(stderr
, "ZPU: regStackTop %d\n", regStackTop
);
1993 /* put address on stack */
1994 if (TARGET_POPPCREL
)
1996 zpu_asm("impcrel %0", operands
);
1997 zpu_asm("poppcrel", operands
);
2000 zpu_asm("im %0", operands
);
2001 zpu_asm("poppc", NULL
);
2010 const char *generate_branch(enum rtx_code code ATTRIBUTE_UNUSED
, rtx loc
, rtx insn
)
2012 return zpu_jump(&loc
, insn
);
2015 const char *zpu_push(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
2018 comment("/* push %R0 */", operands
);
2019 push_operand_value(operands
+0);
2021 /* we tell a small lie. We change the SP during tree expansion, but we intended to */
2030 static int reg_save(int regno
)
2033 if (regs_ever_live
[regno
]&&!call_used_regs
[regno
])
2037 /* FIX!!! how do we check if we've eliminated the argument pointer? */
2041 static int calcSavedSize(void)
2045 for (regno
= 0; regno
< R_STACK_REG
; regno
++)
2046 if (reg_save(regno
))
2053 static int calcStackRegSize(void)
2057 for (regno
= R_STACK_REG
; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
2058 if (reg_save(regno
))
2066 /* Define the offset between two registers, one to be eliminated, and the
2067 other its replacement, at the start of a routine. */
2068 int zpu_initial_elimination_offset (int from
, int to
)
2071 /* The difference between the argument pointer and the stack pointer is
2072 * the sum of the size of this function's frame, the callee register save
2073 * area, and the fixed stack space needed for function calls (if any).
2075 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
2077 offset
=current_function_outgoing_args_size
+ calcStackRegSize() + get_frame_size () + calcSavedSize() + 4 ;
2078 } else if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
2080 offset
=calcSavedSize() + 4;
2081 } else if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
2083 offset
=current_function_outgoing_args_size
+ calcStackRegSize() + get_frame_size ();
2084 } else if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
2094 static int allocFrameSize(void)
2096 return current_function_outgoing_args_size
+calcStackRegSize()+get_frame_size();
2099 void zpu_expand_prologue (void)
2105 HOST_WIDE_INT frameSize
;
2109 for (i
=R_STACK_REG
; i
<R_NUM
; i
++)
2111 regMapper
[i
-R_STACK_REG
]=-1;
2114 for (i
=0; i
<R_NUM
; i
++)
2116 if ((i
>=R_STACK_REG
)&®_save(i
))
2118 regMapper
[i
-R_STACK_REG
]=mapper
++;
2120 reg
[i
]=gen_rtx_REG(SImode
, i
);
2125 mem_push_rtx
= gen_rtx_MEM (SImode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2127 /* Push each of the registers to save. */
2128 for (regno
= 0; regno
< R_STACK_REG
; regno
++)
2129 if (reg_save(regno
))
2131 insn
= emit_move_insn (mem_push_rtx
, gen_rtx_REG (SImode
, regno
));
2132 RTX_FRAME_RELATED_P (insn
) = 1;
2135 /* Set up the frame pointer, if required. */
2136 if (frame_pointer_needed
)
2138 insn
= emit_move_insn (hard_frame_pointer_rtx
, stack_pointer_rtx
);
2139 RTX_FRAME_RELATED_P (insn
) = 1;
2141 /* DANGER!!!! I believe that we can trust the GCC compiler to
2142 * always eliminate the argument pointer register, if not we're
2143 * in trouble, because we do not emit any code here */
2145 frameSize
=allocFrameSize();
2148 insn
=emit_move_insn (stack_pointer_rtx
,
2149 gen_rtx_PLUS (SImode
, stack_pointer_rtx
, GEN_INT (-frameSize
)));
2150 RTX_FRAME_RELATED_P (insn
) = 1;
2155 void zpu_expand_epilogue (void)
2157 rtx mem_pop_rtx
, insn
;
2159 HOST_WIDE_INT frameSize
;
2162 mem_pop_rtx
= gen_rtx_MEM (SImode
, gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
));
2164 frameSize
=allocFrameSize();
2167 insn
= emit_move_insn (stack_pointer_rtx
,
2168 gen_rtx_PLUS (SImode
, stack_pointer_rtx
, GEN_INT (frameSize
)));
2169 RTX_FRAME_RELATED_P (insn
) = 1;
2172 /* Restore any call-saved registers. */
2173 for (regno
= R_STACK_REG
- 1; regno
>= 0; regno
--)
2174 if (reg_save(regno
))
2176 insn
= emit_move_insn (gen_rtx_REG (SImode
, regno
), mem_pop_rtx
);
2179 /* FIX! a single poppc should suffice for no argument fn's */
2180 mem_push_rtx
= gen_rtx_MEM (SImode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2181 insn
= emit_jump_insn (gen_zpu_return());
2184 rtx
zpu_return_addr_rtx(void)
2186 return gen_rtx_MEM (Pmode
, plus_constant (virtual_incoming_args_rtx
, -4));
2190 const char *zpu_call(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
2194 zpu_gen_call(operands
);
2201 const char *zpu_call_value(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
2205 zpu_gen_call(operands
+1);
2207 if ((GET_CODE(operands
[0])!=REG
)&&(REGNO(operands
[0])!=R_R0
))
2209 rtx reg
=gen_rtx_REG(SImode
, 0);
2213 store_to_operand(operands
+0);
2220 /* change all QImode and HImode to SImode load's*/
2222 void zpu_expand_set(enum machine_mode mode
, rtx operands
[])
2224 emit_insn(gen_rtx_SET(mode
, operands
[0], operands
[1]));
2230 zpu_file_start (void)
2232 default_file_start ();
2235 /* Value is the number of bytes of arguments automatically
2236 popped when returning from a subroutine call.
2237 FUNDECL is the declaration node of the function (as a tree),
2238 FUNTYPE is the data type of the function (as a tree),
2239 or for a library call it is an identifier node for the subroutine name.
2240 SIZE is the number of bytes of arguments passed on the stack.
2242 On the ZPU, the RET insn may be used to pop them if the number
2243 of args is fixed, but if the number is variable then the caller
2245 Use of RET is should be a selectable option, since it is incompatible with
2246 standard Unix calling sequences. If the option is not selected,
2247 the caller must always pop the args.
2252 zpu_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
, tree funtype
, int size
)
2254 if (TREE_CODE (funtype
) == IDENTIFIER_NODE
)
2257 if (TYPE_ARG_TYPES (funtype
) == NULL_TREE
2258 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype
))) == void_type_node
))
2269 move_double_src_operand (rtx op
, enum machine_mode mode
)
2271 switch (GET_CODE (op
))
2278 /* FIX! not entirely sure why this isn't
2279 * handled by register_operand
2284 return register_operand (op
, mode
);
2287 /* (subreg (mem ...) ...) can occur here if the inner part was once a
2288 pseudo-reg and is now a stack slot. */
2289 if (GET_CODE (SUBREG_REG (op
)) == MEM
)
2290 return move_double_src_operand (SUBREG_REG (op
), mode
);
2292 return register_operand (op
, mode
);
2295 /* Disallow auto inc/dec for now. */
2296 if ((GET_CODE (XEXP (op
, 0)) == POST_INC
)&&
2297 (!REG_P(XEXP (XEXP (op
, 0), 0))||
2298 REGNO(XEXP (XEXP (op
, 0), 0)))!=R_SP
)
2300 return memory_operand (op
, mode
);
2306 /* Return true if OP is an acceptable argument for a move destination. */
2309 move_double_dest_operand (rtx op
, enum machine_mode mode
)
2311 switch (GET_CODE (op
))
2315 return register_operand (op
, mode
);
2318 /* (subreg (mem ...) ...) can occur here if the inner part was once a
2319 pseudo-reg and is now a stack slot. */
2320 if (GET_CODE (SUBREG_REG (op
)) == MEM
)
2321 return address_operand (XEXP (SUBREG_REG (op
), 0), mode
);
2323 return register_operand (op
, mode
);
2326 /* Disallow auto inc for now. */
2327 if (GET_CODE (XEXP (op
, 0)) == POST_INC
)
2330 /* FIX!!!! a) why isn't this necessary? b) why does it break compilation? */
2331 if ((GET_CODE (XEXP (op
, 0)) == PRE_DEC
)&&
2332 ((!REG_P(XEXP (XEXP (op
, 0), 0))||
2333 REGNO(XEXP (XEXP (op
, 0), 0)))!=R_SP
))
2336 return memory_operand (op
, mode
);
2343 /* Split a 2 word move (DI or DF) into component parts. */
2346 gen_split_move_double (rtx operands
[])
2348 enum machine_mode mode
= GET_MODE (operands
[0]);
2349 rtx dest
= operands
[0];
2350 rtx src
= operands
[1];
2353 /* We might have (SUBREG (MEM)) here, so just get rid of the
2354 subregs to make this code simpler. It is safe to call
2355 alter_subreg any time after reload. */
2356 if (GET_CODE (dest
) == SUBREG
)
2357 alter_subreg (&dest
);
2358 if (GET_CODE (src
) == SUBREG
)
2359 alter_subreg (&src
);
2362 if (GET_CODE (dest
) == REG
)
2364 int dregno
= REGNO (dest
);
2367 if (GET_CODE (src
) == REG
)
2369 int sregno
= REGNO (src
);
2371 int reverse
= (dregno
== sregno
+ 1);
2373 /* We normally copy the low-numbered register first. However, if
2374 the first register operand 0 is the same as the second register of
2375 operand 1, we must copy in the opposite order. */
2376 emit_insn (gen_rtx_SET (VOIDmode
,
2377 operand_subword (dest
, reverse
, TRUE
, mode
),
2378 operand_subword (src
, reverse
, TRUE
, mode
)));
2380 emit_insn (gen_rtx_SET (VOIDmode
,
2381 operand_subword (dest
, !reverse
, TRUE
, mode
),
2382 operand_subword (src
, !reverse
, TRUE
, mode
)));
2385 /* Reg = constant. */
2386 else if (GET_CODE (src
) == CONST_INT
|| GET_CODE (src
) == CONST_DOUBLE
)
2389 split_double (src
, &words
[0], &words
[1]);
2390 emit_insn (gen_rtx_SET (VOIDmode
,
2391 operand_subword (dest
, 0, TRUE
, mode
),
2394 emit_insn (gen_rtx_SET (VOIDmode
,
2395 operand_subword (dest
, 1, TRUE
, mode
),
2400 else if (GET_CODE (src
) == MEM
)
2402 /* If the high-address word is used in the address, we must load it
2403 last. Otherwise, load it first. */
2405 = (refers_to_regno_p (dregno
, dregno
+ 1, XEXP (src
, 0), 0) != 0);
2407 /* We used to optimize loads from single registers as
2411 if r3 were not used subsequently. However, the REG_NOTES aren't
2412 propagated correctly by the reload phase, and it can cause bad
2413 code to be generated. We could still try:
2415 ld r1,r3+; ld r2,r3; addi r3,-4
2417 which saves 2 bytes and doesn't force longword alignment. */
2418 emit_insn (gen_rtx_SET (VOIDmode
,
2419 operand_subword (dest
, reverse
, TRUE
, mode
),
2420 adjust_address (src
, SImode
,
2421 reverse
* UNITS_PER_WORD
)));
2423 emit_insn (gen_rtx_SET (VOIDmode
,
2424 operand_subword (dest
, !reverse
, TRUE
, mode
),
2425 adjust_address (src
, SImode
,
2426 !reverse
* UNITS_PER_WORD
)));
2433 /* We used to optimize loads from single registers as
2437 if r3 were not used subsequently. However, the REG_NOTES aren't
2438 propagated correctly by the reload phase, and it can cause bad
2439 code to be generated. We could still try:
2441 st r1,r3; st r2,+r3; addi r3,-4
2443 which saves 2 bytes and doesn't force longword alignment. */
2444 else if (GET_CODE (dest
) == MEM
&& (GET_CODE(XEXP(dest
, 0))==PRE_DEC
) && GET_CODE (src
) == REG
)
2446 emit_insn (gen_rtx_SET (VOIDmode
,
2447 gen_rtx_MEM(SImode
, XEXP(dest
, 0)),
2448 operand_subword (src
, 1, TRUE
, mode
)));
2450 emit_insn (gen_rtx_SET (VOIDmode
,
2451 gen_rtx_MEM(SImode
, XEXP(dest
, 0)),
2452 operand_subword (src
, 0, TRUE
, mode
)));
2454 } else if (GET_CODE (dest
) == MEM
&& GET_CODE (src
) == REG
)
2456 emit_insn (gen_rtx_SET (VOIDmode
,
2457 adjust_address (dest
, SImode
, 0),
2458 operand_subword (src
, 0, TRUE
, mode
)));
2460 emit_insn (gen_rtx_SET (VOIDmode
,
2461 adjust_address (dest
, SImode
, UNITS_PER_WORD
),
2462 operand_subword (src
, 1, TRUE
, mode
)));
2467 debug_rtx(operands
[0]);
2468 debug_rtx(operands
[1]);
2478 const char *zpu_changestackpointer(rtx operands
[], rtx insn
)
2483 set
=single_set(insn
);
2489 t
[0]=stack_pointer_rtx
;
2492 return zpu_generate_move(t
, insn
);
2500 #undef TARGET_ASM_FILE_START
2501 #define TARGET_ASM_FILE_START zpu_file_start
2502 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
2503 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
2506 struct gcc_target targetm
= TARGET_INITIALIZER
;