emul_generic.c revision 1.1.1.4 1 1.1 christos /* This file is part of the program psim.
2 1.1 christos
3 1.1 christos Copyright (C) 1994-1997, Andrew Cagney <cagney (at) highland.com.au>
4 1.1 christos
5 1.1 christos This program is free software; you can redistribute it and/or modify
6 1.1 christos it under the terms of the GNU General Public License as published by
7 1.1.1.2 christos the Free Software Foundation; either version 3 of the License, or
8 1.1 christos (at your option) any later version.
9 1.1 christos
10 1.1 christos This program is distributed in the hope that it will be useful,
11 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
12 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 1.1 christos GNU General Public License for more details.
14 1.1 christos
15 1.1 christos You should have received a copy of the GNU General Public License
16 1.1.1.2 christos along with this program; if not, see <http://www.gnu.org/licenses/>.
17 1.1 christos
18 1.1 christos */
19 1.1 christos
20 1.1 christos
21 1.1 christos #ifndef _EMUL_GENERIC_C_
22 1.1 christos #define _EMUL_GENERIC_C_
23 1.1 christos
24 1.1 christos #include "emul_generic.h"
25 1.1 christos
26 1.1 christos #ifndef STATIC_INLINE_EMUL_GENERIC
27 1.1 christos #define STATIC_INLINE_EMUL_GENERIC STATIC_INLINE
28 1.1 christos #endif
29 1.1 christos
30 1.1 christos
31 1.1 christos STATIC_INLINE_EMUL_GENERIC void
32 1.1 christos emul_syscall_enter(emul_syscall *emul,
33 1.1 christos int call,
34 1.1 christos int arg0,
35 1.1 christos cpu *processor,
36 1.1 christos unsigned_word cia)
37 1.1 christos {
38 1.1 christos printf_filtered("%d:0x%lx:%s(",
39 1.1 christos cpu_nr(processor) + 1,
40 1.1 christos (long)cia,
41 1.1 christos emul->syscall_descriptor[call].name);
42 1.1 christos }
43 1.1 christos
44 1.1 christos
45 1.1 christos STATIC_INLINE_EMUL_GENERIC void
46 1.1 christos emul_syscall_exit(emul_syscall *emul,
47 1.1 christos int call,
48 1.1 christos int arg0,
49 1.1 christos cpu *processor,
50 1.1 christos unsigned_word cia)
51 1.1 christos {
52 1.1 christos int status = cpu_registers(processor)->gpr[3];
53 1.1 christos int error = cpu_registers(processor)->gpr[0];
54 1.1 christos printf_filtered(")=%d", status);
55 1.1 christos if (error > 0 && error < emul->nr_error_names)
56 1.1 christos printf_filtered("[%s]", emul->error_names[error]);
57 1.1 christos printf_filtered("\n");
58 1.1 christos }
59 1.1 christos
60 1.1 christos
61 1.1.1.4 christos INLINE_EMUL_GENERIC uint64_t
62 1.1 christos emul_read_gpr64(cpu *processor,
63 1.1 christos int g)
64 1.1 christos {
65 1.1.1.4 christos uint32_t hi;
66 1.1.1.4 christos uint32_t lo;
67 1.1.1.4 christos if (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) {
68 1.1 christos hi = cpu_registers(processor)->gpr[g];
69 1.1 christos lo = cpu_registers(processor)->gpr[g+1];
70 1.1 christos }
71 1.1 christos else {
72 1.1 christos lo = cpu_registers(processor)->gpr[g];
73 1.1 christos hi = cpu_registers(processor)->gpr[g+1];
74 1.1 christos }
75 1.1 christos return (INSERTED64(hi, 0, 31) | INSERTED64(lo, 32, 63));
76 1.1 christos }
77 1.1 christos
78 1.1 christos
79 1.1 christos INLINE_EMUL_GENERIC void
80 1.1 christos emul_write_gpr64(cpu *processor,
81 1.1 christos int g,
82 1.1.1.4 christos uint64_t val)
83 1.1 christos {
84 1.1.1.4 christos uint32_t hi = EXTRACTED64(val, 0, 31);
85 1.1.1.4 christos uint32_t lo = EXTRACTED64(val, 32, 63);
86 1.1.1.4 christos if (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) {
87 1.1 christos cpu_registers(processor)->gpr[g] = hi;
88 1.1 christos cpu_registers(processor)->gpr[g+1] = lo;
89 1.1 christos }
90 1.1 christos else {
91 1.1 christos cpu_registers(processor)->gpr[g] = lo;
92 1.1 christos cpu_registers(processor)->gpr[g+1] = hi;
93 1.1 christos }
94 1.1 christos }
95 1.1 christos
96 1.1 christos
97 1.1 christos INLINE_EMUL_GENERIC char *
98 1.1 christos emul_read_string(char *dest,
99 1.1 christos unsigned_word addr,
100 1.1 christos unsigned nr_bytes,
101 1.1 christos cpu *processor,
102 1.1 christos unsigned_word cia)
103 1.1 christos {
104 1.1 christos unsigned nr_moved = 0;
105 1.1 christos if (addr == 0)
106 1.1 christos return NULL;
107 1.1 christos while (1) {
108 1.1 christos dest[nr_moved] = vm_data_map_read_1(cpu_data_map(processor),
109 1.1 christos addr + nr_moved,
110 1.1 christos processor, cia);
111 1.1 christos if (dest[nr_moved] == '\0' || nr_moved >= nr_bytes)
112 1.1 christos break;
113 1.1 christos nr_moved++;
114 1.1 christos }
115 1.1 christos dest[nr_moved] = '\0';
116 1.1 christos return dest;
117 1.1 christos }
118 1.1 christos
119 1.1 christos
120 1.1 christos INLINE_EMUL_GENERIC void
121 1.1 christos emul_write_status(cpu *processor,
122 1.1 christos int status,
123 1.1.1.4 christos int err)
124 1.1 christos {
125 1.1.1.4 christos if (status == -1 && err != 0) {
126 1.1.1.4 christos cpu_registers(processor)->gpr[3] = err;
127 1.1 christos CR_SET(0, cr_i_summary_overflow);
128 1.1 christos }
129 1.1 christos else {
130 1.1 christos cpu_registers(processor)->gpr[3] = status;
131 1.1 christos CR_SET(0, 0);
132 1.1 christos }
133 1.1 christos }
134 1.1 christos
135 1.1 christos
136 1.1 christos INLINE_EMUL_GENERIC void
137 1.1 christos emul_write2_status(cpu *processor,
138 1.1 christos int status1,
139 1.1 christos int status2,
140 1.1.1.4 christos int err)
141 1.1 christos {
142 1.1.1.4 christos if (status1 == -1 && err != 0) {
143 1.1.1.4 christos cpu_registers(processor)->gpr[3] = err;
144 1.1 christos CR_SET(0, cr_i_summary_overflow);
145 1.1 christos }
146 1.1 christos else {
147 1.1 christos cpu_registers(processor)->gpr[3] = status1;
148 1.1 christos cpu_registers(processor)->gpr[4] = status2;
149 1.1 christos CR_SET(0, 0);
150 1.1 christos }
151 1.1 christos }
152 1.1 christos
153 1.1 christos
154 1.1 christos INLINE_EMUL_GENERIC unsigned_word
155 1.1 christos emul_read_word(unsigned_word addr,
156 1.1 christos cpu *processor,
157 1.1 christos unsigned_word cia)
158 1.1 christos {
159 1.1 christos return vm_data_map_read_word(cpu_data_map(processor),
160 1.1 christos addr,
161 1.1 christos processor, cia);
162 1.1 christos }
163 1.1 christos
164 1.1 christos
165 1.1 christos INLINE_EMUL_GENERIC void
166 1.1 christos emul_write_word(unsigned_word addr,
167 1.1 christos unsigned_word buf,
168 1.1 christos cpu *processor,
169 1.1 christos unsigned_word cia)
170 1.1 christos {
171 1.1 christos vm_data_map_write_word(cpu_data_map(processor),
172 1.1 christos addr,
173 1.1 christos buf,
174 1.1 christos processor, cia);
175 1.1 christos }
176 1.1 christos
177 1.1 christos
178 1.1 christos INLINE_EMUL_GENERIC void
179 1.1 christos emul_write_buffer(const void *source,
180 1.1 christos unsigned_word addr,
181 1.1 christos unsigned nr_bytes,
182 1.1 christos cpu *processor,
183 1.1 christos unsigned_word cia)
184 1.1 christos {
185 1.1 christos int nr_moved;
186 1.1 christos for (nr_moved = 0; nr_moved < nr_bytes; nr_moved++) {
187 1.1 christos vm_data_map_write_1(cpu_data_map(processor),
188 1.1 christos addr + nr_moved,
189 1.1 christos ((const char*)source)[nr_moved],
190 1.1 christos processor, cia);
191 1.1 christos }
192 1.1 christos }
193 1.1 christos
194 1.1 christos
195 1.1 christos INLINE_EMUL_GENERIC void
196 1.1 christos emul_read_buffer(void *dest,
197 1.1 christos unsigned_word addr,
198 1.1 christos unsigned nr_bytes,
199 1.1 christos cpu *processor,
200 1.1 christos unsigned_word cia)
201 1.1 christos {
202 1.1 christos int nr_moved;
203 1.1 christos for (nr_moved = 0; nr_moved < nr_bytes; nr_moved++) {
204 1.1 christos ((char*)dest)[nr_moved] = vm_data_map_read_1(cpu_data_map(processor),
205 1.1 christos addr + nr_moved,
206 1.1 christos processor, cia);
207 1.1 christos }
208 1.1 christos }
209 1.1 christos
210 1.1 christos
211 1.1 christos INLINE_EMUL_GENERIC void
212 1.1 christos emul_do_system_call(os_emul_data *emul_data,
213 1.1 christos emul_syscall *emul,
214 1.1 christos unsigned call,
215 1.1 christos const int arg0,
216 1.1 christos cpu *processor,
217 1.1 christos unsigned_word cia)
218 1.1 christos {
219 1.1 christos emul_syscall_handler *handler = NULL;
220 1.1 christos if (call >= emul->nr_system_calls)
221 1.1 christos error("do_call() os_emul call %d out-of-range\n", call);
222 1.1 christos
223 1.1 christos handler = emul->syscall_descriptor[call].handler;
224 1.1 christos if (handler == NULL) {
225 1.1 christos if (emul->syscall_descriptor[call].name) {
226 1.1 christos error("do_call() unimplemented call %s\n", emul->syscall_descriptor[call].name);
227 1.1 christos } else {
228 1.1 christos error("do_call() unimplemented call %d\n", call);
229 1.1 christos }
230 1.1 christos }
231 1.1 christos
232 1.1 christos if (WITH_TRACE && ppc_trace[trace_os_emul])
233 1.1 christos emul_syscall_enter(emul, call, arg0, processor, cia);
234 1.1 christos
235 1.1 christos cpu_registers(processor)->gpr[0] = 0; /* default success */
236 1.1 christos handler(emul_data, call, arg0, processor, cia);
237 1.1 christos
238 1.1 christos if (WITH_TRACE && ppc_trace[trace_os_emul])
239 1.1 christos emul_syscall_exit(emul, call, arg0, processor, cia);
240 1.1 christos }
241 1.1 christos
242 1.1 christos
243 1.1 christos /* default size for the first bank of memory */
244 1.1 christos
245 1.1 christos #ifndef OEA_MEMORY_SIZE
246 1.1 christos #define OEA_MEMORY_SIZE 0x100000
247 1.1 christos #endif
248 1.1 christos
249 1.1 christos
250 1.1 christos /* Add options to the device tree */
251 1.1 christos
252 1.1 christos INLINE_EMUL_GENERIC void
253 1.1 christos emul_add_tree_options(device *tree,
254 1.1 christos bfd *image,
255 1.1 christos const char *emul,
256 1.1 christos const char *env,
257 1.1 christos int oea_interrupt_prefix)
258 1.1 christos {
259 1.1 christos int little_endian = 0;
260 1.1 christos
261 1.1 christos /* sort out little endian */
262 1.1 christos if (tree_find_property(tree, "/options/little-endian?"))
263 1.1 christos little_endian = tree_find_boolean_property(tree, "/options/little-endian?");
264 1.1 christos else {
265 1.1 christos little_endian = (image != NULL && bfd_little_endian(image));
266 1.1 christos tree_parse(tree, "/options/little-endian? %s",
267 1.1 christos little_endian ? "true" : "false");
268 1.1 christos }
269 1.1 christos
270 1.1 christos /* misc other stuff */
271 1.1 christos tree_parse(tree, "/openprom/options/oea-memory-size 0x%x",
272 1.1 christos OEA_MEMORY_SIZE);
273 1.1 christos tree_parse(tree, "/openprom/options/oea-interrupt-prefix %d",
274 1.1 christos oea_interrupt_prefix);
275 1.1 christos tree_parse(tree, "/openprom/options/smp 1");
276 1.1 christos tree_parse(tree, "/openprom/options/env %s", env);
277 1.1 christos tree_parse(tree, "/openprom/options/os-emul %s", emul);
278 1.1 christos tree_parse(tree, "/openprom/options/strict-alignment? %s",
279 1.1 christos (WITH_ALIGNMENT == STRICT_ALIGNMENT)
280 1.1 christos ? "true" : "false");
281 1.1 christos tree_parse(tree, "/openprom/options/floating-point? %s",
282 1.1 christos WITH_FLOATING_POINT ? "true" : "false");
283 1.1 christos tree_parse(tree, "/openprom/options/use-stdio? %s",
284 1.1 christos ((WITH_STDIO == DO_USE_STDIO
285 1.1 christos || WITH_STDIO == 0)
286 1.1 christos ? "true" : "false"));
287 1.1 christos tree_parse(tree, "/openprom/options/model \"%s",
288 1.1 christos model_name[WITH_DEFAULT_MODEL]);
289 1.1 christos tree_parse(tree, "/openprom/options/model-issue %d",
290 1.1 christos MODEL_ISSUE_IGNORE);
291 1.1 christos
292 1.1 christos /* useful options */
293 1.1 christos }
294 1.1 christos
295 1.1 christos INLINE_EMUL_GENERIC void
296 1.1 christos emul_add_tree_hardware(device *root)
297 1.1 christos {
298 1.1 christos int i;
299 1.1 christos int nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
300 1.1 christos
301 1.1 christos /* sanity check the number of processors */
302 1.1 christos if (nr_cpus > MAX_NR_PROCESSORS)
303 1.1 christos error("Specified number of processors (%d) exceeds the number configured (%d).\n",
304 1.1 christos nr_cpus, MAX_NR_PROCESSORS);
305 1.1 christos
306 1.1 christos /* set the number of address cells (1 or 2) */
307 1.1 christos tree_parse(root, "#address-cells %d", WITH_TARGET_WORD_BITSIZE / 32);
308 1.1 christos
309 1.1 christos /* add some memory */
310 1.1 christos if (tree_find_device(root, "/memory") == NULL) {
311 1.1 christos unsigned_word memory_size =
312 1.1 christos tree_find_integer_property(root, "/openprom/options/oea-memory-size");
313 1.1 christos const unsigned_word avail_start = 0x3000;
314 1.1 christos tree_parse(root, "/memory@0/reg 0x0 0x%lx",
315 1.1 christos (unsigned long)memory_size);
316 1.1 christos /* reserve the first 0x3000 for the PowerPC interrupt table */
317 1.1 christos tree_parse(root, "/memory@0/available 0x%lx 0x%lx",
318 1.1 christos (unsigned long)avail_start,
319 1.1 christos (unsigned long)memory_size - avail_start);
320 1.1 christos }
321 1.1 christos
322 1.1 christos /* our processors */
323 1.1 christos for (i = 0; i < nr_cpus; i++) {
324 1.1 christos tree_parse(root, "/cpus/cpu@%d/cpu-nr %d", i, i);
325 1.1 christos }
326 1.1 christos
327 1.1 christos /* the debugging pal - hide it in the openprom and don't attach it
328 1.1 christos to any bus */
329 1.1 christos tree_parse(root, "/openprom/pal");
330 1.1 christos
331 1.1 christos /* chosen etc */
332 1.1 christos tree_parse(root, "/chosen/stdin */openprom/pal");
333 1.1 christos tree_parse(root, "/chosen/stdout !/chosen/stdin");
334 1.1 christos tree_parse(root, "/chosen/memory */memory");
335 1.1 christos }
336 1.1 christos
337 1.1 christos #endif /* _EMUL_GENERIC_C_ */
338