URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [oc/] [insight/] [gdb/] [remote-or1k.c] - Rev 1771
Go to most recent revision | Compare with Previous | Blame | View Log
/* Remote debugging interface for various or1k debugging protocols. Copyright 1993-1995, 2000 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Marko Mlinar <markom@opencores.org> This file is part of GDB. 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. */ #include "defs.h" #include "inferior.h" #include "bfd.h" #include "symfile.h" #include "gdb_wait.h" #include "gdbcmd.h" #include "gdbcore.h" #include "target.h" #include "remote-utils.h" #include "gdb_string.h" #include "tm.h" #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> extern void jtag_init PARAMS ((char * args)); extern unsigned int jtag_read_reg PARAMS ((unsigned int regno)); extern void jtag_write_reg PARAMS ((unsigned int regno, unsigned int data)); extern unsigned int jtag_read_tap_reg PARAMS ((unsigned int regno)); extern void jtag_write_tap_reg PARAMS ((unsigned int regno, unsigned int data)); extern void jtag_done PARAMS ((void)); struct target_ops or1k_jtag_ops; static struct or1k_target_ops or1k_target_jtag = { "jtag", jtag_init, jtag_done, jtag_read_reg, jtag_write_reg, jtag_read_tap_reg, jtag_write_tap_reg, NULL, &or1k_jtag_ops, OPS_MAGIC }; struct target_ops or1k_sim_ops; static struct or1k_target_ops or1k_target_sim = { "simulator", NULL, NULL, NULL, NULL, NULL, NULL, NULL, &or1k_sim_ops, OPS_MAGIC }; struct target_ops or1k_dummy_ops; static struct or1k_target_ops or1k_target_dummy = { "dummy", NULL, NULL, NULL, NULL, NULL, NULL, NULL, &or1k_dummy_ops, OPS_MAGIC }; const char *str_err[] = { "None", "CRC error" }; const char *status_name[] = { "UNDEFINED", "CONNECTING", "DISCONNECTING", "RUNNING", "STOPPED" }; /* Implementation specific information. Set by or1k_initialize. */ struct struct_or1k_implementation or1k_implementation; /* Current target status. */ static enum target_status or1k_status = TARGET_UNDEFINED; /* The target vector. */ struct target_ops or1k_dummy_ops, or1k_jtag_ops, or1k_sim_ops; /* Currently active target description (if or1k_is_open == 1) */ static struct target_ops *current_ops; /* Currently active or1k target operations. */ static struct or1k_target_ops *current_or1k_target = NULL; /* Set to 1 if the target is open. */ static int or1k_is_open = 0; /* Error last occured, zero = ok. */ static int err = 0; /* Number of interrupts while waiting for process. */ static int interrupt_count = 0; /* Current register values. */ static unsigned int dmr1 = 0; static unsigned int dmr2 = 0; static unsigned int dsr = 0; static unsigned int drr = 0; /* Current watchpoints. */ static int dvr[8]; static struct dcr_struct dcr[8]; /* Handle low-level error that we can't recover from. Note that just error()ing out from target_wait or some such low-level place will cause all hell to break loose--the rest of GDB will tend to get left in an inconsistent state. */ static NORETURN void or1k_error (char *string,...) { va_list args; va_start (args, string); target_terminal_ours (); wrap_here (""); /* Force out any buffered output */ gdb_flush (gdb_stdout); if (error_pre_print) fprintf_filtered (gdb_stderr, error_pre_print); vfprintf_filtered (gdb_stderr, string, args); fprintf_filtered (gdb_stderr, "\n"); va_end (args); gdb_flush (gdb_stderr); /* Clean up in such a way that or1k_close won't try to talk to the board (it almost surely won't work since we weren't able to talk to it). */ or1k_is_open = 0; printf_unfiltered ("Ending remote or1k debugging.\n"); target_mourn_inferior (); return_to_top_level (RETURN_ERROR); } const char * or1k_err_name (e) int e; { return str_err[e]; } /* putc_readable - print a character, displaying non-printable chars in ^x notation or in hex. */ static void fputc_readable (ch, file) int ch; struct ui_file *file; { if (ch == '\n') fputc_unfiltered ('\n', file); else if (ch == '\r') fprintf_unfiltered (file, "\\r"); else if (ch < 0x20) /* ASCII control character */ fprintf_unfiltered (file, "^%c", ch + '@'); else if (ch >= 0x7f) /* non-ASCII characters (rubout or greater) */ fprintf_unfiltered (file, "[%02x]", ch & 0xff); else fputc_unfiltered (ch, file); } /* puts_readable - print a string, displaying non-printable chars in ^x notation or in hex. */ static void fputs_readable (string, file) char *string; struct ui_file *file; { int c; while ((c = *string++) != '\0') fputc_readable (c, file); } /* Sets register/memory regno to data. */ void or1k_write_reg (regno, data) unsigned int regno; unsigned int data; { if (current_or1k_target != NULL && current_or1k_target->to_write_spr_reg != NULL) current_or1k_target->to_write_spr_reg (regno, data); } /* Reads register/memory from regno. */ unsigned int or1k_read_reg (regno) unsigned int regno; { if (current_or1k_target != NULL && current_or1k_target->to_read_spr_reg != NULL) return current_or1k_target->to_read_spr_reg (regno); else return 0x1234; } /* Stalls the CPU. */ static void or1k_stall () { //!!! or1k_write_tap_reg (xxx, xxx); } /* Unstalls the CPU. */ static void or1k_unstall () { //!!! or1k_write_tap_reg (xxx, xxx); } static void or1k_set_undefined_cleanups (arg) PTR arg; { or1k_status = TARGET_UNDEFINED; } /* Initialize a new connection to the or1k board, and make sure we are really connected. */ static void or1k_init (args) char *args; { struct cleanup *old_cleanups = make_cleanup (or1k_set_undefined_cleanups, NULL); int i; /* What is this code doing here? I don't see any way it can happen, and it might mean or1k_initializing didn't get cleared properly. So I'll make it a warning. */ if (or1k_status == TARGET_CONNECTING) { warning ("internal error: or1k_initialize called twice"); return; } or1k_status = TARGET_CONNECTING; or1k_stall (); if (current_or1k_target != NULL && current_or1k_target->to_init != NULL) current_or1k_target->to_init (args); /* Determine implementation configuration. */ or1k_implementation.VR = or1k_read_reg (VR_SPRNUM); or1k_implementation.UPR = or1k_read_reg (UPR_SPRNUM); /* Determine max number of supported matchpoints. */ or1k_implementation.num_matchpoints = 2; or1k_implementation.num_gpr_regs = 32; /*!!! FINISH */ /* Is implementation supported? */ /* First we should have system and debug groups implemented. */ if (or1k_implementation.VR & (1 << SPR_SYSTEM_GROUP) == 0) error ("System group should be available in the or1k implementation."); if (or1k_implementation.VR & (1 << SPR_DEBUG_GROUP) == 0) error ("Debug group should be available in the or1k implementation."); /* Delete break, watch, catch points. */ for(i = 0; i < NUM_MATCHPOINTS; i++) or1k_write_reg (DCR0_SPRNUM + i, 0); dmr1 = 0; or1k_write_reg (DMR1_SPRNUM, dmr1); dmr2 = 0; or1k_write_reg (DMR2_SPRNUM, dmr2); if (err != 0) error ("Cannot connect."); /* Stop when breakpoint occurs. */ or1k_write_reg (DSR_SPRNUM, 0x1000); do_cleanups (old_cleanups); /* This should cause an error if not connected. */ or1k_fetch_registers (-1); set_current_frame (create_new_frame (read_fp (), read_pc ())); select_frame (get_current_frame (), 0); } /* Kill the process running on the board. */ void or1k_kill () { if (or1k_status != TARGET_RUNNING) return; or1k_status = TARGET_UNDEFINED; /* HW STEP. Set DMR1_ST. */ dmr1 |= DMR1_ST; or1k_write_reg (DMR1_SPRNUM, dmr1); dmr1 &= ~DMR1_ST; or1k_stall(); or1k_status = TARGET_UNDEFINED; inferior_pid = 0; } /* Open a connection to the remote board. */ static void or1k_open (name, from_tty) char *name; int from_tty; { or1k_init (name); /* Switch to using remote target now. */ current_ops = current_or1k_target->gdb_ops; or1k_is_open = 1; push_target (current_ops); /* FIXME: Should we call start_remote here? */ /* This is really the job of start_remote however, that makes an assumption that the target is about to print out a status message of some sort. That doesn't happen here (in fact, it may not be possible to get the monitor to send the appropriate packet). */ flush_cached_frames (); registers_changed (); stop_pc = read_pc (); set_current_frame (create_new_frame (read_fp (), stop_pc)); select_frame (get_current_frame (), 0); print_stack_frame (selected_frame, -1, 1); } /* Close a connection to the remote board. */ static void or1k_close (quitting) int quitting; { if (or1k_is_open) { or1k_kill (); if (current_or1k_target != NULL && current_or1k_target->to_done != NULL) current_or1k_target->to_done (); current_or1k_target = NULL; } generic_mourn_inferior (); } /* Detach from the remote board. */ static void or1k_detach (args, from_tty) char *args; int from_tty; { if (args) error ("Argument given to \"detach\" when remotely debugging."); pop_target (); or1k_close (1); if (from_tty) printf_unfiltered ("Ending remote or1k debugging.\n"); } /* Resume execution of the target process. STEP says whether to single-step or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given to the target, or zero for no signal. */ static void or1k_resume (pid, step, siggnal) int pid, step; enum target_signal siggnal; { if (or1k_status != TARGET_STOPPED) if (or1k_status == TARGET_RUNNING) error ("Program is already running."); else error ("The program is not being run."); /* Clear reason register for later. */ or1k_write_reg (DRR_SPRNUM, 0); if (step) { /* HW STEP. Set DMR1_ST. */ dmr1 |= DMR1_ST; or1k_write_reg (DMR1_SPRNUM, dmr1); dmr1 &= ~DMR1_ST; } /* Run the target. */ or1k_unstall (); or1k_status = TARGET_RUNNING; } /* Wait until the remote stops, and return a wait status. */ static int or1k_wait (pid, status) int pid; struct target_waitstatus *status; { interrupt_count = 0; /* If we have not sent a single step or continue command, then the board is waiting for us to do something. Return a status indicating that it is stopped. */ if (or1k_status != TARGET_RUNNING) { if (or1k_status != TARGET_STOPPED) error("Target in invalid state."); status->kind = TARGET_WAITKIND_STOPPED; status->value.sig = TARGET_SIGNAL_TRAP; return 0; } if (err) or1k_error ("Remote failure: %s", or1k_err_name (err)); /* Wait for or1k DRR register to be nonzero. */ do { drr = or1k_read_reg (DRR_SPRNUM); usleep (10); } while (drr == 0); status->kind = TARGET_WAITKIND_STOPPED; if (drr & DRR_RSTE) status->value.sig = TARGET_SIGNAL_REALTIME_33; else if (drr & DRR_BUSEE) status->value.sig = TARGET_SIGNAL_BUS; else if (drr & DRR_DPFE) status->value.sig = TARGET_SIGNAL_REALTIME_34; else if (drr & DRR_IPFE) status->value.sig = TARGET_SIGNAL_REALTIME_35; else if (drr & DRR_LPINTE) status->value.sig = TARGET_SIGNAL_INT; else if (drr & DRR_AE) status->value.sig = TARGET_SIGNAL_REALTIME_36; else if (drr & DRR_IIE) status->value.sig = TARGET_SIGNAL_ILL; else if (drr & DRR_HPINTE) status->value.sig = TARGET_SIGNAL_INT; else if (drr & DRR_DME) status->value.sig = TARGET_SIGNAL_REALTIME_37; else if (drr & DRR_IME) status->value.sig = TARGET_SIGNAL_REALTIME_38; else if (drr & DRR_RE) status->value.sig = TARGET_SIGNAL_REALTIME_39; else if (drr & DRR_SCE) status->value.sig = TARGET_SIGNAL_REALTIME_40; else if (drr & DRR_BE) status->value.sig = TARGET_SIGNAL_TRAP; else { status->value.sig = TARGET_SIGNAL_UNKNOWN; warning ("Invalid exception occured."); } or1k_status = TARGET_STOPPED; /* If the stop PC is in the _exit function, assume we hit the 'break 0x3ff' instruction in _exit, so this is not a normal breakpoint. */ { char *func_name; CORE_ADDR func_start; CORE_ADDR pc = read_pc (); find_pc_partial_function (pc, &func_name, &func_start, NULL); if (func_name != NULL && strcmp (func_name, "_exit") == 0 && func_start == pc) status->kind = TARGET_WAITKIND_EXITED; } return 0; } /* Fetch a word from the target board. */ static unsigned int or1k_fetch_word (addr) CORE_ADDR addr; { return or1k_read_reg (addr + MEM_SPACE); } /* Store a word to the target board. Returns errno code or zero for success. */ static int or1k_store_word (addr, val) CORE_ADDR addr; unsigned int val; { or1k_write_reg (addr + MEM_SPACE, val); return err; } /* Fetch the remote registers. */ void or1k_fetch_registers (regno) int regno; { unsigned int val; if (regno == -1) { for (regno = 0; regno < NUM_REGS; regno++) or1k_fetch_registers (regno); return; } if (regno >= NUM_REGS) error("Invalid register number!"); /* Convert to SPRNUM and read. */ val = or1k_read_reg (REGNUM_TO_SPRNUM(regno) + REG_SPACE); { char buf[MAX_REGISTER_RAW_SIZE]; /* We got the number the register holds, but gdb expects to see a value in the target byte ordering. */ store_unsigned_integer (buf, REGISTER_RAW_SIZE (regno), val); supply_register (regno, buf); } if (err) or1k_error ("Can't read register %d(%i): %s", regno, REGNUM_TO_SPRNUM(regno) + REG_SPACE, or1k_err_name (err)); } /* Fetch and return instruction from the specified location. */ unsigned int or1k_fetch_instruction (addr) CORE_ADDR addr; { char buf[OR1K_INSTLEN]; int status; status = read_memory_nobpt (addr, buf, OR1K_INSTLEN); if (status) memory_error (status, addr); return extract_unsigned_integer (buf, OR1K_INSTLEN); } static void or1k_prepare_to_store () { } /* Store remote register(s). */ static void or1k_store_registers (regno) int regno; { if (regno == -1) { for (regno = 0; regno < NUM_REGS; regno++) or1k_store_registers (regno); return; } if (regno >= NUM_REGS) error("Invalid register number!"); or1k_write_reg (REGNUM_TO_SPRNUM(regno) + REG_SPACE, or1k_read_reg (REGNUM_TO_SPRNUM(regno) + REG_SPACE)); if (err) or1k_error ("Can't write register %d(%i): %s", regno, REGNUM_TO_SPRNUM(regno) + REG_SPACE, or1k_err_name (err)); } /* Read or write LEN bytes from inferior memory at MEMADDR, transferring to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is nonzero. Returns length of data written or read; 0 for error. Note that protocol gives us the correct value for a longword, since it transfers values in ASCII. We want the byte values, so we have to swap the longword values. */ static int or1k_xfer_memory (memaddr, myaddr, len, write, ignore) CORE_ADDR memaddr; char *myaddr; int len; int write; struct target_ops *ignore; { register int i; /* Round starting address down to longword boundary. */ register CORE_ADDR addr = memaddr & ~3; /* Round ending address up; get number of longwords that makes. */ register int count = (((memaddr + len) - addr) + 3) / 4; /* Allocate buffer of that many longwords. */ register char *buffer = alloca (count * 4); int status; if (memaddr >= MEM_SPACE) error("Invalid address"); if (write) { /* Fill start and end extra bytes of buffer with existing data. */ if (addr != memaddr || len < 4) { /* Need part of initial word -- fetch it. */ store_unsigned_integer (&buffer[0], 4, or1k_fetch_word (addr)); } if (count > 1) { /* Need part of last word -- fetch it. FIXME: we do this even if we don't need it. */ store_unsigned_integer (&buffer[(count - 1) * 4], 4, or1k_fetch_word (addr + (count - 1) * 4)); } /* Copy data to be written over corresponding part of buffer */ memcpy ((char *) buffer + (memaddr & 3), myaddr, len); /* Write the entire buffer. */ for (i = 0; i < count; i++, addr += 4) { status = or1k_store_word (addr, extract_unsigned_integer (&buffer[i * 4], 4)); /* Report each kilobyte (we download 32-bit words at a time) */ if (i % 256 == 255) { printf_unfiltered ("*"); gdb_flush (gdb_stdout); } if (status) { errno = status; return 0; } /* FIXME: Do we want a QUIT here? */ } if (count >= 256) printf_unfiltered ("\n"); } else { /* Read all the longwords */ for (i = 0; i < count; i++, addr += 4) { store_unsigned_integer (&buffer[i * 4], 4, or1k_fetch_word (addr)); QUIT; } /* Copy appropriate bytes out of the buffer. */ memcpy (myaddr, buffer + (memaddr & 3), len); } return len; } /* Print info on this target. */ static void or1k_files_info (ignore) struct target_ops *ignore; { char *file = "nothing"; if (exec_bfd) file = bfd_get_filename (exec_bfd); printf_filtered ("or1k_files_info: file \"%s\"\n", file); if (exec_bfd) { printf_filtered ("\tAttached to %s running program %s\n", target_shortname, file); } /* Print target info. */ printf_filtered ("Status: %s\n", status_name[or1k_status]); } /* We can write a breakpoint and read the shadow contents in one operation. */ /* Tell whether we can support a hardware breakpoint. */ static int or1k_can_use_hardware_breakpoint () { int i; /* Search for unused breakpoint. */ for (i = 0; i < NUM_MATCHPOINTS; i++) if (dcr[i].dp == 0) return 1; return 0; } /* Insert a breakpoint. On targets that don't have built-in breakpoint support, we read the contents of the target location and stash it, then overwrite it with a breakpoint instruction. ADDR is the target location in the target machine. CONTENTS_CACHE is a pointer to memory allocated for saving the target contents. It is guaranteed by the caller to be long enough to save sizeof BREAKPOINT bytes (this is accomplished via BREAKPOINT_MAX). */ static int or1k_insert_breakpoint (addr, contents_cache) CORE_ADDR addr; char *contents_cache; { if (or1k_can_use_hardware_breakpoint()) return set_breakpoint (addr); else return memory_insert_breakpoint (addr, contents_cache); } static int or1k_remove_breakpoint (addr, contents_cache) CORE_ADDR addr; char *contents_cache; { /* First try to remove HW breakpoint at address */ if (clear_breakpoint (addr)) return memory_remove_breakpoint (addr, contents_cache); else return 0; } /* Insert a breakpoint. */ int set_breakpoint (addr) CORE_ADDR addr; { int i; unsigned int u; /* Search for unused breakpoint. */ for (i = 0; i < NUM_MATCHPOINTS; i++) if (dcr[i].dp == 0) break; if (i >= NUM_MATCHPOINTS) return 1; dvr[i] = addr; dcr[i].dp = 1; dcr[i].cc = CC_EQUAL; dcr[i].sc = 0; dcr[i].ct = CT_FETCH; or1k_write_reg (DVR0_SPRNUM + i, dvr[i]); memcpy (&u, &dcr[i], sizeof(dcr[i])); or1k_write_reg (DCR0_SPRNUM + i, u); return 0; } /* Clear a breakpoint. */ int clear_breakpoint (addr) CORE_ADDR addr; { int i; unsigned int u; /* Search for matching breakpoint. */ for (i = 0; i < NUM_MATCHPOINTS; i++) if ((dcr[i].dp == 1) && (dvr[i] == addr) && (dcr[i].cc == CC_EQUAL) && (dcr[i].sc == 0) && (dcr[i].ct == CT_FETCH)) break; if (i >= NUM_MATCHPOINTS) return 1; dcr[i].dp = 0; memcpy (&u, &dcr[i], sizeof(dcr[i])); or1k_write_reg (DCR0_SPRNUM + i, u); return 0; } /* Start running on the target board. */ static void or1k_create_inferior (execfile, args, env) char *execfile; char *args; char **env; { CORE_ADDR entry_pt; if (args && *args) { warning ("\ Can't pass arguments to remote OR1K board; arguments ignored."); /* And don't try to use them on the next "run" command. */ execute_command ("set args", 0); } if (execfile == 0 || exec_bfd == 0) error ("No executable file specified"); or1k_kill (); remove_breakpoints (); entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd); init_wait_for_inferior (); /* FIXME: Should we set inferior_pid here? */ //inferior_pid = 42; insert_breakpoints (); /* Needed to get correct instruction in cache */ clear_proceed_status (); or1k_status = TARGET_STOPPED; proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); } /* Clean up after a process. Actually nothing to do. */ static void or1k_mourn_inferior () { generic_mourn_inferior (); } static void or1k_dummy_open (name, from_tty) char *name; int from_tty; { target_preopen (from_tty); if (or1k_is_open) unpush_target (current_ops); current_or1k_target = &or1k_target_dummy; or1k_open (name, from_tty); } static void or1k_jtag_open (name, from_tty) char *name; int from_tty; { target_preopen (from_tty); if (or1k_is_open) unpush_target (current_ops); current_or1k_target = &or1k_target_jtag; or1k_open (name, from_tty); } static void or1k_sim_open (name, from_tty) char *name; int from_tty; { /* target_preopen (from_tty); - do we need this ? */ if (or1k_is_open) unpush_target (current_ops); current_or1k_target = &or1k_target_sim; or1k_open (name, from_tty); } /* Executes command on the target. */ void or1k_sim_cmd (char *args, int from_tty) { if (current_or1k_target != NULL && current_or1k_target->to_exec_command != NULL) current_or1k_target->to_exec_command (args, from_tty); else error ("Command not supported on this target. "); } void _initialize_remote_or1k () { /* Initialize the fields in or1k_ops that are common to all targets. */ or1k_dummy_ops.to_close = or1k_close; or1k_dummy_ops.to_detach = or1k_detach; or1k_dummy_ops.to_resume = or1k_resume; or1k_dummy_ops.to_wait = or1k_wait; or1k_dummy_ops.to_fetch_registers = or1k_fetch_registers; or1k_dummy_ops.to_store_registers = or1k_store_registers; or1k_dummy_ops.to_prepare_to_store = or1k_prepare_to_store; or1k_dummy_ops.to_xfer_memory = or1k_xfer_memory; or1k_dummy_ops.to_files_info = or1k_files_info; or1k_dummy_ops.to_insert_breakpoint = or1k_insert_breakpoint; or1k_dummy_ops.to_remove_breakpoint = or1k_remove_breakpoint; or1k_dummy_ops.to_kill = or1k_kill; or1k_dummy_ops.to_load = generic_load; or1k_dummy_ops.to_create_inferior = or1k_create_inferior; or1k_dummy_ops.to_mourn_inferior = or1k_mourn_inferior; or1k_dummy_ops.to_stratum = process_stratum; or1k_dummy_ops.to_has_all_memory = 0; /* We can access memory while program is running. */ or1k_dummy_ops.to_has_memory = 1; or1k_dummy_ops.to_has_stack = 1; or1k_dummy_ops.to_has_registers = 1; or1k_dummy_ops.to_has_execution = 1; or1k_dummy_ops.to_magic = OPS_MAGIC; //or1k_ops.to_wait = or1k_wait; /* Copy the common fields to all target vectors. */ or1k_jtag_ops = or1k_sim_ops = or1k_dummy_ops; /* Initialize target-specific fields in the target vectors adn add targets. */ or1k_jtag_ops.to_shortname = "jtag"; or1k_jtag_ops.to_longname = "Remote or1k debugging over JTAG port"; or1k_jtag_ops.to_doc = "\ Debug a board using the OR1K remote debugging protocol over a parallel line.\n\ The argument is the device it is connected to or, if it contains a colon,\n"; or1k_jtag_ops.to_open = or1k_jtag_open; add_target (&or1k_jtag_ops); or1k_dummy_ops.to_shortname = "dummy"; or1k_dummy_ops.to_longname = "Dummy target"; or1k_dummy_ops.to_doc = "Actually no real target attached - more like /dev/null.\n"; or1k_dummy_ops.to_open = or1k_dummy_open; add_target (&or1k_dummy_ops); or1k_sim_ops.to_shortname = "sim"; or1k_sim_ops.to_longname = "Remote or1k debugging using architecture simulator"; or1k_sim_ops.to_doc = "Debug using an architecture simulator.\n"; or1k_sim_ops.to_open = or1k_sim_open; add_target (&or1k_sim_ops); }
Go to most recent revision | Compare with Previous | Blame | View Log