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 	R4 = 0;
106 	CC = R4 == R7;
107 	IF CC jump _new_instruction;
108 
109 	/* is the opcode (R0) greater than the 2nd entry in the table (R6) */
110 	/* if so look at the next line in the table */
111 	CC = R6 < R0;
112 	if CC jump _match;
113 
114 	/* is the opcode (R0) smaller than the first entry in the table (R7) */
115 	/* this means it's somewhere between the two lines, and should be legal */
116 	CC = R7 <= R0;
117 	if !CC jump _legal_instruction;
118 
119 	/* is the current EXCAUSE (R3), the same as the table (R5) */
120 	/* if not, fail */
121 	CC = R3 == R5
122 	if !CC jump fail_lvl;
123 
124 _match_done:
125 	/* back up, and store the location to search next */
126 	[P4] = P2;
127 
128 	/* it matches, so fall through */
129 	jump _next_instruction;
130 
131 _new_instruction:
132 	se_all_new_insn_stub
133 
134 	/* output the insn (R0) and excause (R3) if diff from last */
135 	loadsym P0, _last_excause;
136 	R2 = [P0];
137 	CC = R2 == R3;
138 	IF CC jump _next_instruction;
139 	[P0] = R3;
140 
141 	se_all_new_insn_log
142 
143 _legal_instruction:
144 	R4 = 0x10;
145 	CC = R3 == R4;
146 	IF !CC JUMP fail_lvl;
147 	/* it wasn't in the list, and was a single step, so fall through */
148 
149 _next_instruction:
150 	se_all_next_insn
151 
152 	/* Make sure the opcode isn't in a write buffer */
153 	SSYNC;
154 
155 	R1 = P5;
156 	RETX = R1;
157 
158 	/* set up pointers to valid data (32Meg), to reduce address violations */
159 	reset_dags
160 	RETS = r0;
161 	RETN = r0;
162 	RETE = r0;
163 	RETI = r0;
164 
165 	RTX;
166 
167 .section .text.usr
168 	.align 4
169 _usr:
170 	se_all_insn_init
171 	loadsym P0, fail_lvl;
172 	JUMP (P0);
173 
174 .data
175 	.align 4;
176 _last_excause:
177 	.dd 0xffff
178 _next_location:
179 	.dd _table_end
180 _location:
181 	.dd 0
182 _table:
183 	se_all_insn_table
184 _table_end:
185 .endm
186 
187 .macro se_all_load_table
188 	R7 = LOAD_PFX[P1++];
189 	R6 = LOAD_PFX[P1++];
190 	R5 = LOAD_PFX[P1++];
191 .endm
192 
193 #ifndef SE_ALL_NEW_INSN_STUB
194 .macro se_all_new_insn_stub
195 	jump fail_lvl;
196 .endm
197 #endif
198 
199 .macro se_all_new_insn_log
200 .ifdef BFIN_JTAG_xxxxx
201 	R1 = R0;
202 #if SE_ALL_BITS == 32
203 	R0 = 0x8;
204 	call __emu_out;
205 	R0 = R1;
206 	call __emu_out;
207 	R0 = R3;
208 #else
209 	R0 = 0x4;
210 	call __emu_out;
211 	R0 = R1 << 16;
212 	R0 = R0 | R3;
213 #endif
214 	call __emu_out;
215 .else
216 	loadsym P0, _next_location;
217 	P1 = [P0];
218 	LOAD_PFX[P1++] = R0;
219 	LOAD_PFX[P1++] = R3;
220 	[P0] = P1;
221 .endif
222 .endm
223