Subject: unaligned.h

From: Brad Parker <[email-masked]>
Date: Tue, 04 Jul 2000 08:18:16 -0400

Hi

I'm forwarding a message from the linux-usb list.  I ran into the same
problem as this person.

I don't understand the comment in unaligned.h.  It says the code is to
catch compile/link errors but it sure looks like it's a run time check
as it will *always* fail linking if you call get_unaligned, right?

I *really* want to define __get_unaligned_bad... (despite the comment)

what am I missing?  

-brad

------- Forwarded Message

Date:    Tue, 27 Jun 2000 17:07:23 +0900
From:    "Hyun-Mo Chung" <[email-masked]>
To:      <[email-masked]>
Subject: [linux-usb-devel] compiling hid.c for ARM

I can't compile hid.c to ARM architecture.
The source of the trouble is :

...
return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) -
1);
...

where get_unaligned() receives a pointer to __u64 as its parameter.
But get_unaligned(ptr), defined in include/asm-arm/unaligned.h,
is designed to intentionally cause a linker fail if sizeof(*ptr) is not one
of 1, 2, or 4.

What should I do to fix it up ?

TIA
Hyun-Mo

_______________________________________________
linux-usb-devel mailing list
[email-masked]
http://lists.sourceforge.net/mailman/listinfo/linux-usb-devel

------- End of Forwarded Message

unsubscribe: body of `unsubscribe linux-arm-kernel' to [email-masked]

---

From: Kunihiko IMAI <[email-masked]>
Date: Tue, 04 Jul 2000 23:08:43 +0900

Hello,

At Tue, 04 Jul 2000 08:18:16 -0400,

> I *really* want to define __get_unaligned_bad... (despite the comment)

It seems that ARM's get_unaligned() supports below 32 bit word access.
You can't use get_unaligned() for 64 bit word access.  I think
__get_unaligned_bad() is defined to detect over 32 bit word access.

# Or I also misunderstand the comment?  I am not a native English
# speaker :-)

I have two ideas to avoid this problem:

o  steal include/asm-sparc/unaligned.h
	SPARC is big-endian arch., but this code seems not to depend
	on endian.  So we can use it on ARM.

o  rewrite hid.c, like this:
	return (le64_to_cpu(
		(((__u64)report[0])<<0)
		|(((__u64)report[1])<<8)
		|(((__u64)report[2])<<16)
		|(((__u64)report[3])<<24)
		|(((__u64)report[4])<<32)
		|(((__u64)report[5])<<40)
		|(((__u64)report[6])<<48)
		|(((__u64)report[7])<<56)
	) >> offset) & ((1 << n) - 1);

	This code is depend on endian.

I tried each method.  Both methods works well.

Thanks.
_._. __._  _.. .  .___ ._. _____ _... ._ _._  _.._. .____  .__. ... .  _._

                                                             Kunihiko IMAI

---

From: Kunihiko IMAI <[email-masked]>
Date: Tue, 04 Jul 2000 23:08:43 +0900

Hello,

Thanks.

                                                             Kunihiko IMAI

---

From: Russell King - ARM Linux Admin <[email-masked]>
Date: Tue, 4 Jul 2000 19:55:14 +0100 (BST)

> __get_unaligned_bad() is defined to detect over 32 bit word access.

There is no reason why we can't support 64-bit unaligned loads.  Its
just that this appears to be the first attempt to use them.

> 	on endian.  So we can use it on ARM.

Only if you want to have inefficient code.

> 	) >> offset) & ((1 << n) - 1);

Also not a preferred method.

The correct way would be to fix unaligned.h
   _____
  |_____| ------------------------------------------------- ---+---+-
  |   |        Russell King       [email-masked]      --- ---
  | | | |            http://www.arm.linux.org.uk/            /  /  |
  | +-+-+                                                     --- -+-
  /   |               THE developer of ARM Linux              |+| /|\
 /  | | |                                                     ---  |
    +-+-+ -------------------------------------------------  /\\\  |

---

From: Kunihiko IMAI <[email-masked]>
Date: Wed, 05 Jul 2000 13:27:32 +0900

Hello,

At Tue, 4 Jul 2000 19:55:14 +0100 (BST),

> The correct way would be to fix unaligned.h

I didn't care performance.

Then, how about is this ?
_._. __._  _.. .  .___ ._. _____ _... ._ _._  _.._. .____  .__. ... .  _._

                                                             Kunihiko IMAI

---- 8< ----
#ifndef __ASM_ARM_UNALIGNED_H
#define __ASM_ARM_UNALIGNED_H

#include <linux/types.h>
#include <linux/string.h>

extern unsigned long __get_unaligned_bad(void);
extern void __put_unaligned_bad(void);

#ifdef CONFIG_BADSIZE_UNALIGNED /* FIXME */
static int __use_unaligned_bad = 1;
#else
static int __use_unaligned_bad = 0;
#endif

#define get_unaligned(ptr) \
	({ \
		__typeof__(*(ptr)) __val = 0; \
		__u8 *__p = (__u8 *)(ptr); \
		switch ( sizeof(__val) ) { \
		case 8: { \
			__u32 *__vh = (__u32 *)(&__val) + 1; \
			*__vh = __p[7] << 24 | __p[6] << 16 \
				| __p[5] << 8 | __p[4]; \
		} \
		case 4: \
			__val |= __p[3] << 24 | __p[2] << 16; \
		case 2: \
			__val |= __p[1] << 8; \
		case 1: \
			__val |= __p[0]; break; \
		default: \
			if ( __use_unaligned_bad ) \
				__get_unaligned_bad(); \
			else \
				memmove ( &__val, __p, sizeof(__val)); \
			break; \
		} \
		__val; \
	})

#define put_unaligned(val,ptr) \
	({ \
		__u8 *__p = (__u8 *)(ptr); \
		__typeof__(*(ptr)) __v = (val); \
		switch ( sizeof(*(ptr))) { \
		case 8: \
			__p[7] = (__u64)__v >> 56; \
			__p[6] = (__u64)__v >> 48; \
			__p[5] = (__u64)__v >> 40; \
			__p[4] = (__u64)__v >> 32; \
		case 4: \
			__p[3] = __v >> 24; \
			__p[2] = __v >> 16; \
		case 2: \
			__p[1] = __v >> 8; \
		case 1: \
			__p[0] = __v; break; \
		default: \
			if ( __use_unaligned_bad ) \
				__put_unaligned_bad(); \
			else \
				memmove ( (ptr), &__v, sizeof(*(ptr)) ); \
			break; \
		} \
		(void) 0; \
	})

#endif
---- 8< ----