1// -*- C -*-
2
3// Simulator definition for the MIPS16e instructions.
4// Copyright (C) 2005-2024 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 3 of the License, or
13// (at your option) 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
21// along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
23
2411101,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
3411101,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
4311101,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
5311101,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)(uint8_t)(GPR[TRX]);
59  TRACE_ALU_RESULT (GPR[TRX]);
60}
61
6211101,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)(uint16_t)(GPR[TRX]);
68  TRACE_ALU_RESULT (GPR[TRX]);
69}
70
7111101,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)(uint32_t)(GPR[TRX]);
78  TRACE_ALU_RESULT (GPR[TRX]);
79}
80
81
8211101,3.RX,100,00000:RR:16::JRC
83"jrc r<TRX>"
84*mips16e:
85{
86  NIA = GPR[TRX];
87}
88
89
9011101,000,101,00000:RR:16::JRCRA
91"jrc ra"
92*mips16e:
93{
94  NIA = RA;
95}
96
97
9811101,3.RX,110,00000:RR:16::JALRC
99"jalrc r<TRX>"
100*mips16e:
101{
102  RA = NIA;
103  NIA = GPR[TRX];
104}
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    ATTRIBUTE_FALLTHROUGH;
216  case 6:
217    do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[23]);
218    ATTRIBUTE_FALLTHROUGH;
219  case 5:
220    do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[22]);
221    ATTRIBUTE_FALLTHROUGH;
222  case 4:
223    do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[21]);
224    ATTRIBUTE_FALLTHROUGH;
225  case 3:
226    do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[20]);
227    ATTRIBUTE_FALLTHROUGH;
228  case 2:
229    do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[19]);
230    ATTRIBUTE_FALLTHROUGH;
231  case 1:
232    do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[18]);
233  }
234
235  if (ras0s1 & 1)
236    do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[17]);
237  if (ras0s1 & 2)
238    do_store (SD_,AccessLength_WORD, temp -= 4, 0, GPR[16]);
239
240  switch (aregs) {
241  case 0: case 4: case 8: case 12: case 14:
242    astatic = 0;
243    break;
244  case 1: case 5: case 9: case 13:
245    astatic = 1;
246    break;
247  case 2: case 6: case 10:
248    astatic = 2;
249    break;
250  case 3: case 7:
251    astatic = 3;
252    break;
253  case 11:
254    astatic = 4;
255    break;
256  default:
257    sim_engine_abort (SD, CPU, CIA, "save: aregs=%d causes unpredictable results\n", aregs);
258  }
259  if (astatic > 0) {
260    do_store (SD_, AccessLength_WORD, temp -= 4, 0, GPR[7]);
261    if (astatic > 1) {
262      do_store (SD_, AccessLength_WORD, temp -= 4, 0, GPR[6]);
263      if (astatic > 2) {
264	do_store (SD_, AccessLength_WORD, temp -= 4, 0, GPR[5]);
265	if (astatic > 3) {
266	  do_store (SD_, AccessLength_WORD, temp -= 4, 0, GPR[4]);
267	}
268      }
269    }
270  }
271
272  GPR[29] -= framesize;
273}
274
27501100,100,1,3.RAS,4.FS:I8:16::SAVE
276"save %s<RAS>,<SFRAME>"
277*mips16e
278{
279  do_save (SD_, 0, 0, RAS, SFRAME);
280}
281
282
28311110,3.XSREGS,4.FSHI,4.AREGS + 01100,100,1,3.RAS,4.FSLO:EXT-I8:16::SAVE
284"save %s<RAS>%s<XSREGS>%s<AREGS><BFRAME>"
285*mips16e
286{
287  do_save (SD_, XSREGS, AREGS, RAS, BFRAME);
288}
289
290
291:function:::void:do_restore:int xsregs, int aregs, int ras0s1, int framesize
292*mips16e
293{
294  unsigned_word temp, temp2;
295  int astatic;
296
297  temp = GPR[29] + framesize;
298  temp2 = temp;
299
300  /* reads are in the same order as the hardware description... */
301
302  if (ras0s1 & 4)
303    GPR[31] = EXTEND32 (do_load(SD_, AccessLength_WORD, temp -= 4, 0));
304
305  switch (xsregs) {
306  case 7:
307    GPR[30] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
308  case 6:
309    GPR[23] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
310  case 5:
311    GPR[22] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
312  case 4:
313    GPR[21] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
314  case 3:
315    GPR[20] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
316  case 2:
317    GPR[19] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
318  case 1:
319    GPR[18] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
320  }
321
322  if (ras0s1 & 1)
323    GPR[17] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
324  if (ras0s1 & 2)
325    GPR[16] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
326
327  switch (aregs) {
328  case 0: case 4: case 8: case 12: case 14:
329    astatic = 0;
330    break;
331  case 1: case 5: case 9: case 13:
332    astatic = 1;
333    break;
334  case 2: case 6: case 10:
335    astatic = 2;
336    break;
337  case 3: case 7:
338    astatic = 3;
339    break;
340  case 11:
341    astatic = 4;
342    break;
343  default:
344    sim_engine_abort (SD, CPU, CIA, "save: aregs=%d causes unpredictable results\n", aregs);
345  }
346  if (astatic > 0) {
347    GPR[7] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
348    if (astatic > 1) {
349      GPR[6] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
350      if (astatic > 2) {
351	GPR[5] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
352	if (astatic > 3) {
353	  GPR[4] = EXTEND32 (do_load (SD_,AccessLength_WORD, temp -= 4, 0));
354	}
355      }
356    }
357  }
358
359  GPR[29] = temp2;
360}
361
36201100,100,0,3.RAS,4.FS:I8:16::RESTORE
363"restore %s<RAS>,<SFRAME>"
364*mips16e
365{
366  do_restore (SD_,0,0,RAS,SFRAME);
367}
368
36911110,3.XSREGS,4.FSHI,4.AREGS + 01100,100,0,3.RAS,4.FSLO:EXT-I8:16::RESTORE
370"restore %s<RAS>%s<XSREGS>%s<AREGS><BFRAME>"
371*mips16e
372{
373  do_restore (SD_,XSREGS,AREGS,RAS,BFRAME);
374}
375