diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1994-07-11 19:23:51 -0400 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1994-07-11 19:23:51 -0400 |
commit | 630e77b6562e834c9f49124bd39117654dfa3259 (patch) | |
tree | 242fe03358b5faaaf36836f96da2d50b6ab3f57f /gcc/config/1750a/1750a.c | |
parent | b4d2cd972daef23a952fa516b9ba02e888d63d98 (diff) | |
download | gcc-630e77b6562e834c9f49124bd39117654dfa3259.zip gcc-630e77b6562e834c9f49124bd39117654dfa3259.tar.gz gcc-630e77b6562e834c9f49124bd39117654dfa3259.tar.bz2 |
Initial revision
From-SVN: r7731
Diffstat (limited to 'gcc/config/1750a/1750a.c')
-rw-r--r-- | gcc/config/1750a/1750a.c | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/gcc/config/1750a/1750a.c b/gcc/config/1750a/1750a.c new file mode 100644 index 0000000..67cf864 --- /dev/null +++ b/gcc/config/1750a/1750a.c @@ -0,0 +1,530 @@ +/* Subroutines for insn-output.c for MIL-STD-1750A. + Copyright (C) 1994 Free Software Foundation, Inc. + Contributed by O.M.Kellogg, Deutsche Aerospace (okellogg@salyko.cube.net). + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 1, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef FILE +#include <stdio.h> +#endif + +#define __datalbl +#include "config.h" +#include "rtl.h" +#include "tree.h" +#include "expr.h" +#define HAVE_cc0 +#include "conditions.h" +#include "real.h" + +struct datalabel_array datalbl[DATALBL_ARRSIZ]; +int datalbl_ndx = -1; +struct jumplabel_array jmplbl[JMPLBL_ARRSIZ]; +int jmplbl_ndx = -1; +int label_pending = 0, program_counter = 0; +enum section current_section=NREL; +char *sectname[4] = { "NREL","IREL","KREL","SREL" }; + +int notice_update_cc(exp) + rtx exp; +{ + if (GET_CODE (exp) == SET) + { + enum rtx_code src_code = GET_CODE (SET_SRC (exp)); + /* Jumps do not alter the cc's. */ + if (SET_DEST (exp) == pc_rtx) + return; + /* Moving register into memory doesn't alter the cc's. + It may invalidate the RTX's which we remember the cc's came from. */ + if (GET_CODE (SET_DEST (exp)) == MEM) + { + if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM) + cc_status.value1 = 0; + if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM) + cc_status.value2 = 0; + return; + } + /* Function calls clobber the cc's. */ + else if (src_code == CALL) + { + CC_STATUS_INIT; + return; + } + /* Emulated longword bit-ops leave cc's incorrect */ + else if (GET_MODE (SET_DEST (exp)) == HImode ? + src_code == AND || src_code == IOR || + src_code == XOR || src_code == NOT : 0) + { + CC_STATUS_INIT; + return; + } + /* Tests and compares set the cc's in predictable ways. */ + else if (SET_DEST (exp) == cc0_rtx) + { + CC_STATUS_INIT; + cc_status.value1 = SET_SRC (exp); + return; + } + /* Anything that lands in a reg will set cc_status. */ + else if (REG_P (SET_DEST (exp))) + { + cc_status.flags = CC_NO_OVERFLOW; + cc_status.value1 = SET_SRC (exp); + cc_status.value2 = SET_DEST (exp); + return; + } + else + { + CC_STATUS_INIT; + } + } + else if (GET_CODE (exp) == PARALLEL + && GET_CODE (XVECEXP (exp, 0, 0)) == SET) + { + if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) + return; + if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) + { + CC_STATUS_INIT; + cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); + return; + } + CC_STATUS_INIT; + } + else + { + CC_STATUS_INIT; + } +} + + +rtx function_arg(cum,mode,type,named) + int cum; + enum machine_mode mode; + tree type; + int named; +{ + int size; + rtx result; + + if (MUST_PASS_IN_STACK(mode,type)) + return (rtx) 0; + if (mode == BLKmode) + size = int_size_in_bytes(type); + else + size = GET_MODE_SIZE (mode); + if (cum + size < 12) + return gen_rtx(REG, mode, cum); + else + return (rtx) 0; +} + + +char *tekasm_float(exp_char,value) + char exp_char; + double value; +{ + extern char *strpbrk(); + int found_letter = 0; + char *p; + static char fbuf[20]; + + sprintf(fbuf,"%g",value); + if ((p = strpbrk(fbuf,"Ee")) == NULL) + sprintf(fbuf+strlen(fbuf),"%c0",exp_char); + else + *p = exp_char; + return fbuf; +} + +char *asm_float_syntax(rtx x) +{ + if (GET_MODE(x) == HFmode) + { + union { double d; int i[2]; } du; + union { float f; int i; } su; + du.i[0] = CONST_DOUBLE_LOW(x); + du.i[1] = CONST_DOUBLE_HIGH(x); + su.f = (float) du.d; + return tekasm_float('E',su.f); + } + else + { + union { double d; int i[2]; } du; + du.i[0] = CONST_DOUBLE_LOW(x); + du.i[1] = CONST_DOUBLE_HIGH(x); + return tekasm_float('D',du.d); + } +} + +char *float_label(char code,char *fltstr) +{ + int i=1; + static char label[32]; + + label[0] = code; + while (*fltstr) + { + label[i] = (*fltstr == '+') ? 'p' : + (*fltstr == '-') ? 'm' : *fltstr; + i++; + fltstr++; + } + if (i > 11) + i = 11; + label[i] = '\0'; + return label; +} + + +char *movcnt_regno_adjust(rtx *op) +{ + static char outstr[40]; + int cntreg = REGNO(op[2]), cntreg_1750 = REGNO(op[0]) + 1; + int dstreg = REGNO(op[0]), srcreg = REGNO(op[1]); + + if (cntreg == cntreg_1750) + sprintf(outstr,"MOV R%%0,R%%1"); + else if (dstreg+1 == srcreg && srcreg == cntreg+2) + sprintf(outstr,"XWR R%d,R%d\n\tMOV R%%0,R%%1",cntreg,dstreg); + else if (dstreg+1 == srcreg && srcreg < cntreg) + sprintf(outstr,"XWR R%d,R%d\n\tMOV R%%0,R%%1",srcreg,cntreg); + else if (srcreg+1 == cntreg && dstreg > cntreg) + sprintf(outstr,"XWR R%d,R%d\n\tMOV R%%0,R%%1",srcreg,dstreg); + else + sprintf(outstr,"XWR R%d,R%d\n\tMOV R%%0,%%1\n\tXWR R%d,R%d", + cntreg,cntreg_1750,cntreg_1750,cntreg); + return outstr; +} + +char *mod_regno_adjust(char *instr,rtx *op) +{ + static char outstr[40]; + char *r = (!strncmp(instr,"DVR",3) ? "R" : ""); + int modregno_gcc = REGNO(op[3]), modregno_1750 = REGNO(op[0]) + 1; + + if (modregno_gcc == modregno_1750) + sprintf(outstr,"%s R%%0,%s%%2",instr,r); + else + sprintf(outstr,"LR R%d,R%d\n\t%s R%%0,%s%%2\n\tXWR R%d,R%d", + modregno_gcc,modregno_1750,instr,r,modregno_1750,modregno_gcc); + return outstr; +} + + +/* Auxiliary to `nonindirect_operand': + Check if op is a valid memory operand for 1750A arith./logic (non-move) + instructions. */ +int memop_valid(register rtx op) +{ + if (GET_MODE(op) != Pmode && GET_MODE(op) != VOIDmode) + return 0; + switch (GET_CODE(op)) + { + case MEM: + case MINUS: + case MULT: + case DIV: + return 0; + case PLUS: + if (! memop_valid(XEXP(op,0))) + return 0; + return memop_valid(XEXP(op,1)); + case REG: + if (REGNO(op) > 0) + return 1; + return 0; + case CONST: + case CONST_INT: + case SYMBOL_REF: + case SUBREG: + return 1; + default: + printf("memop_valid: code=%d\n",(int) GET_CODE(op)); + return 1; + } +} + +/* extra predicate for recog: */ +int nonindirect_operand(register rtx op, enum machine_mode mode) +{ + int retval; + + switch (GET_CODE(op)) + { + case MEM: + retval = memop_valid(XEXP(op,0)); + return retval; + case REG: + return 1; + default: + if (! CONSTANT_P(op)) + return 0; + } + return 1; +} + +/* predicate for the STC instruction: */ +int small_nonneg_const(register rtx op, enum machine_mode mode) +{ + if (GET_CODE(op) == CONST_INT && INTVAL(op) >= 0 && INTVAL(op) <= 15) + return 1; + return 0; +} + +/* Decide whether to output a conditional jump as a "Jump Conditional" + or as a "Branch Conditional": */ + +int find_jmplbl(int labelnum) +{ + int i, found = 0; + + for (i = 0; i <= jmplbl_ndx; i++) + if (labelnum == jmplbl[i].num) + { + found = 1; + break; + } + if (found) + return i; + return -1; +} + +char *branch_or_jump(char *condition, int targetlabel_number) +{ + static char buf[30]; + int index; + + if ((index = find_jmplbl(targetlabel_number)) >= 0) + if (program_counter - jmplbl[index].pc < 128) + { + sprintf(buf,"B%s %%l0",condition); + return buf; + } + sprintf(buf,"JC %s,%%l0",condition); + return buf; +} + + + +/* The PRINT_OPERAND and PRINT_OPERAND_ADDRESS macros have been + made functions: */ + +print_operand(file, x, code) + FILE *file; + rtx x; + enum rtx_code code; +{ + switch (GET_CODE(x)) + { + case REG: + fprintf (file, "%d",REGNO (x)); + break; + case SYMBOL_REF: + fprintf(file,"%s",XSTR(x,0)); + break; + case LABEL_REF: + case CONST: + case MEM: + output_address(XEXP(x,0)); + break; + case CONST_DOUBLE: + if (code == 'D' || code == 'E') /* KREL output hack: */ + { /* make a label out of a floating-point number. */ + char *fltstr = (char *)asm_float_syntax(x); + int i, found = 0; + for (i = 0; i <= datalbl_ndx; i++) + if (strcmp(fltstr,datalbl[i].value) == 0) { found = 1; break; } + if (! found) + { + strcpy(datalbl[i = ++datalbl_ndx].value,fltstr); + strcpy(datalbl[i].name,(char *)float_label(code,fltstr)); + datalbl[i].size = (code=='D') ? 3 : 2; + check_section(KREL); + fprintf(file,"K%s \tDATAF %s ;p_o\n", datalbl[i].name,fltstr); + check_section(NREL); + } + } + else if (code == 'F') + { + char *fltstr = (char *)asm_float_syntax(x); + int i, found = 0; + for (i = 0; i <= datalbl_ndx; i++) + if (strcmp(fltstr,datalbl[i].value) == 0) + { + found = 1; + break; + } + if (! found) + { + printf("Aborting: 'F' float label not found in datalbl[].\n"); + abort(); + } + fprintf(file,"%s ;P_O 'F'",datalbl[i].name); + } + else + fprintf(file,"%s ;P_O cst_dbl",(char *)asm_float_syntax(x)); + break; + case CONST_INT: + if (code == 'J') + fprintf (file, "%d",-INTVAL(x)); + else if (INTVAL(x) > 0x7FFF) + fprintf (file, "%d ; range correction (val>0x7FFF) applied", + INTVAL(x) - 0x10000); + else + fprintf (file, "%d", INTVAL(x)); + break; + case CODE_LABEL: + fprintf (file, "L%d", XINT(x,3)); + break; + case CALL: + fprintf(file,"CALL nargs=%d, func is either '%s' or '%s'", + XEXP(x,1),XSTR(XEXP(XEXP(x,0),1),0),XSTR(XEXP(x,0),1)); + break; + case PLUS: + { + rtx op0 = XEXP(x,0), op1 = XEXP(x,1); + int op0code=GET_CODE(op0), op1code=GET_CODE(op1); + if (op1code == CONST_INT) + switch (op0code) + { + case REG: + fprintf(file,"%d,R%d ; p_o_PLUS for REG and CONST", + INTVAL(op1),REGNO(op0)); + break; + case SYMBOL_REF: + fprintf(file,"%d+%s",INTVAL(op1),XSTR(op0,0)); + break; + case MEM: + fprintf(file,"%d,[mem:",INTVAL(op1)); + output_address(XEXP(op0,0)); + fprintf(file,"] ;P_O plus"); + break; + default: + fprintf(file,"p_o_PLUS UFO, code=%d, with CONST=%d", + (int)op0code,INTVAL(op1)); + } + else if (op1code == SYMBOL_REF && op0code == REG) + fprintf(file,"%s,R%d ; P_O: (plus reg sym)", + XSTR(op1,0),REGNO(op0)); + else + fprintf(file,"p_o_+: op0code=%d, op1code=%d",op0code,op1code); + } + break; + default: + fprintf (file, "p_o_UFO code=%d", GET_CODE(x)); + } +} + +print_operand_address(file, addr) + FILE *file; + rtx addr; +{ + switch (GET_CODE (addr)) + { + case REG: + fprintf (file, "0,R%d ; P_O_A", REGNO (addr)); + break; + case PLUS: + { + register rtx x = XEXP(addr,0), y = XEXP(addr,1); + switch (GET_CODE(x)) + { + case REG: + switch (GET_CODE(y)) + { + case CONST: + output_address(XEXP(y,0)); + fprintf(file, ",R%d ;P_O_A reg + const expr",REGNO(x)); + break; + case CONST_INT: + fprintf(file,"%d,R%d ; P_O_A reg + const_int", + INTVAL(y),REGNO(x)); + break; + case SYMBOL_REF: + fprintf(file,"%s,R%d ; P_O_A reg + sym", + XSTR(y,0),REGNO(x)); + break; + default: + fprintf(file, "[P_O_A reg%d+UFO code=%d]", + REGNO(x),GET_CODE(y)); + } + break; + case LABEL_REF: + case SYMBOL_REF: + switch (GET_CODE(y)) + { + case CONST_INT: + fprintf (file,"%d+%s",INTVAL(y),XSTR(x,0)); + break; + case REG: + fprintf (file,"%s,R%d ;P_O_A sym + reg", + XSTR(x,0),REGNO(y)); + break; + default: + fprintf(file, "P_O_A sym/lab+UFO[sym=%s,code(y)=%d]", + XSTR(x,0),GET_CODE(y)); + } + break; + case CONST: + output_address(XEXP(x,0)); + if (GET_CODE(y) == REG) + fprintf(file, ",R%d ;P_O_A const + reg",REGNO(x)); + else + fprintf(file,"P_O_A const+UFO code(y)=%d]",GET_CODE(y)); + break; + case MEM: + output_address(y); + fprintf(file, ",[mem:"); + output_address(XEXP(x,0)); + fprintf(file, "] ;P_O_A plus"); + break; + default: + fprintf(file, "P_O_A plus op1_UFO[code1=%d,code2=%d]", + GET_CODE(x),GET_CODE(y)); + } + } + break; + case CONST_INT: + if (INTVAL(addr) < 0x10000 && INTVAL(addr) >= -0x10000) + fprintf (file, "%d ; p_o_a const addr?!", INTVAL(addr)); + else + { + fprintf(file,"[p_o_a=ILLEGAL_CONST]"); + output_addr_const (file, addr); + } + break; + case LABEL_REF: + case SYMBOL_REF: + fprintf(file,"%s",XSTR(addr,0)); + break; + case MEM: + fprintf(file,"[memUFO:"); + output_address(XEXP(addr,0)); + fprintf(file,"]"); + break; + case CONST: + output_address(XEXP(addr,0)); + fprintf(file," ;P_O_A const"); + break; + default: + fprintf(file," p_o_a UFO, code=%d val=0x%x", + (int) GET_CODE(addr),INTVAL(addr)); + break; + } +} + |