📄 out-mips.c
字号:
/* Compute a string to use as a temporary file name. */static FILE *make_temp_file (){ char *temp_filename; FILE *stream; extern char *getenv (); char *base = getenv ("TMPDIR"); int len; if (base == (char *)0) {#ifdef P_tmpdir if (access (P_tmpdir, R_OK | W_OK) == 0) base = P_tmpdir; else#endif if (access ("/usr/tmp", R_OK | W_OK) == 0) base = "/usr/tmp/"; else base = "/tmp/"; } len = strlen (base); temp_filename = (char *) alloca (len + sizeof("/ccXXXXXX")); strcpy (temp_filename, base); if (len > 0 && temp_filename[len-1] != '/') temp_filename[len++] = '/'; strcpy (temp_filename + len, "ccXXXXXX"); mktemp (temp_filename); stream = fopen (temp_filename, "w+"); if (!stream) pfatal_with_name (temp_filename); unlink (temp_filename); return stream;}/* Output at beginning of assembler file. If we are optimizing to use the global pointer, create a temporary file to hold all of the text stuff, and write it out to the end. This is needed because the MIPS assembler is evidently one pass, and if it hasn't seen the relevant .comm/.lcomm/.extern/.sdata declaration when the code is processed, it generates a two instruction sequence. */voidmips_asm_file_start (stream) FILE *stream;{ if (TARGET_NAME_REGS) fprintf (stream, "#include <regdef.h>\n"); ASM_OUTPUT_SOURCE_FILENAME (stream, main_input_filename); print_options (stream); data_section (); /* put gcc_compiled. in data, not text*/ if (TARGET_GP_OPT) { asm_out_data_file = stream; asm_out_text_file = make_temp_file (); } else asm_out_data_file = asm_out_text_file = stream;}/* If optimizing for the global pointer, keep track of all of the externs, so that at the end of the file, we can emit the appropriate .extern declaration for them, before writing out the text section. We assume that all names passed to us are in the permanent obstack, so that they will be valid at the end of the compilation. If we have -G 0, or the extern size is unknown, don't bother emitting the .externs. */intmips_output_external (file, decl, name) FILE *file; tree decl; char *name;{ extern char *permalloc (); register struct extern_list *p; int len; if (TARGET_GP_OPT && mips_section_threshold != 0 && ((TREE_CODE (decl)) != FUNCTION_DECL) && ((len = int_size_in_bytes (TREE_TYPE (decl))) > 0)) { p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list)); p->next = extern_head; p->name = name; p->size = len; extern_head = p; } return 0;}/* If we are optimizing the global pointer, emit the text section now and any small externs which did not have .comm, etc that are needed. Also, give a warning if the data area is more than 32K and -pic because 3 instructions are needed to reference the data pointers. */intmips_asm_file_end (file) FILE *file;{ char buffer[8192]; tree name_tree; struct extern_list *p; int len; extern tree lookup_name (); if (TARGET_GP_OPT) { if (extern_head) fputs ("\n", file); for (p = extern_head; p != 0; p = p->next) { name_tree = get_identifier (p->name); if (!TREE_ADDRESSABLE (name_tree)) { TREE_ADDRESSABLE (name_tree) = 1; fprintf (file, "\t.extern\t%s, %d\n", p->name, p->size); } } fprintf (file, "\n\t.text\n"); rewind (asm_out_text_file); if (ferror (asm_out_text_file)) fatal_io_error ("write of text assembly file in mips_asm_file_end"); while ((len = fread (buffer, 1, sizeof (buffer), asm_out_text_file)) > 0) if (fwrite (buffer, 1, len, file) != len) pfatal_with_name ("write of final assembly file in mips_asm_file_end"); if (len < 0) pfatal_with_name ("read of text assembly file in mips_asm_file_end"); if (fclose (asm_out_text_file) != 0) pfatal_with_name ("close of tempfile in mips_asm_file_end"); }}/* Fix references to the frame pointer to be off of the stack pointer. */struct rtx_def *mips_fix_frame_pointer (oldaddr, depth) rtx oldaddr; int depth;{ rtx newaddr; rtx sp_diff_rtx; char temp[40]; int frame_offset = 0; extern rtx eliminate_constant_term (); newaddr = eliminate_constant_term (oldaddr, &frame_offset); if (newaddr != frame_pointer_rtx) return oldaddr; if (sp_fp_difference == (char *)0) { sprintf (temp, "$Ls%d", number_functions_processed); sp_fp_difference = IDENTIFIER_POINTER (get_identifier (temp)); } sp_diff_rtx = gen_rtx (SYMBOL_REF, SImode, sp_fp_difference); if (frame_offset + depth == 0) newaddr = gen_rtx (PLUS, Pmode, stack_pointer_rtx, sp_diff_rtx); else newaddr = gen_rtx (PLUS, Pmode, stack_pointer_rtx, gen_rtx (CONST, Pmode, gen_rtx (PLUS, Pmode, sp_diff_rtx, gen_rtx (CONST_INT, VOIDmode, frame_offset + depth)))); if (TARGET_DEBUGC_MODE) { fprintf (stderr, "\n==================== FIX_FRAME, depth = %d, sp prealloc = %d, offset = %d\n", depth, stack_args_preallocated, frame_offset); fprintf (stderr, "old INSN:"); debug_rtx (oldaddr); fprintf (stderr, "\nnew INSN:"); debug_rtx (newaddr); } return newaddr;}/* Set up the stack and frame (if desired) for the function. */voidfunction_prologue (file, size) FILE *file; int size;{ extern char call_used_regs[]; extern char *reg_numchar[]; extern tree current_function_decl; int regno; int mask; int fmask; int push_loc; int tsize; int num_regs; char **reg_name_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar; char *base_str; char *sp_str = reg_name_ptr[STACK_POINTER_REGNUM]; char *fp_str = (!frame_pointer_needed) ? sp_str : reg_name_ptr[FRAME_POINTER_REGNUM]; tree fndecl = current_function_decl; /* current... is tooo long */ tree fntype = TREE_TYPE (fndecl); tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE) ? DECL_ARGUMENTS (fndecl) : 0; tree next_arg; tree cur_arg; char *arg_name = (char *)0; CUMULATIVE_ARGS args_so_far; inside_function = 1; if (write_symbols != NO_DEBUG) ASM_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl)); fprintf (file, "\t.ent\t%s\n%s:\n", current_function_name, current_function_name); fprintf (file, " #PROLOGUE\n"); /* Determine the last argument, and get it's name. */ for (cur_arg = fnargs; cur_arg != (tree)0; cur_arg = next_arg) { next_arg = TREE_CHAIN (cur_arg); if (next_arg == (tree)0) { if (DECL_NAME (cur_arg)) arg_name = IDENTIFIER_POINTER (DECL_NAME (cur_arg)); break; } } /* If this function is a varargs function, store any registers that would normally hold arguments ($4 - $7) on the stack. */ if ((TYPE_ARG_TYPES (fntype) != 0 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node)) || (arg_name && (strcmp (arg_name, "__builtin_va_alist") == 0 || strcmp (arg_name, "va_alist") == 0))) { tree parm; regno = 4; INIT_CUMULATIVE_ARGS (args_so_far, fntype); for (parm = fnargs; (parm && (regno <= 7)); parm = TREE_CHAIN (parm)) { rtx entry_parm; enum machine_mode passed_mode; tree type; type = DECL_ARG_TYPE (parm); passed_mode = TYPE_MODE (type); entry_parm = FUNCTION_ARG (args_so_far, passed_mode, DECL_ARG_TYPE (parm), 1); if (entry_parm) { int words; /* passed in a register, so will get homed automatically */ if (GET_MODE (entry_parm) == BLKmode) words = (int_size_in_bytes (type) + 3) / 4; else words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4; regno = REGNO (entry_parm) + words - 1; } else { regno = 8; break; } FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, DECL_ARG_TYPE (parm), 1); } switch (regno) { case 4: fprintf(file, "\tsd\t%s,0(%s)\t#varargs: home regs 4-5\n", reg_name_ptr[4], sp_str); fprintf(file, "\tsd\t%s,8(%s)\t#varargs: home regs 6-7\n", reg_name_ptr[6], sp_str); break; case 5: fprintf(file, "\tsw\t%s,4(%s)\t#varargs: home reg 5\n", reg_name_ptr[5], sp_str); fprintf(file, "\tsd\t%s,8(%s)\t#varargs: home regs 6-7\n", reg_name_ptr[6], sp_str); break; case 6: fprintf(file, "\tsd\t%s,8(%s)\t#varargs: home regs 6-7\n", reg_name_ptr[6], sp_str); break; case 7: fprintf(file, "\tsw\t%s,12(%s)\t#varargs: home reg 7\n", reg_name_ptr[7], sp_str); break; default: break; } } mask = 0; fmask = 0; num_regs = 0; push_loc = stack_args_preallocated; tsize = AL_ADJUST_ALIGN (size) + stack_args_preallocated; for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) if (MUST_SAVE_REGISTER (regno)) { tsize += 4; num_regs += 4; mask |= 1 << (regno - GP_REG_FIRST); } tsize = AL_ADJUST_ALIGN (tsize); num_regs = AL_ADJUST_ALIGN (num_regs); for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += 2) if (regs_ever_live[regno] && !call_used_regs[regno]) { tsize += 8; num_regs += 8; fmask |= 1 << (regno - FP_REG_FIRST); } if (tsize) tsize -= STARTING_FRAME_OFFSET; if (!frame_pointer_needed && sp_fp_difference != (char *)0) fprintf (file,"%s\t= %d\t\t\t#Difference between SP & FP\n\n", sp_fp_difference, tsize); current_function_total_framesize = tsize; current_function_saved_reg_size = num_regs; if (tsize > 0) { if (tsize <= 32767) fprintf (file, "\tsubu\t%s,%s,%d\t# temp= %d, regs= %d, args= %d, sfo= %d\n", sp_str, sp_str, tsize, size, num_regs, stack_args_preallocated, STARTING_FRAME_OFFSET); else fprintf (file, "\tli\t%s,%d\n\tsubu\t%s,%s,%s\t# temp= %d, regs= %d, args= %d, sfo= %d\n", reg_name_ptr[MIPS_TEMP1_REGNUM], tsize, sp_str, sp_str, reg_name_ptr[MIPS_TEMP1_REGNUM], size, num_regs, stack_args_preallocated, STARTING_FRAME_OFFSET); } fprintf (file, "\t.frame\t%s,%d,%s\n", fp_str, (frame_pointer_needed) ? 0 : tsize, reg_name_ptr[31]); if (push_loc > 32767 && num_regs > 0) { if ((tsize - (push_loc + num_regs)) <= 32767) { base_str = reg_name_ptr[MIPS_TEMP1_REGNUM]; push_loc = tsize - push_loc; } else { base_str = reg_name_ptr[MIPS_TEMP2_REGNUM]; fprintf (file, "\tli\t%s,%d\n", base_str, push_loc); push_loc = 0; } } else base_str = sp_str; for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) if ((mask & (1 << (regno - GP_REG_FIRST))) != 0) { fprintf (file, "\tsw\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc, base_str); push_loc += 4; } fprintf (file, "\t.mask\t0x%08x,%d\n", mask, push_loc - tsize - 4); push_loc = AL_ADJUST_ALIGN (push_loc); for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += 2) if ((fmask & (1 << (regno - FP_REG_FIRST))) != 0) { fprintf (file, "\ts.d\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc, base_str); push_loc += 8; } fprintf (file, "\t.fmask\t0x%08x,%d\n", fmask, push_loc - tsize - 4); if (frame_pointer_needed) { if (tsize <= 32767) fprintf (file, "\taddu\t%s,%s,%d\t# set up frame pointer\n", fp_str, sp_str, tsize); else fprintf (file, "\taddu\t%s,%s,%s\t# set up frame pointer\n", fp_str, sp_str, reg_name_ptr[MIPS_TEMP1_REGNUM]); } fprintf (file," #END PROLOGUE\n");}/* Do any necessary cleanup after a function to restore stack, frame, and regs. */voidfunction_epilogue (file, size) FILE *file; int size;{ extern FILE *asm_out_data_file, *asm_out_file; extern char call_used_regs[]; extern char *reg_numchar[]; extern char *current_function_name; extern int frame_pointer_needed; int regno; int push_loc = stack_args_preallocated; int tsize = current_function_total_framesize; int num_regs = current_function_saved_reg_size; char **reg_name_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar; char *sp_str = reg_name_ptr[STACK_POINTER_REGNUM]; char *t1_str = reg_name_ptr[MIPS_TEMP1_REGNUM]; char *base_str; fprintf (file," #EPILOGUE\n"); if (tsize > 32767) fprintf (file, "\tli\t%s,%d\n", t1_str, tsize); if (frame_pointer_needed) { char *fp_str = reg_name_ptr[FRAME_POINTER_REGNUM]; if (tsize > 32767) fprintf (file,"\tsubu\t%s,%s,%s\t# sp not trusted here\n", sp_str, fp_str, t1_str); else fprintf (file,"\tsubu\t%s,%s,%d\t# sp not trusted here\n", sp_str, fp_str, tsize); } if (push_loc > 32767 && num_regs > 0) { if ((tsize - (push_loc + num_regs)) <= 32767) { base_str = t1_str; push_loc = tsize - push_loc; } else { base_str = reg_name_ptr[MIPS_TEMP2_REGNUM]; fprintf (file, "\tli\t%s,%d\n", base_str, push_loc); push_loc = 0; } } else base_str = sp_str; for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) if (MUST_SAVE_REGISTER (regno)) { fprintf (file,"\tlw\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc, base_str); push_loc += 4; } push_loc = AL_ADJUST_ALIGN (push_loc); for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += 2) if (regs_ever_live[regno] && !call_used_regs[regno]) { fprintf (file, "\tl.d\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc, base_str); push_loc += 8; } if (tsize > 32767) fprintf (file, "\taddu\t%s,%s,%s\n", sp_str, sp_str, t1_str); else if (tsize > 0) fprintf (file, "\taddu\t%s,%s,%d\n", sp_str, sp_str, tsize); fprintf (file,"\tj\t%s\n", reg_name_ptr[31]); fprintf (file," #END EPILOGUE\n"); fprintf (file,"\t.end\t%s\n", current_function_name); /* Reset state info for each function. */ stack_args_pushed = 0; stack_args_preallocated = 0; inside_function = 0; sp_fp_difference = (char *)0; number_functions_processed++; /* Restore the output file if optimizing the GP (optimizing the GP causes the text to be diverted to a tempfile, so that data decls come before references to the data). */ if (TARGET_GP_OPT) asm_out_file = asm_out_data_file;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -