146283Sdfr/* Remote debugging interface for DINK32 (PowerPC) ROM monitor for
246283Sdfr   GDB, the GNU debugger.
398944Sobrien   Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
446283Sdfr
598944Sobrien   This file is part of GDB.
646283Sdfr
798944Sobrien   This program is free software; you can redistribute it and/or modify
898944Sobrien   it under the terms of the GNU General Public License as published by
998944Sobrien   the Free Software Foundation; either version 2 of the License, or
1098944Sobrien   (at your option) any later version.
1146283Sdfr
1298944Sobrien   This program is distributed in the hope that it will be useful,
1398944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1498944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598944Sobrien   GNU General Public License for more details.
1646283Sdfr
1798944Sobrien   You should have received a copy of the GNU General Public License
1898944Sobrien   along with this program; if not, write to the Free Software
1998944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2098944Sobrien   Boston, MA 02111-1307, USA.  */
2146283Sdfr
2246283Sdfr#include "defs.h"
2346283Sdfr#include "gdbcore.h"
2446283Sdfr#include "target.h"
2546283Sdfr#include "monitor.h"
2646283Sdfr#include "serial.h"
2798944Sobrien#include "symfile.h" /* For generic_load() */
2898944Sobrien#include "inferior.h" /* For write_pc() */
2998944Sobrien#include "regcache.h"
3046283Sdfr
3198944Sobrienstatic void dink32_open (char *args, int from_tty);
3246283Sdfr
3346283Sdfrstatic void
3498944Sobriendink32_supply_register (char *regname, int regnamelen, char *val, int vallen)
3546283Sdfr{
3698944Sobrien  int regno = 0;
3746283Sdfr
3846283Sdfr  if (regnamelen < 2 || regnamelen > 4)
3946283Sdfr    return;
4046283Sdfr
4146283Sdfr  switch (regname[0])
4246283Sdfr    {
4346283Sdfr    case 'R':
4446283Sdfr      if (regname[1] < '0' || regname[1] > '9')
4546283Sdfr	return;
4646283Sdfr      if (regnamelen == 2)
4746283Sdfr	regno = regname[1] - '0';
4846283Sdfr      else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9')
4946283Sdfr	regno = (regname[1] - '0') * 10 + (regname[2] - '0');
5046283Sdfr      else
5146283Sdfr	return;
5246283Sdfr      break;
5346283Sdfr    case 'F':
5446283Sdfr      if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9')
5546283Sdfr	return;
5646283Sdfr      if (regnamelen == 3)
5746283Sdfr	regno = 32 + regname[2] - '0';
5846283Sdfr      else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9')
5946283Sdfr	regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0');
6046283Sdfr      else
6146283Sdfr	return;
6246283Sdfr      break;
6346283Sdfr    case 'I':
6446283Sdfr      if (regnamelen != 2 || regname[1] != 'P')
6546283Sdfr	return;
6646283Sdfr      regno = 64;
6746283Sdfr      break;
6846283Sdfr    case 'M':
6946283Sdfr      if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R')
7046283Sdfr	return;
7146283Sdfr      regno = 65;
7246283Sdfr      break;
7346283Sdfr    case 'C':
7446283Sdfr      if (regnamelen != 2 || regname[1] != 'R')
7546283Sdfr	return;
7646283Sdfr      regno = 66;
7746283Sdfr      break;
7846283Sdfr    case 'S':
7946283Sdfr      if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R')
8046283Sdfr	return;
8146283Sdfr      else if (regname[3] == '8')
8246283Sdfr	regno = 67;
8346283Sdfr      else if (regname[3] == '9')
8446283Sdfr	regno = 68;
8546283Sdfr      else if (regname[3] == '1')
8646283Sdfr	regno = 69;
8746283Sdfr      else if (regname[3] == '0')
8846283Sdfr	regno = 70;
8946283Sdfr      else
9046283Sdfr	return;
9146283Sdfr      break;
9246283Sdfr    default:
9346283Sdfr      return;
9446283Sdfr    }
9546283Sdfr
9646283Sdfr  monitor_supply_register (regno, val);
9746283Sdfr}
9846283Sdfr
9946283Sdfr/* This array of registers needs to match the indexes used by GDB. The
10046283Sdfr   whole reason this exists is because the various ROM monitors use
10146283Sdfr   different names than GDB does, and don't support all the registers
10246283Sdfr   either.  */
10346283Sdfr
10498944Sobrienstatic char *dink32_regnames[] =
10546283Sdfr{
10698944Sobrien  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
10798944Sobrien  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
10898944Sobrien  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
10998944Sobrien  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
11046283Sdfr
11198944Sobrien  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
11298944Sobrien  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
11398944Sobrien  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
11498944Sobrien  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
11546283Sdfr
11698944Sobrien  "srr0", "msr", "cr", "lr", "ctr", "xer", "xer"
11746283Sdfr};
11846283Sdfr
11946283Sdfrstatic struct target_ops dink32_ops;
12046283Sdfr
12198944Sobrienstatic char *dink32_inits[] =
12298944Sobrien{"\r", NULL};
12346283Sdfr
12446283Sdfrstatic struct monitor_ops dink32_cmds;
12546283Sdfr
12646283Sdfrstatic void
12798944Sobriendink32_open (char *args, int from_tty)
12846283Sdfr{
12946283Sdfr  monitor_open (args, &dink32_cmds, from_tty);
13046283Sdfr}
13146283Sdfr
132130803Smarcelextern initialize_file_ftype _initialize_dink32_rom; /* -Wmissing-prototypes */
133130803Smarcel
13446283Sdfrvoid
13598944Sobrien_initialize_dink32_rom (void)
13646283Sdfr{
13746283Sdfr  dink32_cmds.flags = MO_HEX_PREFIX | MO_GETMEM_NEEDS_RANGE | MO_FILL_USES_ADDR | MO_HANDLE_NL | MO_32_REGS_PAIRED | MO_SETREG_INTERACTIVE | MO_SETMEM_INTERACTIVE | MO_GETMEM_16_BOUNDARY | MO_CLR_BREAK_1_BASED | MO_SREC_ACK | MO_SREC_ACK_ROTATE;
13846283Sdfr  dink32_cmds.init = dink32_inits;
13946283Sdfr  dink32_cmds.cont = "go +\r";
14046283Sdfr  dink32_cmds.step = "tr +\r";
14146283Sdfr  dink32_cmds.set_break = "bp 0x%x\r";
14246283Sdfr  dink32_cmds.clr_break = "bp %d\r";
14398944Sobrien#if 0				/* Would need to follow strict alignment rules.. */
14446283Sdfr  dink32_cmds.fill = "mf %x %x %x\r";
14546283Sdfr#endif
14646283Sdfr  dink32_cmds.setmem.cmdb = "mm -b %x\r";
14746283Sdfr  dink32_cmds.setmem.cmdw = "mm -w %x\r";
14846283Sdfr  dink32_cmds.setmem.cmdl = "mm %x\r";
14946283Sdfr  dink32_cmds.setmem.term = " ?  ";
15046283Sdfr  dink32_cmds.getmem.cmdb = "md %x\r";
15146283Sdfr  dink32_cmds.getmem.resp_delim = "        ";
15246283Sdfr  dink32_cmds.setreg.cmd = "rm %s\r";
15346283Sdfr  dink32_cmds.setreg.term = " ?  ";
15446283Sdfr  dink32_cmds.getreg.cmd = "rd %s\r";
15546283Sdfr  dink32_cmds.getreg.resp_delim = ": ";
15646283Sdfr  dink32_cmds.dump_registers = "rd r\r";
15746283Sdfr  dink32_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)";
15846283Sdfr  dink32_cmds.supply_register = dink32_supply_register;
15946283Sdfr  /* S-record download, via "keyboard port".  */
16046283Sdfr  dink32_cmds.load = "dl -k\r";
16146283Sdfr  dink32_cmds.loadresp = "Set Input Port : set to Keyboard Port\r";
16246283Sdfr  dink32_cmds.prompt = "DINK32_603 >>";
16346283Sdfr  dink32_cmds.line_term = "\r";
16446283Sdfr  dink32_cmds.target = &dink32_ops;
16546283Sdfr  dink32_cmds.stopbits = SERIAL_1_STOPBITS;
16646283Sdfr  dink32_cmds.regnames = dink32_regnames;
16746283Sdfr  dink32_cmds.magic = MONITOR_OPS_MAGIC;
16846283Sdfr
16946283Sdfr  init_monitor_ops (&dink32_ops);
17046283Sdfr
17146283Sdfr  dink32_ops.to_shortname = "dink32";
17246283Sdfr  dink32_ops.to_longname = "DINK32 monitor";
17346283Sdfr  dink32_ops.to_doc = "Debug using the DINK32 monitor.\n\
17446283SdfrSpecify the serial device it is connected to (e.g. /dev/ttya).";
17546283Sdfr  dink32_ops.to_open = dink32_open;
17646283Sdfr
17746283Sdfr  add_target (&dink32_ops);
17846283Sdfr}
179