aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2015-01-16 21:57:53 -0500
committerDJ Delorie <dj@gcc.gnu.org>2015-01-16 21:57:53 -0500
commit48c528ae3a2fddd58a7e45b9ef334b42c1ea1686 (patch)
treea6dc530575b555ad5687e67f0b30f6cfa3c387ff
parentd31b87976f1722476ae6bfa8e6bcbf78f5350867 (diff)
downloadgcc-48c528ae3a2fddd58a7e45b9ef334b42c1ea1686.zip
gcc-48c528ae3a2fddd58a7e45b9ef334b42c1ea1686.tar.gz
gcc-48c528ae3a2fddd58a7e45b9ef334b42c1ea1686.tar.bz2
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 (add<mode>3_virt): Likewise. (sub<mode>3_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 <nickc@redhat.com> From-SVN: r219791
-rw-r--r--gcc/ChangeLog102
-rw-r--r--gcc/config/rl78/constraints.md33
-rw-r--r--gcc/config/rl78/predicates.md39
-rw-r--r--gcc/config/rl78/rl78-c.c1
-rw-r--r--gcc/config/rl78/rl78-expand.md18
-rw-r--r--gcc/config/rl78/rl78-protos.h8
-rw-r--r--gcc/config/rl78/rl78-real.md201
-rw-r--r--gcc/config/rl78/rl78-virt.md20
-rw-r--r--gcc/config/rl78/rl78.c721
-rw-r--r--gcc/config/rl78/rl78.h15
-rw-r--r--gcc/config/rl78/rl78.opt4
11 files changed, 1001 insertions, 161 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4f0414a..9b9053a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,105 @@
+2015-01-16 DJ Delorie <dj@redhat.com>
+ Nick Clifton <nickc@redhat.com>
+
+ * 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 (add<mode>3_virt): Likewise.
+ (sub<mode>3_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 <maxim.kuvyrkov@linaro.org>
* 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 c6cc1a8..209f1e6 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 af10ebd..b89eed2 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
;; <http://www.gnu.org/licenses/>.
-(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 8c5d00c..c8410cd 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 219f2c0..ac3939d 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 0a5934e..56d3649 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 f92a0756..8ec2f3d 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 c24b939..fadcbc5 100644
--- a/gcc/config/rl78/rl78-virt.md
+++ b/gcc/config/rl78/rl78-virt.md
@@ -88,7 +88,7 @@
(define_insn "*add<mode>3_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 "*sub<mode>3_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 6b199a6..4cf271c 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 f1f719a..d7ec21c 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 ba94201..1e4c14c 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.