/* SPDX-License-Identifier: GPL-2.0-only */

/*
 * This file define some function used to swap value between memory
 * and float register. This will be used in misaligned access exception
 * handling.
 */

#if defined(__riscv_flen)
#if __riscv_flen >= 32

	.text

/* void read_f32(int regnum, uint32_t* v)
 *    regnum : which register want to read
 *    v : address to hold bits info of reading
 */
	.align	1
	.globl read_f32
read_f32:
	la	a2, .Lr32_t
	andi	a0, a0, 31
	slli	a0, a0, 1
	add	a0, a0, a2
	lbu	a0, 0(a0)
	add	a0, a0, a2
	jr	a0
	.align	2
.Lr32_t:
	.half	.Lr32_f0  - .Lr32_t
	.half	.Lr32_f1  - .Lr32_t
	.half	.Lr32_f2  - .Lr32_t
	.half	.Lr32_f3  - .Lr32_t
	.half	.Lr32_f4  - .Lr32_t
	.half	.Lr32_f5  - .Lr32_t
	.half	.Lr32_f6  - .Lr32_t
	.half	.Lr32_f7  - .Lr32_t
	.half	.Lr32_f8  - .Lr32_t
	.half	.Lr32_f9  - .Lr32_t
	.half	.Lr32_f10 - .Lr32_t
	.half	.Lr32_f11 - .Lr32_t
	.half	.Lr32_f12 - .Lr32_t
	.half	.Lr32_f13 - .Lr32_t
	.half	.Lr32_f14 - .Lr32_t
	.half	.Lr32_f15 - .Lr32_t
	.half	.Lr32_f16 - .Lr32_t
	.half	.Lr32_f17 - .Lr32_t
	.half	.Lr32_f18 - .Lr32_t
	.half	.Lr32_f19 - .Lr32_t
	.half	.Lr32_f20 - .Lr32_t
	.half	.Lr32_f21 - .Lr32_t
	.half	.Lr32_f22 - .Lr32_t
	.half	.Lr32_f23 - .Lr32_t
	.half	.Lr32_f24 - .Lr32_t
	.half	.Lr32_f25 - .Lr32_t
	.half	.Lr32_f26 - .Lr32_t
	.half	.Lr32_f27 - .Lr32_t
	.half	.Lr32_f28 - .Lr32_t
	.half	.Lr32_f29 - .Lr32_t
	.half	.Lr32_f30 - .Lr32_t
	.half	.Lr32_f31 - .Lr32_t
#define  read32(which)	.Lr32_##which: fsw which, 0(a1); ret
	read32(f0)
	read32(f1)
	read32(f2)
	read32(f3)
	read32(f4)
	read32(f5)
	read32(f6)
	read32(f7)
	read32(f8)
	read32(f9)
	read32(f10)
	read32(f11)
	read32(f12)
	read32(f13)
	read32(f14)
	read32(f15)
	read32(f16)
	read32(f17)
	read32(f18)
	read32(f19)
	read32(f20)
	read32(f21)
	read32(f22)
	read32(f23)
	read32(f24)
	read32(f25)
	read32(f26)
	read32(f27)
	read32(f28)
	read32(f29)
	read32(f30)
	read32(f31)

/* void write_f32(int regnum, uint32_t* v)
 *    regnum: which register want to write
 *    v : address to hold bits info of writing
 */
	.align	1
	.globl write_f32
write_f32:
	la	a2, .Lw32_t
	andi	a0, a0, 31
	slli	a0, a0, 1
	add	a0, a0, a2
	lbu	a0, 0(a0)
	add	a0, a0, a2
	jr	a0
	.align	2
.Lw32_t:
	.half	.Lw32_f0  - .Lw32_t
	.half	.Lw32_f1  - .Lw32_t
	.half	.Lw32_f2  - .Lw32_t
	.half	.Lw32_f3  - .Lw32_t
	.half	.Lw32_f4  - .Lw32_t
	.half	.Lw32_f5  - .Lw32_t
	.half	.Lw32_f6  - .Lw32_t
	.half	.Lw32_f7  - .Lw32_t
	.half	.Lw32_f8  - .Lw32_t
	.half	.Lw32_f9  - .Lw32_t
	.half	.Lw32_f10 - .Lw32_t
	.half	.Lw32_f11 - .Lw32_t
	.half	.Lw32_f12 - .Lw32_t
	.half	.Lw32_f13 - .Lw32_t
	.half	.Lw32_f14 - .Lw32_t
	.half	.Lw32_f15 - .Lw32_t
	.half	.Lw32_f16 - .Lw32_t
	.half	.Lw32_f17 - .Lw32_t
	.half	.Lw32_f18 - .Lw32_t
	.half	.Lw32_f19 - .Lw32_t
	.half	.Lw32_f20 - .Lw32_t
	.half	.Lw32_f21 - .Lw32_t
	.half	.Lw32_f22 - .Lw32_t
	.half	.Lw32_f23 - .Lw32_t
	.half	.Lw32_f24 - .Lw32_t
	.half	.Lw32_f25 - .Lw32_t
	.half	.Lw32_f26 - .Lw32_t
	.half	.Lw32_f27 - .Lw32_t
	.half	.Lw32_f28 - .Lw32_t
	.half	.Lw32_f29 - .Lw32_t
	.half	.Lw32_f30 - .Lw32_t
	.half	.Lw32_f31 - .Lw32_t
#define write32(which)	.Lw32_##which: flw which, 0(a1); ret
	write32(f0)
	write32(f1)
	write32(f2)
	write32(f3)
	write32(f4)
	write32(f5)
	write32(f6)
	write32(f7)
	write32(f8)
	write32(f9)
	write32(f10)
	write32(f11)
	write32(f12)
	write32(f13)
	write32(f14)
	write32(f15)
	write32(f16)
	write32(f17)
	write32(f18)
	write32(f19)
	write32(f20)
	write32(f21)
	write32(f22)
	write32(f23)
	write32(f24)
	write32(f25)
	write32(f26)
	write32(f27)
	write32(f28)
	write32(f29)
	write32(f30)
	write32(f31)
#endif // __riscv_flen >= 32

#if __riscv_flen >= 64

	.text

/* void read_f64(int regnum, uint64_t* v)
 *    regnum : which register want to read
 *    v : address to hold bits info of reading
 */
	.align	1
	.globl read_f64
read_f64:
	la	a2, .Lr64_t
	andi	a0, a0, 31
	slli	a0, a0, 1
	add	a0, a0, a2
	lbu	a0, 0(a0)
	add	a0, a0, a2
	jr	a0
	.align	2
.Lr64_t:
	.half	.Lr64_f0  - .Lr64_t
	.half	.Lr64_f1  - .Lr64_t
	.half	.Lr64_f2  - .Lr64_t
	.half	.Lr64_f3  - .Lr64_t
	.half	.Lr64_f4  - .Lr64_t
	.half	.Lr64_f5  - .Lr64_t
	.half	.Lr64_f6  - .Lr64_t
	.half	.Lr64_f7  - .Lr64_t
	.half	.Lr64_f8  - .Lr64_t
	.half	.Lr64_f9  - .Lr64_t
	.half	.Lr64_f10 - .Lr64_t
	.half	.Lr64_f11 - .Lr64_t
	.half	.Lr64_f12 - .Lr64_t
	.half	.Lr64_f13 - .Lr64_t
	.half	.Lr64_f14 - .Lr64_t
	.half	.Lr64_f15 - .Lr64_t
	.half	.Lr64_f16 - .Lr64_t
	.half	.Lr64_f17 - .Lr64_t
	.half	.Lr64_f18 - .Lr64_t
	.half	.Lr64_f19 - .Lr64_t
	.half	.Lr64_f20 - .Lr64_t
	.half	.Lr64_f21 - .Lr64_t
	.half	.Lr64_f22 - .Lr64_t
	.half	.Lr64_f23 - .Lr64_t
	.half	.Lr64_f24 - .Lr64_t
	.half	.Lr64_f25 - .Lr64_t
	.half	.Lr64_f26 - .Lr64_t
	.half	.Lr64_f27 - .Lr64_t
	.half	.Lr64_f28 - .Lr64_t
	.half	.Lr64_f29 - .Lr64_t
	.half	.Lr64_f30 - .Lr64_t
	.half	.Lr64_f31 - .Lr64_t
#define  read64(which)	.Lr64_##which: fsd which, 0(a1); ret
	read64(f0)
	read64(f1)
	read64(f2)
	read64(f3)
	read64(f4)
	read64(f5)
	read64(f6)
	read64(f7)
	read64(f8)
	read64(f9)
	read64(f10)
	read64(f11)
	read64(f12)
	read64(f13)
	read64(f14)
	read64(f15)
	read64(f16)
	read64(f17)
	read64(f18)
	read64(f19)
	read64(f20)
	read64(f21)
	read64(f22)
	read64(f23)
	read64(f24)
	read64(f25)
	read64(f26)
	read64(f27)
	read64(f28)
	read64(f29)
	read64(f30)
	read64(f31)

/* void write_f64(int regnum, uint64_t* v)
 *    regnum: which register want to write
 *    v : address to hold bits info of writing
 */
	.align	1
	.globl write_f64
write_f64:
	la	a2, .Lw64_t
	andi	a0, a0, 31
	slli	a0, a0, 1
	add	a0, a0, a2
	lbu	a0, 0(a0)
	add	a0, a0, a2
	jr	a0
	.align	2
.Lw64_t:
	.half	.Lw64_f0  - .Lw64_t
	.half	.Lw64_f1  - .Lw64_t
	.half	.Lw64_f2  - .Lw64_t
	.half	.Lw64_f3  - .Lw64_t
	.half	.Lw64_f4  - .Lw64_t
	.half	.Lw64_f5  - .Lw64_t
	.half	.Lw64_f6  - .Lw64_t
	.half	.Lw64_f7  - .Lw64_t
	.half	.Lw64_f8  - .Lw64_t
	.half	.Lw64_f9  - .Lw64_t
	.half	.Lw64_f10 - .Lw64_t
	.half	.Lw64_f11 - .Lw64_t
	.half	.Lw64_f12 - .Lw64_t
	.half	.Lw64_f13 - .Lw64_t
	.half	.Lw64_f14 - .Lw64_t
	.half	.Lw64_f15 - .Lw64_t
	.half	.Lw64_f16 - .Lw64_t
	.half	.Lw64_f17 - .Lw64_t
	.half	.Lw64_f18 - .Lw64_t
	.half	.Lw64_f19 - .Lw64_t
	.half	.Lw64_f20 - .Lw64_t
	.half	.Lw64_f21 - .Lw64_t
	.half	.Lw64_f22 - .Lw64_t
	.half	.Lw64_f23 - .Lw64_t
	.half	.Lw64_f24 - .Lw64_t
	.half	.Lw64_f25 - .Lw64_t
	.half	.Lw64_f26 - .Lw64_t
	.half	.Lw64_f27 - .Lw64_t
	.half	.Lw64_f28 - .Lw64_t
	.half	.Lw64_f29 - .Lw64_t
	.half	.Lw64_f30 - .Lw64_t
	.half	.Lw64_f31 - .Lw64_t
#define write64(which)	.Lw64_##which: fld which, 0(a1); ret
	write64(f0)
	write64(f1)
	write64(f2)
	write64(f3)
	write64(f4)
	write64(f5)
	write64(f6)
	write64(f7)
	write64(f8)
	write64(f9)
	write64(f10)
	write64(f11)
	write64(f12)
	write64(f13)
	write64(f14)
	write64(f15)
	write64(f16)
	write64(f17)
	write64(f18)
	write64(f19)
	write64(f20)
	write64(f21)
	write64(f22)
	write64(f23)
	write64(f24)
	write64(f25)
	write64(f26)
	write64(f27)
	write64(f28)
	write64(f29)
	write64(f30)
	write64(f31)

#endif // __riscv_flen >= 64

#endif // defined(__riscv_flen)
