1 /* This file is part of the program psim.
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #ifndef _EMUL_GENERIC_C_
22 #define _EMUL_GENERIC_C_
24 #include "emul_generic.h"
26 #ifndef STATIC_INLINE_EMUL_GENERIC
27 #define STATIC_INLINE_EMUL_GENERIC STATIC_INLINE
31 STATIC_INLINE_EMUL_GENERIC
void
32 emul_syscall_enter(emul_syscall
*emul
,
38 printf_filtered("%d:0x%lx:%s(",
39 cpu_nr(processor
) + 1,
41 emul
->syscall_descriptor
[call
].name
);
45 STATIC_INLINE_EMUL_GENERIC
void
46 emul_syscall_exit(emul_syscall
*emul
,
52 int status
= cpu_registers(processor
)->gpr
[3];
53 int error
= cpu_registers(processor
)->gpr
[0];
54 printf_filtered(")=%d", status
);
55 if (error
> 0 && error
< emul
->nr_error_names
)
56 printf_filtered("[%s]", emul
->error_names
[error
]);
57 printf_filtered("\n");
61 INLINE_EMUL_GENERIC unsigned64
62 emul_read_gpr64(cpu
*processor
,
67 if (CURRENT_TARGET_BYTE_ORDER
== BIG_ENDIAN
) {
68 hi
= cpu_registers(processor
)->gpr
[g
];
69 lo
= cpu_registers(processor
)->gpr
[g
+1];
72 lo
= cpu_registers(processor
)->gpr
[g
];
73 hi
= cpu_registers(processor
)->gpr
[g
+1];
75 return (INSERTED64(hi
, 0, 31) | INSERTED64(lo
, 32, 63));
79 INLINE_EMUL_GENERIC
void
80 emul_write_gpr64(cpu
*processor
,
84 unsigned32 hi
= EXTRACTED64(val
, 0, 31);
85 unsigned32 lo
= EXTRACTED64(val
, 32, 63);
86 if (CURRENT_TARGET_BYTE_ORDER
== BIG_ENDIAN
) {
87 cpu_registers(processor
)->gpr
[g
] = hi
;
88 cpu_registers(processor
)->gpr
[g
+1] = lo
;
91 cpu_registers(processor
)->gpr
[g
] = lo
;
92 cpu_registers(processor
)->gpr
[g
+1] = hi
;
97 INLINE_EMUL_GENERIC
char *
98 emul_read_string(char *dest
,
104 unsigned nr_moved
= 0;
108 dest
[nr_moved
] = vm_data_map_read_1(cpu_data_map(processor
),
111 if (dest
[nr_moved
] == '\0' || nr_moved
>= nr_bytes
)
115 dest
[nr_moved
] = '\0';
120 INLINE_EMUL_GENERIC
void
121 emul_write_status(cpu
*processor
,
125 if (status
== -1 && errno
!= 0) {
126 cpu_registers(processor
)->gpr
[3] = errno
;
127 CR_SET(0, cr_i_summary_overflow
);
130 cpu_registers(processor
)->gpr
[3] = status
;
136 INLINE_EMUL_GENERIC
void
137 emul_write2_status(cpu
*processor
,
142 if (status1
== -1 && errno
!= 0) {
143 cpu_registers(processor
)->gpr
[3] = errno
;
144 CR_SET(0, cr_i_summary_overflow
);
147 cpu_registers(processor
)->gpr
[3] = status1
;
148 cpu_registers(processor
)->gpr
[4] = status2
;
154 INLINE_EMUL_GENERIC unsigned_word
155 emul_read_word(unsigned_word addr
,
159 return vm_data_map_read_word(cpu_data_map(processor
),
165 INLINE_EMUL_GENERIC
void
166 emul_write_word(unsigned_word addr
,
171 vm_data_map_write_word(cpu_data_map(processor
),
178 INLINE_EMUL_GENERIC
void
179 emul_write_buffer(const void *source
,
186 for (nr_moved
= 0; nr_moved
< nr_bytes
; nr_moved
++) {
187 vm_data_map_write_1(cpu_data_map(processor
),
189 ((const char*)source
)[nr_moved
],
195 INLINE_EMUL_GENERIC
void
196 emul_read_buffer(void *dest
,
203 for (nr_moved
= 0; nr_moved
< nr_bytes
; nr_moved
++) {
204 ((char*)dest
)[nr_moved
] = vm_data_map_read_1(cpu_data_map(processor
),
211 INLINE_EMUL_GENERIC
void
212 emul_do_system_call(os_emul_data
*emul_data
,
219 emul_syscall_handler
*handler
= NULL
;
220 if (call
>= emul
->nr_system_calls
)
221 error("do_call() os_emul call %d out-of-range\n", call
);
223 handler
= emul
->syscall_descriptor
[call
].handler
;
224 if (handler
== NULL
) {
225 if (emul
->syscall_descriptor
[call
].name
) {
226 error("do_call() unimplemented call %s\n", emul
->syscall_descriptor
[call
].name
);
228 error("do_call() unimplemented call %d\n", call
);
232 if (WITH_TRACE
&& ppc_trace
[trace_os_emul
])
233 emul_syscall_enter(emul
, call
, arg0
, processor
, cia
);
235 cpu_registers(processor
)->gpr
[0] = 0; /* default success */
236 handler(emul_data
, call
, arg0
, processor
, cia
);
238 if (WITH_TRACE
&& ppc_trace
[trace_os_emul
])
239 emul_syscall_exit(emul
, call
, arg0
, processor
, cia
);
243 /* default size for the first bank of memory */
245 #ifndef OEA_MEMORY_SIZE
246 #define OEA_MEMORY_SIZE 0x100000
250 /* Add options to the device tree */
252 INLINE_EMUL_GENERIC
void
253 emul_add_tree_options(device
*tree
,
257 int oea_interrupt_prefix
)
259 int little_endian
= 0;
261 /* sort out little endian */
262 if (tree_find_property(tree
, "/options/little-endian?"))
263 little_endian
= tree_find_boolean_property(tree
, "/options/little-endian?");
265 little_endian
= (image
!= NULL
&& bfd_little_endian(image
));
266 tree_parse(tree
, "/options/little-endian? %s",
267 little_endian
? "true" : "false");
270 /* misc other stuff */
271 tree_parse(tree
, "/openprom/options/oea-memory-size 0x%x",
273 tree_parse(tree
, "/openprom/options/oea-interrupt-prefix %d",
274 oea_interrupt_prefix
);
275 tree_parse(tree
, "/openprom/options/smp 1");
276 tree_parse(tree
, "/openprom/options/env %s", env
);
277 tree_parse(tree
, "/openprom/options/os-emul %s", emul
);
278 tree_parse(tree
, "/openprom/options/strict-alignment? %s",
279 (WITH_ALIGNMENT
== STRICT_ALIGNMENT
)
281 tree_parse(tree
, "/openprom/options/floating-point? %s",
282 WITH_FLOATING_POINT
? "true" : "false");
283 tree_parse(tree
, "/openprom/options/use-stdio? %s",
284 ((WITH_STDIO
== DO_USE_STDIO
286 ? "true" : "false"));
287 tree_parse(tree
, "/openprom/options/model \"%s",
288 model_name
[WITH_DEFAULT_MODEL
]);
289 tree_parse(tree
, "/openprom/options/model-issue %d",
295 INLINE_EMUL_GENERIC
void
296 emul_add_tree_hardware(device
*root
)
299 int nr_cpus
= tree_find_integer_property(root
, "/openprom/options/smp");
301 /* sanity check the number of processors */
302 if (nr_cpus
> MAX_NR_PROCESSORS
)
303 error("Specified number of processors (%d) exceeds the number configured (%d).\n",
304 nr_cpus
, MAX_NR_PROCESSORS
);
306 /* set the number of address cells (1 or 2) */
307 tree_parse(root
, "#address-cells %d", WITH_TARGET_WORD_BITSIZE
/ 32);
309 /* add some memory */
310 if (tree_find_device(root
, "/memory") == NULL
) {
311 unsigned_word memory_size
=
312 tree_find_integer_property(root
, "/openprom/options/oea-memory-size");
313 const unsigned_word avail_start
= 0x3000;
314 tree_parse(root
, "/memory@0/reg 0x0 0x%lx",
315 (unsigned long)memory_size
);
316 /* reserve the first 0x3000 for the PowerPC interrupt table */
317 tree_parse(root
, "/memory@0/available 0x%lx 0x%lx",
318 (unsigned long)avail_start
,
319 (unsigned long)memory_size
- avail_start
);
323 for (i
= 0; i
< nr_cpus
; i
++) {
324 tree_parse(root
, "/cpus/cpu@%d/cpu-nr %d", i
, i
);
327 /* the debugging pal - hide it in the openprom and don't attach it
329 tree_parse(root
, "/openprom/pal");
332 tree_parse(root
, "/chosen/stdin */openprom/pal");
333 tree_parse(root
, "/chosen/stdout !/chosen/stdin");
334 tree_parse(root
, "/chosen/memory */memory");
337 #endif /* _EMUL_GENERIC_C_ */