fix typo
[deliverable/binutils-gdb.git] / sim / ppc / emul_bugapi.c
CommitLineData
93fac324
MM
1/* This file is part of the program psim.
2
eada1efc 3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
93fac324
MM
4
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 2 of the License, or
8 (at your option) any later version.
9
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.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22#ifndef _EMUL_BUGAPI_C_
23#define _EMUL_BUGAPI_C_
24
25
ad836e02
MM
26/* from PowerPCBug Debugging Package User's Manual, part 2 of 2 and also bug.S - Dale Rahn */
27#define _INCHR 0x000 /* Input character */
28#define _INSTAT 0x001 /* Input serial port status */
29#define _INLN 0x002 /* Input line (pointer / pointer format) */
30#define _READSTR 0x003 /* Input string (pointer / count format) */
31#define _READLN 0x004 /* Input line (pointer / count format) */
32#define _CHKBRK 0x005 /* Check for break */
33#define _DSKRD 0x010 /* Disk read */
34#define _DKSWR 0x011 /* Disk write */
35#define _DSKCFIG 0x012 /* Disk configure */
36#define _DSKFMT 0x014 /* Disk format */
37#define _DSKCTRL 0x015 /* Disk control */
38#define _NETRD 0x018 /* Read from host */
39#define _NETWR 0x019 /* Write to host */
40#define _NETCFIG 0x01a /* Configure network parameters */
41#define _NETOPN 0x01b /* Open file for reading */
42#define _NETFRD 0x01c /* Retreive specified file blocks */
43#define _NETCTRL 0x01d /* Implement special control functions */
44#define _OUTCHR 0x020 /* Output character (pointer / pointer format) */
45#define _OUTSTR 0x021 /* Output string (pointer / pointer format) */
46#define _OUTLN 0x022 /* Output line (pointer / pointer format) */
47#define _WRITE 0x023 /* Output string (pointer / count format) */
48#define _WRITELN 0x024 /* Output line (pointer / count format) */
49#define _WRITDLN 0x025 /* Output line with data (pointer / count format) */
50#define _PCRLF 0x026 /* Output carriage return and line feed */
51#define _ERASLN 0x027 /* Erase line */
52#define _WRITD 0x028 /* Output string with data (pointer / count format) */
53#define _SNDBRK 0x029 /* Send break */
54#define _DELAY 0x043 /* Timer delay */
55#define _RTC_TM 0x050 /* Time initialization for RTC */
56#define _RTC_DT 0x051 /* Date initialization for RTC */
57#define _RTC_DSP 0x052 /* Display RTC time and date */
58#define _RTC_RD 0x053 /* Read the RTC registers */
59#define _REDIR 0x060 /* Redirect I/O of a system call function */
60#define _REDIR_I 0x061 /* Redirect input */
61#define _REDIR_O 0x062 /* Redirect output */
62#define _RETURN 0x063 /* Return to PPCbug */
63#define _BINDEC 0x064 /* Convert binary to binary coded decimal (BCD) */
64#define _CHANGEV 0x067 /* Parse value */
65#define _STRCMP 0x068 /* Compare two strings (pointer / count format) */
66#define _MULU32 0x069 /* Multiply two 32-bit unsigned integers */
67#define _DIVU32 0x06a /* Divide two 32-bit unsigned integers */
68#define _CHK_SUM 0x06b /* Generate checksum */
69#define _BRD_ID 0x070 /* Return pointer to board ID packet */
70#define _ENVIRON 0x071 /* Access boot environment parameters */
71#define _DIAGFCN 0x074 /* Diagnostic function(s) */
72#define _SIOPEPS 0x090 /* Retrieve SCSI pointers */
73#define _IOINQ 0x120 /* Port inquire */
74#define _IOINFORM 0x124 /* Port inform */
75#define _IOCONFIG 0x128 /* Port configure */
76#define _IODELETE 0x12c /* Port delete */
77#define _SYMBOLTA 0x130 /* Attach symbol table */
78#define _SYMBOLDA 0x131 /* Detach symbol table */
79
80struct bug_map {
81 int value;
82 const char *info;
83};
84
85static const struct bug_map bug_mapping[] = {
86 { _INCHR, ".INCHR -- Input character" },
87 { _INSTAT, ".INSTAT -- Input serial port status" },
88 { _INLN, ".INLN -- Input line (pointer / pointer format)" },
89 { _READSTR, ".READSTR -- Input string (pointer / count format)" },
90 { _READLN, ".READLN -- Input line (pointer / count format)" },
91 { _CHKBRK, ".CHKBRK -- Check for break" },
92 { _DSKRD, ".DSKRD -- Disk read" },
93 { _DKSWR, ".DKSWR -- Disk write" },
94 { _DSKCFIG, ".DSKCFIG -- Disk configure" },
95 { _DSKFMT, ".DSKFMT -- Disk format" },
96 { _DSKCTRL, ".DSKCTRL -- Disk control" },
97 { _NETRD, ".NETRD -- Read from host" },
98 { _NETWR, ".NETWR -- Write to host" },
99 { _NETCFIG, ".NETCFIG -- Configure network parameters" },
100 { _NETOPN, ".NETOPN -- Open file for reading" },
101 { _NETFRD, ".NETFRD -- Retreive specified file blocks" },
102 { _NETCTRL, ".NETCTRL -- Implement special control functions" },
103 { _OUTCHR, ".OUTCHR -- Output character" },
104 { _OUTSTR, ".OUTSTR -- Output string (pointer / pointer format)" },
105 { _OUTLN, ".OUTLN -- Output line (pointer / pointer format)" },
106 { _WRITE, ".WRITE -- Output string (pointer / count format)" },
107 { _WRITELN, ".WRITELN -- Output line (pointer / count format)" },
108 { _WRITDLN, ".WRITDLN -- Output line with data (pointer / count format)" },
109 { _PCRLF, ".PCRLF -- Output carriage return and line feed" },
110 { _ERASLN, ".ERASLN -- Erase line" },
111 { _WRITD, ".WRITD -- Output string with data (pointer / count format)" },
112 { _SNDBRK, ".SNDBRK -- Send break" },
113 { _DELAY, ".DELAY -- Timer delay" },
114 { _RTC_TM, ".RTC_TM -- Time initialization for RTC" },
115 { _RTC_DT, ".RTC_DT -- Date initialization for RTC" },
116 { _RTC_DSP, ".RTC_DSP -- Display RTC time and date" },
117 { _RTC_RD, ".RTC_RD -- Read the RTC registers" },
118 { _REDIR, ".REDIR -- Redirect I/O of a system call function" },
119 { _REDIR, ".REDIR -- Redirect input" },
120 { _REDIR, ".REDIR -- Redirect output" },
121 { _RETURN, ".RETURN -- Return to PPCbug" },
122 { _BINDEC, ".BINDEC -- Convert binary to binary coded decimal (BCD)" },
123 { _CHANGEV, ".CHANGEV -- Parse value" },
124 { _STRCMP, ".STRCMP -- Compare two strings (pointer / count format)" },
125 { _MULU32, ".MULU32 -- Multiply two 32-bit unsigned integers" },
126 { _DIVU32, ".DIVU32 -- Divide two 32-bit unsigned integers" },
127 { _CHK_SUM, ".CHK_SUM -- Generate checksum" },
128 { _BRD_ID, ".BRD_ID -- Return pointer to board ID packet" },
129 { _ENVIRON, ".ENVIRON -- Access boot environment parameters" },
130 { _DIAGFCN, ".DIAGFCN -- Diagnostic function(s)" },
131 { _SIOPEPS, ".SIOPEPS -- Retrieve SCSI pointers" },
132 { _IOINQ, ".IOINQ -- Port inquire" },
133 { _IOINFORM, ".IOINFORM -- Port inform" },
134 { _IOCONFIG, ".IOCONFIG -- Port configure" },
135 { _IODELETE, ".IODELETE -- Port delete" },
136 { _SYMBOLTA, ".SYMBOLTA -- Attach symbol table" },
137 { _SYMBOLDA, ".SYMBOLDA -- Detach symbol table" },
138};
979c3c25 139
93fac324
MM
140/* Note: this module is called via a table. There is no benefit in
141 making it inline */
142
143#include "emul_generic.h"
144#include "emul_bugapi.h"
145
93fac324 146
eada1efc
MM
147#ifndef OEA_START_ADDRESS
148#define OEA_START_ADDRESS 0x100000
93fac324
MM
149#endif
150
979c3c25 151
979c3c25 152
eada1efc
MM
153struct _os_emul_data {
154 unsigned_word memory_size;
155 unsigned_word top_of_stack;
156 int interrupt_prefix;
157 unsigned_word interrupt_vector_address;
158 unsigned_word system_call_address;
159 unsigned_word stall_cpu_loop_address;
160 int little_endian;
161 int floating_point_available;
162};
979c3c25
MM
163
164
93fac324
MM
165static os_emul_data *
166emul_bugapi_create(device *root,
167 bfd *image,
168 const char *name)
169{
eada1efc
MM
170 int elf_binary;
171 device *node;
172 os_emul_data *bugapi;
93fac324
MM
173
174 /* check it really is for us */
175 if (name != NULL
979c3c25
MM
176 && strcmp(name, "bugapi") != 0
177 && strcmp(name, "bug") != 0)
93fac324
MM
178 return NULL;
179 if (image != NULL
979c3c25 180 && name == NULL
93fac324
MM
181 && bfd_get_start_address(image) > OEA_START_ADDRESS)
182 return NULL;
183
eada1efc
MM
184 bugapi = ZALLOC(os_emul_data);
185
186 /* some defaults */
187 elf_binary = image->xvec->flavour == bfd_target_elf_flavour;
188
189 /* options */
190 emul_add_tree_options(root, image, "bug", "oea",
191 1 /*oea-interrupt-prefix*/);
192
193 /* add some real hardware */
194 emul_add_tree_hardware(root);
195
196 bugapi->memory_size
197 = device_find_integer_property(root, "/openprom/options/oea-memory-size");
198 bugapi->interrupt_prefix =
199 device_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
200 bugapi->interrupt_vector_address = (bugapi->interrupt_prefix
201 ? MASK(0, 43)
202 : 0);
203 bugapi->system_call_address = (bugapi->interrupt_vector_address + 0x00c00);
204 bugapi->stall_cpu_loop_address = (bugapi->system_call_address + 0x000f0);
205 bugapi->top_of_stack = bugapi->memory_size - 0x1000;
206 bugapi->little_endian
207 = device_find_boolean_property(root, "/options/little-endian?");
208 bugapi->floating_point_available
209 = device_find_boolean_property(root, "/openprom/options/floating-point?");
210
211 /* initialization */
212 device_tree_add_parsed(root, "/openprom/init/register/0.pc 0x%lx",
213 (unsigned long)bfd_get_start_address(image));
214 device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx",
215 (unsigned long)bugapi->stall_cpu_loop_address);
216 device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx",
217 (unsigned long)(bugapi->top_of_stack - 16));
218 device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x",
219 (msr_recoverable_interrupt
220 | (bugapi->little_endian
221 ? (msr_little_endian_mode
222 | msr_interrupt_little_endian_mode)
223 : 0)
224 | (bugapi->floating_point_available
225 ? msr_floating_point_available
226 : 0)
227 | (bugapi->interrupt_prefix
228 ? msr_interrupt_prefix
229 : 0)
230 ));
231
232 /* patch the system call instruction to call this emulation and then
233 do an rfi */
234 node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
235 (long)bugapi->system_call_address);
236 device_tree_add_parsed(node, "./real-address 0x%lx",
237 (long)bugapi->system_call_address);
238 device_tree_add_parsed(node, "./data 0x%x",
239 emul_call_instruction);
240 node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
241 (long)(bugapi->system_call_address + 4));
242 device_tree_add_parsed(node, "./real-address 0x%lx",
243 (long)(bugapi->system_call_address + 4));
244 device_tree_add_parsed(node, "./data 0x%x",
245 emul_rfi_instruction);
246
247 /* patch the end of the system call instruction so that it contains
248 a loop to self instruction and point all the cpu's at this */
249 node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
250 (unsigned long)bugapi->stall_cpu_loop_address);
251 device_tree_add_parsed(node, "./real-address 0x%lx",
252 (unsigned long)bugapi->stall_cpu_loop_address);
253 device_tree_add_parsed(node, "./data 0x%lx",
254 (unsigned long)emul_loop_instruction);
93fac324 255
eada1efc
MM
256 device_tree_add_parsed(root, "/openprom/init/stack/stack-type %s",
257 elf_binary ? "elf" : "aix");
93fac324 258
eada1efc
MM
259 device_tree_add_parsed(root, "/openprom/init/load-binary/file-name \"%s",
260 bfd_get_filename(image));
261
262 return bugapi;
93fac324
MM
263}
264
265static void
266emul_bugapi_init(os_emul_data *emul_data,
267 int nr_cpus)
268{
269 /* nothing happens here */
270}
271
ad836e02
MM
272static const char *
273emul_bugapi_instruction_name(int call_id)
274{
275 static char buffer[40];
276 int i;
277
278 for (i = 0; i < sizeof (bug_mapping) / sizeof (bug_mapping[0]); i++)
279 {
280 if (bug_mapping[i].value == call_id)
281 return bug_mapping[i].info;
282 }
283
284 (void) sprintf (buffer, "Unknown bug call 0x%x", call_id);
285 return buffer;
286}
287
288static void
289emul_bugapi_do_write(cpu *processor,
290 unsigned_word cia,
291 unsigned_word buf,
292 int nbytes,
293 const char *suffix)
294{
295 void *scratch_buffer = NULL;
296 char *p;
297 int nr_moved;
298
299 /* get a tempoary bufer */
300 if (nbytes > 0)
301 {
302 scratch_buffer = zalloc(nbytes);
303
304 /* copy in */
305 nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
306 scratch_buffer,
307 buf,
308 nbytes);
309 if (nr_moved != nbytes) {
310 /* FIXME - should handle better */
311 error("system_call()write copy failed (nr_moved=%d != nbytes=%d)\n",
312 nr_moved, nbytes);
313 }
314
315 /* write */
316 for (p = (char *)scratch_buffer; nbytes-- > 0; p++)
317 printf_filtered("%c", *p);
318
319 zfree(scratch_buffer);
320 }
321
322 if (suffix)
323 printf_filtered("%s", suffix);
324}
325
93fac324
MM
326static int
327emul_bugapi_instruction_call(cpu *processor,
328 unsigned_word cia,
329 unsigned_word ra,
330 os_emul_data *emul_data)
331{
979c3c25 332 const int call_id = cpu_registers(processor)->gpr[10];
ad836e02
MM
333 const char *my_prefix = "bugapi";
334
335 ITRACE (trace_os_emul,(" 0x%x %s, r3 = 0x%lx, r4 = 0x%lx\n",
336 call_id, emul_bugapi_instruction_name (call_id),
337 (long)cpu_registers(processor)->gpr[3],
338 (long)cpu_registers(processor)->gpr[4]));;
339
979c3c25 340 /* check that this isn't an invalid instruction */
eada1efc 341 if (cia != emul_data->system_call_address)
979c3c25
MM
342 return 0;
343 switch (call_id) {
ad836e02
MM
344 default:
345 error("emul-bugapi: unimplemented bugapi %s from address 0x%lx\n",
346 emul_bugapi_instruction_name (call_id), SRR0);
347 break;
348 /* output a character, r3 = character */
979c3c25 349 case _OUTCHR:
52edddb9 350 printf_filtered("%c", (char)cpu_registers(processor)->gpr[3]);
979c3c25 351 break;
ad836e02
MM
352 /* output a string, r3 = ptr to 1st byte, r4 = ptr to last byte+1 */
353 case _OUTSTR:
354 emul_bugapi_do_write(processor, cia,
355 cpu_registers(processor)->gpr[3],
356 cpu_registers(processor)->gpr[4] - cpu_registers(processor)->gpr[3],
357 (const char *)0);
358 break;
359 /* output a string followed by \r\n, r3 = ptr to 1st byte, r4 = ptr to last byte+1 */
979c3c25 360 case _OUTLN:
ad836e02
MM
361
362 emul_bugapi_do_write(processor, cia,
363 cpu_registers(processor)->gpr[3],
364 cpu_registers(processor)->gpr[4] - cpu_registers(processor)->gpr[3],
365 "\n");
366 break;
367 /* output a \r\n */
368 case _PCRLF:
979c3c25
MM
369 printf_filtered("\n");
370 break;
ad836e02 371 /* return to ppcbug monitor */
979c3c25
MM
372 case _RETURN:
373 cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
374 break;
979c3c25 375 }
93fac324 376 return 1;
979c3c25
MM
377 /* the instruction following this one is a RFI. Thus by just
378 continuing the return from system call is performed */
93fac324
MM
379}
380
381const os_emul emul_bugapi = {
382 "bugapi",
383 emul_bugapi_create,
384 emul_bugapi_init,
385 0, /*system_call*/
386 emul_bugapi_instruction_call,
387 0 /*data*/
388};
389
390#endif
This page took 0.044363 seconds and 4 git commands to generate.