1139595Smarcel/*
2139595Smarcel * Copyright (c) 2005 Marcel Moolenaar
3139595Smarcel * All rights reserved.
4139595Smarcel *
5139595Smarcel * Redistribution and use in source and binary forms, with or without
6139595Smarcel * modification, are permitted provided that the following conditions
7139595Smarcel * are met:
8139595Smarcel *
9139595Smarcel * 1. Redistributions of source code must retain the above copyright
10139595Smarcel *    notice, this list of conditions and the following disclaimer.
11139595Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12139595Smarcel *    notice, this list of conditions and the following disclaimer in the
13139595Smarcel *    documentation and/or other materials provided with the distribution.
14139595Smarcel *
15139595Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16139595Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17139595Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18139595Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19139595Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20139595Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21139595Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22139595Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23139595Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24139595Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25139595Smarcel *
26139595Smarcel * $FreeBSD$
27139595Smarcel */
28139595Smarcel
29140892Smarcel#include <machine/float.h>
30139595Smarcel#include <string.h>
31139595Smarcel
32140892Smarcel/* Memory accesses. */
33140892Smarcel#define	Load			0x01
34140892Smarcel#define	Store			0x02
35140892Smarcel
36140892Smarcel/* Data type. */
37140892Smarcel#define	Integer			0x11
38140892Smarcel#define	FloatingPoint		0x12
39140892Smarcel
40140892Smarcel/* Data size. */
41140892Smarcel#define	Small			0x21
42140892Smarcel#define	Medium			0x22
43140892Smarcel#define	Large			0x23
44140892Smarcel
45140892Smarcel/* Post increment. */
46140892Smarcel#define	NoPostInc		0x31
47140892Smarcel#define	MinConstPostInc		0x32
48140892Smarcel#define	PlusConstPostInc	0x33
49140892Smarcel#define	ScratchRegPostInc	0x34
50140892Smarcel#define	PreservedRegPostInc	0x35
51140892Smarcel
52140892Smarcel#if ACCESS == 0 || TYPE == 0 || SIZE == 0 || POSTINC == 0
53140892Smarcel#error define ACCESS, TYPE, SIZE and/or POSTINC
54140892Smarcel#endif
55140892Smarcel
56140892Smarcel#if TYPE == Integer
57140892Smarcel#  define	REG		"r8"
58140892Smarcel#  if SIZE == Small
59140892Smarcel#    define	DATA_TYPE	short
60140892Smarcel#    define	DATA_VALUE	0x1234
61140892Smarcel#    define	LD		"ld2"
62140892Smarcel#    define	ST		"st2"
63140892Smarcel#  elif SIZE == Medium
64140892Smarcel#    define	DATA_TYPE	int
65140892Smarcel#    define	DATA_VALUE	0x12345678
66140892Smarcel#    define	LD		"ld4"
67140892Smarcel#    define	ST		"st4"
68140892Smarcel#  elif SIZE == Large
69140892Smarcel#    define	DATA_TYPE	long
70140892Smarcel#    define	DATA_VALUE	0x1234567890ABCDEF
71140892Smarcel#    define	LD		"ld8"
72140892Smarcel#    define	ST		"st8"
73140892Smarcel#  endif
74140892Smarcel#elif TYPE == FloatingPoint
75140892Smarcel#  define	REG		"f6"
76140892Smarcel#  if SIZE == Small
77140892Smarcel#    define	DATA_TYPE	float
78140892Smarcel#    define	DATA_VALUE	FLT_MIN
79140892Smarcel#    define	LD		"ldfs"
80140892Smarcel#    define	ST		"stfs"
81140892Smarcel#  elif SIZE == Medium
82140892Smarcel#    define	DATA_TYPE	double
83140892Smarcel#    define	DATA_VALUE	DBL_MIN
84140892Smarcel#    define	LD		"ldfd"
85140892Smarcel#    define	ST		"stfd"
86140892Smarcel#  elif SIZE == Large
87140892Smarcel#    define	DATA_TYPE	long double
88140892Smarcel#    define	DATA_VALUE	LDBL_MIN
89140892Smarcel#    define	LD		"ldfe"
90140892Smarcel#    define	ST		"stfe"
91140892Smarcel#  endif
92140892Smarcel#endif
93140892Smarcel
94140919Smarcelstruct {
95139595Smarcel	DATA_TYPE aligned;
96139595Smarcel	char _;
97139595Smarcel	char misaligned[sizeof(DATA_TYPE)];
98139595Smarcel} data;
99139595Smarcel
100140919SmarcelDATA_TYPE *aligned = &data.aligned;
101140919SmarcelDATA_TYPE *misaligned = (DATA_TYPE *)data.misaligned;
102140919SmarcelDATA_TYPE value = DATA_VALUE;
103140919Smarcel
104140922Smarcelvoid
105140922Smarcelblock_copy(void *dst, void *src, size_t sz)
106140922Smarcel{
107140922Smarcel
108140922Smarcel	memcpy(dst, src, sz);
109140922Smarcel}
110140922Smarcel
111139595Smarcelint
112139595Smarcelmain()
113139595Smarcel{
114139595Smarcel
115139595Smarcel	/* Set PSR.ac. */
116139595Smarcel	asm volatile("sum 8");
117139595Smarcel
118140892Smarcel#if ACCESS == Load
119140892Smarcel	/*
120140892Smarcel	 * LOAD
121140892Smarcel	 */
122140922Smarcel	block_copy(misaligned, &value, sizeof(DATA_TYPE));
123140892Smarcel
124140892Smarcel#  if POSTINC == NoPostInc
125140892Smarcel	/* Misaligned load. */
126140892Smarcel	*aligned = *misaligned;
127140892Smarcel#  elif POSTINC == MinConstPostInc
128140892Smarcel	asm volatile(
129140892Smarcel		"ld8 r2=%0;;"
130140892Smarcel		LD " " REG "=[r2],%2;;"
131140892Smarcel		"st8 %0=r2;" ST " %1=" REG ";;"
132140892Smarcel	    : "=m"(misaligned), "=m"(*aligned)
133140892Smarcel	    : "i"(-sizeof(DATA_TYPE))
134140892Smarcel	    : REG, "r2", "memory");
135140892Smarcel#  elif POSTINC == PlusConstPostInc
136140892Smarcel	asm volatile(
137140892Smarcel		"ld8 r2=%0;;"
138140892Smarcel		LD " " REG "=[r2],%2;;"
139140892Smarcel		"st8 %0=r2;" ST " %1=" REG ";;"
140140892Smarcel	    : "=m"(misaligned), "=m"(*aligned)
141140892Smarcel	    : "i"(sizeof(DATA_TYPE))
142140892Smarcel	    : REG, "r2", "memory");
143140892Smarcel#  elif POSTINC == ScratchRegPostInc
144140892Smarcel	asm volatile(
145140892Smarcel		"ld8 r2=%0; mov r3=%2;;"
146140892Smarcel		LD " " REG "=[r2],r3;;"
147140892Smarcel		"st8 %0=r2;" ST " %1=" REG ";;"
148140892Smarcel	    : "=m"(misaligned), "=m"(*aligned)
149140892Smarcel	    : "i"(sizeof(DATA_TYPE))
150140892Smarcel	    : REG, "r2", "r3", "memory");
151140892Smarcel#  elif POSTINC == PreservedRegPostInc
152140892Smarcel	asm volatile(
153140892Smarcel		"ld8 r2=%0; mov r4=%2;;"
154140892Smarcel		LD " " REG "=[r2],r4;;"
155140892Smarcel		"st8 %0=r2;" ST " %1=" REG ";;"
156140892Smarcel	    : "=m"(misaligned), "=m"(*aligned)
157140892Smarcel	    : "i"(sizeof(DATA_TYPE))
158140892Smarcel	    : REG, "r2", "r4", "memory");
159140892Smarcel#  endif
160140892Smarcel
161140892Smarcel#elif ACCESS == Store
162140892Smarcel	/*
163140892Smarcel	 * STORE
164140892Smarcel	 */
165140892Smarcel
166140892Smarcel#  if POSTINC == NoPostInc
167139595Smarcel	/* Misaligned store. */
168139595Smarcel	*misaligned = value;
169140892Smarcel#  elif POSTINC == MinConstPostInc
170140892Smarcel	asm volatile(
171140892Smarcel		"ld8 r2=%0;" LD " " REG "=%1;;"
172140892Smarcel		ST " [r2]=" REG ",%2;;"
173140892Smarcel		"st8 %0=r2;;"
174140892Smarcel	    : "=m"(misaligned)
175140892Smarcel	    : "m"(value), "i"(-sizeof(DATA_TYPE))
176140892Smarcel	    : REG, "r2", "memory");
177140892Smarcel#  elif POSTINC == PlusConstPostInc
178140892Smarcel	asm volatile(
179140892Smarcel		"ld8 r2=%0;" LD " " REG "=%1;;"
180140892Smarcel		ST " [r2]=" REG ",%2;;"
181140892Smarcel		"st8 %0=r2;;"
182140892Smarcel	    : "=m"(misaligned)
183140892Smarcel	    : "m"(value), "i"(sizeof(DATA_TYPE))
184140892Smarcel	    : REG, "r2", "memory");
185140892Smarcel#  elif POSTINC == ScratchRegPostInc || POSTINC == PreservedRegPostInc
186140892Smarcel	return (1);
187140892Smarcel#  endif
188140892Smarcel
189140922Smarcel	block_copy(aligned, data.misaligned, sizeof(DATA_TYPE));
190140892Smarcel#endif
191140892Smarcel
192140892Smarcel	if (*aligned != value)
193140892Smarcel		return (2);
194140892Smarcel
195140892Smarcel#if POSTINC == NoPostInc
196140892Smarcel	return (0);
197140892Smarcel#elif POSTINC == MinConstPostInc
198140892Smarcel	return (((char *)misaligned == data.misaligned - sizeof(DATA_TYPE))
199140892Smarcel	    ? 0 : 4);
200139595Smarcel#else
201140892Smarcel	return (((char *)misaligned == data.misaligned + sizeof(DATA_TYPE))
202140892Smarcel	    ? 0 : 4);
203139595Smarcel#endif
204139595Smarcel}
205