1// -*- C -*-
2
3// Simulator definition for the MIPS 32/64 revision 2 instructions.
4// Copyright (C) 2004-2024 Free Software Foundation, Inc.
5// Contributed by David Ung, of MIPS Technologies.
6//
7// This file is part of the MIPS sim.
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
11// the Free Software Foundation; either version 3 of the License, or
12// (at your option) any later version.
13//
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.
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/>.
21
22:function:::void:do_dsbh:int rd, int rt
23{
24  union { uint64_t d; uint16_t 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  uint64_t 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 { uint32_t w; uint16_t 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}
192
193011111,5.RS,5.RT,5.SIZE,5.LSB,000011::64::DEXT
194"dext r<RT>, r<RS>, <LSB>, <SIZE+1>"
195*mips64r2:
196*mips64r6:
197{
198  check_u64 (SD_, instruction_0);
199  do_dext (SD_, RT, RS, LSB, SIZE);
200}
201
202011111,5.RS,5.RT,5.SIZE,5.LSB,000001::64::DEXTM
203"dextm r<RT>, r<RS>, <LSB>, <SIZE+33>"
204*mips64r2:
205*mips64r6:
206{
207  check_u64 (SD_, instruction_0);
208  do_dextm (SD_, RT, RS, LSB, SIZE);
209}
210
211011111,5.RS,5.RT,5.SIZE,5.LSB,000010::64::DEXTU
212"dextu r<RT>, r<RS>, <LSB+32>, <SIZE+1>"
213*mips64r2:
214*mips64r6:
215{
216  check_u64 (SD_, instruction_0);
217  do_dextu (SD_, RT, RS, LSB, SIZE);
218}
219
220
221010000,01011,5.RT,01100,00000,0,00,000::32::DI
222"di":RT == 0
223"di r<RT>"
224*mips32r2:
225*mips32r6:
226*mips64r2:
227*mips64r6:
228{
229  do_di (SD_, RT);
230}
231
232
233011111,5.RS,5.RT,5.MSB,5.LSB,000111::64::DINS
234"dins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>"
235*mips64r2:
236*mips64r6:
237{
238  check_u64 (SD_, instruction_0);
239  do_dins (SD_, RT, RS, LSB, MSB);
240}
241
242011111,5.RS,5.RT,5.MSB,5.LSB,000101::64::DINSM
243"dinsm r<RT>, r<RS>, <LSB>, <MSB+32-LSB+1>"
244*mips64r2:
245*mips64r6:
246{
247  check_u64 (SD_, instruction_0);
248  do_dinsm (SD_, RT, RS, LSB, MSB);
249}
250
251011111,5.RS,5.RT,5.MSB,5.LSB,000110::64::DINSU
252"dinsu r<RT>, r<RS>, <LSB+32>, <MSB-LSB+1>"
253*mips64r2:
254*mips64r6:
255{
256  check_u64 (SD_, instruction_0);
257  do_dinsu (SD_, RT, RS, LSB, MSB);
258}
259
260
261011111,00000,5.RT,5.RD,00010,100100::64::DSBH
262"dsbh r<RD>, r<RT>"
263*mips64r2:
264*mips64r6:
265{
266  check_u64 (SD_, instruction_0);
267  do_dsbh (SD_, RD, RT);
268}
269
270011111,00000,5.RT,5.RD,00101,100100::64::DSHD
271"dshd r<RD>, r<RT>"
272*mips64r2:
273*mips64r6:
274{
275  check_u64 (SD_, instruction_0);
276  do_dshd (SD_, RD, RT);
277}
278
279010000,01011,5.RT,01100,00000,1,00,000::32::EI
280"ei":RT == 0
281"ei r<RT>"
282*mips32r2:
283*mips32r6:
284*mips64r2:
285*mips64r6:
286{
287  do_ei (SD_, RT);
288}
289
290
291011111,5.RS,5.RT,5.SIZE,5.LSB,000000::32::EXT
292"ext r<RT>, r<RS>, <LSB>, <SIZE+1>"
293*mips32r2:
294*mips32r6:
295*mips64r2:
296*mips64r6:
297{
298  do_ext (SD_, RT, RS, LSB, SIZE);
299}
300
301
302010001,00011,5.RT,5.FS,00000000000:COP1Sa:32,f::MFHC1
303"mfhc1 r<RT>, f<FS>"
304*mips32r2:
305*mips32r6:
306*mips64r2:
307*mips64r6:
308{
309  do_mfhc1 (SD_, RT, FS);
310}
311
312010001,00111,5.RT,5.FS,00000000000:COP1Sa:32,f::MTHC1
313"mthc1 r<RT>, f<FS>"
314*mips32r2:
315*mips32r6:
316*mips64r2:
317*mips64r6:
318{
319  do_mthc1 (SD_, RT, FS);
320}
321
322
323011111,5.RS,5.RT,5.MSB,5.LSB,000100::32::INS
324"ins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>"
325*mips32r2:
326*mips32r6:
327*mips64r2:
328*mips64r6:
329{
330  do_ins (SD_, RT, RS, LSB, MSB);
331}
332
333
334011111,00000,5.RT,5.RD,10000,100000::32::SEB
335"seb r<RD>, r<RT>"
336*mips32r2:
337*mips32r6:
338*mips64r2:
339*mips64r6:
340{
341  do_seb (SD_, RD, RT);
342}
343
344011111,00000,5.RT,5.RD,11000,100000::32::SEH
345"seh r<RD>, r<RT>"
346*mips32r2:
347*mips32r6:
348*mips64r2:
349*mips64r6:
350{
351  do_seh (SD_, RD, RT);
352}
353
354
355000001,5.BASE,11111,16.OFFSET::32::SYNCI
356"synci <OFFSET>(r<BASE>)"
357*mips32r2:
358*mips32r6:
359*mips64r2:
360*mips64r6:
361{
362  // sync i-cache - nothing to do currently
363}
364
365
366011111,00000,5.RT,5.RD,00000,111011::32::RDHWR
367"rdhwr r<RT>, r<RD>"
368*mips32r2:
369*mips32r6:
370*mips64r2:
371*mips64r6:
372{
373  do_rdhwr (SD_, RT, RD);
374}
375
376
377011111,00000,5.RT,5.RD,00010,100000::32::WSBH
378"wsbh r<RD>, r<RT>"
379*mips32r2:
380*mips32r6:
381*mips64r2:
382*mips64r6:
383{
384  do_wsbh (SD_, RD, RT);
385}
386
387
388
389