unaligned.h

来自「linux 内核源代码」· C头文件 代码 · 共 203 行

H
203
字号
/* unaligned.h: unaligned access handler * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#ifndef _ASM_UNALIGNED_H#define _ASM_UNALIGNED_H/* * Unaligned accesses on uClinux can't be performed in a fault handler - the * CPU detects them as imprecise exceptions making this impossible. * * With the FR451, however, they are precise, and so we used to fix them up in * the memory access fault handler.  However, instruction bundling make this * impractical.  So, now we fall back to using memcpy. */#ifdef CONFIG_MMU/* * The asm statement in the macros below is a way to get GCC to copy a * value from one variable to another without having any clue it's * actually doing so, so that it won't have any idea that the values * in the two variables are related. */#define get_unaligned(ptr) ({				\	typeof((*(ptr))) __x;				\	void *__ptrcopy;				\	asm("" : "=r" (__ptrcopy) : "0" (ptr));		\	memcpy(&__x, __ptrcopy, sizeof(*(ptr)));	\	__x;						\})#define put_unaligned(val, ptr) ({			\	typeof((*(ptr))) __x = (val);			\	void *__ptrcopy;				\	asm("" : "=r" (__ptrcopy) : "0" (ptr));		\	memcpy(__ptrcopy, &__x, sizeof(*(ptr)));	\})extern int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0);#else#define get_unaligned(ptr)							\({										\	typeof(*(ptr)) x;							\	const char *__p = (const char *) (ptr);					\										\	switch (sizeof(x)) {							\	case 1:									\		x = *(ptr);							\		break;								\	case 2:									\	{									\		uint8_t a;							\		asm("	ldub%I2		%M2,%0		\n"			\		    "	ldub%I3.p	%M3,%1		\n"			\		    "	slli		%0,#8,%0	\n"			\		    "	or		%0,%1,%0	\n"			\		    : "=&r"(x), "=&r"(a)					\		    : "m"(__p[0]),  "m"(__p[1])					\		    );								\		break;								\	}									\										\	case 4:									\	{									\		uint8_t a;							\		asm("	ldub%I2		%M2,%0		\n"			\		    "	ldub%I3.p	%M3,%1		\n"			\		    "	slli		%0,#8,%0	\n"			\		    "	or		%0,%1,%0	\n"			\		    "	ldub%I4.p	%M4,%1		\n"			\		    "	slli		%0,#8,%0	\n"			\		    "	or		%0,%1,%0	\n"			\		    "	ldub%I5.p	%M5,%1		\n"			\		    "	slli		%0,#8,%0	\n"			\		    "	or		%0,%1,%0	\n"			\		    : "=&r"(x), "=&r"(a)					\		    : "m"(__p[0]),  "m"(__p[1]), "m"(__p[2]), "m"(__p[3])	\		    );								\		break;								\	}									\										\	case 8:									\	{									\		union { uint64_t x; u32 y[2]; } z;				\		uint8_t a;							\		asm("	ldub%I3		%M3,%0		\n"			\		    "	ldub%I4.p	%M4,%2		\n"			\		    "	slli		%0,#8,%0	\n"			\		    "	or		%0,%2,%0	\n"			\		    "	ldub%I5.p	%M5,%2		\n"			\		    "	slli		%0,#8,%0	\n"			\		    "	or		%0,%2,%0	\n"			\		    "	ldub%I6.p	%M6,%2		\n"			\		    "	slli		%0,#8,%0	\n"			\		    "	or		%0,%2,%0	\n"			\		    "	ldub%I7		%M7,%1		\n"			\		    "	ldub%I8.p	%M8,%2		\n"			\		    "	slli		%1,#8,%1	\n"			\		    "	or		%1,%2,%1	\n"			\		    "	ldub%I9.p	%M9,%2		\n"			\		    "	slli		%1,#8,%1	\n"			\		    "	or		%1,%2,%1	\n"			\		    "	ldub%I10.p	%M10,%2		\n"			\		    "	slli		%1,#8,%1	\n"			\		    "	or		%1,%2,%1	\n"			\		    : "=&r"(z.y[0]), "=&r"(z.y[1]), "=&r"(a)			\		    : "m"(__p[0]), "m"(__p[1]), "m"(__p[2]), "m"(__p[3]),	\		      "m"(__p[4]), "m"(__p[5]), "m"(__p[6]), "m"(__p[7])	\		    );								\		x = z.x;							\		break;								\	}									\										\	default:								\		x = 0;								\		BUG();								\		break;								\	}									\										\	x;									\})#define put_unaligned(val, ptr)								\do {											\	char *__p = (char *) (ptr);							\	int x;										\											\	switch (sizeof(*ptr)) {								\	case 2:										\	{										\		asm("	stb%I1.p	%0,%M1		\n"				\		    "	srli		%0,#8,%0	\n"				\		    "	stb%I2		%0,%M2		\n"				\		    : "=r"(x), "=m"(__p[1]),  "=m"(__p[0])				\		    : "0"(val)								\		    );									\		break;									\	}										\											\	case 4:										\	{										\		asm("	stb%I1.p	%0,%M1		\n"				\		    "	srli		%0,#8,%0	\n"				\		    "	stb%I2.p	%0,%M2		\n"				\		    "	srli		%0,#8,%0	\n"				\		    "	stb%I3.p	%0,%M3		\n"				\		    "	srli		%0,#8,%0	\n"				\		    "	stb%I4		%0,%M4		\n"				\		    : "=r"(x), "=m"(__p[3]),  "=m"(__p[2]), "=m"(__p[1]), "=m"(__p[0])	\		    : "0"(val)								\		    );									\		break;									\	}										\											\	case 8:										\	{										\		uint32_t __high, __low;							\		__high = (uint64_t)val >> 32;						\		__low = val & 0xffffffff;						\		asm("	stb%I2.p	%0,%M2		\n"				\		    "	srli		%0,#8,%0	\n"				\		    "	stb%I3.p	%0,%M3		\n"				\		    "	srli		%0,#8,%0	\n"				\		    "	stb%I4.p	%0,%M4		\n"				\		    "	srli		%0,#8,%0	\n"				\		    "	stb%I5.p	%0,%M5		\n"				\		    "	srli		%0,#8,%0	\n"				\		    "	stb%I6.p	%1,%M6		\n"				\		    "	srli		%1,#8,%1	\n"				\		    "	stb%I7.p	%1,%M7		\n"				\		    "	srli		%1,#8,%1	\n"				\		    "	stb%I8.p	%1,%M8		\n"				\		    "	srli		%1,#8,%1	\n"				\		    "	stb%I9		%1,%M9		\n"				\		    : "=&r"(__low), "=&r"(__high), "=m"(__p[7]), "=m"(__p[6]), 		\		      "=m"(__p[5]), "=m"(__p[4]), "=m"(__p[3]), "=m"(__p[2]), 		\		      "=m"(__p[1]), "=m"(__p[0])					\		    : "0"(__low), "1"(__high)						\		    );									\		break;									\	}										\											\        default:									\		*(ptr) = (val);								\		break;									\	}										\} while(0)#endif#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?