1a583158cSAtsushi Nemoto/* 2a583158cSAtsushi Nemoto * This file is subject to the terms and conditions of the GNU General Public 3a583158cSAtsushi Nemoto * License. See the file "COPYING" in the main directory of this archive 4a583158cSAtsushi Nemoto * for more details. 5a583158cSAtsushi Nemoto * 6a583158cSAtsushi Nemoto * Copyright (C) 1998, 1999, 2000 by Ralf Baechle 7a583158cSAtsushi Nemoto * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 826c5e07dSSteven J. Hill * Copyright (C) 2007 by Maciej W. Rozycki 926c5e07dSSteven J. Hill * Copyright (C) 2011, 2012 MIPS Technologies, Inc. 10a583158cSAtsushi Nemoto */ 11a583158cSAtsushi Nemoto#include <asm/asm.h> 12a583158cSAtsushi Nemoto#include <asm/asm-offsets.h> 13576a2f0cSPaul Burton#include <asm/export.h> 14a583158cSAtsushi Nemoto#include <asm/regdef.h> 15a583158cSAtsushi Nemoto 16a583158cSAtsushi Nemoto#if LONGSIZE == 4 17a583158cSAtsushi Nemoto#define LONG_S_L swl 18a583158cSAtsushi Nemoto#define LONG_S_R swr 19a583158cSAtsushi Nemoto#else 20a583158cSAtsushi Nemoto#define LONG_S_L sdl 21a583158cSAtsushi Nemoto#define LONG_S_R sdr 22a583158cSAtsushi Nemoto#endif 23a583158cSAtsushi Nemoto 2426c5e07dSSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS 2526c5e07dSSteven J. Hill#define STORSIZE (LONGSIZE * 2) 2626c5e07dSSteven J. Hill#define STORMASK (STORSIZE - 1) 2726c5e07dSSteven J. Hill#define FILL64RG t8 2826c5e07dSSteven J. Hill#define FILLPTRG t7 2926c5e07dSSteven J. Hill#undef LONG_S 3026c5e07dSSteven J. Hill#define LONG_S LONG_SP 3126c5e07dSSteven J. Hill#else 3226c5e07dSSteven J. Hill#define STORSIZE LONGSIZE 3326c5e07dSSteven J. Hill#define STORMASK LONGMASK 3426c5e07dSSteven J. Hill#define FILL64RG a1 3526c5e07dSSteven J. Hill#define FILLPTRG t0 3626c5e07dSSteven J. Hill#endif 3726c5e07dSSteven J. Hill 386d5155c2SMarkos Chandras#define LEGACY_MODE 1 396d5155c2SMarkos Chandras#define EVA_MODE 2 406d5155c2SMarkos Chandras 41fd9720e9SMarkos Chandras/* 42fd9720e9SMarkos Chandras * No need to protect it with EVA #ifdefery. The generated block of code 43fd9720e9SMarkos Chandras * will never be assembled if EVA is not enabled. 44fd9720e9SMarkos Chandras */ 45fd9720e9SMarkos Chandras#define __EVAFY(insn, reg, addr) __BUILD_EVA_INSN(insn##e, reg, addr) 46fd9720e9SMarkos Chandras#define ___BUILD_EVA_INSN(insn, reg, addr) __EVAFY(insn, reg, addr) 47fd9720e9SMarkos Chandras 48a583158cSAtsushi Nemoto#define EX(insn,reg,addr,handler) \ 49fd9720e9SMarkos Chandras .if \mode == LEGACY_MODE; \ 50a583158cSAtsushi Nemoto9: insn reg, addr; \ 51fd9720e9SMarkos Chandras .else; \ 52fd9720e9SMarkos Chandras9: ___BUILD_EVA_INSN(insn, reg, addr); \ 53fd9720e9SMarkos Chandras .endif; \ 54a583158cSAtsushi Nemoto .section __ex_table,"a"; \ 55a583158cSAtsushi Nemoto PTR 9b, handler; \ 56a583158cSAtsushi Nemoto .previous 57a583158cSAtsushi Nemoto 58fd9720e9SMarkos Chandras .macro f_fill64 dst, offset, val, fixup, mode 5926c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 0 * STORSIZE)(\dst), \fixup) 6026c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 1 * STORSIZE)(\dst), \fixup) 6126c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 2 * STORSIZE)(\dst), \fixup) 6226c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 3 * STORSIZE)(\dst), \fixup) 6326c5e07dSSteven J. Hill#if ((defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) || !defined(CONFIG_CPU_MICROMIPS)) 6426c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 4 * STORSIZE)(\dst), \fixup) 6526c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 5 * STORSIZE)(\dst), \fixup) 6626c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 6 * STORSIZE)(\dst), \fixup) 6726c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 7 * STORSIZE)(\dst), \fixup) 6826c5e07dSSteven J. Hill#endif 6926c5e07dSSteven J. Hill#if (!defined(CONFIG_CPU_MICROMIPS) && (LONGSIZE == 4)) 7026c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 8 * STORSIZE)(\dst), \fixup) 7126c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 9 * STORSIZE)(\dst), \fixup) 7226c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 10 * STORSIZE)(\dst), \fixup) 7326c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 11 * STORSIZE)(\dst), \fixup) 7426c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 12 * STORSIZE)(\dst), \fixup) 7526c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 13 * STORSIZE)(\dst), \fixup) 7626c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 14 * STORSIZE)(\dst), \fixup) 7726c5e07dSSteven J. Hill EX(LONG_S, \val, (\offset + 15 * STORSIZE)(\dst), \fixup) 78a583158cSAtsushi Nemoto#endif 79a583158cSAtsushi Nemoto .endm 80a583158cSAtsushi Nemoto 81a583158cSAtsushi Nemoto .set noreorder 82a583158cSAtsushi Nemoto .align 5 83a583158cSAtsushi Nemoto 846d5155c2SMarkos Chandras /* 856d5155c2SMarkos Chandras * Macro to generate the __bzero{,_user} symbol 866d5155c2SMarkos Chandras * Arguments: 876d5155c2SMarkos Chandras * mode: LEGACY_MODE or EVA_MODE 886d5155c2SMarkos Chandras */ 896d5155c2SMarkos Chandras .macro __BUILD_BZERO mode 906d5155c2SMarkos Chandras /* Initialize __memset if this is the first time we call this macro */ 916d5155c2SMarkos Chandras .ifnotdef __memset 926d5155c2SMarkos Chandras .set __memset, 1 936d5155c2SMarkos Chandras .hidden __memset /* Make sure it does not leak */ 946d5155c2SMarkos Chandras .endif 95a583158cSAtsushi Nemoto 9626c5e07dSSteven J. Hill sltiu t0, a2, STORSIZE /* very small region? */ 976d5155c2SMarkos Chandras bnez t0, .Lsmall_memset\@ 9826c5e07dSSteven J. Hill andi t0, a0, STORMASK /* aligned? */ 99a583158cSAtsushi Nemoto 10026c5e07dSSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS 10126c5e07dSSteven J. Hill move t8, a1 /* used by 'swp' instruction */ 10226c5e07dSSteven J. Hill move t9, a1 10326c5e07dSSteven J. Hill#endif 104619b6e18SMaciej W. Rozycki#ifndef CONFIG_CPU_DADDI_WORKAROUNDS 105a583158cSAtsushi Nemoto beqz t0, 1f 10626c5e07dSSteven J. Hill PTR_SUBU t0, STORSIZE /* alignment in bytes */ 107619b6e18SMaciej W. Rozycki#else 108619b6e18SMaciej W. Rozycki .set noat 10926c5e07dSSteven J. Hill li AT, STORSIZE 110619b6e18SMaciej W. Rozycki beqz t0, 1f 111619b6e18SMaciej W. Rozycki PTR_SUBU t0, AT /* alignment in bytes */ 112619b6e18SMaciej W. Rozycki .set at 113619b6e18SMaciej W. Rozycki#endif 114a583158cSAtsushi Nemoto 1158c56208aSLeonid Yegoshin#ifndef CONFIG_CPU_MIPSR6 116930bff88SThomas Bogendoerfer R10KCBARRIER(0(ra)) 117a583158cSAtsushi Nemoto#ifdef __MIPSEB__ 1186d5155c2SMarkos Chandras EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ 119dd2adea4SMarkos Chandras#else 1206d5155c2SMarkos Chandras EX(LONG_S_R, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */ 121a583158cSAtsushi Nemoto#endif 122a583158cSAtsushi Nemoto PTR_SUBU a0, t0 /* long align ptr */ 123a583158cSAtsushi Nemoto PTR_ADDU a2, t0 /* correct size */ 124a583158cSAtsushi Nemoto 1258c56208aSLeonid Yegoshin#else /* CONFIG_CPU_MIPSR6 */ 1268c56208aSLeonid Yegoshin#define STORE_BYTE(N) \ 1278c56208aSLeonid Yegoshin EX(sb, a1, N(a0), .Lbyte_fixup\@); \ 1288c56208aSLeonid Yegoshin beqz t0, 0f; \ 1298c56208aSLeonid Yegoshin PTR_ADDU t0, 1; 1308c56208aSLeonid Yegoshin 1318c56208aSLeonid Yegoshin PTR_ADDU a2, t0 /* correct size */ 1328c56208aSLeonid Yegoshin PTR_ADDU t0, 1 1338c56208aSLeonid Yegoshin STORE_BYTE(0) 1348c56208aSLeonid Yegoshin STORE_BYTE(1) 1358c56208aSLeonid Yegoshin#if LONGSIZE == 4 1368c56208aSLeonid Yegoshin EX(sb, a1, 2(a0), .Lbyte_fixup\@) 1378c56208aSLeonid Yegoshin#else 1388c56208aSLeonid Yegoshin STORE_BYTE(2) 1398c56208aSLeonid Yegoshin STORE_BYTE(3) 1408c56208aSLeonid Yegoshin STORE_BYTE(4) 1418c56208aSLeonid Yegoshin STORE_BYTE(5) 1428c56208aSLeonid Yegoshin EX(sb, a1, 6(a0), .Lbyte_fixup\@) 1438c56208aSLeonid Yegoshin#endif 1448c56208aSLeonid Yegoshin0: 1458c56208aSLeonid Yegoshin ori a0, STORMASK 1468c56208aSLeonid Yegoshin xori a0, STORMASK 1478c56208aSLeonid Yegoshin PTR_ADDIU a0, STORSIZE 1488c56208aSLeonid Yegoshin#endif /* CONFIG_CPU_MIPSR6 */ 149a583158cSAtsushi Nemoto1: ori t1, a2, 0x3f /* # of full blocks */ 150a583158cSAtsushi Nemoto xori t1, 0x3f 1516d5155c2SMarkos Chandras beqz t1, .Lmemset_partial\@ /* no block to fill */ 15226c5e07dSSteven J. Hill andi t0, a2, 0x40-STORSIZE 153a583158cSAtsushi Nemoto 154a583158cSAtsushi Nemoto PTR_ADDU t1, a0 /* end address */ 155a583158cSAtsushi Nemoto .set reorder 156a583158cSAtsushi Nemoto1: PTR_ADDIU a0, 64 157930bff88SThomas Bogendoerfer R10KCBARRIER(0(ra)) 158fd9720e9SMarkos Chandras f_fill64 a0, -64, FILL64RG, .Lfwd_fixup\@, \mode 159a583158cSAtsushi Nemoto bne t1, a0, 1b 160a583158cSAtsushi Nemoto .set noreorder 161a583158cSAtsushi Nemoto 1626d5155c2SMarkos Chandras.Lmemset_partial\@: 163930bff88SThomas Bogendoerfer R10KCBARRIER(0(ra)) 164a583158cSAtsushi Nemoto PTR_LA t1, 2f /* where to start */ 16526c5e07dSSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS 16626c5e07dSSteven J. Hill LONG_SRL t7, t0, 1 16726c5e07dSSteven J. Hill#endif 168a583158cSAtsushi Nemoto#if LONGSIZE == 4 16926c5e07dSSteven J. Hill PTR_SUBU t1, FILLPTRG 170a583158cSAtsushi Nemoto#else 171a583158cSAtsushi Nemoto .set noat 17226c5e07dSSteven J. Hill LONG_SRL AT, FILLPTRG, 1 173a583158cSAtsushi Nemoto PTR_SUBU t1, AT 174619b6e18SMaciej W. Rozycki .set at 175a583158cSAtsushi Nemoto#endif 176a583158cSAtsushi Nemoto jr t1 177a583158cSAtsushi Nemoto PTR_ADDU a0, t0 /* dest ptr */ 178a583158cSAtsushi Nemoto 179a583158cSAtsushi Nemoto .set push 180a583158cSAtsushi Nemoto .set noreorder 181a583158cSAtsushi Nemoto .set nomacro 1826d5155c2SMarkos Chandras /* ... but first do longs ... */ 183fd9720e9SMarkos Chandras f_fill64 a0, -64, FILL64RG, .Lpartial_fixup\@, \mode 184a583158cSAtsushi Nemoto2: .set pop 18526c5e07dSSteven J. Hill andi a2, STORMASK /* At most one long to go */ 186a583158cSAtsushi Nemoto 187a583158cSAtsushi Nemoto beqz a2, 1f 1888c56208aSLeonid Yegoshin#ifndef CONFIG_CPU_MIPSR6 189a583158cSAtsushi Nemoto PTR_ADDU a0, a2 /* What's left */ 190930bff88SThomas Bogendoerfer R10KCBARRIER(0(ra)) 191a583158cSAtsushi Nemoto#ifdef __MIPSEB__ 1926d5155c2SMarkos Chandras EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@) 193dd2adea4SMarkos Chandras#else 1946d5155c2SMarkos Chandras EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@) 195a583158cSAtsushi Nemoto#endif 1968c56208aSLeonid Yegoshin#else 1978c56208aSLeonid Yegoshin PTR_SUBU t0, $0, a2 198b1c03f1eSMatt Redfearn move a2, zero /* No remaining longs */ 1998c56208aSLeonid Yegoshin PTR_ADDIU t0, 1 2008c56208aSLeonid Yegoshin STORE_BYTE(0) 2018c56208aSLeonid Yegoshin STORE_BYTE(1) 2028c56208aSLeonid Yegoshin#if LONGSIZE == 4 2038c56208aSLeonid Yegoshin EX(sb, a1, 2(a0), .Lbyte_fixup\@) 2048c56208aSLeonid Yegoshin#else 2058c56208aSLeonid Yegoshin STORE_BYTE(2) 2068c56208aSLeonid Yegoshin STORE_BYTE(3) 2078c56208aSLeonid Yegoshin STORE_BYTE(4) 2088c56208aSLeonid Yegoshin STORE_BYTE(5) 2098c56208aSLeonid Yegoshin EX(sb, a1, 6(a0), .Lbyte_fixup\@) 2108c56208aSLeonid Yegoshin#endif 2118c56208aSLeonid Yegoshin0: 2128c56208aSLeonid Yegoshin#endif 213a583158cSAtsushi Nemoto1: jr ra 214a583158cSAtsushi Nemoto move a2, zero 215a583158cSAtsushi Nemoto 2166d5155c2SMarkos Chandras.Lsmall_memset\@: 217a583158cSAtsushi Nemoto beqz a2, 2f 218a583158cSAtsushi Nemoto PTR_ADDU t1, a0, a2 219a583158cSAtsushi Nemoto 220a583158cSAtsushi Nemoto1: PTR_ADDIU a0, 1 /* fill bytewise */ 221930bff88SThomas Bogendoerfer R10KCBARRIER(0(ra)) 222a583158cSAtsushi Nemoto bne t1, a0, 1b 2238a8158c8SMatt Redfearn EX(sb, a1, -1(a0), .Lsmall_fixup\@) 224a583158cSAtsushi Nemoto 225a583158cSAtsushi Nemoto2: jr ra /* done */ 226a583158cSAtsushi Nemoto move a2, zero 2276d5155c2SMarkos Chandras .if __memset == 1 228a583158cSAtsushi Nemoto END(memset) 2296d5155c2SMarkos Chandras .set __memset, 0 2306d5155c2SMarkos Chandras .hidden __memset 2316d5155c2SMarkos Chandras .endif 232a583158cSAtsushi Nemoto 2338e85f275SMaciej W. Rozycki#ifdef CONFIG_CPU_MIPSR6 2348c56208aSLeonid Yegoshin.Lbyte_fixup\@: 235*6312455aSMatt Redfearn /* 236*6312455aSMatt Redfearn * unset_bytes = (#bytes - (#unaligned bytes)) - (-#unaligned bytes remaining + 1) + 1 237*6312455aSMatt Redfearn * a2 = a2 - t0 + 1 238*6312455aSMatt Redfearn */ 239b1c03f1eSMatt Redfearn PTR_SUBU a2, t0 2408c56208aSLeonid Yegoshin jr ra 2418c56208aSLeonid Yegoshin PTR_ADDIU a2, 1 2428e85f275SMaciej W. Rozycki#endif /* CONFIG_CPU_MIPSR6 */ 2438c56208aSLeonid Yegoshin 2446d5155c2SMarkos Chandras.Lfirst_fixup\@: 245*6312455aSMatt Redfearn /* unset_bytes already in a2 */ 246a583158cSAtsushi Nemoto jr ra 247a583158cSAtsushi Nemoto nop 248a583158cSAtsushi Nemoto 2496d5155c2SMarkos Chandras.Lfwd_fixup\@: 250*6312455aSMatt Redfearn /* 251*6312455aSMatt Redfearn * unset_bytes = partial_start_addr + #bytes - fault_addr 252*6312455aSMatt Redfearn * a2 = t1 + (a2 & 3f) - $28->task->BUADDR 253*6312455aSMatt Redfearn */ 254a583158cSAtsushi Nemoto PTR_L t0, TI_TASK($28) 255a583158cSAtsushi Nemoto andi a2, 0x3f 256e5674ad6STony Wu LONG_L t0, THREAD_BUADDR(t0) 257a583158cSAtsushi Nemoto LONG_ADDU a2, t1 258a583158cSAtsushi Nemoto jr ra 259a583158cSAtsushi Nemoto LONG_SUBU a2, t0 260a583158cSAtsushi Nemoto 2616d5155c2SMarkos Chandras.Lpartial_fixup\@: 262*6312455aSMatt Redfearn /* 263*6312455aSMatt Redfearn * unset_bytes = partial_end_addr + #bytes - fault_addr 264*6312455aSMatt Redfearn * a2 = a0 + (a2 & STORMASK) - $28->task->BUADDR 265*6312455aSMatt Redfearn */ 266a583158cSAtsushi Nemoto PTR_L t0, TI_TASK($28) 26726c5e07dSSteven J. Hill andi a2, STORMASK 268e5674ad6STony Wu LONG_L t0, THREAD_BUADDR(t0) 269daf70d89SMatt Redfearn LONG_ADDU a2, a0 270a583158cSAtsushi Nemoto jr ra 271a583158cSAtsushi Nemoto LONG_SUBU a2, t0 272a583158cSAtsushi Nemoto 2736d5155c2SMarkos Chandras.Llast_fixup\@: 274*6312455aSMatt Redfearn /* unset_bytes already in a2 */ 275a583158cSAtsushi Nemoto jr ra 276c96eebf0SMatt Redfearn nop 2776d5155c2SMarkos Chandras 2788a8158c8SMatt Redfearn.Lsmall_fixup\@: 279*6312455aSMatt Redfearn /* 280*6312455aSMatt Redfearn * unset_bytes = end_addr - current_addr + 1 281*6312455aSMatt Redfearn * a2 = t1 - a0 + 1 282*6312455aSMatt Redfearn */ 2838a8158c8SMatt Redfearn PTR_SUBU a2, t1, a0 2848a8158c8SMatt Redfearn jr ra 2858a8158c8SMatt Redfearn PTR_ADDIU a2, 1 2868a8158c8SMatt Redfearn 2876d5155c2SMarkos Chandras .endm 2886d5155c2SMarkos Chandras 2896d5155c2SMarkos Chandras/* 2906d5155c2SMarkos Chandras * memset(void *s, int c, size_t n) 2916d5155c2SMarkos Chandras * 2926d5155c2SMarkos Chandras * a0: start of area to clear 2936d5155c2SMarkos Chandras * a1: char to fill with 2946d5155c2SMarkos Chandras * a2: size of area to clear 2956d5155c2SMarkos Chandras */ 2966d5155c2SMarkos Chandras 2976d5155c2SMarkos ChandrasLEAF(memset) 298576a2f0cSPaul BurtonEXPORT_SYMBOL(memset) 2996d5155c2SMarkos Chandras beqz a1, 1f 3006d5155c2SMarkos Chandras move v0, a0 /* result */ 3016d5155c2SMarkos Chandras 3026d5155c2SMarkos Chandras andi a1, 0xff /* spread fillword */ 3036d5155c2SMarkos Chandras LONG_SLL t1, a1, 8 3046d5155c2SMarkos Chandras or a1, t1 3056d5155c2SMarkos Chandras LONG_SLL t1, a1, 16 3066d5155c2SMarkos Chandras#if LONGSIZE == 8 3076d5155c2SMarkos Chandras or a1, t1 3086d5155c2SMarkos Chandras LONG_SLL t1, a1, 32 3096d5155c2SMarkos Chandras#endif 3106d5155c2SMarkos Chandras or a1, t1 3116d5155c2SMarkos Chandras1: 312fd9720e9SMarkos Chandras#ifndef CONFIG_EVA 3136d5155c2SMarkos ChandrasFEXPORT(__bzero) 314576a2f0cSPaul BurtonEXPORT_SYMBOL(__bzero) 315d6a428fbSJames Hogan#else 316d6a428fbSJames HoganFEXPORT(__bzero_kernel) 317576a2f0cSPaul BurtonEXPORT_SYMBOL(__bzero_kernel) 318fd9720e9SMarkos Chandras#endif 3196d5155c2SMarkos Chandras __BUILD_BZERO LEGACY_MODE 320fd9720e9SMarkos Chandras 321fd9720e9SMarkos Chandras#ifdef CONFIG_EVA 322fd9720e9SMarkos ChandrasLEAF(__bzero) 323576a2f0cSPaul BurtonEXPORT_SYMBOL(__bzero) 324fd9720e9SMarkos Chandras __BUILD_BZERO EVA_MODE 325fd9720e9SMarkos ChandrasEND(__bzero) 326fd9720e9SMarkos Chandras#endif 327