binutils-gdb/sim/ppc/emul_bugapi.c

235 lines
6.2 KiB
C

/* This file is part of the program psim.
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _EMUL_BUGAPI_C_
#define _EMUL_BUGAPI_C_
/* from bug.S - Dale Rahn */
#define _INCHR 0x00
#define _INSTAT 0x01
#define _INLN 0x02
#define _READSTR 0x03
#define _READLN 0x04
#define _OUTCHR 0x20
#define _OUTSTR 0x21
#define _OUTLN 0x22
#define _DSKRD 0x10
#define _DSKWR 0x11
#define _DSKCFIG 0x12
#define _DSKFMT 0x14
#define _DSKCTRL 0x15
#define _WRITE 0x23
#define _WRITELN 0x24
#define _DELAY 0x43
#define _RTC_RD 0x53
#define _RETURN 0x63
#define _BRD_ID 0x70
/* Note: this module is called via a table. There is no benefit in
making it inline */
#include "emul_generic.h"
#include "emul_bugapi.h"
/* Any starting address less than this is assumed to be an OEA program
rather than VEA. */
#ifndef OEA_START_ADDRESS
#define OEA_START_ADDRESS 0x4000
#endif
#ifndef OEA_MEMORY_SIZE
#define OEA_MEMORY_SIZE 0x100000
#endif
/* All but CPU 0 are put into an infinate loop, this loop instruction
is stored at the address below */
#ifndef OEA_STALL_CPU_LOOP_ADDRESS
#define OEA_STALL_CPU_LOOP_ADDRESS 0x00c10
#endif
/* At initiallization, the system call exception branches to the BUG
emulation code */
#ifndef OEA_SYSTEM_CALL_ADDRESS
#define OEA_SYSTEM_CALL_ADDRESS 0x00c00
#endif
static os_emul_data *
emul_bugapi_create(device *root,
bfd *image,
const char *name)
{
/* check it really is for us */
if (name != NULL
&& strcmp(name, "bugapi") != 0
&& strcmp(name, "bug") != 0)
return NULL;
if (image != NULL
&& name == NULL
&& bfd_get_start_address(image) > OEA_START_ADDRESS)
return NULL;
{
const memory_size = OEA_MEMORY_SIZE;
const elf_binary = (image != NULL
&& image->xvec->flavour == bfd_target_elf_flavour);
#ifdef bfd_little_endian /* new bfd */
const little_endian = (image != NULL && bfd_little_endian(image));
#else
const little_endian = (image != NULL &&
!image->xvec->byteorder_big_p);
#endif
{ /* options */
device *options = device_tree_add_found(root, "/", "options");
device_add_integer_property(options,
"smp",
MAX_NR_PROCESSORS);
device_add_boolean_property(options,
"little-endian?",
little_endian);
device_add_string_property(options,
"env",
"operating");
device_add_boolean_property(options,
"strict-alignment?",
(WITH_ALIGNMENT == STRICT_ALIGNMENT
|| little_endian));
device_add_boolean_property(options,
"floating-point?",
WITH_FLOATING_POINT);
device_add_string_property(options,
"os-emul",
"bugapi");
}
/* hardware */
device_tree_add_found_uw_u_u(root, "/", "memory",
0, memory_size, access_read_write_exec);
device_tree_add_found(root, "/", "iobus@0x400000");
device_tree_add_found(root, "/iobus", "console@0x000000,16");
device_tree_add_found(root, "/iobus", "halt@0x100000,4");
device_tree_add_found(root, "/iobus", "icu@0x200000,4");
{ /* initialization */
device *init = device_tree_add_found(root, "/", "init");
{
device *init_register = device_tree_add_found(init, "", "register");
device_add_integer_property(init_register,
"pc",
OEA_STALL_CPU_LOOP_ADDRESS);
device_add_integer_property(init_register,
"0.pc",
bfd_get_start_address(image));
device_add_integer_property(init_register,
"sp",
memory_size-16);
device_add_integer_property(init_register,
"msr",
(msr_recoverable_interrupt
| (little_endian
? msr_little_endian_mode
: 0)
));
device_tree_add_found_uw_u_u(init, "",
"data",
OEA_SYSTEM_CALL_ADDRESS,
4, emul_call_instruction);
device_tree_add_found_uw_u_u(init, "",
"data",
OEA_SYSTEM_CALL_ADDRESS + 4,
4, emul_rfi_instruction);
device_tree_add_found_uw_u_u(init, "",
"data",
OEA_STALL_CPU_LOOP_ADDRESS,
4, emul_loop_instruction);
}
{
device *init_stack = device_tree_add_found(init, "", "stack");
device_add_null_property(init_stack,
(elf_binary
? "elf"
: "aix"));
}
{
device *init_load_binary = device_tree_add_found(init, "",
"load-binary");
device_add_null_property(init_load_binary,
bfd_get_filename(image));
}
}
}
return (os_emul_data*)-1;
}
static void
emul_bugapi_init(os_emul_data *emul_data,
int nr_cpus)
{
/* nothing happens here */
}
static int
emul_bugapi_instruction_call(cpu *processor,
unsigned_word cia,
unsigned_word ra,
os_emul_data *emul_data)
{
const int call_id = cpu_registers(processor)->gpr[10];
/* check that this isn't an invalid instruction */
if (cia != OEA_SYSTEM_CALL_ADDRESS)
return 0;
switch (call_id) {
case _OUTCHR:
printf_filtered("%c", (char)cpu_registers(processor)->gpr[3]);
break;
case _OUTLN:
printf_filtered("\n");
break;
case _RETURN:
cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
break;
default:
error("emul-bugapi: unimplemented bugapi call 0x%x from address 0x%lx\n",
call_id, SRR0);
break;
}
return 1;
/* the instruction following this one is a RFI. Thus by just
continuing the return from system call is performed */
}
const os_emul emul_bugapi = {
"bugapi",
emul_bugapi_create,
emul_bugapi_init,
0, /*system_call*/
emul_bugapi_instruction_call,
0 /*data*/
};
#endif