diff options
Diffstat (limited to 'arch/mips/mm/pg-r4k.c')
-rw-r--r-- | arch/mips/mm/pg-r4k.c | 66 |
1 files changed, 31 insertions, 35 deletions
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c index 4f770ac885ce..9185fbf37c0d 100644 --- a/arch/mips/mm/pg-r4k.c +++ b/arch/mips/mm/pg-r4k.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2003, 04, 05 Ralf Baechle (ralf@linux-mips.org) | 6 | * Copyright (C) 2003, 04, 05 Ralf Baechle (ralf@linux-mips.org) |
7 | * Copyright (C) 2007 Maciej W. Rozycki | ||
7 | */ | 8 | */ |
8 | #include <linux/init.h> | 9 | #include <linux/init.h> |
9 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
@@ -12,6 +13,7 @@ | |||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/proc_fs.h> | 14 | #include <linux/proc_fs.h> |
14 | 15 | ||
16 | #include <asm/bugs.h> | ||
15 | #include <asm/cacheops.h> | 17 | #include <asm/cacheops.h> |
16 | #include <asm/inst.h> | 18 | #include <asm/inst.h> |
17 | #include <asm/io.h> | 19 | #include <asm/io.h> |
@@ -255,64 +257,58 @@ static inline void build_store_reg(int reg) | |||
255 | __build_store_reg(reg); | 257 | __build_store_reg(reg); |
256 | } | 258 | } |
257 | 259 | ||
258 | static inline void build_addiu_a2_a0(unsigned long offset) | 260 | static inline void build_addiu_rt_rs(unsigned int rt, unsigned int rs, |
261 | unsigned long offset) | ||
259 | { | 262 | { |
260 | union mips_instruction mi; | 263 | union mips_instruction mi; |
261 | 264 | ||
262 | BUG_ON(offset > 0x7fff); | 265 | BUG_ON(offset > 0x7fff); |
263 | 266 | ||
264 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; | 267 | if (cpu_has_64bit_gp_regs && DADDI_WAR && r4k_daddiu_bug()) { |
265 | mi.i_format.rs = 4; /* $a0 */ | 268 | mi.i_format.opcode = addiu_op; |
266 | mi.i_format.rt = 6; /* $a2 */ | 269 | mi.i_format.rs = 0; /* $zero */ |
267 | mi.i_format.simmediate = offset; | 270 | mi.i_format.rt = 25; /* $t9 */ |
271 | mi.i_format.simmediate = offset; | ||
272 | emit_instruction(mi); | ||
268 | 273 | ||
274 | mi.r_format.opcode = spec_op; | ||
275 | mi.r_format.rs = rs; | ||
276 | mi.r_format.rt = 25; /* $t9 */ | ||
277 | mi.r_format.rd = rt; | ||
278 | mi.r_format.re = 0; | ||
279 | mi.r_format.func = daddu_op; | ||
280 | } else { | ||
281 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? | ||
282 | daddiu_op : addiu_op; | ||
283 | mi.i_format.rs = rs; | ||
284 | mi.i_format.rt = rt; | ||
285 | mi.i_format.simmediate = offset; | ||
286 | } | ||
269 | emit_instruction(mi); | 287 | emit_instruction(mi); |
270 | } | 288 | } |
271 | 289 | ||
272 | static inline void build_addiu_a2(unsigned long offset) | 290 | static inline void build_addiu_a2_a0(unsigned long offset) |
273 | { | 291 | { |
274 | union mips_instruction mi; | 292 | build_addiu_rt_rs(6, 4, offset); /* $a2, $a0, offset */ |
275 | 293 | } | |
276 | BUG_ON(offset > 0x7fff); | ||
277 | |||
278 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; | ||
279 | mi.i_format.rs = 6; /* $a2 */ | ||
280 | mi.i_format.rt = 6; /* $a2 */ | ||
281 | mi.i_format.simmediate = offset; | ||
282 | 294 | ||
283 | emit_instruction(mi); | 295 | static inline void build_addiu_a2(unsigned long offset) |
296 | { | ||
297 | build_addiu_rt_rs(6, 6, offset); /* $a2, $a2, offset */ | ||
284 | } | 298 | } |
285 | 299 | ||
286 | static inline void build_addiu_a1(unsigned long offset) | 300 | static inline void build_addiu_a1(unsigned long offset) |
287 | { | 301 | { |
288 | union mips_instruction mi; | 302 | build_addiu_rt_rs(5, 5, offset); /* $a1, $a1, offset */ |
289 | |||
290 | BUG_ON(offset > 0x7fff); | ||
291 | |||
292 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; | ||
293 | mi.i_format.rs = 5; /* $a1 */ | ||
294 | mi.i_format.rt = 5; /* $a1 */ | ||
295 | mi.i_format.simmediate = offset; | ||
296 | 303 | ||
297 | load_offset -= offset; | 304 | load_offset -= offset; |
298 | |||
299 | emit_instruction(mi); | ||
300 | } | 305 | } |
301 | 306 | ||
302 | static inline void build_addiu_a0(unsigned long offset) | 307 | static inline void build_addiu_a0(unsigned long offset) |
303 | { | 308 | { |
304 | union mips_instruction mi; | 309 | build_addiu_rt_rs(4, 4, offset); /* $a0, $a0, offset */ |
305 | |||
306 | BUG_ON(offset > 0x7fff); | ||
307 | |||
308 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; | ||
309 | mi.i_format.rs = 4; /* $a0 */ | ||
310 | mi.i_format.rt = 4; /* $a0 */ | ||
311 | mi.i_format.simmediate = offset; | ||
312 | 310 | ||
313 | store_offset -= offset; | 311 | store_offset -= offset; |
314 | |||
315 | emit_instruction(mi); | ||
316 | } | 312 | } |
317 | 313 | ||
318 | static inline void build_bne(unsigned int *dest) | 314 | static inline void build_bne(unsigned int *dest) |