Merge from vendor branch BINUTILS:
[dragonfly.git] / contrib / gdb / gdb / dink32-rom.c
1 /* Remote debugging interface for DINK32 (PowerPC) ROM monitor for
2    GDB, the GNU debugger.
3    Copyright 1997 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "defs.h"
22 #include "gdbcore.h"
23 #include "target.h"
24 #include "monitor.h"
25 #include "serial.h"
26
27 static void dink32_open PARAMS ((char *args, int from_tty));
28
29 static void
30 dink32_supply_register (regname, regnamelen, val, vallen)
31      char *regname;
32      int regnamelen;
33      char *val;
34      int vallen;
35 {
36   int regno = 0, base = 0;
37
38   if (regnamelen < 2 || regnamelen > 4)
39     return;
40
41   switch (regname[0])
42     {
43     case 'R':
44       if (regname[1] < '0' || regname[1] > '9')
45         return;
46       if (regnamelen == 2)
47         regno = regname[1] - '0';
48       else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9')
49         regno = (regname[1] - '0') * 10 + (regname[2] - '0');
50       else
51         return;
52       break;
53     case 'F':
54       if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9')
55         return;
56       if (regnamelen == 3)
57         regno = 32 + regname[2] - '0';
58       else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9')
59         regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0');
60       else
61         return;
62       break;
63     case 'I':
64       if (regnamelen != 2 || regname[1] != 'P')
65         return;
66       regno = 64;
67       break;
68     case 'M':
69       if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R')
70         return;
71       regno = 65;
72       break;
73     case 'C':
74       if (regnamelen != 2 || regname[1] != 'R')
75         return;
76       regno = 66;
77       break;
78     case 'S':
79       if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R')
80         return;
81       else if (regname[3] == '8')
82         regno = 67;
83       else if (regname[3] == '9')
84         regno = 68;
85       else if (regname[3] == '1')
86         regno = 69;
87       else if (regname[3] == '0')
88         regno = 70;
89       else
90         return;
91       break;
92     default:
93       return;
94     }
95
96   monitor_supply_register (regno, val);
97 }
98
99 static void
100 dink32_load (monops, filename, from_tty)
101      struct monitor_ops *monops;
102      char *filename;
103      int from_tty;
104 {
105   extern int inferior_pid;
106
107   generic_load (filename, from_tty);
108
109   /* Finally, make the PC point at the start address */
110   if (exec_bfd)
111     write_pc (bfd_get_start_address (exec_bfd));
112
113   inferior_pid = 0;             /* No process now */
114 }
115
116
117 /* This array of registers needs to match the indexes used by GDB. The
118    whole reason this exists is because the various ROM monitors use
119    different names than GDB does, and don't support all the registers
120    either.  */
121
122 static char *dink32_regnames[NUM_REGS] =
123 {
124   "r0",   "r1",   "r2",   "r3",   "r4",   "r5",   "r6",   "r7",
125   "r8",   "r9",   "r10",  "r11",  "r12",  "r13",  "r14",  "r15",
126   "r16",  "r17",  "r18",  "r19",  "r20",  "r21",  "r22",  "r23",
127   "r24",  "r25",  "r26",  "r27",  "r28",  "r29",  "r30",  "r31",
128
129   "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
130   "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
131   "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
132   "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",
133
134   "srr0", "msr",  "cr",   "lr",   "ctr",  "xer",  "xer"
135 };
136
137 static struct target_ops dink32_ops;
138
139 static char *dink32_inits[] = {"\r", NULL};
140
141 static struct monitor_ops dink32_cmds;
142
143 static void
144 dink32_open (args, from_tty)
145      char *args;
146      int from_tty;
147 {
148   monitor_open (args, &dink32_cmds, from_tty);
149 }
150
151 void
152 _initialize_dink32_rom ()
153 {
154   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;
155   dink32_cmds.init = dink32_inits;
156   dink32_cmds.cont = "go +\r";
157   dink32_cmds.step = "tr +\r";
158   dink32_cmds.set_break = "bp 0x%x\r";
159   dink32_cmds.clr_break = "bp %d\r";
160 #if 0 /* Would need to follow strict alignment rules.. */
161   dink32_cmds.fill = "mf %x %x %x\r";
162 #endif
163   dink32_cmds.setmem.cmdb = "mm -b %x\r";
164   dink32_cmds.setmem.cmdw = "mm -w %x\r";
165   dink32_cmds.setmem.cmdl = "mm %x\r";
166   dink32_cmds.setmem.term = " ?  ";
167   dink32_cmds.getmem.cmdb = "md %x\r";
168   dink32_cmds.getmem.resp_delim = "        ";
169   dink32_cmds.setreg.cmd = "rm %s\r";
170   dink32_cmds.setreg.term = " ?  ";
171   dink32_cmds.getreg.cmd = "rd %s\r";
172   dink32_cmds.getreg.resp_delim = ": ";
173   dink32_cmds.dump_registers = "rd r\r";
174   dink32_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)";
175   dink32_cmds.supply_register = dink32_supply_register;
176   /* S-record download, via "keyboard port".  */
177   dink32_cmds.load = "dl -k\r";
178   dink32_cmds.loadresp = "Set Input Port : set to Keyboard Port\r";
179 #if 0 /* slow load routine not needed if S-records work... */
180   dink32_cmds.load_routine = dink32_load;
181 #endif
182   dink32_cmds.prompt = "DINK32_603 >>";
183   dink32_cmds.line_term = "\r";
184   dink32_cmds.target = &dink32_ops;
185   dink32_cmds.stopbits = SERIAL_1_STOPBITS;
186   dink32_cmds.regnames = dink32_regnames;
187   dink32_cmds.magic = MONITOR_OPS_MAGIC;
188
189   init_monitor_ops (&dink32_ops);
190
191   dink32_ops.to_shortname = "dink32";
192   dink32_ops.to_longname = "DINK32 monitor";
193   dink32_ops.to_doc = "Debug using the DINK32 monitor.\n\
194 Specify the serial device it is connected to (e.g. /dev/ttya).";
195   dink32_ops.to_open = dink32_open;
196
197   add_target (&dink32_ops);
198 }