1 #include <stdio.h>
2 
3 /* Dummy variable. Needed to work around GCC code generation bugs */
4 volatile long v;
5 
6 #define SUB_REG_MEM(insn, s1, s2, NOBORROW)		\
7 ({							\
8 	unsigned long tmp = s1;				\
9 	int cc;						\
10 	asm volatile(	"lghi 0," #NOBORROW "\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 " %16.16lX - %16.16lX - %d = %16.16lX (cc=%d)\n", s1, s2, !NOBORROW, tmp, cc); \
19 })
20 
21 #define SUB_REG_REG(insn, s1, s2, NOBORROW)		\
22 ({							\
23 	unsigned long tmp = s1;				\
24 	int cc;						\
25 	asm volatile(	"lghi 0," #NOBORROW "\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 " %16.16lX - %16.16lX - %d = %16.16lX (cc=%d)\n", s1, s2, !NOBORROW, tmp, cc); \
34 })
35 
36 #define SUB_REG_IMM(insn, s1, s2, NOBORROW)		\
37 ({							\
38 	register unsigned long tmp asm("2") = s1;	\
39 	int cc;						\
40 	asm volatile(	"lghi 0," #NOBORROW "\n"		\
41 			"aghi 0, 0\n"			\
42                         insn(2,s2)			\
43 			"ipm %1\n"			\
44 			"srl %1,28\n"			\
45 			: "+d" (tmp), "=d" (cc)		\
46 			: "d" (tmp)			\
47 			: "0", "cc");			\
48 	v = tmp;					\
49 	printf(#insn " %16.16lX - %16.16lX - %d = %16.16lX (cc=%d)\n", s1, (unsigned long) 0x00000000##s2, !NOBORROW, v, cc); \
50 })
51 
52 #define memsweep(i, s2, carryset)				\
53 ({								\
54 	SUB_REG_MEM(i, 0ul, s2, carryset);			\
55 	SUB_REG_MEM(i, 1ul, s2, carryset);			\
56 	SUB_REG_MEM(i, 0xfffful, s2, carryset);			\
57 	SUB_REG_MEM(i, 0x7ffful, s2, carryset);			\
58 	SUB_REG_MEM(i, 0x8000ul, s2, carryset);			\
59 	SUB_REG_MEM(i, 0xfffffffful, s2, carryset);		\
60 	SUB_REG_MEM(i, 0x80000000ul, s2, carryset);		\
61 	SUB_REG_MEM(i, 0x7ffffffful, s2, carryset);		\
62 	SUB_REG_MEM(i, 0xfffffffffffffffful, s2, carryset);	\
63 	SUB_REG_MEM(i, 0x8000000000000000ul, s2, carryset);	\
64 	SUB_REG_MEM(i, 0x7ffffffffffffffful, s2, carryset);	\
65 })
66 
67 #define regsweep(i, s2, carryset)				\
68 ({								\
69 	SUB_REG_REG(i, 0ul, s2, carryset);			\
70 	SUB_REG_REG(i, 1ul, s2, carryset);			\
71 	SUB_REG_REG(i, 0xfffful, s2, carryset);			\
72 	SUB_REG_REG(i, 0x7ffful, s2, carryset);			\
73 	SUB_REG_REG(i, 0x8000ul, s2, carryset);			\
74 	SUB_REG_REG(i, 0xfffffffful, s2, carryset);		\
75 	SUB_REG_REG(i, 0x80000000ul, s2, carryset);		\
76 	SUB_REG_REG(i, 0x7ffffffful, s2, carryset);		\
77 	SUB_REG_REG(i, 0xfffffffffffffffful, s2, carryset);	\
78 	SUB_REG_REG(i, 0x8000000000000000ul, s2, carryset);	\
79 	SUB_REG_REG(i, 0x7ffffffffffffffful, s2, carryset);	\
80 })
81 
82 #define immsweep(i, s2, carryset)				\
83 ({								\
84 	SUB_REG_IMM(i, 0ul, s2, carryset);			\
85 	SUB_REG_IMM(i, 1ul, s2, carryset);			\
86 	SUB_REG_IMM(i, 0xfffful, s2, carryset);			\
87 	SUB_REG_IMM(i, 0x7ffful, s2, carryset);			\
88 	SUB_REG_IMM(i, 0x8000ul, s2, carryset);			\
89 	SUB_REG_IMM(i, 0xfffffffful, s2, carryset);		\
90 	SUB_REG_IMM(i, 0x80000000ul, s2, carryset);		\
91 	SUB_REG_IMM(i, 0x7ffffffful, s2, carryset);		\
92 	SUB_REG_IMM(i, 0xfffffffffffffffful, s2, carryset);	\
93 	SUB_REG_IMM(i, 0x8000000000000000ul, s2, carryset);	\
94 	SUB_REG_IMM(i, 0x7ffffffffffffffful, s2, carryset);	\
95 })
96 
97 #define SUB_REG_LDISP(insn, s1, s2, NOBORROW)			\
98 ({								\
99 	register unsigned long tmp asm("2") = s1;		\
100 	register unsigned long *addr asm("5") = &s2;		\
101 	int cc;							\
102 	asm volatile(	"lghi 0," #NOBORROW "\n"		\
103 			"aghi 0, 0\n"				\
104 			insn(2,0,5,000,00)			\
105 			"ipm %1\n"				\
106 			"srl %1,28\n"				\
107 			: "+d" (tmp), "=d" (cc)			\
108 			: "d" (tmp), "Q" (s2), "d"(addr)	\
109 			: "cc");				\
110 	v = tmp; /* work around GCC code gen bug */     \
111 	printf(#insn " %16.16lX - %16.16lX - %d = %16.16lX (cc=%d)\n", s1, s2, !NOBORROW, v, cc); \
112 })
113 
114 #define ldispsweep(i, s2, carryset)				\
115 ({								\
116 	SUB_REG_LDISP(i, 0ul, s2, carryset);			\
117 	SUB_REG_LDISP(i, 1ul, s2, carryset);			\
118 	SUB_REG_LDISP(i, 0xfffful, s2, carryset);		\
119 	SUB_REG_LDISP(i, 0x7ffful, s2, carryset);		\
120 	SUB_REG_LDISP(i, 0x8000ul, s2, carryset);		\
121 	SUB_REG_LDISP(i, 0xfffffffful, s2, carryset);		\
122 	SUB_REG_LDISP(i, 0x80000000ul, s2, carryset);		\
123 	SUB_REG_LDISP(i, 0x7ffffffful, s2, carryset);		\
124 	SUB_REG_LDISP(i, 0xfffffffffffffffful, s2, carryset);	\
125 	SUB_REG_LDISP(i, 0x8000000000000000ul, s2, carryset);	\
126 	SUB_REG_LDISP(i, 0x7ffffffffffffffful, s2, carryset);	\
127 })
128