xref: /netbsd-src/external/gpl3/gdb/dist/sim/testsuite/bfin/se_allopcodes.h (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
1 /*
2  * set up pointers to valid data (32Meg), to reduce address violations
3  */
4 .macro reset_dags
5 	imm32 r0, 0x2000000;
6 	l0 = 0; l1 = 0; l2 = 0; l3 = 0;
7 	p0 = r0; p1 = r0; p2 = r0; p3 = r0; p4 = r0; p5 = r0;
8 	usp = r0; fp = r0;
9 	i0 = r0; i1 = r0; i2 = r0; i3 = r0;
10 	b0 = r0; b1 = r0; b2 = r0; b3 = r0;
11 .endm
12 
13 #if SE_ALL_BITS == 32
14 # define LOAD_PFX
15 #elif SE_ALL_BITS == 16
16 # define LOAD_PFX W
17 #else
18 # error "Please define SE_ALL_BITS"
19 #endif
20 
21 /*
22  * execute a test of an opcode space.  host test
23  * has to fill out a number of callbacks.
24  *
25  *	se_all_insn_init
26  *		the first insn to start executing
27  *	se_all_insn_table
28  *		the table of insn ranges and expected seqstat
29  *
30  *	se_all_load_insn
31  *	  in: P5
32  *	  out: R0, R2
33  *	  scratch: R1
34  *		load current user insn via register P5 into R0.
35  *		register R2 is available for caching with se_all_next_insn.
36  *	se_all_load_table
37  *	  in: P1
38  *	  out: R7, R6, R5
39  *	  scratch: R1
40  *		load insn range/seqstat entry from table via register P1
41  *		R7: low range
42  *		R6: high range
43  *		R5: seqstat
44  *
45  *	se_all_next_insn
46  *	  in: P5, R2
47  *	  out: <nothing>
48  *	  scratch: all but P5
49  *		advance current insn to next one for testing.  register R2
50  *		is retained from se_all_load_insn.  write out new insn to
51  *		the location via register P5.
52  *
53  *	se_all_new_insn_stub
54  *	se_all_new_insn_log
55  *		for handling of new insns ... generally not needed once done
56  */
57 .macro se_all_test
58 	start
59 
60 	/* Set up exception handler */
61 	imm32 P4, EVT3;
62 	loadsym R1, _evx;
63 	[P4] = R1;
64 
65 	/* set up the _location */
66 	loadsym P0, _location
67 	loadsym P1, _table;
68 	[P0] = P1;
69 
70 	/* Enable single stepping */
71 	R0 = 1;
72 	SYSCFG = R0;
73 
74 	/* Lower to the code we want to single step through */
75 	loadsym P1, _usr;
76 	RETI = P1;
77 
78 	/* set up pointers to valid data (32Meg), to reduce address violations */
79 	reset_dags
80 
81 	RTI;
82 
83 pass_lvl:
84 	dbg_pass;
85 fail_lvl:
86 	dbg_fail;
87 
88 _evx:
89 	/* Make sure exception reason is as we expect */
90 	R3 = SEQSTAT;
91 	R4 = 0x3f;
92 	R3 = R3 & R4;
93 
94 	/* find a match */
95 	loadsym P5, _usr;
96 	loadsym P4, _location;
97 	P1 = [P4];
98 	se_all_load_insn
99 
100 _match:
101 	P2 = P1;
102 	se_all_load_table
103 
104 	/* is this the end of the table? */
105 	CC = R7 == 0;
106 	IF CC jump _new_instruction;
107 
108 	/* is the opcode (R0) greater than the 2nd entry in the table (R6) */
109 	/* if so look at the next line in the table */
110 	CC = R6 < R0;
111 	if CC jump _match;
112 
113 	/* is the opcode (R0) smaller than the first entry in the table (R7) */
114 	/* this means it's somewhere between the two lines, and should be legal */
115 	CC = R7 <= R0;
116 	if !CC jump _legal_instruction;
117 
118 	/* is the current EXCAUSE (R3), the same as the table (R5) */
119 	/* if not, fail */
120 	CC = R3 == R5
121 	if !CC jump fail_lvl;
122 
123 _match_done:
124 	/* back up, and store the location to search next */
125 	[P4] = P2;
126 
127 	/* it matches, so fall through */
128 	jump _next_instruction;
129 
130 _new_instruction:
131 	/* The table is generated in memory and can be extracted:
132 	   (gdb) dump binary memory bin &table next_location
133 
134 	   16bit:
135 	   $ od -j6 -x --width=4 bin | \
136 	     awk '{ s=last; e=strtonum("0x"$2); \
137 	       printf "\t.dw 0x%04x,\t0x%04x,\t\t0x%02x\n", \
138 	          s, e-1, strtonum("0x"seq); \
139 	       last=e; seq=$3}'
140 
141 	   32bit:
142 	   $ od -j12 -x --width=8 bin | \
143 	     awk '{ s=last; e=strtonum("0x"$3$2); \
144 	       printf "\t.dw 0x%04x, 0x%04x,\t0x%04x, 0x%04x,\t\t0x%02x, 0\n", \
145 	          and(s,0xffff), rshift(s,16), and(e-1,0xffff), rshift(e-1,16), \
146 	          strtonum("0x"seq); \
147 	       last=e; seq=$3}'
148 
149 	   This should be much faster than dumping over serial/jtag.  */
150 	se_all_new_insn_stub
151 
152 	/* output the insn (R0) and excause (R3) if diff from last */
153 	loadsym P0, _last_excause;
154 	R2 = [P0];
155 	CC = R2 == R3;
156 	IF CC jump _next_instruction;
157 	[P0] = R3;
158 
159 	se_all_new_insn_log
160 
161 _legal_instruction:
162 	R4 = 0x10;
163 	CC = R3 == R4;
164 	IF !CC JUMP fail_lvl;
165 	/* it wasn't in the list, and was a single step, so fall through */
166 
167 _next_instruction:
168 	se_all_next_insn
169 
170 .ifdef BFIN_JTAG
171 	/* Make sure the opcode isn't in a write buffer */
172 	SSYNC;
173 .endif
174 
175 	R1 = P5;
176 	RETX = R1;
177 
178 	/* set up pointers to valid data (32Meg), to reduce address violations */
179 	reset_dags
180 	RETS = r0;
181 
182 	RTX;
183 
184 .section .text.usr
185 	.align 4
186 _usr:
187 	se_all_insn_init
188 	loadsym P0, fail_lvl;
189 	JUMP (P0);
190 
191 .data
192 	.align 4;
193 _last_excause:
194 	.dd 0xffff
195 _next_location:
196 	.dd _table_end
197 _location:
198 	.dd 0
199 _table:
200 	se_all_insn_table
201 _table_end:
202 .endm
203 
204 .macro se_all_load_table
205 	R7 = LOAD_PFX[P1++];
206 	R6 = LOAD_PFX[P1++];
207 	R5 = LOAD_PFX[P1++];
208 .endm
209 
210 #ifndef SE_ALL_NEW_INSN_STUB
211 .macro se_all_new_insn_stub
212 	jump fail_lvl;
213 .endm
214 #endif
215 
216 .macro se_all_new_insn_log
217 .ifdef BFIN_JTAG_xxxxx
218 	R1 = R0;
219 #if SE_ALL_BITS == 32
220 	R0 = 0x8;
221 	call __emu_out;
222 	R0 = R1;
223 	call __emu_out;
224 	R0 = R3;
225 #else
226 	R0 = 0x4;
227 	call __emu_out;
228 	R0 = R1 << 16;
229 	R0 = R0 | R3;
230 #endif
231 	call __emu_out;
232 .else
233 	loadsym P0, _next_location;
234 	P1 = [P0];
235 	LOAD_PFX[P1++] = R0;
236 	LOAD_PFX[P1++] = R3;
237 	[P0] = P1;
238 .endif
239 .endm
240