📄 dsp16xx.c
字号:
cc_status.value2 = SET_DEST (exp); break; default: CC_STATUS_INIT; } 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; }}intdsp16xx_makes_calls (){ rtx insn; for (insn = get_insns (); insn; insn = next_insn (insn)) if (GET_CODE (insn) == CALL_INSN) return (1); return 0;}longcompute_frame_size (size) int size;{ long total_size; long var_size; long args_size; long extra_size; long reg_size; /* This value is needed to compute reg_size. */ current_frame_info.function_makes_calls = !leaf_function_p (); reg_size = 0; extra_size = 0; var_size = size; args_size = current_function_outgoing_args_size; reg_size = reg_save_size (); total_size = var_size + args_size + extra_size + reg_size; /* Save other computed information. */ current_frame_info.total_size = total_size; current_frame_info.var_size = var_size; current_frame_info.args_size = args_size; current_frame_info.extra_size = extra_size; current_frame_info.reg_size = reg_size; current_frame_info.initialized = reload_completed; current_frame_info.reg_size = reg_size / UNITS_PER_WORD; if (reg_size) { unsigned long offset = args_size + var_size + reg_size; current_frame_info.sp_save_offset = offset; current_frame_info.fp_save_offset = offset - total_size; } return total_size;}intdsp16xx_call_saved_register (regno) int regno;{#if 0 if (regno == REG_PR && current_frame_info.function_makes_calls) return 1;#endif return (regs_ever_live[regno] && !call_used_regs[regno] && !IS_YBASE_REGISTER_WINDOW(regno));}intybase_regs_ever_used (){ int regno; int live = 0; for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++) if (regs_ever_live[regno]) { live = 1; break; } return live;}static void dsp16xx_output_function_prologue (file, size) FILE *file; HOST_WIDE_INT size;{ int regno; long total_size; fp = reg_names[FRAME_POINTER_REGNUM]; sp = reg_names[STACK_POINTER_REGNUM]; rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */ a1h = reg_names[REG_A1]; total_size = compute_frame_size (size); fprintf (file, "\t/* FUNCTION PROLOGUE: */\n"); fprintf (file, "\t/* total=%ld, vars= %ld, regs= %d, args=%d, extra= %ld */\n", current_frame_info.total_size, current_frame_info.var_size, current_frame_info.reg_size, current_function_outgoing_args_size, current_frame_info.extra_size); fprintf (file, "\t/* fp save offset= %ld, sp save_offset= %ld */\n\n", current_frame_info.fp_save_offset, current_frame_info.sp_save_offset); /* Set up the 'ybase' register window. */ if (ybase_regs_ever_used()) { fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]); if (TARGET_YBASE_HIGH) fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h); else fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h); fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h); } if (current_frame_info.var_size) { if (current_frame_info.var_size == 1) fprintf (file, "\t*%s++\n", sp); else { if (SMALL_INTVAL(current_frame_info.var_size) && ((current_frame_info.var_size & 0x8000) == 0)) fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.var_size, sp, reg_names[REG_J]); else fatal_error ("stack size > 32k"); } } /* Save any registers this function uses, unless they are used in a call, in which case we don't need to. */ for(regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno) if (dsp16xx_call_saved_register (regno)) { fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[regno]); } /* For debugging purposes, we want the return address to be at a predictable location. */ if (current_frame_info.function_makes_calls) fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[RETURN_ADDRESS_REGNUM]); if (current_frame_info.args_size) { if (current_frame_info.args_size == 1) fprintf (file, "\t*%s++\n", sp); else error ("stack size > 32k"); } if (frame_pointer_needed) { fprintf (file, "\t%s=%s\n", a1h, sp); fprintf (file, "\t%s=%s\n", fp, a1h); /* Establish new base frame */ fprintf (file, "\t%s=%ld\n", reg_names[REG_J], -total_size); fprintf (file, "\t*%s++%s\n", fp, reg_names[REG_J]); } fprintf (file, "\t/* END FUNCTION PROLOGUE: */\n\n");}voidinit_emulation_routines (){ dsp16xx_addhf3_libcall = (rtx) 0; dsp16xx_subhf3_libcall = (rtx) 0; dsp16xx_mulhf3_libcall = (rtx) 0; dsp16xx_divhf3_libcall = (rtx) 0; dsp16xx_cmphf3_libcall = (rtx) 0; dsp16xx_fixhfhi2_libcall = (rtx) 0; dsp16xx_floathihf2_libcall = (rtx) 0; dsp16xx_neghf2_libcall = (rtx) 0; dsp16xx_mulhi3_libcall = (rtx) 0; dsp16xx_udivqi3_libcall = (rtx) 0; dsp16xx_udivhi3_libcall = (rtx) 0; dsp16xx_divqi3_libcall = (rtx) 0; dsp16xx_divhi3_libcall = (rtx) 0; dsp16xx_modqi3_libcall = (rtx) 0; dsp16xx_modhi3_libcall = (rtx) 0; dsp16xx_umodqi3_libcall = (rtx) 0; dsp16xx_umodhi3_libcall = (rtx) 0; dsp16xx_ashrhi3_libcall = (rtx) 0; dsp16xx_ashlhi3_libcall = (rtx) 0; dsp16xx_ucmphi2_libcall = (rtx) 0; dsp16xx_lshrhi3_libcall = (rtx) 0;}static voiddsp16xx_output_function_epilogue (file, size) FILE *file; HOST_WIDE_INT size ATTRIBUTE_UNUSED;{ int regno; fp = reg_names[FRAME_POINTER_REGNUM]; sp = reg_names[STACK_POINTER_REGNUM]; rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */ a1h = reg_names[REG_A1]; fprintf (file, "\n\t/* FUNCTION EPILOGUE: */\n"); if (current_frame_info.args_size) { if (current_frame_info.args_size == 1) fprintf (file, "\t*%s--\n", sp); else { fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]); } } if (ybase_regs_ever_used()) { fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]); if (TARGET_YBASE_HIGH) fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h); else fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h); fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h); } if (current_frame_info.function_makes_calls) fprintf (file, "\t%s=pop(*%s)\n", reg_names[RETURN_ADDRESS_REGNUM], sp); for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno) if (dsp16xx_call_saved_register(regno)) { fprintf (file, "\t%s=pop(*%s)\n", reg_names[regno], sp); } if (current_frame_info.var_size) { if (current_frame_info.var_size == 1) fprintf (file, "\t*%s--\n", sp); else { fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]); } } fprintf (file, "\treturn\n"); /* Reset the frame info for the next function. */ current_frame_info = zero_frame_info; init_emulation_routines ();}/* Emit insns to move operands[1] into operands[0]. Return 1 if we have written out everything that needs to be done to do the move. Otherwise, return 0 and the caller will emit the move normally. */intemit_move_sequence (operands, mode) rtx *operands; enum machine_mode mode;{ register rtx operand0 = operands[0]; register rtx operand1 = operands[1]; /* We can only store registers to memory. */ if (GET_CODE (operand0) == MEM && GET_CODE (operand1) != REG) operands[1] = force_reg (mode, operand1); return 0;}voiddouble_reg_from_memory (operands) rtx operands[];{ rtx xoperands[4]; if (GET_CODE(XEXP(operands[1],0)) == POST_INC) { output_asm_insn ("%u0=%1", operands); output_asm_insn ("%w0=%1", operands); } else if (GET_CODE(XEXP(operands[1],0)) == POST_DEC) { xoperands[1] = XEXP (XEXP (operands[1], 0), 0); xoperands[0] = operands[0]; /* We can't use j anymore since the compiler can allocate it. *//* output_asm_insn ("j=-3\n\t%u0=*%1++\n\t%w0=*%1++j", xoperands); */ output_asm_insn ("%u0=*%1++\n\t%w0=*%1--\n\t*%1--\n\t*%1--", xoperands); } else if (GET_CODE(XEXP(operands[1],0)) == PLUS) { rtx addr; int offset = 0; output_asm_insn ("%u0=%1", operands); /* In order to print out the least significant word we must use 'offset + 1'. */ addr = XEXP (operands[1], 0); if (GET_CODE (XEXP(addr,0)) == CONST_INT) offset = INTVAL(XEXP(addr,0)) + 1; else if (GET_CODE (XEXP(addr,1)) == CONST_INT) offset = INTVAL(XEXP(addr,1)) + 1; fprintf (asm_out_file, "\t%s=*(%d)\n", reg_names[REGNO(operands[0]) + 1], offset + 31); } else { xoperands[1] = XEXP(operands[1],0); xoperands[0] = operands[0]; output_asm_insn ("%u0=*%1++\n\t%w0=*%1--", xoperands); }}voiddouble_reg_to_memory (operands) rtx operands[];{ rtx xoperands[4]; if (GET_CODE(XEXP(operands[0],0)) == POST_INC) { output_asm_insn ("%0=%u1", operands); output_asm_insn ("%0=%w1", operands); } else if (GET_CODE(XEXP(operands[0],0)) == POST_DEC) { xoperands[0] = XEXP (XEXP (operands[0], 0), 0); xoperands[1] = operands[1]; /* We can't use j anymore since the compiler can allocate it. *//* output_asm_insn ("j=-3\n\t*%0++=%u1\n\t*%0++j=%w1", xoperands); */ output_asm_insn ("*%0++=%u1\n\t*%0--=%w1\n\t*%0--\n\t*%0--", xoperands); } else if (GET_CODE(XEXP(operands[0],0)) == PLUS) { rtx addr; int offset = 0; output_asm_insn ("%0=%u1", operands); /* In order to print out the least significant word we must use 'offset + 1'. */ addr = XEXP (operands[0], 0); if (GET_CODE (XEXP(addr,0)) == CONST_INT) offset = INTVAL(XEXP(addr,0)) + 1; else if (GET_CODE (XEXP(addr,1)) == CONST_INT) offset = INTVAL(XEXP(addr,1)) + 1; else fatal_error ("invalid addressing mode"); fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]); } else { xoperands[0] = XEXP(operands[0],0); xoperands[1] = operands[1]; output_asm_insn ("*%0++=%u1\n\t*%0--=%w1", xoperands); }}voidoverride_options (){ if (chip_name == (char *) 0) chip_name = DEFAULT_CHIP_NAME; if (text_seg_name == (char *) 0) text_seg_name = DEFAULT_TEXT_SEG_NAME; if (data_seg_name == (char *) 0) data_seg_name = DEFAULT_DATA_SEG_NAME; if (bss_seg_name == (char *) 0) bss_seg_name = DEFAULT_BSS_SEG_NAME; if (const_seg_name == (char *) 0) const_seg_name = DEFAULT_CONST_SEG_NAME; save_chip_name = xstrdup (chip_name); rsect_text = concat (".rsect \"", text_seg_name, "\"", NULL); rsect_data = concat (".rsect \"", data_seg_name, "\"", NULL); rsect_bss = concat (".rsect \"", bss_seg_name, "\"", NULL); rsect_const = concat (".rsect \"", const_seg_name, "\"", NULL);}intnext_cc_user_unsigned (insn) rtx insn;{ switch (next_cc_user_code (insn)) { case GTU: case GEU: case LTU: case LEU: return 1; default: return 0; }}enum rtx_codenext_cc_user_code (insn) rtx insn;{ /* If no insn could be found we assume that the jump has been deleted and the compare will be deleted later. */ if (!(insn = next_cc0_user (insn))) return (enum rtx_code) 0; else if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == SET && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE) return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)); else if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode)) return GET_CODE (SET_SRC (PATTERN (insn))); else abort ();}voidprint_operand(file, op, letter) FILE *file; rtx op; int letter;{ enum rtx_code code; code = GET_CODE(op); switch (letter) { case 'I': code = reverse_condition (code); /* Fallthrough */ case 'C': if (code == EQ) { fputs ("eq", file); return; } else if (code == NE) { fputs ("ne", file); return; } else if (code == GT || code == GTU) { fputs ("gt", file); return; } else if (code == LT || code == LTU) { fputs ("mi", file); return; } else if (code == GE || code == GEU) { fputs ("pl", file); return; } else if (code == LE || code == LEU) { fputs ("le", file); return; } else abort (); break; default: break; } if (code == REG) { /* Print the low half of a 32-bit register pair. */ if (letter == 'w') fprintf (file, "%s", reg_names[REGNO (op) + 1]); else if (letter == 'u' || !letter) fprintf (file, "%s", reg_names[REGNO (op)]); else if (letter == 'b') fprintf (file, "%sh", reg_names[REGNO (op)]); else if (letter == 'm') fprintf (file, "%s", himode_reg_name[REGNO (op)]); else output_operand_lossage ("bad register extension code"); } else if (code == MEM) output_address (XEXP(op,0)); else if (code == CONST_INT) { HOST_WIDE_INT val = INTVAL (op); if (letter == 'H') fprintf (file, HOST_WIDE_INT_PRINT_HEX, val & 0xffff); else if (letter == 'h') fprintf (file, HOST_WIDE_INT_PRINT_DEC, val); else if (letter == 'U') fprintf (file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff); else output_addr_const(file, op); } else if (code == CONST_DOUBLE && GET_MODE(op) != DImode) { long l; REAL_VALUE_TYPE r; REAL_VALUE_FROM_CONST_DOUBLE (r, op); REAL_VALUE_TO_TARGET_SINGLE (r, l); fprintf (file, "0x%lx", l); } else if (code == CONST) { rtx addr = XEXP (op, 0); if (GET_CODE (addr) != PLUS) { output_addr_const(file, op); return; } if ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF || GET_CODE (XEXP (addr, 0)) == LABEL_REF) && (GET_CODE (XEXP (addr, 1)) == CONST_INT)) { int n = INTVAL (XEXP(addr, 1)); output_addr_const (file, XEXP (addr, 0)); if (n >= 0) fprintf (file, "+"); n = (int) (short) n; fprintf (file, "%d", n); } else if ((GET_CODE (XEXP (addr, 1)) == SYMBOL_REF || GET_CODE (XEXP (addr, 1)) == LABEL_REF) && (GET_CODE (XEXP (addr, 0)) == CONST_INT)) { int n = INTVAL (XEXP(addr, 0)); output_addr_const (file, XEXP (addr, 1)); if (n >= 0) fprintf (file, "+"); n = (int) (short) n; fprintf (file, "%d", n); } else output_addr_const(file, op); } else output_addr_const (file, op);}voidprint_operand_address(file, addr) FILE *file; rtx addr;{ rtx base; int offset = 0;; switch (GET_CODE (addr)) { case REG: fprintf (file, "*%s", reg_names[REGNO (addr)]); break; case POST_DEC: fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]); break; case POST_INC: fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]); break; case PLUS: if (GET_CODE (XEXP(addr,0)) == CONST_INT) offset = INTVAL(XEXP(addr,0)), base = XEXP(addr,1); else if (GET_CODE (XEXP(addr,1)) == CONST_INT) offset = INTVAL(XEXP(addr,1)), base = XEXP(addr,0); else abort(); if (GET_CODE (base) == REG && REGNO(base) == STACK_POINTER_REGNUM) { if (offset >= -31 && offset <= 0) offset = 31 + offset; else fatal_error ("invalid offset in ybase addressing"); } else fatal_error ("invalid register in ybase addressing"); fprintf (file, "*(%d)", offset); break; default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -