Various fixes for far memory addressing (and large programs in general).  
Committed.

        * config/rl78/constraints.md (Wfr): Change to be a non-memory
        constraint.
        * config/rl78/rl78-protos.h (rl78_one_far_p): Declare.
        * config/rl78/rl78.c (rl78_one_far_p): Define.
        * config/rl78/rl78-virt (movqi_virt): Fix far memory
        alternatives.
        (movhi_virt): Likewise.
        (zero_extendqihi2_virt): Likewise.
        (extendqihi2_virt): Likewise.
        (add<mode>3_virt): Likewise.
        (sub<mode>3_virt): Likewise.
        (andqi3_virt): Likewise.
        (iorqi3_virt): Likewise.
        (xorqi3_virt): Likewise.
        * config/rl78/rl78-real.md (bf,br): Use long forms to avoid reloc
        overflow in large files.

Index: gcc/config/rl78/constraints.md
===================================================================
--- gcc/config/rl78/constraints.md      (revision 231385)
+++ gcc/config/rl78/constraints.md      (working copy)
@@ -361,13 +361,13 @@
 (define_memory_constraint "Ws1"
   "es:word8[SP]"
   (match_test "(rl78_es_addr (op) && satisfies_constraint_Cs1 (rl78_es_base 
(op)))
                || satisfies_constraint_Cs1 (op)")
   )
 
-(define_memory_constraint "Wfr"
+(define_constraint "Wfr"
   "ES/CS far pointer"
   (and (match_code "mem")
        (match_test "rl78_far_p (op)"))
   )
 
 (define_memory_constraint "Wsa"
Index: gcc/config/rl78/rl78-protos.h
===================================================================
--- gcc/config/rl78/rl78-protos.h       (revision 231385)
+++ gcc/config/rl78/rl78-protos.h       (working copy)
@@ -51,6 +51,8 @@ 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);
+
+int            rl78_one_far_p (rtx *operands, int num_operands);
Index: gcc/config/rl78/rl78-real.md
===================================================================
--- gcc/config/rl78/rl78-real.md        (revision 231385)
+++ gcc/config/rl78/rl78-real.md        (working copy)
@@ -586,25 +586,25 @@
        (if_then_else (eq (and (reg:QI A_REG)
                               (match_operand 0 "immediate_operand" "n"))
                          (const_int 0))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
   ""
-  "bf\tA.%B0, $%1"
+  "bt\tA.%B0, $1f\n\tbr !!%1\n\t1:"
   [(set (attr "update_Z") (const_string "clobber"))]
 )
 
 (define_insn "bt"
   [(set (pc)
        (if_then_else (ne (and (reg:QI A_REG)
                               (match_operand 0 "immediate_operand" "n"))
                          (const_int 0))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
   ""
-  "bt\tA.%B0, $%1"
+  "bf\tA.%B0, $1f\n\tbr !!%1\n\t1:"
   [(set (attr "update_Z") (const_string "clobber"))]
 )
 
 ;; NOTE: These peepholes are fragile.  They rely upon GCC generating
 ;; a specific sequence on insns, based upon examination of test code.
 ;; Improvements to GCC or using code other than the test code can result
Index: gcc/config/rl78/rl78-virt.md
===================================================================
--- gcc/config/rl78/rl78-virt.md        (revision 231385)
+++ gcc/config/rl78/rl78-virt.md        (working copy)
@@ -39,14 +39,14 @@
   "rl78_virt_insns_ok ()"
   "v.mov %0, %1"
   [(set_attr "valloc" "op1")]
 )
 
 (define_insn "*movqi_virt"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=vY,v,Wfr")
-       (match_operand    1 "general_operand" "vInt8J,YWfr,vInt8J"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=vY,v,*Wfr,Y,*Wfr,*Wfr")
+       (match_operand    1 "general_operand" 
"vInt8JY,*Wfr,vInt8J,*Wfr,Y,*Wfr"))]
   "rl78_virt_insns_ok ()"
   "v.mov %0, %1"
   [(set_attr "valloc" "op1")]
 )
 
 (define_insn "*movhi_virt_mm"
@@ -55,33 +55,33 @@
   "rl78_virt_insns_ok ()"
   "v.movw %0, %1"
   [(set_attr "valloc" "op1")]
 )
 
 (define_insn "*movhi_virt"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=vS,  Y,   v,   Wfr")
-       (match_operand:HI 1 "general_operand"      "viYS, viS, Wfr, vi"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=vS,  Y,   v,   *Wfr")
+       (match_operand:HI 1 "general_operand"      "viYS, viS, *Wfr, vi"))]
   "rl78_virt_insns_ok ()"
   "v.movw %0, %1"
   [(set_attr "valloc" "op1")]
 )
 
 ;;---------- Conversions ------------------------
 
 (define_insn "*zero_extendqihi2_virt"
-  [(set (match_operand:HI                 0 "rl78_nonfar_nonimm_operand" "=vm")
-       (zero_extend:HI (match_operand:QI 1 "general_operand" "vim")))]
-  "rl78_virt_insns_ok ()"
+  [(set (match_operand:HI                 0 "rl78_nonfar_nonimm_operand" 
"=vY,*Wfr")
+       (zero_extend:HI (match_operand:QI 1 "general_operand" "vim,viY")))]
+  "rl78_virt_insns_ok () && rl78_one_far_p (operands, 2)"
   "v.zero_extend\t%0, %1"
   [(set_attr "valloc" "op1")]
   )
 
 (define_insn "*extendqihi2_virt"
-  [(set (match_operand:HI                 0 "rl78_nonfar_nonimm_operand" "=vm")
-       (sign_extend:HI (match_operand:QI 1 "general_operand" "vim")))]
-  "rl78_virt_insns_ok ()"
+  [(set (match_operand:HI                 0 "rl78_nonfar_nonimm_operand" 
"=vY,*Wfr")
+       (sign_extend:HI (match_operand:QI 1 "general_operand" "vim,viY")))]
+  "rl78_virt_insns_ok () && rl78_one_far_p (operands, 2)"
   "v.sign_extend\t%0, %1"
   [(set_attr "valloc" "op1")]
   )
 
 ;;---------- Arithmetic ------------------------
 
@@ -92,26 +92,26 @@
    ]
   "rl78_virt_insns_ok ()"
   "v.inc\t%0, %1, %2"
 )
 
 (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 "rl78_general_operand" "vim,i")))
+  [(set (match_operand:QHI           0 "rl78_nonimmediate_operand" "=vY,  S, 
*Wfr,  vY")
+       (plus:QHI (match_operand:QHI 1 "rl78_general_operand"      "%viY, 0, 
0viY, *Wfr")
+                 (match_operand:QHI 2 "rl78_general_operand"       "vim, i, 
viY,  viY")))
    ]
-  "rl78_virt_insns_ok ()"
+  "rl78_virt_insns_ok () && rl78_one_far_p (operands, 3)"
   "v.add\t%0, %1, %2"
 )
 
 (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 "rl78_general_operand" "vim,i")))
+  [(set (match_operand:QHI            0 "rl78_nonimmediate_operand" "=vY, S, 
*Wfr,  vY")
+       (minus:QHI (match_operand:QHI 1 "rl78_general_operand"      "viY, 0, 
0viY, *Wfr")
+                  (match_operand:QHI 2 "rl78_general_operand"      "vim, i, 
viY,  viY")))
    ]
-  "rl78_virt_insns_ok ()"
+  "rl78_virt_insns_ok () && rl78_one_far_p (operands, 3)"
   "v.sub\t%0, %1, %2"
 )
 
 (define_insn "*umulhi3_shift_virt"
   [(set (match_operand:HI          0 "register_operand" "=v")
         (mult:HI (match_operand:HI 1 "rl78_nonfar_operand" "%vim")
@@ -128,35 +128,35 @@
   "rl78_virt_insns_ok () && !TARGET_G10"
   "v.mulu\t%0, %2"
   [(set_attr "valloc" "umul")]
 )
 
 (define_insn "*andqi3_virt"
-  [(set (match_operand:QI         0 "rl78_nonimmediate_operand" "=vm")
-       (and:QI (match_operand:QI 1 "rl78_general_operand" "vim")
-               (match_operand:QI 2 "rl78_general_operand" "vim")))
+  [(set (match_operand:QI         0 "rl78_nonimmediate_operand" "=vm,  *Wfr,  
vY")
+       (and:QI (match_operand:QI 1 "rl78_general_operand"      "%vim, 0viY, 
*Wfr")
+               (match_operand:QI 2 "rl78_general_operand"      "vim,  viY,  
viY")))
    ]
-  "rl78_virt_insns_ok ()"
+  "rl78_virt_insns_ok () && rl78_one_far_p (operands, 3)"
   "v.and\t%0, %1, %2"
 )
 
 (define_insn "*iorqi3_virt"
-  [(set (match_operand:QI         0 "rl78_nonimmediate_operand" "=vm")
-       (ior:QI (match_operand:QI 1 "rl78_general_operand" "vim")
-               (match_operand:QI 2 "rl78_general_operand" "vim")))
+  [(set (match_operand:QI         0 "rl78_nonimmediate_operand" "=vm,  *Wfr,  
vY")
+       (ior:QI (match_operand:QI 1 "rl78_general_operand"      "%vim, 0viY, 
*Wfr")
+               (match_operand:QI 2 "rl78_general_operand"      "vim,  viY,  
viY")))
    ]
-  "rl78_virt_insns_ok ()"
+  "rl78_virt_insns_ok () && rl78_one_far_p (operands, 3)"
   "v.or\t%0, %1, %2"
 )
 
 (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 "rl78_general_operand" "i,vm,vim")))
+  [(set (match_operand:QI         0 "rl78_nonimmediate_operand" "=vm,  *Wfr,  
vY")
+       (xor:QI (match_operand:QI 1 "rl78_general_operand"      "%vim, 0viY, 
*Wfr")
+               (match_operand    2 "rl78_general_operand"      "vim,  viY,  
viY")))
    ]
-  "rl78_virt_insns_ok ()"
+  "rl78_virt_insns_ok () && rl78_one_far_p (operands, 3)"
   "v.xor\t%0, %1, %2"
 )
 
 ;;---------- Shifts ------------------------
 
 (define_insn "*ashl<mode>3_virt"
Index: gcc/config/rl78/rl78.c
===================================================================
--- gcc/config/rl78/rl78.c      (revision 231385)
+++ gcc/config/rl78/rl78.c      (working copy)
@@ -607,12 +607,30 @@ rl78_force_nonfar_3 (rtx *operands, rtx 
   emit_insn (gen (operands[0], operands[1], operands[2]));
   if (temp_reg)
     emit_move_insn (temp_reg, operands[0]);
   return 1;
 }
 
+int
+rl78_one_far_p (rtx *operands, int n)
+{
+  rtx which = NULL;
+  int i, c = 0;
+
+  for (i = 0; i < n; i ++)
+    if (rl78_far_p (operands[i]))
+      {
+       if (which == NULL)
+         which = operands[i];
+       else if (rtx_equal_p (operands[i], which))
+         continue;
+       c ++;
+      }
+  return c <= 1;
+}
+
 #undef  TARGET_CAN_ELIMINATE
 #define TARGET_CAN_ELIMINATE           rl78_can_eliminate
 
 static bool
 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to 
ATTRIBUTE_UNUSED)
 {

Reply via email to