📄 a29k.c
字号:
return; case 'B': if (GET_CODE (x) == GE) fprintf (file, "t"); else fprintf (file, "f"); return; case 'J': /* It so happens that the RTX names for the conditions are the same as the 29k's insns except for "ne", which requires "neq". */ fprintf (file, GET_RTX_NAME (GET_CODE (x))); if (GET_CODE (x) == NE) fprintf (file, "q"); return; case 'e': if (optimize && flag_delayed_branch && a29k_last_prologue_insn == 0 && epilogue_operand (x, VOIDmode) && dbr_sequence_length () == 0) { /* We need to output the label number of the last label in the function, which is not necessarily X since there might be a USE insn in between. First go forward to the last insn, then back up to a label. */ while (NEXT_INSN (x) != 0) x = NEXT_INSN (x); while (GET_CODE (x) != CODE_LABEL) x = PREV_INSN (x); ASM_GENERATE_INTERNAL_LABEL (buf, "LX", CODE_LABEL_NUMBER (x)); assemble_name (file, buf); } else output_asm_label (x); return; case 'E': if (dbr_sequence_length ()) ; else if (a29k_last_prologue_insn) { fprintf (file, "\n\t%s", a29k_last_prologue_insn); a29k_last_prologue_insn = 0; } else if (optimize && flag_delayed_branch && epilogue_operand (x, VOIDmode)) { fprintf (file, "\n\t%s", a29k_first_epilogue_insn); a29k_first_epilogue_insn_used = 1; } else fprintf (file, "\n\tnop"); return; case 'F': output_addr_const (file, x); if (dbr_sequence_length () == 0) { /* If this doesn't have its delay slot filled, see if we need to put the last insn of the prolog in it. If not, see if this is a recursive call. If so, we can put the first insn of its prolog in the delay slot. Otherwise, write a nop. */ if (a29k_last_prologue_insn) { fprintf (file, "\n\t%s", a29k_last_prologue_insn); a29k_last_prologue_insn = 0; } else if (GET_CODE (x) == SYMBOL_REF && ! strcmp (XSTR (x, 0), current_function_name)) fprintf (file, "+4\n\t%s,%d", a29k_regstack_size >= 64 ? "const gr121" : "sub gr1,gr1", a29k_regstack_size * 4); else fprintf (file, "\n\tnop"); } return; case 'L': if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode) { union real_extract u; bcopy ((char *) &CONST_DOUBLE_LOW (x), (char *) &u, sizeof u); fprintf (file, "$double1(%.20e)", u.d); } else if (GET_CODE (x) == REG) fprintf (file, "%s", reg_names[REGNO (x) + 1]); else output_operand_lossage ("invalid %%L value"); return; case 'O': if (GET_CODE (x) != REG) output_operand_lossage ("invalid %%O value"); fprintf (file, "%s", reg_names[REGNO (x) + 2]); return; case 'P': if (GET_CODE (x) != REG) output_operand_lossage ("invalid %%P value"); fprintf (file, "%s", reg_names[REGNO (x) + 3]); return; case 'S': fprintf (file, "%d", (GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD)-1); return; case 'V': if (GET_CODE (x) != PARALLEL) output_operand_lossage ("invalid %%V value"); fprintf (file, "%d", XVECLEN (x, 0) - 2); return; case '#': if (dbr_sequence_length () == 0) { if (a29k_last_prologue_insn) { fprintf (file, "\n\t%s", a29k_last_prologue_insn); a29k_last_prologue_insn = 0; } else fprintf (file, "\n\tnop"); } return; case '*': fprintf (file, "%s", reg_names [R_TPC]); return; } if (GET_CODE (x) == REG) fprintf (file, "%s", reg_names [REGNO (x)]); else if (GET_CODE (x) == MEM) output_address (XEXP (x, 0)); else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == SUBREG && GET_CODE (SUBREG_REG (XEXP (x, 0))) == CONST_DOUBLE) { union real_extract u; if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode) fprintf (file, "$float"); else fprintf (file, "$double%d", SUBREG_WORD (XEXP (x, 0))); bcopy ((char *) &CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), (char *) &u, sizeof u); fprintf (file, "(%.20e)", u.d); } else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) { union real_extract u; bcopy ((char *) &CONST_DOUBLE_LOW (x), (char *) &u, sizeof u); fprintf (file, "$%s(%.20e)", GET_MODE (x) == SFmode ? "float" : "double0", u.d); } else output_addr_const (file, x);}/* This page contains routines to output function prolog and epilog code. *//* Compute the size of the register stack, and determine if there are any call instructions. */static voidcompute_regstack_size (){ int i; rtx insn; /* See if we make any calls. We need to set lr1 if so. */ a29k_makes_calls = 0; for (insn = get_insns (); insn; insn = next_insn (insn)) if (GET_CODE (insn) == CALL_INSN || (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN)) { a29k_makes_calls = 1; break; } /* Find the highest local register used. */ for (i = R_LR (127); i >= R_LR (0); i--) if (regs_ever_live[i]) break; a29k_regstack_size = i - (R_LR (0) - 1); /* If calling routines, ensure we count lr0 & lr1. */ if (a29k_makes_calls && a29k_regstack_size < 2) a29k_regstack_size = 2; /* Count frame pointer and align to 8 byte boundary (even number of registers). */ a29k_regstack_size += frame_pointer_needed; if (a29k_regstack_size & 1) a29k_regstack_size++;}/* Sets register names for incoming arguments and frame pointer. This can't be computed until after register allocation. */voida29k_compute_reg_names (){ int i; compute_regstack_size (); /* Set the names and numbers of the frame pointer and incoming argument registers. */ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) a29k_debug_reg_map[i] = i; reg_names[FRAME_POINTER_REGNUM] = reg_names[R_LR (a29k_regstack_size - 1)]; a29k_debug_reg_map[FRAME_POINTER_REGNUM] = R_LR (a29k_regstack_size - 1); for (i = 0; i < 16; i++) { reg_names[R_AR (i)] = reg_names[R_LR (a29k_regstack_size + i + 2)]; a29k_debug_reg_map[R_AR (i)] = R_LR (a29k_regstack_size + i + 2); } /* If using kernel register map, swap numbers for kernel and user registers. */ if (TARGET_KERNEL_REGISTERS) for (i = 0; i < 32; i++) { int tem = a29k_debug_reg_map[i]; a29k_debug_reg_map[i] = a29k_debug_reg_map[R_KR (i)]; a29k_debug_reg_map[R_KR (i)] = tem; }}/* Output function prolog code to file FILE. Memory stack size is SIZE. */voidoutput_prolog (file, size) FILE *file; int size;{ int i; int arg_count = 0; rtx insn; unsigned int tag_word; /* See how many incoming arguments we have in registers. */ for (i = R_AR (0); i < R_AR (16); i++) if (! fixed_regs[i]) arg_count++; /* The argument count includes the caller's lr0 and lr1. */ arg_count += 2; /* Compute memory stack size. Add in number of bytes that the we should push and pretend the caller did and the size of outgoing arguments. Then round to a doubleword boundary. */ size += (current_function_pretend_args_size + current_function_outgoing_args_size); size = (size + 7) & ~7; /* Write header words. See if one or two word form. */ tag_word = (frame_pointer_needed ? 0x400000 : 0) + (arg_count << 16); if (size / 8 > 0xff) fprintf (file, "\t.word %d, 0x%0x\n", (size / 8) << 2, 0x800000 + tag_word); else fprintf (file, "\t.word 0x%0x\n", tag_word + ((size / 8) << 3)); /* Define the function name. */ assemble_name (file, a29k_function_name); fprintf (file, ":\n"); /* Push the register stack by the proper amount. There are two possible ways to do this. */ if (a29k_regstack_size >= 256/4) fprintf (file, "\tconst %s,%d\n\tsub gr1,gr1,%s\n", reg_names[R_TAV], a29k_regstack_size * 4, reg_names[R_TAV]); else if (a29k_regstack_size) fprintf (file, "\tsub gr1,gr1,%d\n", a29k_regstack_size * 4); /* Test that the registers are available. */ if (a29k_regstack_size) fprintf (file, "\tasgeu V_%sSPILL,gr1,%s\n", TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RAB]); /* Set up frame pointer, if one is needed. */ if (frame_pointer_needed) fprintf (file, "\tsll %s,%s,0\n", reg_names[FRAME_POINTER_REGNUM], reg_names[R_MSP]); /* Make room for any frame space. There are three ways to do this. */ if (size >= 256) { fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size); if (size >= 65536) fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size); if (TARGET_STACK_CHECK) fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]); fprintf (file, "\tsub %s,%s,%s\n", reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]); } else if (size) { if (TARGET_STACK_CHECK) fprintf (file, "\tcall %s,__msp_check\n", reg_names[R_TPC]); fprintf (file, "\tsub %s,%s,%d\n", reg_names[R_MSP], reg_names[R_MSP], size); } /* If this routine will make calls, set lr1. If we see an insn that can use a delay slot before a call or jump, save this insn for that slot (this condition is equivalent to seeing if we have an insn that needs delay slots before an insn that has a filled delay slot). */ a29k_last_prologue_insn = 0; if (a29k_makes_calls) { i = (a29k_regstack_size + arg_count) * 4; if (i >= 256) fprintf (file, "\tconst %s,%d\n\tadd lr1,gr1,%s\n", reg_names[R_TAV], i, reg_names[R_TAV]); else { if (optimize && flag_delayed_branch) for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { if (GET_CODE (insn) == CODE_LABEL || (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)) break; if (GET_CODE (insn) == NOTE || (GET_CODE (insn) == INSN && (GET_CODE (PATTERN (insn)) == USE || GET_CODE (PATTERN (insn)) == CLOBBER))) continue; if (num_delay_slots (insn) > 0) { a29k_last_prologue_insn = (char *) oballoc (100); sprintf (a29k_last_prologue_insn, "add lr1,gr1,%d", i); break; } } if (a29k_last_prologue_insn == 0) fprintf (file, "\tadd lr1,gr1,%d\n", i); } } /* Compute the first insn of the epilogue. */ a29k_first_epilogue_insn_used = 0; if (size == 0 && a29k_regstack_size == 0 && ! frame_pointer_needed) a29k_first_epilogue_insn = 0; else a29k_first_epilogue_insn = (char *) oballoc (100); if (frame_pointer_needed) sprintf (a29k_first_epilogue_insn, "sll %s,%s,0", reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]); else if (a29k_regstack_size) { if (a29k_regstack_size >= 256 / 4) sprintf (a29k_first_epilogue_insn, "const %s,%d", reg_names[R_TAV], a29k_regstack_size * 4); else sprintf (a29k_first_epilogue_insn, "add gr1,gr1,%d", a29k_regstack_size * 4); } else if (size) { if (size >= 256) sprintf (a29k_first_epilogue_insn, "const %s,%d", reg_names[R_TAV], size); else sprintf (a29k_first_epilogue_insn, "add %s,%s,%d", reg_names[R_MSP], reg_names[R_MSP], size); }}/* Call this after writing what might be the first instruction of the epilogue. If that first insn was used in a delay slot, an intermediate label is written. */static voidcheck_epilogue_internal_label (file) FILE *file;{ rtx insn; if (! a29k_first_epilogue_insn_used) return; for (insn = get_last_insn (); GET_CODE (insn) != CODE_LABEL; insn = PREV_INSN (insn)) ; ASM_OUTPUT_INTERNAL_LABEL (file, "LX", CODE_LABEL_NUMBER (insn)); a29k_first_epilogue_insn_used = 0;}/* Output the epilog of the last procedure to file FILE. SIZE is the memory stack size. The register stack size is in the variable A29K_REGSTACK_SIZE. */voidoutput_epilog (file, size) FILE *file; int size;{ rtx insn; int locals_unavailable = 0; /* True until after first insn after gr1 update. */ /* If we hit a BARRIER before a real insn or CODE_LABEL, we don't need to do anything because we are never jumped to. */ insn = get_last_insn (); if (GET_CODE (insn) == NOTE) insn = prev_nonnote_insn (insn); if (insn && GET_CODE (insn) == BARRIER) return; /* If a frame pointer was needed we must restore the memory stack pointer before adjusting the register stack. */ if (frame_pointer_needed) { fprintf (file, "\tsll %s,%s,0\n", reg_names[R_MSP], reg_names[FRAME_POINTER_REGNUM]); check_epilogue_internal_label (file); } /* Restore the register stack. There are two ways to do this. */ if (a29k_regstack_size) { if (a29k_regstack_size >= 256/4) { fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], a29k_regstack_size * 4); check_epilogue_internal_label (file); fprintf (file, "\tadd gr1,gr1,%s\n", reg_names[R_TAV]); } else { fprintf (file, "\tadd gr1,gr1,%d\n", a29k_regstack_size * 4); check_epilogue_internal_label (file); } locals_unavailable = 1; } /* Restore the memory stack pointer if there is no frame pointer. Adjust the size to include any pretend arguments and pushed arguments and round to doubleword boundary. */ size += (current_function_pretend_args_size + current_function_outgoing_args_size); size = (size + 7) & ~7; if (size && ! frame_pointer_needed) { if (size >= 256) { fprintf (file, "\tconst %s,%d\n", reg_names[R_TAV], size); check_epilogue_internal_label (file); locals_unavailable = 0; if (size >= 65536) fprintf (file, "\tconsth %s,%d\n", reg_names[R_TAV], size); fprintf (file, "\tadd %s,%s,%s\n", reg_names[R_MSP], reg_names[R_MSP], reg_names[R_TAV]); } else { fprintf (file, "\tadd %s,%s,%d\n", reg_names[R_MSP], reg_names[R_MSP], size); check_epilogue_internal_label (file); locals_unavailable = 0; } } if (locals_unavailable) { /* If we have an insn for this delay slot, write it. */ if (current_function_epilogue_delay_list) final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), file, 1, -2, 1); else fprintf (file, "\tnop\n"); } fprintf (file, "\tjmpi lr0\n"); if (a29k_regstack_size) fprintf (file, "\tasleu V_%sFILL,lr1,%s\n", TARGET_KERNEL_REGISTERS ? "K" : "", reg_names[R_RFB]); else if (current_function_epilogue_delay_list) final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), file, 1, -2, 1); else fprintf (file, "\tnop\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -