master
c 224 lines 6.94 KB
Raw
1 /*
2 * Test m68k trap addresses.
3 */
4
5 #define _GNU_SOURCE 1
6 #include <signal.h>
7 #include <assert.h>
8 #include <limits.h>
9
10 static int expect_sig;
11 static int expect_si_code;
12 static void *expect_si_addr;
13 static greg_t expect_mc_pc;
14 static volatile int got_signal;
15
16 static void sig_handler(int sig, siginfo_t *si, void *puc)
17 {
18 ucontext_t *uc = puc;
19 mcontext_t *mc = &uc->uc_mcontext;
20
21 assert(sig == expect_sig);
22 assert(si->si_code == expect_si_code);
23 assert(si->si_addr == expect_si_addr);
24 assert(mc->gregs[R_PC] == expect_mc_pc);
25
26 got_signal = 1;
27 }
28
29 #define FMT_INS [ad] "a"(&expect_si_addr), [pc] "a"(&expect_mc_pc)
30 #define FMT0_STR(S) \
31 "move.l #1f, (%[ad])\n\tmove.l #1f, (%[pc])\n" S "\n1:\n"
32 #define FMT2_STR(S) \
33 "move.l #0f, (%[ad])\n\tmove.l #1f, (%[pc])\n" S "\n1:\n"
34
35 #define CHECK_SIG do { assert(got_signal); got_signal = 0; } while (0)
36 #define OUT_CZ "\n\tscs %0\n\tseq %1" : [c] "=r"(c), [z] "=r"(z) :
37
38 int main(int argc, char **argv)
39 {
40 struct sigaction act = {
41 .sa_sigaction = sig_handler,
42 .sa_flags = SA_SIGINFO
43 };
44 int t0, t1;
45 char bbounds[2] = { 0, 2 };
46 short wbounds[2] = { 0, 2 };
47 int lbounds[2] = { 0, 2 };
48 static int sbounds[2] = { 0, 2 };
49 void *intermediate;
50 char c, z;
51
52 /*
53 * Tests for CMP2, which sets the condition code register just as
54 * CHK2 does but doesn't raise out-of-bounds exceptions:
55 */
56 asm volatile("cmp2.b %2, %3" OUT_CZ "m"(bbounds), "d"(-1));
57 assert(c && !z);
58 asm volatile("cmp2.b %2, %3" OUT_CZ "m"(bbounds), "d"(0));
59 assert(!c && z);
60 asm volatile("cmp2.b %2, %3" OUT_CZ "m"(bbounds), "d"(1));
61 assert(!c && !z);
62 asm volatile("cmp2.b %2, %3" OUT_CZ "m"(bbounds), "d"(2));
63 assert(!c && z);
64 asm volatile("cmp2.b %2, %3" OUT_CZ "m"(bbounds), "d"(3));
65 assert(c && !z);
66 asm volatile("cmp2.w %2, %3" OUT_CZ "m"(wbounds), "d"(-1));
67 assert(c && !z);
68 asm volatile("cmp2.w %2, %3" OUT_CZ "m"(wbounds), "d"(0));
69 assert(!c && z);
70 asm volatile("cmp2.w %2, %3" OUT_CZ "m"(wbounds), "d"(1));
71 assert(!c && !z);
72 asm volatile("cmp2.w %2, %3" OUT_CZ "m"(wbounds), "d"(2));
73 assert(!c && z);
74 asm volatile("cmp2.w %2, %3" OUT_CZ "m"(wbounds), "d"(3));
75 assert(c && !z);
76 asm volatile("cmp2.l %2, %3" OUT_CZ "m"(lbounds), "d"(-1));
77 assert(c && !z);
78 asm volatile("cmp2.l %2, %3" OUT_CZ "m"(lbounds), "d"(0));
79 assert(!c && z);
80 asm volatile("cmp2.l %2, %3" OUT_CZ "m"(lbounds), "d"(1));
81 assert(!c && !z);
82 asm volatile("cmp2.l %2, %3" OUT_CZ "m"(lbounds), "d"(2));
83 assert(!c && z);
84 asm volatile("cmp2.l %2, %3" OUT_CZ "m"(lbounds), "d"(3));
85 assert(c && !z);
86
87 /*
88 * CHK2 shouldn't raise out-of-bounds exceptions, either, when the
89 * register value is within bounds:
90 */
91 asm volatile("chk2.b %2, %3" OUT_CZ "m"(bbounds), "d"(0));
92 assert(!c && z);
93 asm volatile("chk2.w %2, %3" OUT_CZ "m"(wbounds), "d"(0));
94 assert(!c && z);
95 asm volatile("chk2.l %2, %3" OUT_CZ "m"(lbounds), "d"(0));
96 assert(!c && z);
97
98 /* Address register indirect addressing (without displacement) */
99 asm volatile("chk2.l %2, %3" OUT_CZ "Q"(lbounds), "d"(2));
100 assert(!c && z);
101
102 /* Absolute long addressing */
103 asm volatile("chk2.l %2, %3" OUT_CZ "m"(sbounds), "d"(2));
104 assert(!c && z);
105
106 /* Memory indirect preindexed addressing */
107 intermediate = (void *)lbounds - 0x0D0D0D0D;
108 asm volatile("chk2.l %2@(0xBDBDBDBD,%3:l:4)@(0x0D0D0D0D), %4" OUT_CZ
109 "a"((void *)&intermediate - 0xBDBDBDBD - 0xEEEE * 4),
110 "r"(0xEEEE), "d"(2));
111 assert(!c && z);
112
113 sigaction(SIGILL, &act, NULL);
114 sigaction(SIGTRAP, &act, NULL);
115 sigaction(SIGFPE, &act, NULL);
116
117 expect_sig = SIGFPE;
118 expect_si_code = FPE_INTOVF;
119 asm volatile(FMT2_STR("0:\tchk %0, %1") : : "d"(0), "d"(-1), FMT_INS);
120 CHECK_SIG;
121
122 /*
123 * The extension word here should be counted when computing the
124 * address of the next instruction in the exception stack frame
125 */
126 asm volatile(FMT2_STR("0:\tchk %0, %1")
127 : : "m"(lbounds), "d"(-1), FMT_INS);
128 CHECK_SIG;
129
130 asm volatile(FMT2_STR("0:\tchk2.b %0, %1")
131 : : "m"(bbounds), "d"(3), FMT_INS);
132 CHECK_SIG;
133
134 asm volatile(FMT2_STR("0:\tchk2.w %0, %1")
135 : : "m"(wbounds), "d"(3), FMT_INS);
136 CHECK_SIG;
137
138 asm volatile(FMT2_STR("0:\tchk2.l %0, %1")
139 : : "m"(lbounds), "d"(3), FMT_INS);
140 CHECK_SIG;
141
142 /* Absolute long addressing */
143 asm volatile(FMT2_STR("0:\tchk2.l %0, %1")
144 : : "m"(sbounds), "d"(3), FMT_INS);
145 CHECK_SIG;
146
147 /*
148 * Memory indirect preindexed addressing; also, the six extension
149 * words here should be counted when computing the address of the
150 * next instruction in the exception stack frame
151 */
152 asm volatile(FMT2_STR("0:\tchk2.l %0@(0xBDBDBDBD,%1:l:4)@(0x0D0D0D0D), %2")
153 : : "a"((void *)&intermediate - 0xBDBDBDBD - 0xEEEE * 4),
154 "r"(0xEEEE), "d"(3), FMT_INS);
155 CHECK_SIG;
156
157 asm volatile(FMT2_STR("cmp.l %0, %1\n0:\ttrapv")
158 : : "d"(INT_MIN), "d"(1), FMT_INS);
159 CHECK_SIG;
160
161 asm volatile(FMT2_STR("cmp.l %0, %0\n0:\ttrapeq")
162 : : "d"(0), FMT_INS);
163 CHECK_SIG;
164
165 asm volatile(FMT2_STR("cmp.l %0, %0\n0:\ttrapeq.w #0x1234")
166 : : "d"(0), FMT_INS);
167 CHECK_SIG;
168
169 asm volatile(FMT2_STR("cmp.l %0, %0\n0:\ttrapeq.l #0x12345678")
170 : : "d"(0), FMT_INS);
171 CHECK_SIG;
172
173 asm volatile(FMT2_STR("fcmp.x %0, %0\n0:\tftrapeq")
174 : : "f"(0.0L), FMT_INS);
175 CHECK_SIG;
176
177 expect_si_code = FPE_INTDIV;
178
179 asm volatile(FMT2_STR("0:\tdivs.w %1, %0")
180 : "=d"(t0) : "d"(0), "0"(1), FMT_INS);
181 CHECK_SIG;
182
183 asm volatile(FMT2_STR("0:\tdivsl.l %2, %1:%0")
184 : "=d"(t0), "=d"(t1) : "d"(0), "0"(1), FMT_INS);
185 CHECK_SIG;
186
187 expect_sig = SIGILL;
188 expect_si_code = ILL_ILLTRP;
189 asm volatile(FMT0_STR("trap #1") : : FMT_INS);
190 CHECK_SIG;
191 asm volatile(FMT0_STR("trap #2") : : FMT_INS);
192 CHECK_SIG;
193 asm volatile(FMT0_STR("trap #3") : : FMT_INS);
194 CHECK_SIG;
195 asm volatile(FMT0_STR("trap #4") : : FMT_INS);
196 CHECK_SIG;
197 asm volatile(FMT0_STR("trap #5") : : FMT_INS);
198 CHECK_SIG;
199 asm volatile(FMT0_STR("trap #6") : : FMT_INS);
200 CHECK_SIG;
201 asm volatile(FMT0_STR("trap #7") : : FMT_INS);
202 CHECK_SIG;
203 asm volatile(FMT0_STR("trap #8") : : FMT_INS);
204 CHECK_SIG;
205 asm volatile(FMT0_STR("trap #9") : : FMT_INS);
206 CHECK_SIG;
207 asm volatile(FMT0_STR("trap #10") : : FMT_INS);
208 CHECK_SIG;
209 asm volatile(FMT0_STR("trap #11") : : FMT_INS);
210 CHECK_SIG;
211 asm volatile(FMT0_STR("trap #12") : : FMT_INS);
212 CHECK_SIG;
213 asm volatile(FMT0_STR("trap #13") : : FMT_INS);
214 CHECK_SIG;
215 asm volatile(FMT0_STR("trap #14") : : FMT_INS);
216 CHECK_SIG;
217
218 expect_sig = SIGTRAP;
219 expect_si_code = TRAP_BRKPT;
220 asm volatile(FMT0_STR("trap #15") : : FMT_INS);
221 CHECK_SIG;
222
223 return 0;
224 }