18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * arch/h8300/asm/include/flat.h -- uClinux flat-format executables
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#ifndef __H8300_FLAT_H__
78c2ecf20Sopenharmony_ci#define __H8300_FLAT_H__
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/*
128c2ecf20Sopenharmony_ci * on the H8 a couple of the relocations have an instruction in the
138c2ecf20Sopenharmony_ci * top byte.  As there can only be 24bits of address space,  we just
148c2ecf20Sopenharmony_ci * always preserve that 8bits at the top,  when it isn't an instruction
158c2ecf20Sopenharmony_ci * is is 0 (davidm@snapgear.com)
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define	flat_get_relocate_addr(rel)		(rel & ~0x00000001)
198c2ecf20Sopenharmony_cistatic inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
208c2ecf20Sopenharmony_ci					u32 *addr)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	u32 val = get_unaligned((__force u32 *)rp);
238c2ecf20Sopenharmony_ci	if (!(flags & FLAT_FLAG_GOTPIC))
248c2ecf20Sopenharmony_ci		val &= 0x00ffffff;
258c2ecf20Sopenharmony_ci	*addr = val;
268c2ecf20Sopenharmony_ci	return 0;
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	u32 *p = (__force u32 *)rp;
328c2ecf20Sopenharmony_ci	put_unaligned((addr & 0x00ffffff) | (*(char *)p << 24), p);
338c2ecf20Sopenharmony_ci	return 0;
348c2ecf20Sopenharmony_ci}
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#endif /* __H8300_FLAT_H__ */
37