1// -*- C -*-
2
3// Simulator definition for the MIPS16e instructions.
4// Copyright (C) 2005-2023 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  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
26901100,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
27711110,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
35601100,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
36311110,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}
369