#include "defs.h"
#include "gdb_string.h"
#include "inferior.h"
#include "gdb_wait.h"
#include "value.h"
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include "terminal.h"
#include "target.h"
#include "gdbcore.h"
#define COMPILE_CHECK 0
#if COMPILE_CHECK
#define Q_REGNUM 0
#define VAB_REGNUM 0
#define CPS_REGNUM 0
#define IPA_REGNUM 0
#define IPB_REGNUM 0
#define GR1_REGNUM 0
#define LR0_REGNUM 0
#define IPC_REGNUM 0
#define CR_REGNUM 0
#define BP_REGNUM 0
#define FC_REGNUM 0
#define INTE_REGNUM 0
#define EXO_REGNUM 0
#define GR96_REGNUM 0
#define NPC_REGNUM
#define FPE_REGNUM 0
#define PC2_REGNUM 0
#define FPS_REGNUM 0
#define ALU_REGNUM 0
#define LRU_REGNUM 0
#define TERMINAL int
#define RAW 1
#define ANYP 1
extern int a29k_freeze_mode;
extern int processor_type;
extern char *processor_name;
#endif
extern int stop_soon_quietly;
extern struct target_ops adapt_ops;
static void adapt_fetch_registers ();
static void adapt_store_registers ();
static void adapt_close ();
static int adapt_clear_breakpoints ();
#define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
#define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
#define ASCII_COFF
#define LOG_FILE "adapt.log"
#if defined (LOG_FILE)
FILE *log_file = NULL;
#endif
static int timeout = 5;
static char *dev_name;
int adapt_desc = -1;
FILE *adapt_stream;
#define ON 1
#define OFF 0
static void
rawmode (int desc, int turnon)
{
TERMINAL sg;
if (desc < 0)
return;
ioctl (desc, TIOCGETP, &sg);
if (turnon)
{
#ifdef HAVE_TERMIO
sg.c_lflag &= ~(ICANON);
#else
sg.sg_flags |= RAW;
#endif
}
else
{
#ifdef HAVE_TERMIO
sg.c_lflag |= ICANON;
#else
sg.sg_flags &= ~(RAW);
#endif
}
ioctl (desc, TIOCSETP, &sg);
}
slurp_input (void)
{
char buf[8];
#ifdef HAVE_TERMIO
while (read (adapt_desc, buf, 8) > 0);
#else
alarm (timeout);
while (read (adapt_desc, buf, 8) > 0);
alarm (0);
#endif
}
static int
readchar (void)
{
char buf;
buf = '\0';
#ifdef HAVE_TERMIO
read (adapt_desc, &buf, 1);
#else
alarm (timeout);
if (read (adapt_desc, &buf, 1) < 0)
{
if (errno == EINTR)
error ("Timeout reading from remote system.");
else
perror_with_name ("remote");
}
alarm (0);
#endif
if (buf == '\0')
error ("Timeout reading from remote system.");
#if defined (LOG_FILE)
putc (buf & 0x7f, log_file);
#endif
return buf & 0x7f;
}
static void
expect (char *string)
{
char *p = string;
fflush (adapt_stream);
immediate_quit++;
while (1)
{
if (readchar () == *p)
{
p++;
if (*p == '\0')
{
immediate_quit--;
return;
}
}
else
p = string;
}
}
static void
expect_prompt (void)
{
#if defined (LOG_FILE)
fflush (log_file);
#endif
fflush (adapt_stream);
expect ("\n# ");
}
static int
get_hex_digit (int ignore_space)
{
int ch;
while (1)
{
ch = readchar ();
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else if (ch == ' ' && ignore_space)
;
else
{
expect_prompt ();
error ("Invalid hex digit from remote system.");
}
}
}
static void
get_hex_byte (char *byt)
{
int val;
val = get_hex_digit (1) << 4;
val |= get_hex_digit (0);
*byt = val;
}
static long
get_hex_word (void)
{
long val;
int j;
val = 0;
for (j = 0; j < 8; j++)
val = (val << 4) + get_hex_digit (j == 0);
return val;
}
static void
get_hex_regs (int n, int regno)
{
long val;
while (n--)
{
val = get_hex_word ();
supply_register (regno++, (char *) &val);
}
}
#ifndef HAVE_TERMIO
#ifndef __STDC__
#ifndef volatile
#define volatile
# endif
#endif
volatile int n_alarms;
void
adapt_timer (void)
{
#if 0
if (kiodebug)
printf ("adapt_timer called\n");
#endif
n_alarms++;
}
#endif
static char *prog_name = NULL;
static int need_artificial_trap = 0;
void
adapt_kill (char *arg, int from_tty)
{
fprintf (adapt_stream, "K");
fprintf (adapt_stream, "\r");
expect_prompt ();
}
static void
adapt_load (char *args, int fromtty)
{
FILE *fp;
int n;
char buffer[1024];
if (!adapt_stream)
{
printf_filtered ("Adapt not open. Use 'target' command to open adapt\n");
return;
}
#ifdef ASCII_COFF
fprintf (adapt_stream, "YA T,0\r");
fflush (adapt_stream);
sprintf (buffer, "cat %s | btoa > /tmp/#adapt-btoa", args);
system (buffer);
fp = fopen ("/tmp/#adapt-btoa", "r");
rawmode (adapt_desc, OFF);
while (n = fread (buffer, 1, 1024, fp))
{
do
{
n -= write (adapt_desc, buffer, n);
}
while (n > 0);
if (n < 0)
{
perror ("writing ascii coff");
break;
}
}
fclose (fp);
rawmode (adapt_desc, ON);
system ("rm /tmp/#adapt-btoa");
#else
fprintf (adapt_stream, "YC T,0\r");
fflush (adapt_stream);
if (!(fp = fopen (args, "r")))
{
printf_filtered ("Can't open %s\n", args);
return;
}
while (n = fread (buffer, 1, 512, fp))
{
do
{
n -= write (adapt_desc, buffer, n);
}
while (n > 0);
if (n < 0)
{
perror ("writing ascii coff");
break;
}
}
fclose (fp);
#endif
expect_prompt ();
fprintf (adapt_stream, "\r");
expect_prompt ();
}
void
adapt_create_inferior (char *execfile, char *args, char **env)
{
int entry_pt;
if (args && *args)
error ("Can't pass arguments to remote adapt process.");
if (execfile == 0 || exec_bfd == 0)
error ("No executable file specified");
entry_pt = (int) bfd_get_start_address (exec_bfd);
if (adapt_stream)
{
adapt_kill (NULL, NULL);
adapt_clear_breakpoints ();
init_wait_for_inferior ();
slurp_input ();
fprintf (adapt_stream, "\r");
expect_prompt ();
printf_filtered ("Do you want to download '%s' (y/n)? [y] : ", prog_name);
{
char buffer[10];
gets (buffer);
if (*buffer != 'n')
{
adapt_load (prog_name, 0);
}
}
#ifdef NOTDEF
fprintf (adapt_stream, "G %x,N\r", entry_pt);
printf_filtered ("Now use the 'continue' command to start.\n");
expect_prompt ();
#else
insert_breakpoints ();
proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
#endif
}
else
{
printf_filtered ("Adapt not open yet.\n");
}
}
#ifndef B19200
#define B19200 EXTA
#endif
#ifndef B38400
#define B38400 EXTB
#endif
static struct
{
int rate, damn_b;
}
baudtab[] =
{
{
0, B0
}
,
{
50, B50
}
,
{
75, B75
}
,
{
110, B110
}
,
{
134, B134
}
,
{
150, B150
}
,
{
200, B200
}
,
{
300, B300
}
,
{
600, B600
}
,
{
1200, B1200
}
,
{
1800, B1800
}
,
{
2400, B2400
}
,
{
4800, B4800
}
,
{
9600, B9600
}
,
{
19200, B19200
}
,
{
38400, B38400
}
,
{
-1, -1
}
,
};
static int
damn_b (int rate)
{
int i;
for (i = 0; baudtab[i].rate != -1; i++)
if (rate == baudtab[i].rate)
return baudtab[i].damn_b;
return B38400;
}
static int baudrate = 9600;
static void
adapt_open (char *name, int from_tty)
{
TERMINAL sg;
unsigned int prl;
char *p;
if (name == 0)
goto erroid;
for (p = name;
*p != '\0' && !isspace (*p); p++)
;
if (*p == '\0')
erroid:
error ("\
Please include the name of the device for the serial port,\n\
the baud rate, and the name of the program to run on the remote system.");
dev_name = (char *) xmalloc (p - name + 1);
strncpy (dev_name, name, p - name);
dev_name[p - name] = '\0';
for (; isspace (*p); p++)
;
if (1 != sscanf (p, "%d ", &baudrate))
goto erroid;
for (; isdigit (*p); p++)
;
for (; isspace (*p); p++)
;
if (prog_name != NULL)
free (prog_name);
prog_name = savestring (p, strlen (p));
adapt_close (0);
adapt_desc = open (dev_name, O_RDWR);
if (adapt_desc < 0)
perror_with_name (dev_name);
ioctl (adapt_desc, TIOCGETP, &sg);
#if ! defined(COMPILE_CHECK)
#ifdef HAVE_TERMIO
sg.c_cc[VMIN] = 0;
sg.c_cc[VTIME] = timeout * 10;
sg.c_lflag &= ~(ICANON | ECHO);
sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
#else
sg.sg_ispeed = damn_b (baudrate);
sg.sg_ospeed = damn_b (baudrate);
sg.sg_flags |= RAW | ANYP;
sg.sg_flags &= ~ECHO;
#endif
ioctl (adapt_desc, TIOCSETP, &sg);
adapt_stream = fdopen (adapt_desc, "r+");
#endif
push_target (&adapt_ops);
#ifndef HAVE_TERMIO
#ifndef NO_SIGINTERRUPT
if (siginterrupt (SIGALRM, 1) != 0)
perror ("adapt_open: error in siginterrupt");
#endif
if ((void (*)) signal (SIGALRM, adapt_timer) == (void (*)) -1)
perror ("adapt_open: error in signal");
#endif
#if defined (LOG_FILE)
log_file = fopen (LOG_FILE, "w");
if (log_file == NULL)
perror_with_name (LOG_FILE);
#endif
write (adapt_desc, "", 1);
write (adapt_desc, "\r", 1);
expect_prompt ();
write (adapt_desc, "\r", 1);
expect_prompt ();
adapt_clear_breakpoints ();
printf_filtered ("Connected to an Adapt via %s.\n", dev_name);
printf_filtered ("Remote debugging using virtual addresses works only\n");
printf_filtered ("\twhen virtual addresses map 1:1 to physical addresses.\n");
if (processor_type != a29k_freeze_mode)
{
fprintf_filtered (gdb_stderr,
"Freeze-mode debugging not available, and can only be done on an A29050.\n");
}
}
static void
adapt_close (int quitting)
{
adapt_clear_breakpoints ();
if (adapt_stream)
{
fflush (adapt_stream);
sleep (1);
write (adapt_desc, "R\r", 2);
}
if (adapt_stream)
fclose (adapt_stream);
if (adapt_desc >= 0)
adapt_stream = NULL;
adapt_desc = -1;
#if defined (LOG_FILE)
if (log_file)
{
if (ferror (log_file))
printf_filtered ("Error writing log file.\n");
if (fclose (log_file) != 0)
printf_filtered ("Error closing log file.\n");
log_file = NULL;
}
#endif
}
static void
adapt_attach (char *args, int from_tty)
{
if (from_tty)
printf_filtered ("Attaching to remote program %s.\n", prog_name);
fprintf (adapt_stream, "K\r");
fflush (adapt_stream);
expect_prompt ();
}
void
adapt_detach (char *args, int from_tty)
{
if (adapt_stream)
{
adapt_clear_breakpoints ();
fprintf (adapt_stream, "G\r");
}
pop_target ();
if (from_tty)
printf_filtered ("Ending remote %s debugging\n", target_shortname);
}
void
adapt_resume (int pid, int step, enum target_signal sig)
{
if (step)
{
write (adapt_desc, "t 1,s\r", 6);
expect ("t 1,s\r\n");
expect ("@");
expect_prompt ();
need_artificial_trap = 1;
}
else
{
write (adapt_desc, "G\r", 2);
expect_prompt ();
}
}
int
adapt_wait (struct target_waitstatus *status)
{
static char bpt[] = "@";
static char exitmsg[] = "@????????I JMPTI GR121,LR0";
char *bp = bpt;
char *ep = exitmsg;
char swallowed[50];
char *swallowed_p = swallowed;
int ch;
int ch_handled;
int old_timeout = timeout;
int old_immediate_quit = immediate_quit;
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
if (need_artificial_trap != 0)
{
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_TRAP;
need_artificial_trap--;
return 0;
}
timeout = 0;
immediate_quit = 1;
while (1)
{
QUIT;
ch_handled = 0;
ch = readchar ();
if (ch == *bp)
{
bp++;
if (*bp == '\0')
break;
ch_handled = 1;
*swallowed_p++ = ch;
}
else
bp = bpt;
if (ch == *ep || *ep == '?')
{
ep++;
if (*ep == '\0')
break;
if (!ch_handled)
*swallowed_p++ = ch;
ch_handled = 1;
}
else
ep = exitmsg;
if (!ch_handled)
{
char *p;
for (p = swallowed; p < swallowed_p; ++p)
putc (*p, stdout);
swallowed_p = swallowed;
putc (ch, stdout);
}
}
expect_prompt ();
if (*bp == '\0')
{
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_TRAP;
}
else
{
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
}
timeout = old_timeout;
immediate_quit = old_immediate_quit;
return 0;
}
static char *
get_reg_name (int regno)
{
static char buf[80];
if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
#if defined(GR64_REGNUM)
else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32)
sprintf (buf, "GR%03d", regno - GR64_REGNUM + 64);
#endif
else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
sprintf (buf, "LR%03d", regno - LR0_REGNUM);
else if (regno == Q_REGNUM)
strcpy (buf, "SR131");
else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
else if (regno == ALU_REGNUM)
strcpy (buf, "SR132");
else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM)
{
if ((regno >= NPC_REGNUM && regno <= PC2_REGNUM) && USE_SHADOW_PC)
sprintf (buf, "SR%03d", regno - NPC_REGNUM + 20);
else
sprintf (buf, "SR%03d", regno - VAB_REGNUM);
}
else if (regno == GR1_REGNUM)
strcpy (buf, "GR001");
return buf;
}
static void
adapt_fetch_registers (void)
{
int reg_index;
int regnum_index;
char tempbuf[10];
int sreg_buf[16];
int i, j;
#if defined(GR64_REGNUM)
write (adapt_desc, "dw gr64,gr95\r", 13);
for (reg_index = 64, regnum_index = GR64_REGNUM;
reg_index < 96;
reg_index += 4, regnum_index += 4)
{
sprintf (tempbuf, "GR%03d ", reg_index);
expect (tempbuf);
get_hex_regs (4, regnum_index);
expect ("\n");
}
#endif
write (adapt_desc, "dw gr96,gr127\r", 14);
for (reg_index = 96, regnum_index = GR96_REGNUM;
reg_index < 128;
reg_index += 4, regnum_index += 4)
{
sprintf (tempbuf, "GR%03d ", reg_index);
expect (tempbuf);
get_hex_regs (4, regnum_index);
expect ("\n");
}
for (i = 0; i < 128; i += 32)
{
sprintf (tempbuf, "dw lr%d\r", i);
write (adapt_desc, tempbuf, strlen (tempbuf));
for (reg_index = i, regnum_index = LR0_REGNUM + i;
reg_index < i + 32;
reg_index += 4, regnum_index += 4)
{
sprintf (tempbuf, "LR%03d ", reg_index);
expect (tempbuf);
get_hex_regs (4, regnum_index);
expect ("\n");
}
}
sprintf (tempbuf, "dw sr0\r");
write (adapt_desc, tempbuf, strlen (tempbuf));
for (i = 0; i < 4; i++)
{
sprintf (tempbuf, "SR%3d", i * 4);
expect (tempbuf);
for (j = 0; j < (i == 3 ? 3 : 4); j++)
sreg_buf[i * 4 + j] = get_hex_word ();
}
expect_prompt ();
if (USE_SHADOW_PC)
{
sreg_buf[10] = read_register (NPC_REGNUM);
sreg_buf[11] = read_register (PC_REGNUM);
sreg_buf[12] = read_register (PC2_REGNUM);
}
for (i = 0; i < 14; i++)
supply_register (VAB_REGNUM + i, (char *) &sreg_buf[i]);
sprintf (tempbuf, "dw sr128\r");
write (adapt_desc, tempbuf, strlen (tempbuf));
for (i = 0; i < 2; i++)
{
sprintf (tempbuf, "SR%3d", 128 + i * 4);
expect (tempbuf);
for (j = 0; j < 4; j++)
sreg_buf[i * 4 + j] = get_hex_word ();
}
expect_prompt ();
supply_register (IPC_REGNUM, (char *) &sreg_buf[0]);
supply_register (IPA_REGNUM, (char *) &sreg_buf[1]);
supply_register (IPB_REGNUM, (char *) &sreg_buf[2]);
supply_register (Q_REGNUM, (char *) &sreg_buf[3]);
supply_register (BP_REGNUM, (char *) &sreg_buf[5]);
supply_register (FC_REGNUM, (char *) &sreg_buf[6]);
supply_register (CR_REGNUM, (char *) &sreg_buf[7]);
{
int val = -1;
supply_register (FPE_REGNUM, (char *) &val);
supply_register (INTE_REGNUM, (char *) &val);
supply_register (FPS_REGNUM, (char *) &val);
supply_register (EXO_REGNUM, (char *) &val);
}
write (adapt_desc, "dw gr1,gr1\r", 11);
expect ("GR001 ");
get_hex_regs (1, GR1_REGNUM);
expect_prompt ();
}
static void
adapt_fetch_register (int regno)
{
if (regno == -1)
adapt_fetch_registers ();
else
{
char *name = get_reg_name (regno);
fprintf (adapt_stream, "dw %s,%s\r", name, name);
expect (name);
expect (" ");
get_hex_regs (1, regno);
expect_prompt ();
}
}
static void
adapt_store_registers (void)
{
int i, j;
fprintf (adapt_stream, "s gr1,%x\r", read_register (GR1_REGNUM));
expect_prompt ();
#if defined(GR64_REGNUM)
for (j = 0; j < 32; j += 16)
{
fprintf (adapt_stream, "s gr%d,", j + 64);
for (i = 0; i < 15; ++i)
fprintf (adapt_stream, "%x,", read_register (GR64_REGNUM + j + i));
fprintf (adapt_stream, "%x\r", read_register (GR64_REGNUM + j + 15));
expect_prompt ();
}
#endif
for (j = 0; j < 32; j += 16)
{
fprintf (adapt_stream, "s gr%d,", j + 96);
for (i = 0; i < 15; ++i)
fprintf (adapt_stream, "%x,", read_register (GR96_REGNUM + j + i));
fprintf (adapt_stream, "%x\r", read_register (GR96_REGNUM + j + 15));
expect_prompt ();
}
for (j = 0; j < 128; j += 16)
{
fprintf (adapt_stream, "s lr%d,", j);
for (i = 0; i < 15; ++i)
fprintf (adapt_stream, "%x,", read_register (LR0_REGNUM + j + i));
fprintf (adapt_stream, "%x\r", read_register (LR0_REGNUM + j + 15));
expect_prompt ();
}
fprintf (adapt_stream, "s sr128,%x,%x,%x\r", read_register (IPC_REGNUM),
read_register (IPA_REGNUM), read_register (IPB_REGNUM));
expect_prompt ();
fprintf (adapt_stream, "s sr133,%x,%x,%x\r", read_register (BP_REGNUM),
read_register (FC_REGNUM), read_register (CR_REGNUM));
expect_prompt ();
fprintf (adapt_stream, "s sr131,%x\r", read_register (Q_REGNUM));
expect_prompt ();
fprintf (adapt_stream, "s sr0,");
for (i = 0; i < 7; ++i)
fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
expect_prompt ();
fprintf (adapt_stream, "s sr7,");
for (i = 7; i < 14; ++i)
fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
expect_prompt ();
}
void
adapt_store_register (int regno)
{
if (regno == -1)
adapt_store_registers ();
else
{
char *name = get_reg_name (regno);
fprintf (adapt_stream, "s %s,%x\r", name, read_register (regno));
if (regno == GR1_REGNUM)
registers_changed ();
expect_prompt ();
}
}
void
adapt_prepare_to_store (void)
{
}
static CORE_ADDR
translate_addr (CORE_ADDR addr)
{
#if defined(KERNEL_DEBUGGING)
if (addr >= UVADDR)
{
CORE_ADDR i = (CORE_ADDR) read_register (PADDR_U_REGNUM);
return (i + addr - (CORE_ADDR) UVADDR);
}
else
{
return (addr);
}
#else
return (addr);
#endif
}
int
adapt_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len, int write)
{
memaddr = translate_addr (memaddr);
if (write)
return adapt_write_inferior_memory (memaddr, myaddr, len);
else
return adapt_read_inferior_memory (memaddr, myaddr, len);
}
void
adapt_files_info (void)
{
printf_filtered ("\tAttached to %s at %d baud and running program %s\n",
dev_name, baudrate, prog_name);
printf_filtered ("\ton an %s processor.\n", processor_name[processor_type]);
}
int
adapt_write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
int i;
unsigned int cps;
cps = read_register (CPS_REGNUM);
if (cps & 0x00000800)
write_register (CPS_REGNUM, cps & ~(0x00000800));
for (i = 0; i < len; i++)
{
if ((i % 16) == 0)
fprintf (adapt_stream, "sb %x,", memaddr + i);
if ((i % 16) == 15 || i == len - 1)
{
fprintf (adapt_stream, "%x\r", ((unsigned char *) myaddr)[i]);
expect_prompt ();
}
else
fprintf (adapt_stream, "%x,", ((unsigned char *) myaddr)[i]);
}
if (cps & 0x00000800)
write_register (CPS_REGNUM, cps);
return len;
}
int
adapt_read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
int i;
int count;
unsigned long startaddr;
int len_this_pass;
if (((memaddr - 1) + len) < memaddr)
return EIO;
startaddr = memaddr;
count = 0;
while (count < len)
{
len_this_pass = 16;
if ((startaddr % 16) != 0)
len_this_pass -= startaddr % 16;
if (len_this_pass > (len - count))
len_this_pass = (len - count);
fprintf (adapt_stream, "db %x,%x\r", startaddr,
(startaddr - 1) + len_this_pass);
#ifdef NOTDEF
expect ("\n");
i = 0;
while (1)
{
if (isxdigit (readchar ()))
++i;
else
{
expect_prompt ();
error ("Hex digit expected from remote system.");
}
if (i >= 8)
break;
}
#endif
expect (" ");
for (i = 0; i < len_this_pass; i++)
get_hex_byte (&myaddr[count++]);
expect_prompt ();
startaddr += len_this_pass;
}
return count;
}
#define MAX_BREAKS 8
static int num_brkpts = 0;
static int
adapt_insert_breakpoint (CORE_ADDR addr, char *save)
{
if (num_brkpts < MAX_BREAKS)
{
num_brkpts++;
fprintf (adapt_stream, "B %x", addr);
fprintf (adapt_stream, "\r");
expect_prompt ();
return (0);
}
else
{
fprintf_filtered (gdb_stderr,
"Too many break points, break point not installed\n");
return (1);
}
}
static int
adapt_remove_breakpoint (CORE_ADDR addr, char *save)
{
if (num_brkpts > 0)
{
num_brkpts--;
fprintf (adapt_stream, "BR %x", addr);
fprintf (adapt_stream, "\r");
fflush (adapt_stream);
expect_prompt ();
}
return (0);
}
static int
adapt_clear_breakpoints (void)
{
if (adapt_stream)
{
fprintf (adapt_stream, "BR");
fprintf (adapt_stream, "\r");
fflush (adapt_stream);
expect_prompt ();
}
num_brkpts = 0;
}
static void
adapt_mourn (void)
{
adapt_clear_breakpoints ();
pop_target ();
generic_mourn_inferior ();
}
static int
display_until (char *str)
{
int i = 0, j, c;
while (c = readchar ())
{
if (c == str[i])
{
i++;
if (i == strlen (str))
return;
}
else
{
if (i)
{
for (j = 0; j < i; j++)
putchar (str[j]);
i = 0;
}
putchar (c);
}
}
}
void
adapt_com (char *args, int fromtty)
{
if (!adapt_stream)
{
printf_filtered ("Adapt not open. Use the 'target' command to open.\n");
return;
}
slurp_input ();
switch (islower (args[0]) ? toupper (args[0]) : args[0])
{
default:
printf_filtered ("Unknown/Unimplemented adapt command '%s'\n", args);
break;
case 'G':
write (adapt_desc, args, strlen (args));
write (adapt_desc, "\r", 1);
expect_prompt ();
break;
case 'B':
case 'C':
case 'D':
case 'I':
case 'J':
case 'K':
case 'L':
case 'O':
case 'T':
case 'P':
case 'X':
case 'Z':
write (adapt_desc, args, strlen (args));
write (adapt_desc, "\r", 1);
expect (args);
display_until ("# ");
break;
case 'S':
if (strchr (args, ','))
{
write (adapt_desc, args, strlen (args));
write (adapt_desc, "\r", 1);
expect_prompt ();
}
break;
}
}
struct target_ops adapt_ops;
static void
init_adapt_ops (void)
{
adapt_ops.to_shortname = "adapt";
adapt_ops.to_longname = "Remote AMD `Adapt' target";
adapt_ops.to_doc = "Remote debug an AMD 290*0 using an `Adapt' monitor via RS232";
adapt_ops.to_open = adapt_open;
adapt_ops.to_close = adapt_close;
adapt_ops.to_attach = adapt_attach;
adapt_ops.to_post_attach = NULL;
adapt_ops.to_require_attach = NULL;
adapt_ops.to_detach = adapt_detach;
adapt_ops.to_require_detach = NULL;
adapt_ops.to_resume = adapt_resume;
adapt_ops.to_wait = adapt_wait;
adapt_ops.to_post_wait = NULL;
adapt_ops.to_fetch_registers = adapt_fetch_register;
adapt_ops.to_store_registers = adapt_store_register;
adapt_ops.to_prepare_to_store = adapt_prepare_to_store;
adapt_ops.to_xfer_memory = adapt_xfer_inferior_memory;
adapt_ops.to_files_info = adapt_files_info;
adapt_ops.to_insert_breakpoint = adapt_insert_breakpoint;
adapt_ops.to_remove_breakpoint = adapt_remove_breakpoint;
adapt_ops.to_terminal_init = 0;
adapt_ops.to_terminal_inferior = 0;
adapt_ops.to_terminal_ours_for_output = 0;
adapt_ops.to_terminal_ours = 0;
adapt_ops.to_terminal_info = 0;
adapt_ops.to_kill = adapt_kill;
adapt_ops.to_load = adapt_load;
adapt_ops.to_lookup_symbol = 0;
adapt_ops.to_create_inferior = adapt_create_inferior;
adapt_ops.to_post_startup_inferior = NULL;
adapt_ops.to_acknowledge_created_inferior = NULL;
adapt_ops.to_clone_and_follow_inferior = NULL;
adapt_ops.to_post_follow_inferior_by_clone = NULL;
adapt_ops.to_insert_fork_catchpoint = NULL;
adapt_ops.to_remove_fork_catchpoint = NULL;
adapt_ops.to_insert_vfork_catchpoint = NULL;
adapt_ops.to_remove_vfork_catchpoint = NULL;
adapt_ops.to_has_forked = NULL;
adapt_ops.to_has_vforked = NULL;
adapt_ops.to_can_follow_vfork_prior_to_exec = NULL;
adapt_ops.to_post_follow_vfork = NULL;
adapt_ops.to_insert_exec_catchpoint = NULL;
adapt_ops.to_remove_exec_catchpoint = NULL;
adapt_ops.to_has_execd = NULL;
adapt_ops.to_reported_exec_events_per_exec_call = NULL;
adapt_ops.to_has_exited = NULL;
adapt_ops.to_mourn_inferior = adapt_mourn;
adapt_ops.to_can_run = 0;
adapt_ops.to_notice_signals = 0;
adapt_ops.to_thread_alive = 0;
adapt_ops.to_stop = 0;
adapt_ops.to_pid_to_exec_file = NULL;
adapt_ops.to_core_file_to_sym_file = NULL;
adapt_ops.to_stratum = 0;
adapt_ops.DONT_USE = 0;
adapt_ops.to_has_all_memory = 1;
adapt_ops.to_has_memory = 1;
adapt_ops.to_has_stack = 1;
adapt_ops.to_has_registers = 1;
adapt_ops.to_has_execution = 0;
adapt_ops.to_sections = 0;
adapt_ops.to_sections_end = 0;
adapt_ops.to_magic = OPS_MAGIC;
}
void
_initialize_remote_adapt (void)
{
init_adapt_ops ();
add_target (&adapt_ops);
add_com ("adapt <command>", class_obscure, adapt_com,
"Send a command to the AMD Adapt remote monitor.");
}