1/*
2 * Copyright (c) 2005 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#include <machine/float.h>
30#include <string.h>
31
32/* Memory accesses. */
33#define	Load			0x01
34#define	Store			0x02
35
36/* Data type. */
37#define	Integer			0x11
38#define	FloatingPoint		0x12
39
40/* Data size. */
41#define	Small			0x21
42#define	Medium			0x22
43#define	Large			0x23
44
45/* Post increment. */
46#define	NoPostInc		0x31
47#define	MinConstPostInc		0x32
48#define	PlusConstPostInc	0x33
49#define	ScratchRegPostInc	0x34
50#define	PreservedRegPostInc	0x35
51
52#if ACCESS == 0 || TYPE == 0 || SIZE == 0 || POSTINC == 0
53#error define ACCESS, TYPE, SIZE and/or POSTINC
54#endif
55
56#if TYPE == Integer
57#  define	REG		"r8"
58#  if SIZE == Small
59#    define	DATA_TYPE	short
60#    define	DATA_VALUE	0x1234
61#    define	LD		"ld2"
62#    define	ST		"st2"
63#  elif SIZE == Medium
64#    define	DATA_TYPE	int
65#    define	DATA_VALUE	0x12345678
66#    define	LD		"ld4"
67#    define	ST		"st4"
68#  elif SIZE == Large
69#    define	DATA_TYPE	long
70#    define	DATA_VALUE	0x1234567890ABCDEF
71#    define	LD		"ld8"
72#    define	ST		"st8"
73#  endif
74#elif TYPE == FloatingPoint
75#  define	REG		"f6"
76#  if SIZE == Small
77#    define	DATA_TYPE	float
78#    define	DATA_VALUE	FLT_MIN
79#    define	LD		"ldfs"
80#    define	ST		"stfs"
81#  elif SIZE == Medium
82#    define	DATA_TYPE	double
83#    define	DATA_VALUE	DBL_MIN
84#    define	LD		"ldfd"
85#    define	ST		"stfd"
86#  elif SIZE == Large
87#    define	DATA_TYPE	long double
88#    define	DATA_VALUE	LDBL_MIN
89#    define	LD		"ldfe"
90#    define	ST		"stfe"
91#  endif
92#endif
93
94struct {
95	DATA_TYPE aligned;
96	char _;
97	char misaligned[sizeof(DATA_TYPE)];
98} data;
99
100DATA_TYPE *aligned = &data.aligned;
101DATA_TYPE *misaligned = (DATA_TYPE *)data.misaligned;
102DATA_TYPE value = DATA_VALUE;
103
104void
105block_copy(void *dst, void *src, size_t sz)
106{
107
108	memcpy(dst, src, sz);
109}
110
111int
112main()
113{
114
115	/* Set PSR.ac. */
116	asm volatile("sum 8");
117
118#if ACCESS == Load
119	/*
120	 * LOAD
121	 */
122	block_copy(misaligned, &value, sizeof(DATA_TYPE));
123
124#  if POSTINC == NoPostInc
125	/* Misaligned load. */
126	*aligned = *misaligned;
127#  elif POSTINC == MinConstPostInc
128	asm volatile(
129		"ld8 r2=%0;;"
130		LD " " REG "=[r2],%2;;"
131		"st8 %0=r2;" ST " %1=" REG ";;"
132	    : "=m"(misaligned), "=m"(*aligned)
133	    : "i"(-sizeof(DATA_TYPE))
134	    : REG, "r2", "memory");
135#  elif POSTINC == PlusConstPostInc
136	asm volatile(
137		"ld8 r2=%0;;"
138		LD " " REG "=[r2],%2;;"
139		"st8 %0=r2;" ST " %1=" REG ";;"
140	    : "=m"(misaligned), "=m"(*aligned)
141	    : "i"(sizeof(DATA_TYPE))
142	    : REG, "r2", "memory");
143#  elif POSTINC == ScratchRegPostInc
144	asm volatile(
145		"ld8 r2=%0; mov r3=%2;;"
146		LD " " REG "=[r2],r3;;"
147		"st8 %0=r2;" ST " %1=" REG ";;"
148	    : "=m"(misaligned), "=m"(*aligned)
149	    : "i"(sizeof(DATA_TYPE))
150	    : REG, "r2", "r3", "memory");
151#  elif POSTINC == PreservedRegPostInc
152	asm volatile(
153		"ld8 r2=%0; mov r4=%2;;"
154		LD " " REG "=[r2],r4;;"
155		"st8 %0=r2;" ST " %1=" REG ";;"
156	    : "=m"(misaligned), "=m"(*aligned)
157	    : "i"(sizeof(DATA_TYPE))
158	    : REG, "r2", "r4", "memory");
159#  endif
160
161#elif ACCESS == Store
162	/*
163	 * STORE
164	 */
165
166#  if POSTINC == NoPostInc
167	/* Misaligned store. */
168	*misaligned = value;
169#  elif POSTINC == MinConstPostInc
170	asm volatile(
171		"ld8 r2=%0;" LD " " REG "=%1;;"
172		ST " [r2]=" REG ",%2;;"
173		"st8 %0=r2;;"
174	    : "=m"(misaligned)
175	    : "m"(value), "i"(-sizeof(DATA_TYPE))
176	    : REG, "r2", "memory");
177#  elif POSTINC == PlusConstPostInc
178	asm volatile(
179		"ld8 r2=%0;" LD " " REG "=%1;;"
180		ST " [r2]=" REG ",%2;;"
181		"st8 %0=r2;;"
182	    : "=m"(misaligned)
183	    : "m"(value), "i"(sizeof(DATA_TYPE))
184	    : REG, "r2", "memory");
185#  elif POSTINC == ScratchRegPostInc || POSTINC == PreservedRegPostInc
186	return (1);
187#  endif
188
189	block_copy(aligned, data.misaligned, sizeof(DATA_TYPE));
190#endif
191
192	if (*aligned != value)
193		return (2);
194
195#if POSTINC == NoPostInc
196	return (0);
197#elif POSTINC == MinConstPostInc
198	return (((char *)misaligned == data.misaligned - sizeof(DATA_TYPE))
199	    ? 0 : 4);
200#else
201	return (((char *)misaligned == data.misaligned + sizeof(DATA_TYPE))
202	    ? 0 : 4);
203#endif
204}
205