From: DJ Delorie Date: Sat, 17 Jan 2015 02:57:53 +0000 (-0500) Subject: rl78-real.md (addqi3_real): Allow volatiles. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=48c528ae3a2fddd58a7e45b9ef334b42c1ea1686;p=gcc.git rl78-real.md (addqi3_real): Allow volatiles. * config/rl78/rl78-real.md (addqi3_real): Allow volatiles. (addhi3_real): Likewise. Fix [HL+0] syntax. (subqi3_real): Likewise. (subhi3_real): Likewise. (cbranchqi4_real): Likewise. Allow saddr,#imm. (cbranchhi4_real): Likewise. (cbranchhi4_real_inverted): Likewise. (cbranchsi4_real_lt): Likewise. (cbranchsi4_real_ge): Likewise. (cbranchsi4_real_ge): Likewise. * config/rl78/rl78-virt.md (add3_virt): Likewise. (sub3_virt): Likewise. (cbranchqi4_virt): Likewise. (cbranchhi4_virt): Likewise. * config/rl78/rl78.c (rl78_print_operand_1): 'p' modifier means always use '[reg+imm]' even when imm is zero. * config/rl78/predicates.md (rl78_volatile_memory_operand): New. (rl78_general_operand): New. (rl78_nonimmediate_operand): New. (rl78_nonfar_operand): Use them. (rl78_nonfar_nonimm_operand): Likewise. (rl78_stack_based_mem): Fix. * config/rl78/constraints.md (Ibqi): New. (IBqi): New. (Wsa): New. (Wsf): New. (Cs1): Fix. * config/rl78/rl78-expand.md (andqi3): Accept volatiles. (iorqi3): Likewise. (xorqi3): Likewise. * config/rl78/rl78-protos.h (rl78_sfr_p): New. * config/rl78/constrains (Qs8): New constraint. * config/rl78/rl78.c (rl78_flags_already_set): New function. * config/rl78/rl78-protos.h (rl78_flags_already_set): New prototype. * config/rl78/rl78-real.md (update_Z): New attribute. Update patterns to set it. (cbranchqi4_real): Call rl78_flags_already_set() to determine if a shorter compare and branch sequence can be used. (cbranchhi4_real): Likewise. (cbranchhi4_real_inverted): Likewise. * config/rl78/predicates.md (uword_operand): Allow symbol_refs. * config/rl78/rl78-c.c (rl78_register_pragmas): Register __near address space. * config/rl78/rl78.c (rl78_get_name_encoding): New. (rl78_option_override): Allow -mes0 only if C. (characterize_address): Support subregs of symbol_refs. (rl78_addr_space_address_mode): Move. Add __near. (rl78_far_p): Likewise. (rl78_addr_space_pointer_mode): Likewise. (rl78_as_legitimate_address): Likewise. (rl78_addr_space_subset_p): Likewise. (rl78_addr_space_convert): Likewise. (rl78_print_operand_1): Support 16-bit addressing of 32-bit symbols with -mes0. (transcode_memory_rtx): Don't copy ES if -mes0. Allow symbol[BC] addressing. (rl78_alloc_physical_registers_op1): Change logic to prefer symbol[BC] addressing. (frodata_section): New. (rl78_asm_init_sections): Initialize it. (rl78_select_section): Put __far readonly symbols in .frodata. (rl78_make_type_far): New. (rl78_insert_attributes): Force all readonly symbols to be __far when -mes0. (rl78_asm_out_integer): New. * config/rl78/rl78.h (ADDR_SPACE_NEAR): New. * config/rl78/rl78.opt (-mes0): New. * config/rl78/rl78.h (ASM_OUTPUT_LABELREF): New. (ASM_OUTPUT_ALIGNED_DECL_COMMON): New. (ASM_OUTPUT_ALIGNED_DECL_LOCAL): New. * config/rl78/rl78-protos.h (rl78_output_labelref): New. (rl78_saddr_p): New. (rl78_output_aligned_common): New. * config/rl78/rl78.c (rl78_output_symbol_ref): Strip encodings. (rl78_handle_saddr_attribute): New. (rl78_handle_naked_attribute): New. (rl78_attribute_table): Add saddr. (rl78_print_operand_1): Don't print '!' on saddr operands. (rl78_print_operand_1): Strip encodings. (rl78_sfr_p): New. (rl78_strip_name_encoding): New. (rl78_attrlist_to_encoding): New. (rl78_encode_section_info): New. (rl78_asm_init_sections): New. (rl78_select_section): New. (rl78_output_labelref): New. (rl78_output_aligned_common): New. (rl78_asm_out_integer): New. (rl78_asm_ctor_dtor): New. (rl78_asm_constructor): New. (rl78_asm_destructor): New. * config/rl78/rl78-real.md (movqi_es): Rename to movqi_to_es. * config/rl78/rl78.c (rl78_expand_epilogue): Update. (transcode_memory_rtx): Update. (rl78_expand_epilogue): Use A_REG instead of 0. Co-Authored-By: Nick Clifton From-SVN: r219791 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4f0414a6b16..9b9053a81b3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,105 @@ +2015-01-16 DJ Delorie + Nick Clifton + + * config/rl78/rl78-real.md (addqi3_real): Allow volatiles. + (addhi3_real): Likewise. Fix [HL+0] syntax. + (subqi3_real): Likewise. + (subhi3_real): Likewise. + (cbranchqi4_real): Likewise. Allow saddr,#imm. + (cbranchhi4_real): Likewise. + (cbranchhi4_real_inverted): Likewise. + (cbranchsi4_real_lt): Likewise. + (cbranchsi4_real_ge): Likewise. + (cbranchsi4_real_ge): Likewise. + * config/rl78/rl78-virt.md (add3_virt): Likewise. + (sub3_virt): Likewise. + (cbranchqi4_virt): Likewise. + (cbranchhi4_virt): Likewise. + * config/rl78/rl78.c (rl78_print_operand_1): 'p' modifier means + always use '[reg+imm]' even when imm is zero. + * config/rl78/predicates.md (rl78_volatile_memory_operand): New. + (rl78_general_operand): New. + (rl78_nonimmediate_operand): New. + (rl78_nonfar_operand): Use them. + (rl78_nonfar_nonimm_operand): Likewise. + (rl78_stack_based_mem): Fix. + * config/rl78/constraints.md (Ibqi): New. + (IBqi): New. + (Wsa): New. + (Wsf): New. + (Cs1): Fix. + * config/rl78/rl78-expand.md (andqi3): Accept volatiles. + (iorqi3): Likewise. + (xorqi3): Likewise. + * config/rl78/rl78-protos.h (rl78_sfr_p): New. + + * config/rl78/constrains (Qs8): New constraint. + * config/rl78/rl78.c (rl78_flags_already_set): New function. + * config/rl78/rl78-protos.h (rl78_flags_already_set): New prototype. + * config/rl78/rl78-real.md (update_Z): New attribute. + Update patterns to set it. + (cbranchqi4_real): Call rl78_flags_already_set() to determine if a + shorter compare and branch sequence can be used. + (cbranchhi4_real): Likewise. + (cbranchhi4_real_inverted): Likewise. + + * config/rl78/predicates.md (uword_operand): Allow symbol_refs. + * config/rl78/rl78-c.c (rl78_register_pragmas): Register __near + address space. + * config/rl78/rl78.c (rl78_get_name_encoding): New. + (rl78_option_override): Allow -mes0 only if C. + (characterize_address): Support subregs of symbol_refs. + (rl78_addr_space_address_mode): Move. Add __near. + (rl78_far_p): Likewise. + (rl78_addr_space_pointer_mode): Likewise. + (rl78_as_legitimate_address): Likewise. + (rl78_addr_space_subset_p): Likewise. + (rl78_addr_space_convert): Likewise. + (rl78_print_operand_1): Support 16-bit addressing of 32-bit + symbols with -mes0. + (transcode_memory_rtx): Don't copy ES if -mes0. Allow symbol[BC] + addressing. + (rl78_alloc_physical_registers_op1): Change logic to prefer + symbol[BC] addressing. + (frodata_section): New. + (rl78_asm_init_sections): Initialize it. + (rl78_select_section): Put __far readonly symbols in .frodata. + (rl78_make_type_far): New. + (rl78_insert_attributes): Force all readonly symbols to be __far when -mes0. + (rl78_asm_out_integer): New. + * config/rl78/rl78.h (ADDR_SPACE_NEAR): New. + * config/rl78/rl78.opt (-mes0): New. + + * config/rl78/rl78.h (ASM_OUTPUT_LABELREF): New. + (ASM_OUTPUT_ALIGNED_DECL_COMMON): New. + (ASM_OUTPUT_ALIGNED_DECL_LOCAL): New. + * config/rl78/rl78-protos.h (rl78_output_labelref): New. + (rl78_saddr_p): New. + (rl78_output_aligned_common): New. + * config/rl78/rl78.c (rl78_output_symbol_ref): Strip encodings. + (rl78_handle_saddr_attribute): New. + (rl78_handle_naked_attribute): New. + (rl78_attribute_table): Add saddr. + (rl78_print_operand_1): Don't print '!' on saddr operands. + (rl78_print_operand_1): Strip encodings. + (rl78_sfr_p): New. + (rl78_strip_name_encoding): New. + (rl78_attrlist_to_encoding): New. + (rl78_encode_section_info): New. + (rl78_asm_init_sections): New. + (rl78_select_section): New. + (rl78_output_labelref): New. + (rl78_output_aligned_common): New. + (rl78_asm_out_integer): New. + (rl78_asm_ctor_dtor): New. + (rl78_asm_constructor): New. + (rl78_asm_destructor): New. + + * config/rl78/rl78-real.md (movqi_es): Rename to movqi_to_es. + * config/rl78/rl78.c (rl78_expand_epilogue): Update. + (transcode_memory_rtx): Update. + (rl78_expand_epilogue): Use A_REG instead of 0. + 2015-01-17 Maxim Kuvyrkov * config/arm/arm-protos.h (struct tune_params): New field diff --git a/gcc/config/rl78/constraints.md b/gcc/config/rl78/constraints.md index c6cc1a8f5b8..209f1e660a1 100644 --- a/gcc/config/rl78/constraints.md +++ b/gcc/config/rl78/constraints.md @@ -111,6 +111,17 @@ (and (match_code "const_int") (match_test "(ival & 0x80) != 0"))) +(define_constraint "Ibqi" + "@internal + Integer constant with one bit in 0..7 set." + (and (match_code "const_int") + (match_test "(ival & 0xff) && (exact_log2 (ival & 0xff) >= 0)"))) +(define_constraint "IBqi" + "@internal + Integer constant with one bit in 0..7 clear." + (and (match_code "const_int") + (match_test "(~ival & 0xff) && (exact_log2 (~ival & 0xff) >= 0)"))) + (define_constraint "J" "Integer constant in the range -255 @dots{} 0" (and (match_code "const_int") @@ -342,9 +353,11 @@ (and (match_code "plus" "0") (and (and (match_code "reg" "00") (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG")) - (match_test "ubyte_operand (XEXP (XEXP (op, 0), 1), VOIDmode)")))) + (and (match_code "const_int" "01") + (match_test "IN_RANGE (INTVAL (XEXP (XEXP (op, 0), 1)), 0, 256 - GET_MODE_SIZE (GET_MODE (op)))"))))) ) ) + (define_memory_constraint "Ws1" "es:word8[SP]" (match_test "(rl78_es_addr (op) && satisfies_constraint_Cs1 (rl78_es_base (op))) @@ -357,6 +370,18 @@ (match_test "rl78_far_p (op)")) ) +(define_memory_constraint "Wsa" + "any SADDR memory access" + (and (match_code "mem") + (match_test "rl78_saddr_p (op)")) +) + +(define_memory_constraint "Wsf" + "any SFR memory access" + (and (match_code "mem") + (match_test "rl78_sfr_p (op)")) +) + (define_memory_constraint "Y" "any near legitimate memory access" (and (match_code "mem") @@ -384,3 +409,9 @@ (define_memory_constraint "Qsc" "synthetic compares" (match_code "gt,lt,ge,le")) + +(define_constraint "Qs8" + "Integer constant computed from (SUBREG (SYMREF))." + (and (match_code "subreg") + (match_test "GET_CODE (XEXP (op, 0)) == SYMBOL_REF")) +) diff --git a/gcc/config/rl78/predicates.md b/gcc/config/rl78/predicates.md index af10ebd2c3a..b89eed22400 100644 --- a/gcc/config/rl78/predicates.md +++ b/gcc/config/rl78/predicates.md @@ -18,18 +18,34 @@ ;; along with GCC; see the file COPYING3. If not see ;; . -(define_predicate "rl78_any_operand" + +(define_predicate "rl78_volatile_memory_operand" + (and (match_code "mem") + (match_test ("memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0), MEM_ADDR_SPACE (op))"))) +) + +; TRUE for any valid general operand. We do this because +; general_operand refuses to match volatile memory refs. + +(define_predicate "rl78_general_operand" (ior (match_operand 0 "general_operand") - (match_code "mem,const_int,const_double,reg")) + (match_operand 0 "rl78_volatile_memory_operand")) +) + +; Likewise for nonimmediate_operand. + +(define_predicate "rl78_nonimmediate_operand" + (ior (match_operand 0 "nonimmediate_operand") + (match_operand 0 "rl78_volatile_memory_operand")) ) (define_predicate "rl78_nonfar_operand" - (and (match_operand 0 "general_operand") + (and (match_operand 0 "rl78_general_operand") (not (match_test "rl78_far_p (op)"))) ) (define_predicate "rl78_nonfar_nonimm_operand" - (and (match_operand 0 "nonimmediate_operand") + (and (match_operand 0 "rl78_nonimmediate_operand") (not (match_test "rl78_far_p (op)"))) ) @@ -47,9 +63,14 @@ (match_test "INTVAL (op) == 2 || INTVAL (op) == 4"))) (define_predicate "uword_operand" - (ior (match_code "const") - (and (match_code "const_int") - (match_test "IN_RANGE (INTVAL (op), 0, 65536)")))) + (ior (ior (ior (match_code "const") + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 65536)"))) + (and (match_code "subreg") + (ior (match_code "symbol_ref" "0") + (match_code "const" "0")))) + (match_code "symbol_ref") + )) (define_predicate "rl78_cmp_operator_signed" (match_code "gt,ge,lt,le")) @@ -73,4 +94,6 @@ (and (match_code "plus" "0") (and (match_code "reg" "00") (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG") - (match_code "const_int" "01")))))) + (and (match_code "const_int" "01") + (match_test "IN_RANGE (INTVAL (XEXP (XEXP (op, 0), 1)), 0, 256 - GET_MODE_SIZE (GET_MODE (op)))")) + ))))) diff --git a/gcc/config/rl78/rl78-c.c b/gcc/config/rl78/rl78-c.c index 8c5d00c0584..c8410cdb4cc 100644 --- a/gcc/config/rl78/rl78-c.c +++ b/gcc/config/rl78/rl78-c.c @@ -39,5 +39,6 @@ void rl78_register_pragmas (void) { + c_register_addr_space ("__near", ADDR_SPACE_NEAR); c_register_addr_space ("__far", ADDR_SPACE_FAR); } diff --git a/gcc/config/rl78/rl78-expand.md b/gcc/config/rl78/rl78-expand.md index 219f2c0d494..ac3939d3ea9 100644 --- a/gcc/config/rl78/rl78-expand.md +++ b/gcc/config/rl78/rl78-expand.md @@ -150,9 +150,9 @@ ) (define_expand "andqi3" - [(set (match_operand:QI 0 "nonimmediate_operand") - (and:QI (match_operand:QI 1 "general_operand") - (match_operand:QI 2 "general_operand"))) + [(set (match_operand:QI 0 "rl78_nonimmediate_operand") + (and:QI (match_operand:QI 1 "rl78_general_operand") + (match_operand:QI 2 "rl78_general_operand"))) ] "" "if (rl78_force_nonfar_3 (operands, gen_andqi3)) @@ -160,9 +160,9 @@ ) (define_expand "iorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand") - (ior:QI (match_operand:QI 1 "general_operand") - (match_operand:QI 2 "general_operand"))) + [(set (match_operand:QI 0 "rl78_nonimmediate_operand") + (ior:QI (match_operand:QI 1 "rl78_general_operand") + (match_operand:QI 2 "rl78_general_operand"))) ] "" "if (rl78_force_nonfar_3 (operands, gen_iorqi3)) @@ -170,9 +170,9 @@ ) (define_expand "xorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand") - (xor:QI (match_operand:QI 1 "general_operand") - (match_operand:QI 2 "general_operand"))) + [(set (match_operand:QI 0 "rl78_nonimmediate_operand") + (xor:QI (match_operand:QI 1 "rl78_general_operand") + (match_operand:QI 2 "rl78_general_operand"))) ] "" "if (rl78_force_nonfar_3 (operands, gen_xorqi3)) diff --git a/gcc/config/rl78/rl78-protos.h b/gcc/config/rl78/rl78-protos.h index 0a5934e9022..56d3649376a 100644 --- a/gcc/config/rl78/rl78-protos.h +++ b/gcc/config/rl78/rl78-protos.h @@ -45,3 +45,11 @@ bool rl78_virt_insns_ok (void); bool rl78_es_addr (rtx); rtx rl78_es_base (rtx); + +bool rl78_flags_already_set (rtx, rtx); +void rl78_output_symbol_ref (FILE *, rtx); +void rl78_output_labelref (FILE *, const char *); +int rl78_saddr_p (rtx x); +int rl78_sfr_p (rtx x); +void rl78_output_aligned_common (FILE *, tree, const char *, + int, int, int); diff --git a/gcc/config/rl78/rl78-real.md b/gcc/config/rl78/rl78-real.md index f92a075658f..8ec2f3d6a6f 100644 --- a/gcc/config/rl78/rl78-real.md +++ b/gcc/config/rl78/rl78-real.md @@ -27,9 +27,17 @@ ;; patterns - other than the constraints - so that the operand info is ;; properly set up for the alloc pass. +;; This attribute reflects how the insn alters the Z flag, +;; based upon the value of the it's output. The default is NO +;; for no change, but other possibilities are UPDATE_Z if it changes +;; the Z flag and CLOBBER if the state of the flag is indeterminate. +;; The CY and AC flags are not set in the same way as the Z flag, so +;; their values are not tracked. +(define_attr "update_Z" "no,update_Z,clobber" (const_string "no")) + ;;---------- Moving ------------------------ -(define_insn "movqi_es" +(define_insn "movqi_to_es" [(set (reg:QI ES_REG) (match_operand:QI 0 "register_operand" "a"))] "" @@ -51,8 +59,8 @@ ) (define_insn "*movqi_real" - [(set (match_operand:QI 0 "nonimmediate_operand" "=g,RaxbcWab,RaxbcWab,a, bcx,R, WabWd2WhlWh1WhbWbcWs1v, bcx") - (match_operand 1 "general_operand" "0,K, M, RInt8sJvWabWdeWd2WhlWh1WhbWbcWs1,Wab,aInt8J,a, R"))] + [(set (match_operand:QI 0 "rl78_nonimmediate_operand" "=g,RaxbcWab,RaxbcWab,a, bcx,R, WabWd2WhlWh1WhbWbcWs1v, bcx,WsaWsf") + (match_operand 1 "rl78_general_operand" "0,K, M, RInt8sJvWabWdeWd2WhlWh1WhbWbcWs1,Wab,aInt8J,a, R, i"))] "rl78_real_insns_ok ()" "@ ; mov\t%0, %1 @@ -62,12 +70,13 @@ mov\t%0, %1 mov\t%0, %1 mov\t%0, %1 - mov\t%0, %S1" + mov\t%0, %S1 + mov\t%0, %1" ) (define_insn "*movhi_real" - [(set (match_operand:HI 0 "nonimmediate_operand" "=g,AB,AB,RSv,A,BDTvSWabWd2WdeWhlWh1WbcWs1, BDT,ABDT,v") - (match_operand:HI 1 "general_operand" " 0,K, M, i, BDTvSWabWd2WdeWh1WhlWbcWs1,A, BDT,vS, ABDT"))] + [(set (match_operand:HI 0 "rl78_nonimmediate_operand" "=g,AB,AB,RSv,A,BDTvSWabWd2WdeWhlWh1WbcWs1, BDT,ABDT,v") + (match_operand:HI 1 "rl78_general_operand" " 0,K, M, i, BDTvSWabWd2WdeWh1WhlWbcWs1,A, BDT,vS, ABDT"))] "rl78_real_insns_ok ()" "@ ; movw\t%0, %1 @@ -104,33 +113,36 @@ ;;---------- Arithmetic ------------------------ (define_insn "*addqi3_real" - [(set (match_operand:QI 0 "nonimmediate_operand" "=rvWabWhlWh1,rvWabWhlWh1,a,*bcdehl") - (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0") - (match_operand:QI 2 "general_operand" "K,L,RWhlWh1Wabi,a"))) + [(set (match_operand:QI 0 "rl78_nonimmediate_operand" "=rvWabWhlWh1,rvWabWhlWh1,a,*bcdehl,Wsa") + (plus:QI (match_operand:QI 1 "rl78_general_operand" "%0,0,0,0,0") + (match_operand:QI 2 "rl78_general_operand" "K,L,RWhlWh1Wabi,a,i"))) ] "rl78_real_insns_ok ()" "@ inc\t%0 dec\t%0 add\t%0, %2 + add\t%0, %2 add\t%0, %2" + [(set (attr "update_Z") (const_string "update_Z"))] ) (define_insn "*addhi3_real" - [(set (match_operand:HI 0 "nonimmediate_operand" "=vABDTWh1Wab,vABDTWh1Wab,v,v,A,S,S,A") - (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0,S") - (match_operand:HI 2 "general_operand" "K,L,N,O,RWh1WhlWabiv,Int8,J,Ri"))) + [(set (match_operand:HI 0 "rl78_nonimmediate_operand" "=vABDTWh1Wab,vABDTWh1Wab,v,v,A,S,S,A") + (plus:HI (match_operand:HI 1 "rl78_general_operand" "%0,0,0,0,0,0,0,S") + (match_operand:HI 2 "" "K,L,N,O,RWh1WhlWabiv,Int8Qs8,J,Ri"))) ] "rl78_real_insns_ok ()" "@ - incw\t%0 - decw\t%0 + incw\t%p0 + decw\t%p0 incw\t%0 \;incw\t%0 decw\t%0 \;decw\t%0 addw\t%0, %p2 addw\t%0, %2 subw\t%0, %m2 movw\t%0, %1 \;addw\t%0, %2" + [(set_attr "update_Z" "*,*,*,*,update_Z,update_Z,update_Z,update_Z")] ) (define_insn "*addqihi3a_real" @@ -140,24 +152,27 @@ ] "rl78_real_insns_ok ()" "add\t%q0, %q1 \;addc\t%Q0, #0" + [(set (attr "update_Z") (const_string "update_Z"))] ) (define_insn "*subqi3_real" [(set (match_operand:QI 0 "nonimmediate_operand" "=a,R,v") (minus:QI (match_operand:QI 1 "general_operand" "0,0,0") - (match_operand:QI 2 "general_operand" "RiWabWhbWh1Whl,a,i"))) + (match_operand:QI 2 "rl78_general_operand" "RiWabWhbWh1Whl,a,i"))) ] "rl78_real_insns_ok ()" "sub\t%0, %2" + [(set (attr "update_Z") (const_string "update_Z"))] ) (define_insn "*subhi3_real" [(set (match_operand:HI 0 "nonimmediate_operand" "=A,S") (minus:HI (match_operand:HI 1 "general_operand" "0,0") - (match_operand:HI 2 "general_operand" "iBDTWabWh1v,i"))) + (match_operand:HI 2 "rl78_general_operand" "iBDTWabWh1v,i"))) ] "rl78_real_insns_ok ()" "subw\t%0, %2" + [(set (attr "update_Z") (const_string "update_Z"))] ) (define_insn "*umulhi3_shift_real" @@ -179,30 +194,41 @@ ) (define_insn "*andqi3_real" - [(set (match_operand:QI 0 "nonimmediate_operand" "=A,R,v") - (and:QI (match_operand:QI 1 "general_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "iRvWabWhbWh1Whl,A,i"))) + [(set (match_operand:QI 0 "rl78_nonimmediate_operand" "=Wsf,A,R,vWsa") + (and:QI (match_operand:QI 1 "rl78_general_operand" "%0,0,0,0") + (match_operand:QI 2 "rl78_general_operand" "IBqi,iRvWabWhbWh1Whl,A,i"))) ] "rl78_real_insns_ok ()" - "and\t%0, %2" + "@ + clr1\t%0.%B2 + and\t%0, %2 + and\t%0, %2 + and\t%0, %2" + [(set_attr "update_Z" "*,update_Z,update_Z,update_Z")] ) (define_insn "*iorqi3_real" - [(set (match_operand:QI 0 "nonimmediate_operand" "=A,R,v") - (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0") - (match_operand:QI 2 "general_operand" "iRvWabWhbWh1Whl,A,i"))) + [(set (match_operand:QI 0 "rl78_nonimmediate_operand" "=Wsf,A,R,vWsa") + (ior:QI (match_operand:QI 1 "rl78_general_operand" "%0,0,0,0") + (match_operand:QI 2 "rl78_general_operand" "Ibqi,iRvWabWhbWh1Whl,A,i"))) ] "rl78_real_insns_ok ()" - "or\t%0, %2" + "@ + set1\t%0.%B2 + or\t%0, %2 + or\t%0, %2 + or\t%0, %2" + [(set_attr "update_Z" "*,update_Z,update_Z,update_Z")] ) (define_insn "*xorqi3_real" - [(set (match_operand:QI 0 "nonimmediate_operand" "=A,R,v") - (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0") - (match_operand 2 "general_operand" "iRvWabWhbWh1Whl,A,i"))) + [(set (match_operand:QI 0 "rl78_nonimmediate_operand" "=A,R,vWsa") + (xor:QI (match_operand:QI 1 "rl78_general_operand" "%0,0,0") + (match_operand 2 "rl78_general_operand" "iRvWabWhbWh1Whl,A,i"))) ] "rl78_real_insns_ok ()" "xor\t%0, %2" + [(set (attr "update_Z") (const_string "update_Z"))] ) ;;---------- Shifts ------------------------ @@ -217,6 +243,7 @@ shl\t%0, %u2 cmp0 %2\; bz $2f\; 1: shl\t%0, 1 \;dec %2 \;bnz $1b\;2: inc %2\;dec %2\;bz $2f\;1: shl\t%0, 1 \;dec %2 \;bnz $1b\;2:" + [(set_attr "update_Z" "*,clobber,clobber")] ) (define_insn "*ashlhi3_real" @@ -229,6 +256,7 @@ shlw\t%0, %u2 cmp0 %2\; bz $2f\; 1: shlw\t%0, 1 \;dec %2 \;bnz $1b\;2: inc %2\;dec %2\;bz $2f\;1: shlw\t%0, 1 \;dec %2 \;bnz $1b\;2:" + [(set_attr "update_Z" "*,clobber,clobber")] ) ;;---------- @@ -243,6 +271,7 @@ sar\t%0, %u2 cmp0 %2\; bz $2f\; 1: sar\t%0, 1 \;dec %2 \;bnz $1b\;2: inc %2\;dec %2\;bz $2f\;1: sar\t%0, 1\;dec %2 \;bnz $1b\;2:" + [(set_attr "update_Z" "*,clobber,clobber")] ) (define_insn "*ashrhi3_real" @@ -255,6 +284,7 @@ sarw\t%0, %u2 cmp0 %2\; bz $2f\; 1: sarw\t%0, 1 \;dec %2 \;bnz $1b\;2: inc %2\;dec %2\;bz $2f\;1: sarw\t%0, 1\;dec %2\;bnz $1b\;2:" + [(set_attr "update_Z" "*,clobber,clobber")] ) ;;---------- @@ -269,6 +299,7 @@ shr\t%0, %u2 cmp0 %2\; bz $2f\; 1: shr\t%0, 1 \;dec %2 \;bnz $1b\;2: inc %2\;dec %2\;bz $2f\;1: shr\t%0, 1\;dec %2\;bnz $1b\;2:" + [(set_attr "update_Z" "*,clobber,clobber")] ) (define_insn "*lshrhi3_real" @@ -281,6 +312,7 @@ shrw\t%0, %u2 cmp0 %2\; bz $2f\; 1: shrw\t%0, 1 \;dec %2 \;bnz $1b\;2: inc %2\;dec %2\;bz $2f\;1: shrw\t%0, 1\;dec %2\;bnz $1b\;2:" + [(set_attr "update_Z" "*,clobber,clobber")] ) ;;---------- Branching ------------------------ @@ -307,6 +339,7 @@ "@ call\t!!%A0 call\t%A0" + [(set (attr "update_Z") (const_string "clobber"))] ) (define_insn "*call_value_real" @@ -317,35 +350,52 @@ "@ call\t!!%A1 call\t%A1" + [(set (attr "update_Z") (const_string "clobber"))] ) (define_insn "*cbranchqi4_real_signed" [(set (pc) (if_then_else (match_operator 0 "rl78_cmp_operator_signed" - [(match_operand:QI 1 "general_operand" "A,A,A") - (match_operand:QI 2 "general_operand" "ISqi,i,v")]) + [(match_operand:QI 1 "general_operand" "A,A,A,A,Wsa") + (match_operand:QI 2 "general_operand" "M,ISqi,i,v,i")]) (label_ref (match_operand 3 "" "")) (pc)))] "rl78_real_insns_ok ()" - "@ - cmp\t%1, %2 \;xor1 CY,%1.7\;not1 CY\;sk%C0 \;br\t!!%3 - cmp\t%1, %2 \;xor1 CY,%1.7\;sk%C0 \;br\t!!%3 - cmp\t%1, %2 \;xor1 CY,%1.7\;xor1 CY,%2.7\;sk%C0 \;br\t!!%3" + { + gcc_assert (GET_CODE (operands[0]) != EQ && GET_CODE (operands[0]) != NE); + + switch (which_alternative) + { + case 0: return "cmp0\t%1\; xor1\tCY, %1.7\; sk%C0\; br\t!!%3"; + case 1: return "cmp\t%1, %2\; xor1\tCY, %1.7\; not1\tCY\; sk%C0\; br\t!!%3"; + case 4: + case 2: return "cmp\t%1, %2\; xor1\tCY, %1.7\; sk%C0\; br\t!!%3"; + case 3: return "cmp\t%1, %2\; xor1\tCY, %1.7\; xor1\tCY, %2.7\; sk%C0\; br\t!!%3"; + default: gcc_unreachable (); + } + } + [(set (attr "update_Z") (const_string "clobber"))] ;; FIXME: flags are set based on %1 vs %2 ) (define_insn "*cbranchqi4_real" [(set (pc) (if_then_else (match_operator 0 "rl78_cmp_operator_real" - [(match_operand:QI 1 "general_operand" "Wabvaxbc,a, v,bcdehl") - (match_operand:QI 2 "general_operand" "M, irvWabWhlWh1Whb,i,a")]) + [(match_operand:QI 1 "rl78_general_operand" "Wabvaxbc,a, vWsaWab,bcdehl") + (match_operand:QI 2 "rl78_general_operand" "M, irvWabWhlWh1Whb,i,a")]) (label_ref (match_operand 3 "" "")) (pc)))] "rl78_real_insns_ok ()" - "@ - cmp0\t%1 \;sk%C0 \;br\t!!%3 - cmp\t%1, %2 \;sk%C0 \;br\t!!%3 - cmp\t%1, %2 \;sk%C0 \;br\t!!%3 - cmp\t%1, %2 \;sk%C0 \;br\t!!%3" + { + if (which_alternative == 0) + { + if (rl78_flags_already_set (operands[0], operands[1])) + return "sk%C0\; br\t!!%3\; # zero-comparison eliminated"; + else + return "cmp0\t%1\; sk%C0\; br\t!!%3"; + } + return "cmp\t%1, %2\; sk%C0\; br\t!!%3"; + } + [(set (attr "update_Z") (const_string "clobber"))] ;; FIXME: alt 0: flags are set based on %1 vs %2 ) (define_insn "*cbranchhi4_real_signed" @@ -357,39 +407,59 @@ (pc)))] "rl78_real_insns_ok ()" "@ - cmpw\t%1, %2 \;xor1 CY,%Q1.7\;not1 CY\;sk%C0 \;br\t!!%3 - cmpw\t%1, %2 \;xor1 CY,%Q1.7\;sk%C0 \;br\t!!%3 - cmpw\t%1, %2 \;xor1 CY,%Q1.7\;xor1 CY,%Q2.7\;sk%C0 \;br\t!!%3 + cmpw\t%1, %2\; xor1\tCY, %Q1.7\; not1\tCY\; sk%C0\; br\t!!%3 + cmpw\t%1, %2\; xor1\tCY, %Q1.7\; sk%C0\; br\t!!%3 + cmpw\t%1, %2\; xor1\tCY, %Q1.7\; xor1\tCY, %Q2.7\; sk%C0\; br\t!!%3 %z0\t!!%3" + [(set_attr "update_Z" "clobber,clobber,clobber,*")] ) (define_insn "cbranchhi4_real" [(set (pc) (if_then_else (match_operator 0 "rl78_cmp_operator_real" - [(match_operand:HI 1 "general_operand" "A,vR") - (match_operand:HI 2 "general_operand" "iBDTvWabWhlWh1,1")]) + [(match_operand:HI 1 "general_operand" "A,A,vR") + (match_operand:HI 2 "rl78_general_operand" "M,iBDTvWabWhlWh1,1")]) (label_ref (match_operand 3 "" "")) (pc)))] "rl78_real_insns_ok ()" - "@ - cmpw\t%1, %2 \;sk%C0 \;br\t!!%3 - %z0\t!!%3" + { + switch (which_alternative) + { + case 0: + if (rl78_flags_already_set (operands[0], operands[1])) + return "sk%C0\; br\t!!%3\; # cmpw eliminated"; + /* else fall through. */ + case 1: + return "cmpw\t%1, %2\; sk%C0\; br\t!!%3"; + case 2: + return "%z0\t!!%3"; + default: + gcc_unreachable (); + } + } + [(set (attr "update_Z") (const_string "clobber"))] ;; FIXME: Z might be set based on %1 vs %2 ) (define_insn "cbranchhi4_real_inverted" [(set (pc) (if_then_else (match_operator 0 "rl78_cmp_operator_real" - [(match_operand:HI 1 "general_operand" "A") - (match_operand:HI 2 "general_operand" "iBDTvWabWhlWh1")]) + [(match_operand:HI 1 "general_operand" "A,A") + (match_operand:HI 2 "rl78_general_operand" "M,iBDTvWabWhlWh1")]) (pc) (label_ref (match_operand 3 "" ""))))] "rl78_real_insns_ok ()" - "cmpw\t%1, %2 \;sk%C0 \;br\t!!%3" + { + if (which_alternative == 0 && rl78_flags_already_set (operands[0], operands[1])) + return "sk%C0\; br\t!!%3\; # inverted cmpw eliminated"; + else + return "cmpw\t%1, %2\; sk%C0\; br\t!!%3"; + } + [(set (attr "update_Z") (const_string "clobber"))] ;; FIXME: flags are set based on %1 vs %2 ) (define_insn "*cbranchsi4_real_lt" [(set (pc) (if_then_else - (lt (match_operand:SI 0 "general_operand" "U,vWabWhlWh1") + (lt (match_operand:SI 0 "rl78_general_operand" "U,vWabWhlWh1") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) @@ -397,13 +467,13 @@ ] "rl78_real_insns_ok ()" "@ - mov a, %E0 \;mov1 CY,a.7 \;sknc \;br\t!!%1 - mov1 CY,%E0.7 \;sknc \;br\t!!%1" + mov\ta, %E0\; mov1\tCY, a.7\; sknc\; br\t!!%1 + mov1\tCY, %E0.7\; sknc\; br\t!!%1" ) (define_insn "*cbranchsi4_real_ge" [(set (pc) (if_then_else - (ge (match_operand:SI 0 "general_operand" "U,vWabWhlWh1") + (ge (match_operand:SI 0 "rl78_general_operand" "U,vWabWhlWh1") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) @@ -411,8 +481,8 @@ ] "rl78_real_insns_ok ()" "@ - mov a, %E0 \;mov1 CY,a.7 \;skc \;br\t!!%1 - mov1 CY,%E0.7 \;skc \;br\t!!%1" + mov\ta, %E0\; mov1\tCY, a.7\; skc\; br\t!!%1 + mov1\tCY, %E0.7\; skc\; br\t!!%1" ) (define_insn "*cbranchsi4_real_signed" @@ -426,11 +496,12 @@ ] "rl78_real_insns_ok ()" "@ - movw ax,%H1 \;cmpw ax, %H2 \;xor1 CY,a.7\;not1 CY\; movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%C0 \;br\t!!%3 - movw ax,%H1 \;cmpw ax, %H2 \;xor1 CY,a.7\; movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%C0 \;br\t!!%3 - movw ax,%H1 \;cmpw ax, %H2 \;xor1 CY,a.7\;xor1 CY,%E2.7\;movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%C0 \;br\t!!%3 - movw ax, %H1\; cmpw ax, %H2\; xor1 CY, a.7\; not1 CY\; movw ax, %h1 \;sknz\; cmpw ax, %h2 \;sk%0 \;br\t!!%3 - movw ax, %H1\; cmpw ax, %H2\; xor1 CY, a.7\; movw ax, %h1\; sknz\; cmpw ax, %h2\; sk%0\; br\t!!%3" + movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; not1\tCY\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%C0\; br\t!!%3 + movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%C0\; br\t!!%3 + movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; xor1\tCY, %E2.7\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%C0\; br\t!!%3 + movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; not1\tCY\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%0\; br\t!!%3 + movw\tax, %H1\; cmpw\tax, %H2\; xor1\tCY, a.7\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%0\; br\t!!%3" + [(set (attr "update_Z") (const_string "clobber"))] ) (define_insn "*cbranchsi4_real" @@ -443,7 +514,8 @@ (clobber (reg:HI AX_REG)) ] "rl78_real_insns_ok ()" - "movw ax,%H1 \;cmpw ax, %H2 \;movw ax,%h1 \;sknz \;cmpw ax, %h2 \;sk%C0 \;br\t!!%3" + "movw\tax, %H1\; cmpw\tax, %H2\; movw\tax, %h1\; sknz\; cmpw\tax, %h2\; sk%C0\; br\t!!%3" + [(set (attr "update_Z") (const_string "clobber"))] ) ;; Peephole to match: @@ -480,6 +552,7 @@ (pc)))] "" "bf\tA.%B0, $%1" + [(set (attr "update_Z") (const_string "clobber"))] ) (define_insn "bt" @@ -491,6 +564,7 @@ (pc)))] "" "bt\tA.%B0, $%1" + [(set (attr "update_Z") (const_string "clobber"))] ) ;; NOTE: These peepholes are fragile. They rely upon GCC generating @@ -565,4 +639,5 @@ ] "rl78_real_insns_ok ()" "xor a, #0xff @ xch a, x @ xor a, #0xff @ xch a, x @ addw ax, #1 @ and a, %Q2 @ xch a, x @ and a, %q2 @ xch a, x" + [(set (attr "update_Z") (const_string "clobber"))] ) diff --git a/gcc/config/rl78/rl78-virt.md b/gcc/config/rl78/rl78-virt.md index c24b939f5d7..fadcbc50433 100644 --- a/gcc/config/rl78/rl78-virt.md +++ b/gcc/config/rl78/rl78-virt.md @@ -88,7 +88,7 @@ (define_insn "*add3_virt" [(set (match_operand:QHI 0 "rl78_nonfar_nonimm_operand" "=vY,S") (plus:QHI (match_operand:QHI 1 "rl78_nonfar_operand" "viY,0") - (match_operand:QHI 2 "general_operand" "vim,i"))) + (match_operand:QHI 2 "rl78_general_operand" "vim,i"))) ] "rl78_virt_insns_ok ()" "v.add\t%0, %1, %2" @@ -97,7 +97,7 @@ (define_insn "*sub3_virt" [(set (match_operand:QHI 0 "rl78_nonfar_nonimm_operand" "=vm,S") (minus:QHI (match_operand:QHI 1 "rl78_nonfar_operand" "vim,0") - (match_operand:QHI 2 "general_operand" "vim,i"))) + (match_operand:QHI 2 "rl78_general_operand" "vim,i"))) ] "rl78_virt_insns_ok ()" "v.sub\t%0, %1, %2" @@ -124,7 +124,7 @@ (define_insn "*andqi3_virt" [(set (match_operand:QI 0 "rl78_nonfar_nonimm_operand" "=vm") (and:QI (match_operand:QI 1 "rl78_nonfar_operand" "vim") - (match_operand:QI 2 "general_operand" "vim"))) + (match_operand:QI 2 "rl78_general_operand" "vim"))) ] "rl78_virt_insns_ok ()" "v.and\t%0, %1, %2" @@ -133,16 +133,16 @@ (define_insn "*iorqi3_virt" [(set (match_operand:QI 0 "rl78_nonfar_nonimm_operand" "=vm") (ior:QI (match_operand:QI 1 "rl78_nonfar_operand" "vim") - (match_operand:QI 2 "general_operand" "vim"))) + (match_operand:QI 2 "rl78_general_operand" "vim"))) ] "rl78_virt_insns_ok ()" "v.or\t%0, %1, %2" ) -(define_insn "*xor3_virt" +(define_insn "*xorqi3_virt" [(set (match_operand:QI 0 "rl78_nonfar_nonimm_operand" "=v,vm,m") (xor:QI (match_operand:QI 1 "rl78_nonfar_operand" "%0,vm,vm") - (match_operand 2 "general_operand" "i,vm,vim"))) + (match_operand 2 "rl78_general_operand" "i,vm,vim"))) ] "rl78_virt_insns_ok ()" "v.xor\t%0, %1, %2" @@ -343,8 +343,8 @@ (define_insn "*cbranchqi4_virt" [(set (pc) (if_then_else (match_operator 0 "rl78_cmp_operator_real" - [(match_operand:QI 1 "general_operand" "vim") - (match_operand:QI 2 "general_operand" "vim")]) + [(match_operand:QI 1 "rl78_general_operand" "vim") + (match_operand:QI 2 "rl78_general_operand" "vim")]) (label_ref (match_operand 3 "" "")) (pc)))] "rl78_virt_insns_ok ()" @@ -367,8 +367,8 @@ (define_insn "*cbranchhi4_virt" [(set (pc) (if_then_else (match_operator 0 "rl78_cmp_operator_real" - [(match_operand:HI 1 "general_operand" "vim") - (match_operand:HI 2 "general_operand" "vim")]) + [(match_operand:HI 1 "rl78_general_operand" "vim") + (match_operand:HI 2 "rl78_general_operand" "vim")]) (label_ref (match_operand 3 "" "")) (pc)))] "rl78_virt_insns_ok ()" diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c index 6b199a6ea0f..4cf271c9b83 100644 --- a/gcc/config/rl78/rl78.c +++ b/gcc/config/rl78/rl78.c @@ -85,10 +85,14 @@ #include "tm-constrs.h" /* for satisfies_constraint_*(). */ #include "insn-flags.h" /* for gen_*(). */ #include "builtins.h" +#include "stringpool.h" static inline bool is_interrupt_func (const_tree decl); static inline bool is_brk_interrupt_func (const_tree decl); static void rl78_reorg (void); +static const char *rl78_strip_name_encoding (const char *); +static const char *rl78_strip_nonasm_name_encoding (const char *); +static section * rl78_select_section (tree, int, unsigned HOST_WIDE_INT); /* Debugging statements are tagged with DEBUG0 only so that they can @@ -318,6 +322,29 @@ rl78_asm_file_start (void) register_pass (& rl78_move_elim_info); } +void +rl78_output_symbol_ref (FILE * file, rtx sym) +{ + tree type = SYMBOL_REF_DECL (sym); + const char *str = XSTR (sym, 0); + + if (str[0] == '*') + { + fputs (str + 1, file); + } + else + { + str = rl78_strip_nonasm_name_encoding (str); + if (type && TREE_CODE (type) == FUNCTION_DECL) + { + fprintf (file, "%%code("); + assemble_name (file, str); + fprintf (file, ")"); + } + else + assemble_name (file, str); + } +} #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE rl78_option_override @@ -338,6 +365,13 @@ rl78_option_override (void) for (i = 24; i < 32; i++) fixed_regs[i] = 0; } + + if (TARGET_ES0 + && strcmp (lang_hooks.name, "GNU C") + /* Compiling with -flto results in a language of GNU GIMPLE being used... */ + && strcmp (lang_hooks.name, "GNU GIMPLE")) + /* Address spaces are currently only supported by C. */ + error ("-mes0 can only be used with C"); } /* Most registers are 8 bits. Some are 16 bits because, for example, @@ -695,6 +729,51 @@ rl78_handle_func_attribute (tree * node, return NULL_TREE; } +/* Check "naked" attributes. */ +static tree +rl78_handle_naked_attribute (tree * node, + tree name ATTRIBUTE_UNUSED, + tree args, + int flags ATTRIBUTE_UNUSED, + bool * no_add_attrs) +{ + gcc_assert (DECL_P (* node)); + gcc_assert (args == NULL_TREE); + + if (TREE_CODE (* node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "naked attribute only applies to functions"); + * no_add_attrs = true; + } + + /* Disable warnings about this function - eg reaching the end without + seeing a return statement - because the programmer is doing things + that gcc does not know about. */ + TREE_NO_WARNING (* node) = 1; + + return NULL_TREE; +} + +/* Check "saddr" attributes. */ +static tree +rl78_handle_saddr_attribute (tree * node, + tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool * no_add_attrs) +{ + gcc_assert (DECL_P (* node)); + + if (TREE_CODE (* node) == FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute doesn't apply to functions", + name); + * no_add_attrs = true; + } + + return NULL_TREE; +} + #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE rl78_attribute_table @@ -707,7 +786,9 @@ const struct attribute_spec rl78_attribute_table[] = false }, { "brk_interrupt", 0, 0, true, false, false, rl78_handle_func_attribute, false }, - { "naked", 0, 0, true, false, false, rl78_handle_func_attribute, + { "naked", 0, 0, true, false, false, rl78_handle_naked_attribute, + false }, + { "saddr", 0, 0, true, false, false, rl78_handle_saddr_attribute, false }, { NULL, 0, 0, false, false, false, NULL, false } }; @@ -748,6 +829,18 @@ characterize_address (rtx x, rtx *base, rtx *index, rtx *addend) *base = XEXP (x, 0); x = XEXP (x, 1); + if (GET_CODE (*base) == SUBREG) + { + if (GET_MODE (*base) == HImode + && GET_MODE (XEXP (*base, 0)) == SImode + && GET_CODE (XEXP (*base, 0)) == REG) + { + /* This is a throw-away rtx just to tell everyone + else what effective register we're using. */ + *base = gen_rtx_REG (HImode, REGNO (XEXP (*base, 0))); + } + } + if (GET_CODE (*base) != REG && GET_CODE (x) == REG) { @@ -781,6 +874,18 @@ characterize_address (rtx x, rtx *base, rtx *index, rtx *addend) case REG: return false; + case SUBREG: + switch (GET_CODE (XEXP (x, 0))) + { + case CONST: + case SYMBOL_REF: + case CONST_INT: + *addend = x; + return true; + default: + return false; + } + case CONST: case SYMBOL_REF: case CONST_INT: @@ -828,6 +933,27 @@ rl78_hl_b_c_addr_p (rtx op) #define REG_IS(r, regno) (((r) == (regno)) || ((r) >= FIRST_PSEUDO_REGISTER && !(strict))) +/* Return the appropriate mode for a named address address. */ + +#undef TARGET_ADDR_SPACE_ADDRESS_MODE +#define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode + +static enum machine_mode +rl78_addr_space_address_mode (addr_space_t addrspace) +{ + switch (addrspace) + { + case ADDR_SPACE_GENERIC: + return HImode; + case ADDR_SPACE_NEAR: + return HImode; + case ADDR_SPACE_FAR: + return SImode; + default: + gcc_unreachable (); + } +} + /* Used in various constraints and predicates to match operands in the "far" address space. */ int @@ -839,7 +965,7 @@ rl78_far_p (rtx x) fprintf (stderr, "\033[35mrl78_far_p: "); debug_rtx (x); fprintf (stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR); #endif - return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR; + return GET_MODE_BITSIZE (rl78_addr_space_address_mode (MEM_ADDR_SPACE (x))) == 32; } /* Return the appropriate mode for a named address pointer. */ @@ -853,6 +979,8 @@ rl78_addr_space_pointer_mode (addr_space_t addrspace) { case ADDR_SPACE_GENERIC: return HImode; + case ADDR_SPACE_NEAR: + return HImode; case ADDR_SPACE_FAR: return SImode; default: @@ -870,23 +998,6 @@ rl78_valid_pointer_mode (machine_mode m) return (m == HImode || m == SImode); } -/* Return the appropriate mode for a named address address. */ -#undef TARGET_ADDR_SPACE_ADDRESS_MODE -#define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode - -static machine_mode -rl78_addr_space_address_mode (addr_space_t addrspace) -{ - switch (addrspace) - { - case ADDR_SPACE_GENERIC: - return HImode; - case ADDR_SPACE_FAR: - return SImode; - default: - gcc_unreachable (); - } -} #undef TARGET_LEGITIMATE_CONSTANT_P #define TARGET_LEGITIMATE_CONSTANT_P rl78_is_legitimate_constant @@ -906,6 +1017,9 @@ rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x, { rtx base, index, addend; bool is_far_addr = false; + int as_bits; + + as_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (as)); if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNS_ES_ADDR) @@ -914,8 +1028,7 @@ rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x, is_far_addr = true; } - if (as == ADDR_SPACE_GENERIC - && (GET_MODE (x) == SImode || is_far_addr)) + if (as_bits == 16 && is_far_addr) return false; if (! characterize_address (x, &base, &index, &addend)) @@ -925,7 +1038,7 @@ rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x, involving a register during devirtualization, so make sure all such __far addresses do not have addends. This forces GCC to do the sum separately. */ - if (addend && base && as == ADDR_SPACE_FAR) + if (addend && base && as_bits == 32 && GET_MODE (base) == SImode) return false; if (base && index) @@ -956,14 +1069,13 @@ rl78_as_legitimate_address (machine_mode mode ATTRIBUTE_UNUSED, rtx x, static bool rl78_addr_space_subset_p (addr_space_t subset, addr_space_t superset) { - gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR); - gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR); + int subset_bits; + int superset_bits; - if (subset == superset) - return true; + subset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (subset)); + superset_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (superset)); - else - return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR); + return (subset_bits <= superset_bits); } #undef TARGET_ADDR_SPACE_CONVERT @@ -976,29 +1088,44 @@ rl78_addr_space_convert (rtx op, tree from_type, tree to_type) addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type)); addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type)); rtx result; + int to_bits; + int from_bits; - gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR); - gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR); + to_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (to_as)); + from_bits = GET_MODE_BITSIZE (rl78_addr_space_address_mode (from_as)); - if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR) + if (to_bits < from_bits) { + rtx tmp; /* This is unpredictable, as we're truncating off usable address bits. */ + warning (OPT_Waddress, "converting far pointer to near pointer"); result = gen_reg_rtx (HImode); - emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0)); + if (GET_CODE (op) == SYMBOL_REF + || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER)) + tmp = gen_rtx_raw_SUBREG (HImode, op, 0); + else + tmp = simplify_subreg (HImode, op, SImode, 0); + gcc_assert (tmp != NULL_RTX); + emit_move_insn (result, tmp); return result; } - else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC) + else if (to_bits > from_bits) { /* This always works. */ result = gen_reg_rtx (SImode); emit_move_insn (rl78_subreg (HImode, result, SImode, 0), op); - emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx); + if (TREE_CODE (from_type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (from_type)) == FUNCTION_TYPE) + emit_move_insn (rl78_subreg (HImode, result, SImode, 2), const0_rtx); + else + emit_move_insn (rl78_subreg (HImode, result, SImode, 2), GEN_INT (0x0f)); return result; } else - gcc_unreachable (); + return op; + gcc_unreachable (); } /* Implements REGNO_MODE_CODE_OK_FOR_BASE_P. */ @@ -1129,19 +1256,20 @@ rl78_expand_prologue (void) if (TARGET_G10) { if (i != 0) - emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i * 2)); - F (emit_insn (gen_push (gen_rtx_REG (HImode, 0)))); + emit_move_insn (gen_rtx_REG (HImode, AX_REG), gen_rtx_REG (HImode, i * 2)); + F (emit_insn (gen_push (gen_rtx_REG (HImode, AX_REG)))); } else { - int need_bank = i/4; + int need_bank = i / 4; if (need_bank != rb) { emit_insn (gen_sel_rb (GEN_INT (need_bank))); rb = need_bank; } - F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2)))); + F (emit_insn (gen_push (gen_rtx_REG (HImode, i * 2)))); + } } @@ -1205,7 +1333,7 @@ rl78_expand_epilogue (void) if (is_interrupt_func (cfun->decl) && cfun->machine->uses_es) { emit_insn (gen_pop (gen_rtx_REG (HImode, AX_REG))); - emit_insn (gen_movqi_es (gen_rtx_REG (QImode, A_REG))); + emit_insn (gen_movqi_to_es (gen_rtx_REG (QImode, A_REG))); } for (i = 15; i >= 0; i--) @@ -1215,7 +1343,7 @@ rl78_expand_epilogue (void) if (TARGET_G10) { - rtx ax = gen_rtx_REG (HImode, 0); + rtx ax = gen_rtx_REG (HImode, AX_REG); emit_insn (gen_pop (ax)); if (i != 0) @@ -1415,7 +1543,8 @@ rl78_print_operand_1 (FILE * file, rtx op, int letter) if (rl78_far_p (op)) { fprintf (file, "es:"); - op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1)); + if (GET_CODE (XEXP (op, 0)) == UNSPEC) + op = gen_rtx_MEM (GET_MODE (op), XVECEXP (XEXP (op, 0), 0, 1)); } if (letter == 'H') { @@ -1449,13 +1578,15 @@ rl78_print_operand_1 (FILE * file, rtx op, int letter) } if (CONSTANT_P (XEXP (op, 0))) { - fprintf (file, "!"); + if (!rl78_saddr_p (op)) + fprintf (file, "!"); rl78_print_operand_1 (file, XEXP (op, 0), letter); } else if (GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF) { - fprintf (file, "!"); + if (!rl78_saddr_p (op)) + fprintf (file, "!"); rl78_print_operand_1 (file, XEXP (op, 0), letter); } else if (GET_CODE (XEXP (op, 0)) == PLUS @@ -1465,6 +1596,8 @@ rl78_print_operand_1 (FILE * file, rtx op, int letter) rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 1), 'u'); fprintf (file, "["); rl78_print_operand_1 (file, XEXP (XEXP (op, 0), 0), 0); + if (letter == 'p' && GET_CODE (XEXP (op, 0)) == REG) + fprintf (file, "+0"); fprintf (file, "]"); } else @@ -1513,7 +1646,15 @@ rl78_print_operand_1 (FILE * file, rtx op, int letter) else if (letter == 'e') fprintf (file, "%ld", (INTVAL (op) >> 16) & 0xff); else if (letter == 'B') - fprintf (file, "%d", exact_log2 (INTVAL (op))); + { + int ival = INTVAL (op); + if (ival == -128) + ival = 0x80; + if (exact_log2 (ival) >= 0) + fprintf (file, "%d", exact_log2 (ival)); + else + fprintf (file, "%d", exact_log2 (~ival & 0xff)); + } else if (letter == 'E') fprintf (file, "%ld", (INTVAL (op) >> 24) & 0xff); else if (letter == 'm') @@ -1597,6 +1738,27 @@ rl78_print_operand_1 (FILE * file, rtx op, int letter) fprintf (file, ")"); break; + case SUBREG: + if (GET_MODE (op) == HImode + && SUBREG_BYTE (op) == 0) + { + fprintf (file, "%%lo16("); + rl78_print_operand_1 (file, SUBREG_REG (op), 0); + fprintf (file, ")"); + } + else if (GET_MODE (op) == HImode + && SUBREG_BYTE (op) == 2) + { + fprintf (file, "%%hi16("); + rl78_print_operand_1 (file, SUBREG_REG (op), 0); + fprintf (file, ")"); + } + else + { + fprintf (file, "(%s)", GET_RTX_NAME (GET_CODE (op))); + } + break; + case SYMBOL_REF: need_paren = 0; if (letter == 'H') @@ -1620,7 +1782,14 @@ rl78_print_operand_1 (FILE * file, rtx op, int letter) if (letter == 'q' || letter == 'Q') output_operand_lossage ("q/Q modifiers invalid for symbol references"); - output_addr_const (file, op); + if (SYMBOL_REF_DECL (op) && TREE_CODE (SYMBOL_REF_DECL (op)) == FUNCTION_DECL) + { + fprintf (file, "%%code("); + assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0))); + fprintf (file, ")"); + } + else + assemble_name (file, rl78_strip_nonasm_name_encoding (XSTR (op, 0))); if (need_paren) fprintf (file, ")"); break; @@ -2488,12 +2657,12 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before) rtx new_m; rtx seg = rl78_hi8 (XEXP (m, 0)); -#if DEBUG_ALLOC - fprintf (stderr, "setting ES:\n"); - debug_rtx(seg); -#endif - emit_insn_before (EM (gen_movqi (A, seg)), before); - emit_insn_before (EM (gen_movqi_es (A)), before); + if (!TARGET_ES0) + { + emit_insn_before (EM (gen_movqi (A, seg)), before); + emit_insn_before (EM (gen_movqi_to_es (A)), before); + } + record_content (A, NULL_RTX); new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0))); @@ -2505,10 +2674,6 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before) characterize_address (XEXP (m, 0), & base, & index, & addendr); gcc_assert (index == NULL_RTX); -#if DEBUG_ALLOC - fprintf (stderr, "\033[33m"); debug_rtx (m); fprintf (stderr, "\033[0m"); - debug_rtx (base); -#endif if (base == NULL_RTX) return m; @@ -2518,9 +2683,11 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before) gcc_assert (REG_P (base)); gcc_assert (REG_P (newbase)); + int limit = 256 - GET_MODE_SIZE (GET_MODE (m)); + if (REGNO (base) == SP_REG) { - if (addend >= 0 && addend <= 255) + if (addend >= 0 && addend <= limit) return m; } @@ -2529,8 +2696,11 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before) address. */ if (addend < 0 - || (addend > 255 && REGNO (newbase) != 2) - || (addendr && GET_CODE (addendr) != CONST_INT)) + || (addend > limit && REGNO (newbase) != BC_REG) + || (addendr + && (GET_CODE (addendr) != CONST_INT) + && ((REGNO (newbase) != BC_REG)) + )) { /* mov ax, vreg add ax, #imm @@ -2543,6 +2713,7 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before) base = newbase; addend = 0; + addendr = 0; } else { @@ -2554,11 +2725,12 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before) record_content (base, NULL_RTX); base = gen_rtx_PLUS (HImode, base, GEN_INT (addend)); } + else if (addendr) + { + record_content (base, NULL_RTX); + base = gen_rtx_PLUS (HImode, base, addendr); + } -#if DEBUG_ALLOC - fprintf (stderr, "\033[33m"); - debug_rtx (m); -#endif if (need_es) { m = change_address (m, GET_MODE (m), gen_es_addr (base)); @@ -2566,10 +2738,6 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before) } else m = change_address (m, GET_MODE (m), base); -#if DEBUG_ALLOC - debug_rtx (m); - fprintf (stderr, "\033[0m"); -#endif return m; } @@ -2724,7 +2892,13 @@ rl78_alloc_physical_registers_op1 (rtx_insn * insn) { /* If necessary, load the operands into BC and HL. Check to see if we already have OP (0) in HL - and if so, swap the order. */ + and if so, swap the order. + + It is tempting to perform this optimization when OP(0) does + not hold a MEM, but this leads to bigger code in general. + The problem is that if OP(1) holds a MEM then swapping it + into BC means a BC-relative load is used and these 3 bytes + long vs 1 byte for an HL load. */ if (MEM_P (OP (0)) && already_contains (HL, XEXP (OP (0), 0))) { @@ -3811,6 +3985,311 @@ static bool rl78_rtx_costs (rtx x, } + + +static GTY(()) section * saddr_section; +static GTY(()) section * frodata_section; + +int +rl78_saddr_p (rtx x) +{ + const char * c; + + if (MEM_P (x)) + x = XEXP (x, 0); + if (GET_CODE (x) == PLUS) + x = XEXP (x, 0); + if (GET_CODE (x) != SYMBOL_REF) + return 0; + + c = XSTR (x, 0); + if (memcmp (c, "@s.", 3) == 0) + return 1; + + return 0; +} + +int +rl78_sfr_p (rtx x) +{ + if (MEM_P (x)) + x = XEXP (x, 0); + if (GET_CODE (x) != CONST_INT) + return 0; + + if ((INTVAL (x) & 0xFF00) != 0xFF00) + return 0; + + return 1; +} + +#undef TARGET_STRIP_NAME_ENCODING +#define TARGET_STRIP_NAME_ENCODING rl78_strip_name_encoding + +static const char * +rl78_strip_name_encoding (const char * sym) +{ + while (1) + { + if (*sym == '*') + sym++; + else if (*sym == '@' && sym[2] == '.') + sym += 3; + else + return sym; + } +} + +/* Like rl78_strip_name_encoding, but does not strip leading asterisks. This + is important if the stripped name is going to be passed to assemble_name() + as that handles asterisk prefixed names in a special manner. */ + +static const char * +rl78_strip_nonasm_name_encoding (const char * sym) +{ + while (1) + { + if (*sym == '@' && sym[2] == '.') + sym += 3; + else + return sym; + } +} + + +static int +rl78_attrlist_to_encoding (tree list, tree decl ATTRIBUTE_UNUSED) +{ + while (list) + { + if (is_attribute_p ("saddr", TREE_PURPOSE (list))) + return 's'; + list = TREE_CHAIN (list); + } + + return 0; +} + +#define RL78_ATTRIBUTES(decl) \ + (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \ + : DECL_ATTRIBUTES (decl) \ + ? (DECL_ATTRIBUTES (decl)) \ + : TYPE_ATTRIBUTES (TREE_TYPE (decl)) + +#undef TARGET_ENCODE_SECTION_INFO +#define TARGET_ENCODE_SECTION_INFO rl78_encode_section_info + +static void +rl78_encode_section_info (tree decl, rtx rtl, int first) +{ + rtx rtlname; + const char * oldname; + char encoding; + char * newname; + tree idp; + tree type; + tree rl78_attributes; + + if (!first) + return; + + rtlname = XEXP (rtl, 0); + + if (GET_CODE (rtlname) == SYMBOL_REF) + oldname = XSTR (rtlname, 0); + else if (GET_CODE (rtlname) == MEM + && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) + oldname = XSTR (XEXP (rtlname, 0), 0); + else + gcc_unreachable (); + + type = TREE_TYPE (decl); + if (type == error_mark_node) + return; + if (! DECL_P (decl)) + return; + rl78_attributes = RL78_ATTRIBUTES (decl); + + encoding = rl78_attrlist_to_encoding (rl78_attributes, decl); + + if (encoding) + { + newname = (char *) alloca (strlen (oldname) + 4); + sprintf (newname, "@%c.%s", encoding, oldname); + idp = get_identifier (newname); + XEXP (rtl, 0) = + gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); + SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl); + SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl); + } +} + +#undef TARGET_ASM_INIT_SECTIONS +#define TARGET_ASM_INIT_SECTIONS rl78_asm_init_sections + +static void +rl78_asm_init_sections (void) +{ + saddr_section + = get_unnamed_section (SECTION_WRITE, output_section_asm_op, + "\t.section .saddr,\"aw\",@progbits"); + frodata_section + = get_unnamed_section (SECTION_WRITE, output_section_asm_op, + "\t.section .frodata,\"aw\",@progbits"); +} + +#undef TARGET_ASM_SELECT_SECTION +#define TARGET_ASM_SELECT_SECTION rl78_select_section + +static section * +rl78_select_section (tree decl, + int reloc ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) +{ + int readonly = 1; + + switch (TREE_CODE (decl)) + { + case VAR_DECL: + if (!TREE_READONLY (decl) + || TREE_SIDE_EFFECTS (decl) + || !DECL_INITIAL (decl) + || (DECL_INITIAL (decl) != error_mark_node + && !TREE_CONSTANT (DECL_INITIAL (decl)))) + readonly = 0; + break; + case CONSTRUCTOR: + if (! TREE_CONSTANT (decl)) + readonly = 0; + break; + + default: + break; + } + + if (TREE_CODE (decl) == VAR_DECL) + { + const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); + + if (name[0] == '@' && name[2] == '.') + switch (name[1]) + { + case 's': + return saddr_section; + } + + if (TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_FAR + && readonly) + { + return frodata_section; + } + } + + if (readonly) + return readonly_data_section; + + return data_section; +} + +void +rl78_output_labelref (FILE *file, const char *str) +{ + const char *str2; + + str2 = targetm.strip_name_encoding (str); + if (str2[0] != '.') + fputs (user_label_prefix, file); + fputs (str2, file); +} + +void +rl78_output_aligned_common (FILE *stream, + tree decl ATTRIBUTE_UNUSED, + const char *name, + int size, int align, int global) +{ + /* We intentionally don't use rl78_section_tag() here. */ + if (name[0] == '@' && name[2] == '.') + { + const char *sec = 0; + switch (name[1]) + { + case 's': + switch_to_section (saddr_section); + sec = ".saddr"; + break; + } + if (sec) + { + const char *name2; + int p2align = 0; + + while (align > BITS_PER_UNIT) + { + align /= 2; + p2align ++; + } + name2 = targetm.strip_name_encoding (name); + if (global) + fprintf (stream, "\t.global\t_%s\n", name2); + fprintf (stream, "\t.p2align %d\n", p2align); + fprintf (stream, "\t.type\t_%s,@object\n", name2); + fprintf (stream, "\t.size\t_%s,%d\n", name2, size); + fprintf (stream, "_%s:\n\t.zero\t%d\n", name2, size); + return; + } + } + + if (!global) + { + fprintf (stream, "\t.local\t"); + assemble_name (stream, name); + fprintf (stream, "\n"); + } + fprintf (stream, "\t.comm\t"); + assemble_name (stream, name); + fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT); +} + +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES rl78_insert_attributes + +static void +rl78_insert_attributes (tree decl, tree *attributes ATTRIBUTE_UNUSED) +{ + if (TARGET_ES0 + && TREE_CODE (decl) == VAR_DECL + && TREE_READONLY (decl) + && TREE_ADDRESSABLE (decl) + && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_GENERIC) + { + tree type = TREE_TYPE (decl); + tree attr = TYPE_ATTRIBUTES (type); + int q = TYPE_QUALS_NO_ADDR_SPACE (type) | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_FAR); + + TREE_TYPE (decl) = build_type_attribute_qual_variant (type, attr, q); + } +} + +#undef TARGET_ASM_INTEGER +#define TARGET_ASM_INTEGER rl78_asm_out_integer + +static bool +rl78_asm_out_integer (rtx x, unsigned int size, int aligned_p) +{ + if (default_assemble_integer (x, size, aligned_p)) + return true; + + if (size == 4) + { + assemble_integer_with_op (".long\t", x); + return true; + } + + return false; +} + + #undef TARGET_UNWIND_WORD_MODE #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode @@ -3820,7 +4299,111 @@ rl78_unwind_word_mode (void) return HImode; } - +#ifndef USE_COLLECT2 +#undef TARGET_ASM_CONSTRUCTOR +#define TARGET_ASM_CONSTRUCTOR rl78_asm_constructor +#undef TARGET_ASM_DESTRUCTOR +#define TARGET_ASM_DESTRUCTOR rl78_asm_destructor + +static void +rl78_asm_ctor_dtor (rtx symbol, int priority, bool is_ctor) +{ + section *sec; + + if (priority != DEFAULT_INIT_PRIORITY) + { + /* This section of the function is based upon code copied + from: gcc/varasm.c:get_cdtor_priority_section(). */ + char buf[16]; + + sprintf (buf, "%s.%.5u", is_ctor ? ".ctors" : ".dtors", + MAX_INIT_PRIORITY - priority); + sec = get_section (buf, 0, NULL); + } + else + sec = is_ctor ? ctors_section : dtors_section; + + assemble_addr_to_section (symbol, sec); +} + +static void +rl78_asm_constructor (rtx symbol, int priority) +{ + rl78_asm_ctor_dtor (symbol, priority, true); +} + +static void +rl78_asm_destructor (rtx symbol, int priority) +{ + rl78_asm_ctor_dtor (symbol, priority, false); +} +#endif /* ! USE_COLLECT2 */ + +/* Scan backwards through the insn chain looking to see if the flags + have been set for a comparison of OP against OPERAND. Start with + the insn *before* the current insn. */ + +bool +rl78_flags_already_set (rtx op, rtx operand) +{ + /* We only track the Z flag. */ + if (GET_CODE (op) != EQ && GET_CODE (op) != NE) + return false; + + /* This should not happen, but let's be paranoid. */ + if (current_output_insn == NULL_RTX) + return false; + + rtx_insn *insn; + bool res = false; + + for (insn = prev_nonnote_nondebug_insn (current_output_insn); + insn != NULL_RTX; + insn = prev_nonnote_nondebug_insn (insn)) + { + if (LABEL_P (insn)) + break; + + if (! INSN_P (insn)) + continue; + + /* Make sure that the insn can be recognized. */ + if (recog_memoized (insn) == -1) + continue; + + enum attr_update_Z updated = get_attr_update_Z (insn); + + rtx set = single_set (insn); + bool must_break = (set != NULL_RTX && rtx_equal_p (operand, SET_DEST (set))); + + switch (updated) + { + case UPDATE_Z_NO: + break; + case UPDATE_Z_CLOBBER: + must_break = true; + break; + case UPDATE_Z_UPDATE_Z: + res = must_break; + must_break = true; + break; + default: + gcc_unreachable (); + } + + if (must_break) + break; + } + + /* We have to re-recognize the current insn as the call(s) to + get_attr_update_Z() above will have overwritten the recog_data cache. */ + recog_memoized (current_output_insn); + cleanup_subreg_operands (current_output_insn); + constrain_operands_cached (current_output_insn, 1); + + return res; +} + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-rl78.h" diff --git a/gcc/config/rl78/rl78.h b/gcc/config/rl78/rl78.h index f1f719a6cdd..d7ec21c0c85 100644 --- a/gcc/config/rl78/rl78.h +++ b/gcc/config/rl78/rl78.h @@ -134,7 +134,8 @@ #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 -#define ADDR_SPACE_FAR 1 +#define ADDR_SPACE_NEAR 1 +#define ADDR_SPACE_FAR 2 #define HAVE_PRE_DECCREMENT 0 #define HAVE_POST_INCREMENT 0 @@ -241,6 +242,8 @@ enum reg_class "ALL_REGS" \ } +/* Note that no class may include the second register in $fp, because + we treat $fp as a single HImode register. */ #define REG_CLASS_CONTENTS \ { \ { 0x00000000, 0x00000000 }, /* No registers, */ \ @@ -424,6 +427,16 @@ typedef unsigned int CUMULATIVE_ARGS; fprintf (FILE, "\t.long .L%d - 1b\n", VALUE) +#define ASM_OUTPUT_SYMBOL_REF(FILE, SYM) rl78_output_symbol_ref ((FILE), (SYM)) + +#define ASM_OUTPUT_LABELREF(FILE, SYM) rl78_output_labelref ((FILE), (SYM)) + +#define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGNMENT) \ + rl78_output_aligned_common (STREAM, DECL, NAME, SIZE, ALIGNMENT, 1) + +#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \ + rl78_output_aligned_common (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0) + #define ASM_OUTPUT_ALIGN(STREAM, LOG) \ do \ { \ diff --git a/gcc/config/rl78/rl78.opt b/gcc/config/rl78/rl78.opt index ba94201bfd4..1e4c14c706e 100644 --- a/gcc/config/rl78/rl78.opt +++ b/gcc/config/rl78/rl78.opt @@ -53,3 +53,7 @@ Enable assembler and linker relaxation. Enabled by default at -Os. mg10 Target Mask(G10) Report Target the RL78/G10 series + +mes0 +Target Mask(ES0) +Assume ES is zero throughout program execution, use ES: for read-only data.