From: Marek Michalkiewicz Date: Fri, 10 May 2002 12:22:36 +0000 (+0200) Subject: avr.c (print_operand): Check that addr is a SYMBOL_REF before using SYMBOL_REF_FLAG... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1a499b9250dfd05a03485d281e873b437d67bc9e;p=gcc.git avr.c (print_operand): Check that addr is a SYMBOL_REF before using SYMBOL_REF_FLAG (addr). * config/avr/avr.c (print_operand): Check that addr is a SYMBOL_REF before using SYMBOL_REF_FLAG (addr). * config/avr/avr-protos.h (avr_io_address_p): Declare. * config/avr/avr.c (io_address_p): Rename to avr_io_address_p. Make non-static. Update all callers. * config/avr/avr.md (*cbi, *sbi, *sbix_branch, *sbix_branch_bit7): New insns to clear/set/test a single bit in I/O address space. From-SVN: r53359 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 94b87900aed..8d1122a2688 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2002-05-10 Marek Michalkiewicz + + * config/avr/avr.c (print_operand): Check that addr is a SYMBOL_REF + before using SYMBOL_REF_FLAG (addr). + + * config/avr/avr-protos.h (avr_io_address_p): Declare. + * config/avr/avr.c (io_address_p): Rename to avr_io_address_p. + Make non-static. Update all callers. + * config/avr/avr.md (*cbi, *sbi, *sbix_branch, *sbix_branch_bit7): + New insns to clear/set/test a single bit in I/O address space. + 2002-05-09 Kaveh R. Ghazi * rtl.h (ENABLE_RTL_FLAG_CHECKING): Also check for gcc >= 2.7. diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index 966a0cb28a4..fe69e636efe 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -141,6 +141,7 @@ extern int compare_eq_p PARAMS ((rtx insn)); extern void out_shift_with_cnt PARAMS ((const char *template, rtx insn, rtx operands[], int *len, int t_len)); +extern int avr_io_address_p PARAMS ((rtx x, int size)); extern int const_int_pow2_p PARAMS ((rtx x)); extern int avr_peep2_scratch_safe PARAMS ((rtx reg_rtx)); #endif /* RTX_CODE */ diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 30ea833c751..40276622ab2 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -56,7 +56,6 @@ static int out_set_stack_ptr PARAMS ((FILE *, int, int)); static RTX_CODE compare_condition PARAMS ((rtx insn)); static int compare_sign_p PARAMS ((rtx insn)); static int reg_was_0 PARAMS ((rtx insn, rtx op)); -static int io_address_p PARAMS ((rtx x, int size)); void debug_hard_reg_set PARAMS ((HARD_REG_SET set)); static tree avr_handle_progmem_attribute PARAMS ((tree *, tree, tree, int, bool *)); static tree avr_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *)); @@ -1001,7 +1000,8 @@ print_operand_address (file, addr) default: if (CONSTANT_ADDRESS_P (addr) - && (SYMBOL_REF_FLAG (addr) || GET_CODE (addr) == LABEL_REF)) + && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr)) + || GET_CODE (addr) == LABEL_REF)) { fprintf (file, "pm("); output_addr_const (file,addr); @@ -1802,7 +1802,7 @@ out_movqi_r_mr (insn, op, l) if (CONSTANT_ADDRESS_P (x)) { - if (io_address_p (x, 1)) + if (avr_io_address_p (x, 1)) { *l = 1; return AS2 (in,%0,%1-0x20); @@ -1971,7 +1971,7 @@ out_movhi_r_mr (insn, op, l) } else if (CONSTANT_ADDRESS_P (base)) { - if (io_address_p (base, 2)) + if (avr_io_address_p (base, 2)) { *l = 2; return (AS2 (in,%A0,%A1-0x20) CR_TAB @@ -2514,7 +2514,7 @@ out_movqi_mr_r (insn, op, l) if (CONSTANT_ADDRESS_P (x)) { - if (io_address_p (x, 1)) + if (avr_io_address_p (x, 1)) { *l = 1; return AS2 (out,%0-0x20,%1); @@ -2592,7 +2592,7 @@ out_movhi_mr_r (insn, op, l) l = &tmp; if (CONSTANT_ADDRESS_P (base)) { - if (io_address_p (base, 2)) + if (avr_io_address_p (base, 2)) { *l = 2; return (AS2 (out,%B0-0x20,%B1) CR_TAB @@ -4927,7 +4927,7 @@ avr_address_cost (x) return 18; if (CONSTANT_ADDRESS_P (x)) { - if (io_address_p (x, 1)) + if (avr_io_address_p (x, 1)) return 2; return 4; } @@ -5246,10 +5246,11 @@ reg_was_0 (insn, op) } /* Returns 1 if X is a valid address for an I/O register of size SIZE - (1 or 2). Used for lds/sts -> in/out optimization. */ + (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE + to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */ -static int -io_address_p (x, size) +int +avr_io_address_p (x, size) rtx x; int size; { diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 762288f6403..da4c571742b 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -2230,6 +2230,105 @@ [(set_attr "length" "1") (set_attr "cc" "compare")]) +;; Clear/set/test a single bit in I/O address space. + +(define_insn "*cbi" + [(set (mem:QI (match_operand 0 "const_int_operand" "n")) + (and:QI (mem:QI (match_dup 0)) + (match_operand 1 "const_int_operand" "n")))] + "avr_io_address_p (operands[0], 1 + 0x20) + && exact_log2 (~INTVAL (operands[1]) & 0xff) >= 0" +{ + operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff)); + return AS2 (cbi,%0-0x20,%2); +} + [(set_attr "length" "1") + (set_attr "cc" "none")]) + +(define_insn "*sbi" + [(set (mem:QI (match_operand 0 "const_int_operand" "n")) + (ior:QI (mem:QI (match_dup 0)) + (match_operand 1 "const_int_operand" "n")))] + "avr_io_address_p (operands[0], 1 + 0x20) + && exact_log2 (INTVAL (operands[1]) & 0xff) >= 0" +{ + operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff)); + return AS2 (sbi,%0-0x20,%2); +} + [(set_attr "length" "1") + (set_attr "cc" "none")]) + +(define_insn "*sbix_branch" + [(set (pc) + (if_then_else + (match_operator 0 "comparison_operator" + [(zero_extract + (mem:QI (match_operand 1 "const_int_operand" "n")) + (const_int 1) + (match_operand 2 "const_int_operand" "n")) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "(GET_CODE (operands[0]) == EQ || GET_CODE (operands[0]) == NE) + && avr_io_address_p (operands[1], 1 + 0x20)" +{ + enum rtx_code comp = GET_CODE (operands[0]); + int reverse = (get_attr_length (insn) == 4); + + if (reverse) + comp = reverse_condition (comp); + if (comp == EQ) + output_asm_insn (AS2 (sbis,%1-0x20,%2), operands); + else + output_asm_insn (AS2 (sbic,%1-0x20,%2), operands); + if (!reverse) + return AS1 (rjmp,%3); + return (AS1 (rjmp,_PC_+4) CR_TAB + AS1 (jmp,%3)); +} + [(set (attr "length") + (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) + (le (minus (pc) (match_dup 3)) (const_int 2046))) + (const_int 2) + (if_then_else (eq_attr "mcu_mega" "no") + (const_int 2) + (const_int 4)))) + (set_attr "cc" "clobber")]) + +;; Tests of bit 7 are pessimized to sign tests, so we need this too... +(define_insn "*sbix_branch_bit7" + [(set (pc) + (if_then_else + (match_operator 0 "comparison_operator" + [(mem:QI (match_operand 1 "const_int_operand" "n")) + (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc)))] + "(GET_CODE (operands[0]) == GE || GET_CODE (operands[0]) == LT) + && avr_io_address_p (operands[1], 1 + 0x20)" +{ + enum rtx_code comp = GET_CODE (operands[0]); + int reverse = (get_attr_length (insn) == 4); + + if (reverse) + comp = reverse_condition (comp); + if (comp == GE) + output_asm_insn (AS2 (sbis,%1-0x20,7), operands); + else + output_asm_insn (AS2 (sbic,%1-0x20,7), operands); + if (!reverse) + return AS1 (rjmp,%2); + return (AS1 (rjmp,_PC_+4) CR_TAB + AS1 (jmp,%2)); +} + [(set (attr "length") + (if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046)) + (le (minus (pc) (match_dup 2)) (const_int 2046))) + (const_int 2) + (if_then_else (eq_attr "mcu_mega" "no") + (const_int 2) + (const_int 4)))) + (set_attr "cc" "clobber")]) ;; ************************* Peepholes ********************************