home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / sim / ppc / emul_bugapi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-24  |  15.1 KB  |  448 lines

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