#include #include "config.h" #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" #include "insn-config.h" #include "conditions.h" #include "insn-flags.h" #include "output.h" #include "insn-attr.h" #include "tree.h" #include "flags.h" #include "function.h" enum reg_class regclass_map[] = { AREG, DREG, CREG, BREG, SIREG, DIREG, BPREG, GENERAL_REGS }; static char *register_names[] = REGISTER_NAMES; int i86_reg_class_from_letter(c) { switch (c) { case 'a': return AREG; case 'b': return BREG; case 'c': return CREG; case 'd': return DREG; case 'S': return SIREG; case 'D': return DIREG; case 'B': return BPREG; case 'r': return GENERAL_REGS; case 'q': return Q_REGS; } return NO_REGS; } i86_const_ok_for_letter_p(v,c) { switch (c) { case 'I': /* The constant that we can shift by: shl ax,1 */ return v == 1; case 'J': /* I/O ports and byte registers */ return v >= 0 && v <= 255; } return 0; } /* The purpose of this function is to decide if "x" represents an addressing mode that the assembler can handle directly. If not, gcc will simplify it. */ #define DEBUG 0 static char packreg[] = "gggbiibs"; char * pack_rtx(r, buf, ebuf, strict) rtx r; char *buf, *ebuf; { rtx x0, x1; if (buf >= ebuf) return buf; switch (GET_CODE(r)) { case PLUS: *buf++ = '+'; buf = pack_rtx(XEXP(r,0), buf, ebuf, strict); buf = pack_rtx(XEXP(r,1), buf, ebuf, strict); break; case MEM: *buf++ = 'm'; buf = pack_rtx(XEXP(r,0), buf, ebuf, strict); break; case PRE_DEC: *buf++ = '<'; buf = pack_rtx(XEXP(r,0), buf, ebuf, strict); break; case REG: if (strict || REGNO(r)= FIRST_PSEUDO_REGISTER ? '?' : packreg[REGNO(r)]; else *buf++ = 'p'; break; case CONST: case CONST_INT: case SYMBOL_REF: *buf++ = '#'; break; default: *buf++ = '?'; break; } return buf; } static char *valid_addr_list[] = { "#", "b", "i", "p", "+bi", "+ib", "+pi", "+ip", "+pb", "+bp", "+pp", "+b#", "+i#", "+p#", "++bi#", "++ib#", "++pi#", "++ip#", "++pb#", "++bp#", "++pp#", "= 0; regno--) if (regs_ever_live[regno] && ! call_used_regs[regno]) fprintf(file, "\tpush\t%s\n", register_names[regno]); fprintf(file, "\n"); } i86_function_epilog(file, size) FILE *file; int size; { int regno; fprintf(file, "\n"); for (regno = 0; regno <= 5; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) fprintf(file, "\tpop\t%s\n", register_names[regno]); fprintf(file, "\tleave\n"); fprintf(file, "\tret\n\n"); } #undef DEBUG #define DEBUG 0 i86_print_operand(s,x,c) FILE *s; rtx x; int c; { rtx x0; #if DEBUG printf("[i86_print_operand(%c)]\n", c?c:' '); print_rtl(stdout, x); printf("\n"); #endif switch (GET_CODE (x)) { case REG: if ((c == 'L' || c == 'H') && REGNO(x) <= 4) fprintf (s, "%c%c", register_names[REGNO(x)][0], c-'L'+'l'); else fprintf (s, "%s", register_names[REGNO(x)]); break; case MEM: if (c == 'P') i86_print_operand(s, XEXP(x,0), 0); else output_address(x); break; case PLUS: i86_print_operand(s, XEXP(x,0),' '); if (GET_CODE(XEXP(x,1)) == CONST_INT) { fprintf(s, "%+d", INTVAL(XEXP(x,1))); } else { fputc('+', s); i86_print_operand(s, XEXP(x,1),' '); } break; case SYMBOL_REF: assemble_name(s, XSTR(x,0)); break; case CONST: case CONST_INT: case CODE_LABEL: output_addr_const(s, x); break; default: printf("blah! default in i86_print_operand %d\n", GET_CODE(x)); break; } } i86_print_operand_address(s,x) FILE *s; rtx x; { putc('[', s); i86_print_operand(s,XEXP(x,0),0); putc(']', s); }