162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/linkage.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <asm/asm.h> 962306a36Sopenharmony_ci#include <asm/asmmacro.h> 1062306a36Sopenharmony_ci#include <asm/asm-extable.h> 1162306a36Sopenharmony_ci#include <asm/errno.h> 1262306a36Sopenharmony_ci#include <asm/regdef.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci.L_fixup_handle_unaligned: 1562306a36Sopenharmony_ci li.w a0, -EFAULT 1662306a36Sopenharmony_ci jr ra 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * unsigned long unaligned_read(void *addr, void *value, unsigned long n, bool sign) 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * a0: addr 2262306a36Sopenharmony_ci * a1: value 2362306a36Sopenharmony_ci * a2: n 2462306a36Sopenharmony_ci * a3: sign 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ciSYM_FUNC_START(unaligned_read) 2762306a36Sopenharmony_ci beqz a2, 5f 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci li.w t2, 0 3062306a36Sopenharmony_ci addi.d t0, a2, -1 3162306a36Sopenharmony_ci slli.d t1, t0, 3 3262306a36Sopenharmony_ci add.d a0, a0, t0 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci beqz a3, 2f 3562306a36Sopenharmony_ci1: ld.b t3, a0, 0 3662306a36Sopenharmony_ci b 3f 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci2: ld.bu t3, a0, 0 3962306a36Sopenharmony_ci3: sll.d t3, t3, t1 4062306a36Sopenharmony_ci or t2, t2, t3 4162306a36Sopenharmony_ci addi.d t1, t1, -8 4262306a36Sopenharmony_ci addi.d a0, a0, -1 4362306a36Sopenharmony_ci addi.d a2, a2, -1 4462306a36Sopenharmony_ci bgtz a2, 2b 4562306a36Sopenharmony_ci4: st.d t2, a1, 0 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci move a0, a2 4862306a36Sopenharmony_ci jr ra 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci5: li.w a0, -EFAULT 5162306a36Sopenharmony_ci jr ra 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci _asm_extable 1b, .L_fixup_handle_unaligned 5462306a36Sopenharmony_ci _asm_extable 2b, .L_fixup_handle_unaligned 5562306a36Sopenharmony_ci _asm_extable 4b, .L_fixup_handle_unaligned 5662306a36Sopenharmony_ciSYM_FUNC_END(unaligned_read) 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* 5962306a36Sopenharmony_ci * unsigned long unaligned_write(void *addr, unsigned long value, unsigned long n) 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * a0: addr 6262306a36Sopenharmony_ci * a1: value 6362306a36Sopenharmony_ci * a2: n 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ciSYM_FUNC_START(unaligned_write) 6662306a36Sopenharmony_ci beqz a2, 3f 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci li.w t0, 0 6962306a36Sopenharmony_ci1: srl.d t1, a1, t0 7062306a36Sopenharmony_ci2: st.b t1, a0, 0 7162306a36Sopenharmony_ci addi.d t0, t0, 8 7262306a36Sopenharmony_ci addi.d a2, a2, -1 7362306a36Sopenharmony_ci addi.d a0, a0, 1 7462306a36Sopenharmony_ci bgtz a2, 1b 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci move a0, a2 7762306a36Sopenharmony_ci jr ra 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci3: li.w a0, -EFAULT 8062306a36Sopenharmony_ci jr ra 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci _asm_extable 2b, .L_fixup_handle_unaligned 8362306a36Sopenharmony_ciSYM_FUNC_END(unaligned_write) 84