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)
 {
