--- gcc/config/i860.c 2018/04/24 17:54:45 1.1.1.2 +++ gcc/config/i860.c 2018/04/24 18:05:33 1.1.1.4 @@ -351,145 +351,6 @@ single_insn_src_p (op, mode) return 0; } } - -/* Nonzero only if this *really* is a single insn operand. */ -int -strict_single_insn_op_p (op, mode) - rtx op; - enum machine_mode mode; -{ - if (mode == VOIDmode) - mode = GET_MODE (op); - - switch (GET_CODE (op)) - { - case CC0: - return 1; - - case CONST_INT: - if (SMALL_INT (op)) - return 1; - /* We can put this set insn into delay slot, because this is one - insn; `orh'. */ - if ((INTVAL (op) & 0xffff) == 0) - return 1; - return 0; - - case SYMBOL_REF: - return 0; - - case REG: -#if 0 - /* This loses when moving an freg to a general reg. */ - return HARD_REGNO_NREGS (REGNO (op), mode) == 1; -#endif - return (mode != DFmode && mode != DImode); - - case MEM: - if (! CONSTANT_ADDRESS_P (XEXP (op, 0))) - return (mode != DFmode && mode != DImode); - return 0; - - /* We never need to negate or complement constants. */ - case NEG: - return (mode != DFmode); - case NOT: - case ZERO_EXTEND: - return 1; - - case PLUS: - case MINUS: - /* Detect cases that require multiple instructions. */ - if (CONSTANT_P (XEXP (op, 1)) - && !(GET_CODE (XEXP (op, 1)) == CONST_INT - && SMALL_INT (XEXP (op, 1)))) - return 0; - case EQ: - case NE: - case LT: - case GT: - case LE: - case GE: - case LTU: - case GTU: - case LEU: - case GEU: - return 1; - - case AND: - if (GET_CODE (XEXP (op, 1)) == NOT) - { - rtx arg = XEXP (XEXP (op, 1), 0); - if (CONSTANT_P (arg) - && !(GET_CODE (arg) == CONST_INT - && (SMALL_INT (arg) - || INTVAL (arg) & 0xffff == 0))) - return 0; - } - case IOR: - case XOR: - /* Both small and round numbers take one instruction; - others take two. */ - if (CONSTANT_P (XEXP (op, 1)) - && !(GET_CODE (XEXP (op, 1)) == CONST_INT - && (SMALL_INT (XEXP (op, 1)) - || INTVAL (XEXP (op, 1)) & 0xffff == 0))) - return 0; - - case LSHIFT: - case ASHIFT: - case ASHIFTRT: - case LSHIFTRT: - return 1; - - case SUBREG: - if (SUBREG_WORD (op) != 0) - return 0; - return strict_single_insn_op_p (SUBREG_REG (op), mode); - - case SIGN_EXTEND: - if (GET_CODE (XEXP (op, 0)) == MEM - && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0))) - return 1; - return 0; - - /* Not doing floating point, since they probably - take longer than the branch slot they might fill. */ - case FLOAT_EXTEND: - case FLOAT_TRUNCATE: - case FLOAT: - case FIX: - case UNSIGNED_FLOAT: - case UNSIGNED_FIX: - return 0; - - default: - return 0; - } -} - -/* Return truth value of whether OP is a relational operator. */ -int -relop (op, mode) - rtx op; - enum machine_mode mode; -{ - switch (GET_CODE (op)) - { - case EQ: - case NE: - case GT: - case GE: - case LT: - case LE: - case GTU: - case GEU: - case LTU: - case LEU: - return 1; - } - return 0; -} /* Return non-zero only if OP is a register of mode MODE, or const0_rtx. */ @@ -669,12 +530,14 @@ singlemove_string (operands) } if (GET_CODE (operands[1]) == CONST_INT) { + if (operands[1] == const0_rtx) + return "mov %?r0,%0"; if((INTVAL (operands[1]) & 0xffff0000) == 0) return "or %L1,%?r0,%0"; + if((INTVAL (operands[1]) & 0xffff8000) == 0xffff8000) + return "adds %1,%?r0,%0"; if((INTVAL (operands[1]) & 0x0000ffff) == 0) return "orh %H1,%?r0,%0"; - if (operands[1] == const0_rtx) - return "mov %?r0,%0"; } return "mov %1,%0"; } @@ -1196,7 +1059,7 @@ output_size_for_block_move (size, reg, a #if 1 cc_status.flags &= ~ CC_KNOW_HI_R31; - output_asm_insn ("mov %1,%0", xoperands); + output_asm_insn (singlemove_string (xoperands), xoperands); #else if (GET_CODE (size) == REG) output_asm_insn ("sub %2,%1,%0", xoperands); @@ -1621,7 +1484,7 @@ sfmode_constant_to_ulong (x) abort (); #if TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT -# error IEEE emulation needed + error IEEE emulation needed #endif REAL_VALUE_FROM_CONST_DOUBLE (d, x); u2.f = d; @@ -2037,15 +1900,49 @@ function_prologue (asm_file, local_bytes instruction, so what the hell. */ +/* This corresponds to a version 4 TDESC structure. Lower numbered + versions successively omit the last word of the structure. We + don't try to handle version 5 here. */ + +typedef struct TDESC_flags { + int version:4; + int reg_packing:1; + int callable_block:1; + int reserved:4; + int fregs:6; /* fp regs 2-7 */ + int iregs:16; /* regs 0-15 */ +} TDESC_flags; + +typedef struct TDESC { + TDESC_flags flags; + int integer_reg_offset; /* same as must_preserve_bytes */ + int floating_point_reg_offset; + unsigned int positive_frame_size; /* same as frame_upper_bytes */ + unsigned int negative_frame_size; /* same as frame_lower_bytes */ +} TDESC; + void function_epilogue (asm_file, local_bytes) register FILE *asm_file; register unsigned local_bytes; { register unsigned frame_upper_bytes; + register unsigned frame_lower_bytes; register unsigned preserved_reg_bytes = 0; register unsigned i; register unsigned restored_so_far = 0; + register unsigned int_restored; + register unsigned mask; + unsigned intflags=0; + register TDESC_flags *flags = (TDESC_flags *) &intflags; + + flags->version = 4; + flags->reg_packing = 1; + flags->iregs = 8; /* old fp always gets saved */ + + /* Round-up the frame_lower_bytes so that it's a multiple of 16. */ + + frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT; /* Count the number of registers that were preserved in the prologue. Ignore r0. It is never preserved. */ @@ -2069,17 +1966,31 @@ function_epilogue (asm_file, local_bytes /* Restore all of the "preserved" registers that need restoring. */ - for (i = 1; i < 32; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) + mask = 2; + + for (i = 1; i < 32; i++, mask<<=1) + if (regs_ever_live[i] && ! call_used_regs[i]) { fprintf (asm_file, "\tld.l %d(%sfp),%s%s\n", must_preserve_bytes + (4 * restored_so_far++), i860_reg_prefix, i860_reg_prefix, reg_names[i]); + if (i > 3 && i < 16) + flags->iregs |= mask; + } + + int_restored = restored_so_far; + mask = 1; - for (i = 32; i < 64; i++) - if (regs_ever_live[i] && ! call_used_regs[i]) + for (i = 32; i < 64; i++) { + if (regs_ever_live[i] && ! call_used_regs[i]) { fprintf (asm_file, "\tfld.l %d(%sfp),%s%s\n", must_preserve_bytes + (4 * restored_so_far++), i860_reg_prefix, i860_reg_prefix, reg_names[i]); + if (i > 33 & i < 40) + flags->fregs |= mask; + } + if (i > 33 && i < 40) + mask<<=1; + } /* Get the value we plan to use to restore the stack pointer into r31. */ @@ -2088,9 +1999,11 @@ function_epilogue (asm_file, local_bytes /* Restore the return address and the old frame pointer. */ - if (must_preserve_r1) + if (must_preserve_r1) { fprintf (asm_file, "\tld.l 4(%sfp),%sr1\n", i860_reg_prefix, i860_reg_prefix); + flags->iregs |= 2; + } fprintf (asm_file, "\tld.l 0(%sfp),%sfp\n", i860_reg_prefix, i860_reg_prefix); @@ -2099,4 +2012,37 @@ function_epilogue (asm_file, local_bytes fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n", i860_reg_prefix, i860_reg_prefix, i860_reg_prefix); + +#ifdef OUTPUT_TDESC /* Output an ABI-compliant TDESC entry */ + if (! frame_lower_bytes) { + flags->version--; + if (! frame_upper_bytes) { + flags->version--; + if (restored_so_far == int_restored) /* No FP saves */ + flags->version--; + } + } + assemble_name(asm_file,current_function_original_name); + fputs(".TDESC:\n", asm_file); + fprintf(asm_file, "%s 0x%0x\n", ASM_LONG, intflags); + fprintf(asm_file, "%s %d\n", ASM_LONG, + int_restored ? must_preserve_bytes : 0); + if (flags->version > 1) { + fprintf(asm_file, "%s %d\n", ASM_LONG, + (restored_so_far == int_restored) ? 0 : must_preserve_bytes + + (4 * int_restored)); + if (flags->version > 2) { + fprintf(asm_file, "%s %d\n", ASM_LONG, frame_upper_bytes); + if (flags->version > 3) + fprintf(asm_file, "%s %d\n", ASM_LONG, frame_lower_bytes); + } + } + tdesc_section(); + fprintf(asm_file, "%s ", ASM_LONG); + assemble_name(asm_file, current_function_original_name); + fprintf(asm_file, "\n%s ", ASM_LONG); + assemble_name(asm_file, current_function_original_name); + fputs(".TDESC\n", asm_file); + text_section(); +#endif }