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 pushHardReg(rtx reg
)
144 rtx regAddr
=GEN_INT(REGNO(reg
)*4);
148 zpu_asm("im _memreg+%0", ®Addr
);
149 zpu_asm("load", NULL
);
152 zpu_asm("im %0", ®Addr
);
153 zpu_asm("im _regpush", NULL
);
154 zpu_asm("call", NULL
);
159 static void pushRegAddress(rtx operand
)
161 /* painful handling of compatiblity with obscure case
162 * of alloca or dynamically sized objects on stack
167 num
=stackSlotNum(REGNO(operand
));
168 pushHardReg(hard_frame_pointer_rtx
);
169 offset
=GEN_INT(-(get_frame_size()+calcStackRegSize())+num
*4);
170 zpu_immediate(&offset
);
172 zpu_asm("add", NULL
);
176 static void pushreg(rtx operand
)
178 if (REGNO(operand
)<R_STACK_REG
)
180 if (REGNO(operand
)<R_NUM
)
182 pushHardReg(operand
);
187 } else if (REGNO(operand
)<R_NUM
)
189 if (current_function_calls_alloca
)
191 pushRegAddress(operand
);
192 zpu_asm("load", NULL
);
196 num
=stackSlotNum(REGNO(operand
));
197 zpu_loadsp(current_function_outgoing_args_size
+num
*4);
206 static void popHardReg(rtx reg
)
209 addr
=GEN_INT(REGNO(reg
)*4);
213 zpu_asm("im _memreg+%0", &addr
);
214 zpu_asm("store", NULL
);
217 zpu_asm("im %0", &addr
);
218 zpu_asm("im _regpop", NULL
);
219 zpu_asm("call", NULL
);
225 static void popreg(rtx operand
)
227 if (REGNO(operand
)<R_STACK_REG
)
229 if (REGNO(operand
)<R_NUM
)
233 } else if (REGNO(operand
)<R_NUM
)
235 if (current_function_calls_alloca
)
237 pushRegAddress(operand
);
238 zpu_asm("store", NULL
);
242 num
=stackSlotNum(REGNO(operand
));
243 zpu_storesp(current_function_outgoing_args_size
+num
*4);
252 /* returns true if both are registers and they are the same register*/
253 static int compareReg(rtx a
, rtx b
)
255 if (GET_CODE(a
)!=REG
)
259 if (GET_CODE(b
)!=REG
)
264 return REGNO(a
)==REGNO(b
);
267 static void comment(const char *format ATTRIBUTE_UNUSED
, rtx
*operands ATTRIBUTE_UNUSED
)
270 /* the testsuite chokes on this */
271 output_asm_insn(format
, operands
);
275 const char * zpu_asm_multi(const char *format
, rtx
*operands
, int byteCount ATTRIBUTE_UNUSED
)
278 /* imX, matches IM & IMPCREL */
279 im
=strncmp("im", format
, 2)==0;
281 if (im
&&prevImmediate
)
283 /* we need to break the pipe when two immediate instructions follow eachother */
284 output_asm_insn("nop", operands
);
286 output_asm_insn(format
, operands
);
292 static void zpu_asm(const char *format
, rtx
*operands
)
294 zpu_asm_multi(format
, operands
, 1);
299 struct RegStackEntry
GTY(())
301 rtx reg
; /* the current location of the register */
304 static GTY(()) struct RegStackEntry regStack
[R_NUM
*2];
305 static const unsigned int regStackSize
=sizeof(regStack
)/sizeof(*regStack
);
307 static rtx next_insn_saved
;
308 static rtx current_insn_saved
;
310 static void storeToReg(rtx newLocation
, rtx origReg
)
312 comment("; explicit pop", &newLocation
);
313 if (GET_CODE(newLocation
)==REG
)
319 int loadsp_offset
=loadstoresp_offset(newLocation
, &found
);
322 fprintf(stderr
, "\nZPU: corrupt regStack\n");
326 comment("; store to register on stack %0", &origReg
);
327 zpu_storesp(loadsp_offset
);
332 static void persistReg(rtx t
)
334 storeToReg(reg
[REGNO(t
)], t
);
339 static void discardRegStackTop(int persist
)
343 if ((regStackTop
>regStackSize
)||(regStackTop
<=0))
345 fprintf(stderr
, "ZPU: corrupt regStack\n");
349 /* this is where we pop the register to... */
350 newLocation
=gen_rtx_REG(SImode
, REGNO(regStack
[regStackTop
-1].reg
));
352 /* ...or is it still on the stack? */
353 for (i
=regStackTop
-2; i
>=0; i
--)
355 if (compareReg(regStack
[regStackTop
-1].reg
, regStack
[i
].reg
))
357 newLocation
=gen_rtx_MEM(SImode
,
358 gen_rtx_PLUS(SImode
, gen_rtx_REG(SImode
, R_SP
), GEN_INT(-(i
+1)*4)));
363 reg
[REGNO(regStack
[regStackTop
-1].reg
)]=newLocation
;
367 /* pop the register into the current location */
368 storeToReg(newLocation
, regStack
[regStackTop
-1].reg
);
374 static void popRegStack(void)
376 discardRegStackTop(1);
379 static void pushRegStack(rtx t
)
381 if (regStackTop
>=regStackSize
)
383 fprintf(stderr
, "ZPU: corrupt regStack\n");
387 regStack
[regStackTop
].reg
=t
;
390 /* GCC does not know that we are changing the stack pointer.
392 * Hence the saved registers are at a negative offset to GCC's concept of
395 reg
[REGNO(t
)]=gen_rtx_MEM(SImode
,
396 gen_rtx_PLUS(SImode
, gen_rtx_REG(SImode
, R_SP
), GEN_INT(-regStackTop
*4)));
400 static int zpu_noop_set(rtx insn
)
403 set
=single_set(insn
);
407 GET_CODE (SET_SRC (set
)) == REG
408 && GET_CODE (SET_DEST (set
)) == REG
409 && REGNO (SET_SRC (set
)) == REGNO (SET_DEST (set
));
414 static int zpu_can_be_split(rtx insn
)
417 set
=single_set(insn
);
420 return (GET_MODE(SET_SRC (set
)) != SImode
);
426 /* it is safe to err on the side of caution here and return 0
429 static rtx
zpu_next_insn(rtx insn
)
433 insn
= NEXT_INSN (insn
);
434 switch (GET_CODE(insn
))
440 if (zpu_noop_set(insn
))
442 /* DRAGONS! we must skip noop moves, because they
443 * are eliminated by the emitter
448 if (zpu_can_be_split(insn
))
460 /* we don't handle these */
468 static int stackPlusConst(rtx operand
, int *found
)
472 if(GET_CODE(operand
) != PLUS
)
476 op0
=XEXP (operand
, 0);
477 op1
=XEXP (operand
, 1);
478 if((GET_CODE(op0
)==REG
) &&(REGNO(op0
)==R_SP
)
479 && (GET_CODE(op1
)==CONST_INT
))
484 if((GET_CODE(op1
)==REG
) &&(REGNO(op1
)==R_SP
)
485 && (GET_CODE(op0
)==CONST_INT
))
493 static int loadstoresp_offset(rtx operand
, int *found
)
496 if (GET_MODE(operand
)!=SImode
)
500 if (GET_CODE(operand
)!=MEM
)
504 operand
=XEXP(operand
, 0);
506 if ((GET_CODE(operand
)==REG
)&&(REGNO(operand
)==R_SP
))
511 return stackPlusConst(operand
, found
);
516 int zpu_binary_operator (rtx op ATTRIBUTE_UNUSED
, enum machine_mode mode ATTRIBUTE_UNUSED
)
518 if (GET_MODE(op
)!=SImode
)
523 switch (GET_CODE(op
))
545 return TARGET_ASHIFTRT
;
547 return TARGET_LSHIFTRT
;
564 int zpu_unary_operator (rtx op ATTRIBUTE_UNUSED
, enum machine_mode mode ATTRIBUTE_UNUSED
)
566 if (GET_MODE(op
)!=SImode
)
571 switch (GET_CODE(op
))
585 static int opCheckTerminal(rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
, int strict
)
587 if (CONSTANT_P(op
)&&(GET_CODE(op
)!=CONST_DOUBLE
))
592 switch (GET_CODE(op
))
595 if ((REGNO(op
)<FIRST_PSEUDO_REGISTER
)||!strict
)
597 if ((REGNO(op
)!=R_PC
)&&(REGNO(op
)!=R_SP
))
612 /* This function is not about what the ZPU is capable of, but what
613 * the GCC & the backend wants/needs.
615 static int opCheck(rtx op
, enum machine_mode mode
, int strict
)
617 switch (GET_CODE(op
))
619 /* we support only *2,4,8 */
621 if (opCheckTerminal(XEXP(op
, 0), mode
, strict
))
623 if (GET_CODE(XEXP(op
, 1))==CONST_INT
)
625 int c
=INTVAL(XEXP(op
, 1));
626 if ((c
==2)||(c
==4)||(c
==8))
634 return opCheckTerminal(XEXP(op
, 0), mode
, strict
)&&
635 opCheckTerminal(XEXP(op
, 1), mode
, strict
);
638 if (REG_P(XEXP(op
, 0))&&(REGNO(XEXP(op
, 0))==R_SP
))
645 if (((mode
==DFmode
)||(mode
==DImode
))&&
647 (REGNO(XEXP(op
, 0))==R_SP
))
652 if ((mode
!=SImode
)&&(mode
!=HImode
)&&(mode
!=QImode
))
656 if (REG_P(XEXP(op
, 0))&&
657 ((REGNO(XEXP(op
, 0))<=R_SP
)
659 (!strict
&&(REGNO(XEXP(op
, 0))>=FIRST_PSEUDO_REGISTER
))
669 return opCheckTerminal(op
, mode
, strict
);
677 int zpu_legitimate_address(enum machine_mode mode ATTRIBUTE_UNUSED
, rtx x ATTRIBUTE_UNUSED
, int strict ATTRIBUTE_UNUSED
)
681 if (opCheck(x
, SImode
, strict
))
683 return countReg
<MAX_REGS_PER_ADDRESS
;
688 void print_operand (FILE *file
, rtx op
, int letter
)
693 print_rtl (file
, op
);
697 switch (GET_CODE (op
))
700 print_operand(file
, XEXP(op
, 0), letter
);
702 print_operand(file
, XEXP(op
, 1), letter
);
707 fprintf(file
, "%d", REGNO(op
)*4);
710 fprintf(file
, "%s", reg_names
[REGNO (op
)]);
716 if (GET_MODE(op
)==SFmode
)
721 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
722 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
723 asm_fprintf (file
, "%I0x%lx", l
);
726 else if (GET_MODE(op
)==DFmode
)
731 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
732 REAL_VALUE_TO_TARGET_DOUBLE (r
, l
);
733 asm_fprintf (file
, "0x%08x%08x", l
[0], l
[1]);
738 output_addr_const(file
, op
);
743 fprintf(file
, "%d", (int)INTVAL (op
));
749 output_addr_const(file
, op
);
757 print_operand(file
, XEXP (op
, 0), letter
);
766 output_addr_const(file
, op
);
776 static void initGenerate(rtx insn ATTRIBUTE_UNUSED
)
780 if ((next_insn_saved
!=NULL
) && (current_insn
!=next_insn_saved
))
783 fprintf(stderr
, "ZPU: zpu_next_insn() broken\n");
785 debug_rtx(current_insn_saved
);
787 /* for debugging purposes it is useful to look this up again so as
788 * to be able to step through the code
790 t
=zpu_next_insn(current_insn_saved
);
798 static int totalStackOffset(void)
801 /* this is the absolute difference between the ZPU stack
802 * pointer and GCC's concept of a stack pointer
804 t
=stackOffset
-regStackTop
*4;
807 fprintf(stderr
, "ZPU: illegal stack offset %d\n", -t
);
813 static void zpu_pushspadd(int offset
)
816 if (TARGET_PUSHSPADD
)
818 t
=GEN_INT((offset
+4)/4);
819 zpu_asm("im %0", &t
);
820 zpu_asm("pushspadd", &t
);
824 zpu_asm("pushsp", &t
);
827 zpu_asm("im %0", &t
);
833 static void zpu_addsp(int offset
)
839 zpu_asm("addsp %0", &t
);
842 zpu_asm("pushsp", NULL
);
845 zpu_asm("im %0", &t
);
846 zpu_asm("add", NULL
);
848 zpu_asm("load", NULL
);
849 zpu_asm("add", NULL
);
853 static void zpu_coreloadsp(int offset
)
862 if (TARGET_LOADSP
&&(offset
/4<32))
864 zpu_asm("loadsp %0", &t
);
867 zpu_pushspadd(offset
);
874 static void zpu_loadsp(int offset
)
877 offset
-=totalStackOffset();
879 zpu_coreloadsp(offset
);
884 static void zpu_storesp(int offset
)
887 offset
-=totalStackOffset();
894 if (TARGET_STORESP
&&(offset
/4<32))
897 zpu_asm("storesp %0", &t
);
900 zpu_pushspadd(offset
);
901 zpu_asm("store", &t
);
907 static int zpu_stack_change(rtx x
)
913 rtx dest
=SET_DEST(set
);
914 rtx src
=SET_SRC(set
);
915 if ((GET_CODE(dest
)==REG
)&&(REGNO(dest
)==R_SP
))
920 if (GET_CODE(dest
)==MEM
)
922 if (GET_CODE(XEXP(dest
, 0))==PRE_DEC
)
924 if (REG_P(XEXP(XEXP(dest
, 0), 0))&®NO(XEXP(XEXP(dest
, 0), 0))==R_SP
)
930 if ((GET_CODE(dest
)==REG
)&&(REGNO(dest
)==R_SP
))
934 if (GET_CODE(src
)==MEM
)
936 if (GET_CODE(XEXP(src
, 0))==POST_INC
)
938 if (REG_P(XEXP(XEXP(src
, 0), 0))&®NO(XEXP(XEXP(src
, 0), 0))==R_SP
)
949 static int isInBasicBlock(rtx insn
)
955 if (GET_CODE(insn
)==INSN
)
957 if (!zpu_stack_change(insn
))
960 set
=single_set(insn
);
963 if (GET_CODE(SET_SRC(set
))!=ASM_OPERANDS
)
976 static void cleanupGenerate(void)
981 fprintf(stderr
, "ZPU: stackOffset %d\n", stackOffset
);
985 /* purge all dead registers off the stack */
986 while ((regStackTop
>0)&&find_regno_note(current_insn
, REG_DEAD
, REGNO(regStack
[regStackTop
-1].reg
)))
991 /* if we are at the end of the basic block, we must clean up
992 * any unpopped registers
994 t
=zpu_next_insn (current_insn
);
995 next_insn_saved
=NULL_RTX
;
996 current_insn_saved
=current_insn
;
998 if (isInBasicBlock(t
))
1003 comment("; barrier, purge regstack", ¤t_insn
);
1004 while (regStackTop
>0)
1012 static void push_operand_address(rtx
*operand
);
1013 static void push_operand_value(rtx
*operand
);
1016 static const char *zpu_immediate(rtx
*operand
)
1018 zpu_asm("im %0", operand
);
1023 static void zpu_neg(rtx
*operand
)
1027 zpu_asm("neg", operand
);
1030 /* FIX!!! is this the right sequence? */
1031 zpu_asm("im 1", operand
);
1032 zpu_asm("add", operand
);
1033 zpu_asm("not", operand
);
1038 /* is "find" the first operand to be pushed in "x".
1040 * It is safe to err on the side of caution and say "no", it will
1041 * only potentially make the code ever so slightly less efficient.
1043 static int zpu_first_push(rtx x
, rtx find
)
1047 const char *format_ptr
;
1066 return zpu_first_push(SET_SRC(x
), find
);
1072 return zpu_first_push(XEXP(x
, 0), find
)||zpu_first_push(XEXP(x
, 1), find
);
1077 /* these are handled by the generic code below */
1082 /* err on the side of caution */
1087 format_ptr
= GET_RTX_FORMAT (code
);
1090 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
1092 switch (*format_ptr
++)
1095 return zpu_first_push (XEXP (x
, i
), find
);
1098 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1099 return zpu_first_push (XVECEXP (x
, i
, j
), find
);
1105 static void zpu_call_asm(void)
1109 zpu_asm("call", NULL
);
1113 zpu_asm("pushsp ; CALL insn - duplicate top of stack", NULL
);
1114 zpu_asm("load", NULL
);
1115 zpu_asm("im 6 ; post POPC address", NULL
);
1116 zpu_asm("pushpc", NULL
);
1117 zpu_asm("add", NULL
);
1118 zpu_asm("pushsp", NULL
);
1119 zpu_asm("im 4", NULL
);
1120 zpu_asm("add", NULL
);
1121 zpu_asm("store", NULL
);
1122 zpu_asm("poppc ; call function ", NULL
);
1128 static void zpu_gen_call(rtx
*operand
)
1130 comment("/* call %R0 */", operand
);
1132 if (GET_CODE(operand
[0])!=MEM
)
1137 if (TARGET_CALLPCREL
&&CONSTANT_P(XEXP(operand
[0], 0)))
1139 zpu_asm("impcrel %0", operand
);
1140 zpu_asm("callpcrel", operand
);
1143 /* address to call... */
1144 push_operand_address(operand
);
1148 fprintf(stderr
, "ZPU: regStackTop %d\n", regStackTop
);
1160 zpu_count_occurrences (rtx x
, rtx find
)
1164 const char *format_ptr
;
1179 if ((GET_CODE(x
) == REG
)&&(REGNO(x
)==REGNO(find
)))
1183 format_ptr
= GET_RTX_FORMAT (code
);
1186 for (i
= 0; i
< GET_RTX_LENGTH (code
); i
++)
1188 switch (*format_ptr
++)
1191 count
+= zpu_count_occurrences (XEXP (x
, i
), find
);
1195 for (j
= 0; j
< XVECLEN (x
, i
); j
++)
1196 count
+= zpu_count_occurrences (XVECEXP (x
, i
, j
), find
);
1203 /* we must err on the side of caution here. */
1204 static int zpu_first_only_push(rtx x
, rtx find
)
1207 if (zpu_first_push(x
, find
))
1216 if (zpu_count_occurrences(x
, find
)==1)
1230 * - the GCC-register is REG_DEAD or overwritten
1231 * - the GCC-register is on top of the stack
1232 * - the first push in the instruction is the GCC-register
1233 * - we only use the register once in the operation
1235 * then we can simply remove the instructions that pop/push
1237 static int dead_or_overwritten(rtx insn
, rtx op
)
1240 if (find_regno_note(insn
, REG_DEAD
, REGNO (op
)))
1245 rtx set
= single_set (insn
);
1248 if (SET_DEST(set
)==op
)
1258 /* Check if the operand on the regStack is one of the operands and
1261 static void push_assosiative(rtx operand
)
1263 if ((regStackTop
>0)&&compareReg(regStack
[regStackTop
-1].reg
, XEXP(operand
, 1)))
1265 push_operand_value(&XEXP(operand
, 1));
1266 push_operand_value(&XEXP(operand
, 0));
1269 /* either this is the other correct way, or it doesn't matter which way we
1272 push_operand_value(&XEXP(operand
, 0));
1273 push_operand_value(&XEXP(operand
, 1));
1278 static int isFreePopPush(rtx
*operand
)
1281 if ((GET_CODE(*operand
)==REG
)&&(REGNO(*operand
)<R_NUM
)&&(GET_CODE(reg
[REGNO(*operand
)])==MEM
))
1283 /* the GCC-register must be on top of the stack for a free push */
1288 fprintf(stderr
, "ZPU: regStack corrupted\n");
1292 if (dead_or_overwritten(current_insn
, *operand
))
1294 if (zpu_first_only_push(current_insn
, *operand
))
1296 comment("; stripping regstack until free pop&push is found %0", operand
);
1297 /* strip the regstack until we have a free pop */
1298 while (!compareReg(regStack
[regStackTop
-1].reg
, *operand
))
1307 comment("; eliminated pop&push %0", operand
);
1310 fprintf(stderr
, "ZPU: eliminated poppush!\n");
1311 debug_rtx (current_insn
);
1321 static int postIncMemSize
;
1322 static void push_operand_value(rtx
*operand
)
1324 if (CONSTANT_P(*operand
))
1326 zpu_immediate(operand
);
1331 if (GET_CODE(*operand
)==REG
)
1333 if (REGNO(*operand
)==R_PC
)
1335 zpu_asm("pushpc", operand
);
1337 } else if (REGNO(*operand
)==R_SP
)
1339 zpu_asm("pushsp", operand
);
1346 if (totalStackOffset()<0)
1348 rtx offset
=GEN_INT(-totalStackOffset());
1349 comment("; stack adjustment offset", &offset
);
1350 zpu_asm("im %0", &offset
);
1351 zpu_asm("add", operand
);
1355 } else if (REGNO(*operand
)<R_NUM
)
1357 /* push GCC-register */
1358 if (GET_CODE(reg
[REGNO(*operand
)])==MEM
)
1360 if (isFreePopPush(operand
))
1362 /* we pretend we pushed it into the stack and clear the top
1365 discardRegStackTop(0);
1369 comment("; referring to unpopped register %0", operand
);
1372 fprintf(stderr
, "ZPU: unpopped register\n");
1373 debug_rtx (reg
[REGNO(*operand
)]);
1375 push_operand_value(®
[REGNO(*operand
)]);
1387 } else if (GET_CODE (*operand
) == POST_INC
)
1391 reg
=XEXP (*operand
, 0);
1392 if (GET_CODE(reg
)!=REG
)
1397 if (REGNO(reg
)>=R_SP
)
1402 push_operand_value(®
);
1406 size
=GEN_INT(postIncMemSize
);
1407 zpu_asm("im %0", &size
);
1408 zpu_asm("add", operand
);
1410 /* we must not leave anything on the stack here */
1412 } else if (GET_CODE (*operand
) == MEM
)
1415 int loadsp_offset
=loadstoresp_offset(*operand
, &found
);
1416 if ((GET_CODE(XEXP (*operand
, 0))==POST_INC
)&&(GET_CODE(XEXP (XEXP (*operand
, 0), 0))==REG
)&&(REGNO(XEXP (XEXP (*operand
, 0), 0))==R_SP
))
1418 /* NOTE!!! We pop this off the stack even though it was placed there before we entered
1419 * this tree expansion. */
1423 zpu_loadsp(loadsp_offset
);
1426 postIncMemSize
=GET_MODE_SIZE(GET_MODE(*operand
));
1428 push_operand_value(&XEXP (*operand
, 0));
1429 switch (GET_MODE(*operand
))
1433 zpu_asm("load", operand
);
1438 zpu_asm("loadh", NULL
);
1441 zpu_asm("im _loadh", NULL
);
1448 zpu_asm("loadb", NULL
);
1451 zpu_asm("im _loadb", NULL
);
1457 fprintf(stderr
, "FIX!!!! miissing operand\n");
1458 print_rtl(stderr
, *operand
);
1459 fprintf(stderr
, "\n");
1463 } else if (GET_CODE(*operand
)==PLUS
)
1467 offset
=stackPlusConst(*operand
, &found
);
1468 if (found
&&((offset
%4)==0))
1470 offset
-=totalStackOffset();
1471 zpu_pushspadd(offset
);
1474 if (isFreePopPush(&XEXP(*operand
, 0))||isFreePopPush(&XEXP(*operand
, 1)))
1476 push_assosiative(*operand
);
1477 zpu_asm("add", operand
);
1481 offset
=addSpRange(XEXP(operand
[0], 0), &found
);
1482 if ((!found
)||((offset
+4)>MAX_ADDSP
))
1484 push_operand_value(&XEXP(operand
[0], 0));
1485 offset
=addSpRange(XEXP(operand
[0], 1), &found
);
1486 if (found
&&(offset
<=MAX_ADDSP
))
1491 push_operand_value(&XEXP(operand
[0], 1));
1492 zpu_asm("add", NULL
);
1497 push_operand_value(&XEXP(operand
[0], 1));
1498 zpu_addsp(offset
+4);
1501 } else if ((GET_CODE(*operand
)==COMPARE
)||(GET_CODE(*operand
)==MINUS
))
1503 push_operand_value(&XEXP (*operand
, 0));
1504 push_operand_value(&XEXP (*operand
, 1));
1505 zpu_asm("sub", operand
);
1507 } else if (GET_CODE(*operand
)==LABEL_REF
)
1509 zpu_immediate(operand
);
1510 } else if (GET_CODE(*operand
)==SYMBOL_REF
)
1512 zpu_immediate(operand
);
1513 } else if (GET_CODE(*operand
)==CODE_LABEL
)
1515 zpu_immediate(operand
);
1516 } else if (GET_CODE(*operand
)==XOR
)
1518 push_assosiative(*operand
);
1519 zpu_asm("xor", operand
);
1520 stackOffset
+=4; /* lost one */
1521 } else if (GET_CODE(*operand
)==AND
)
1523 push_assosiative(*operand
);
1524 zpu_asm("and", operand
);
1525 stackOffset
+=4; /* lost one */
1526 } else if (GET_CODE(*operand
)==IOR
)
1528 push_assosiative(*operand
);
1529 zpu_asm("or", operand
);
1530 stackOffset
+=4; /* lost one */
1531 } else if (GET_CODE(*operand
)==NOT
)
1533 push_operand_value(&XEXP (*operand
, 0));
1534 zpu_asm("not", operand
);
1535 } else if (GET_CODE(*operand
)==NEG
)
1537 push_operand_value(&XEXP (*operand
, 0));
1539 } else if ((GET_CODE(*operand
)==EQ
)||(GET_CODE(*operand
)==NE
))
1541 push_operand_value(&XEXP (*operand
, 0));
1542 push_operand_value(&XEXP (*operand
, 1));
1545 zpu_asm("eq", operand
);
1548 zpu_asm("im _eq", NULL
);
1551 if (GET_CODE(*operand
)==NE
)
1554 zpu_asm("not", operand
);
1555 zpu_asm("im 1", operand
);
1556 zpu_asm("and", operand
);
1558 stackOffset
+=4; /* lost one */
1559 } else if ((GET_CODE(*operand
)==LE
)||(GET_CODE(*operand
)==GE
)||
1560 (GET_CODE(*operand
)==LEU
)||(GET_CODE(*operand
)==GEU
)||
1561 (GET_CODE(*operand
)==GT
)||(GET_CODE(*operand
)==LT
)||
1562 (GET_CODE(*operand
)==GTU
)||(GET_CODE(*operand
)==LTU
))
1567 int code
=GET_CODE(*operand
);
1569 comment("/* %R0 */", operand
);
1571 /* 'less than' is the base case here and then we tweak it into the
1574 sign
=(code
==GE
) || (code
==LE
) || (code
==GT
) || (code
==LT
);
1575 flip_args
=(code
==GT
) || (code
==GE
) || (code
==GTU
) || (code
==GEU
);
1576 equal
=(code
==GE
) || (code
==LE
) || (code
==GEU
) || (code
==LEU
);
1578 push_operand_value(&XEXP (*operand
, flip_args
?0:1)); /* b */
1579 push_operand_value(&XEXP (*operand
, flip_args
?1:0)); /* a */
1587 zpu_asm("ulessthanorequal", operand
);
1590 zpu_asm("im _ulessthanorequal", NULL
);
1597 zpu_asm("ulessthan", operand
);
1600 zpu_asm("im _ulessthan", NULL
);
1610 zpu_asm("lessthanorequal", operand
);
1613 zpu_asm("im _lessthanorequal", NULL
);
1620 zpu_asm("lessthan", operand
);
1623 zpu_asm("im _lessthan", NULL
);
1629 stackOffset
+=4; /* lost one */
1630 } else if (GET_CODE(*operand
)==LSHIFTRT
)
1632 push_operand_value(&XEXP (*operand
, 0));
1633 push_operand_value(&XEXP (*operand
, 1));
1634 zpu_asm("lshiftright", operand
);
1635 stackOffset
+=4; /* lost one */
1636 } else if (GET_CODE(*operand
)==ASHIFTRT
)
1638 push_operand_value(&XEXP (*operand
, 0));
1639 push_operand_value(&XEXP (*operand
, 1));
1640 zpu_asm("ashiftright", operand
);
1641 stackOffset
+=4; /* lost one */
1642 } else if (GET_CODE(*operand
)==ASHIFT
)
1644 if ((GET_CODE(XEXP (*operand
, 1))==CONST_INT
)&&(INTVAL(XEXP (*operand
, 1))==1))
1646 push_operand_value(&XEXP (*operand
, 0));
1650 push_operand_value(&XEXP (*operand
, 0));
1651 push_operand_value(&XEXP (*operand
, 1));
1652 zpu_asm("ashiftleft", operand
);
1653 stackOffset
+=4; /* lost one */
1655 } else if (GET_CODE(operand
[0])==MULT
)
1658 /* NOTE! This is a most crucial optimisation as MULT is used in
1661 if ((GET_CODE(XEXP(*operand
, 1))==CONST_INT
))
1663 int c
=INTVAL(XEXP(*operand
, 1));
1669 if ((c
==2)||((optimize
&&!optimize_size
)&&((c
==4)||(c
==8))))
1672 push_operand_value(&XEXP (*operand
, 0));
1683 push_operand_value(&XEXP (*operand
, 0));
1684 push_operand_value(&XEXP (*operand
, 1));
1685 zpu_asm("mult", operand
);
1688 } else if (GET_CODE(operand
[0])==DIV
)
1690 push_operand_value(&XEXP (*operand
, 1));
1691 push_operand_value(&XEXP (*operand
, 0));
1692 zpu_asm("div", operand
);
1694 } else if (GET_CODE(operand
[0])==MOD
)
1696 push_operand_value(&XEXP (*operand
, 1));
1697 push_operand_value(&XEXP (*operand
, 0));
1698 zpu_asm("mod", operand
);
1700 } else if (GET_CODE(operand
[0])==ZERO_EXTEND
)
1702 push_operand_value(&XEXP (*operand
, 0));
1703 if (GET_CODE(XEXP (*operand
, 0))!=MEM
)
1705 switch (GET_MODE(XEXP (*operand
, 0)))
1708 /* its a bit silly to extend a VOIDmode, i.e. a constant,
1714 zpu_asm("im 0xff", operand
);
1715 zpu_asm("and", operand
);
1718 zpu_asm("im 0xffff", operand
);
1719 zpu_asm("and", operand
);
1727 print_rtl(stderr
, *operand
);
1736 /* even registers have addresses on a ZPU that we can push onto the stack */
1737 static void push_operand_address(rtx
*operand
)
1739 if (GET_CODE (*operand
) == MEM
)
1741 push_operand_value(&XEXP (*operand
, 0));
1742 } else if (GET_CODE(*operand
)==SYMBOL_REF
)
1744 zpu_immediate(operand
);
1745 } else if (GET_CODE (*operand
) == REG
)
1747 push_operand_value(operand
);
1755 static void store_to_operand(rtx
*operand
)
1757 if (GET_CODE(*operand
)==PC
)
1759 zpu_asm("poppc ; jump", operand
);
1761 } else if (GET_CODE(*operand
)==REG
)
1763 if (REGNO(*operand
)==R_SP
)
1765 zpu_asm("popsp", operand
);
1767 } else if (REGNO(*operand
)==R_PC
)
1769 zpu_asm("poppc ; jump", operand
);
1771 } else if (REGNO(*operand
)<R_NUM
)
1773 if (regStackTop
<regStackSize
)
1775 /* we always leave the value on the stack, if there is space
1777 * The cleanupGenerate() handles this case.
1779 comment("; left %0 on stack", operand
);
1780 pushRegStack(*operand
);
1784 comment("; regStack full", operand
);
1785 persistReg(*operand
);
1791 } else if (GET_CODE(operand
[0])==MEM
)
1794 int loadsp_offset
=loadstoresp_offset(*operand
, &found
);
1795 if ((GET_MODE(operand
[0])!=SFmode
)&&(GET_MODE(operand
[0])!=SImode
)&&(GET_MODE(operand
[0])!=HImode
)&&(GET_MODE(operand
[0])!=QImode
))
1797 fprintf(stderr
, "\nUnsupported dest\n");
1798 print_rtl (stderr
, *operand
);
1799 fprintf(stderr
, "\n");
1804 if (GET_CODE(XEXP (operand
[0], 0))==PRE_DEC
)
1806 rtx reg
=XEXP(XEXP(operand
[0], 0), 0);
1811 if (REGNO(reg
)==R_SP
)
1813 /* we've already pushed the result onto the stack. */
1814 /* we tell a small lie. We change the SP during tree expansion, but we intended to */
1822 zpu_storesp(loadsp_offset
);
1826 postIncMemSize
=GET_MODE_SIZE(GET_MODE(*operand
));
1828 push_operand_address(operand
);
1829 switch (GET_MODE(operand
[0]))
1833 zpu_asm("store", operand
);
1838 zpu_asm("storeh", NULL
);
1841 zpu_asm("im _storeh", NULL
);
1848 zpu_asm("storeb", NULL
);
1851 zpu_asm("im _storeb", NULL
);
1857 fprintf(stderr
, "FIX!!!! Missing operand\n");
1858 print_rtl(stderr
, *operand
);
1859 fprintf(stderr
, "\n");
1866 fprintf(stderr
, "\nUnsupported dest\n");
1867 print_rtl (stderr
, *operand
);
1868 fprintf(stderr
, "\n");
1877 const char *zpu_generate_move(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
1881 comment("/* move %R1, %R0 */", operands
);
1883 /* first we push the source onto the stack, then we figure out the
1886 push_operand_value(operands
+1);
1888 store_to_operand(operands
+0);
1895 const char *zpu_generate_set(rtx insn
)
1900 set
=single_set(insn
);
1901 comment("/* %R0 */", &set
);
1903 /* first we push the source onto the stack, then we figure out the
1906 push_operand_value(&SET_SRC(set
));
1908 store_to_operand(&SET_DEST(set
));
1915 static void zpu_neqbranch(rtx operand
)
1918 zpu_asm("impcrel %0", &operand
);
1919 if (TARGET_NEQBRANCH
)
1922 zpu_asm("neqbranch", NULL
);
1925 zpu_asm("im _neqbranch", NULL
);
1931 const char *zpu_generate_if_then_else(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
1935 comment("/* if_then_else %R0 */", operands
);
1937 /* evaluate boolean expression. this RTL contains the two suboperands */
1938 push_operand_value(&operands
[0]);
1942 fprintf(stderr
, "ZPU: regStackTop %d\n", regStackTop
);
1946 zpu_neqbranch(operands
[3]);
1956 const char *zpu_generate_if_not_zero_then_else(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
1958 if ((GET_CODE(operands
[2])!=CONST_INT
)||INTVAL(operands
[2])!=0)
1960 return zpu_generate_if_then_else(operands
, insn
);
1965 /* evaluate boolean expression. this RTL contains the two suboperands */
1966 push_operand_value(&operands
[0]);
1968 zpu_neqbranch(operands
[1]);
1978 static const char *zpu_jump_core(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
, int table
)
1981 comment("/* jump %R0 */", operands
);
1983 /* put address on stack */
1984 push_operand_value(operands
+0);
1988 comment("/* tablejump */", operands
);
1991 zpu_asm("poppc", operands
);
1999 const char *zpu_jump(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
2001 return zpu_jump_core(operands
, insn
, 0);
2004 const char *zpu_table_jump(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
2006 return zpu_jump_core(operands
, insn
, 1);
2010 const char *zpu_jump_pcrel(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
2016 fprintf(stderr
, "ZPU: regStackTop %d\n", regStackTop
);
2020 /* put address on stack */
2021 if (TARGET_POPPCREL
)
2023 zpu_asm("impcrel %0", operands
);
2024 zpu_asm("poppcrel", operands
);
2027 zpu_asm("im %0", operands
);
2028 zpu_asm("poppc", NULL
);
2037 const char *generate_branch(enum rtx_code code ATTRIBUTE_UNUSED
, rtx loc
, rtx insn
)
2039 return zpu_jump(&loc
, insn
);
2042 const char *zpu_push(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
2045 comment("/* push %R0 */", operands
);
2046 push_operand_value(operands
+0);
2048 /* we tell a small lie. We change the SP during tree expansion, but we intended to */
2057 static int reg_save(int regno
)
2060 if (regs_ever_live
[regno
]&&!call_used_regs
[regno
])
2064 /* FIX!!! how do we check if we've eliminated the argument pointer? */
2068 static int calcSavedSize(void)
2072 for (regno
= 0; regno
< R_STACK_REG
; regno
++)
2073 if (reg_save(regno
))
2080 static int calcStackRegSize(void)
2084 for (regno
= R_STACK_REG
; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
2085 if (reg_save(regno
))
2093 /* Define the offset between two registers, one to be eliminated, and the
2094 other its replacement, at the start of a routine. */
2095 int zpu_initial_elimination_offset (int from
, int to
)
2098 /* The difference between the argument pointer and the stack pointer is
2099 * the sum of the size of this function's frame, the callee register save
2100 * area, and the fixed stack space needed for function calls (if any).
2102 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
2104 offset
=current_function_outgoing_args_size
+ calcStackRegSize() + get_frame_size () + calcSavedSize() + 4 ;
2105 } else if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
2107 offset
=calcSavedSize() + 4;
2108 } else if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
2110 offset
=current_function_outgoing_args_size
+ calcStackRegSize() + get_frame_size ();
2111 } else if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
2121 static int allocFrameSize(void)
2123 return current_function_outgoing_args_size
+calcStackRegSize()+get_frame_size();
2126 void zpu_expand_prologue (void)
2132 HOST_WIDE_INT frameSize
;
2136 for (i
=R_STACK_REG
; i
<R_NUM
; i
++)
2138 regMapper
[i
-R_STACK_REG
]=-1;
2141 for (i
=0; i
<R_NUM
; i
++)
2143 if ((i
>=R_STACK_REG
)&®_save(i
))
2145 regMapper
[i
-R_STACK_REG
]=mapper
++;
2147 reg
[i
]=gen_rtx_REG(SImode
, i
);
2152 mem_push_rtx
= gen_rtx_MEM (SImode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2154 /* Push each of the registers to save. */
2155 for (regno
= 0; regno
< R_STACK_REG
; regno
++)
2156 if (reg_save(regno
))
2158 insn
= emit_move_insn (mem_push_rtx
, gen_rtx_REG (SImode
, regno
));
2159 RTX_FRAME_RELATED_P (insn
) = 1;
2162 /* Set up the frame pointer, if required. */
2163 if (frame_pointer_needed
)
2165 insn
= emit_move_insn (hard_frame_pointer_rtx
, stack_pointer_rtx
);
2166 RTX_FRAME_RELATED_P (insn
) = 1;
2168 /* DANGER!!!! I believe that we can trust the GCC compiler to
2169 * always eliminate the argument pointer register, if not we're
2170 * in trouble, because we do not emit any code here */
2172 frameSize
=allocFrameSize();
2175 insn
=emit_move_insn (stack_pointer_rtx
,
2176 gen_rtx_PLUS (SImode
, stack_pointer_rtx
, GEN_INT (-frameSize
)));
2177 RTX_FRAME_RELATED_P (insn
) = 1;
2182 void zpu_expand_epilogue (void)
2184 rtx mem_pop_rtx
, insn
;
2186 HOST_WIDE_INT frameSize
;
2189 mem_pop_rtx
= gen_rtx_MEM (SImode
, gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
));
2191 frameSize
=allocFrameSize();
2194 insn
= emit_move_insn (stack_pointer_rtx
,
2195 gen_rtx_PLUS (SImode
, stack_pointer_rtx
, GEN_INT (frameSize
)));
2196 RTX_FRAME_RELATED_P (insn
) = 1;
2199 /* Restore any call-saved registers. */
2200 for (regno
= R_STACK_REG
- 1; regno
>= 0; regno
--)
2201 if (reg_save(regno
))
2203 insn
= emit_move_insn (gen_rtx_REG (SImode
, regno
), mem_pop_rtx
);
2206 /* FIX! a single poppc should suffice for no argument fn's */
2207 mem_push_rtx
= gen_rtx_MEM (SImode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2208 insn
= emit_jump_insn (gen_zpu_return());
2211 rtx
zpu_return_addr_rtx(void)
2213 return gen_rtx_MEM (Pmode
, plus_constant (virtual_incoming_args_rtx
, -4));
2217 const char *zpu_call(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
2221 zpu_gen_call(operands
);
2228 const char *zpu_call_value(rtx operands
[], rtx insn ATTRIBUTE_UNUSED
)
2232 zpu_gen_call(operands
+1);
2234 if ((GET_CODE(operands
[0])!=REG
)&&(REGNO(operands
[0])!=R_R0
))
2236 rtx reg
=gen_rtx_REG(SImode
, 0);
2240 store_to_operand(operands
+0);
2247 /* change all QImode and HImode to SImode load's*/
2249 void zpu_expand_set(enum machine_mode mode
, rtx operands
[])
2251 emit_insn(gen_rtx_SET(mode
, operands
[0], operands
[1]));
2257 zpu_file_start (void)
2259 default_file_start ();
2262 /* Value is the number of bytes of arguments automatically
2263 popped when returning from a subroutine call.
2264 FUNDECL is the declaration node of the function (as a tree),
2265 FUNTYPE is the data type of the function (as a tree),
2266 or for a library call it is an identifier node for the subroutine name.
2267 SIZE is the number of bytes of arguments passed on the stack.
2269 On the ZPU, the RET insn may be used to pop them if the number
2270 of args is fixed, but if the number is variable then the caller
2272 Use of RET is should be a selectable option, since it is incompatible with
2273 standard Unix calling sequences. If the option is not selected,
2274 the caller must always pop the args.
2279 zpu_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
, tree funtype
, int size
)
2281 if (TREE_CODE (funtype
) == IDENTIFIER_NODE
)
2284 if (TYPE_ARG_TYPES (funtype
) == NULL_TREE
2285 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype
))) == void_type_node
))
2296 move_double_src_operand (rtx op
, enum machine_mode mode
)
2298 switch (GET_CODE (op
))
2305 /* FIX! not entirely sure why this isn't
2306 * handled by register_operand
2311 return register_operand (op
, mode
);
2314 /* (subreg (mem ...) ...) can occur here if the inner part was once a
2315 pseudo-reg and is now a stack slot. */
2316 if (GET_CODE (SUBREG_REG (op
)) == MEM
)
2317 return move_double_src_operand (SUBREG_REG (op
), mode
);
2319 return register_operand (op
, mode
);
2322 /* Disallow auto inc/dec for now. */
2323 if ((GET_CODE (XEXP (op
, 0)) == POST_INC
)&&
2324 (!REG_P(XEXP (XEXP (op
, 0), 0))||
2325 REGNO(XEXP (XEXP (op
, 0), 0)))!=R_SP
)
2327 return memory_operand (op
, mode
);
2333 /* Return true if OP is an acceptable argument for a move destination. */
2336 move_double_dest_operand (rtx op
, enum machine_mode mode
)
2338 switch (GET_CODE (op
))
2342 return register_operand (op
, mode
);
2345 /* (subreg (mem ...) ...) can occur here if the inner part was once a
2346 pseudo-reg and is now a stack slot. */
2347 if (GET_CODE (SUBREG_REG (op
)) == MEM
)
2348 return address_operand (XEXP (SUBREG_REG (op
), 0), mode
);
2350 return register_operand (op
, mode
);
2353 /* Disallow auto inc for now. */
2354 if (GET_CODE (XEXP (op
, 0)) == POST_INC
)
2357 /* FIX!!!! a) why isn't this necessary? b) why does it break compilation? */
2358 if ((GET_CODE (XEXP (op
, 0)) == PRE_DEC
)&&
2359 ((!REG_P(XEXP (XEXP (op
, 0), 0))||
2360 REGNO(XEXP (XEXP (op
, 0), 0)))!=R_SP
))
2363 return memory_operand (op
, mode
);
2370 /* Split a 2 word move (DI or DF) into component parts. */
2373 gen_split_move_double (rtx operands
[])
2375 enum machine_mode mode
= GET_MODE (operands
[0]);
2376 rtx dest
= operands
[0];
2377 rtx src
= operands
[1];
2380 /* We might have (SUBREG (MEM)) here, so just get rid of the
2381 subregs to make this code simpler. It is safe to call
2382 alter_subreg any time after reload. */
2383 if (GET_CODE (dest
) == SUBREG
)
2384 alter_subreg (&dest
);
2385 if (GET_CODE (src
) == SUBREG
)
2386 alter_subreg (&src
);
2389 if (GET_CODE (dest
) == REG
)
2391 int dregno
= REGNO (dest
);
2394 if (GET_CODE (src
) == REG
)
2396 int sregno
= REGNO (src
);
2398 int reverse
= (dregno
== sregno
+ 1);
2400 /* We normally copy the low-numbered register first. However, if
2401 the first register operand 0 is the same as the second register of
2402 operand 1, we must copy in the opposite order. */
2403 emit_insn (gen_rtx_SET (VOIDmode
,
2404 operand_subword (dest
, reverse
, TRUE
, mode
),
2405 operand_subword (src
, reverse
, TRUE
, mode
)));
2407 emit_insn (gen_rtx_SET (VOIDmode
,
2408 operand_subword (dest
, !reverse
, TRUE
, mode
),
2409 operand_subword (src
, !reverse
, TRUE
, mode
)));
2412 /* Reg = constant. */
2413 else if (GET_CODE (src
) == CONST_INT
|| GET_CODE (src
) == CONST_DOUBLE
)
2416 split_double (src
, &words
[0], &words
[1]);
2417 emit_insn (gen_rtx_SET (VOIDmode
,
2418 operand_subword (dest
, 0, TRUE
, mode
),
2421 emit_insn (gen_rtx_SET (VOIDmode
,
2422 operand_subword (dest
, 1, TRUE
, mode
),
2427 else if (GET_CODE (src
) == MEM
)
2429 /* If the high-address word is used in the address, we must load it
2430 last. Otherwise, load it first. */
2432 = (refers_to_regno_p (dregno
, dregno
+ 1, XEXP (src
, 0), 0) != 0);
2434 /* We used to optimize loads from single registers as
2438 if r3 were not used subsequently. However, the REG_NOTES aren't
2439 propagated correctly by the reload phase, and it can cause bad
2440 code to be generated. We could still try:
2442 ld r1,r3+; ld r2,r3; addi r3,-4
2444 which saves 2 bytes and doesn't force longword alignment. */
2445 emit_insn (gen_rtx_SET (VOIDmode
,
2446 operand_subword (dest
, reverse
, TRUE
, mode
),
2447 adjust_address (src
, SImode
,
2448 reverse
* UNITS_PER_WORD
)));
2450 emit_insn (gen_rtx_SET (VOIDmode
,
2451 operand_subword (dest
, !reverse
, TRUE
, mode
),
2452 adjust_address (src
, SImode
,
2453 !reverse
* UNITS_PER_WORD
)));
2460 /* We used to optimize loads from single registers as
2464 if r3 were not used subsequently. However, the REG_NOTES aren't
2465 propagated correctly by the reload phase, and it can cause bad
2466 code to be generated. We could still try:
2468 st r1,r3; st r2,+r3; addi r3,-4
2470 which saves 2 bytes and doesn't force longword alignment. */
2471 else if (GET_CODE (dest
) == MEM
&& (GET_CODE(XEXP(dest
, 0))==PRE_DEC
) && GET_CODE (src
) == REG
)
2473 emit_insn (gen_rtx_SET (VOIDmode
,
2474 gen_rtx_MEM(SImode
, XEXP(dest
, 0)),
2475 operand_subword (src
, 1, TRUE
, mode
)));
2477 emit_insn (gen_rtx_SET (VOIDmode
,
2478 gen_rtx_MEM(SImode
, XEXP(dest
, 0)),
2479 operand_subword (src
, 0, TRUE
, mode
)));
2481 } else if (GET_CODE (dest
) == MEM
&& GET_CODE (src
) == REG
)
2483 emit_insn (gen_rtx_SET (VOIDmode
,
2484 adjust_address (dest
, SImode
, 0),
2485 operand_subword (src
, 0, TRUE
, mode
)));
2487 emit_insn (gen_rtx_SET (VOIDmode
,
2488 adjust_address (dest
, SImode
, UNITS_PER_WORD
),
2489 operand_subword (src
, 1, TRUE
, mode
)));
2494 debug_rtx(operands
[0]);
2495 debug_rtx(operands
[1]);
2505 const char *zpu_changestackpointer(rtx operands
[], rtx insn
)
2510 set
=single_set(insn
);
2516 t
[0]=stack_pointer_rtx
;
2519 return zpu_generate_move(t
, insn
);
2527 #undef TARGET_ASM_FILE_START
2528 #define TARGET_ASM_FILE_START zpu_file_start
2529 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
2530 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
2533 struct gcc_target targetm
= TARGET_INITIALIZER
;