diff options
Diffstat (limited to 'gcc/config/sparc')
-rw-r--r-- | gcc/config/sparc/sparc.c | 68 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.h | 17 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 106 |
3 files changed, 122 insertions, 69 deletions
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 38fdad0..c2803ab 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -406,17 +406,6 @@ arith_operand (op, mode) || (GET_CODE (op) == CONST_INT && SMALL_INT (op))); } -/* Return truth value of whether OP can be used as an operand in a two - address arithmetic insn (such as set 123456,%o4) of mode MODE. */ - -int -arith32_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - return (register_operand (op, mode) || GET_CODE (op) == CONST_INT); -} - /* Return truth value of whether OP is a register or a CONST_DOUBLE. */ int @@ -634,10 +623,20 @@ legitimize_pic_address (orig, mode, reg, scratch) rtx temp_reg = ((reload_in_progress || reload_completed) ? reg : gen_reg_rtx (Pmode)); + /* Must put the SYMBOL_REF inside an UNSPEC here so that cse + won't get confused into thinking that these two instructions + are loading in the true address of the symbol. If in the + future a PIC rtx exists, that should be used instead. */ emit_insn (gen_rtx (SET, VOIDmode, temp_reg, - gen_rtx (HIGH, Pmode, orig))); + gen_rtx (HIGH, Pmode, + gen_rtx (UNSPEC, Pmode, + gen_rtvec (1, orig), + 0)))); emit_insn (gen_rtx (SET, VOIDmode, temp_reg, - gen_rtx (LO_SUM, Pmode, temp_reg, orig))); + gen_rtx (LO_SUM, Pmode, temp_reg, + gen_rtx (UNSPEC, Pmode, + gen_rtvec (1, orig), + 0)))); address = temp_reg; } else @@ -1548,7 +1547,7 @@ output_block_move (operands) here. The SUN assembler complains about labels in branch delay slots, so we - do this before outputing the load address, so that there will always + do this before outputting the load address, so that there will always be a harmless insn between the branch here and the next label emitted below. */ @@ -2048,7 +2047,7 @@ output_cbranch (op, label, reversed, annul, noop) enum machine_mode mode = GET_MODE (XEXP (op, 0)); static char labelno[] = " %lX"; - /* ??? FP branches can not be preceeded by another floating point insn. + /* ??? FP branches can not be preceded by another floating point insn. Because there is currently no concept of pre-delay slots, we can fix this only by always emitting a nop before a floating point branch. */ @@ -2284,22 +2283,29 @@ output_arc_profiler (arcno, insert_after) gen_rtx (PLUS, Pmode, profiler_label, gen_rtx (CONST_INT, VOIDmode, 4 * arcno))); register rtx profiler_reg = gen_reg_rtx (SImode); - register rtx temp = gen_reg_rtx (Pmode); - register rtx profiler_target = gen_rtx (MEM, SImode, - gen_rtx (LO_SUM, Pmode, temp, - profiler_target_addr)); - /* The insns are emitted from last to first after the insn insert_after. - Emit_insn_after is used because sometimes we want to put the - instrumentation code after the last insn of the function. */ - emit_insn_after (gen_rtx (SET, VOIDmode, profiler_target, profiler_reg), - insert_after); - emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg, - gen_rtx (PLUS, SImode, profiler_reg, const1_rtx)), - insert_after); - emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg, profiler_target), - insert_after); - emit_insn_after (gen_rtx (SET, VOIDmode, temp, - gen_rtx (HIGH, Pmode, profiler_target_addr)), + register rtx address_reg = gen_reg_rtx (Pmode); + rtx mem_ref; + + insert_after = emit_insn_after (gen_rtx (SET, VOIDmode, address_reg, + gen_rtx (HIGH, Pmode, + profiler_target_addr)), + insert_after); + + mem_ref = gen_rtx (MEM, SImode, gen_rtx (LO_SUM, Pmode, address_reg, + profiler_target_addr)); + insert_after = emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg, + mem_ref), + insert_after); + + insert_after = emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg, + gen_rtx (PLUS, SImode, profiler_reg, + const1_rtx)), + insert_after); + + /* This is the same rtx as above, but it is not legal to share this rtx. */ + mem_ref = gen_rtx (MEM, SImode, gen_rtx (LO_SUM, Pmode, address_reg, + profiler_target_addr)); + emit_insn_after (gen_rtx (SET, VOIDmode, mem_ref, profiler_reg), insert_after); } diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 61bd204..3451083 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -122,7 +122,7 @@ extern int target_flags; matters when cross-compiling. */ #define WORDS_BIG_ENDIAN 1 -/* number of bits in an addressible storage unit */ +/* number of bits in an addressable storage unit */ #define BITS_PER_UNIT 8 /* Width in bits of a "word", which is the contents of a machine register. @@ -171,9 +171,9 @@ extern int target_flags; && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) -/* Define this if move instructions will actually fail to work +/* Set this nonzero if move instructions will actually fail to work when given unaligned data. */ -#define STRICT_ALIGNMENT +#define STRICT_ALIGNMENT 1 /* Things that must be doubleword aligned cannot go in the text section, because the linker fails to align the text section enough! @@ -422,9 +422,9 @@ enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES }; /* This is the order in which to allocate registers normally. */ #define REG_ALLOC_ORDER \ -{ 8, 9, 10, 11, 12, 13, 2, 15, \ - 16, 17, 18, 19, 20, 21, 22, 23, \ - 24, 25, 26, 27, 28, 29, 3, 31, \ +{ 8, 9, 10, 11, 12, 13, 2, 3, \ + 15, 16, 17, 18, 19, 20, 21, 22, \ + 23, 24, 25, 26, 27, 28, 29, 31, \ 32, 33, 34, 35, 36, 37, 38, 39, \ 40, 41, 42, 43, 44, 45, 46, 47, \ 48, 49, 50, 51, 52, 53, 54, 55, \ @@ -571,7 +571,7 @@ extern char leaf_reg_backmap[]; #define REG_PARM_STACK_SPACE(DECL) (NPARM_REGS * UNITS_PER_WORD) /* Keep the stack pointer constant throughout the function. - This is both an optimization and a neccessity: longjmp + This is both an optimization and a necessity: longjmp doesn't behave itself when the stack pointer moves within the function! */ #define ACCUMULATE_OUTGOING_ARGS @@ -1187,6 +1187,9 @@ extern struct rtx_def *legitimize_pic_address (); between pointers and any other objects of this machine mode. */ #define Pmode SImode +/* Generate calls to memcpy, memcmp and memset. */ +#define TARGET_MEM_FUNCTIONS + /* Add any extra modes needed to represent the condition code. On the Sparc, we have a "no-overflow" mode which is used when an add or diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index f8f5495..20cfca8 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -56,6 +56,8 @@ (match_operand 2 "arith_double_operand" "")) (const_int 1) (const_int 3)) + (eq_attr "type" "multi") (const_int 2) + (eq_attr "type" "move,unary") (if_then_else (ior (match_operand 1 "arith_operand" "") (match_operand 1 "arith_double_operand" "")) @@ -451,8 +453,7 @@ (clobber (reg:CC 0))] "" "subcc %%g0,%1,%%g0\;addx %2,-1,%0" - [(set_attr "type" "unary") - (set_attr "length" "2")]) + [(set_attr "length" "2")]) ;; We can also do GEU and LTU directly, but these operate after a ;; compare. @@ -518,8 +519,7 @@ (plus:SI (match_operand:SI 1 "arith_operand" "%r") (match_operand:SI 2 "arith_operand" "rI"))))] "" - "addx %1,%2,%0" - [(set_attr "type" "binary")]) + "addx %1,%2,%0") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -536,8 +536,7 @@ (match_operand:SI 2 "arith_operand" "rI")) (ltu:SI (reg:CC 0) (const_int 0))))] "" - "subx %1,%2,%0" - [(set_attr "type" "binary")]) + "subx %1,%2,%0") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -545,8 +544,7 @@ (plus:SI (ltu:SI (reg:CC 0) (const_int 0)) (match_operand:SI 2 "arith_operand" "rI"))))] "" - "subx %1,%2,%0" - [(set_attr "type" "binary")]) + "subx %1,%2,%0") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -572,7 +570,8 @@ (match_operator:SI 1 "normal_comp_operator" [(reg 0) (const_int 0)]))] "" "* return output_scc_insn (operands, insn); " - [(set_attr "type" "multi")]) + [(set_attr "type" "multi") + (set_attr "length" "3")]) ;; These control RTL generation for conditional jump insns @@ -734,7 +733,7 @@ ;; subreg sets. ;; We cannot combine the similar 'r' and 'f' constraints, because it causes -;; problems with register allocation. Reload might try to put an interger +;; problems with register allocation. Reload might try to put an integer ;; in an fp register, or an fp number is an integer register. (define_insn "" @@ -751,8 +750,8 @@ st %r1,%0 st %r1,%0 st %r1,[%%fp-4]\;ld [%%fp-4],%0" - [(set_attr "type" "move,move,load,load,store,store,misc") - (set_attr "length" "*,1,*,*,*,*,2")]) + [(set_attr "type" "move,move,load,load,store,store,multi") + (set_attr "length" "*,1,*,*,*,*,*")]) ;; Special pic pattern, for loading the address of a label into a register. ;; It clobbers o7 because the call puts the return address (i.e. pc value) @@ -803,6 +802,16 @@ [(set_attr "type" "move") (set_attr "length" "2")]) +;; For PIC, symbol_refs are put inside unspec so that the optimizer won't +;; confuse them with real addresses. +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))] + "check_pic (1)" + "sethi %%hi(%a1),%0" + [(set_attr "type" "move") + (set_attr "length" "1")]) + (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (high:SI (match_operand 1 "" "")))] @@ -836,6 +845,18 @@ ;; is not an "arith_operand". [(set_attr "length" "1")]) +;; For PIC, symbol_refs are put inside unspec so that the optimizer won't +;; confuse them with real addresses. +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))] + "" + "or %1,%%lo(%a2),%0" + ;; Need to set length for this arith insn because operand2 + ;; is not an "arith_operand". + [(set_attr "length" "1")]) + (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (lo_sum:SI (match_operand:SI 1 "register_operand" "r") @@ -944,7 +965,7 @@ (define_expand "movstrsi" [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) (mem:BLK (match_operand:BLK 1 "general_operand" ""))) - (use (match_operand:SI 2 "arith32_operand" "")) + (use (match_operand:SI 2 "nonmemory_operand" "")) (use (match_operand:SI 3 "immediate_operand" "")) (clobber (match_dup 0)) (clobber (match_dup 1)) @@ -967,7 +988,7 @@ (define_insn "" [(set (mem:BLK (match_operand:SI 0 "register_operand" "r")) (mem:BLK (match_operand:SI 1 "register_operand" "r"))) - (use (match_operand:SI 2 "arith32_operand" "rn")) + (use (match_operand:SI 2 "nonmemory_operand" "rn")) (use (match_operand:SI 3 "immediate_operand" "i")) (clobber (match_dup 0)) (clobber (match_dup 1)) @@ -976,7 +997,8 @@ (clobber (reg:SI 1))] "" "* return output_block_move (operands);" - [(set_attr "type" "multi")]) + [(set_attr "type" "multi") + (set_attr "length" "6")]) ;; Floating point move insns @@ -1071,7 +1093,7 @@ return output_fp_move_double (operands); return output_move_double (operands); }" - [(set_attr "type" "move,store,load,misc,multi,fp,fpload,multi,fpstore") + [(set_attr "type" "move,store,load,multi,multi,fp,fpload,multi,fpstore") (set_attr "length" "2,3,3,3,3,2,3,3,3")]) ;; Floating-point move insns. @@ -1099,8 +1121,7 @@ ld %1,%0 st %r1,%0 st %r1,%0" - [(set_attr "type" "fp,move,multi,fpload,load,fpstore,store") - (set_attr "length" "*,*,2,*,*,*,*")]) + [(set_attr "type" "fp,move,multi,fpload,load,fpstore,store")]) (define_insn "" [(set (mem:SF (match_operand:SI 0 "symbolic_operand" "i")) @@ -1277,6 +1298,27 @@ "ldsb %1,%0" [(set_attr "type" "load")]) +;; Special pattern for optimizing bit-field compares. This is needed +;; because combine uses this as a canonical form. + +(define_insn "" + [(set (reg:CC 0) + (compare:CC + (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "small_int" "n") + (match_operand:SI 2 "small_int" "n")) + (const_int 0)))] + "INTVAL (operands[2]) > 19" + "* +{ + int len = INTVAL (operands[1]); + int pos = 32 - INTVAL (operands[2]) - len; + unsigned mask = ((1 << len) - 1) << pos; + + operands[1] = gen_rtx (CONST_INT, VOIDmode, mask); + return \"andcc %0,%1,%%g0\"; +}") + ;; Conversions between float and double. (define_insn "extendsfdf2" @@ -1372,7 +1414,7 @@ { rtx op2 = operands[2]; - /* If constant is postive, upper bits zeroed, otherwise unchanged + /* If constant is positive, upper bits zeroed, otherwise unchanged * give the assembler a chance to pick the move instruction. */ if (GET_CODE (op2) == CONST_INT) { @@ -1430,8 +1472,8 @@ { rtx op2 = operands[2]; - /* If constant is postive, upper bits zeroed, otherwise unchanged - * give the assembler a chance to pick the move instruction. */ + /* If constant is positive, upper bits zeroed, otherwise unchanged + /* If constant is positive, upper bits zeroed, otherwise unchanged if (GET_CODE (op2) == CONST_INT) { int sign = INTVAL (op2); @@ -1498,7 +1540,7 @@ { rtx op2 = operands[2]; - /* If constant is postive, upper bits zeroed, otherwise unchanged + /* If constant is positive, upper bits zeroed, otherwise unchanged * give the assembler a chance to pick the move instruction. */ if (GET_CODE (op2) == CONST_INT) { @@ -1558,7 +1600,7 @@ { rtx op2 = operands[2]; - /* If constant is postive, upper bits zeroed, otherwise unchanged + /* If constant is positive, upper bits zeroed, otherwise unchanged * give the assembler a chance to pick the move instruction. */ if (GET_CODE (op2) == CONST_INT) { @@ -2004,7 +2046,7 @@ ;; Unconditional and other jump instructions ;; Note that for the Sparc, by setting the annul bit on an unconditional ;; branch, the following insn is never executed. This saves us a nop, -;; but requires a debugger which can handle annuled branches. +;; but requires a debugger which can handle annulled branches. (define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" @@ -2263,12 +2305,15 @@ (define_insn "" [(unspec_volatile [(const_int 0)] 0)] "" - "ta 3") + "ta 3" + [(set_attr "type" "misc")]) (define_insn "" [(unspec_volatile [(const_int 0)] 1)] "" - "jmp %%o0+0\;restore") + "jmp %%o0+0\;restore" + [(set_attr "type" "misc") + (set_attr "length" "2")]) ;(define_insn "tail_call" ;; tail call ; [(set (pc) (match_operand 0 "memory_operand" "m"))] @@ -2469,8 +2514,7 @@ (const_int 0)))] "rtx_equal_p (operands[2], operands[0]) || rtx_equal_p (operands[2], operands[1])" - "orcc %1,%%g0,%0" - [(set_attr "type" "move")]) + "orcc %1,%%g0,%0") ;; Do {sign,zero}-extended compares somewhat more efficiently. ;; ??? Is this now the Right Way to do this? Or will SCRATCH @@ -2604,7 +2648,8 @@ (match_operand:SF 0 "register_operand" "f")) (return)] "! TARGET_EPILOGUE" - "ret\;fmovs %0,%%f0") + "ret\;fmovs %0,%%f0" + [(set_attr "type" "multi")]) ;; Now peepholes to go a call followed by a jump. @@ -2638,8 +2683,7 @@ (clobber (reg:CC 0))]) (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))] "" - "subxcc %r1,0,%0" - [(set_attr "type" "compare")]) + "subxcc %r1,0,%0") ;;- Local variables: ;;- mode:emacs-lisp |