Added -mno-memreg to use CALL for registers. -mmemreg now uses global variable _memre...
[zpugcc.git] / toolchain / gcc / gcc / config / zpu / zpu.c
blobd7c81230a911817ddd15fbb4fd5fc450f988f0cb
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)
11 any later version.
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. */
23 #include <stdio.h>
24 #include <limits.h>
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "tm_p.h"
32 #include "regs.h"
33 #include "real.h"
34 #include "insn-config.h"
35 #include "insn-flags.h"
36 #include "expr.h"
37 #include "recog.h"
38 #include "reload.h"
39 #include "output.h"
40 #include "hard-reg-set.h"
41 #include "real.h"
42 #include "insn-config.h"
43 #include "conditions.h"
44 #include "output.h"
45 #include "insn-attr.h"
46 #include "flags.h"
47 #include "libfuncs.h"
48 #include "toplev.h"
49 #include "basic-block.h"
50 #include "function.h"
51 #include "ggc.h"
53 #include "target.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
65 * location
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"); \
80 abort(); \
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)
98 missingOperand();
100 return regMapper[regNo-R_STACK_REG];
103 /* sp + offset to stack register */
104 static int stackRegOffset(rtx operand)
106 int num;
107 num=stackSlotNum(REGNO(operand));
108 return current_function_outgoing_args_size+num*4-totalStackOffset();
111 static int addSpRange(rtx operand, int *found)
113 *found=0;
115 if (current_function_calls_alloca)
117 /* no way to know in this case */
118 return -1;
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();
126 } else
128 if ((REGNO(operand)>=R_STACK_REG)&&
129 (REGNO(operand)<=R_STACK_REG_LAST))
131 *found=1;
132 return stackRegOffset(operand);
135 } else
137 return loadstoresp_offset(operand, found)-totalStackOffset();
139 return -1;
142 static void pushHardReg(rtx reg)
144 rtx regAddr=GEN_INT(REGNO(reg)*4);
146 if (TARGET_MEMREG)
148 zpu_asm("im _memreg+%0", &regAddr);
149 zpu_asm("load", NULL);
150 } else
152 zpu_asm("im %0", &regAddr);
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
164 int num;
165 rtx offset;
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);
171 stackOffset+=4;
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);
183 } else
185 missingOperand();
187 } else if (REGNO(operand)<R_NUM)
189 if (current_function_calls_alloca)
191 pushRegAddress(operand);
192 zpu_asm("load", NULL);
193 } else
195 int num;
196 num=stackSlotNum(REGNO(operand));
197 zpu_loadsp(current_function_outgoing_args_size+num*4);
198 stackOffset+=4;
200 } else
202 missingOperand();
206 static void popHardReg(rtx reg)
208 rtx addr;
209 addr=GEN_INT(REGNO(reg)*4);
211 if (TARGET_MEMREG)
213 zpu_asm("im _memreg+%0", &addr);
214 zpu_asm("store", NULL);
215 } else
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)
231 popHardReg(operand);
233 } else if (REGNO(operand)<R_NUM)
235 if (current_function_calls_alloca)
237 pushRegAddress(operand);
238 zpu_asm("store", NULL);
239 } else
241 int num;
242 num=stackSlotNum(REGNO(operand));
243 zpu_storesp(current_function_outgoing_args_size+num*4);
245 } else
247 missingOperand();
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)
257 return 0;
259 if (GET_CODE(b)!=REG)
261 return 0;
264 return REGNO(a)==REGNO(b);
267 static void comment(const char *format ATTRIBUTE_UNUSED, rtx *operands ATTRIBUTE_UNUSED)
269 #if 0
270 /* the testsuite chokes on this */
271 output_asm_insn(format, operands);
272 #endif
275 const char * zpu_asm_multi(const char *format, rtx *operands, int byteCount ATTRIBUTE_UNUSED)
277 int im;
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);
288 prevImmediate=im;
289 return "";
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)
315 popreg(newLocation);
316 } else
318 int found;
319 int loadsp_offset=loadstoresp_offset(newLocation, &found);
320 if (!found)
322 fprintf(stderr, "\nZPU: corrupt regStack\n");
323 missingOperand();
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);
335 stackOffset+=4;
339 static void discardRegStackTop(int persist)
341 rtx newLocation;
342 int i;
343 if ((regStackTop>regStackSize)||(regStackTop<=0))
345 fprintf(stderr, "ZPU: corrupt regStack\n");
346 missingOperand();
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)));
359 break;
363 reg[REGNO(regStack[regStackTop-1].reg)]=newLocation;
365 if (persist)
367 /* pop the register into the current location */
368 storeToReg(newLocation, regStack[regStackTop-1].reg);
371 regStackTop--;
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");
384 missingOperand();
387 regStack[regStackTop].reg=t;
388 regStackTop++;
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
393 * SP
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)
402 rtx set;
403 set=single_set(insn);
404 if (set!=NULL_RTX)
406 return
407 GET_CODE (SET_SRC (set)) == REG
408 && GET_CODE (SET_DEST (set)) == REG
409 && REGNO (SET_SRC (set)) == REGNO (SET_DEST (set));
411 return 0;
414 static int zpu_can_be_split(rtx insn)
416 rtx set;
417 set=single_set(insn);
418 if (set!=NULL_RTX)
420 return (GET_MODE(SET_SRC (set)) != SImode);
422 return 0;
426 /* it is safe to err on the side of caution here and return 0
427 * if we don't know.
429 static rtx zpu_next_insn(rtx insn)
431 while (insn)
433 insn = NEXT_INSN (insn);
434 switch (GET_CODE(insn))
436 case JUMP_INSN:
437 return insn;
439 case INSN:
440 if (zpu_noop_set(insn))
442 /* DRAGONS! we must skip noop moves, because they
443 * are eliminated by the emitter
445 break;
448 if (zpu_can_be_split(insn))
450 return NULL;
453 return insn;
455 /* skip */
456 case NOTE:
457 break;
459 default:
460 /* we don't handle these */
461 return NULL;
465 return insn;
468 static int stackPlusConst(rtx operand, int *found)
470 rtx op0,op1;
471 *found=0;
472 if(GET_CODE(operand) != PLUS)
474 return 0;
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))
481 *found=1;
482 return INTVAL(op1);
484 if((GET_CODE(op1)==REG) &&(REGNO(op1)==R_SP)
485 && (GET_CODE(op0)==CONST_INT))
487 *found=1;
488 return INTVAL(op0);
490 return 0;
493 static int loadstoresp_offset(rtx operand, int *found)
495 *found=0;
496 if (GET_MODE(operand)!=SImode)
498 return -1;
500 if (GET_CODE(operand)!=MEM)
502 return -1;
504 operand=XEXP(operand, 0);
506 if ((GET_CODE(operand)==REG)&&(REGNO(operand)==R_SP))
508 *found=1;
509 return 0;
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)
520 return 0;
523 switch (GET_CODE(op))
525 case LE:
526 case GE:
527 case LEU:
528 case GEU:
529 case GT:
530 case LT:
531 case GTU:
532 case LTU:
533 case COMPARE:
534 case ASHIFT:
535 case XOR:
538 case IOR:
539 case AND:
540 case MINUS:
541 case PLUS:
543 return 1;
544 case ASHIFTRT:
545 return TARGET_ASHIFTRT;
546 case LSHIFTRT:
547 return TARGET_LSHIFTRT;
548 case MULT:
549 return TARGET_MULT;
550 case DIV:
551 return TARGET_DIV;
552 case MOD:
553 return TARGET_MOD;
555 default:
556 break;
558 return 0;
564 int zpu_unary_operator (rtx op ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED)
566 if (GET_MODE(op)!=SImode)
568 return 0;
571 switch (GET_CODE(op))
573 case NEG:
574 case NOT:
575 return 1;
577 default:
578 break;
580 return 0;
583 static int countReg;
585 static int opCheckTerminal(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED, int strict)
587 if (CONSTANT_P(op)&&(GET_CODE(op)!=CONST_DOUBLE))
589 return 1;
592 switch (GET_CODE(op))
594 case REG:
595 if ((REGNO(op)<FIRST_PSEUDO_REGISTER)||!strict)
597 if ((REGNO(op)!=R_PC)&&(REGNO(op)!=R_SP))
599 countReg++;
601 return 1;
603 break;
605 default:
606 break;
609 return 0;
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 */
620 case MULT:
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))
628 return 1;
632 return 0;
633 case PLUS:
634 return opCheckTerminal(XEXP(op, 0), mode, strict)&&
635 opCheckTerminal(XEXP(op, 1), mode, strict);
637 case PRE_DEC:
638 if (REG_P(XEXP(op, 0))&&(REGNO(XEXP(op, 0))==R_SP))
640 return 1;
642 break;
644 case POST_INC:
645 if (((mode==DFmode)||(mode==DImode))&&
646 REG_P(XEXP(op, 0))&&
647 (REGNO(XEXP(op, 0))==R_SP))
649 return 1;
652 if ((mode!=SImode)&&(mode!=HImode)&&(mode!=QImode))
654 return 0;
656 if (REG_P(XEXP(op, 0))&&
657 ((REGNO(XEXP(op, 0))<=R_SP)
659 (!strict&&(REGNO(XEXP(op, 0))>=FIRST_PSEUDO_REGISTER))
664 return 1;
666 break;
668 default:
669 return opCheckTerminal(op, mode, strict);
672 return 0;
677 int zpu_legitimate_address(enum machine_mode mode ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED, int strict ATTRIBUTE_UNUSED)
679 countReg=0;
681 if (opCheck(x, SImode, strict))
683 return countReg<MAX_REGS_PER_ADDRESS;
685 return 0;
688 void print_operand (FILE *file, rtx op, int letter)
691 if (letter=='R')
693 print_rtl (file, op);
694 return;
697 switch (GET_CODE (op))
699 case PLUS:
700 print_operand(file, XEXP(op, 0), letter);
701 fprintf(file, "+");
702 print_operand(file, XEXP(op, 1), letter);
703 break;
704 case REG:
705 if (letter=='X')
707 fprintf(file, "%d", REGNO(op)*4);
708 } else
710 fprintf(file, "%s", reg_names[REGNO (op)]);
712 break;
714 case CONST_DOUBLE:
716 if (GET_MODE(op)==SFmode)
718 REAL_VALUE_TYPE r;
719 long l;
721 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
722 REAL_VALUE_TO_TARGET_SINGLE (r, l);
723 asm_fprintf (file, "%I0x%lx", l);
725 #if 0
726 else if (GET_MODE(op)==DFmode)
728 REAL_VALUE_TYPE r;
729 long l[2];
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]);
735 #endif
736 else
738 output_addr_const(file, op);
740 break;
742 case CONST_INT:
743 fprintf(file, "%d", (int)INTVAL (op));
744 break;
746 case LABEL_REF:
747 case SYMBOL_REF:
748 case CODE_LABEL:
749 output_addr_const(file, op);
750 break;
752 case MEM:
753 if (letter!='X')
755 fprintf(file, "(");
757 print_operand(file, XEXP (op, 0), letter);
758 if (letter!='X')
760 fprintf(file, ")");
762 break;
765 default:
766 output_addr_const(file, op);
767 break;
776 static void initGenerate(rtx insn ATTRIBUTE_UNUSED)
778 current_insn=insn;
780 if ((next_insn_saved!=NULL) && (current_insn!=next_insn_saved))
782 rtx t;
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);
792 missingOperand();
795 stackOffset=0;
798 static int totalStackOffset(void)
800 int t;
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;
805 if (t>0)
807 fprintf(stderr, "ZPU: illegal stack offset %d\n", -t);
808 missingOperand();
810 return t;
813 static void zpu_pushspadd(int offset)
815 rtx t;
816 if (TARGET_PUSHSPADD)
818 t=GEN_INT((offset+4)/4);
819 zpu_asm("im %0", &t);
820 zpu_asm("pushspadd", &t);
821 } else
823 t=GEN_INT(offset);
824 zpu_asm("pushsp", &t);
825 if (offset!=0)
827 zpu_asm("im %0", &t);
828 zpu_asm("add", &t);
833 static void zpu_addsp(int offset)
835 rtx t;
836 t=GEN_INT(offset);
837 if (TARGET_ADDSP)
839 zpu_asm("addsp %0", &t);
840 } else
842 zpu_asm("pushsp", NULL);
843 if (offset!=0)
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)
855 rtx t;
856 if (offset<0)
858 missingOperand();
861 t=GEN_INT(offset);
862 if (TARGET_LOADSP&&(offset/4<32))
864 zpu_asm("loadsp %0", &t);
865 } else
867 zpu_pushspadd(offset);
868 zpu_asm("load", &t);
874 static void zpu_loadsp(int offset)
877 offset-=totalStackOffset();
879 zpu_coreloadsp(offset);
880 stackOffset-=4;
884 static void zpu_storesp(int offset)
886 rtx t;
887 offset-=totalStackOffset();
889 if (offset<0)
891 missingOperand();
894 if (TARGET_STORESP&&(offset/4<32))
896 t=GEN_INT(offset);
897 zpu_asm("storesp %0", &t);
898 } else
900 zpu_pushspadd(offset);
901 zpu_asm("store", &t);
907 static int zpu_stack_change(rtx x)
909 rtx set;
910 set=single_set(x);
911 if (set!=NULL_RTX)
913 rtx dest=SET_DEST(set);
914 rtx src=SET_SRC(set);
915 if ((GET_CODE(dest)==REG)&&(REGNO(dest)==R_SP))
917 return 1;
920 if (GET_CODE(dest)==MEM)
922 if (GET_CODE(XEXP(dest, 0))==PRE_DEC)
924 if (REG_P(XEXP(XEXP(dest, 0), 0))&&REGNO(XEXP(XEXP(dest, 0), 0))==R_SP)
926 return 1;
930 if ((GET_CODE(dest)==REG)&&(REGNO(dest)==R_SP))
932 return 1;
934 if (GET_CODE(src)==MEM)
936 if (GET_CODE(XEXP(src, 0))==POST_INC)
938 if (REG_P(XEXP(XEXP(src, 0), 0))&&REGNO(XEXP(XEXP(src, 0), 0))==R_SP)
940 return 1;
945 return 0;
949 static int isInBasicBlock(rtx insn)
951 if (insn==NULL_RTX)
953 return 0;
955 if (GET_CODE(insn)==INSN)
957 if (!zpu_stack_change(insn))
959 rtx set;
960 set=single_set(insn);
961 if (set!=NULL_RTX)
963 if (GET_CODE(SET_SRC(set))!=ASM_OPERANDS)
965 return 1;
970 return 0;
976 static void cleanupGenerate(void)
978 rtx t;
979 if (stackOffset!=0)
981 fprintf(stderr, "ZPU: stackOffset %d\n", stackOffset);
982 missingOperand();
985 /* purge all dead registers off the stack */
986 while ((regStackTop>0)&&find_regno_note(current_insn, REG_DEAD, REGNO(regStack[regStackTop-1].reg)))
988 popRegStack();
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))
1000 next_insn_saved=t;
1001 } else
1003 comment("; barrier, purge regstack", &current_insn);
1004 while (regStackTop>0)
1006 popRegStack();
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);
1019 stackOffset-=4;
1020 return "";
1023 static void zpu_neg(rtx *operand)
1025 if (TARGET_NEG)
1027 zpu_asm("neg", operand);
1028 } else
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)
1045 int i, j;
1046 enum rtx_code code;
1047 const char *format_ptr;
1048 int count;
1050 if (x==NULL)
1051 return 0;
1053 if (CONSTANT_P(x))
1055 return 0;
1059 code=GET_CODE(x);
1060 switch (code)
1062 case EXPR_LIST:
1063 return 0;
1065 case SET:
1066 return zpu_first_push(SET_SRC(x), find);
1068 case PLUS:
1069 case XOR:
1070 case AND:
1071 case IOR:
1072 return zpu_first_push(XEXP(x, 0), find)||zpu_first_push(XEXP(x, 1), find);
1074 case REG:
1075 return (x==find);
1077 /* these are handled by the generic code below */
1078 case INSN:
1079 break;
1081 default:
1082 /* err on the side of caution */
1083 return 0;
1087 format_ptr = GET_RTX_FORMAT (code);
1088 count = 0;
1090 for (i = 0; i < GET_RTX_LENGTH (code); i++)
1092 switch (*format_ptr++)
1094 case 'e':
1095 return zpu_first_push (XEXP (x, i), find);
1097 case 'E':
1098 for (j = 0; j < XVECLEN (x, i); j++)
1099 return zpu_first_push (XVECEXP (x, i, j), find);
1102 return 0;
1105 static void zpu_call_asm(void)
1107 if (TARGET_CALL)
1109 zpu_asm("call", NULL);
1110 } else
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)
1134 missingOperand();
1137 if (TARGET_CALLPCREL&&CONSTANT_P(XEXP(operand[0], 0)))
1139 zpu_asm("impcrel %0", operand);
1140 zpu_asm("callpcrel", operand);
1141 } else
1143 /* address to call... */
1144 push_operand_address(operand);
1146 if (regStackTop!=0)
1148 fprintf(stderr, "ZPU: regStackTop %d\n", regStackTop);
1149 missingOperand();
1151 zpu_call_asm();
1154 stackOffset+=4;
1159 static int
1160 zpu_count_occurrences (rtx x, rtx find)
1162 int i, j;
1163 enum rtx_code code;
1164 const char *format_ptr;
1165 int count;
1167 if (x==NULL)
1168 return 0;
1170 code=GET_CODE(x);
1171 switch (code)
1173 case EXPR_LIST:
1174 return 0;
1175 default:
1176 break;
1179 if ((GET_CODE(x) == REG)&&(REGNO(x)==REGNO(find)))
1180 return 1;
1183 format_ptr = GET_RTX_FORMAT (code);
1184 count = 0;
1186 for (i = 0; i < GET_RTX_LENGTH (code); i++)
1188 switch (*format_ptr++)
1190 case 'e':
1191 count += zpu_count_occurrences (XEXP (x, i), find);
1192 break;
1194 case 'E':
1195 for (j = 0; j < XVECLEN (x, i); j++)
1196 count += zpu_count_occurrences (XVECEXP (x, i, j), find);
1197 break;
1200 return count;
1203 /* we must err on the side of caution here. */
1204 static int zpu_first_only_push(rtx x, rtx find)
1206 int result=0;
1207 if (zpu_first_push(x, find))
1209 enum rtx_code code;
1210 code=GET_CODE(x);
1211 if (code==SET)
1213 x=SET_SRC(x);
1216 if (zpu_count_occurrences(x, find)==1)
1218 result=1;
1221 return result;
1229 /* if:
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)
1239 int result=0;
1240 if (find_regno_note(insn, REG_DEAD, REGNO (op)))
1242 result=1;
1243 } else
1245 rtx set = single_set (insn);
1246 if (set!=NULL_RTX)
1248 if (SET_DEST(set)==op)
1250 result=1;
1255 return result;
1258 /* Check if the operand on the regStack is one of the operands and
1259 * push it first
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));
1267 } else
1269 /* either this is the other correct way, or it doesn't matter which way we
1270 * do it.
1272 push_operand_value(&XEXP(operand, 0));
1273 push_operand_value(&XEXP(operand, 1));
1278 static int isFreePopPush(rtx *operand)
1280 int freePopPush=0;
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 */
1284 if (stackOffset==0)
1286 if (regStackTop<=0)
1288 fprintf(stderr, "ZPU: regStack corrupted\n");
1289 missingOperand();
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))
1300 popRegStack();
1303 if (regStackTop<=0)
1305 missingOperand();
1307 comment("; eliminated pop&push %0", operand);
1308 if (debug_output)
1310 fprintf(stderr, "ZPU: eliminated poppush!\n");
1311 debug_rtx (current_insn);
1313 freePopPush=1;
1318 return freePopPush;
1321 static int postIncMemSize;
1322 static void push_operand_value(rtx *operand)
1324 if (CONSTANT_P(*operand))
1326 zpu_immediate(operand);
1327 return;
1331 if (GET_CODE(*operand)==REG)
1333 if (REGNO(*operand)==R_PC)
1335 zpu_asm("pushpc", operand);
1336 stackOffset-=4;
1337 } else if (REGNO(*operand)==R_SP)
1339 zpu_asm("pushsp", operand);
1341 if (stackOffset>0)
1343 missingOperand();
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);
1354 stackOffset-=4;
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
1363 * stack slot
1365 discardRegStackTop(0);
1366 stackOffset-=4;
1367 } else
1369 comment("; referring to unpopped register %0", operand);
1370 if (debug_output)
1372 fprintf(stderr, "ZPU: unpopped register\n");
1373 debug_rtx (reg[REGNO(*operand)]);
1375 push_operand_value(&reg[REGNO(*operand)]);
1377 } else
1379 pushreg(*operand);
1380 stackOffset-=4;
1382 } else
1384 missingOperand();
1386 return;
1387 } else if (GET_CODE (*operand) == POST_INC)
1389 rtx reg;
1390 rtx size;
1391 reg=XEXP (*operand, 0);
1392 if (GET_CODE(reg)!=REG)
1394 missingOperand();
1397 if (REGNO(reg)>=R_SP)
1399 missingOperand();
1402 push_operand_value(&reg);
1404 zpu_coreloadsp(0);
1405 stackOffset-=4;
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 */
1411 persistReg(reg);
1412 } else if (GET_CODE (*operand) == MEM)
1414 int found;
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. */
1420 stackOffset-=4;
1421 } else if (found)
1423 zpu_loadsp(loadsp_offset);
1424 } else
1426 postIncMemSize=GET_MODE_SIZE(GET_MODE(*operand));
1428 push_operand_value(&XEXP (*operand, 0));
1429 switch (GET_MODE(*operand))
1431 case SFmode:
1432 case SImode:
1433 zpu_asm("load", operand);
1434 break;
1435 case HImode:
1436 if (TARGET_SHORTOP)
1438 zpu_asm("loadh", NULL);
1439 } else
1441 zpu_asm("im _loadh", NULL);
1442 zpu_call_asm();
1444 break;
1445 case QImode:
1446 if (TARGET_BYTEOP)
1448 zpu_asm("loadb", NULL);
1449 } else
1451 zpu_asm("im _loadb", NULL);
1452 zpu_call_asm();
1455 break;
1456 default:
1457 fprintf(stderr, "FIX!!!! miissing operand\n");
1458 print_rtl(stderr, *operand);
1459 fprintf(stderr, "\n");
1460 break;
1463 } else if (GET_CODE(*operand)==PLUS)
1465 int found;
1466 int offset;
1467 offset=stackPlusConst(*operand, &found);
1468 if (found&&((offset%4)==0))
1470 offset-=totalStackOffset();
1471 zpu_pushspadd(offset);
1472 stackOffset-=4;
1473 } else
1474 if (isFreePopPush(&XEXP(*operand, 0))||isFreePopPush(&XEXP(*operand, 1)))
1476 push_assosiative(*operand);
1477 zpu_asm("add", operand);
1478 stackOffset+=4;
1479 } else
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))
1488 zpu_addsp(offset);
1489 } else
1491 push_operand_value(&XEXP(operand[0], 1));
1492 zpu_asm("add", NULL);
1493 stackOffset+=4;
1495 } else
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);
1506 stackOffset+=4;
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));
1538 zpu_neg(operand);
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));
1543 if (TARGET_EQ)
1545 zpu_asm("eq", operand);
1546 } else
1548 zpu_asm("im _eq", NULL);
1549 zpu_call_asm();
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))
1564 int sign;
1565 int flip_args;
1566 int equal;
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
1572 * other cases
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 */
1581 if (!sign)
1583 if (equal)
1585 if (TARGET_COMPARE)
1587 zpu_asm("ulessthanorequal", operand);
1588 } else
1590 zpu_asm("im _ulessthanorequal", NULL);
1591 zpu_call_asm();
1593 } else
1595 if (TARGET_COMPARE)
1597 zpu_asm("ulessthan", operand);
1598 } else
1600 zpu_asm("im _ulessthan", NULL);
1601 zpu_call_asm();
1604 } else
1606 if (equal)
1608 if (TARGET_COMPARE)
1610 zpu_asm("lessthanorequal", operand);
1611 } else
1613 zpu_asm("im _lessthanorequal", NULL);
1614 zpu_call_asm();
1616 } else
1618 if (TARGET_COMPARE)
1620 zpu_asm("lessthan", operand);
1621 } else
1623 zpu_asm("im _lessthan", NULL);
1624 zpu_call_asm();
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));
1647 zpu_addsp(0);
1648 } else
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)
1657 int mult=1;
1658 /* NOTE! This is a most crucial optimisation as MULT is used in
1659 * address modes.
1661 if ((GET_CODE(XEXP(*operand, 1))==CONST_INT))
1663 int c=INTVAL(XEXP(*operand, 1));
1664 if ((c==0)||(c==1))
1666 missingOperand();
1669 if ((c==2)||((optimize&&!optimize_size)&&((c==4)||(c==8))))
1671 mult=0;
1672 push_operand_value(&XEXP (*operand, 0));
1673 while (c>1)
1675 zpu_addsp(0);
1676 c/=2;
1681 if (mult)
1683 push_operand_value(&XEXP (*operand, 0));
1684 push_operand_value(&XEXP (*operand, 1));
1685 zpu_asm("mult", operand);
1686 stackOffset+=4;
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);
1693 stackOffset+=4;
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);
1699 stackOffset+=4;
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)))
1707 case VOIDmode:
1708 /* its a bit silly to extend a VOIDmode, i.e. a constant,
1710 * This is a no-op.
1712 break;
1713 case QImode:
1714 zpu_asm("im 0xff", operand);
1715 zpu_asm("and", operand);
1716 break;
1717 case HImode:
1718 zpu_asm("im 0xffff", operand);
1719 zpu_asm("and", operand);
1720 break;
1721 default:
1722 missingOperand();
1725 } else
1727 print_rtl(stderr, *operand);
1728 missingOperand();
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);
1748 } else
1750 missingOperand();
1755 static void store_to_operand(rtx *operand)
1757 if (GET_CODE(*operand)==PC)
1759 zpu_asm("poppc ; jump", operand);
1760 stackOffset+=4;
1761 } else if (GET_CODE(*operand)==REG)
1763 if (REGNO(*operand)==R_SP)
1765 zpu_asm("popsp", operand);
1766 stackOffset+=4;
1767 } else if (REGNO(*operand)==R_PC)
1769 zpu_asm("poppc ; jump", operand);
1770 stackOffset+=4;
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);
1781 stackOffset+=4;
1782 } else
1784 comment("; regStack full", operand);
1785 persistReg(*operand);
1787 } else
1789 missingOperand();
1791 } else if (GET_CODE(operand[0])==MEM)
1793 int found;
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");
1800 abort();
1804 if (GET_CODE(XEXP (operand[0], 0))==PRE_DEC)
1806 rtx reg=XEXP(XEXP(operand[0], 0), 0);
1807 if (!REG_P(reg))
1809 missingOperand();
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 */
1815 stackOffset+=4;
1816 } else
1818 missingOperand();
1820 } else if (found)
1822 zpu_storesp(loadsp_offset);
1823 stackOffset+=4;
1824 } else
1826 postIncMemSize=GET_MODE_SIZE(GET_MODE(*operand));
1828 push_operand_address(operand);
1829 switch (GET_MODE(operand[0]))
1831 case SFmode:
1832 case SImode:
1833 zpu_asm("store", operand);
1834 break;
1835 case HImode:
1836 if (TARGET_SHORTOP)
1838 zpu_asm("storeh", NULL);
1839 } else
1841 zpu_asm("im _storeh", NULL);
1842 zpu_call_asm();
1844 break;
1845 case QImode:
1846 if (TARGET_BYTEOP)
1848 zpu_asm("storeb", NULL);
1849 } else
1851 zpu_asm("im _storeb", NULL);
1852 zpu_call_asm();
1855 break;
1856 default:
1857 fprintf(stderr, "FIX!!!! Missing operand\n");
1858 print_rtl(stderr, *operand);
1859 fprintf(stderr, "\n");
1860 break;
1862 stackOffset+=8;
1864 } else
1866 fprintf(stderr, "\nUnsupported dest\n");
1867 print_rtl (stderr, *operand);
1868 fprintf(stderr, "\n");
1869 abort();
1871 stackOffset+=4;
1877 const char *zpu_generate_move(rtx operands[], rtx insn ATTRIBUTE_UNUSED)
1879 initGenerate(insn);
1881 comment("/* move %R1, %R0 */", operands);
1883 /* first we push the source onto the stack, then we figure out the
1884 * destination
1886 push_operand_value(operands+1);
1888 store_to_operand(operands+0);
1890 cleanupGenerate();
1892 return "";
1895 const char *zpu_generate_set(rtx insn)
1897 rtx set;
1898 initGenerate(insn);
1900 set=single_set(insn);
1901 comment("/* %R0 */", &set);
1903 /* first we push the source onto the stack, then we figure out the
1904 * destination
1906 push_operand_value(&SET_SRC(set));
1908 store_to_operand(&SET_DEST(set));
1910 cleanupGenerate();
1912 return "";
1915 static void zpu_neqbranch(rtx operand)
1918 zpu_asm("impcrel %0", &operand);
1919 if (TARGET_NEQBRANCH)
1922 zpu_asm("neqbranch", NULL);
1923 } else
1925 zpu_asm("im _neqbranch", NULL);
1926 zpu_call_asm();
1931 const char *zpu_generate_if_then_else(rtx operands[], rtx insn ATTRIBUTE_UNUSED)
1933 initGenerate(insn);
1935 comment("/* if_then_else %R0 */", operands);
1937 /* evaluate boolean expression. this RTL contains the two suboperands */
1938 push_operand_value(&operands[0]);
1940 if (regStackTop!=0)
1942 fprintf(stderr, "ZPU: regStackTop %d\n", regStackTop);
1943 missingOperand();
1946 zpu_neqbranch(operands[3]);
1948 stackOffset+=4;
1950 cleanupGenerate();
1952 return "";
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);
1961 } else
1963 initGenerate(insn);
1965 /* evaluate boolean expression. this RTL contains the two suboperands */
1966 push_operand_value(&operands[0]);
1968 zpu_neqbranch(operands[1]);
1969 stackOffset+=4;
1971 cleanupGenerate();
1974 return "";
1978 static const char *zpu_jump_core(rtx operands[], rtx insn ATTRIBUTE_UNUSED, int table)
1980 initGenerate(insn);
1981 comment("/* jump %R0 */", operands);
1983 /* put address on stack */
1984 push_operand_value(operands+0);
1986 if (table)
1988 comment("/* tablejump */", operands);
1991 zpu_asm("poppc", operands);
1992 stackOffset+=4;
1994 cleanupGenerate();
1996 return "";
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)
2012 initGenerate(insn);
2014 if (regStackTop!=0)
2016 fprintf(stderr, "ZPU: regStackTop %d\n", regStackTop);
2017 missingOperand();
2020 /* put address on stack */
2021 if (TARGET_POPPCREL)
2023 zpu_asm("impcrel %0", operands);
2024 zpu_asm("poppcrel", operands);
2025 } else
2027 zpu_asm("im %0", operands);
2028 zpu_asm("poppc", NULL);
2031 cleanupGenerate();
2033 return "";
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)
2044 initGenerate(insn);
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 */
2049 stackOffset+=4;
2051 cleanupGenerate();
2053 return "";
2057 static int reg_save(int regno)
2059 int result=0;
2060 if (regs_ever_live[regno]&&!call_used_regs[regno])
2062 result=1;
2064 /* FIX!!! how do we check if we've eliminated the argument pointer? */
2065 return result;
2068 static int calcSavedSize(void)
2070 int regno;
2071 int savedSize=0;
2072 for (regno = 0; regno < R_STACK_REG; regno++)
2073 if (reg_save(regno))
2075 savedSize+=4;
2077 return savedSize;
2080 static int calcStackRegSize(void)
2082 int regno;
2083 int savedSize=0;
2084 for (regno = R_STACK_REG; regno < FIRST_PSEUDO_REGISTER; regno++)
2085 if (reg_save(regno))
2087 savedSize+=4;
2089 return savedSize;
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)
2097 int offset;
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)
2113 offset=0;
2114 } else
2116 abort ();
2118 return offset;
2121 static int allocFrameSize(void)
2123 return current_function_outgoing_args_size+calcStackRegSize()+get_frame_size();
2126 void zpu_expand_prologue (void)
2128 int i;
2129 int regno;
2130 rtx insn;
2131 rtx mem_push_rtx;
2132 HOST_WIDE_INT frameSize;
2133 int mapper=0;
2135 prevImmediate=0;
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)&&reg_save(i))
2145 regMapper[i-R_STACK_REG]=mapper++;
2147 reg[i]=gen_rtx_REG(SImode, i);
2149 regStackTop=0;
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();
2173 if (frameSize>0)
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;
2185 int regno;
2186 HOST_WIDE_INT frameSize;
2187 rtx mem_push_rtx;
2189 mem_pop_rtx = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
2191 frameSize=allocFrameSize();
2192 if (frameSize>0)
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)
2219 initGenerate(insn);
2221 zpu_gen_call(operands);
2223 cleanupGenerate();
2224 return "";
2228 const char *zpu_call_value(rtx operands[], rtx insn ATTRIBUTE_UNUSED)
2230 initGenerate(insn);
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);
2237 pushreg(reg);
2238 stackOffset-=4;
2240 store_to_operand(operands+0);
2243 cleanupGenerate();
2244 return "";
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]));
2256 static void
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
2271 must pop them all.
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)
2282 return size;
2284 if (TYPE_ARG_TYPES (funtype) == NULL_TREE
2285 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
2286 return size;
2288 return 0;
2296 move_double_src_operand (rtx op, enum machine_mode mode)
2298 switch (GET_CODE (op))
2300 case CONST_INT :
2301 case CONST_DOUBLE :
2302 return 1;
2304 case SUBREG:
2305 /* FIX! not entirely sure why this isn't
2306 * handled by register_operand
2308 return 1;
2310 case REG :
2311 return register_operand (op, mode);
2313 #if 0
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);
2318 else
2319 return register_operand (op, mode);
2320 #endif
2321 case MEM :
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)
2326 return 0;
2327 return memory_operand (op, mode);
2328 default :
2329 return 0;
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))
2340 case REG :
2341 case SUBREG :
2342 return register_operand (op, mode);
2343 #if 0
2344 case SUBREG :
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);
2349 else
2350 return register_operand (op, mode);
2351 #endif
2352 case MEM :
2353 /* Disallow auto inc for now. */
2354 if (GET_CODE (XEXP (op, 0)) == POST_INC)
2355 return 0;
2356 #if 0
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))
2361 return 0;
2362 #endif
2363 return memory_operand (op, mode);
2364 default :
2365 return 0;
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];
2378 rtx val;
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);
2388 start_sequence ();
2389 if (GET_CODE (dest) == REG)
2391 int dregno = REGNO (dest);
2393 /* Reg = reg. */
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)
2415 rtx words[2];
2416 split_double (src, &words[0], &words[1]);
2417 emit_insn (gen_rtx_SET (VOIDmode,
2418 operand_subword (dest, 0, TRUE, mode),
2419 words[0]));
2421 emit_insn (gen_rtx_SET (VOIDmode,
2422 operand_subword (dest, 1, TRUE, mode),
2423 words[1]));
2426 /* Reg = mem. */
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. */
2431 int reverse
2432 = (refers_to_regno_p (dregno, dregno + 1, XEXP (src, 0), 0) != 0);
2434 /* We used to optimize loads from single registers as
2436 ld r1,r3+; ld r2,r3
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)));
2455 else
2456 abort ();
2459 /* Mem = reg. */
2460 /* We used to optimize loads from single registers as
2462 st r1,r3; st r2,+r3
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)));
2492 else
2494 debug_rtx(operands[0]);
2495 debug_rtx(operands[1]);
2496 abort();
2499 val = get_insns ();
2500 end_sequence ();
2501 return val;
2505 const char *zpu_changestackpointer(rtx operands[], rtx insn)
2507 rtx t[2];
2508 rtx set;
2510 set=single_set(insn);
2511 if (set==NULL_RTX)
2513 abort();
2516 t[0]=stack_pointer_rtx;
2517 t[1]=SET_SRC(set);
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;
2536 #include "gt-zpu.h"