1/* Simulator parallel routines for CGEN simulators (and maybe others).
2   Copyright (C) 1999-2023 Free Software Foundation, Inc.
3   Contributed by Cygnus Solutions.
4
5This file is part of the GNU instruction set simulator.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20/* This must come before any other includes.  */
21#include "defs.h"
22
23#include <stdlib.h>
24
25#include "sim-main.h"
26#include "cgen-mem.h"
27#include "cgen-par.h"
28
29/* Functions required by the cgen interface.  These functions add various
30   kinds of writes to the write queue.  */
31void sim_queue_bi_write (SIM_CPU *cpu, BI *target, BI value)
32{
33  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
34  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
35  element->kind = CGEN_BI_WRITE;
36  element->insn_address = CPU_PC_GET (cpu);
37  element->kinds.bi_write.target = target;
38  element->kinds.bi_write.value  = value;
39}
40
41void sim_queue_qi_write (SIM_CPU *cpu, UQI *target, UQI value)
42{
43  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
44  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
45  element->kind = CGEN_QI_WRITE;
46  element->insn_address = CPU_PC_GET (cpu);
47  element->kinds.qi_write.target = target;
48  element->kinds.qi_write.value  = value;
49}
50
51void sim_queue_si_write (SIM_CPU *cpu, SI *target, SI value)
52{
53  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
54  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
55  element->kind = CGEN_SI_WRITE;
56  element->insn_address = CPU_PC_GET (cpu);
57  element->kinds.si_write.target = target;
58  element->kinds.si_write.value  = value;
59}
60
61void sim_queue_sf_write (SIM_CPU *cpu, SI *target, SF value)
62{
63  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
64  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
65  element->kind = CGEN_SF_WRITE;
66  element->insn_address = CPU_PC_GET (cpu);
67  element->kinds.sf_write.target = target;
68  element->kinds.sf_write.value  = value;
69}
70
71void sim_queue_pc_write (SIM_CPU *cpu, USI value)
72{
73  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
74  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
75  element->kind = CGEN_PC_WRITE;
76  element->insn_address = CPU_PC_GET (cpu);
77  element->kinds.pc_write.value = value;
78}
79
80void sim_queue_fn_hi_write (
81  SIM_CPU *cpu,
82  void (*write_function)(SIM_CPU *cpu, UINT, UHI),
83  UINT regno,
84  UHI value
85)
86{
87  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
88  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
89  element->kind = CGEN_FN_HI_WRITE;
90  element->insn_address = CPU_PC_GET (cpu);
91  element->kinds.fn_hi_write.function = write_function;
92  element->kinds.fn_hi_write.regno = regno;
93  element->kinds.fn_hi_write.value = value;
94}
95
96void sim_queue_fn_si_write (
97  SIM_CPU *cpu,
98  void (*write_function)(SIM_CPU *cpu, UINT, USI),
99  UINT regno,
100  USI value
101)
102{
103  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
104  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
105  element->kind = CGEN_FN_SI_WRITE;
106  element->insn_address = CPU_PC_GET (cpu);
107  element->kinds.fn_si_write.function = write_function;
108  element->kinds.fn_si_write.regno = regno;
109  element->kinds.fn_si_write.value = value;
110}
111
112void sim_queue_fn_sf_write (
113  SIM_CPU *cpu,
114  void (*write_function)(SIM_CPU *cpu, UINT, SF),
115  UINT regno,
116  SF value
117)
118{
119  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
120  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
121  element->kind = CGEN_FN_SF_WRITE;
122  element->insn_address = CPU_PC_GET (cpu);
123  element->kinds.fn_sf_write.function = write_function;
124  element->kinds.fn_sf_write.regno = regno;
125  element->kinds.fn_sf_write.value = value;
126}
127
128void sim_queue_fn_di_write (
129  SIM_CPU *cpu,
130  void (*write_function)(SIM_CPU *cpu, UINT, DI),
131  UINT regno,
132  DI value
133)
134{
135  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
136  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
137  element->kind = CGEN_FN_DI_WRITE;
138  element->insn_address = CPU_PC_GET (cpu);
139  element->kinds.fn_di_write.function = write_function;
140  element->kinds.fn_di_write.regno = regno;
141  element->kinds.fn_di_write.value = value;
142}
143
144void sim_queue_fn_xi_write (
145  SIM_CPU *cpu,
146  void (*write_function)(SIM_CPU *cpu, UINT, SI *),
147  UINT regno,
148  SI *value
149)
150{
151  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
152  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
153  element->kind = CGEN_FN_XI_WRITE;
154  element->insn_address = CPU_PC_GET (cpu);
155  element->kinds.fn_xi_write.function = write_function;
156  element->kinds.fn_xi_write.regno = regno;
157  element->kinds.fn_xi_write.value[0] = value[0];
158  element->kinds.fn_xi_write.value[1] = value[1];
159  element->kinds.fn_xi_write.value[2] = value[2];
160  element->kinds.fn_xi_write.value[3] = value[3];
161}
162
163void sim_queue_fn_df_write (
164  SIM_CPU *cpu,
165  void (*write_function)(SIM_CPU *cpu, UINT, DF),
166  UINT regno,
167  DF value
168)
169{
170  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
171  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
172  element->kind = CGEN_FN_DF_WRITE;
173  element->insn_address = CPU_PC_GET (cpu);
174  element->kinds.fn_df_write.function = write_function;
175  element->kinds.fn_df_write.regno = regno;
176  element->kinds.fn_df_write.value = value;
177}
178
179void sim_queue_fn_pc_write (
180  SIM_CPU *cpu,
181  void (*write_function)(SIM_CPU *cpu, USI),
182  USI value
183)
184{
185  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
186  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
187  element->kind = CGEN_FN_PC_WRITE;
188  element->insn_address = CPU_PC_GET (cpu);
189  element->kinds.fn_pc_write.function = write_function;
190  element->kinds.fn_pc_write.value = value;
191}
192
193void sim_queue_mem_qi_write (SIM_CPU *cpu, SI address, QI value)
194{
195  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
196  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
197  element->kind = CGEN_MEM_QI_WRITE;
198  element->insn_address = CPU_PC_GET (cpu);
199  element->kinds.mem_qi_write.address = address;
200  element->kinds.mem_qi_write.value   = value;
201}
202
203void sim_queue_mem_hi_write (SIM_CPU *cpu, SI address, HI value)
204{
205  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
206  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
207  element->kind = CGEN_MEM_HI_WRITE;
208  element->insn_address = CPU_PC_GET (cpu);
209  element->kinds.mem_hi_write.address = address;
210  element->kinds.mem_hi_write.value   = value;
211}
212
213void sim_queue_mem_si_write (SIM_CPU *cpu, SI address, SI value)
214{
215  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
216  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
217  element->kind = CGEN_MEM_SI_WRITE;
218  element->insn_address = CPU_PC_GET (cpu);
219  element->kinds.mem_si_write.address = address;
220  element->kinds.mem_si_write.value   = value;
221}
222
223void sim_queue_mem_di_write (SIM_CPU *cpu, SI address, DI value)
224{
225  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
226  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
227  element->kind = CGEN_MEM_DI_WRITE;
228  element->insn_address = CPU_PC_GET (cpu);
229  element->kinds.mem_di_write.address = address;
230  element->kinds.mem_di_write.value   = value;
231}
232
233void sim_queue_mem_df_write (SIM_CPU *cpu, SI address, DF value)
234{
235  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
236  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
237  element->kind = CGEN_MEM_DF_WRITE;
238  element->insn_address = CPU_PC_GET (cpu);
239  element->kinds.mem_df_write.address = address;
240  element->kinds.mem_df_write.value   = value;
241}
242
243void sim_queue_mem_xi_write (SIM_CPU *cpu, SI address, SI *value)
244{
245  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
246  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
247  element->kind = CGEN_MEM_XI_WRITE;
248  element->insn_address = CPU_PC_GET (cpu);
249  element->kinds.mem_xi_write.address = address;
250  element->kinds.mem_xi_write.value[0] = value[0];
251  element->kinds.mem_xi_write.value[1] = value[1];
252  element->kinds.mem_xi_write.value[2] = value[2];
253  element->kinds.mem_xi_write.value[3] = value[3];
254}
255
256void sim_queue_fn_mem_qi_write (
257  SIM_CPU *cpu,
258  void (*write_function)(SIM_CPU *cpu, IADDR, SI, QI),
259  SI address,
260  QI value
261)
262{
263  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
264  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
265  element->kind = CGEN_FN_MEM_QI_WRITE;
266  element->insn_address = CPU_PC_GET (cpu);
267  element->kinds.fn_mem_qi_write.function = write_function;
268  element->kinds.fn_mem_qi_write.address = address;
269  element->kinds.fn_mem_qi_write.value   = value;
270}
271
272void sim_queue_fn_mem_hi_write (
273  SIM_CPU *cpu,
274  void (*write_function)(SIM_CPU *cpu, IADDR, SI, HI),
275  SI address,
276  HI value
277)
278{
279  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
280  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
281  element->kind = CGEN_FN_MEM_HI_WRITE;
282  element->insn_address = CPU_PC_GET (cpu);
283  element->kinds.fn_mem_hi_write.function = write_function;
284  element->kinds.fn_mem_hi_write.address = address;
285  element->kinds.fn_mem_hi_write.value   = value;
286}
287
288void sim_queue_fn_mem_si_write (
289  SIM_CPU *cpu,
290  void (*write_function)(SIM_CPU *cpu, IADDR, SI, SI),
291  SI address,
292  SI value
293)
294{
295  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
296  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
297  element->kind = CGEN_FN_MEM_SI_WRITE;
298  element->insn_address = CPU_PC_GET (cpu);
299  element->kinds.fn_mem_si_write.function = write_function;
300  element->kinds.fn_mem_si_write.address = address;
301  element->kinds.fn_mem_si_write.value   = value;
302}
303
304void sim_queue_fn_mem_di_write (
305  SIM_CPU *cpu,
306  void (*write_function)(SIM_CPU *cpu, IADDR, SI, DI),
307  SI address,
308  DI value
309)
310{
311  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
312  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
313  element->kind = CGEN_FN_MEM_DI_WRITE;
314  element->insn_address = CPU_PC_GET (cpu);
315  element->kinds.fn_mem_di_write.function = write_function;
316  element->kinds.fn_mem_di_write.address = address;
317  element->kinds.fn_mem_di_write.value   = value;
318}
319
320void sim_queue_fn_mem_df_write (
321  SIM_CPU *cpu,
322  void (*write_function)(SIM_CPU *cpu, IADDR, SI, DF),
323  SI address,
324  DF value
325)
326{
327  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
328  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
329  element->kind = CGEN_FN_MEM_DF_WRITE;
330  element->insn_address = CPU_PC_GET (cpu);
331  element->kinds.fn_mem_df_write.function = write_function;
332  element->kinds.fn_mem_df_write.address = address;
333  element->kinds.fn_mem_df_write.value   = value;
334}
335
336void sim_queue_fn_mem_xi_write (
337  SIM_CPU *cpu,
338  void (*write_function)(SIM_CPU *cpu, IADDR, SI, SI *),
339  SI address,
340  SI *value
341)
342{
343  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu);
344  CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q);
345  element->kind = CGEN_FN_MEM_XI_WRITE;
346  element->insn_address = CPU_PC_GET (cpu);
347  element->kinds.fn_mem_xi_write.function = write_function;
348  element->kinds.fn_mem_xi_write.address = address;
349  element->kinds.fn_mem_xi_write.value[0] = value[0];
350  element->kinds.fn_mem_xi_write.value[1] = value[1];
351  element->kinds.fn_mem_xi_write.value[2] = value[2];
352  element->kinds.fn_mem_xi_write.value[3] = value[3];
353}
354
355/* Execute a write stored on the write queue.  */
356void
357cgen_write_queue_element_execute (SIM_CPU *cpu, CGEN_WRITE_QUEUE_ELEMENT *item)
358{
359  IADDR pc;
360  switch (CGEN_WRITE_QUEUE_ELEMENT_KIND (item))
361    {
362    case CGEN_BI_WRITE:
363      *item->kinds.bi_write.target = item->kinds.bi_write.value;
364      break;
365    case CGEN_QI_WRITE:
366      *item->kinds.qi_write.target = item->kinds.qi_write.value;
367      break;
368    case CGEN_SI_WRITE:
369      *item->kinds.si_write.target = item->kinds.si_write.value;
370      break;
371    case CGEN_SF_WRITE:
372      *item->kinds.sf_write.target = item->kinds.sf_write.value;
373      break;
374    case CGEN_PC_WRITE:
375      CPU_PC_SET (cpu, item->kinds.pc_write.value);
376      break;
377    case CGEN_FN_HI_WRITE:
378      item->kinds.fn_hi_write.function (cpu,
379					item->kinds.fn_hi_write.regno,
380					item->kinds.fn_hi_write.value);
381      break;
382    case CGEN_FN_SI_WRITE:
383      item->kinds.fn_si_write.function (cpu,
384					item->kinds.fn_si_write.regno,
385					item->kinds.fn_si_write.value);
386      break;
387    case CGEN_FN_SF_WRITE:
388      item->kinds.fn_sf_write.function (cpu,
389					item->kinds.fn_sf_write.regno,
390					item->kinds.fn_sf_write.value);
391      break;
392    case CGEN_FN_DI_WRITE:
393      item->kinds.fn_di_write.function (cpu,
394					item->kinds.fn_di_write.regno,
395					item->kinds.fn_di_write.value);
396      break;
397    case CGEN_FN_DF_WRITE:
398      item->kinds.fn_df_write.function (cpu,
399					item->kinds.fn_df_write.regno,
400					item->kinds.fn_df_write.value);
401      break;
402    case CGEN_FN_XI_WRITE:
403      item->kinds.fn_xi_write.function (cpu,
404					item->kinds.fn_xi_write.regno,
405					item->kinds.fn_xi_write.value);
406      break;
407    case CGEN_FN_PC_WRITE:
408      item->kinds.fn_pc_write.function (cpu, item->kinds.fn_pc_write.value);
409      break;
410    case CGEN_MEM_QI_WRITE:
411      pc = item->insn_address;
412      SETMEMQI (cpu, pc, item->kinds.mem_qi_write.address,
413		item->kinds.mem_qi_write.value);
414      break;
415    case CGEN_MEM_HI_WRITE:
416      pc = item->insn_address;
417      SETMEMHI (cpu, pc, item->kinds.mem_hi_write.address,
418		item->kinds.mem_hi_write.value);
419      break;
420    case CGEN_MEM_SI_WRITE:
421      pc = item->insn_address;
422      SETMEMSI (cpu, pc, item->kinds.mem_si_write.address,
423		item->kinds.mem_si_write.value);
424      break;
425    case CGEN_MEM_DI_WRITE:
426      pc = item->insn_address;
427      SETMEMDI (cpu, pc, item->kinds.mem_di_write.address,
428		item->kinds.mem_di_write.value);
429      break;
430    case CGEN_MEM_DF_WRITE:
431      pc = item->insn_address;
432      SETMEMDF (cpu, pc, item->kinds.mem_df_write.address,
433		item->kinds.mem_df_write.value);
434      break;
435    case CGEN_MEM_XI_WRITE:
436      pc = item->insn_address;
437      SETMEMSI (cpu, pc, item->kinds.mem_xi_write.address,
438		item->kinds.mem_xi_write.value[0]);
439      SETMEMSI (cpu, pc, item->kinds.mem_xi_write.address + 4,
440		item->kinds.mem_xi_write.value[1]);
441      SETMEMSI (cpu, pc, item->kinds.mem_xi_write.address + 8,
442		item->kinds.mem_xi_write.value[2]);
443      SETMEMSI (cpu, pc, item->kinds.mem_xi_write.address + 12,
444		item->kinds.mem_xi_write.value[3]);
445      break;
446    case CGEN_FN_MEM_QI_WRITE:
447      pc = item->insn_address;
448      item->kinds.fn_mem_qi_write.function (cpu, pc,
449					    item->kinds.fn_mem_qi_write.address,
450					    item->kinds.fn_mem_qi_write.value);
451      break;
452    case CGEN_FN_MEM_HI_WRITE:
453      pc = item->insn_address;
454      item->kinds.fn_mem_hi_write.function (cpu, pc,
455					    item->kinds.fn_mem_hi_write.address,
456					    item->kinds.fn_mem_hi_write.value);
457      break;
458    case CGEN_FN_MEM_SI_WRITE:
459      pc = item->insn_address;
460      item->kinds.fn_mem_si_write.function (cpu, pc,
461					    item->kinds.fn_mem_si_write.address,
462					    item->kinds.fn_mem_si_write.value);
463      break;
464    case CGEN_FN_MEM_DI_WRITE:
465      pc = item->insn_address;
466      item->kinds.fn_mem_di_write.function (cpu, pc,
467					    item->kinds.fn_mem_di_write.address,
468					    item->kinds.fn_mem_di_write.value);
469      break;
470    case CGEN_FN_MEM_DF_WRITE:
471      pc = item->insn_address;
472      item->kinds.fn_mem_df_write.function (cpu, pc,
473					    item->kinds.fn_mem_df_write.address,
474					    item->kinds.fn_mem_df_write.value);
475      break;
476    case CGEN_FN_MEM_XI_WRITE:
477      pc = item->insn_address;
478      item->kinds.fn_mem_xi_write.function (cpu, pc,
479					    item->kinds.fn_mem_xi_write.address,
480					    item->kinds.fn_mem_xi_write.value);
481      break;
482    default:
483      abort ();
484      break; /* FIXME: for now....print message later.  */
485    }
486}
487
488/* Utilities for the write queue.  */
489CGEN_WRITE_QUEUE_ELEMENT *
490cgen_write_queue_overflow (CGEN_WRITE_QUEUE *q)
491{
492  abort (); /* FIXME: for now....print message later.  */
493  return 0;
494}
495