1 #include <stdio.h>
2 
3 /* Dummy variable. Needed to work around GCC code generation bugs */
4 volatile long v;
5 
6 #define ADD_REG_MEM(insn, s1, s2, CARRY)		\
7 ({							\
8 	unsigned long tmp = s1;				\
9 	int cc;						\
10 	asm volatile(	"lghi 0," #CARRY "\n"		\
11 			"aghi 0, 0\n"			\
12 			#insn " %0, %3\n"		\
13 			"ipm %1\n"			\
14 			"srl %1,28\n"			\
15 			: "+d" (tmp), "=d" (cc)		\
16 			: "d" (tmp), "Q" (s2)		\
17 			: "0", "cc");			\
18 	printf(#insn " " #CARRY " + %16.16lX + %16.16lX = %16.16lX (cc=%d)\n", s1, s2, tmp, cc); \
19 })
20 
21 #define ADD_REG_REG(insn, s1, s2, CARRY)		\
22 ({							\
23 	unsigned long tmp = s1;				\
24 	int cc;						\
25 	asm volatile(	"lghi 0," #CARRY "\n"		\
26 			"aghi 0, 0\n"			\
27 			#insn " %0, %3\n"		\
28 			"ipm %1\n"			\
29 			"srl %1,28\n"			\
30 			: "+d" (tmp), "=d" (cc)		\
31 			: "d" (tmp), "d" (s2)		\
32 			: "0", "cc");			\
33 	printf(#insn " " #CARRY " + %16.16lX + %16.16lX = %16.16lX (cc=%d)\n", s1, s2, tmp, cc); \
34 })
35 
36 #define ADD_REG_IMM(insn, s1, s2, CARRY)		\
37 ({							\
38 	unsigned long tmp = s1;				\
39 	int cc;						\
40 	asm volatile(	"lghi 0," #CARRY "\n"		\
41 			"aghi 0, 0\n"			\
42 			#insn " %0," #s2 "\n"		\
43 			"ipm %1\n"			\
44 			"srl %1,28\n"			\
45 			: "+d" (tmp), "=d" (cc)		\
46 			: "d" (tmp)			\
47 			: "0", "cc");			\
48 	printf(#insn " " #CARRY " + %16.16lX + %16.16lX = %16.16lX (cc=%d)\n", s1, (unsigned long) s2, tmp, cc); \
49 })
50 
51 #define ADD_MEM_IMM(insn, s1, s2, CARRY)		\
52 ({							\
53 	unsigned long tmp = s1, v2;			\
54 	register unsigned long *addr asm("5") = &tmp;	\
55 	int cc;						\
56 	asm volatile(	"lghi 0," #CARRY "\n"		\
57 			"aghi 0, 0\n"			\
58 			insn(s2,5,000,00)		\
59 			"ipm %1\n"			\
60 			"srl %1,28\n"			\
61 			: "+Q" (tmp), "=d" (cc)		\
62 			: "Q" (tmp), "d" (addr)		\
63 			: "0", "cc");			\
64         v2 =  (((signed long)((unsigned long)0x##s2 << 56)) >> 56); \
65 	printf(#insn " " #CARRY " + %16.16lX + %16.16lX = %16.16lX (cc=%d)\n", s1, v2, tmp, cc); \
66 })
67 
68 
69 #define memsweep(i, s2, carryset)				\
70 ({								\
71 	ADD_REG_MEM(i, 0ul, s2, carryset);			\
72 	ADD_REG_MEM(i, 1ul, s2, carryset);			\
73 	ADD_REG_MEM(i, 0xfffful, s2, carryset);			\
74 	ADD_REG_MEM(i, 0x7ffful, s2, carryset);			\
75 	ADD_REG_MEM(i, 0x8000ul, s2, carryset);			\
76 	ADD_REG_MEM(i, 0xfffffffful, s2, carryset);		\
77 	ADD_REG_MEM(i, 0x80000000ul, s2, carryset);		\
78 	ADD_REG_MEM(i, 0x7ffffffful, s2, carryset);		\
79 	ADD_REG_MEM(i, 0xfffffffffffffffful, s2, carryset);	\
80 	ADD_REG_MEM(i, 0x8000000000000000ul, s2, carryset);	\
81 	ADD_REG_MEM(i, 0x7ffffffffffffffful, s2, carryset);	\
82 })
83 
84 #define regsweep(i, s2, carryset)				\
85 ({								\
86 	ADD_REG_REG(i, 0ul, s2, carryset);			\
87 	ADD_REG_REG(i, 1ul, s2, carryset);			\
88 	ADD_REG_REG(i, 0xfffful, s2, carryset);			\
89 	ADD_REG_REG(i, 0x7ffful, s2, carryset);			\
90 	ADD_REG_REG(i, 0x8000ul, s2, carryset);			\
91 	ADD_REG_REG(i, 0xfffffffful, s2, carryset);		\
92 	ADD_REG_REG(i, 0x80000000ul, s2, carryset);		\
93 	ADD_REG_REG(i, 0x7ffffffful, s2, carryset);		\
94 	ADD_REG_REG(i, 0xfffffffffffffffful, s2, carryset);	\
95 	ADD_REG_REG(i, 0x8000000000000000ul, s2, carryset);	\
96 	ADD_REG_REG(i, 0x7ffffffffffffffful, s2, carryset);	\
97 })
98 
99 #define immsweep(i, s2, carryset)				\
100 ({								\
101 	ADD_REG_IMM(i, 0ul, s2, carryset);			\
102 	ADD_REG_IMM(i, 1ul, s2, carryset);			\
103 	ADD_REG_IMM(i, 0xfffful, s2, carryset);			\
104 	ADD_REG_IMM(i, 0x7ffful, s2, carryset);			\
105 	ADD_REG_IMM(i, 0x8000ul, s2, carryset);			\
106 	ADD_REG_IMM(i, 0xfffffffful, s2, carryset);		\
107 	ADD_REG_IMM(i, 0x80000000ul, s2, carryset);		\
108 	ADD_REG_IMM(i, 0x7ffffffful, s2, carryset);		\
109 	ADD_REG_IMM(i, 0xfffffffffffffffful, s2, carryset);	\
110 	ADD_REG_IMM(i, 0x8000000000000000ul, s2, carryset);	\
111 	ADD_REG_IMM(i, 0x7ffffffffffffffful, s2, carryset);	\
112 })
113 
114 #define memimmsweep(i, s2, carryset)				\
115 ({								\
116 	ADD_MEM_IMM(i, 0ul, s2, carryset);			\
117 	ADD_MEM_IMM(i, 1ul, s2, carryset);			\
118 	ADD_MEM_IMM(i, 0xfffful, s2, carryset);			\
119 	ADD_MEM_IMM(i, 0x7ffful, s2, carryset);			\
120 	ADD_MEM_IMM(i, 0x8000ul, s2, carryset);			\
121 	ADD_MEM_IMM(i, 0xfffffffful, s2, carryset);		\
122 	ADD_MEM_IMM(i, 0x80000000ul, s2, carryset);		\
123 	ADD_MEM_IMM(i, 0x7ffffffful, s2, carryset);		\
124 	ADD_MEM_IMM(i, 0xfffffffffffffffful, s2, carryset);	\
125 	ADD_MEM_IMM(i, 0x8000000000000000ul, s2, carryset);	\
126 	ADD_MEM_IMM(i, 0x7ffffffffffffffful, s2, carryset);	\
127 })
128 
129 #define ahysweep(i, s2, carryset)				\
130 ({								\
131 	ADD_REG_MEM(i, 0ul, s2, carryset);			\
132 	ADD_REG_MEM(i, 1ul, s2, carryset);			\
133 	ADD_REG_MEM(i, 0xfffful, s2, carryset);			\
134 	ADD_REG_MEM(i, 0x7ffful, s2, carryset);			\
135 	ADD_REG_MEM(i, 0x8000ul, s2, carryset);			\
136 	ADD_REG_MEM(i, 0xfffffffful, s2, carryset);		\
137 	ADD_REG_MEM(i, 0x80000000ul, s2, carryset);		\
138 	ADD_REG_MEM(i, 0x7ffffffful, s2, carryset);		\
139 	ADD_REG_MEM(i, 0xfffffffffffffffful, s2, carryset);	\
140 	ADD_REG_MEM(i, 0x8000000000000000ul, s2, carryset);	\
141 	ADD_REG_MEM(i, 0x7ffffffffffffffful, s2, carryset);	\
142 })
143 
144 #define ADD_REG_LDISP(insn, s1, s2, CARRY)			\
145 ({								\
146 	register unsigned long tmp asm("2") = s1;		\
147 	register unsigned long *addr asm("5") = &s2;		\
148 	int cc;							\
149 	asm volatile(	"lghi 0," #CARRY "\n"			\
150 			"aghi 0, 0\n"				\
151 			insn(2,0,5,000,00)			\
152 			"ipm %1\n"				\
153 			"srl %1,28\n"				\
154 			: "+d" (tmp), "=d" (cc)			\
155 			: "d" (tmp), "Q" (s2), "d"(addr)	\
156 			: "cc");				\
157 	v = tmp; /* work around GCC code gen bug */     \
158 	printf(#insn " " #CARRY " + %16.16lX + %16.16lX = %16.16lX (cc=%d)\n", s1, s2, v, cc); \
159 })
160 
161 #define ldispsweep(i, s2, carryset)				\
162 ({								\
163 	ADD_REG_LDISP(i, 0ul, s2, carryset);			\
164 	ADD_REG_LDISP(i, 1ul, s2, carryset);			\
165 	ADD_REG_LDISP(i, 0xfffful, s2, carryset);		\
166 	ADD_REG_LDISP(i, 0x7ffful, s2, carryset);		\
167 	ADD_REG_LDISP(i, 0x8000ul, s2, carryset);		\
168 	ADD_REG_LDISP(i, 0xfffffffful, s2, carryset);		\
169 	ADD_REG_LDISP(i, 0x80000000ul, s2, carryset);		\
170 	ADD_REG_LDISP(i, 0x7ffffffful, s2, carryset);		\
171 	ADD_REG_LDISP(i, 0xfffffffffffffffful, s2, carryset);	\
172 	ADD_REG_LDISP(i, 0x8000000000000000ul, s2, carryset);	\
173 	ADD_REG_LDISP(i, 0x7ffffffffffffffful, s2, carryset);	\
174 })
175 
176 #define ADD_REG_XIMM(insn, s1, us2,s2, CARRY)		\
177 ({							\
178 	register unsigned long tmp asm("2") = s1;	\
179 	int cc;						\
180 	asm volatile(	"lghi 0," #CARRY "\n"		\
181 			"aghi 0, 0\n"			\
182 			insn(2,s2)			\
183 			"ipm %1\n"			\
184 			"srl %1,28\n"			\
185 			: "+d" (tmp), "=d" (cc)		\
186 			: "d" (tmp)			\
187 			: "0", "cc");			\
188 	v = tmp; /* work around GCC code gen bug */     \
189 	printf(#insn " " #CARRY " + %16.16lX + %16.16lX = %16.16lX (cc=%d)\n", s1, (unsigned long) 0x##us2##s2, v, cc); \
190 })
191 
192 #define ximmsweep(i, us2, s2, carryset)					\
193 ({									\
194 	ADD_REG_XIMM(i, 0ul, us2, s2, carryset);			\
195 	ADD_REG_XIMM(i, 1ul, us2, s2, carryset);			\
196 	ADD_REG_XIMM(i, 0xfffful, us2, s2, carryset);			\
197 	ADD_REG_XIMM(i, 0x7ffful, us2, s2, carryset);			\
198 	ADD_REG_XIMM(i, 0x8000ul, us2, s2, carryset);			\
199 	ADD_REG_XIMM(i, 0xfffffffful, us2, s2, carryset);		\
200 	ADD_REG_XIMM(i, 0x80000000ul, us2, s2, carryset);		\
201 	ADD_REG_XIMM(i, 0x7ffffffful, us2, s2, carryset);		\
202 	ADD_REG_XIMM(i, 0xfffffffffffffffful, us2, s2, carryset);	\
203 	ADD_REG_XIMM(i, 0x8000000000000000ul, us2, s2, carryset);	\
204 	ADD_REG_XIMM(i, 0x7ffffffffffffffful, us2, s2, carryset);	\
205 })
206 
207