Commit | Line | Data |
---|---|---|
e70cb6cd CD |
1 | // -*- C -*- |
2 | ||
3 | // Simulator definition for the MIPS 32/64 revision 2 instructions. | |
e2882c85 | 4 | // Copyright (C) 2004-2018 Free Software Foundation, Inc. |
e70cb6cd CD |
5 | // Contributed by David Ung, of MIPS Technologies. |
6 | // | |
8e394ffc | 7 | // This file is part of the MIPS sim. |
e70cb6cd CD |
8 | // |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
4744ac1b JB |
11 | // the Free Software Foundation; either version 3 of the License, or |
12 | // (at your option) any later version. | |
13 | // | |
e70cb6cd CD |
14 | // This program is distributed in the hope that it will be useful, |
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | // GNU General Public License for more details. | |
4744ac1b JB |
18 | // |
19 | // You should have received a copy of the GNU General Public License | |
20 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | |
e70cb6cd | 21 | |
8e394ffc AB |
22 | :function:::void:do_dsbh:int rd, int rt |
23 | { | |
24 | union { unsigned64 d; unsigned16 h[4]; } u; | |
25 | TRACE_ALU_INPUT1 (GPR[rt]); | |
26 | u.d = GPR[rt]; | |
27 | u.h[0] = SWAP_2 (u.h[0]); | |
28 | u.h[1] = SWAP_2 (u.h[1]); | |
29 | u.h[2] = SWAP_2 (u.h[2]); | |
30 | u.h[3] = SWAP_2 (u.h[3]); | |
31 | GPR[rd] = u.d; | |
32 | TRACE_ALU_RESULT1 (GPR[rd]); | |
33 | } | |
34 | ||
35 | :function:::void:do_dshd:int rd, int rt | |
36 | { | |
37 | unsigned64 d; | |
38 | TRACE_ALU_INPUT1 (GPR[rt]); | |
39 | d = GPR[rt]; | |
40 | GPR[rd] = ((d >> 48) | |
41 | | (d << 48) | |
42 | | ((d & 0x0000ffff00000000ULL) >> 16) | |
43 | | ((d & 0x00000000ffff0000ULL) << 16)); | |
44 | TRACE_ALU_RESULT1 (GPR[rd]); | |
45 | } | |
46 | ||
47 | :function:::void:do_dext:int rt, int rs, int lsb, int size | |
48 | { | |
49 | TRACE_ALU_INPUT3 (GPR[rs], lsb, size); | |
50 | GPR[rt] = EXTRACTED64 (GPR[rs], lsb + size, lsb); | |
51 | TRACE_ALU_RESULT1 (GPR[rt]); | |
52 | } | |
53 | ||
54 | :function:::void:do_dextm:int rt, int rs, int lsb, int size | |
55 | { | |
56 | TRACE_ALU_INPUT3 (GPR[rs], lsb, size); | |
57 | GPR[rt] = EXTRACTED64 (GPR[rs], lsb + size + 32, lsb); | |
58 | TRACE_ALU_RESULT1 (GPR[rt]); | |
59 | } | |
60 | ||
61 | :function:::void:do_dextu:int rt, int rs, int lsb, int size | |
62 | { | |
63 | TRACE_ALU_INPUT3 (GPR[rs], lsb, size); | |
64 | GPR[rt] = EXTRACTED64 (GPR[rs], lsb + 32 + size, lsb + 32); | |
65 | TRACE_ALU_RESULT1 (GPR[rt]); | |
66 | } | |
67 | ||
68 | :function:::void:do_di:int rt | |
69 | { | |
70 | TRACE_ALU_INPUT0 (); | |
71 | GPR[rt] = EXTEND32 (SR); | |
72 | SR &= ~status_IE; | |
73 | TRACE_ALU_RESULT1 (GPR[rt]); | |
74 | } | |
75 | ||
76 | :function:::void:do_dins:int rt, int rs, int lsb, int msb | |
77 | { | |
78 | TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb); | |
79 | if (lsb <= msb) | |
80 | GPR[rt] ^= (GPR[rt] ^ (GPR[rs] << lsb)) & MASK64 (msb, lsb); | |
81 | TRACE_ALU_RESULT1 (GPR[rt]); | |
82 | } | |
83 | ||
84 | :function:::void:do_dinsm:int rt, int rs, int lsb, int msb | |
85 | { | |
86 | TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb); | |
87 | if (lsb <= msb + 32) | |
88 | GPR[rt] ^= (GPR[rt] ^ (GPR[rs] << lsb)) & MASK64 (msb + 32, lsb); | |
89 | TRACE_ALU_RESULT1 (GPR[rt]); | |
90 | } | |
91 | ||
92 | :function:::void:do_ei:int rt | |
93 | { | |
94 | TRACE_ALU_INPUT0 (); | |
95 | GPR[rt] = EXTEND32 (SR); | |
96 | SR |= status_IE; | |
97 | TRACE_ALU_RESULT1 (GPR[rt]); | |
98 | } | |
99 | ||
100 | :function:::void:do_ext:int rt, int rs, int lsb, int size | |
101 | { | |
102 | TRACE_ALU_INPUT3 (GPR[rs], lsb, size); | |
103 | GPR[rt] = EXTEND32 (EXTRACTED32 (GPR[rs], lsb + size, lsb)); | |
104 | TRACE_ALU_RESULT1 (GPR[rt]); | |
105 | } | |
106 | ||
107 | :function:::void:do_mfhc1:int rt, int fs | |
108 | { | |
109 | check_fpu (SD_); | |
110 | if (SizeFGR() == 64) | |
111 | GPR[rt] = EXTEND32 (WORD64HI (FGR[fs])); | |
112 | else if ((fs & 0x1) == 0) | |
113 | GPR[rt] = EXTEND32 (FGR[fs + 1]); | |
114 | else | |
115 | { | |
116 | if (STATE_VERBOSE_P(SD)) | |
117 | sim_io_eprintf (SD, | |
118 | "Warning: PC 0x%lx: MFHC1 32-bit use of odd FPR number\n", | |
119 | (long) CIA); | |
120 | GPR[rt] = EXTEND32 (0xBADF00D); | |
121 | } | |
122 | TRACE_ALU_RESULT (GPR[rt]); | |
123 | } | |
124 | ||
125 | :function:::void:do_mthc1:int rt, int fs | |
126 | { | |
127 | check_fpu (SD_); | |
128 | if (SizeFGR() == 64) | |
129 | StoreFPR (fs, fmt_uninterpreted_64, SET64HI (GPR[rt]) | VL4_8 (FGR[fs])); | |
130 | else if ((fs & 0x1) == 0) | |
131 | StoreFPR (fs + 1, fmt_uninterpreted_32, VL4_8 (GPR[rt])); | |
132 | else | |
133 | { | |
134 | if (STATE_VERBOSE_P(SD)) | |
135 | sim_io_eprintf (SD, | |
136 | "Warning: PC 0x%lx: MTHC1 32-bit use of odd FPR number\n", | |
137 | (long) CIA); | |
138 | StoreFPR (fs, fmt_uninterpreted_32, 0xDEADC0DE); | |
139 | } | |
140 | TRACE_FP_RESULT (GPR[rt]); | |
141 | } | |
142 | ||
143 | :function:::void:do_ins:int rt, int rs, int lsb, int msb | |
144 | { | |
145 | TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb); | |
146 | if (lsb <= msb) | |
147 | GPR[rt] = EXTEND32 (GPR[rt] ^ | |
148 | ((GPR[rt] ^ (GPR[rs] << lsb)) & MASK32 (msb, lsb))); | |
149 | TRACE_ALU_RESULT1 (GPR[rt]); | |
150 | } | |
151 | ||
152 | :function:::void:do_dinsu:int rt, int rs, int lsb, int msb | |
153 | { | |
154 | TRACE_ALU_INPUT4 (GPR[rt], GPR[rs], lsb, msb); | |
155 | if (lsb <= msb) | |
156 | GPR[rt] ^= (GPR[rt] ^ (GPR[rs] << (lsb + 32))) | |
157 | & MASK64 (msb + 32, lsb + 32); | |
158 | TRACE_ALU_RESULT1 (GPR[rt]); | |
159 | } | |
160 | ||
161 | :function:::void:do_seb:int rd, int rt | |
162 | { | |
163 | TRACE_ALU_INPUT1 (GPR[rt]); | |
164 | GPR[rd] = EXTEND8 (GPR[rt]); | |
165 | TRACE_ALU_RESULT1 (GPR[rd]); | |
166 | } | |
167 | ||
168 | :function:::void:do_seh:int rd, int rt | |
169 | { | |
170 | TRACE_ALU_INPUT1 (GPR[rt]); | |
171 | GPR[rd] = EXTEND16 (GPR[rt]); | |
172 | TRACE_ALU_RESULT1 (GPR[rd]); | |
173 | } | |
174 | ||
175 | :function:::void:do_rdhwr:int rt, int rd | |
176 | { | |
177 | // Return 0 for all hardware registers currently | |
178 | GPR[rt] = EXTEND32 (0); | |
179 | TRACE_ALU_RESULT1 (GPR[rt]); | |
180 | } | |
181 | ||
182 | :function:::void:do_wsbh:int rd, int rt | |
183 | { | |
184 | union { unsigned32 w; unsigned16 h[2]; } u; | |
185 | TRACE_ALU_INPUT1 (GPR[rt]); | |
186 | u.w = GPR[rt]; | |
187 | u.h[0] = SWAP_2 (u.h[0]); | |
188 | u.h[1] = SWAP_2 (u.h[1]); | |
189 | GPR[rd] = EXTEND32 (u.w); | |
190 | TRACE_ALU_RESULT1 (GPR[rd]); | |
191 | } | |
e70cb6cd CD |
192 | |
193 | 011111,5.RS,5.RT,5.SIZE,5.LSB,000011::64::DEXT | |
194 | "dext r<RT>, r<RS>, <LSB>, <SIZE+1>" | |
195 | *mips64r2: | |
196 | { | |
197 | check_u64 (SD_, instruction_0); | |
8e394ffc | 198 | do_dext (SD_, RT, RS, LSB, SIZE); |
e70cb6cd CD |
199 | } |
200 | ||
201 | 011111,5.RS,5.RT,5.SIZE,5.LSB,000001::64::DEXTM | |
202 | "dextm r<RT>, r<RS>, <LSB>, <SIZE+33>" | |
203 | *mips64r2: | |
204 | { | |
205 | check_u64 (SD_, instruction_0); | |
8e394ffc | 206 | do_dextm (SD_, RT, RS, LSB, SIZE); |
e70cb6cd CD |
207 | } |
208 | ||
209 | 011111,5.RS,5.RT,5.SIZE,5.LSB,000010::64::DEXTU | |
210 | "dextu r<RT>, r<RS>, <LSB+32>, <SIZE+1>" | |
211 | *mips64r2: | |
212 | { | |
213 | check_u64 (SD_, instruction_0); | |
8e394ffc | 214 | do_dextu (SD_, RT, RS, LSB, SIZE); |
e70cb6cd CD |
215 | } |
216 | ||
217 | ||
218 | 010000,01011,5.RT,01100,00000,0,00,000::32::DI | |
219 | "di":RT == 0 | |
220 | "di r<RT>" | |
221 | *mips32r2: | |
222 | *mips64r2: | |
223 | { | |
8e394ffc | 224 | do_di (SD_, RT); |
e70cb6cd CD |
225 | } |
226 | ||
227 | ||
228 | 011111,5.RS,5.RT,5.MSB,5.LSB,000111::64::DINS | |
229 | "dins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>" | |
230 | *mips64r2: | |
231 | { | |
232 | check_u64 (SD_, instruction_0); | |
8e394ffc | 233 | do_dins (SD_, RT, RS, LSB, MSB); |
e70cb6cd CD |
234 | } |
235 | ||
236 | 011111,5.RS,5.RT,5.MSB,5.LSB,000101::64::DINSM | |
237 | "dinsm r<RT>, r<RS>, <LSB>, <MSB+32-LSB+1>" | |
238 | *mips64r2: | |
239 | { | |
240 | check_u64 (SD_, instruction_0); | |
8e394ffc | 241 | do_dinsm (SD_, RT, RS, LSB, MSB); |
e70cb6cd CD |
242 | } |
243 | ||
244 | 011111,5.RS,5.RT,5.MSB,5.LSB,000110::64::DINSU | |
245 | "dinsu r<RT>, r<RS>, <LSB+32>, <MSB-LSB+1>" | |
246 | *mips64r2: | |
247 | { | |
248 | check_u64 (SD_, instruction_0); | |
8e394ffc | 249 | do_dinsu (SD_, RT, RS, LSB, MSB); |
e70cb6cd CD |
250 | } |
251 | ||
252 | ||
253 | 011111,00000,5.RT,5.RD,00010,100100::64::DSBH | |
254 | "dsbh r<RD>, r<RT>" | |
255 | *mips64r2: | |
256 | { | |
e70cb6cd | 257 | check_u64 (SD_, instruction_0); |
8e394ffc | 258 | do_dsbh (SD_, RD, RT); |
e70cb6cd CD |
259 | } |
260 | ||
261 | 011111,00000,5.RT,5.RD,00101,100100::64::DSHD | |
262 | "dshd r<RD>, r<RT>" | |
263 | *mips64r2: | |
264 | { | |
e70cb6cd | 265 | check_u64 (SD_, instruction_0); |
8e394ffc | 266 | do_dshd (SD_, RD, RT); |
e70cb6cd CD |
267 | } |
268 | ||
e70cb6cd CD |
269 | 010000,01011,5.RT,01100,00000,1,00,000::32::EI |
270 | "ei":RT == 0 | |
271 | "ei r<RT>" | |
272 | *mips32r2: | |
273 | *mips64r2: | |
274 | { | |
8e394ffc | 275 | do_ei (SD_, RT); |
e70cb6cd CD |
276 | } |
277 | ||
278 | ||
279 | 011111,5.RS,5.RT,5.SIZE,5.LSB,000000::32::EXT | |
280 | "ext r<RT>, r<RS>, <LSB>, <SIZE+1>" | |
281 | *mips32r2: | |
282 | *mips64r2: | |
283 | { | |
8e394ffc | 284 | do_ext (SD_, RT, RS, LSB, SIZE); |
e70cb6cd CD |
285 | } |
286 | ||
287 | ||
288 | 010001,00011,5.RT,5.FS,00000000000:COP1Sa:32,f::MFHC1 | |
289 | "mfhc1 r<RT>, f<FS>" | |
290 | *mips32r2: | |
291 | *mips64r2: | |
292 | { | |
8e394ffc | 293 | do_mfhc1 (SD_, RT, FS); |
e70cb6cd CD |
294 | } |
295 | ||
296 | 010001,00111,5.RT,5.FS,00000000000:COP1Sa:32,f::MTHC1 | |
297 | "mthc1 r<RT>, f<FS>" | |
298 | *mips32r2: | |
299 | *mips64r2: | |
300 | { | |
8e394ffc | 301 | do_mthc1 (SD_, RT, FS); |
e70cb6cd CD |
302 | } |
303 | ||
304 | ||
305 | 011111,5.RS,5.RT,5.MSB,5.LSB,000100::32::INS | |
306 | "ins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>" | |
307 | *mips32r2: | |
308 | *mips64r2: | |
309 | { | |
8e394ffc | 310 | do_ins (SD_, RT, RS, LSB, MSB); |
e70cb6cd CD |
311 | } |
312 | ||
313 | ||
314 | 011111,00000,5.RT,5.RD,10000,100000::32::SEB | |
315 | "seb r<RD>, r<RT>" | |
316 | *mips32r2: | |
317 | *mips64r2: | |
318 | { | |
8e394ffc | 319 | do_seb (SD_, RD, RT); |
e70cb6cd CD |
320 | } |
321 | ||
322 | 011111,00000,5.RT,5.RD,11000,100000::32::SEH | |
323 | "seh r<RD>, r<RT>" | |
324 | *mips32r2: | |
325 | *mips64r2: | |
326 | { | |
8e394ffc | 327 | do_seh (SD_, RD, RT); |
e70cb6cd CD |
328 | } |
329 | ||
330 | ||
331 | 000001,5.BASE,11111,16.OFFSET::32::SYNCI | |
332 | "synci <OFFSET>(r<BASE>)" | |
333 | *mips32r2: | |
334 | *mips64r2: | |
335 | { | |
336 | // sync i-cache - nothing to do currently | |
337 | } | |
338 | ||
339 | ||
37cb8f8e SE |
340 | 011111,00000,5.RT,5.RD,00000,111011::32::RDHWR |
341 | "rdhwr r<RT>, r<RD>" | |
342 | *mips32r2: | |
343 | *mips64r2: | |
344 | { | |
8e394ffc | 345 | do_rdhwr (SD_, RT, RD); |
37cb8f8e SE |
346 | } |
347 | ||
348 | ||
e70cb6cd CD |
349 | 011111,00000,5.RT,5.RD,00010,100000::32::WSBH |
350 | "wsbh r<RD>, r<RT>" | |
351 | *mips32r2: | |
352 | *mips64r2: | |
353 | { | |
8e394ffc | 354 | do_wsbh (SD_, RD, RT); |
e70cb6cd CD |
355 | } |
356 | ||
357 | ||
358 |