Commit | Line | Data |
---|---|---|
b16d63da DU |
1 | // -*- C -*- |
2 | ||
3 | // Simulator definition for the MIPS16e instructions. | |
8acc9f48 | 4 | // Copyright (C) 2005-2013 Free Software Foundation, Inc. |
b16d63da DU |
5 | // Contributed by Nigel Stephens (nigel@mips.com) and |
6 | // David Ung (davidu@mips.com) of MIPS Technologies. | |
7 | // | |
8 | // This file is part of GDB, the GNU debugger. | |
9 | // | |
10 | // This program is free software; you can redistribute it and/or modify | |
11 | // it under the terms of the GNU General Public License as published by | |
4744ac1b JB |
12 | // the Free Software Foundation; either version 3 of the License, or |
13 | // (at your option) any later version. | |
14 | // | |
b16d63da DU |
15 | // This program is distributed in the hope that it will be useful, |
16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | // GNU General Public License for more details. | |
4744ac1b JB |
19 | // |
20 | // You should have received a copy of the GNU General Public License | |
21 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | |
b16d63da DU |
22 | |
23 | ||
24 | 11101,3.RX,100,10001:RR:16::SEB | |
25 | "seb r<TRX>" | |
26 | *mips16e: | |
27 | { | |
28 | TRACE_ALU_INPUT1 (GPR[TRX]); | |
29 | GPR[TRX] = EXTEND8 (GPR[TRX]); | |
30 | TRACE_ALU_RESULT (GPR[TRX]); | |
31 | } | |
32 | ||
33 | ||
34 | 11101,3.RX,101,10001:RR:16::SEH | |
35 | "seh r<TRX>" | |
36 | *mips16e: | |
37 | { | |
38 | TRACE_ALU_INPUT1 (GPR[TRX]); | |
39 | GPR[TRX] = EXTEND16 (GPR[TRX]); | |
40 | TRACE_ALU_RESULT (GPR[TRX]); | |
41 | } | |
42 | ||
43 | 11101,3.RX,110,10001:RR:16::SEW | |
44 | "sew r<TRX>" | |
45 | *mips16e: | |
46 | { | |
47 | check_u64 (SD_, instruction_0); | |
48 | TRACE_ALU_INPUT1 (GPR[TRX]); | |
49 | GPR[TRX] = EXTEND32 (GPR[TRX]); | |
50 | TRACE_ALU_RESULT (GPR[TRX]); | |
51 | } | |
52 | ||
53 | 11101,3.RX,000,10001:RR:16::ZEB | |
54 | "zeb r<TRX>" | |
55 | *mips16e: | |
56 | { | |
57 | TRACE_ALU_INPUT1 (GPR[TRX]); | |
58 | GPR[TRX] = (unsigned_word)(unsigned8)(GPR[TRX]); | |
59 | TRACE_ALU_RESULT (GPR[TRX]); | |
60 | } | |
61 | ||
62 | 11101,3.RX,001,10001:RR:16::ZEH | |
63 | "zeh r<TRX>" | |
64 | *mips16e: | |
65 | { | |
66 | TRACE_ALU_INPUT1 (GPR[TRX]); | |
67 | GPR[TRX] = (unsigned_word)(unsigned16)(GPR[TRX]); | |
68 | TRACE_ALU_RESULT (GPR[TRX]); | |
69 | } | |
70 | ||
71 | 11101,3.RX,010,10001:RR:16::ZEW | |
72 | "zew r<TRX>" | |
73 | *mips16e: | |
74 | { | |
75 | check_u64 (SD_, instruction_0); | |
76 | TRACE_ALU_INPUT1 (GPR[TRX]); | |
77 | GPR[TRX] = (unsigned_word)(unsigned32)(GPR[TRX]); | |
78 | TRACE_ALU_RESULT (GPR[TRX]); | |
79 | } | |
80 | ||
81 | ||
82 | 11101,3.RX,100,00000:RR:16::JRC | |
83 | "jrc r<TRX>" | |
84 | *mips16e: | |
85 | { | |
86 | NIA = GPR[TRX]; | |
87 | } | |
88 | ||
89 | ||
90 | 11101,000,101,00000:RR:16::JRCRA | |
91 | "jrc ra" | |
92 | *mips16e: | |
93 | { | |
94 | NIA = RA; | |
95 | } | |
96 | ||
97 | ||
98 | 11101,3.RX,110,00000:RR:16::JALRC | |
99 | "jalrc r<TRX>" | |
100 | *mips16e: | |
101 | { | |
102 | RA = NIA; | |
103 | NIA = GPR[TRX]; | |
104 | } | |
d85c3a10 TS |
105 | |
106 | ||
107 | // format routines for save/restore | |
108 | :%s::::RAS:int ras | |
109 | *mips16e | |
110 | { | |
111 | static char buf[10]; | |
112 | buf[0] = '\0'; | |
113 | if (ras & 4) | |
114 | strcat (buf,"ra,"); | |
115 | if (ras & 2) | |
116 | strcat (buf,"s0,"); | |
117 | if (ras & 1) | |
118 | strcat (buf,"s1,"); | |
119 | return (buf); | |
120 | } | |
121 | ||
122 | :%s::::XSREGS:int xsregs | |
123 | *mips16e | |
124 | { | |
125 | if (xsregs > 6) | |
126 | return "s2,s3,s4,s5,s6,s7,s8,"; | |
127 | if (xsregs > 5) | |
128 | return "s2,s3,s4,s5,s6,s7,"; | |
129 | if (xsregs > 4) | |
130 | return "s2,s3,s4,s5,s6,"; | |
131 | if (xsregs > 3) | |
132 | return "s2,s3,s4,s5,"; | |
133 | if (xsregs > 2) | |
134 | return "s2,s3,s4,"; | |
135 | if (xsregs > 1) | |
136 | return "s2,s3,"; | |
137 | if (xsregs > 0) | |
138 | return "s2,"; | |
139 | return ""; | |
140 | } | |
141 | ||
142 | :%s::::AREGS:int aregs | |
143 | *mips16e | |
144 | { | |
145 | // Fixme: how is the arg/static distinction made by the assembler? | |
146 | static const char * const aregstr[16] = { | |
147 | "", | |
148 | "A3,", | |
149 | "A2,A3,", | |
150 | "A1,A2,A3,", | |
151 | "A0,A1,A2,A3,", | |
152 | "a0,", | |
153 | "a0,A3,", | |
154 | "a0,A2,A3,", | |
155 | "a0,A1,A2,A3,", | |
156 | "a0,a1,", | |
157 | "a0,a1,A3,", | |
158 | "a0,a1,A2,A3,", | |
159 | "a0,a1,a2,", | |
160 | "a0,a1,a2,A3,", | |
161 | "?," | |
162 | }; | |
163 | return aregstr[aregs]; | |
164 | } | |
165 | ||
166 | :compute:::int:SFRAME:FS:((FS == 0) ? 128 \: (FS << 3)) | |
167 | :compute:::int:BFRAME:FSHI,FSLO:(((FSHI << 4) | FSLO) << 3) | |
168 | ||
169 | :function:::void:do_save:int xsregs, int aregs, int ras0s1, int framesize | |
170 | { | |
171 | unsigned_word temp; | |
172 | int args, astatic; | |
173 | ||
174 | temp = GPR[29]; | |
175 | ||
176 | /* writes are in the same order as the hardware description... */ | |
177 | switch (aregs) { | |
178 | case 0: case 1: case 2: case 3: case 11: | |
179 | args = 0; | |
180 | break; | |
181 | case 4: case 5: case 6: case 7: | |
182 | args = 1; | |
183 | break; | |
184 | case 8: case 9: case 10: | |
185 | args = 2; | |
186 | break; | |
187 | case 12: case 13: | |
188 | args = 3; | |
189 | break; | |
190 | case 14: | |
191 | args = 4; | |
192 | break; | |
193 | default: | |
194 | sim_engine_abort (SD, CPU, CIA, "save: aregs=%d causes unpredictable results\n", aregs); | |
195 | } | |
196 | if (args > 0) { | |
197 | do_store (SD_, AccessLength_WORD, temp, 0, GPR[4]); | |
198 | if (args > 1) { | |
199 | do_store (SD_,AccessLength_WORD, temp, 4 , GPR[5]); | |
200 | if (args > 2) { | |
201 | do_store (SD_,AccessLength_WORD, temp, 8 , GPR[6]); | |
202 | if (args > 3) { | |
203 | do_store (SD_,AccessLength_WORD, temp, 12, GPR[7]); | |
204 | } | |
205 | } | |
206 | } | |
207 | } | |
208 | ||
209 | if (ras0s1 & 4) | |
210 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[31]); | |
211 | ||
212 | switch (xsregs) { | |
213 | case 7: | |
214 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[30]); | |
215 | case 6: | |
216 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[23]); | |
217 | case 5: | |
218 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[22]); | |
219 | case 4: | |
220 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[21]); | |
221 | case 3: | |
222 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[20]); | |
223 | case 2: | |
224 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[19]); | |
225 | case 1: | |
226 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[18]); | |
227 | } | |
228 | ||
229 | if (ras0s1 & 1) | |
230 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[17]); | |
231 | if (ras0s1 & 2) | |
232 | do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[16]); | |
233 | ||
234 | switch (aregs) { | |
235 | case 0: case 4: case 8: case 12: case 14: | |
236 | astatic = 0; | |
237 | break; | |
238 | case 1: case 5: case 9: case 13: | |
239 | astatic = 1; | |
240 | break; | |
241 | case 2: case 6: case 10: | |
242 | astatic = 2; | |
243 | break; | |
244 | case 3: case 7: | |
245 | astatic = 3; | |
246 | break; | |
247 | case 11: | |
248 | astatic = 4; | |
249 | break; | |
250 | default: | |
251 | sim_engine_abort (SD, CPU, CIA, "save: aregs=%d causes unpredictable results\n", aregs); | |
252 | } | |
253 | if (astatic > 0) { | |
254 | do_store (SD_, AccessLength_WORD, temp -= 4, 0, GPR[7]); | |
255 | if (astatic > 1) { | |
256 | do_store (SD_, AccessLength_WORD, temp -= 4, 0, GPR[6]); | |
257 | if (astatic > 2) { | |
258 | do_store (SD_, AccessLength_WORD, temp -= 4, 0, GPR[5]); | |
259 | if (astatic > 3) { | |
260 | do_store (SD_, AccessLength_WORD, temp -= 4, 0, GPR[4]); | |
261 | } | |
262 | } | |
263 | } | |
264 | } | |
265 | ||
266 | GPR[29] -= framesize; | |
267 | } | |
268 | ||
269 | 01100,100,1,3.RAS,4.FS:I8:16::SAVE | |
270 | "save %s<RAS>,<SFRAME>" | |
271 | *mips16e | |
272 | { | |
273 | do_save (SD_, 0, 0, RAS, SFRAME); | |
274 | } | |
275 | ||
276 | ||
277 | 11110,3.XSREGS,4.FSHI,4.AREGS + 01100,100,1,3.RAS,4.FSLO:EXT-I8:16::SAVE | |
278 | "save %s<RAS>%s<XSREGS>%s<AREGS><BFRAME>" | |
279 | *mips16e | |
280 | { | |
281 | do_save (SD_, XSREGS, AREGS, RAS, BFRAME); | |
282 | } | |
283 | ||
284 | ||
285 | :function:::void:do_restore:int xsregs, int aregs, int ras0s1, int framesize | |
286 | *mips16e | |
287 | { | |
288 | unsigned_word temp, temp2; | |
289 | int astatic; | |
290 | ||
291 | temp = GPR[29] + framesize; | |
292 | temp2 = temp; | |
293 | ||
294 | /* reads are in the same order as the hardware description... */ | |
295 | ||
296 | if (ras0s1 & 4) | |
297 | GPR[31] = EXTEND32 (do_load(SD_, AccessLength_WORD, temp -= 4, 0)); | |
298 | ||
299 | switch (xsregs) { | |
300 | case 7: | |
301 | GPR[30] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
302 | case 6: | |
303 | GPR[23] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
304 | case 5: | |
305 | GPR[22] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
306 | case 4: | |
307 | GPR[21] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
308 | case 3: | |
309 | GPR[20] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
310 | case 2: | |
311 | GPR[19] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
312 | case 1: | |
313 | GPR[18] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
314 | } | |
315 | ||
316 | if (ras0s1 & 1) | |
317 | GPR[17] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
318 | if (ras0s1 & 2) | |
319 | GPR[16] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
320 | ||
321 | switch (aregs) { | |
322 | case 0: case 4: case 8: case 12: case 14: | |
323 | astatic = 0; | |
324 | break; | |
325 | case 1: case 5: case 9: case 13: | |
326 | astatic = 1; | |
327 | break; | |
328 | case 2: case 6: case 10: | |
329 | astatic = 2; | |
330 | break; | |
331 | case 3: case 7: | |
332 | astatic = 3; | |
333 | break; | |
334 | case 11: | |
335 | astatic = 4; | |
336 | break; | |
337 | default: | |
338 | sim_engine_abort (SD, CPU, CIA, "save: aregs=%d causes unpredictable results\n", aregs); | |
339 | } | |
340 | if (astatic > 0) { | |
341 | GPR[7] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
342 | if (astatic > 1) { | |
343 | GPR[6] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
344 | if (astatic > 2) { | |
345 | GPR[5] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
346 | if (astatic > 3) { | |
347 | GPR[4] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0)); | |
348 | } | |
349 | } | |
350 | } | |
351 | } | |
352 | ||
353 | GPR[29] = temp2; | |
354 | } | |
355 | ||
356 | 01100,100,0,3.RAS,4.FS:I8:16::RESTORE | |
357 | "restore %s<RAS>,<SFRAME>" | |
358 | *mips16e | |
359 | { | |
360 | do_restore (SD_,0,0,RAS,SFRAME); | |
361 | } | |
362 | ||
363 | 11110,3.XSREGS,4.FSHI,4.AREGS + 01100,100,0,3.RAS,4.FSLO:EXT-I8:16::RESTORE | |
364 | "restore %s<RAS>%s<XSREGS>%s<AREGS><BFRAME>" | |
365 | *mips16e | |
366 | { | |
367 | do_restore (SD_,XSREGS,AREGS,RAS,BFRAME); | |
368 | } |