Index: gcc/config/score/t-score-elf
===================================================================
--- gcc/config/score/t-score-elf	(revision 120252)
+++ gcc/config/score/t-score-elf	(working copy)
@@ -35,7 +35,7 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
 # without the $gp register.
 TARGET_LIBGCC2_CFLAGS = -G 0
 
-MULTILIB_OPTIONS = fPIC mel mscore7
+MULTILIB_OPTIONS = mmac mel fPIC
 MULTILIB_MATCHES = fPIC=fpic
 
 EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
@@ -43,4 +43,3 @@ EXTRA_MULTILIB_PARTS = crtbegin.o crtend
 LIBGCC = stmp-multilib
 INSTALL_LIBGCC = install-multilib
 
-
Index: gcc/config/score/crti.asm
===================================================================
--- gcc/config/score/crti.asm	(revision 120252)
+++ gcc/config/score/crti.asm	(working copy)
@@ -43,8 +43,8 @@
         .mask   0x00000000, 0
 _start:
         la      r28, _gp
-        la      r8, __bss_start
-        la      r9, __bss_end__
+        la      r8, _bss_start
+        la      r9, _bss_end__
         sub!    r9, r8
         srli!   r9, 2
         addi    r9, -1
@@ -91,8 +91,8 @@ _fini:
         .mask   0x00000000,0
 _start:
         la      r28, _gp
-        la      r8, __bss_start
-        la      r9, __bss_end__
+        la      r8, _bss_start
+        la      r9, _bss_end__
         sub!    r9, r8
         srli!   r9, 2
         addi    r9, -1
@@ -102,15 +102,10 @@ _start:
         sw      r9, [r8]+, 4
         bcnz    1b
         la      r0, _stack
-#       jl      _init
-#       la      r4, _end
-#       jl      _init_argv
         ldiu!   r4, 0
         ldiu!   r5, 0
-#       jl      main
         la      r29, main
         brl     r29
-#       jl      exit
         la      r29, exit
         brl     r29
         .end    _start
Index: gcc/config/score/predicates.md
===================================================================
--- gcc/config/score/predicates.md	(revision 120252)
+++ gcc/config/score/predicates.md	(working copy)
@@ -35,13 +35,11 @@
   (ior (match_operand 0 "const_call_insn_operand")
        (match_operand 0 "register_operand")))
 
-(define_predicate "const_bi_operand"
-  (and (match_code "const_int")
-       (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'J')")))
-
-(define_predicate "pindex_off_operand"
-  (and (match_code "const_int")
-       (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'P')")))
+(define_predicate "const_uimm5"
+  (match_code "const_int")
+{
+  return IMM_IN_RANGE (INTVAL (op), 5, 0);
+})
 
 (define_predicate "hireg_operand"
   (and (match_code "reg")
@@ -51,6 +49,10 @@
   (and (match_code "reg")
        (match_test "REGNO (op) == LO_REGNUM")))
 
+(define_predicate "sr0_operand"
+  (and (match_code "reg")
+       (match_test "REGNO (op) == CN_REGNUM")))
+
 (define_predicate "g32reg_operand"
   (and (match_code "reg")
        (match_test "GP_REG_P (REGNO (op))")))
@@ -61,3 +63,26 @@
 (define_predicate "branch_nz_operator"
   (match_code "eq,ne,lt,ge"))
 
+(define_predicate "const_simm12"
+  (match_code "const_int")
+{
+  return IMM_IN_RANGE (INTVAL (op), 12, 1);
+})
+
+(define_predicate "const_simm15"
+  (match_code "const_int")
+{
+  return IMM_IN_RANGE (INTVAL (op), 15, 1);
+})
+
+(define_predicate "const_pow2"
+  (match_code "const_int")
+{
+  return IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) INTVAL (op), 0, 31);
+})
+
+(define_predicate "const_npow2"
+  (match_code "const_int")
+{
+  return IMM_IS_POW_OF_2 (~(unsigned HOST_WIDE_INT) INTVAL (op), 0, 31);
+})
Index: gcc/config/score/score-version.h
===================================================================
--- gcc/config/score/score-version.h	(revision 120252)
+++ gcc/config/score/score-version.h	(working copy)
@@ -18,4 +18,4 @@
    the Free Software Foundation, 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.  */
 
-#define SCORE_GCC_VERSION "1.1"
+#define SCORE_GCC_VERSION "1.2"
Index: gcc/config/score/crtn.asm
===================================================================
--- gcc/config/score/crtn.asm	(revision 120252)
+++ gcc/config/score/crtn.asm	(working copy)
@@ -59,4 +59,3 @@
         br      r3
 #endif
 
-
Index: gcc/config/score/score-protos.h
===================================================================
--- gcc/config/score/score-protos.h	(revision 120252)
+++ gcc/config/score/score-protos.h	(working copy)
@@ -36,7 +36,7 @@ enum reg_class score_preferred_reload_cl
 enum reg_class score_secondary_reload_class (enum reg_class class,
                                              enum machine_mode mode, rtx x);
 
-int score_const_ok_for_letter_p (int value, char c);
+int score_const_ok_for_letter_p (HOST_WIDE_INT value, char c);
 
 int score_extra_constraint (rtx op, char c);
 
Index: gcc/config/score/misc.md
===================================================================
--- gcc/config/score/misc.md	(revision 120252)
+++ gcc/config/score/misc.md	(working copy)
@@ -84,8 +84,8 @@
   [(set (match_operand:SI 0 "register_operand" "=d")
         (if_then_else:SI (match_operator 1 "comparison_operator"
                           [(reg:CC CC_REGNUM) (const_int 0)])
-                         (match_operand:SI 2 "register_operand" "d")
-                         (match_operand:SI 3 "register_operand" "0")))]
+                         (match_operand:SI 2 "arith_operand" "d")
+                         (match_operand:SI 3 "arith_operand" "0")))]
   ""
   "mv%C1   %0, %2"
   [(set_attr "type" "cndmv")
@@ -95,7 +95,7 @@
   [(set (reg:CC_NZ CC_REGNUM)
         (compare:CC_NZ (unspec:SI
                         [(match_operand:SI 0 "register_operand" "*e,d")
-                         (match_operand:SI 1 "const_bi_operand" "")]
+                         (match_operand:SI 1 "const_uimm5" "")]
                         BITTST)
                        (const_int 0)))]
   ""
@@ -106,3 +106,312 @@
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
 
+(define_expand "extzv"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (zero_extract (match_operand:SI 1 "memory_operand" "")
+                      (match_operand:SI 2 "immediate_operand" "")
+                      (match_operand:SI 3 "immediate_operand" "")))]
+  "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN"
+{
+  if (mdx_unaligned_load (operands))
+    DONE;
+  else
+    FAIL;
+})
+
+(define_expand "insv"
+  [(set (zero_extract (match_operand:SI 0 "memory_operand" "")
+                      (match_operand:SI 1 "immediate_operand" "")
+                      (match_operand:SI 2 "immediate_operand" ""))
+        (match_operand:SI 3 "register_operand" ""))]
+  "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN"
+{
+  if (mdx_unaligned_store (operands))
+    DONE;
+  else
+    FAIL;
+})
+
+(define_expand "extv"
+  [(set (match_operand:SI 0 "register_operand" "")
+        (sign_extract (match_operand:SI 1 "memory_operand" "")
+                      (match_operand:SI 2 "immediate_operand" "")
+                      (match_operand:SI 3 "immediate_operand" "")))]
+  "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN"
+{
+  if (mdx_unaligned_load (operands))
+    DONE;
+  else
+    FAIL;
+})
+
+(define_expand "movmemsi"
+  [(parallel [(set (match_operand:BLK 0 "general_operand")
+                   (match_operand:BLK 1 "general_operand"))
+              (use (match_operand:SI 2 ""))
+              (use (match_operand:SI 3 "const_int_operand"))])]
+  "!TARGET_SCORE5U"
+{
+  if (mdx_block_move (operands))
+    DONE;
+  else
+    FAIL;
+})
+
+(define_insn "move_lbu_a"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (match_operand:QI 3 "register_operand" "=d")
+        (mem:QI (match_dup 1)))]
+  "!TARGET_SCORE5U"
+  "lbu     %3, [%1]+, %2"
+  [(set_attr "type" "load")
+   (set_attr "mode" "QI")])
+
+(define_insn "move_lhu_a"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (match_operand:HI 3 "register_operand" "=d")
+        (mem:HI (match_dup 1)))]
+  "!TARGET_SCORE5U"
+  "lhu     %3, [%1]+, %2"
+  [(set_attr "type" "load")
+   (set_attr "mode" "HI")])
+
+(define_insn "move_lw_a"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (match_operand:SI 3 "register_operand" "=d")
+        (mem:SI (match_dup 1)))]
+  "!TARGET_SCORE5U"
+  "lw      %3, [%1]+, %2"
+  [(set_attr "type" "load")
+   (set_attr "mode" "SI")])
+
+(define_insn "move_sb_a"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (mem:QI (match_dup 1))
+        (match_operand:QI 3 "register_operand" "d"))]
+  "!TARGET_SCORE5U"
+  "sb      %3, [%1]+, %2"
+  [(set_attr "type" "store")
+   (set_attr "mode" "QI")])
+
+(define_insn "move_sh_a"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (mem:HI (match_dup 1))
+        (match_operand:HI 3 "register_operand" "d"))]
+  "!TARGET_SCORE5U"
+  "sh      %3, [%1]+, %2"
+  [(set_attr "type" "store")
+   (set_attr "mode" "HI")])
+
+(define_insn "move_sw_a"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (mem:SI (match_dup 1))
+        (match_operand:SI 3 "register_operand" "d"))]
+  "!TARGET_SCORE5U"
+  "sw      %3, [%1]+, %2"
+  [(set_attr "type" "store")
+   (set_attr "mode" "SI")])
+
+(define_insn "move_lbu_b"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (match_operand:QI 3 "register_operand" "=d")
+        (mem:QI (plus:SI (match_dup 1)
+                         (match_dup 2))))]
+  "!TARGET_SCORE5U"
+  "lbu     %3, [%1, %2]+"
+  [(set_attr "type" "load")
+   (set_attr "mode" "QI")])
+
+(define_insn "move_lhu_b"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (match_operand:HI 3 "register_operand" "=d")
+        (mem:HI (plus:SI (match_dup 1)
+                         (match_dup 2))))]
+  "!TARGET_SCORE5U"
+  "lhu     %3, [%1, %2]+"
+  [(set_attr "type" "load")
+   (set_attr "mode" "HI")])
+
+(define_insn "move_lw_b"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (match_operand:SI 3 "register_operand" "=d")
+        (mem:SI (plus:SI (match_dup 1)
+                         (match_dup 2))))]
+  "!TARGET_SCORE5U"
+  "lw      %3, [%1, %2]+"
+  [(set_attr "type" "load")
+   (set_attr "mode" "SI")])
+
+(define_insn "move_sb_b"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (mem:QI (plus:SI (match_dup 1)
+                         (match_dup 2)))
+        (match_operand:QI 3 "register_operand" "d"))]
+  "!TARGET_SCORE5U"
+  "sb      %3, [%1, %2]+"
+  [(set_attr "type" "store")
+   (set_attr "mode" "QI")])
+
+(define_insn "move_sh_b"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (mem:HI (plus:SI (match_dup 1)
+                         (match_dup 2)))
+        (match_operand:HI 3 "register_operand" "d"))]
+  "!TARGET_SCORE5U"
+  "sh      %3, [%1, %2]+"
+  [(set_attr "type" "store")
+   (set_attr "mode" "HI")])
+
+(define_insn "move_sw_b"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (match_operand:SI 2 "const_simm12" "")))
+   (set (mem:SI (plus:SI (match_dup 1)
+                         (match_dup 2)))
+        (match_operand:SI 3 "register_operand" "d"))]
+  "!TARGET_SCORE5U"
+  "sw      %3, [%1, %2]+"
+  [(set_attr "type" "store")
+   (set_attr "mode" "SI")])
+
+(define_insn "move_lcb"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (const_int 4)))
+   (set (reg:SI LC_REGNUM)
+        (unspec:SI [(mem:BLK (match_dup 1))] LCB))]
+  "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN"
+  "lcb     [%1]+"
+  [(set_attr "type" "load")
+   (set_attr "mode" "SI")])
+
+(define_insn "move_lcw"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (const_int 4)))
+   (set (match_operand:SI 2 "register_operand" "=d")
+        (unspec:SI [(mem:BLK (match_dup 1))
+                    (reg:SI LC_REGNUM)] LCW))
+   (set (reg:SI LC_REGNUM)
+        (unspec:SI [(mem:BLK (match_dup 1))] LCB))]
+  "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN"
+  "lcw     %2, [%1]+"
+  [(set_attr "type" "load")
+   (set_attr "mode" "SI")])
+
+(define_insn "move_lce"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (const_int 4)))
+   (set (match_operand:SI 2 "register_operand" "=d")
+        (unspec:SI [(mem:BLK (match_dup 1))
+                    (reg:SI LC_REGNUM)] LCE))]
+  "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN"
+  "lce     %2, [%1]+"
+  [(set_attr "type" "load")
+   (set_attr "mode" "SI")])
+
+(define_insn "move_scb"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (const_int 4)))
+   (set (mem:BLK (match_dup 1))
+        (unspec:BLK [(match_operand:SI 2 "register_operand" "d")] SCB))
+   (set (reg:SI SC_REGNUM)
+        (unspec:SI [(match_dup 2)] SCLC))]
+  "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN"
+  "scb     %2, [%1]+"
+  [(set_attr "type" "store")
+   (set_attr "mode" "SI")])
+
+(define_insn "move_scw"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (const_int 4)))
+   (set (mem:BLK (match_dup 1))
+        (unspec:BLK [(match_operand:SI 2 "register_operand" "d")
+                     (reg:SI SC_REGNUM)] SCW))
+   (set (reg:SI SC_REGNUM)
+        (unspec:SI [(match_dup 2)] SCLC))]
+  "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN"
+  "scw     %2, [%1]+"
+  [(set_attr "type" "store")
+   (set_attr "mode" "SI")])
+
+(define_insn "move_sce"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0")
+                 (const_int 4)))
+   (set (mem:BLK (match_dup 1))
+        (unspec:BLK [(reg:SI SC_REGNUM)] SCE))]
+  "!TARGET_SCORE5U && !TARGET_LITTLE_ENDIAN"
+  "sce     [%1]+"
+  [(set_attr "type" "store")
+   (set_attr "mode" "SI")])
+
+(define_insn "andsi3_extzh"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+        (and:SI (match_operand:SI 1 "register_operand" "d")
+                (const_int 65535)))]
+  ""
+  "extzh   %0, %1"
+  [(set_attr "type" "arith")
+   (set_attr "mode" "SI")])
+
+(define_insn "bitclr_c"
+  [(set (match_operand:SI 0 "register_operand" "=e,d")
+        (and:SI (match_operand:SI 1 "register_operand" "0,d")
+                (match_operand:SI 2 "const_npow2")))
+   (clobber (reg:CC CC_REGNUM))]
+  ""
+  "@
+   bitclr!    %0, %F2
+   bitclr.c   %0, %1, %F2"
+  [(set_attr "type" "arith")
+   (set_attr "mode" "SI")])
+
+(define_insn "bitset_c"
+  [(set (match_operand:SI 0 "register_operand" "=e,d")
+        (ior:SI (match_operand:SI 1 "register_operand" "0,d")
+                (match_operand:SI 2 "const_pow2")))
+   (clobber (reg:CC CC_REGNUM))]
+  ""
+  "@
+   bitset!    %0, %E2
+   bitset.c   %0, %1, %E2"
+  [(set_attr "type" "arith")
+   (set_attr "mode" "SI")])
+
+(define_insn "bittgl_c"
+  [(set (match_operand:SI 0 "register_operand" "=e,d")
+        (xor:SI (match_operand:SI 1 "register_operand" "0,d")
+                (match_operand:SI 2 "const_pow2")))
+   (clobber (reg:CC CC_REGNUM))]
+  ""
+  "@
+   bittgl!    %0, %E2
+   bittgl.c   %0, %1, %E2"
+  [(set_attr "type" "arith")
+   (set_attr "mode" "SI")])
Index: gcc/config/score/score.c
===================================================================
--- gcc/config/score/score.c	(revision 120252)
+++ gcc/config/score/score.c	(working copy)
@@ -67,7 +67,9 @@ static int score_symbol_insns (enum scor
 
 static int score_address_insns (rtx, enum machine_mode);
 
-static bool score_rtx_costs (rtx, int, int, int *);
+static bool score_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *);
+
+static int score_address_cost (rtx);
 
 #undef  TARGET_ASM_FILE_START
 #define TARGET_ASM_FILE_START           th_asm_file_start
@@ -126,6 +128,9 @@ static bool score_rtx_costs (rtx, int, i
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS                score_rtx_costs
 
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST             score_address_cost
+
 #undef TARGET_DEFAULT_TARGET_FLAGS
 #define TARGET_DEFAULT_TARGET_FLAGS     TARGET_DEFAULT
 
@@ -154,7 +159,7 @@ score_pass_by_reference (CUMULATIVE_ARGS
 static rtx
 score_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
 {
-  if (!CONST_OK_FOR_LETTER_P (offset, 'O'))
+  if (!IMM_IN_RANGE (offset, 15, 1))
     {
       reg = expand_simple_binop (GET_MODE (reg), PLUS,
                                  gen_int_mode (offset & 0xffffc000,
@@ -499,12 +504,13 @@ enum reg_class score_char_to_class[256];
 void
 score_override_options (void)
 {
+  flag_pic = false;
   if (!flag_pic)
     sdata_max = g_switch_set ? g_switch_value : DEFAULT_SDATA_MAX;
   else
     {
       sdata_max = 0;
-      if (g_switch_set)
+      if (g_switch_set && (g_switch_value != 0))
         warning (0, "-fPIC and -G are incompatible");
     }
 
@@ -540,7 +546,7 @@ score_reg_class (int regno)
       || regno == ARG_POINTER_REGNUM)
     return ALL_REGS;
 
-  for (c = 0 ; c < N_REG_CLASSES ; c++)
+  for (c = 0; c < N_REG_CLASSES; c++)
     if (TEST_HARD_REG_BIT (reg_class_contents[c], regno))
       return c;
 
@@ -551,10 +557,10 @@ score_reg_class (int regno)
 enum reg_class
 score_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class)
 {
-  if (reg_class_subset_p (G32_REGS, class))
-    class = G32_REGS;
   if (reg_class_subset_p (G16_REGS, class))
-    class = G16_REGS;
+    return G16_REGS;
+  if (reg_class_subset_p (G32_REGS, class))
+    return G32_REGS;
   return class;
 }
 
@@ -576,41 +582,34 @@ score_secondary_reload_class (enum reg_c
 
 /* Implement CONST_OK_FOR_LETTER_P macro.  */
 /* imm constraints
-   I        IMM8        (i15-2-form)
-   J        IMM5        (i15_1-form)
-   K        IMM16       (i-form)
-   L        IMM16s      (i-form)
-   M        IMM14       (ri-form)
-   N        IMM14s      (ri-form)
-   O        IMM15s      (ri-form)
-   P        IMM12s      (rix-form) / IMM10s(cop-form) << 2  */
+   I        imm16 << 16
+   J        uimm5
+   K        uimm16
+   L        simm16
+   M        uimm14
+   N        simm14  */
 int
-score_const_ok_for_letter_p (int value, char c)
+score_const_ok_for_letter_p (HOST_WIDE_INT value, char c)
 {
   switch (c)
     {
-    case 'I': return IMM_IN_RANGE (value, 8, 0);
+    case 'I': return ((value & 0xffff) == 0);
     case 'J': return IMM_IN_RANGE (value, 5, 0);
     case 'K': return IMM_IN_RANGE (value, 16, 0);
     case 'L': return IMM_IN_RANGE (value, 16, 1);
     case 'M': return IMM_IN_RANGE (value, 14, 0);
     case 'N': return IMM_IN_RANGE (value, 14, 1);
-    case 'O': return IMM_IN_RANGE (value, 15, 1);
-    case 'P': return IMM_IN_RANGE (value, 12, 1);
     default : return 0;
     }
 }
 
 /* Implement EXTRA_CONSTRAINT macro.  */
-/* Q        const_hi    imm
-   Z        symbol_ref  */
+/* Z        symbol_ref  */
 int
 score_extra_constraint (rtx op, char c)
 {
   switch (c)
     {
-    case 'Q':
-      return (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0);
     case 'Z':
       return GET_CODE (op) == SYMBOL_REF;
     default:
@@ -917,10 +916,8 @@ score_address_insns (rtx x, enum machine
   int factor;
 
   if (mode == BLKmode)
-    /* BLKmode is used for single unaligned loads and stores.  */
     factor = 1;
   else
-    /* Each word of a multi-word value will be accessed individually.  */
     factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 
   if (mda_classify_address (&addr, mode, x, false))
@@ -938,24 +935,53 @@ score_address_insns (rtx x, enum machine
 
 /* Implement TARGET_RTX_COSTS macro.  */
 static bool
-score_rtx_costs (rtx x, int code, int outer_code, int *total)
+score_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
+                 int *total)
 {
   enum machine_mode mode = GET_MODE (x);
 
   switch (code)
     {
     case CONST_INT:
-      /* These can be used anywhere. */
-      *total = 0;
+      if (outer_code == SET)
+        {
+          if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+              || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L'))
+            *total = COSTS_N_INSNS (1);
+          else
+            *total = COSTS_N_INSNS (2);
+        }
+      else if (outer_code == PLUS || outer_code == MINUS)
+        {
+          if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'N'))
+            *total = 0;
+          else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+                   || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L'))
+            *total = 1;
+          else
+            *total = COSTS_N_INSNS (2);
+        }
+      else if (outer_code == AND || outer_code == IOR)
+        {
+          if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'M'))
+            *total = 0;
+          else if (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+                   || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K'))
+            *total = 1;
+          else
+            *total = COSTS_N_INSNS (2);
+        }
+      else
+        {
+          *total = 0;
+        }
       return true;
 
-      /* Otherwise fall through to the handling below because
-         we'll need to construct the constant.  */
     case CONST:
     case SYMBOL_REF:
     case LABEL_REF:
     case CONST_DOUBLE:
-      *total = COSTS_N_INSNS (1);
+      *total = COSTS_N_INSNS (2);
       return true;
 
     case MEM:
@@ -1011,7 +1037,8 @@ score_rtx_costs (rtx x, int code, int ou
           *total = COSTS_N_INSNS (4);
           return true;
         }
-      return false;
+      *total = COSTS_N_INSNS (1);
+      return true;
 
     case NEG:
       if (mode == DImode)
@@ -1022,22 +1049,38 @@ score_rtx_costs (rtx x, int code, int ou
       return false;
 
     case MULT:
-      *total = COSTS_N_INSNS (12);
+      *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (12);
       return true;
 
     case DIV:
     case MOD:
     case UDIV:
     case UMOD:
-      *total = COSTS_N_INSNS (33);
+      *total = optimize_size ? COSTS_N_INSNS (2) : COSTS_N_INSNS (33);
       return true;
 
     case SIGN_EXTEND:
-      *total = COSTS_N_INSNS (2);
-      return true;
-
     case ZERO_EXTEND:
-      *total = COSTS_N_INSNS (1);
+      switch (GET_MODE (XEXP (x, 0)))
+        {
+        case QImode:
+        case HImode:
+          if (GET_CODE (XEXP (x, 0)) == MEM)
+            {
+              *total = COSTS_N_INSNS (2);
+
+              if (!TARGET_LITTLE_ENDIAN &&
+                  side_effects_p (XEXP (XEXP (x, 0), 0)))
+                *total = 100;
+            }
+          else
+            *total = COSTS_N_INSNS (1);
+          break;
+
+        default:
+          *total = COSTS_N_INSNS (1);
+          break;
+        }
       return true;
 
     default:
@@ -1045,6 +1088,13 @@ score_rtx_costs (rtx x, int code, int ou
     }
 }
 
+/* Implement TARGET_ADDRESS_COST macro.  */
+int
+score_address_cost (rtx addr)
+{
+  return score_address_insns (addr, SImode);
+}
+
 /* Implement ASM_OUTPUT_EXTERNAL macro.  */
 int
 score_output_external (FILE *file ATTRIBUTE_UNUSED,
@@ -1089,18 +1139,16 @@ score_return_addr (int count, rtx frame 
 /* Implement PRINT_OPERAND macro.  */
 /* Score-specific operand codes:
    '['        print .set nor1 directive
-   ']'        print .set r1        directive
-
+   ']'        print .set r1 directive
    'U'        print hi part of a CONST_INT rtx
-   'D'        print first part of const double
-   'S'        selectively print '!' if operand is 15bit instruction accessible
-   'V'        print "v!" if operand is 15bit instruction accessible, or
-   "lfh!"
-
+   'E'        print log2(v)
+   'F'        print log2(~v)
+   'D'        print SFmode const double
+   'S'        selectively print "!" if operand is 15bit instruction accessible
+   'V'        print "v!" if operand is 15bit instruction accessible, or "lfh!"
    'L'        low  part of DImode reg operand
    'H'        high part of DImode reg operand
-
-   'C'  print part of opcode for a branch condition.  */
+   'C'        print part of opcode for a branch condition.  */
 void
 score_print_operand (FILE *file, rtx op, int c)
 {
@@ -1125,9 +1173,11 @@ score_print_operand (FILE *file, rtx op,
   else if (c == 'D')
     {
       if (GET_CODE (op) == CONST_DOUBLE)
-        fprintf (file, HOST_WIDE_INT_PRINT_HEX,
-                 TARGET_LITTLE_ENDIAN
-                 ? CONST_DOUBLE_LOW (op) : CONST_DOUBLE_HIGH (op));
+        {
+          rtx temp = gen_lowpart (SImode, op);
+          gcc_assert (GET_MODE (op) == SFmode);
+          fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (temp));
+        }
       else
         output_addr_const (file, op);
     }
@@ -1142,23 +1192,17 @@ score_print_operand (FILE *file, rtx op,
       gcc_assert (code == REG);
       fprintf (file, G16_REG_P (REGNO (op)) ? "v!" : "lfh!");
     }
-  else if (code == REG)
-    {
-      int regnum = REGNO (op);
-      if ((c == 'H' && !WORDS_BIG_ENDIAN)
-          || (c == 'L' && WORDS_BIG_ENDIAN))
-        regnum ++;
-      fprintf (file, "%s", reg_names[regnum]);
-    }
   else if (c == 'C')
     {
+      enum machine_mode mode = GET_MODE (XEXP (op, 0));
+
       switch (code)
         {
         case EQ: fputs ("eq", file); break;
         case NE: fputs ("ne", file); break;
         case GT: fputs ("gt", file); break;
-        case GE: fputs ("ge", file); break;
-        case LT: fputs ("lt", file); break;
+        case GE: fputs (mode != CCmode ? "pl" : "ge", file); break;
+        case LT: fputs (mode != CCmode ? "mi" : "lt", file); break;
         case LE: fputs ("le", file); break;
         case GTU: fputs ("gtu", file); break;
         case GEU: fputs ("cs", file); break;
@@ -1168,6 +1212,46 @@ score_print_operand (FILE *file, rtx op,
           output_operand_lossage ("invalid operand for code: '%c'", code);
         }
     }
+  else if (c == 'E')
+    {
+      unsigned HOST_WIDE_INT i;
+      unsigned HOST_WIDE_INT pow2mask = 1;
+      unsigned HOST_WIDE_INT val;
+
+      val = INTVAL (op);
+      for (i = 0; i < 32; i++)
+        {
+          if (val == pow2mask)
+            break;
+          pow2mask <<= 1;
+        }
+      gcc_assert (i < 32);
+      fprintf (file, HOST_WIDE_INT_PRINT_HEX, i);
+    }
+  else if (c == 'F')
+    {
+      unsigned HOST_WIDE_INT i;
+      unsigned HOST_WIDE_INT pow2mask = 1;
+      unsigned HOST_WIDE_INT val;
+
+      val = ~INTVAL (op);
+      for (i = 0; i < 32; i++)
+        {
+          if (val == pow2mask)
+            break;
+          pow2mask <<= 1;
+        }
+      gcc_assert (i < 32);
+      fprintf (file, HOST_WIDE_INT_PRINT_HEX, i);
+    }
+  else if (code == REG)
+    {
+      int regnum = REGNO (op);
+      if ((c == 'H' && !WORDS_BIG_ENDIAN)
+          || (c == 'L' && WORDS_BIG_ENDIAN))
+        regnum ++;
+      fprintf (file, "%s", reg_names[regnum]);
+    }
   else
     {
       switch (code)
@@ -1233,4 +1317,48 @@ score_print_operand_address (FILE *file,
   gcc_unreachable ();
 }
 
+/* Implement SELECT_CC_MODE macro.  */
+enum machine_mode
+score_select_cc_mode (enum rtx_code op, rtx x, rtx y)
+{
+  if ((op == EQ || op == NE || op == LT || op == GE)
+      && y == const0_rtx
+      && GET_MODE (x) == SImode)
+    {
+      switch (GET_CODE (x))
+        {
+        case PLUS:
+        case MINUS:
+        case NEG:
+        case AND:
+        case IOR:
+        case XOR:
+        case NOT:
+        case ASHIFT:
+        case LSHIFTRT:
+        case ASHIFTRT:
+          return CC_NZmode;
+
+        case SIGN_EXTEND:
+        case ZERO_EXTEND:
+        case ROTATE:
+        case ROTATERT:
+          return (op == LT || op == GE) ? CC_Nmode : CCmode;
+
+        default:
+          return CCmode;
+        }
+    }
+
+  if ((op == EQ || op == NE)
+      && (GET_CODE (y) == NEG)
+      && register_operand (XEXP (y, 0), SImode)
+      && register_operand (x, SImode))
+    {
+      return CC_NZmode;
+    }
+
+  return CCmode;
+}
+
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/score/score.h
===================================================================
--- gcc/config/score/score.h	(revision 120252)
+++ gcc/config/score/score.h	(working copy)
@@ -28,19 +28,20 @@ extern GTY(()) rtx cmp_op0;
 extern GTY(()) rtx cmp_op1;
 
 /* Controlling the Compilation Driver.  */
+#undef SWITCH_TAKES_ARG
 #define SWITCH_TAKES_ARG(CHAR) \
   (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
 
 /* CC1_SPEC is the set of arguments to pass to the compiler proper.  */
 #undef CC1_SPEC
-#define CC1_SPEC                 "%{!mel:-meb}"
+#define CC1_SPEC                 "%{G*} %{!mel:-meb}"
 
 #undef ASM_SPEC
 #define ASM_SPEC \
   "%{!mel:-EB} %{mel:-EL} %{mscore5u:-SCORE5U} %{mscore7:-SCORE7} %{G*}"
 
 #undef LINK_SPEC
-#define LINK_SPEC                 "%{!mel:-EB} %{mel:-EL} %{G*}"
+#define LINK_SPEC                "%{!mel:-EB} %{mel:-EL} %{G*}"
 
 /* Run-time Target Specification.  */
 #define TARGET_CPU_CPP_BUILTINS()               \
@@ -96,7 +97,7 @@ extern GTY(()) rtx cmp_op1;
 
 /* Allocation boundary (in *bits*) for storing arguments in argument list.  */
 #define PARM_BOUNDARY                  BITS_PER_WORD
-#define STACK_BOUNDARY                 64
+#define STACK_BOUNDARY                 BITS_PER_WORD
 
 /* Allocation boundary (in *bits*) for the code of a function.  */
 #define FUNCTION_BOUNDARY              BITS_PER_WORD
@@ -115,12 +116,41 @@ extern GTY(()) rtx cmp_op1;
    data to make it all fit in fewer cache lines.  Another is to
    cause character arrays to be word-aligned so that `strcpy' calls
    that copy constants to character arrays can be done inline.  */
-#define DATA_ALIGNMENT(TYPE, ALIGN)                                     \
-  ((((ALIGN) < BITS_PER_WORD)                                           \
-    && (TREE_CODE (TYPE) == ARRAY_TYPE                                  \
-        || TREE_CODE (TYPE) == UNION_TYPE                               \
+#define DATA_ALIGNMENT(TYPE, ALIGN)                                      \
+  ((((ALIGN) < BITS_PER_WORD)                                            \
+    && (TREE_CODE (TYPE) == ARRAY_TYPE                                   \
+        || TREE_CODE (TYPE) == UNION_TYPE                                \
         || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
 
+/* If defined, a C expression to compute the alignment given to a
+   constant that is being placed in memory.  EXP is the constant
+   and ALIGN is the alignment that the object would ordinarily have.
+   The value of this macro is used instead of that alignment to align
+   the object.
+
+   If this macro is not defined, then ALIGN is used.
+
+   The typical use of this macro is to increase alignment for string
+   constants to be word aligned so that `strcpy' calls that copy
+   constants can be done inline.  */
+#define CONSTANT_ALIGNMENT(EXP, ALIGN)                                  \
+  ((TREE_CODE (EXP) == STRING_CST  || TREE_CODE (EXP) == CONSTRUCTOR)   \
+   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+/* If defined, a C expression to compute the alignment for a local
+   variable.  TYPE is the data type, and ALIGN is the alignment that
+   the object would ordinarily have.  The value of this macro is used
+   instead of that alignment to align the object.
+
+   If this macro is not defined, then ALIGN is used.
+
+   One use of this macro is to increase alignment of medium-size
+   data to make it all fit in fewer cache lines.  */
+#define LOCAL_ALIGNMENT(TYPE, ALIGN)                                    \
+  ((TREE_CODE (TYPE) == ARRAY_TYPE                                      \
+    && TYPE_MODE (TREE_TYPE (TYPE)) == QImode                           \
+    && (ALIGN) < BITS_PER_WORD) ? BITS_PER_WORD : (ALIGN))
+
 /* Alignment of field after `int : 0' in a structure.  */
 #define EMPTY_FIELD_BOUNDARY           32
 
@@ -209,7 +239,7 @@ extern GTY(()) rtx cmp_op1;
 {                                                        \
   /* General Purpose Registers  */                       \
   1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        \
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1,        \
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,        \
   /* Control Registers  */                               \
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,        \
   /* CEH/ CEL/ CNT/ LCR/ SCR / ARG_POINTER_REGNUM/ FRAME_POINTER_REGNUM */\
@@ -245,8 +275,8 @@ extern GTY(()) rtx cmp_op1;
 }
 
 #define REG_ALLOC_ORDER                                                   \
-{   0,  1,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,        \
-   18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,  2,  3,        \
+{   0,  1,  6,  7,  8,  9, 10, 11,  4,  5, 22, 23, 24, 25, 26, 27,        \
+   12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 28, 29, 30, 31,  2,  3,        \
    32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,        \
    48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,        \
    64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,        \
@@ -386,18 +416,18 @@ enum reg_class
   score_preferred_reload_class (X, CLASS)
 
 /* If we need to load shorts byte-at-a-time, then we need a scratch.  */
-#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X)        \
+#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
   score_secondary_reload_class (CLASS, MODE, X)
 
 /* Return the register class of a scratch register needed to copy IN into
    or out of a register in CLASS in MODE.  If it can be done directly,
    NO_REGS is returned.  */
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X)       \
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
   score_secondary_reload_class (CLASS, MODE, X)
 
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.  */
-#define CLASS_MAX_NREGS(CLASS, MODE)    \
+#define CLASS_MAX_NREGS(CLASS, MODE) \
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
 #define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)    \
@@ -607,8 +637,8 @@ typedef struct score_args
 #define HAVE_PRE_DECREMENT              1
 #define HAVE_POST_INCREMENT             1
 #define HAVE_POST_DECREMENT             1
-#define HAVE_PRE_MODIFY_DISP            0
-#define HAVE_POST_MODIFY_DISP           0
+#define HAVE_PRE_MODIFY_DISP            1
+#define HAVE_POST_MODIFY_DISP           1
 #define HAVE_PRE_MODIFY_REG             0
 #define HAVE_POST_MODIFY_REG            0
 
@@ -660,6 +690,13 @@ typedef struct score_args
 
 #define LEGITIMATE_CONSTANT_P(X)        1
 
+/* Condition Code Status.  */
+#define SELECT_CC_MODE(OP, X, Y)        score_select_cc_mode (OP, X, Y)
+
+/* Return nonzero if SELECT_CC_MODE will never return MODE for a
+   floating point inequality comparison.  */
+#define REVERSIBLE_CC_MODE(MODE)        1
+
 /* Describing Relative Costs of Operations  */
 /* Compute extra cost of moving data between one register class and another.  */
 #define REGISTER_MOVE_COST(MODE, FROM, TO) \
@@ -753,32 +790,32 @@ typedef struct score_args
   sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long) (NUM))
 
 /* Output of Assembler Instructions.  */
-#define REGISTER_NAMES                                                   \
-{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",                        \
-  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",                  \
-  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",                \
-  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",                \
-                                                                         \
-  "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",                \
-  "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",          \
-                                                                         \
-  "ceh", "cel", "sr0", "sr1", "sr2", "_arg", "_frame", "",               \
-  "cr24", "cr25", "cr26", "cr27", "cr28", "cr29", "cr30", "cr31",        \
-                                                                         \
-  "c1r0", "c1r1", "c1r2", "c1r3", "c1r4", "c1r5", "c1r6", "c1r7",        \
-  "c1r8", "c1r9", "c1r10", "c1r11", "c1r12", "c1r13", "c1r14", "c1r15",  \
-  "c1r16", "c1r17", "c1r18", "c1r19", "c1r20", "c1r21", "c1r22", "c1r23",\
-  "c1r24", "c1r25", "c1r26", "c1r27", "c1r28", "c1r29", "c1r30", "c1r31",\
-                                                                         \
-  "c2r0", "c2r1", "c2r2", "c2r3", "c2r4", "c2r5", "c2r6", "c2r7",        \
-  "c2r8", "c2r9", "c2r10", "c2r11", "c2r12", "c2r13", "c2r14", "c2r15",  \
-  "c2r16", "c2r17", "c2r18", "c2r19", "c2r20", "c2r21", "c2r22", "c2r23",\
-  "c2r24", "c2r25", "c2r26", "c2r27", "c2r28", "c2r29", "c2r30", "c2r31",\
-                                                                         \
-  "c3r0", "c3r1", "c3r2", "c3r3", "c3r4", "c3r5", "c3r6", "c3r7",        \
-  "c3r8", "c3r9", "c3r10", "c3r11", "c3r12", "c3r13", "c3r14", "c3r15",  \
-  "c3r16", "c3r17", "c3r18", "c3r19", "c3r20", "c3r21", "c3r22", "c3r23",\
-  "c3r24", "c3r25", "c3r26", "c3r27", "c3r28", "c3r29", "c3r30", "c3r31",\
+#define REGISTER_NAMES                                                    \
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",                         \
+  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",                   \
+  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",                 \
+  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",                 \
+                                                                          \
+  "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",                 \
+  "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15",           \
+                                                                          \
+  "ceh", "cel", "sr0", "sr1", "sr2", "_arg", "_frame", "",                \
+  "cr24", "cr25", "cr26", "cr27", "cr28", "cr29", "cr30", "cr31",         \
+                                                                          \
+  "c1r0", "c1r1", "c1r2", "c1r3", "c1r4", "c1r5", "c1r6", "c1r7",         \
+  "c1r8", "c1r9", "c1r10", "c1r11", "c1r12", "c1r13", "c1r14", "c1r15",   \
+  "c1r16", "c1r17", "c1r18", "c1r19", "c1r20", "c1r21", "c1r22", "c1r23", \
+  "c1r24", "c1r25", "c1r26", "c1r27", "c1r28", "c1r29", "c1r30", "c1r31", \
+                                                                          \
+  "c2r0", "c2r1", "c2r2", "c2r3", "c2r4", "c2r5", "c2r6", "c2r7",         \
+  "c2r8", "c2r9", "c2r10", "c2r11", "c2r12", "c2r13", "c2r14", "c2r15",   \
+  "c2r16", "c2r17", "c2r18", "c2r19", "c2r20", "c2r21", "c2r22", "c2r23", \
+  "c2r24", "c2r25", "c2r26", "c2r27", "c2r28", "c2r29", "c2r30", "c2r31", \
+                                                                          \
+  "c3r0", "c3r1", "c3r2", "c3r3", "c3r4", "c3r5", "c3r6", "c3r7",         \
+  "c3r8", "c3r9", "c3r10", "c3r11", "c3r12", "c3r13", "c3r14", "c3r15",   \
+  "c3r16", "c3r17", "c3r18", "c3r19", "c3r20", "c3r21", "c3r22", "c3r23", \
+  "c3r24", "c3r25", "c3r26", "c3r27", "c3r28", "c3r29", "c3r30", "c3r31", \
 }
 
 /* Print operand X (an rtx) in assembler syntax to file FILE.  */
@@ -907,4 +944,4 @@ struct extern_list GTY ((chain_next ("%h
   int size;                             /* size in bytes  */
 };
 
-extern GTY (()) struct extern_list      *extern_head ;
+extern GTY (()) struct extern_list      *extern_head;
Index: gcc/config/score/score-conv.h
===================================================================
--- gcc/config/score/score-conv.h	(revision 120252)
+++ gcc/config/score/score-conv.h	(working copy)
@@ -45,7 +45,7 @@ extern int target_flags;
 
 #define CE_REG_P(REGNO)        REG_CONTAIN (REGNO, CE_REG_FIRST, CE_REG_NUM)
 
-#define UIMM_IN_RANGE(V, W)  ((V) >= 0 && (V) < ((HOST_WIDE_INT)1 << (W)))
+#define UIMM_IN_RANGE(V, W)  ((V) >= 0 && (V) < ((HOST_WIDE_INT) 1 << (W)))
 
 #define SIMM_IN_RANGE(V, W)                            \
   ((V) >= (-1 * ((HOST_WIDE_INT) 1 << ((W) - 1)))      \
@@ -54,6 +54,11 @@ extern int target_flags;
 #define IMM_IN_RANGE(V, W, S) \
   ((S) ? SIMM_IN_RANGE (V, W) : UIMM_IN_RANGE (V, W))
 
+#define IMM_IS_POW_OF_2(V, E1, E2)                \
+  ((V) >= ((unsigned HOST_WIDE_INT) 1 << (E1))     \
+   && (V) <= ((unsigned HOST_WIDE_INT) 1 << (E2))  \
+   && ((V) & ((V) - 1)) == 0)
+
 #define SCORE_STACK_ALIGN(LOC)          (((LOC) + 3) & ~3)
 
 #define SCORE_MAX_FIRST_STACK_STEP      (0x3ff0)
Index: gcc/config/score/score-mdaux.c
===================================================================
--- gcc/config/score/score-mdaux.c	(revision 120252)
+++ gcc/config/score/score-mdaux.c	(working copy)
@@ -108,10 +108,9 @@ score_symbol_type score_classify_symbol 
   if (GET_CODE (x) == LABEL_REF)
     return SYMBOL_GENERAL;
 
-  if (GET_CODE (x) != SYMBOL_REF)
-    gcc_unreachable ();
+  gcc_assert (GET_CODE (x) == SYMBOL_REF);
 
-  if (CONSTANT_POOL_ADDRESS_P(x))
+  if (CONSTANT_POOL_ADDRESS_P (x))
     {
       if (GET_MODE_SIZE (get_pool_mode (x)) <= SCORE_SDATA_MAX)
         return SYMBOL_SMALL_DATA;
@@ -185,14 +184,14 @@ mda_compute_frame_size (HOST_WIDE_INT si
   f->mask = 0;
   f->var_size = SCORE_STACK_ALIGN (size);
   f->args_size = current_function_outgoing_args_size;
-  f->cprestore_size = SCORE_STACK_ALIGN (STARTING_FRAME_OFFSET) - f->args_size;
+  f->cprestore_size = flag_pic ? UNITS_PER_WORD : 0;
   if (f->var_size == 0 && current_function_is_leaf)
     f->args_size = f->cprestore_size = 0;
 
   if (f->args_size == 0 && current_function_calls_alloca)
     f->args_size = UNITS_PER_WORD;
 
-  f->total_size = f->var_size + f->args_size;
+  f->total_size = f->var_size + f->args_size + f->cprestore_size;
   for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
     {
       if (score_save_reg_p (regno))
@@ -205,7 +204,7 @@ mda_compute_frame_size (HOST_WIDE_INT si
   if (current_function_calls_eh_return)
     {
       unsigned int i;
-      for (i = 0; ; ++i)
+      for (i = 0;; ++i)
         {
           regno = EH_RETURN_DATA_REGNO (i);
           if (regno == INVALID_REGNUM)
@@ -215,7 +214,7 @@ mda_compute_frame_size (HOST_WIDE_INT si
         }
     }
 
-  f->total_size += SCORE_STACK_ALIGN (f->gp_reg_size);
+  f->total_size += f->gp_reg_size;
   f->num_gp = f->gp_reg_size / UNITS_PER_WORD;
 
   if (f->mask)
@@ -226,12 +225,7 @@ mda_compute_frame_size (HOST_WIDE_INT si
       f->gp_sp_offset = offset;
     }
   else
-    {
-      f->gp_sp_offset = 0;
-    }
-
-  if ((f->total_size == f->gp_reg_size) && flag_pic)
-    f->total_size += 8;
+    f->gp_sp_offset = 0;
 
   return f;
 }
@@ -294,8 +288,13 @@ mdx_prologue (void)
   if (frame_pointer_needed)
     EMIT_PL (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx));
 
-  if (flag_pic)
-    emit_insn (gen_cprestore (GEN_INT (size + 4)));
+  if (flag_pic && f->cprestore_size)
+    {
+      if (frame_pointer_needed)
+        emit_insn (gen_cprestore_use_fp (GEN_INT (size - f->cprestore_size)));
+      else
+        emit_insn (gen_cprestore_use_sp (GEN_INT (size - f->cprestore_size)));
+    }
 
 #undef EMIT_PL
 }
@@ -392,7 +391,7 @@ mda_classify_address (struct score_addre
       info->offset = XEXP (x, 1);
       return (mda_valid_base_register_p (info->reg, strict)
               && GET_CODE (info->offset) == CONST_INT
-              && CONST_OK_FOR_LETTER_P (INTVAL (info->offset), 'O'));
+              && IMM_IN_RANGE (INTVAL (info->offset), 15, 1));
     case PRE_DEC:
     case POST_DEC:
     case PRE_INC:
@@ -405,7 +404,7 @@ mda_classify_address (struct score_addre
       return mda_valid_base_register_p (info->reg, strict);
     case CONST_INT:
       info->type = ADD_CONST_INT;
-      return CONST_OK_FOR_LETTER_P (INTVAL (x), 'O');
+      return IMM_IN_RANGE (INTVAL (x), 15, 1);
     case CONST:
     case LABEL_REF:
     case SYMBOL_REF:
@@ -443,7 +442,7 @@ mda_symbolic_constant_p (rtx x, enum sco
     return 1;
 
   /* if offset > 15bit, must reload  */
-  if (!CONST_OK_FOR_LETTER_P (offset, 'O'))
+  if (!IMM_IN_RANGE (offset, 15, 1))
     return 0;
 
   switch (*symbol_type)
@@ -459,11 +458,9 @@ mda_symbolic_constant_p (rtx x, enum sco
 void
 mdx_movsicc (rtx *ops)
 {
-  enum machine_mode mode = CCmode;
-
-  if (GET_CODE (ops[1]) == EQ || GET_CODE (ops[1]) == NE)
-    mode = CC_NZmode;
+  enum machine_mode mode;
 
+  mode = score_select_cc_mode (GET_CODE (ops[1]), ops[2], ops[3]);
   emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (mode, CC_REGNUM),
                           gen_rtx_COMPARE (mode, cmp_op0, cmp_op1)));
 }
@@ -533,14 +530,15 @@ mds_movdi (rtx *ops)
 void
 mds_zero_extract_andi (rtx *ops)
 {
-  if (INTVAL (ops[1]) == 1 && const_bi_operand (ops[2], SImode))
+  if (INTVAL (ops[1]) == 1 && const_uimm5 (ops[2], SImode))
     emit_insn (gen_zero_extract_bittst (ops[0], ops[2]));
   else
     {
       unsigned HOST_WIDE_INT mask;
       mask = (0xffffffffU & ((1U << INTVAL (ops[1])) - 1U));
       mask = mask << INTVAL (ops[2]);
-      emit_insn (gen_andsi3_cmp (ops[0], gen_int_mode (mask, SImode)));
+      emit_insn (gen_andsi3_cmp (ops[3], ops[0],
+                                 gen_int_mode (mask, SImode)));
     }
 }
 
@@ -637,17 +635,20 @@ mdp_sinsn (rtx *ops, enum mda_mem_unit u
 const char *
 mdp_limm (rtx *ops)
 {
+  HOST_WIDE_INT v;
+
   gcc_assert (GET_CODE (ops[0]) == REG);
+  gcc_assert (GET_CODE (ops[1]) == CONST_INT);
 
-  if (G16_REG_P (REGNO (ops[0]))
-      && CONST_OK_FOR_LETTER_P (INTVAL (ops[1]), 'I'))
+  v = INTVAL (ops[1]);
+  if (G16_REG_P (REGNO (ops[0])) && IMM_IN_RANGE (v, 8, 0))
     return "ldiu!   %0, %c1";
-  else if (CONST_OK_FOR_LETTER_P (INTVAL (ops[1]), 'L'))
+  else if (IMM_IN_RANGE (v, 16, 1))
     return "ldi     %0, %c1";
-  else if (EXTRA_CONSTRAINT (ops[1], 'Q'))
+  else if ((v & 0xffff) == 0)
     return "ldis    %0, %U1";
   else
-    return "li      %0, %D1";
+    return "li      %0, %c1";
 }
 
 /* Output asm insn for move.  */
@@ -670,69 +671,389 @@ mdp_move (rtx *ops)
     return "mv      %0, %1";
 }
 
-/* Score support add/sub with exponent immediate insn,
-   use to judge imm condition.  */
-static unsigned int
-num_bits1 (unsigned HOST_WIDE_INT v)
+/* Emit lcb/lce insns.  */
+bool
+mdx_unaligned_load (rtx *ops)
+{
+  rtx dst = ops[0];
+  rtx src = ops[1];
+  rtx len = ops[2];
+  rtx off = ops[3];
+  rtx addr_reg;
+
+  if (INTVAL (len) != BITS_PER_WORD
+      || (INTVAL (off) % BITS_PER_UNIT) != 0)
+    return false;
+
+  gcc_assert (GET_MODE_SIZE (GET_MODE (dst)) == GET_MODE_SIZE (SImode));
+
+  addr_reg = copy_addr_to_reg (XEXP (src, 0));
+  emit_insn (gen_move_lcb (addr_reg, addr_reg));
+  emit_insn (gen_move_lce (addr_reg, addr_reg, dst));
+
+  return true;
+}
+
+/* Emit scb/sce insns.  */
+bool
+mdx_unaligned_store (rtx *ops)
+{
+  rtx dst = ops[0];
+  rtx len = ops[1];
+  rtx off = ops[2];
+  rtx src = ops[3];
+  rtx addr_reg;
+
+  if (INTVAL(len) != BITS_PER_WORD
+      || (INTVAL(off) % BITS_PER_UNIT) != 0)
+    return false;
+
+  gcc_assert (GET_MODE_SIZE (GET_MODE (src)) == GET_MODE_SIZE (SImode));
+
+  addr_reg = copy_addr_to_reg (XEXP (dst, 0));
+  emit_insn (gen_move_scb (addr_reg, addr_reg, src));
+  emit_insn (gen_move_sce (addr_reg, addr_reg));
+
+  return true;
+}
+
+/* If length is short, generate move insns straight.  */
+static void
+mdx_block_move_straight (rtx dst, rtx src, HOST_WIDE_INT length)
+{
+  HOST_WIDE_INT leftover;
+  int i, reg_count;
+  rtx *regs;
+
+  leftover = length % UNITS_PER_WORD;
+  length -= leftover;
+  reg_count = length / UNITS_PER_WORD;
+
+  regs = alloca (sizeof (rtx) * reg_count);
+  for (i = 0; i < reg_count; i++)
+    regs[i] = gen_reg_rtx (SImode);
+
+  /* Load from src to regs.  */
+  if (MEM_ALIGN (src) >= BITS_PER_WORD)
+    {
+      HOST_WIDE_INT offset = 0;
+      for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++)
+        emit_move_insn (regs[i], adjust_address (src, SImode, offset));
+    }
+  else if (reg_count >= 1)
+    {
+      rtx src_reg = copy_addr_to_reg (XEXP (src, 0));
+
+      emit_insn (gen_move_lcb (src_reg, src_reg));
+      for (i = 0; i < (reg_count - 1); i++)
+        emit_insn (gen_move_lcw (src_reg, src_reg, regs[i]));
+      emit_insn (gen_move_lce (src_reg, src_reg, regs[i]));
+    }
+
+  /* Store regs to dest.  */
+  if (MEM_ALIGN (dst) >= BITS_PER_WORD)
+    {
+      HOST_WIDE_INT offset = 0;
+      for (i = 0; i < reg_count; offset += UNITS_PER_WORD, i++)
+        emit_move_insn (adjust_address (dst, SImode, offset), regs[i]);
+    }
+  else if (reg_count >= 1)
+    {
+      rtx dst_reg = copy_addr_to_reg (XEXP (dst, 0));
+
+      emit_insn (gen_move_scb (dst_reg, dst_reg, regs[0]));
+      for (i = 1; i < reg_count; i++)
+        emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i]));
+      emit_insn (gen_move_sce (dst_reg, dst_reg));
+    }
+
+  /* Mop up any left-over bytes.  */
+  if (leftover > 0)
+    {
+      src = adjust_address (src, BLKmode, length);
+      dst = adjust_address (dst, BLKmode, length);
+      move_by_pieces (dst, src, leftover,
+                      MIN (MEM_ALIGN (src), MEM_ALIGN (dst)), 0);
+    }
+}
+
+/* Generate loop head when dst or src is unaligned.  */
+static void
+mdx_block_move_loop_head (rtx dst_reg, HOST_WIDE_INT dst_align,
+                          rtx src_reg, HOST_WIDE_INT src_align,
+                          HOST_WIDE_INT length)
 {
-  int i, n = 0;
+  bool src_unaligned = (src_align < BITS_PER_WORD);
+  bool dst_unaligned = (dst_align < BITS_PER_WORD);
+
+  rtx temp = gen_reg_rtx (SImode);
 
-  for (i = 0; i < BITS_PER_WORD; i++)
-    n += BITSET_P (v, i) ? 1 : 0;
-  return n;
+  gcc_assert (length == UNITS_PER_WORD);
+
+  if (src_unaligned)
+    {
+      emit_insn (gen_move_lcb (src_reg, src_reg));
+      emit_insn (gen_move_lcw (src_reg, src_reg, temp));
+    }
+  else
+    emit_insn (gen_move_lw_a (src_reg,
+                              src_reg, gen_int_mode (4, SImode), temp));
+
+  if (dst_unaligned)
+    emit_insn (gen_move_scb (dst_reg, dst_reg, temp));
+  else
+    emit_insn (gen_move_sw_a (dst_reg,
+                              dst_reg, gen_int_mode (4, SImode), temp));
 }
 
-/* Generate add insn, insn will affect condition flag. Optimize used.  */
+/* Generate loop body, copy length bytes per iteration.  */
+static void
+mdx_block_move_loop_body (rtx dst_reg, HOST_WIDE_INT dst_align,
+                          rtx src_reg, HOST_WIDE_INT src_align,
+                          HOST_WIDE_INT length)
+{
+  int reg_count = length / UNITS_PER_WORD;
+  rtx *regs = alloca (sizeof (rtx) * reg_count);
+  int i;
+  bool src_unaligned = (src_align < BITS_PER_WORD);
+  bool dst_unaligned = (dst_align < BITS_PER_WORD);
+
+  for (i = 0; i < reg_count; i++)
+    regs[i] = gen_reg_rtx (SImode);
+
+  if (src_unaligned)
+    {
+      for (i = 0; i < reg_count; i++)
+        emit_insn (gen_move_lcw (src_reg, src_reg, regs[i]));
+    }
+  else
+    {
+      for (i = 0; i < reg_count; i++)
+        emit_insn (gen_move_lw_a (src_reg,
+                                  src_reg, gen_int_mode (4, SImode), regs[i]));
+    }
+
+  if (dst_unaligned)
+    {
+      for (i = 0; i < reg_count; i++)
+        emit_insn (gen_move_scw (dst_reg, dst_reg, regs[i]));
+    }
+  else
+    {
+      for (i = 0; i < reg_count; i++)
+        emit_insn (gen_move_sw_a (dst_reg,
+                                  dst_reg, gen_int_mode (4, SImode), regs[i]));
+    }
+}
+
+/* Generate loop foot, copy the leftover bytes.  */
+static void
+mdx_block_move_loop_foot (rtx dst_reg, HOST_WIDE_INT dst_align,
+                          rtx src_reg, HOST_WIDE_INT src_align,
+                          HOST_WIDE_INT length)
+{
+  bool src_unaligned = (src_align < BITS_PER_WORD);
+  bool dst_unaligned = (dst_align < BITS_PER_WORD);
+
+  HOST_WIDE_INT leftover;
+
+  leftover = length % UNITS_PER_WORD;
+  length -= leftover;
+
+  if (length > 0)
+    mdx_block_move_loop_body (dst_reg, dst_align,
+                              src_reg, src_align, length);
+
+  if (dst_unaligned)
+    emit_insn (gen_move_sce (dst_reg, dst_reg));
+
+  if (leftover > 0)
+    {
+      HOST_WIDE_INT src_adj = src_unaligned ? -4 : 0;
+      HOST_WIDE_INT dst_adj = dst_unaligned ? -4 : 0;
+      rtx temp;
+
+      gcc_assert (leftover < UNITS_PER_WORD);
+
+      if (leftover >= UNITS_PER_WORD / 2
+          && src_align >= BITS_PER_WORD / 2
+          && dst_align >= BITS_PER_WORD / 2)
+        {
+          temp = gen_reg_rtx (HImode);
+          emit_insn (gen_move_lhu_b (src_reg, src_reg,
+                                     gen_int_mode (src_adj, SImode), temp));
+          emit_insn (gen_move_sh_b (dst_reg, dst_reg,
+                                    gen_int_mode (dst_adj, SImode), temp));
+          leftover -= UNITS_PER_WORD / 2;
+          src_adj = UNITS_PER_WORD / 2;
+          dst_adj = UNITS_PER_WORD / 2;
+        }
+
+      while (leftover > 0)
+        {
+          temp = gen_reg_rtx (QImode);
+          emit_insn (gen_move_lbu_b (src_reg, src_reg,
+                                     gen_int_mode (src_adj, SImode), temp));
+          emit_insn (gen_move_sb_b (dst_reg, dst_reg,
+                                    gen_int_mode (dst_adj, SImode), temp));
+          leftover--;
+          src_adj = 1;
+          dst_adj = 1;
+        }
+    }
+}
+
+#define MIN_MOVE_REGS 3
+#define MIN_MOVE_BYTES (MIN_MOVE_REGS * UNITS_PER_WORD)
+#define MAX_MOVE_REGS 4
+#define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
+
+/* The length is large, generate a loop if necessary.
+   The loop is consisted by loop head/body/foot.  */
+static void
+mdx_block_move_loop (rtx dst, rtx src, HOST_WIDE_INT length)
+{
+  HOST_WIDE_INT src_align = MEM_ALIGN (src);
+  HOST_WIDE_INT dst_align = MEM_ALIGN (dst);
+  HOST_WIDE_INT loop_mov_bytes;
+  HOST_WIDE_INT iteration = 0;
+  HOST_WIDE_INT head_length = 0, leftover;
+  rtx label, src_reg, dst_reg, final_dst;
+
+  bool gen_loop_head = (src_align < BITS_PER_WORD
+                        || dst_align < BITS_PER_WORD);
+
+  if (gen_loop_head)
+    head_length += UNITS_PER_WORD;
+
+  for (loop_mov_bytes = MAX_MOVE_BYTES;
+       loop_mov_bytes >= MIN_MOVE_BYTES;
+       loop_mov_bytes -= UNITS_PER_WORD)
+    {
+      iteration = (length - head_length) / loop_mov_bytes;
+      if (iteration > 1)
+        break;
+    }
+  if (iteration <= 1)
+    {
+      mdx_block_move_straight (dst, src, length);
+      return;
+    }
+
+  leftover = (length - head_length) % loop_mov_bytes;
+  length -= leftover;
+
+  src_reg = copy_addr_to_reg (XEXP (src, 0));
+  dst_reg = copy_addr_to_reg (XEXP (dst, 0));
+  final_dst = expand_simple_binop (Pmode, PLUS, dst_reg, GEN_INT (length),
+                                   0, 0, OPTAB_WIDEN);
+
+  if (gen_loop_head)
+    mdx_block_move_loop_head (dst_reg, dst_align,
+                              src_reg, src_align, head_length);
+
+  label = gen_label_rtx ();
+  emit_label (label);
+
+  mdx_block_move_loop_body (dst_reg, dst_align,
+                            src_reg, src_align, loop_mov_bytes);
+
+  emit_insn (gen_cmpsi (dst_reg, final_dst));
+  emit_jump_insn (gen_bne (label));
+
+  mdx_block_move_loop_foot (dst_reg, dst_align,
+                            src_reg, src_align, leftover);
+}
+
+/* Generate block move, for misc.md: "movmemsi".  */
+bool
+mdx_block_move (rtx *ops)
+{
+  rtx dst = ops[0];
+  rtx src = ops[1];
+  rtx length = ops[2];
+
+  if (TARGET_LITTLE_ENDIAN
+      && (MEM_ALIGN (src) < BITS_PER_WORD || MEM_ALIGN (dst) < BITS_PER_WORD)
+      && INTVAL (length) >= UNITS_PER_WORD)
+    return false;
+
+  if (GET_CODE (length) == CONST_INT)
+    {
+      if (INTVAL (length) <= 2 * MAX_MOVE_BYTES)
+        {
+           mdx_block_move_straight (dst, src, INTVAL (length));
+           return true;
+        }
+      else if (optimize &&
+               !(flag_unroll_loops || flag_unroll_all_loops))
+        {
+          mdx_block_move_loop (dst, src, INTVAL (length));
+          return true;
+        }
+    }
+  return false;
+}
+
+/* Generate add insn.  */
 const char *
-mdp_add_imm_ucc (rtx *ops)
+mdp_select_add_imm (rtx *ops, bool set_cc)
 {
   HOST_WIDE_INT v = INTVAL (ops[2]);
 
   gcc_assert (GET_CODE (ops[2]) == CONST_INT);
   gcc_assert (REGNO (ops[0]) == REGNO (ops[1]));
 
-  if (G16_REG_P (REGNO (ops[0])))
+  if (set_cc && G16_REG_P (REGNO (ops[0])))
     {
-      if (v > 0 && num_bits1 (v) == 1 && IMM_IN_RANGE (ffs (v) - 1, 4, 0))
+      if (v > 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) v, 0, 15))
         {
           ops[2] = GEN_INT (ffs (v) - 1);
           return "addei!  %0, %c2";
         }
 
-      if (v < 0 && num_bits1 (-v) == 1 && IMM_IN_RANGE (ffs (-v) - 1, 4, 0))
+      if (v < 0 && IMM_IS_POW_OF_2 ((unsigned HOST_WIDE_INT) (-v), 0, 15))
         {
           ops[2] = GEN_INT (ffs (-v) - 1);
           return "subei!  %0, %c2";
         }
     }
+
+  if (set_cc)
     return "addi.c  %0, %c2";
+  else
+    return "addi    %0, %c2";
 }
 
-/* Output arith insn, insn will update condition flag.  */
+/* Output arith insn.  */
 const char *
-mdp_select (rtx *ops, const char *inst_pre, bool commu, const char *let)
+mdp_select (rtx *ops, const char *inst_pre,
+            bool commu, const char *letter, bool set_cc)
 {
   gcc_assert (GET_CODE (ops[0]) == REG);
   gcc_assert (GET_CODE (ops[1]) == REG);
 
-  if (G16_REG_P (REGNO (ops[0]))
+  if (set_cc && G16_REG_P (REGNO (ops[0]))
       && (GET_CODE (ops[2]) == REG ? G16_REG_P (REGNO (ops[2])) : 1)
       && REGNO (ops[0]) == REGNO (ops[1]))
     {
-      snprintf (ins, INS_BUF_SZ, "%s!        %%0, %%%s2", inst_pre, let);
+      snprintf (ins, INS_BUF_SZ, "%s!  %%0, %%%s2", inst_pre, letter);
       return ins;
     }
 
-  if (commu && G16_REG_P (REGNO (ops[0]))
+  if (commu && set_cc && G16_REG_P (REGNO (ops[0]))
       && G16_REG_P (REGNO (ops[1]))
       && REGNO (ops[0]) == REGNO (ops[2]))
     {
       gcc_assert (GET_CODE (ops[2]) == REG);
-      snprintf (ins, INS_BUF_SZ, "%s!        %%0, %%%s1", inst_pre, let);
+      snprintf (ins, INS_BUF_SZ, "%s!  %%0, %%%s1", inst_pre, letter);
       return ins;
     }
 
-  snprintf (ins, INS_BUF_SZ, "%s.c        %%0, %%1, %%%s2", inst_pre, let);
+  if (set_cc)
+    snprintf (ins, INS_BUF_SZ, "%s.c  %%0, %%1, %%%s2", inst_pre, letter);
+  else
+    snprintf (ins, INS_BUF_SZ, "%s    %%0, %%1, %%%s2", inst_pre, letter);
   return ins;
 }
 
Index: gcc/config/score/score.md
===================================================================
--- gcc/config/score/score.md	(revision 120252)
+++ gcc/config/score/score.md	(working copy)
@@ -59,8 +59,8 @@
 
 (define_constants
    [(BITTST         0)
-    (LOAD_ADD       1)
-    (STORE_ADD      2)
+    (CPLOAD         1)
+    (CPRESTORE      2)
 
     (SCB            3)
     (SCW            4)
@@ -88,10 +88,22 @@
 (include "misc.md")
 (include "mac.md")
 
-(define_insn "movqi"
+(define_expand "movqi"
+  [(set (match_operand:QI 0 "nonimmediate_operand")
+        (match_operand:QI 1 "general_operand"))]
+  ""
+{
+  if (MEM_P (operands[0])
+      && !register_operand (operands[1], QImode))
+    {
+      operands[1] = force_reg (QImode, operands[1]);
+    }
+})
+
+(define_insn "*movqi_insns"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a")
         (match_operand:QI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))]
-  ""
+  "!MEM_P (operands[0]) || register_operand (operands[1], QImode)"
 {
   switch (which_alternative)
     {
@@ -109,10 +121,22 @@
   [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr")
    (set_attr "mode" "QI")])
 
-(define_insn "movhi"
+(define_expand "movhi"
+  [(set (match_operand:HI 0 "nonimmediate_operand")
+        (match_operand:HI 1 "general_operand"))]
+  ""
+{
+  if (MEM_P (operands[0])
+      && !register_operand (operands[1], HImode))
+    {
+      operands[1] = force_reg (HImode, operands[1]);
+    }
+})
+
+(define_insn "*movhi_insns"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a")
         (match_operand:HI 1 "general_operand" "i,d,m,d,*x,d,*a,d"))]
-  ""
+  "!MEM_P (operands[0]) || register_operand (operands[1], HImode)"
 {
   switch (which_alternative)
     {
@@ -130,11 +154,23 @@
   [(set_attr "type" "arith,move,load,store,fce,tce,fsr,tsr")
    (set_attr "mode" "HI")])
 
-(define_insn "movsi"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a,d,c")
-        (match_operand:SI 1 "general_operand" "i,d,m,d,*x,d,*a,d,c,d"))]
+(define_expand "movsi"
+  [(set (match_operand:SI 0 "nonimmediate_operand")
+        (match_operand:SI 1 "general_operand"))]
   ""
 {
+  if (MEM_P (operands[0])
+      && !register_operand (operands[1], SImode))
+    {
+      operands[1] = force_reg (SImode, operands[1]);
+    }
+})
+
+(define_insn "*movsi_insns"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,d,*x,d,*a,d,*c")
+        (match_operand:SI 1 "general_operand" "i,d,m,d,*x,d,*a,d,*c,d"))]
+  "!MEM_P (operands[0]) || register_operand (operands[1], SImode)"
+{
   switch (which_alternative)
     {
     case 0:
@@ -169,46 +205,103 @@
   DONE;
 })
 
+(define_expand "movsf"
+  [(set (match_operand:SF 0 "nonimmediate_operand")
+        (match_operand:SF 1 "general_operand"))]
+  ""
+{
+  if (MEM_P (operands[0])
+      && !register_operand (operands[1], SFmode))
+    {
+      operands[1] = force_reg (SFmode, operands[1]);
+    }
+})
+
+(define_insn "*movsf_insns"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,m")
+        (match_operand:SF 1 "general_operand" "i,d,m,d"))]
+  "!MEM_P (operands[0]) || register_operand (operands[1], SFmode)"
+{
+  switch (which_alternative)
+    {
+    case 0: return \"li      %0, %D1\";;
+    case 1: return mdp_move (operands);
+    case 2: return mdp_linsn (operands, MDA_WORD, false);
+    case 3: return mdp_sinsn (operands, MDA_WORD);
+    default: gcc_unreachable ();
+    }
+}
+  [(set_attr "type" "arith,move,load,store")
+   (set_attr "mode" "SI")])
+
+(define_insn_and_split "movdf"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,m")
+        (match_operand:DF 1 "general_operand" "i,d,m,d"))]
+  ""
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  mds_movdi (operands);
+  DONE;
+})
+
 (define_insn "addsi3"
-  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
-        (plus:SI (match_operand:SI 1 "register_operand" "0,d,%d")
-                 (match_operand:SI 2 "arith_operand" "L,N,d")))]
+  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
+        (plus:SI (match_operand:SI 1 "register_operand" "0,0,d,d")
+                 (match_operand:SI 2 "arith_operand" "I,L,N,d")))]
   ""
-  "@
-   addi    %0, %c2
-   addri   %0, %1, %c2
-   add     %0, %1, %2"
+{
+  switch (which_alternative)
+    {
+    case 0: return \"addis %0, %U2\";
+    case 1: return mdp_select_add_imm (operands, false);
+    case 2: return \"addri %0, %1, %c2\";
+    case 3: return mdp_select (operands, "add", true, "", false);
+    default: gcc_unreachable ();
+    }
+}
   [(set_attr "type" "arith")
    (set_attr "mode" "SI")])
 
 (define_insn "*addsi3_cmp"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (plus:SI (match_operand:SI 0 "register_operand" "d,d,d")
-                                (match_operand:SI 1 "arith_operand" "N,L,d"))
-                       (const_int 0)))]
+        (compare:CC_NZ (plus:SI
+                        (match_operand:SI 1 "register_operand" "0,0,d,d")
+                        (match_operand:SI 2 "arith_operand" "I,L,N,d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d,d,d,d"))]
   ""
-  "@
-   %[       addri.c r1, %0, %c1       %]
-   %[       m%V0    r1, %0\;addi.c  r1, %2        %]
-   %[       add.c   r1, %0, %1        %]"
+{
+  switch (which_alternative)
+    {
+    case 0: return \"addis.c %0, %U2\";
+    case 1: return mdp_select_add_imm (operands, true);
+    case 2: return \"addri.c %0, %1, %c2\";
+    case 3: return mdp_select (operands, "add", true, "", true);
+    default: gcc_unreachable ();
+    }
+}
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
 
-(define_insn "addsi3_ucc"
+(define_insn "*addsi3_ucc"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (plus:SI (match_operand:SI 1 "register_operand" "0,d,d")
-                                (match_operand:SI 2 "arith_operand" "L,N,d"))
+        (compare:CC_NZ (plus:SI
+                        (match_operand:SI 1 "register_operand" "0,0,d,d")
+                        (match_operand:SI 2 "arith_operand" "I,L,N,d"))
                        (const_int 0)))
-   (set (match_operand:SI 0 "register_operand" "=d,d,d")
+   (set (match_operand:SI 0 "register_operand" "=d,d,d,d")
         (plus:SI (match_dup 1) (match_dup 2)))]
   ""
 {
   switch (which_alternative)
     {
-    case 0: return mdp_add_imm_ucc (operands);
-    case 1: return \"addri.c %0, %1, %c2\";
-    case 2: return mdp_select (operands, "add", true, "");
+    case 0: return \"addis.c %0, %U2\";
+    case 1: return mdp_select_add_imm (operands, true);
+    case 2: return \"addri.c %0, %1, %c2\";
+    case 3: return mdp_select (operands, "add", true, "", true);
     default: gcc_unreachable ();
     }
 }
@@ -217,9 +310,9 @@
    (set_attr "mode" "SI")])
 
 (define_insn "adddi3"
-  [(set (match_operand:DI 0 "register_operand" "=*e,d")
-        (plus:DI (match_operand:DI 1 "register_operand" "*0,d")
-                 (match_operand:DI 2 "register_operand" "*e,d")))
+  [(set (match_operand:DI 0 "register_operand" "=e,d")
+        (plus:DI (match_operand:DI 1 "register_operand" "0,d")
+                 (match_operand:DI 2 "register_operand" "e,d")))
   (clobber (reg:CC CC_REGNUM))]
   ""
   "@
@@ -233,17 +326,22 @@
         (minus:SI (match_operand:SI 1 "register_operand" "d")
                   (match_operand:SI 2 "register_operand" "d")))]
   ""
-  "sub     %0, %1, %2"
+{
+  return mdp_select (operands, "sub", false, "", false);
+}
   [(set_attr "type" "arith")
    (set_attr "mode" "SI")])
 
 (define_insn "*subsi3_cmp"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (minus:SI (match_operand:SI 0 "register_operand" "d")
-                                 (match_operand:SI 1 "register_operand" "d"))
-                       (const_int 0)))]
+        (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "d")
+                                 (match_operand:SI 2 "register_operand" "d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d"))]
   ""
-  "%[        sub.c   r1, %0, %1        %]"
+{
+  return mdp_select (operands, "sub", false, "", true);
+}
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
@@ -255,11 +353,10 @@
    (set (reg:CC CC_REGNUM)
         (compare:CC (match_dup 1) (match_dup 2)))]
   ""
-  [(parallel
-       [(set (reg:CC CC_REGNUM)
-             (compare:CC (match_dup 1) (match_dup 2)))
-        (set (match_dup 0)
-             (minus:SI (match_dup 1) (match_dup 2)))])])
+  [(set (reg:CC CC_REGNUM)
+        (compare:CC (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+        (minus:SI (match_dup 1) (match_dup 2)))])
 
 (define_insn "subsi3_ucc_pcmp"
   [(parallel
@@ -270,7 +367,7 @@
              (minus:SI (match_dup 1) (match_dup 2)))])]
   ""
 {
-  return mdp_select (operands, "sub", false, "");
+  return mdp_select (operands, "sub", false, "", true);
 }
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
@@ -285,16 +382,16 @@
         (minus:SI (match_dup 1) (match_dup 2)))]
   ""
 {
-  return mdp_select (operands, "sub", false, "");
+  return mdp_select (operands, "sub", false, "", true);
 }
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
 
 (define_insn "subdi3"
-  [(set (match_operand:DI 0 "register_operand" "=*e,d")
-        (minus:DI (match_operand:DI 1 "register_operand" "*0,d")
-                  (match_operand:DI 2 "register_operand" "*e,d")))
+  [(set (match_operand:DI 0 "register_operand" "=e,d")
+        (minus:DI (match_operand:DI 1 "register_operand" "0,d")
+                  (match_operand:DI 2 "register_operand" "e,d")))
    (clobber (reg:CC CC_REGNUM))]
   ""
   "@
@@ -306,36 +403,47 @@
 (define_insn "andsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
         (and:SI (match_operand:SI 1 "register_operand" "0,0,d,d")
-                (match_operand:SI 2 "arith_operand" "K,Q,M,d")))]
+                (match_operand:SI 2 "arith_operand" "I,K,M,d")))]
   ""
-  "@
-   andi    %0, %c2
-   andis   %0, %U2
-   andri   %0, %1, %c2
-   and     %0, %1, %2"
+{
+  switch (which_alternative)
+    {
+    case 0: return \"andis %0, %U2\";
+    case 1: return \"andi  %0, %c2";
+    case 2: return \"andri %0, %1, %c2\";
+    case 3: return mdp_select (operands, "and", true, "", false);
+    default: gcc_unreachable ();
+    }
+}
   [(set_attr "type" "arith")
    (set_attr "mode" "SI")])
 
 (define_insn "andsi3_cmp"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (and:SI (match_operand:SI 0 "register_operand" "d,d,d,d")
-                               (match_operand:SI 1 "arith_operand" "M,K,Q,d"))
-                       (const_int 0)))]
+        (compare:CC_NZ (and:SI (match_operand:SI 1 "register_operand" "0,0,0,d")
+                               (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d,d,d,d"))]
   ""
-  "@
-   %[        andri.c r1, %0, %c1      %]
-   %[        m%V0    r1, %0\;andi.c  r1, %c1        %]
-   %[        m%V0    r1, %0\;andis.c r1, %U1        %]
-   %[        and.c   r1, %0, %1       %]"
+{
+  switch (which_alternative)
+    {
+    case 0: return \"andis.c %0, %U2\";
+    case 1: return \"andi.c  %0, %c2";
+    case 2: return \"andri.c %0, %1, %c2\";
+    case 3: return mdp_select (operands, "and", true, "", true);
+    default: gcc_unreachable ();
+    }
+}
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
 
-(define_insn "andsi3_ucc"
+(define_insn "*andsi3_ucc"
   [(set (reg:CC_NZ CC_REGNUM)
         (compare:CC_NZ (and:SI
                         (match_operand:SI 1 "register_operand" "0,0,d,d")
-                        (match_operand:SI 2 "arith_operand" "K,Q,M,d"))
+                        (match_operand:SI 2 "arith_operand" "I,K,M,d"))
                        (const_int 0)))
    (set (match_operand:SI 0 "register_operand" "=d,d,d,d")
         (and:SI (match_dup 1) (match_dup 2)))]
@@ -343,10 +451,10 @@
 {
   switch (which_alternative)
     {
-    case 0:  return \"andi.c  %0, %c2\";
-    case 1:  return \"andis.c %0, %U2\";
-    case 2:  return \"andri.c %0, %1, %c2\";
-    case 3:  return mdp_select (operands, "and", true, "");
+    case 0: return \"andis.c %0, %U2\";
+    case 1: return \"andi.c  %0, %c2";
+    case 2: return \"andri.c %0, %1, %c2\";
+    case 3: return mdp_select (operands, "and", true, "", true);
     default: gcc_unreachable ();
     }
 }
@@ -355,12 +463,12 @@
    (set_attr "mode" "SI")])
 
 (define_insn_and_split "*zero_extract_andi"
-  [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (zero_extract:SI
-                        (match_operand:SI 0 "register_operand" "d")
-                        (match_operand:SI 1 "const_bi_operand" "")
-                        (match_operand:SI 2 "const_bi_operand" ""))
-                       (const_int 0)))]
+  [(set (reg:CC CC_REGNUM)
+        (compare:CC (zero_extract:SI
+                     (match_operand:SI 0 "register_operand" "d")
+                     (match_operand:SI 1 "const_uimm5" "")
+                     (match_operand:SI 2 "const_uimm5" ""))
+                    (const_int 0)))]
   ""
   "#"
   ""
@@ -373,26 +481,39 @@
 (define_insn "iorsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
         (ior:SI (match_operand:SI 1 "register_operand" "0,0,d,d")
-                (match_operand:SI 2 "arith_operand" "K,Q,M,d")))]
+                (match_operand:SI 2 "arith_operand" "I,K,M,d")))]
   ""
-  "@
-   ori     %0, %c2
-   oris    %0, %U2
-   orri    %0, %1, %c2
-   or      %0, %1, %2"
+{
+  switch (which_alternative)
+    {
+    case 0: return \"oris %0, %U2\";
+    case 1: return \"ori  %0, %c2\";
+    case 2: return \"orri %0, %1, %c2\";
+    case 3: return mdp_select (operands, "or", true, "", false);
+    default: gcc_unreachable ();
+    }
+}
   [(set_attr "type" "arith")
    (set_attr "mode" "SI")])
 
 (define_insn "iorsi3_ucc"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (ior:SI (match_operand:SI 1 "register_operand" "d")
-                               (match_operand:SI 2 "register_operand" "d"))
+        (compare:CC_NZ (ior:SI
+                        (match_operand:SI 1 "register_operand" "0,0,d,d")
+                        (match_operand:SI 2 "arith_operand" "I,K,M,d"))
                        (const_int 0)))
-   (set (match_operand:SI 0 "register_operand" "=d")
+   (set (match_operand:SI 0 "register_operand" "=d,d,d,d")
         (ior:SI (match_dup 1) (match_dup 2)))]
   ""
 {
-  return mdp_select (operands, "or", true, "");
+  switch (which_alternative)
+    {
+    case 0: return \"oris.c %0, %U2\";
+    case 1: return \"ori.c  %0, %c2\";
+    case 2: return \"orri.c %0, %1, %c2\";
+    case 3: return mdp_select (operands, "or", true, "", true);
+    default: gcc_unreachable ();
+    }
 }
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
@@ -400,11 +521,22 @@
 
 (define_insn "iorsi3_cmp"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (ior:SI (match_operand:SI 0 "register_operand" "d")
-                               (match_operand:SI 1 "register_operand" "d"))
-                       (const_int 0)))]
+        (compare:CC_NZ (ior:SI
+                        (match_operand:SI 1 "register_operand" "0,0,d,d")
+                        (match_operand:SI 2 "arith_operand" "I,K,M,d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d,d,d,d"))]
   ""
-  "%[        or.c    r1, %0, %1       %]"
+{
+  switch (which_alternative)
+    {
+    case 0: return \"oris.c %0, %U2\";
+    case 1: return \"ori.c  %0, %c2\";
+    case 2: return \"orri.c %0, %1, %c2\";
+    case 3: return mdp_select (operands, "or", true, "", true);
+    default: gcc_unreachable ();
+    }
+}
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
@@ -414,7 +546,9 @@
         (xor:SI (match_operand:SI 1 "register_operand" "d")
                 (match_operand:SI 2 "register_operand" "d")))]
   ""
-  "xor     %0, %1, %2"
+{
+  return mdp_select (operands, "xor", true, "", false);
+}
   [(set_attr "type" "arith")
    (set_attr "mode" "SI")])
 
@@ -427,7 +561,7 @@
         (xor:SI (match_dup 1) (match_dup 2)))]
   ""
 {
-  return mdp_select (operands, "xor", true, "");
+  return mdp_select (operands, "xor", true, "", true);
 }
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
@@ -435,11 +569,14 @@
 
 (define_insn "xorsi3_cmp"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (xor:SI (match_operand:SI 0 "register_operand" "d")
-                               (match_operand:SI 1 "register_operand" "d"))
-                       (const_int 0)))]
+        (compare:CC_NZ (xor:SI (match_operand:SI 1 "register_operand" "d")
+                               (match_operand:SI 2 "register_operand" "d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d"))]
   ""
-  "%[        xor.c   r1, %0, %1       %]"
+{
+  return mdp_select (operands, "xor", true, "", true);
+}
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
@@ -459,49 +596,35 @@
   [(set_attr "type" "arith,load")
    (set_attr "mode" "SI")])
 
-(define_insn "extendqisi2_cmp"
+(define_insn "*extendqisi2_ucc"
   [(set (reg:CC_N CC_REGNUM)
         (compare:CC_N (ashiftrt:SI
-                       (ashift:SI (match_operand:SI 0 "register_operand" "d")
+                       (ashift:SI (match_operand:SI 1 "register_operand" "d")
                                   (const_int 24))
                        (const_int 24))
-                      (const_int 0)))]
+                      (const_int 0)))
+   (set (match_operand:SI 0 "register_operand" "=d")
+        (sign_extend:SI (match_operand:QI 2 "register_operand" "0")))]
   ""
-  "%[        extsb.c r1, %0       %]"
+  "extsb.c %0, %1"
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
 
-(define_insn "extendqisi2_ucc"
+(define_insn "*extendqisi2_cmp"
   [(set (reg:CC_N CC_REGNUM)
         (compare:CC_N (ashiftrt:SI
                        (ashift:SI (match_operand:SI 1 "register_operand" "d")
                                   (const_int 24))
                        (const_int 24))
                       (const_int 0)))
-   (set (match_operand:SI 0 "register_operand" "=d")
-        (sign_extend:SI (match_operand:QI 2 "register_operand" "0")))]
+   (clobber (match_scratch:SI 0 "=d"))]
   ""
   "extsb.c %0, %1"
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
 
-(define_insn "zero_extendqisi2"
-  [(set (match_operand:SI 0 "register_operand""=d,d")
-        (zero_extend:SI (match_operand:QI 1 "register_operand" "d,m")))]
-  ""
-{
-  switch (which_alternative)
-    {
-    case 0: return \"extzb   %0, %1\";
-    case 1: return mdp_linsn (operands, MDA_BYTE, false);
-    default: gcc_unreachable ();
-    }
-}
-  [(set_attr "type" "arith, load")
-   (set_attr "mode" "SI")])
-
 (define_insn "extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
@@ -517,34 +640,79 @@
   [(set_attr "type" "arith, load")
    (set_attr "mode" "SI")])
 
-(define_insn "extendhisi2_cmp"
+(define_insn "*extendhisi2_ucc"
   [(set (reg:CC_N CC_REGNUM)
         (compare:CC_N (ashiftrt:SI
-                       (ashift:SI (match_operand:SI 0 "register_operand" "d")
+                       (ashift:SI (match_operand:SI 1 "register_operand" "d")
                                   (const_int 16))
                        (const_int 16))
-                      (const_int 0)))]
+                      (const_int 0)))
+  (set (match_operand:SI 0 "register_operand" "=d")
+       (sign_extend:SI (match_operand:HI 2 "register_operand" "0")))]
   ""
-  "%[        extsh.c r1, %0       %]"
+  "extsh.c %0, %1"
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
 
-(define_insn "extendhisi2_ucc"
+(define_insn "*extendhisi2_cmp"
   [(set (reg:CC_N CC_REGNUM)
         (compare:CC_N (ashiftrt:SI
                        (ashift:SI (match_operand:SI 1 "register_operand" "d")
                                   (const_int 16))
                        (const_int 16))
                       (const_int 0)))
-  (set (match_operand:SI 0 "register_operand" "=d")
-       (sign_extend:SI (match_operand:HI 2 "register_operand" "0")))]
+   (clobber (match_scratch:SI 0 "=d"))]
   ""
   "extsh.c %0, %1"
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
 
+(define_insn "zero_extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "=d,d")
+        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+  ""
+{
+  switch (which_alternative)
+    {
+    case 0: return \"extzb   %0, %1\";
+    case 1: return mdp_linsn (operands, MDA_BYTE, false);
+    default: gcc_unreachable ();
+    }
+  }
+  [(set_attr "type" "arith, load")
+   (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendqisi2_ucc"
+  [(set (reg:CC_N CC_REGNUM)
+        (compare:CC_N (lshiftrt:SI
+                       (ashift:SI (match_operand:SI 1 "register_operand" "d")
+                                  (const_int 24))
+                       (const_int 24))
+                      (const_int 0)))
+   (set (match_operand:SI 0 "register_operand" "=d")
+        (zero_extend:SI (match_operand:QI 2 "register_operand" "0")))]
+  ""
+  "extzb.c %0, %1"
+  [(set_attr "type" "arith")
+   (set_attr "up_c" "yes")
+   (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendqisi2_cmp"
+  [(set (reg:CC_N CC_REGNUM)
+        (compare:CC_N (lshiftrt:SI
+                       (ashift:SI (match_operand:SI 1 "register_operand" "d")
+                                  (const_int 24))
+                       (const_int 24))
+                      (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d"))]
+  ""
+  "extzb.c %0, %1"
+  [(set_attr "type" "arith")
+   (set_attr "up_c" "yes")
+   (set_attr "mode" "SI")])
+
 (define_insn "zero_extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
@@ -560,6 +728,35 @@
   [(set_attr "type" "arith, load")
    (set_attr "mode" "SI")])
 
+(define_insn "*zero_extendhisi2_ucc"
+  [(set (reg:CC_N CC_REGNUM)
+        (compare:CC_N (lshiftrt:SI
+                       (ashift:SI (match_operand:SI 1 "register_operand" "d")
+                                  (const_int 16))
+                       (const_int 16))
+                      (const_int 0)))
+  (set (match_operand:SI 0 "register_operand" "=d")
+       (zero_extend:SI (match_operand:HI 2 "register_operand" "0")))]
+  ""
+  "extzh.c %0, %1"
+  [(set_attr "type" "arith")
+   (set_attr "up_c" "yes")
+   (set_attr "mode" "SI")])
+
+(define_insn "*zero_extendhisi2_cmp"
+  [(set (reg:CC_N CC_REGNUM)
+        (compare:CC_N (lshiftrt:SI
+                       (ashift:SI (match_operand:SI 1 "register_operand" "d")
+                                  (const_int 16))
+                       (const_int 16))
+                      (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d"))]
+  ""
+  "extzh.c %0, %1"
+  [(set_attr "type" "arith")
+   (set_attr "up_c" "yes")
+   (set_attr "mode" "SI")])
+
 (define_insn "mulsi3"
   [(set (match_operand:SI 0 "register_operand" "=l")
         (mult:SI (match_operand:SI 1 "register_operand" "d")
@@ -572,7 +769,8 @@
 
 (define_insn "mulsidi3"
   [(set (match_operand:DI 0 "register_operand" "=x")
-        (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
+        (mult:DI (sign_extend:DI
+                  (match_operand:SI 1 "register_operand" "d"))
                  (sign_extend:DI
                   (match_operand:SI 2 "register_operand" "d"))))]
   "!TARGET_SCORE5U"
@@ -582,7 +780,8 @@
 
 (define_insn "umulsidi3"
   [(set (match_operand:DI 0 "register_operand" "=x")
-        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
+        (mult:DI (zero_extend:DI
+                  (match_operand:SI 1 "register_operand" "d"))
                  (zero_extend:DI
                   (match_operand:SI 2 "register_operand" "d"))))]
   "!TARGET_SCORE5U"
@@ -635,8 +834,8 @@
 {
   switch (which_alternative)
     {
-    case 0: return mdp_select (operands, "slli", false, "c");
-    case 1: return mdp_select (operands, "sll", false, "");
+    case 0: return mdp_select (operands, "slli", false, "c", true);
+    case 1: return mdp_select (operands, "sll", false, "", true);
     default: gcc_unreachable ();
     }
 }
@@ -647,13 +846,19 @@
 (define_insn "ashlsi3_cmp"
   [(set (reg:CC_NZ CC_REGNUM)
         (compare:CC_NZ (ashift:SI
-                        (match_operand:SI 0 "register_operand" "d,d")
-                        (match_operand:SI 1 "arith_operand" "J,d"))
-                       (const_int 0)))]
+                        (match_operand:SI 1 "register_operand" "d,d")
+                        (match_operand:SI 2 "arith_operand" "J,d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d,d"))]
   ""
-  "@
-   %[        slli.c  r1, %0, %c1      %]
-   %[        sll.c   r1, %0, %1       %]"
+{
+  switch (which_alternative)
+    {
+    case 0: return mdp_select (operands, "slli", false, "c", true);
+    case 1: return mdp_select (operands, "sll", false, "", true);
+    default: gcc_unreachable ();
+    }
+}
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
@@ -682,7 +887,7 @@
   switch (which_alternative)
     {
     case 0: return \"srai.c  %0, %1, %c2\";
-    case 1: return mdp_select (operands, "sra", false, "");
+    case 1: return mdp_select (operands, "sra", false, "", true);
     default: gcc_unreachable ();
     }
 }
@@ -693,31 +898,16 @@
 (define_insn "ashrsi3_cmp"
   [(set (reg:CC_NZ CC_REGNUM)
         (compare:CC_NZ (ashiftrt:SI
-                        (match_operand:SI 0 "register_operand" "d,d")
-                        (match_operand:SI 1 "arith_operand" "J,d"))
-                       (const_int 0)))]
-  ""
-  "@
-   %[        srai.c  r1, %0, %c1      %]
-   %[        sra.c   r1, %0, %1       %]"
-  [(set_attr "type" "arith")
-   (set_attr "up_c" "yes")
-   (set_attr "mode" "SI")])
-
-(define_insn "ashrsi3_ucc_n"
-  [(set (reg:CC_N CC_REGNUM)
-        (compare:CC_N (ashiftrt:SI
-                       (match_operand:SI 1 "register_operand" "d,d")
-                       (match_operand:SI 2 "arith_operand" "J,d"))
-                      (const_int 0)))
-   (set (match_operand:SI 0 "register_operand" "=d,d")
-        (ashiftrt:SI (match_dup 1) (match_dup 2)))]
+                        (match_operand:SI 1 "register_operand" "d,d")
+                        (match_operand:SI 2 "arith_operand" "J,d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d,d"))]
   ""
 {
   switch (which_alternative)
     {
     case 0: return \"srai.c  %0, %1, %c2\";
-    case 1: return mdp_select (operands, "sra", false, "");
+    case 1: return mdp_select (operands, "sra", false, "", true);
     default: gcc_unreachable ();
     }
 }
@@ -725,20 +915,6 @@
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
 
-(define_insn "ashrsi3_cmp_n"
-  [(set (reg:CC_N CC_REGNUM)
-        (compare:CC_N (ashiftrt:SI
-                       (match_operand:SI 0 "register_operand" "d,d")
-                       (match_operand:SI 1 "arith_operand" "J,d"))
-                      (const_int 0)))]
-  ""
-  "@
-   %[        srai.c  r1, %0, %c1      %]
-   %[        sra.c   r1, %0, %1       %]"
-  [(set_attr "type" "arith")
-   (set_attr "up_c" "yes")
-   (set_attr "mode" "SI")])
-
 (define_insn "lshrsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d")
         (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d")
@@ -762,8 +938,8 @@
 {
   switch (which_alternative)
     {
-    case 0: return mdp_select (operands, "srli", false, "c");
-    case 1: return mdp_select (operands, "srl", false, "");
+    case 0: return mdp_select (operands, "srli", false, "c", true);
+    case 1: return mdp_select (operands, "srl", false, "", true);
     default: gcc_unreachable ();
     }
 }
@@ -774,13 +950,19 @@
 (define_insn "lshrsi3_cmp"
   [(set (reg:CC_NZ CC_REGNUM)
         (compare:CC_NZ (lshiftrt:SI
-                        (match_operand:SI 0 "register_operand" "d,d")
-                        (match_operand:SI 1 "arith_operand" "J,d"))
-                       (const_int 0)))]
+                        (match_operand:SI 1 "register_operand" "d,d")
+                        (match_operand:SI 2 "arith_operand" "J,d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=d,d"))]
   ""
-  "@
-   %[        srli.c  r1, %0, %c1      %]
-   %[        srl.c   r1, %0, %1       %]"
+{
+  switch (which_alternative)
+    {
+    case 0: return mdp_select (operands, "srli", false, "c", true);
+    case 1: return mdp_select (operands, "srl", false, "", true);
+    default: gcc_unreachable ();
+    }
+}
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
@@ -793,11 +975,24 @@
   [(set_attr "type" "arith")
    (set_attr "mode" "SI")])
 
+(define_insn "*negsi2_cmp"
+  [(set (reg:CC_NZ CC_REGNUM)
+        (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "e,d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=e,d"))]
+  ""
+  "@
+   neg!    %0, %1
+   neg.c   %0, %1"
+  [(set_attr "type" "arith")
+   (set_attr "up_c" "yes")
+   (set_attr "mode" "SI")])
+
 (define_insn "negsi2_ucc"
-  [(set (reg:CC CC_REGNUM)
-        (compare:CC (neg:SI (match_operand:SI 1 "register_operand" "*e,d"))
-                    (const_int 0)))
-   (set (match_operand:SI 0 "register_operand" "=*e,d")
+  [(set (reg:CC_NZ CC_REGNUM)
+        (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "e,d"))
+                       (const_int 0)))
+   (set (match_operand:SI 0 "register_operand" "=e,d")
         (neg:SI (match_dup 1)))]
   ""
   "@
@@ -817,9 +1012,9 @@
 
 (define_insn "one_cmplsi2_ucc"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "*e,d"))
+        (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "e,d"))
                        (const_int 0)))
-   (set (match_operand:SI 0 "register_operand" "=*e,d")
+   (set (match_operand:SI 0 "register_operand" "=e,d")
         (not:SI (match_dup 1)))]
   ""
   "@
@@ -831,12 +1026,13 @@
 
 (define_insn "one_cmplsi2_cmp"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (not:SI (match_operand:SI 0 "register_operand" "*e,d"))
-                       (const_int 0)))]
+        (compare:CC_NZ (not:SI (match_operand:SI 1 "register_operand" "e,d"))
+                       (const_int 0)))
+   (clobber (match_scratch:SI 0 "=e,d"))]
   ""
   "@
-   %[        not!    r1, %0       %]
-   %[        not.c   r1, %0       %]"
+   not!    %0, %1
+   not.c   %0, %1"
   [(set_attr "type" "arith")
    (set_attr "up_c" "yes")
    (set_attr "mode" "SI")])
@@ -877,8 +1073,8 @@
 
 (define_insn "cmpsi_nz"
   [(set (reg:CC_NZ CC_REGNUM)
-        (compare:CC_NZ (match_operand:SI 0 "register_operand" "d,*e,d")
-                       (match_operand:SI 1 "arith_operand" "L,*e,d")))]
+        (compare:CC_NZ (match_operand:SI 0 "register_operand" "d,e,d")
+                       (match_operand:SI 1 "arith_operand" "L,e,d")))]
   ""
   "@
    cmpi.c  %0, %c1
@@ -890,8 +1086,8 @@
 
 (define_insn "cmpsi_n"
   [(set (reg:CC_N CC_REGNUM)
-        (compare:CC_N (match_operand:SI 0 "register_operand" "d,*e,d")
-                      (match_operand:SI 1 "arith_operand" "L,*e,d")))]
+        (compare:CC_N (match_operand:SI 0 "register_operand" "d,e,d")
+                      (match_operand:SI 1 "arith_operand" "L,e,d")))]
   ""
   "@
    cmpi.c  %0, %c1
@@ -901,10 +1097,23 @@
     (set_attr "up_c" "yes")
     (set_attr "mode" "SI")])
 
+(define_insn "*cmpsi_to_addsi"
+  [(set (reg:CC_NZ CC_REGNUM)
+        (compare:CC_NZ (match_operand:SI 1 "register_operand" "0,d")
+                       (neg:SI (match_operand:SI 2 "register_operand" "e,d"))))
+   (clobber (match_scratch:SI 0 "=e,d"))]
+  ""
+  "@
+   add!    %0, %2
+   add.c   %0, %1, %2"
+   [(set_attr "type" "cmp")
+    (set_attr "up_c" "yes")
+    (set_attr "mode" "SI")])
+
 (define_insn "cmpsi_cc"
   [(set (reg:CC CC_REGNUM)
-        (compare:CC (match_operand:SI 0 "register_operand" "d,*e,d")
-                    (match_operand:SI 1 "arith_operand" "L,*e,d")))]
+        (compare:CC (match_operand:SI 0 "register_operand" "d,e,d")
+                    (match_operand:SI 1 "arith_operand" "L,e,d")))]
   ""
   "@
    cmpi.c  %0, %c1
@@ -1078,17 +1287,17 @@
    (clobber (reg:SI RT_REGNUM))]
   "SIBLING_CALL_P (insn)"
 {
-  if (!flag_pic) 
-    switch (which_alternative) 
+  if (!flag_pic)
+    switch (which_alternative)
       {
       case 0: return \"br%S0   %0\";
       case 1: return \"j       %0\";
       default: gcc_unreachable ();
       }
   else
-    switch (which_alternative) 
+    switch (which_alternative)
       {
-      case 0: return \"mv      r29, %0\;.cpadd  r29\;br      r29\";
+      case 0: return \"mv      r29, %0\;br      r29\";
       case 1: return \"la      r29, %0\;br      r29\";
       default: gcc_unreachable ();
       }
@@ -1112,17 +1321,17 @@
    (clobber (reg:SI RT_REGNUM))]
   "SIBLING_CALL_P (insn)"
 {
-  if (!flag_pic) 
-    switch (which_alternative) 
+  if (!flag_pic)
+    switch (which_alternative)
       {
       case 0: return \"br%S1   %1\";
       case 1: return \"j       %1\";
       default: gcc_unreachable ();
       }
   else
-    switch (which_alternative) 
+    switch (which_alternative)
       {
-      case 0: return \"mv      r29, %1\;.cpadd  r29\;br      r29\";
+      case 0: return \"mv      r29, %1\;br      r29\";
       case 1: return \"la      r29, %1\;br      r29\";
       default: gcc_unreachable ();
       }
@@ -1154,7 +1363,7 @@
   else
      switch (which_alternative)
       {
-      case 0: return \"mv      r29, %0\;.cpadd  r29\;brl     r29\";
+      case 0: return \"mv      r29, %0\;brl     r29\";
       case 1: return \"la      r29, %0\;brl     r29\";
       default: gcc_unreachable ();
       }
@@ -1163,7 +1372,7 @@
 
 (define_expand "call_value"
   [(parallel [(set (match_operand 0 "" "")
-              (call (match_operand 1 "" "") (match_operand 2 "" "")))
+                   (call (match_operand 1 "" "") (match_operand 2 "" "")))
               (use (match_operand 3 "" ""))])]
   ""
 {
@@ -1188,7 +1397,7 @@
   else
     switch (which_alternative)
       {
-      case 0: return \"mv      r29, %1\;.cpadd  r29\;brl     r29\";
+      case 0: return \"mv      r29, %1\;brl     r29\";
       case 1: return \"la      r29, %1\;brl     r29\";
       default: gcc_unreachable ();
       }
@@ -1277,13 +1486,59 @@
 )
 
 (define_insn "cpload"
-  [(unspec:SI [(const_int 1)] 1)]
+  [(unspec_volatile:SI [(const_int 1)] CPLOAD)]
   "flag_pic"
   ".cpload r29"
 )
 
-(define_insn "cprestore"
-  [(unspec:SI [(match_operand:SI 0 "" "")] 2)]
+(define_insn "cprestore_use_fp"
+  [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE)
+   (use (reg:SI FP_REGNUM))]
   "flag_pic"
-  ".cprestore %0"
+  ".cprestore r2, %0"
 )
+
+(define_insn "cprestore_use_sp"
+  [(unspec_volatile:SI [(match_operand:SI 0 "" "")] CPRESTORE)
+   (use (reg:SI SP_REGNUM))]
+  "flag_pic"
+  ".cprestore r0, %0"
+)
+
+(define_expand "doloop_end"
+  [(use (match_operand 0 "" ""))    ; loop pseudo
+   (use (match_operand 1 "" ""))    ; iterations; zero if unknown
+   (use (match_operand 2 "" ""))    ; max iterations
+   (use (match_operand 3 "" ""))    ; loop level
+   (use (match_operand 4 "" ""))]   ; label
+  ""
+  {
+    if (INTVAL (operands[3]) > 1)
+      FAIL;
+
+    if (GET_MODE (operands[0]) == SImode)
+      {
+        rtx sr0 = gen_rtx_REG (SImode, CN_REGNUM);
+        emit_jump_insn (gen_doloop_end_si (sr0, operands[4]));
+      }
+    else
+      FAIL;
+
+    DONE;
+  })
+
+(define_insn "doloop_end_si"
+  [(set (pc)
+        (if_then_else
+         (ne (match_operand:SI 0 "sr0_operand" "")
+             (const_int 0))
+         (label_ref (match_operand 1 "" ""))
+         (pc)))
+   (set (match_dup 0)
+        (plus:SI (match_dup 0)
+                 (const_int -1)))
+   (clobber (reg:CC CC_REGNUM))
+]
+  ""
+  "bcnz %1"
+  [(set_attr "type" "branch")])
Index: gcc/config/score/score-modes.def
===================================================================
--- gcc/config/score/score-modes.def	(revision 120252)
+++ gcc/config/score/score-modes.def	(working copy)
@@ -21,6 +21,5 @@
 /* CC_NZmode should be used if the N (sign) and Z (zero) flag is set correctly.
    CC_Nmode should be used if only the N flag is set correctly.  */
 
-CC_MODE (CC_NZ);
 CC_MODE (CC_N);
-
+CC_MODE (CC_NZ);
Index: gcc/config/score/score-mdaux.h
===================================================================
--- gcc/config/score/score-mdaux.h	(revision 120252)
+++ gcc/config/score/score-mdaux.h	(working copy)
@@ -69,8 +69,6 @@ void mda_gen_cmp (enum machine_mode mode
 
 int mda_symbolic_constant_p (rtx x, enum score_symbol_type *symbol_type);
 
-bool mda_pindex_mem (rtx addr);
-
 int mda_bp (void);
 
 /* Machine Expand.  */
@@ -87,8 +85,6 @@ void mdx_call_value (rtx *ops, bool sibc
 /* Machine Split.  */
 void mds_movdi (rtx *ops);
 
-void mds_addsi (rtx *ops);
-
 void mds_zero_extract_andi (rtx *ops);
 
 /* Machine Print.  */
@@ -100,14 +96,21 @@ const char * mdp_linsn (rtx *ops, enum m
 
 const char * mdp_sinsn (rtx *ops, enum mda_mem_unit unit);
 
-const char * mdp_add_imm_ucc (rtx *ops);
+const char * mdp_select_add_imm (rtx *ops, bool set_cc);
 
 const char * mdp_select (rtx *ops, const char *inst_pre,
-                        bool comu, const char *let);
+                        bool commu, const char *letter, bool set_cc);
 
 const char * mdp_limm (rtx *ops);
 
 const char * mdp_move (rtx *ops);
 
+/* Machine unaligned memory load/store. */
+bool mdx_unaligned_load (rtx* ops);
+
+bool mdx_unaligned_store (rtx* ops);
+
+bool mdx_block_move (rtx* ops);
+
 #endif
 
Index: gcc/config/score/mul-div.S
===================================================================
--- gcc/config/score/mul-div.S	(revision 120252)
+++ gcc/config/score/mul-div.S	(working copy)
@@ -242,7 +242,7 @@ _flush_cache:
         #nop!
         addi    r8, 16
         bcnz    2b
-        .cprestore      12              # pic used
+        .cprestore r0, 12               # pic used
         addi    r0, 8                   # pic used
         br      r3
 #endif
@@ -278,7 +278,7 @@ __mulsi3_loop2:
         cmpi.c  a1, 0
         bne     __mulsi3_loop
         mv      r4, t1
-        .cprestore 12                   # pic used
+        .cprestore r0, 12               # pic used
         addi    r0, 8                   # pic used
         br      ra
         .end    __mulsi3
@@ -334,7 +334,7 @@ __uds_loop3:
 __uds_exit:
         mv      a1, a0
         mv      r4, t4
-        .cprestore 12                   # pic used
+        .cprestore r0, 12               # pic used
         addi    r0, 8                   # pic used
         br      ra
         .end    __udivsi3
@@ -350,7 +350,7 @@ __umodsi3:
         la      r29, __udivsi3
         brl     r29
         mv      r4, a1
-        .cprestore 12                   # pic used
+        .cprestore r0, 12               # pic used
         addi    r0, 8                   # pic used
         br      t3
         .end    __umodsi3
@@ -383,7 +383,7 @@ __divsi3_adjust:
         bge     __divsi3_exit
         neg     r4, r4
 __divsi3_exit:
-        .cprestore 12                   # pic used
+        .cprestore r0, 12               # pic used
         addi    r0, 8                   # pic used
         br      t3
         .end    __divsi3
