fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / mips / mm / pg-r4k.c
index f51e180..dc795be 100644 (file)
@@ -124,7 +124,7 @@ static inline void build_nop(void)
 
 static inline void build_src_pref(int advance)
 {
-       if (!(load_offset & (cpu_dcache_line_size() - 1))) {
+       if (!(load_offset & (cpu_dcache_line_size() - 1)) && advance) {
                union mips_instruction mi;
 
                mi.i_format.opcode     = pref_op;
@@ -166,7 +166,7 @@ static inline void build_load_reg(int reg)
 
 static inline void build_dst_pref(int advance)
 {
-       if (!(store_offset & (cpu_dcache_line_size() - 1))) {
+       if (!(store_offset & (cpu_dcache_line_size() - 1)) && advance) {
                union mips_instruction mi;
 
                mi.i_format.opcode     = pref_op;
@@ -243,11 +243,10 @@ static void __init __build_store_reg(int reg)
 
 static inline void build_store_reg(int reg)
 {
-       if (cpu_has_prefetch)
-               if (reg)
-                       build_dst_pref(pref_offset_copy);
-               else
-                       build_dst_pref(pref_offset_clear);
+       int pref_off = cpu_has_prefetch ?
+               (reg ? pref_offset_copy : pref_offset_clear) : 0;
+       if (pref_off)
+               build_dst_pref(pref_off);
        else if (cpu_has_cache_cdex_s)
                build_cdex_s();
        else if (cpu_has_cache_cdex_p)
@@ -270,6 +269,20 @@ static inline void build_addiu_a2_a0(unsigned long offset)
        emit_instruction(mi);
 }
 
+static inline void build_addiu_a2(unsigned long offset)
+{
+       union mips_instruction mi;
+
+       BUG_ON(offset > 0x7fff);
+
+       mi.i_format.opcode     = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op;
+       mi.i_format.rs         = 6;             /* $a2 */
+       mi.i_format.rt         = 6;             /* $a2 */
+       mi.i_format.simmediate = offset;
+
+       emit_instruction(mi);
+}
+
 static inline void build_addiu_a1(unsigned long offset)
 {
        union mips_instruction mi;
@@ -333,6 +346,7 @@ static inline void build_jr_ra(void)
 void __init build_clear_page(void)
 {
        unsigned int loop_start;
+       unsigned long off;
 
        epc = (unsigned int *) &clear_page_array;
        instruction_pending = 0;
@@ -340,6 +354,12 @@ void __init build_clear_page(void)
 
        if (cpu_has_prefetch) {
                switch (current_cpu_data.cputype) {
+               case CPU_TX49XX:
+                       /* TX49 supports only Pref_Load */
+                       pref_offset_clear = 0;
+                       pref_offset_copy = 0;
+                       break;
+
                case CPU_RM9000:
                        /*
                         * As a workaround for erratum G105 which make the
@@ -351,6 +371,7 @@ void __init build_clear_page(void)
 
                case CPU_R10000:
                case CPU_R12000:
+               case CPU_R14000:
                        pref_src_mode = Pref_LoadStreamed;
                        pref_dst_mode = Pref_StoreStreamed;
                        break;
@@ -362,7 +383,12 @@ void __init build_clear_page(void)
                }
        }
 
-       build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0));
+        off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0);
+       if (off > 0x7fff) {
+               build_addiu_a2_a0(off >> 1);
+               build_addiu_a2(off >> 1);
+       } else
+               build_addiu_a2_a0(off);
 
        if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
                build_insn_word(0x3c01a000);    /* lui     $at, 0xa000  */
@@ -413,12 +439,18 @@ dest = label();
 void __init build_copy_page(void)
 {
        unsigned int loop_start;
+       unsigned long off;
 
        epc = (unsigned int *) &copy_page_array;
        store_offset = load_offset = 0;
        instruction_pending = 0;
 
-       build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0));
+       off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0);
+       if (off > 0x7fff) {
+               build_addiu_a2_a0(off >> 1);
+               build_addiu_a2(off >> 1);
+       } else
+               build_addiu_a2_a0(off);
 
        if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
                build_insn_word(0x3c01a000);    /* lui     $at, 0xa000  */