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