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