From 43ff13b4182f3853e19e9100c84313a6e9302b70 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Mon, 5 Jul 1999 17:58:44 +0000 Subject: [PATCH] import gdb-1999-07-05 snapshot --- gdb/ChangeLog | 201 ++++++++++ gdb/Makefile.in | 7 +- gdb/blockframe.c | 14 +- gdb/breakpoint.c | 76 +++- gdb/config/mn10300/tm-mn10300.h | 3 + gdb/configure.host | 2 +- gdb/defs.h | 39 +- gdb/doc/ChangeLog | 4 + gdb/doc/gdbint.texinfo | 6 + gdb/event-loop.c | 16 +- gdb/event-loop.h | 5 +- gdb/event-top.c | 103 ++++- gdb/frame.h | 1 + gdb/infcmd.c | 377 ++++++++++++++--- gdb/inferior.h | 13 + gdb/infrun.c | 123 +++++- gdb/main.c | 3 + gdb/mn10300-tdep.c | 4 +- gdb/remote-os9k.c | 9 +- gdb/remote-sim.c | 10 +- gdb/remote-st.c | 9 +- gdb/remote.c | 676 ++++++++++++++++++++++++++++++- gdb/ser-tcp.c | 6 +- gdb/ser-unix.c | 6 +- gdb/source.c | 2 +- gdb/sparcl-tdep.c | 6 +- gdb/target.c | 1 + gdb/target.h | 5 + gdb/testsuite/ChangeLog | 5 + gdb/testsuite/lib/gdb.exp | 50 ++- gdb/top.c | 23 +- gdb/top.h | 1 - gdb/utils.c | 54 +++ gdb/valops.c | 4 + sim/common/ChangeLog | 13 + sim/common/Make-common.in | 9 +- sim/common/cgen-cpu.h | 4 + sim/common/cgen-mem.h | 88 ++-- sim/common/cgen-ops.h | 688 ++++---------------------------- sim/common/cgen-sim.h | 1 + sim/common/cgen-types.h | 9 +- 41 files changed, 1886 insertions(+), 790 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f41bc52ed95..ac6d4d2267d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,203 @@ +1999-07-05 Jason Molenda (jsm@bugshack.cygnus.com) + + * remote.c: Include if it exists in order to pick up + FD_SET et al defns. + * remote-os9k.c: Same. + * remote-st.c: Same. + * ser-tcp.c: Same. + * ser-unix.c: Same. + * sparcl-tdep.c: Same. + +Fri Jul 2 19:38:43 1999 Andrew Cagney + + * top.c (target_output_hook): Delete definition. + * defs.h (target_output_hook): Delete declaration. + + * remote.c (remote_console_output): Delete call to + target_output_hook(). Send target output to gdb_stdtarg using an + unfiltered write. Make more robust. + + * remote-sim.c (gdb_os_write_stdout, gdb_os_write_stderr): + Ditto. For moment, do not try to separate target stdout and stderr + streams. + + * defs.h (gdb_stdtarg): New global. Output from target and + simulators. + +1999-07-02 Elena Zannoni + + * top.c (return_to_top_level): Do all the exec_cleanups too. + + * event-top.c (command_handler): Set up for a continuation, if we + are in the middle of running an execution command which will + finish later on. Do cleanups, an display of time/space only if not + running with an async target or not running an execution command. + (command_line_handler_continuation): New function. Continuation + for command_line_handler. + + * utils.c (exec_cleanup_chain): New cleanup chain to be used in + async mode for the execution commands. + (make_exec_cleanup): New function. Add a cleanup to the + exec_cleanup_chain. + (do_exec_cleanups): New Function. Do cleanups on the + exec_cleanup_chain. + (add_continuation): New function. Add a new continuation to the + cmd_continuation list. + (do_all_continuations): New function. Do all the continuations on + the cmd_continuation list. + + * top.h (ALL_CLEANUPS): Move from here to defs.h. + + * defs.h (struct continuation_arg): New structure. Arg to pass to + the call to a command continuation. + (struct continuation): New structure. Continuation for an + execution command. + (ALL_CLEANUPS): Move here from top.h. + + * remote.c (remote_async_open_1): Set things up for telling the + target we are running the extended protocol, only after the target + has stopped. + (set_extended_protocol): New function. Tell the target we are + using the extended protocol. + (remote_async_resume): Set things up for sync execution only if + this is the first time we are called. + + * breakpoint.c (until_break_command_continuation): New function. + Stuff to be done after the target stops during the 'until' + command. + (until_break_command): Set things up for completing the 'until' + command later on. Do the final cleanups only if not running + asynchronously or async execution is not supported by the target. + + * infcmd.c (until_command): Recognize '&' at end of command and + handle it properly. + (finish_command_continuation): New function. Do whatever is needed + after the target has stopped. + (finish_command): Recognize '&' at end of command and handle it + properly. Don't do stuff needed after target has stopped if + running asynchronously and target has async. Use exec_cleanup_chain + if running asynchronously and target is asynchronous. + + * infrun.c (cmd_continuation): New gloabl variable. Used to + coplete execution commands in async mode, after the target has + stoped. + (fetch_inferior_event): Use exec_cleanup_chain, instead of + cleanup_chain. Do all the exec cleanups at the end. Do all the + continuations at the end. Call complete_execution from here, + instead of normal_stop. + (complete_execution): Cleanup the signals handlers for SIGINT + before displaying the prompt. + (start_remote): Set target_executing to 1. + (normal_stop): Don't call complete_execution from here. + +Thu Jul 1 19:14:30 1999 Andrew Cagney + + * blockframe.c (struct dummy_frame): Add member ``top''. + (generic_push_dummy_frame): Initialize top to sp. + (generic_save_dummy_frame_tos): New function. Initialize top. + (generic_find_dummy_frame): Check for the top of the frame. + + * blockframe.c (generic_push_dummy_frame): Free the dummy_frame + registers. + + * config/mn10300/tm-mn10300.h (SAVE_DUMMY_FRAME_TOS): Define. + (TARGET_READ_FP): Return the SP as a best guess. + +Wed Jun 30 15:45:48 1999 Jeffrey A Law (law@cygnus.com) + + * configure.host (hppa*-*-hpux11*): Accept any version of hpux11 + instead of hpux11.0*. + +1999-06-30 Fernando Nasser + + * source.c (directory_command): Add missing test for from_tty. + +1999-06-29 Elena Zannoni + + * remote.c: Include event-loop.h. + (remote_async_ops, extended_async_remote_ops): Define new target + vector structures for asynchronous debugging. + (remote_async_open): New function. Asynchronous version of + remote_open. + (extended_remote_async_open): New function. Asynchronous version + of extended_remote_open. + (remote_async_open_1): New function. Async version of + remote_open_1. + (remote_async_detach): New function. Async version of + remote_detach. + (remote_async_resume): New function. Async version of + remote_resume. + (initialize_sigint_signal_handler, handle_remote_sigint, + handle_remote_sigint_twice, async_remote_interrupt, + async_remote_interrupt_twice, cleanup_sigint_signal_handler): New + functions. Used for handling ^C while target is running. + (remote_async_wait): New function. Async version of remote_wait. + (remote_async_kill): New function. Async version of remote_kill. + (extended_remote_async_create_inferior): New function. Async + version of extended_remote_create_inferior. + (init_remote_async_ops): New function. Initialize target vector + for target async. + (init_extended_async_remote_ops): New function. Initialize target + vector for target extended-async. + (_initialize_remote): Initialize remote_async_ops and + extended_async_remote_ops. + + * infrun.c: Include "event-loop.h". + (sync_execution): new global variable. + (proceed): Invoke wait_for_inferior and normal_stop only if not + running in async mode or if target doesn't support async + execution. + (start_remote): Don't call wait_for_inferior and normal_stop if + not running in async mode or if target not async. If running async + and target is async, start the target in simulated synchronous + mode. + (async_ecss, async_ecs): New global vars, for inferior state. + (fetch_inferior_event): New function. Async version of + wait_for_inferior. + (complete_execution): New function. Reset of gdb prompt and stdin, + after inferior execution has completed. + (normal_stop): Call complete_execution at end of asynchronous + execution. + + * infcmd.c (strip_bg_char): New function to detect the background + execution char '&'. + (run_command): Modify to support background and foreground + execution in async mode. + (continue_command): Ditto. + (step_1): Ditto. + (jump_command): Ditto. + (interrupt_target_command): New function. Interrupt the + target execution. + (_initialize_infcmd): Add new command 'interrupt'. + + * top.c (target_executing): New global variable. + (execute_command): Reject commands that cannot be executed while + the target is running asynchronously. + + * event-top.c (push_prompt): Make non static. + (pop_prompt): Make non static. If the current prompt is empty, + don't try to copy it over the previous one. + (handle_sigint): Make non static. + (command_handler): Do the cleanups only when not executing with an + asynchronous target. + + * event-loop.c (delete_async_signal_handler): Pass a pointer to a + pointer to a signal handler, so that is can be freed at the end. + + * target.c (update_current_target): Inherit to_has_async_exec. + + * inferior.h: Add global variables target_executing, and + sync_execution. Export function fetch_inferior_event. + + * event-loop.h: Add push_prompt, pop_prompt, handle_sigint to the + exported functions. Update prototype for delete_signal_handler. + + * target.h (struct target_ops): New target op: to_has_async_exec. + (target_has_async): New macro. + + * Makefile.in (infrun.o): Add dependency on event-loop.h. + (remote.o): Ditto. + 1999-06-28 Jim Blandy * solib.c (clear_solib): Don't disable breakpoints if we're @@ -136,6 +336,7 @@ Wed Jun 23 15:30:46 1999 Andrew Cagney * Makefile.in (top_h): Define. (event-loop.o): Add dependencies on top.h and defs.h. (event-top.o): Add dependency on terminal.h. + * event-loop.c: Get rid of #include . * event-loop.h: Get rid of nested #include's. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 177333e515f..b13fa01b21e 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -224,7 +224,7 @@ CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \ ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) -VERSION = 19990628 +VERSION = 19990705 DIST=gdb LINT=/usr/5bin/lint @@ -1206,7 +1206,7 @@ infptrace.o: infptrace.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \ gdb_string.h $(wait_h) $(command_h) infrun.o: infrun.c $(wait_h) $(defs_h) $(gdbcmd_h) $(gdbcore_h) \ - $(inferior_h) target.h gdbthread.h gdb_string.h + $(inferior_h) target.h gdbthread.h gdb_string.h $(event_loop_h) inftarg.o: inftarg.c $(wait_h) $(defs_h) $(gdbcore_h) $(inferior_h) \ target.h terminal.h $(command_h) @@ -1462,7 +1462,8 @@ remote-utils.o: remote-utils.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \ $(inferior_h) $(remote_utils_h) gdb_string.h remote.o: remote.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \ - $(inferior_h) $(remote_utils_h) symfile.h terminal.h gdb_string.h + $(inferior_h) $(remote_utils_h) symfile.h terminal.h gdb_string.h \ + $(event_loop_h) remote-nrom.o: remote-nrom.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \ $(inferior_h) $(remote_utils_h) symfile.h terminal.h diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 8f93d6ed531..87ce8bf5d1b 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -1121,6 +1121,7 @@ struct dummy_frame CORE_ADDR pc; CORE_ADDR fp; CORE_ADDR sp; + CORE_ADDR top; char *registers; }; @@ -1142,7 +1143,9 @@ generic_find_dummy_frame (pc, fp) for (dummyframe = dummy_frame_stack; dummyframe != NULL; dummyframe = dummyframe->next) - if (fp == dummyframe->fp || fp == dummyframe->sp) + if (fp == dummyframe->fp + || fp == dummyframe->sp + || fp == dummyframe->top) /* The frame in question lies between the saved fp and sp, inclusive */ return dummyframe->registers; @@ -1203,6 +1206,7 @@ generic_push_dummy_frame () if (INNER_THAN (dummy_frame->fp, fp)) /* stale -- destroy! */ { dummy_frame_stack = dummy_frame->next; + free (dummy_frame->registers); free (dummy_frame); dummy_frame = dummy_frame_stack; } @@ -1214,12 +1218,20 @@ generic_push_dummy_frame () dummy_frame->pc = read_register (PC_REGNUM); dummy_frame->sp = read_register (SP_REGNUM); + dummy_frame->top = dummy_frame->sp; dummy_frame->fp = fp; read_register_bytes (0, dummy_frame->registers, REGISTER_BYTES); dummy_frame->next = dummy_frame_stack; dummy_frame_stack = dummy_frame; } +void +generic_save_dummy_frame_tos (sp) + CORE_ADDR sp; +{ + dummy_frame_stack->top = sp; +} + /* Function: pop_frame Restore the machine state from either the saved dummy stack or a real stack frame. */ diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 11caae0d077..16a3ad68f7c 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2418,7 +2418,33 @@ bpstat_what (bs) after stopping, the check for whether to step over a breakpoint (BPSTAT_WHAT_SINGLE type stuff) is handled in proceed() without reference to how we stopped. We retain separate wp_silent and bp_silent - codes in case we want to change that someday. */ + codes in case we want to change that someday. + + Another possibly interesting property of this table is that + there's a partial ordering, priority-like, of the actions. Once + you've decided that some action is appropriate, you'll never go + back and decide something of a lower priority is better. The + ordering is: + + kc < clr sgl shl slr sn sr ss ts + sgl < clrs shl shlr slr sn sr ss ts + slr < err shl shlr sn sr ss ts + clr < clrs err shl shlr sn sr ss ts + clrs < err shl shlr sn sr ss ts + ss < shl shlr sn sr ts + sn < shl shlr sr ts + sr < shl shlr ts + shl < shlr + ts < + shlr < + + What I think this means is that we don't need a damned table + here. If you just put the rows and columns in the right order, + it'd look awfully regular. We could simply walk the bpstat list + and choose the highest priority action we find, with a little + logic to handle the 'err' cases, and the CLEAR_LONGJMP_RESUME/ + CLEAR_LONGJMP_RESUME_SINGLE distinction (which breakpoint.h says + is messy anyway). */ /* step_resume entries: a step resume breakpoint overrides another breakpoint of signal handling (see comment in wait_for_inferior @@ -4480,9 +4506,23 @@ static void awatch_command (arg, from_tty) } -/* Helper routine for the until_command routine in infcmd.c. Here +/* Helper routines for the until_command routine in infcmd.c. Here because it uses the mechanisms of breakpoints. */ +/* This function is called by fetch_inferior_event via the + cmd_continuation pointer, to complete the until command. It takes + care of cleaning up the temporary breakpoints set up by the until + command. */ +void +until_break_command_continuation (arg) + struct continuation_arg *arg; +{ + /* Do all the exec cleanups, which at this point should only be the + one set up in the first part of the until_break_command + function. */ + do_exec_cleanups (ALL_CLEANUPS); +} + /* ARGSUSED */ void until_break_command (arg, from_tty) @@ -4494,6 +4534,7 @@ until_break_command (arg, from_tty) struct frame_info *prev_frame = get_prev_frame (selected_frame); struct breakpoint *breakpoint; struct cleanup *old_chain; + struct continuation_arg *arg1, *arg2; clear_proceed_status (); @@ -4519,7 +4560,26 @@ until_break_command (arg, from_tty) breakpoint = set_momentary_breakpoint (sal, selected_frame, bp_until); - old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); + if (!async_p || !target_has_async) + old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); + else + make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); + + /* If we are running asynchronously, and the target supports async + execution, we are not waiting for the target to stop, in the call + tp proceed, below. This means that we cannot delete the + brekpoints until the target has actually stopped. The only place + where we get a chance to do that is in fetch_inferior_event, so + we must set things up for that. */ + + if (async_p && target_has_async) + { + /* In this case we don't need args for the continuation, because + all it needs to do is do the cleanups in the + exec_cleanup_chain, which will be only those inserted by this + function. We can get away by using ALL_CLEANUPS. */ + add_continuation (until_break_command_continuation, NULL); + } /* Keep within the current frame */ @@ -4528,11 +4588,17 @@ until_break_command (arg, from_tty) sal = find_pc_line (prev_frame->pc, 0); sal.pc = prev_frame->pc; breakpoint = set_momentary_breakpoint (sal, prev_frame, bp_until); - make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); + if (!async_p || !target_has_async) + make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); + else + make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); } proceed (-1, TARGET_SIGNAL_DEFAULT, 0); - do_cleanups(old_chain); + /* Do the cleanups now, anly if we are not running asynchronously, + of if we are, but the target is still synchronous. */ + if (!async_p || !target_has_async) + do_cleanups(old_chain); } #if 0 diff --git a/gdb/config/mn10300/tm-mn10300.h b/gdb/config/mn10300/tm-mn10300.h index eb47fecf218..20f93f4aa03 100644 --- a/gdb/config/mn10300/tm-mn10300.h +++ b/gdb/config/mn10300/tm-mn10300.h @@ -128,10 +128,13 @@ extern void mn10300_pop_frame PARAMS ((struct frame_info *)); #define FIX_CALL_DUMMY(DUMMY, START, FUNADDR, NARGS, ARGS, TYPE, GCCP) #define CALL_DUMMY_ADDRESS() entry_point_address () +#define TARGET_READ_FP() read_sp () + extern CORE_ADDR mn10300_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR)); #define PUSH_RETURN_ADDRESS(PC, SP) mn10300_push_return_address (PC, SP) #define PUSH_DUMMY_FRAME generic_push_dummy_frame () +#define SAVE_DUMMY_FRAME_TOS(SP) generic_save_dummy_frame_tos (SP) extern CORE_ADDR mn10300_push_arguments PARAMS ((int, struct value **, CORE_ADDR, diff --git a/gdb/configure.host b/gdb/configure.host index 50e4f6beb1a..84df8fa2aec 100644 --- a/gdb/configure.host +++ b/gdb/configure.host @@ -42,7 +42,7 @@ arm-*-*) gdb_host=arm ;; hppa*-*-bsd*) gdb_host=hppabsd ;; hppa*-*-hiux*) gdb_host=hppahpux ;; hppa*-*-hpux10.20) gdb_host=hpux1020 ;; -hppa*-*-hpux11.0*) gdb_host=hpux1100 ;; +hppa*-*-hpux11*) gdb_host=hpux1100 ;; hppa*-*-hpux*) gdb_host=hppahpux ;; hppa*-*-osf*) gdb_host=hppaosf ;; diff --git a/gdb/defs.h b/gdb/defs.h index 88564f4a216..b933698455b 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -272,6 +272,7 @@ extern void do_cleanups PARAMS ((struct cleanup *)); extern void do_final_cleanups PARAMS ((struct cleanup *)); extern void do_my_cleanups PARAMS ((struct cleanup **, struct cleanup *)); extern void do_run_cleanups PARAMS ((struct cleanup *)); +extern void do_exec_cleanups PARAMS ((struct cleanup *)); extern void discard_cleanups PARAMS ((struct cleanup *)); extern void discard_final_cleanups PARAMS ((struct cleanup *)); @@ -290,6 +291,8 @@ extern struct cleanup *make_my_cleanup PARAMS ((struct cleanup **, extern struct cleanup *make_run_cleanup PARAMS ((make_cleanup_func, void *)); +extern struct cleanup *make_exec_cleanup PARAMS ((make_cleanup_func, void *)); + extern struct cleanup *save_cleanups PARAMS ((void)); extern struct cleanup *save_final_cleanups PARAMS ((void)); extern struct cleanup *save_my_cleanups PARAMS ((struct cleanup **)); @@ -368,6 +371,11 @@ extern GDB_FILE *gdb_stderr; *_unfiltered. In the very near future that restriction shall be removed - either call shall be unfiltered. (cagney 1999-06-13). */ extern GDB_FILE *gdb_stdlog; +/* Target output that should bypass normal stdout/stderr filtering. + For momement, always call this stream using *_unfiltered. In the + very near future that restriction shall be removed - either call + shall be unfiltered. (cagney 1999-07-02). */ +extern GDB_FILE *gdb_stdtarg; #if defined(TUI) #include "tui.h" @@ -613,6 +621,34 @@ extern struct command_line *read_command_lines PARAMS ((char *, int)); extern void free_command_lines PARAMS ((struct command_line **)); +/* To continue the execution commands when running gdb asynchronously. + A continuation structure contains a pointer to a function to be called + to finish the command, once the target has stopped. Such mechanism is + used bt the finish and until commands, and in the remote protocol + when opening an extended-remote connection. */ + +struct continuation_arg +{ + struct continuation_arg *next; + PTR data; +}; + +struct continuation +{ + void (*continuation_hook) PARAMS ((struct continuation_arg *)); + struct continuation_arg *arg_list; + struct continuation *next; +} +continuation; + +/* In infrun.c. */ +extern struct continuation *cmd_continuation; + +/* From utils.c */ +void add_continuation PARAMS ((void (*) PARAMS ((struct continuation_arg *)), + struct continuation_arg *)); +void do_all_continuations PARAMS ((void)); + /* String containing the current directory (what getwd would return). */ extern char *current_directory; @@ -794,6 +830,8 @@ enum return_reason { RETURN_ERROR }; +#define ALL_CLEANUPS ((struct cleanup *)0) + #define RETURN_MASK_QUIT (1 << (int)RETURN_QUIT) #define RETURN_MASK_ERROR (1 << (int)RETURN_ERROR) #define RETURN_MASK_ALL (RETURN_MASK_QUIT | RETURN_MASK_ERROR) @@ -1109,7 +1147,6 @@ extern void (*flush_hook) PARAMS ((GDB_FILE *stream)); extern void (*create_breakpoint_hook) PARAMS ((struct breakpoint *b)); extern void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); extern void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); -extern void (*target_output_hook) PARAMS ((char *)); extern void (*interactive_hook) PARAMS ((void)); extern void (*registers_changed_hook) PARAMS ((void)); extern void (*readline_begin_hook) PARAMS ((char *, ...)); diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 10e4ef7de9b..bc9e6aae023 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +Tue Jun 29 11:43:55 1999 Andrew Cagney + + * gdbint.texinfo (SAVE_DUMMY_FRAME_TOS): Define. + Fri Jun 25 11:47:06 1999 Andrew Cagney * remote.texi (Communication Protocol): ``v'' is in use. Fix diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 4db5212a693..40a43a0b5c1 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -1573,6 +1573,12 @@ Deprecated in favor of @var{REGISTER_NAME}. Define this to return 1 if the given type will be passed by pointer rather than directly. +@item SAVE_DUMMY_FRAME_TOS (sp) +Used in @samp{call_function_by_hand} to notify the target dependent code +of the top-of-stack value that will be passed to the the inferior code. +This is the value of the @var{SP} after both the dummy frame and space +for parameters/results have been allocated on the stack. + @item SDB_REG_TO_REGNUM Define this to convert sdb register numbers into GDB regnums. If not defined, no conversion will be done. diff --git a/gdb/event-loop.c b/gdb/event-loop.c index 1e22e06c0fe..3f15da57594 100644 --- a/gdb/event-loop.c +++ b/gdb/event-loop.c @@ -290,6 +290,7 @@ gdb_do_one_event () } return result; } + /* Start up the event loop. This is the entry point to the event loop from the command loop. */ @@ -752,26 +753,27 @@ invoke_async_signal_handler () Free the space allocated for it. */ void delete_async_signal_handler (async_handler_ptr) - async_signal_handler *async_handler_ptr; + async_signal_handler **async_handler_ptr; { async_signal_handler *prev_ptr; - if (sighandler_list.first_handler == async_handler_ptr) + if (sighandler_list.first_handler == (*async_handler_ptr)) { - sighandler_list.first_handler = async_handler_ptr->next_handler; + sighandler_list.first_handler = (*async_handler_ptr)->next_handler; if (sighandler_list.first_handler == NULL) sighandler_list.last_handler = NULL; } else { prev_ptr = sighandler_list.first_handler; - while (prev_ptr->next_handler != async_handler_ptr) + while (prev_ptr->next_handler != (*async_handler_ptr) && prev_ptr) prev_ptr = prev_ptr->next_handler; - prev_ptr->next_handler = async_handler_ptr->next_handler; - if (sighandler_list.last_handler == async_handler_ptr) + prev_ptr->next_handler = (*async_handler_ptr)->next_handler; + if (sighandler_list.last_handler == (*async_handler_ptr)) sighandler_list.last_handler = prev_ptr; } - free ((char *) async_handler_ptr); + free ((char *) (*async_handler_ptr)); + (*async_handler_ptr) = NULL; } /* Is it necessary to call invoke_async_signal_handler? */ diff --git a/gdb/event-loop.h b/gdb/event-loop.h index e06fb8cb52d..b53f8e25235 100644 --- a/gdb/event-loop.h +++ b/gdb/event-loop.h @@ -230,7 +230,7 @@ extern void add_file_handler PARAMS ((int, file_handler_func, gdb_client_data)); extern void mark_async_signal_handler PARAMS ((async_signal_handler *)); extern async_signal_handler * create_async_signal_handler PARAMS ((async_handler_func *, gdb_client_data)); -extern void delete_async_signal_handler PARAMS ((async_signal_handler *async_handler_ptr)); +extern void delete_async_signal_handler PARAMS ((async_signal_handler **async_handler_ptr)); /* Exported functions from event-top.c. FIXME: these should really go into top.h. */ @@ -241,6 +241,9 @@ extern void set_async_editing_command PARAMS ((char *, int, struct cmd_list_elem extern void set_async_annotation_level PARAMS ((char *, int, struct cmd_list_element *)); extern void set_async_prompt PARAMS ((char *, int, struct cmd_list_element *)); extern void handle_stop_sig PARAMS ((int)); +extern void handle_sigint PARAMS ((int)); +extern void pop_prompt PARAMS ((void)); +extern void push_prompt PARAMS ((char *, char *, char *)); extern void gdb_readline2 PARAMS ((void)); /* Exported variables from event-top.c. diff --git a/gdb/event-top.c b/gdb/event-top.c index 223e670c70f..91b6389f363 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -35,15 +35,16 @@ extern void _initialize_event_loop PARAMS ((void)); static void command_line_handler PARAMS ((char *)); +static void command_line_handler_continuation PARAMS ((struct continuation_arg *)); void gdb_readline2 PARAMS ((void)); -static void pop_prompt PARAMS ((void)); -static void push_prompt PARAMS ((char *, char *, char *)); +void pop_prompt PARAMS ((void)); +void push_prompt PARAMS ((char *, char *, char *)); static void change_line_handler PARAMS ((void)); static void change_annotation_level PARAMS ((void)); static void command_handler PARAMS ((char *)); /* Signal handlers. */ -static void handle_sigint PARAMS ((int)); +void handle_sigint PARAMS ((int)); static void handle_sigquit PARAMS ((int)); static void handle_sighup PARAMS ((int)); static void handle_sigfpe PARAMS ((int)); @@ -331,7 +332,7 @@ change_annotation_level () parts: prefix, prompt, suffix. Usually prefix and suffix are empty strings, except when the annotation level is 2. Memory is allocated within savestring for the new prompt. */ -static void +void push_prompt (prefix, prompt, suffix) char *prefix; char *prompt; @@ -340,6 +341,9 @@ push_prompt (prefix, prompt, suffix) the_prompts.top++; PREFIX (0) = savestring (prefix, strlen (prefix)); + /* Note that this function is used by the set annotate 2 + command. This is why we take care of saving the old prompt + in case a new one is not specified. */ if (prompt) PROMPT (0) = savestring (prompt, strlen (prompt)); else @@ -349,14 +353,21 @@ push_prompt (prefix, prompt, suffix) } /* Pops the top of the prompt stack, and frees the memory allocated for it. */ -static void +void pop_prompt () { - if (strcmp (PROMPT (0), PROMPT (-1))) - { - free (PROMPT (-1)); - PROMPT (-1) = savestring (PROMPT (0), strlen (PROMPT (0))); - } + /* If we are not during a 'synchronous' execution command, in which + case, the top prompt would be empty. */ + if (strcmp (PROMPT (0), "")) + /* This is for the case in which the prompt is set while the + annotation level is 2. The top prompt will be changed, but when + we return to annotation level < 2, we want that new prompt to be + in effect, until the user does another 'set prompt'. */ + if (strcmp (PROMPT (0), PROMPT (-1))) + { + free (PROMPT (-1)); + PROMPT (-1) = savestring (PROMPT (0), strlen (PROMPT (0))); + } free (PREFIX (0)); free (PROMPT (0)); @@ -376,6 +387,8 @@ command_handler (command) { struct cleanup *old_chain; int stdin_is_tty = ISATTY (stdin); + struct continuation_arg *arg1; + struct continuation_arg *arg2; long time_at_cmd_start; #ifdef HAVE_SBRK long space_at_cmd_start = 0; @@ -416,11 +429,72 @@ command_handler (command) } execute_command (command, instream == stdin); + + /* Set things up for this function to be compete later, once the + executin has completed, if we are doing an execution command, + otherwise, just go ahead and finish. */ + if (target_has_async && target_executing) + { + arg1 = + (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); + arg2 = + (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); + arg1->next = arg2; + arg2->next = NULL; + arg1->data = (PTR) time_at_cmd_start; + arg2->data = (PTR) space_at_cmd_start; + add_continuation (command_line_handler_continuation, arg1); + } - /* Do any commands attached to breakpoint we stopped at. */ - bpstat_do_actions (&stop_bpstat); - do_cleanups (old_chain); + /* Do any commands attached to breakpoint we stopped at. Only if we + are always running synchronously. Or if we have just executed a + command that doesn't start the target. */ + if (!target_has_async || !target_executing) + { + bpstat_do_actions (&stop_bpstat); + do_cleanups (old_chain); + + if (display_time) + { + long cmd_time = get_run_time () - time_at_cmd_start; + printf_unfiltered ("Command execution time: %ld.%06ld\n", + cmd_time / 1000000, cmd_time % 1000000); + } + + if (display_space) + { +#ifdef HAVE_SBRK + extern char **environ; + char *lim = (char *) sbrk (0); + long space_now = lim - (char *) &environ; + long space_diff = space_now - space_at_cmd_start; + + printf_unfiltered ("Space used: %ld (%c%ld for this command)\n", + space_now, + (space_diff >= 0 ? '+' : '-'), + space_diff); +#endif + } + } +} + +/* Do any commands attached to breakpoint we stopped at. Only if we + are always running synchronously. Or if we have just executed a + command that doesn't start the target. */ +void +command_line_handler_continuation (arg) + struct continuation_arg *arg; +{ + extern int display_time; + extern int display_space; + + long time_at_cmd_start = (long) arg->data; + long space_at_cmd_start = (long) arg->next->data; + + bpstat_do_actions (&stop_bpstat); + /*do_cleanups (old_chain);*/ /*?????FIXME?????*/ + if (display_time) { long cmd_time = get_run_time () - time_at_cmd_start; @@ -428,7 +502,6 @@ command_handler (command) printf_unfiltered ("Command execution time: %ld.%06ld\n", cmd_time / 1000000, cmd_time % 1000000); } - if (display_space) { #ifdef HAVE_SBRK @@ -797,7 +870,7 @@ mark_async_signal_handler_wrapper (token) /* Tell the event loop what to do if SIGINT is received. See event-signal.c. */ -static void +void handle_sigint (sig) int sig; { diff --git a/gdb/frame.h b/gdb/frame.h index b00d8f17064..77cc4915740 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -134,6 +134,7 @@ extern int default_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *)); extern int alternate_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *)); extern int nonnull_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *)); extern int generic_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *)); +extern void generic_save_dummy_frame_tos PARAMS ((CORE_ADDR sp)); #if !defined (FRAME_CHAIN_VALID) #if !defined (FRAME_CHAIN_VALID_ALTERNATE) diff --git a/gdb/infcmd.c b/gdb/infcmd.c index eb111694ae2..ba4e798696d 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "language.h" #include "symfile.h" #include "objfiles.h" +#include "event-loop.h" /* Functions exported for general use: */ @@ -46,6 +47,8 @@ void registers_info PARAMS ((char *, int)); void continue_command PARAMS ((char *, int)); +static void finish_command_continuation PARAMS ((struct continuation_arg *)); + static void until_next_command PARAMS ((int)); static void until_command PARAMS ((char *, int)); @@ -94,6 +97,8 @@ static void run_no_args_command PARAMS ((char *args, int from_tty)); static void go_command PARAMS ((char *line_no, int from_tty)); +static int strip_bg_char PARAMS ((char **)); + void _initialize_infcmd PARAMS ((void)); #define GO_USAGE "Usage: go \n" @@ -184,6 +189,35 @@ int step_multi; struct environ *inferior_environ; +/* This function detects whether or not a '&' character (indicating + background execution) has been added as *the last* of the arguments ARGS + of a command. If it has, it removes it and returns 1. Otherwise it + does nothing and returns 0. */ +static int +strip_bg_char (args) + char **args; +{ + char *p = NULL; + + if (p = strchr (*args, '&')) + { + if (p == (*args + strlen (*args) - 1)) + { + if (strlen (*args) >1) + { + do + p--; + while (*p == ' ' || *p == '\t'); + *(p + 1) = '\0'; + } + else + *args = 0; + return 1; + } + } + return 0; +} + /* ARGSUSED */ void tty_command (file, from_tty) @@ -239,12 +273,33 @@ Start it from the beginning? ")) the user has to manually nuke all symbols between runs if they want them to go away (PR 2207). This is probably reasonable. */ - if (args) + if (!args) + sync_execution = 1; + else { char *cmd; - cmd = concat ("set args ", args, NULL); - make_cleanup (free, cmd); - execute_command (cmd, from_tty); + int async_exec = strip_bg_char (&args); + + /* If we get a request for running in the bg but the target + doesn't support it, error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we don't get a request of running in the bg, then we need + to simulate synchronous (fg) execution. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + + /* If there were other args, beside '&', process them. */ + if (args) + { + cmd = concat ("set args ", args, NULL); + make_cleanup (free, cmd); + execute_command (cmd, from_tty); + } } if (from_tty) @@ -278,10 +333,28 @@ continue_command (proc_count_exp, from_tty) char *proc_count_exp; int from_tty; { + int async_exec = 0; ERROR_NO_INFERIOR; - /* If have argument, set proceed count of breakpoint we stopped at. */ + /* Find out whether we must run in the background. */ + if (proc_count_exp != NULL) + async_exec = strip_bg_char (&proc_count_exp); + + /* If we must run in the background, but the target can't do it, + error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we are not asked to run in the bg, then prepare to run in the + foreground, synchronously. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + /* If have argument (besides '&'), set proceed count of breakpoint + we stopped at. */ if (proc_count_exp != NULL) { bpstat bs = stop_bpstat; @@ -363,8 +436,26 @@ step_1 (skip_subroutines, single_inst, count_string) register int count = 1; struct frame_info *frame; struct cleanup *cleanups = 0; - + int async_exec = 0; + ERROR_NO_INFERIOR; + + if (count_string) + async_exec = strip_bg_char (&count_string); + + /* If we get a request for running in the bg but the target + doesn't support it, error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we don't get a request of running in the bg, then we need + to simulate synchronous (fg) execution. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + count = count_string ? parse_and_eval_address (count_string) : 1; if (!single_inst || skip_subroutines) /* leave si command alone */ @@ -443,9 +534,27 @@ jump_command (arg, from_tty) struct symtab_and_line sal; struct symbol *fn; struct symbol *sfn; - + int async_exec = 0; + ERROR_NO_INFERIOR; + /* Find out whether we must run in the background. */ + if (arg != NULL) + async_exec = strip_bg_char (&arg); + + /* If we must run in the background, but the target can't do it, + error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we are not asked to run in the bg, then prepare to run in the + foreground, synchronously. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + if (!arg) error_no_arg ("starting address"); @@ -490,7 +599,6 @@ jump_command (arg, from_tty) } } - addr = sal.pc; if (from_tty) @@ -731,14 +839,110 @@ until_command (arg, from_tty) char *arg; int from_tty; { + int async_exec = 0; + if (!target_has_execution) error ("The program is not running."); + + /* Find out whether we must run in the background. */ + if (arg != NULL) + async_exec = strip_bg_char (&arg); + + /* If we must run in the background, but the target can't do it, + error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we are not asked to run in the bg, then prepare to run in the + foreground, synchronously. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } + if (arg) until_break_command (arg, from_tty); else until_next_command (from_tty); } + +/* Stuff that needs to be done by the finish command after the target + has stopped. In asynchronous mode, we wait for the target to stop in + the call to poll or select in the event loop, so it is impossible to + do all the stuff as part of the finish_command function itself. The + only chance we have to complete this command is in + fetch_inferior_event, which is called by the event loop as soon as it + detects that the target has stopped. This function is called via the + cmd_continaution pointer. */ +void +finish_command_continuation (arg) + struct continuation_arg *arg; +{ + register struct symbol *function; + struct breakpoint *breakpoint; + + breakpoint = (struct breakpoint *) arg->data; + function = (struct symbol *) (arg->next)->data; + + if (bpstat_find_breakpoint(stop_bpstat, breakpoint) != NULL + && function != 0) + { + struct type *value_type; + register value_ptr val; + CORE_ADDR funcaddr; + int struct_return; + + value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); + if (!value_type) + fatal ("internal: finish_command: function has no target type"); + + if (TYPE_CODE (value_type) == TYPE_CODE_VOID) + { + do_exec_cleanups (ALL_CLEANUPS); + return; + } + + funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); + + struct_return = using_struct_return (value_of_variable (function, NULL), + + funcaddr, + check_typedef (value_type), + BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))); + + if (!struct_return) + { + val = value_being_returned (value_type, stop_registers, struct_return); + printf_filtered ("Value returned is $%d = ", record_latest_value (val)); + value_print (val, gdb_stdout, 0, Val_no_prettyprint); + printf_filtered ("\n"); + } + else + { + /* We cannot determine the contents of the structure because + it is on the stack, and we don't know where, since we did not + initiate the call, as opposed to the call_function_by_hand case */ +#ifdef VALUE_RETURNED_FROM_STACK + val = 0; + printf_filtered ("Value returned has type: %s.", + TYPE_NAME (value_type)); + printf_filtered (" Cannot determine contents\n"); +#else + val = value_being_returned (value_type, stop_registers, + struct_return); + printf_filtered ("Value returned is $%d = ", + record_latest_value (val)); + value_print (val, gdb_stdout, 0, Val_no_prettyprint); + printf_filtered ("\n"); +#endif + + } + } + do_exec_cleanups (ALL_CLEANUPS); +} + /* "finish": Set a temporary breakpoint at the place the selected frame will return to, then continue. */ @@ -752,6 +956,26 @@ finish_command (arg, from_tty) register struct symbol *function; struct breakpoint *breakpoint; struct cleanup *old_chain; + struct continuation_arg *arg1, *arg2; + + int async_exec = 0; + + /* Find out whether we must run in the background. */ + if (arg != NULL) + async_exec = strip_bg_char (&arg); + + /* If we must run in the background, but the target can't do it, + error out. */ + if (async_p && async_exec && !target_has_async) + error ("Asynchronous execution not supported on this target."); + + /* If we are not asked to run in the bg, then prepare to run in the + foreground, synchronously. */ + if (async_p && !async_exec && target_has_async) + { + /* Simulate synchronous execution */ + sync_execution = 1; + } if (arg) error ("The \"finish\" command does not take any arguments."); @@ -771,7 +995,10 @@ finish_command (arg, from_tty) breakpoint = set_momentary_breakpoint (sal, frame, bp_finish); - old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); + if (!async_p || !target_has_async) + old_chain = make_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); + else + make_exec_cleanup ((make_cleanup_func) delete_breakpoint, breakpoint); /* Find the function we will return from. */ @@ -785,62 +1012,89 @@ finish_command (arg, from_tty) print_stack_frame (selected_frame, selected_frame_level, 0); } + /* If running asynchronously and the target support asynchronous + execution, set things up for the rest of the finish command to be + completed later on, when gdb has detected that the target has + stopped, in fetch_inferior_event. */ + if (async_p && target_has_async) + { + arg1 = + (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); + arg2 = + (struct continuation_arg *) xmalloc (sizeof (struct continuation_arg)); + arg1->next = arg2; + arg2->next = NULL; + arg1->data = (PTR) breakpoint; + arg2->data = (PTR) function; + add_continuation (finish_command_continuation, arg1); + } + proceed_to_finish = 1; /* We want stop_registers, please... */ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); - /* Did we stop at our breakpoint? */ - if (bpstat_find_breakpoint(stop_bpstat, breakpoint) != NULL - && function != 0) - { - struct type *value_type; - register value_ptr val; - CORE_ADDR funcaddr; - int struct_return; + /* Do this only if not running asynchronously or if the target + cannot do async execution. Otherwise, complete this command when + the target actually stops, in fetch_inferior_event.*/ + if (!async_p || !target_has_async) + { - value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); - if (!value_type) - fatal ("internal: finish_command: function has no target type"); - - if (TYPE_CODE (value_type) == TYPE_CODE_VOID) - return; + /* Did we stop at our breakpoint? */ + if (bpstat_find_breakpoint(stop_bpstat, breakpoint) != NULL + && function != 0) + { + struct type *value_type; + register value_ptr val; + CORE_ADDR funcaddr; + int struct_return; - funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); + value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); + if (!value_type) + fatal ("internal: finish_command: function has no target type"); - struct_return = using_struct_return (value_of_variable (function, NULL), + /* FIXME: Shouldn't we do the cleanups before returning? */ + if (TYPE_CODE (value_type) == TYPE_CODE_VOID) + return; + + funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function)); + struct_return = + using_struct_return (value_of_variable (function, NULL), funcaddr, check_typedef (value_type), - BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))); - - if (!struct_return) - { - val = value_being_returned (value_type, stop_registers, struct_return); - printf_filtered ("Value returned is $%d = ", record_latest_value (val)); - value_print (val, gdb_stdout, 0, Val_no_prettyprint); - printf_filtered ("\n"); - } - else - { - /* elz: we cannot determine the contents of the structure because - it is on the stack, and we don't know where, since we did not - initiate the call, as opposed to the call_function_by_hand case */ + BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))); + + if (!struct_return) + { + val = + value_being_returned (value_type, stop_registers, struct_return); + printf_filtered ("Value returned is $%d = ", + record_latest_value (val)); + value_print (val, gdb_stdout, 0, Val_no_prettyprint); + printf_filtered ("\n"); + } + else + { + /* We cannot determine the contents of the structure + because it is on the stack, and we don't know + where, since we did not initiate the call, as + opposed to the call_function_by_hand case */ #ifdef VALUE_RETURNED_FROM_STACK - val = 0; - printf_filtered ("Value returned has type: %s.", - TYPE_NAME (value_type)); - printf_filtered (" Cannot determine contents\n"); + val = 0; + printf_filtered ("Value returned has type: %s.", + TYPE_NAME (value_type)); + printf_filtered (" Cannot determine contents\n"); #else - val = value_being_returned (value_type, stop_registers, - struct_return); - printf_filtered ("Value returned is $%d = ", - record_latest_value (val)); - value_print (val, gdb_stdout, 0, Val_no_prettyprint); - printf_filtered ("\n"); -#endif - + val = value_being_returned (value_type, stop_registers, + struct_return); + printf_filtered ("Value returned is $%d = ", + record_latest_value (val)); + value_print (val, gdb_stdout, 0, Val_no_prettyprint); + printf_filtered ("\n"); +#endif + } + } + do_cleanups(old_chain); } - } - do_cleanups(old_chain); } /* ARGSUSED */ @@ -1355,6 +1609,20 @@ detach_command (args, from_tty) #endif } +/* Stop the execution of the target while running in async mode, in + the backgound. */ +static void +interrupt_target_command (args, from_tty) + char *args; + int from_tty; +{ + if (async_p && target_has_async) + { + dont_repeat (); /* Not for the faint of heart */ + target_stop (); + } +} + /* ARGSUSED */ static void float_info (addr_exp, from_tty) @@ -1530,6 +1798,9 @@ use \"set args\" without arguments."); add_com ("R", class_run, run_no_args_command, "Start debugged program with no arguments."); + add_com ("interrupt", class_run, interrupt_target_command, + "Interrupt the execution of the debugged program."); + add_info ("registers", nofp_registers_info, "List of integer registers and their contents, for selected stack frame.\n\ Register name as argument means describe only that register."); diff --git a/gdb/inferior.h b/gdb/inferior.h index b87bca9899d..9ba86c7a623 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -71,6 +71,17 @@ extern char *inferior_io_terminal; extern int inferior_pid; +/* Is the inferior running right now, as a result of a 'run&', + 'continue&' etc command? This is used in asycn gdb to determine + whether a command that the user enters while the target is running + is allowed or not. */ +extern int target_executing; + +/* Are we simulating synchronous execution? This is used in async gdb + to implement the 'run', 'continue' etc commands, which will not + redisplay the prompt until the execution is actually over. */ +extern int sync_execution; + /* This is only valid when inferior_pid is non-zero. If this is 0, then exec events should be noticed and responded to @@ -148,6 +159,8 @@ extern void generic_target_write_fp PARAMS ((CORE_ADDR)); extern void wait_for_inferior PARAMS ((void)); +extern void fetch_inferior_event PARAMS ((void)); + extern void init_wait_for_inferior PARAMS ((void)); extern void close_exec_file PARAMS ((void)); diff --git a/gdb/infrun.c b/gdb/infrun.c index 339acf826b4..80cc89157ad 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -32,8 +32,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "annotate.h" #include "symfile.h" /* for overlay functions */ #include "top.h" - #include +#include "event-loop.h" /* Prototypes for local functions */ @@ -53,9 +53,14 @@ static void delete_breakpoint_current_contents PARAMS ((PTR)); static void set_follow_fork_mode_command PARAMS ((char *arg, int from_tty, struct cmd_list_element *c)); +static void complete_execution PARAMS ((void)); + int inferior_ignoring_startup_exec_events = 0; int inferior_ignoring_leading_exec_events = 0; +/* In asynchronous mode, but simulating synchronous execution. */ +int sync_execution = 0; + /* wait_for_inferior and normal_stop use this to notify the user when the inferior stopped in a different thread than it had been running in. */ @@ -1006,9 +1011,13 @@ The same program may be running in another process."); /* Wait for it to stop (if not standalone) and in any case decode why it stopped, and act accordingly. */ - - wait_for_inferior (); - normal_stop (); + /* Do this only if we are not using the event loop, or if the target + does not support asynchronous execution. */ + if (!async_p || !target_has_async) + { + wait_for_inferior (); + normal_stop (); + } } /* Record the pc and sp of the program the last time it stopped. @@ -1021,7 +1030,6 @@ static char *prev_func_name; /* Start remote-debugging of a machine over a serial link. */ - void start_remote () { @@ -1029,8 +1037,24 @@ start_remote () init_wait_for_inferior (); stop_soon_quietly = 1; trap_expected = 0; - wait_for_inferior (); - normal_stop (); + + /* Go on waiting only in case gdb is not started in async mode, or + in case the target doesn't support async execution. */ + if (!async_p || !target_has_async) + { + wait_for_inferior (); + normal_stop (); + } + else + { + /* The 'tar rem' command should always look synchronous, + i.e. display the prompt only once it has connected and + started the target. */ + sync_execution = 1; + push_prompt ("", "", ""); + delete_file_handler (input_fd); + target_executing = 1; + } } /* Initialize static vars when a new inferior begins. */ @@ -1179,6 +1203,72 @@ wait_for_inferior () do_cleanups (old_cleanups); } +/* Asynchronous version of wait_for_inferior. It is called by the + event loop whenever a change of state is detected on the file + descriptor corresponding to the target. It can be called more than + once to complete a single execution command. In such cases we need + to keep the state in a global variable ASYNC_ECSS. If it is the + last time that this function is called for a single execution + command, then report to the user that the inferior has stopped, and + do the necessary cleanups. */ + +struct execution_control_state async_ecss; +struct execution_control_state *async_ecs; + +void +fetch_inferior_event () +{ + static struct cleanup *old_cleanups; + + async_ecs = &async_ecss; + + if (!async_ecs->wait_some_more) + { + old_cleanups = make_exec_cleanup (delete_breakpoint_current_contents, + &step_resume_breakpoint); + make_exec_cleanup (delete_breakpoint_current_contents, + &through_sigtramp_breakpoint); + + /* Fill in with reasonable starting values. */ + init_execution_control_state (async_ecs); + + thread_step_needed = 0; + + /* We'll update this if & when we switch to a new thread. */ + if (may_switch_from_inferior_pid) + switched_from_inferior_pid = inferior_pid; + + overlay_cache_invalid = 1; + + /* We have to invalidate the registers BEFORE calling target_wait + because they can be loaded from the target while in target_wait. + This makes remote debugging a bit more efficient for those + targets that provide critical registers as part of their normal + status mechanism. */ + + registers_changed (); + } + + if (target_wait_hook) + async_ecs->pid = target_wait_hook (async_ecs->waiton_pid, async_ecs->wp); + else + async_ecs->pid = target_wait (async_ecs->waiton_pid, async_ecs->wp); + + /* Now figure out what to do with the result of the result. */ + handle_inferior_event (async_ecs); + + if (!async_ecs->wait_some_more) + { + do_exec_cleanups (old_cleanups); + normal_stop (); + /* Is there anything left to do for the command issued to + complete? */ + do_all_continuations (); + /* Reset things after target has stopped for the async commands. */ + complete_execution (); + } +} + /* Prepare an execution control state for looping through a wait_for_inferior-type loop. */ @@ -3011,6 +3101,25 @@ stopped_for_shlib_catchpoint (bs, cp_p) } +/* Reset proper settings after an asynchronous command has finished. + If the execution command was in synchronous mode, register stdin + with the event loop, and reset the prompt. */ +static void +complete_execution () +{ +extern cleanup_sigint_signal_handler PARAMS ((void)); + + if (sync_execution) + { + add_file_handler (input_fd, (file_handler_func *) call_readline, 0); + pop_prompt (); + sync_execution = 0; + cleanup_sigint_signal_handler (); + display_gdb_prompt (0); + } + target_executing = 0; +} + /* Here to return control to GDB when the inferior stops for real. Print appropriate messages, remove breakpoints, give terminal our modes. diff --git a/gdb/main.c b/gdb/main.c index 09f4cff0f1e..b5daec3a018 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -62,6 +62,7 @@ int dbx_commands = 0; GDB_FILE *gdb_stdout; GDB_FILE *gdb_stderr; GDB_FILE *gdb_stdlog; +GDB_FILE *gdb_stdtarg; /* Whether to enable writing into executable and core files */ extern int write_files; @@ -163,10 +164,12 @@ main (argc, argv) gdb_stdout = stdio_fileopen (stdout); gdb_stderr = stdio_fileopen (stderr); gdb_stdlog = gdb_stderr; /* for moment */ + gdb_stdtarg = gdb_stderr; /* for moment */ #else gdb_stdout = tui_fileopen (stdout); gdb_stderr = tui_fileopen (stderr); gdb_stdlog = gdb_stdout; /* for moment */ + gdb_stdtarg = gdb_stderr; /* for moment */ #endif /* Parse arguments and options. */ diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c index a0113edc892..c758d774855 100644 --- a/gdb/mn10300-tdep.c +++ b/gdb/mn10300-tdep.c @@ -275,7 +275,9 @@ mn10300_analyze_prologue (fi, pc) /* Do nothing if we couldn't find the start of this function or if we're stopped at the first instruction in the prologue. */ if (status == 0) - return pc; + { + return pc; + } /* If we're in start, then give up. */ if (strcmp (name, "start") == 0) diff --git a/gdb/remote-os9k.c b/gdb/remote-os9k.c index 2abfa837683..714400f57d5 100644 --- a/gdb/remote-os9k.c +++ b/gdb/remote-os9k.c @@ -1,5 +1,5 @@ /* Remote debugging interface for boot monitors, for GDB. - Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -40,14 +40,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gdbcore.h" #include "target.h" #include "wait.h" + #ifdef ANSI_PROTOTYPES #include #else #include #endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif #include -#include "gdb_string.h" #include + +#include "gdb_string.h" #include "command.h" #include "serial.h" #include "monitor.h" diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c index b8ced919847..8923aec658d 100644 --- a/gdb/remote-sim.c +++ b/gdb/remote-sim.c @@ -197,10 +197,7 @@ gdb_os_write_stdout (p, buf, len) { b[0] = buf[i]; b[1] = 0; - if (target_output_hook) - target_output_hook (b); - else - fputs_filtered (b, gdb_stdout); + fputs_unfiltered (b, gdb_stdtarg); } return len; } @@ -229,10 +226,7 @@ gdb_os_write_stderr (p, buf, len) { b[0] = buf[i]; b[1] = 0; - if (target_output_hook) - target_output_hook (b); - else - fputs_filtered (b, gdb_stderr); + fputs_unfiltered (b, gdb_stdtarg); } return len; } diff --git a/gdb/remote-st.c b/gdb/remote-st.c index 1efdbfac027..108fa9618c3 100644 --- a/gdb/remote-st.c +++ b/gdb/remote-st.c @@ -1,5 +1,5 @@ /* Remote debugging interface for Tandem ST2000 phone switch, for GDB. - Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1999 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus. This file is part of GDB. @@ -38,14 +38,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gdbcore.h" #include "target.h" #include "wait.h" + #ifdef ANSI_PROTOTYPES #include #else #include #endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif #include -#include "gdb_string.h" #include + +#include "gdb_string.h" #include "serial.h" extern struct target_ops st2000_ops; /* Forward declaration */ diff --git a/gdb/remote.c b/gdb/remote.c index 8fadca8c415..a88194cf324 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1,5 +1,5 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright 1988, 91, 92, 93, 94, 95, 96, 97, 1998 + Copyright 1988, 91, 92, 93, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -219,10 +219,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#include "event-loop.h" + #include #include "serial.h" /* Prototypes for local functions */ +static void initialize_sigint_signal_handler PARAMS ((void)); +static void handle_remote_sigint PARAMS ((int)); +static void handle_remote_sigint_twice PARAMS ((int)); +static void async_remote_interrupt PARAMS ((gdb_client_data)); +static void async_remote_interrupt_twice PARAMS ((gdb_client_data)); + +static void set_extended_protocol PARAMS ((struct continuation_arg *)); static void build_remote_gdbarch_data PARAMS ((void)); @@ -244,15 +257,21 @@ static void remote_fetch_registers PARAMS ((int regno)); static void remote_resume PARAMS ((int pid, int step, enum target_signal siggnal)); +static void remote_async_resume PARAMS ((int pid, int step, + enum target_signal siggnal)); static int remote_start_remote PARAMS ((PTR)); static void remote_open PARAMS ((char *name, int from_tty)); +static void remote_async_open PARAMS ((char *name, int from_tty)); static void extended_remote_open PARAMS ((char *name, int from_tty)); +static void extended_remote_async_open PARAMS ((char *name, int from_tty)); static void remote_open_1 PARAMS ((char *, int, struct target_ops *, int extended_p)); +static void remote_async_open_1 PARAMS ((char *, int, struct target_ops *, + int extended_p)); static void remote_close PARAMS ((int quitting)); @@ -265,6 +284,7 @@ static void extended_remote_restart PARAMS ((void)); static void extended_remote_mourn PARAMS ((void)); static void extended_remote_create_inferior PARAMS ((char *, char *, char **)); +static void extended_remote_async_create_inferior PARAMS ((char *, char *, char **)); static void remote_mourn_1 PARAMS ((struct target_ops *)); @@ -273,12 +293,15 @@ static void remote_send PARAMS ((char *buf)); static int readchar PARAMS ((int timeout)); static int remote_wait PARAMS ((int pid, struct target_waitstatus * status)); +static int remote_async_wait PARAMS ((int pid, struct target_waitstatus * status)); static void remote_kill PARAMS ((void)); +static void remote_async_kill PARAMS ((void)); static int tohex PARAMS ((int nib)); static void remote_detach PARAMS ((char *args, int from_tty)); +static void remote_async_detach PARAMS ((char *args, int from_tty)); static void remote_interrupt PARAMS ((int signo)); @@ -362,6 +385,12 @@ static struct target_ops remote_ops; static struct target_ops extended_remote_ops; +/* Temporary target ops. Just like the remote_ops and + extended_remote_ops, but with asynchronous support. */ +static struct target_ops remote_async_ops; + +static struct target_ops extended_async_remote_ops; + /* This was 5 seconds, which is a long time to sit and wait. Unless this is going though some terminal server or multiplexer or other form of hairy serial connection, I would think 2 seconds would @@ -444,6 +473,10 @@ static int remote_register_buf_size = 0; doesn't support 'P', the only consequence is some unnecessary traffic. */ static int stub_supports_P = 1; +/* Tokens for use by the asynchronous signal handlers for SIGINT */ +PTR sigint_remote_twice_token; +PTR sigint_remote_token; + /* These are pointers to hook functions that may be set in order to modify resume/wait behavior for a particular architecture. */ @@ -1604,6 +1637,15 @@ remote_open (name, from_tty) remote_open_1 (name, from_tty, &remote_ops, 0); } +/* Just like remote_open, but with asynchronous support. */ +static void +remote_async_open (name, from_tty) + char *name; + int from_tty; +{ + remote_async_open_1 (name, from_tty, &remote_async_ops, 0); +} + /* Open a connection to a remote debugger using the extended remote gdb protocol. NAME is the filename used for communication. */ @@ -1615,6 +1657,15 @@ extended_remote_open (name, from_tty) remote_open_1 (name, from_tty, &extended_remote_ops, 1/*extended_p*/); } +/* Just like extended_remote_open, but with asynchronous support. */ +static void +extended_remote_async_open (name, from_tty) + char *name; + int from_tty; +{ + remote_async_open_1 (name, from_tty, &extended_async_remote_ops, 1/*extended_p*/); +} + /* Generic code for opening a connection to a remote target. */ static DCACHE *remote_dcache; @@ -1649,7 +1700,6 @@ serial device is attached to the remote system (e.g. /dev/ttya)."); } } - SERIAL_RAW (remote_desc); /* If there is something sitting in the buffer we might take it as a @@ -1705,6 +1755,124 @@ serial device is attached to the remote system (e.g. /dev/ttya)."); } } +/* Just like remote_open but with asynchronous support. */ +static void +remote_async_open_1 (name, from_tty, target, extended_p) + char *name; + int from_tty; + struct target_ops *target; + int extended_p; +{ + if (name == 0) + error ("To open a remote debug connection, you need to specify what\n\ +serial device is attached to the remote system (e.g. /dev/ttya)."); + + target_preopen (from_tty); + + unpush_target (target); + + remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes); + + remote_desc = SERIAL_OPEN (name); + if (!remote_desc) + perror_with_name (name); + + if (baud_rate != -1) + { + if (SERIAL_SETBAUDRATE (remote_desc, baud_rate)) + { + SERIAL_CLOSE (remote_desc); + perror_with_name (name); + } + } + + SERIAL_RAW (remote_desc); + + /* If there is something sitting in the buffer we might take it as a + response to a command, which would be bad. */ + SERIAL_FLUSH_INPUT (remote_desc); + + if (from_tty) + { + puts_filtered ("Remote debugging using "); + puts_filtered (name); + puts_filtered ("\n"); + } + + /* If running in asynchronous mode, register the target with the + event loop. Set things up so that when there is an event on the + file descriptor, the event loop will call fetch_inferior_event, + which will do the proper analysis to determine what happened. */ + if (async_p) + add_file_handler (remote_desc->fd, (file_handler_func *) fetch_inferior_event, 0); + + push_target (target); /* Switch to using remote target now */ + + /* Start out by trying the 'P' request to set registers. We set + this each time that we open a new target so that if the user + switches from one stub to another, we can (if the target is + closed and reopened) cope. */ + stub_supports_P = 1; + + general_thread = -2; + continue_thread = -2; + + /* Force remote_write_bytes to check whether target supports + binary downloading. */ + remote_binary_checked = 0; + + /* If running asynchronously, set things up for telling the target + to use the extended protocol. This will happen only after the + target has been connected to, in fetch_inferior_event. */ + if (extended_p && async_p) + add_continuation (set_extended_protocol, NULL); + + /* Without this, some commands which require an active target (such + as kill) won't work. This variable serves (at least) double duty + as both the pid of the target process (if it has such), and as a + flag indicating that a target is active. These functions should + be split out into seperate variables, especially since GDB will + someday have a notion of debugging several processes. */ + + inferior_pid = MAGIC_NULL_PID; + /* Start the remote connection; if error (0), discard this target. + In particular, if the user quits, be sure to discard it + (we'd be in an inconsistent state otherwise). */ + if (!catch_errors (remote_start_remote, NULL, + "Couldn't establish connection to remote target\n", + RETURN_MASK_ALL)) + { + /* Unregister the file descriptor from the event loop. */ + if (async_p) + delete_file_handler (remote_desc->fd); + pop_target (); + return; + } + + if (!async_p) + { + if (extended_p) + { + /* tell the remote that we're using the extended protocol. */ + char *buf = alloca (PBUFSIZ); + putpkt ("!"); + getpkt (buf, 0); + } + } +} + +/* This will be called by fetch_inferior_event, via the + cmd_continuation pointer, only after the target has stopped. */ +static void +set_extended_protocol (arg) + struct continuation_arg * arg; +{ + /* tell the remote that we're using the extended protocol. */ + char *buf = alloca (PBUFSIZ); + putpkt ("!"); + getpkt (buf, 0); +} + /* This takes a program previously attached to and detaches it. After this is done, GDB can be used to debug some other program. We better not have left any breakpoints in the target program or it'll @@ -1729,6 +1897,30 @@ remote_detach (args, from_tty) puts_filtered ("Ending remote debugging.\n"); } +/* Same as remote_detach, but with async support. */ +static void +remote_async_detach (args, from_tty) + char *args; + int from_tty; +{ + char *buf = alloca (PBUFSIZ); + + if (args) + error ("Argument given to \"detach\" when remotely debugging."); + + /* Tell the remote target to detach. */ + strcpy (buf, "D"); + remote_send (buf); + + /* Unregister the file descriptor from the event loop. */ + if (async_p) + delete_file_handler (remote_desc->fd); + + pop_target (); + if (from_tty) + puts_filtered ("Ending remote debugging.\n"); +} + /* Convert hex digit A to a number. */ int @@ -1797,10 +1989,134 @@ remote_resume (pid, step, siggnal) putpkt (buf); } + +/* Same as remote_resume, but with async support. */ +static void +remote_async_resume (pid, step, siggnal) + int pid, step; + enum target_signal siggnal; +{ + char *buf = alloca (PBUFSIZ); + + if (pid == -1) + set_thread (0, 0); /* run any thread */ + else + set_thread (pid, 0); /* run this thread */ + + dcache_flush (remote_dcache); + + last_sent_signal = siggnal; + last_sent_step = step; + + /* A hook for when we need to do something at the last moment before + resumption. */ + if (target_resume_hook) + (*target_resume_hook) (); + + /* Set things up before execution starts for async commands. */ + /* This function can be entered more than once for the same execution + command, because it is also called by handle_inferior_event. So + we make sure that we don't do the initialization for sync + execution more than once. */ + if (async_p && !target_executing) + { + target_executing = 1; + + /* If the command must look synchronous, fake it, by making gdb + display an empty prompt after the command has completed. Also + disable input. */ + if (sync_execution) + { + push_prompt ("", "", ""); + delete_file_handler (input_fd); + initialize_sigint_signal_handler (); + } + } + + if (siggnal != TARGET_SIGNAL_0) + { + buf[0] = step ? 'S' : 'C'; + buf[1] = tohex (((int)siggnal >> 4) & 0xf); + buf[2] = tohex ((int)siggnal & 0xf); + buf[3] = '\0'; + } + else + strcpy (buf, step ? "s": "c"); + + putpkt (buf); +} + +/* Set up the signal handler for SIGINT, while the target is + executing, ovewriting the 'regular' SIGINT signal handler. */ +static void +initialize_sigint_signal_handler () +{ + sigint_remote_token = + create_async_signal_handler (async_remote_interrupt, NULL); + signal (SIGINT, handle_remote_sigint); +} + +/* Signal handler for SIGINT, while the target is executing. */ +static void +handle_remote_sigint (sig) + int sig; +{ + signal (sig, handle_remote_sigint_twice); + sigint_remote_twice_token = + create_async_signal_handler (async_remote_interrupt_twice, NULL); + mark_async_signal_handler_wrapper (sigint_remote_token); +} + +/* Signal handler for SIGINT, installed after SIGINT has already been + sent once. It will take effect the second time that the user sends + a ^C. */ +static void +handle_remote_sigint_twice (sig) + int sig; +{ + signal (sig, handle_sigint); + sigint_remote_twice_token = + create_async_signal_handler (async_remote_interrupt, NULL); + mark_async_signal_handler_wrapper (sigint_remote_twice_token); +} + +/* Perform the real interruption of hte target execution, in response + to a ^C. */ +static void +async_remote_interrupt (arg) + gdb_client_data arg; +{ + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n"); + + target_stop (); +} + +/* Perform interrupt, if the first attempt did not succeed. Just give + up on the target alltogether. */ +static void +async_remote_interrupt_twice (arg) + gdb_client_data arg; +{ + interrupt_query (); + signal (SIGINT, handle_remote_sigint); +} + +/* Reinstall the usual SIGINT handlers, after the target has + stopped. */ +void +cleanup_sigint_signal_handler () +{ + signal (SIGINT, handle_sigint); + if (sigint_remote_twice_token) + delete_async_signal_handler ((async_signal_handler**) &sigint_remote_twice_token); + if (sigint_remote_token) + delete_async_signal_handler ((async_signal_handler**) &sigint_remote_token); +} + /* Send ^C to target to halt it. Target will respond, and send us a packet. */ - static void (*ofunc) PARAMS ((int)); /* The command line interface's stop routine. This function is installed @@ -1875,16 +2191,13 @@ remote_console_output (msg) { char *p; - for (p = msg; *p; p +=2) + for (p = msg; p[0] && p[1]; p +=2) { char tb[2]; char c = fromhex (p[0]) * 16 + fromhex (p[1]); tb[0] = c; tb[1] = 0; - if (target_output_hook) - target_output_hook (tb); - else - fputs_filtered (tb, gdb_stdout); + fputs_unfiltered (tb, gdb_stdtarg); } } @@ -2109,6 +2422,225 @@ Packet Dropped"); return inferior_pid; } +/* Async version of remote_wait. */ +static int +remote_async_wait (pid, status) + int pid; + struct target_waitstatus *status; +{ + unsigned char *buf = alloca (PBUFSIZ); + int thread_num = -1; + + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = 0; + + while (1) + { + unsigned char *p; + + if (!async_p) + ofunc = signal (SIGINT, remote_interrupt); + getpkt ((char *) buf, 1); + if (!async_p) + signal (SIGINT, ofunc); + + /* This is a hook for when we need to do something (perhaps the + collection of trace data) every time the target stops. */ + if (target_wait_loop_hook) + (*target_wait_loop_hook) (); + + switch (buf[0]) + { + case 'E': /* Error of some sort */ + warning ("Remote failure reply: %s", buf); + continue; + case 'T': /* Status with PC, SP, FP, ... */ + { + int i; + long regno; + char regs[MAX_REGISTER_RAW_SIZE]; + + /* Expedited reply, containing Signal, {regno, reg} repeat */ + /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where + ss = signal number + n... = register number + r... = register contents + */ + p = &buf[3]; /* after Txx */ + + while (*p) + { + unsigned char *p1; + char *p_temp; + + /* Read the register number */ + regno = strtol ((const char *) p, &p_temp, 16); + p1 = (unsigned char *)p_temp; + + if (p1 == p) /* No register number present here */ + { + p1 = (unsigned char *) strchr ((const char *) p, ':'); + if (p1 == NULL) + warning ("Malformed packet(a) (missing colon): %s\n\ +Packet: '%s'\n", + p, buf); + if (strncmp ((const char *) p, "thread", p1 - p) == 0) + { + p_temp = unpack_varlen_hex (++p1, &thread_num); + record_currthread (thread_num); + p = (unsigned char *) p_temp; + } + } + else + { + p = p1; + + if (*p++ != ':') + warning ("Malformed packet(b) (missing colon): %s\n\ +Packet: '%s'\n", + p, buf); + + if (regno >= NUM_REGS) + warning ("Remote sent bad register number %ld: %s\n\ +Packet: '%s'\n", + regno, p, buf); + + for (i = 0; i < REGISTER_RAW_SIZE (regno); i++) + { + if (p[0] == 0 || p[1] == 0) + warning ("Remote reply is too short: %s", buf); + regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); + p += 2; + } + supply_register (regno, regs); + } + + if (*p++ != ';') + { + warning ("Remote register badly formatted: %s", buf); + warning (" here: %s",p); + } + } + } + /* fall through */ + case 'S': /* Old style status, just signal only */ + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = (enum target_signal) + (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); + + if (buf[3] == 'p') + { + /* Export Cisco kernel mode as a convenience variable + (so that it can be used in the GDB prompt if desired). */ + + if (cisco_kernel_mode == 1) + set_internalvar (lookup_internalvar ("cisco_kernel_mode"), + value_from_string ("PDEBUG-")); + cisco_kernel_mode = 0; + thread_num = strtol ((const char *) &buf[4], NULL, 16); + record_currthread (thread_num); + } + else if (buf[3] == 'k') + { + /* Export Cisco kernel mode as a convenience variable + (so that it can be used in the GDB prompt if desired). */ + + if (cisco_kernel_mode == 1) + set_internalvar (lookup_internalvar ("cisco_kernel_mode"), + value_from_string ("KDEBUG-")); + cisco_kernel_mode = 1; + } + goto got_status; + case 'N': /* Cisco special: status and offsets */ + { + bfd_vma text_addr, data_addr, bss_addr; + bfd_signed_vma text_off, data_off, bss_off; + unsigned char *p1; + + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = (enum target_signal) + (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); + + if (symfile_objfile == NULL) + { + warning ("Relocation packet recieved with no symbol file. \ +Packet Dropped"); + goto got_status; + } + + /* Relocate object file. Buffer format is NAATT;DD;BB + * where AA is the signal number, TT is the new text + * address, DD * is the new data address, and BB is the + * new bss address. */ + + p = &buf[3]; + text_addr = strtoul (p, (char **) &p1, 16); + if (p1 == p || *p1 != ';') + warning ("Malformed relocation packet: Packet '%s'", buf); + p = p1 + 1; + data_addr = strtoul (p, (char **) &p1, 16); + if (p1 == p || *p1 != ';') + warning ("Malformed relocation packet: Packet '%s'", buf); + p = p1 + 1; + bss_addr = strtoul (p, (char **) &p1, 16); + if (p1 == p) + warning ("Malformed relocation packet: Packet '%s'", buf); + + if (remote_cisco_section_offsets (text_addr, data_addr, bss_addr, + &text_off, &data_off, &bss_off) + == 0) + if (text_off != 0 || data_off != 0 || bss_off != 0) + remote_cisco_objfile_relocate (text_off, data_off, bss_off); + + goto got_status; + } + case 'W': /* Target exited */ + { + /* The remote process exited. */ + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]); + goto got_status; + } + case 'X': + status->kind = TARGET_WAITKIND_SIGNALLED; + status->value.sig = (enum target_signal) + (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); + kill_kludge = 1; + + goto got_status; + case 'O': /* Console output */ + remote_console_output (buf + 1); + continue; + case '\0': + if (last_sent_signal != TARGET_SIGNAL_0) + { + /* Zero length reply means that we tried 'S' or 'C' and + the remote system doesn't support it. */ + target_terminal_ours_for_output (); + printf_filtered + ("Can't send signals to this remote system. %s not sent.\n", + target_signal_to_name (last_sent_signal)); + last_sent_signal = TARGET_SIGNAL_0; + target_terminal_inferior (); + + strcpy ((char *) buf, last_sent_step ? "s" : "c"); + putpkt ((char *) buf); + continue; + } + /* else fallthrough */ + default: + warning ("Invalid remote reply: %s", buf); + continue; + } + } + got_status: + if (thread_num != -1) + { + return thread_num; + } + return inferior_pid; +} + /* Number of bytes of registers this stub implements. */ static int register_bytes_found; @@ -2792,7 +3324,7 @@ putpkt_binary (buf, cnt) /* Copy the packet into buffer BUF2, encapsulating it and giving it a checksum. */ - if (cnt > (int) sizeof (buf2) - 5) /* Prosanity check */ + if (cnt > BUFSIZ - 5) /* Prosanity check */ abort (); p = buf2; @@ -3116,6 +3648,32 @@ remote_kill () target_mourn_inferior (); } +/* Async version of remote_kill. */ +static void +remote_async_kill () +{ + /* Unregister the file descriptor from the event loop. */ + if (async_p) + delete_file_handler (remote_desc->fd); + + /* For some mysterious reason, wait_for_inferior calls kill instead of + mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */ + if (kill_kludge) + { + kill_kludge = 0; + target_mourn_inferior (); + return; + } + + /* Use catch_errors so the user can quit from gdb even when we aren't on + speaking terms with the remote system. */ + catch_errors ((catch_errors_ftype*) putpkt, "k", "", RETURN_MASK_ERROR); + + /* Don't wait for it to die. I'm not really sure it matters whether + we do or not. For the existing stubs, kill is a noop. */ + target_mourn_inferior (); +} + static void remote_mourn () { @@ -3175,6 +3733,36 @@ extended_remote_create_inferior (exec_file, args, env) proceed (-1, TARGET_SIGNAL_0, 0); } +/* Async version of extended_remote_create_inferior. */ +static void +extended_remote_async_create_inferior (exec_file, args, env) + char *exec_file; + char *args; + char **env; +{ + /* Rip out the breakpoints; we'll reinsert them after restarting + the remote server. */ + remove_breakpoints (); + + /* If running asynchronously, register the target file descriptor + with the event loop. */ + if (async_p) + add_file_handler (remote_desc->fd, (file_handler_func *) fetch_inferior_event, 0); + + /* Now restart the remote server. */ + extended_remote_restart (); + + /* Now put the breakpoints back in. This way we're safe if the + restart function works via a unix fork on the remote side. */ + insert_breakpoints (); + + /* Clean up from the last time we were running. */ + clear_proceed_status (); + + /* Let the remote process run. */ + proceed (-1, TARGET_SIGNAL_0, 0); +} + /* On some machines, e.g. 68k, we may use a different breakpoint instruction than other targets; in those use REMOTE_BREAKPOINT instead of just @@ -4103,13 +4691,75 @@ Specify the serial device it is connected to (e.g. host:2020)."; remote_cisco_ops.to_magic = OPS_MAGIC; } +/* Target async and target extended-async. + + This are temporary targets, until it is all tested. Eventually + async support will be incorporated int the usual 'remote' + target. */ + +static void +init_remote_async_ops () +{ + remote_async_ops.to_shortname = "async"; + remote_async_ops.to_longname = "Remote serial target in async version of the gdb-specific protocol"; + remote_async_ops.to_doc = + "Use a remote computer via a serial line, using a gdb-specific protocol.\n\ +Specify the serial device it is connected to (e.g. /dev/ttya)."; + remote_async_ops.to_open = remote_async_open; + remote_async_ops.to_close = remote_close; + remote_async_ops.to_detach = remote_async_detach; + remote_async_ops.to_resume = remote_async_resume; + remote_async_ops.to_wait = remote_async_wait; + remote_async_ops.to_fetch_registers = remote_fetch_registers; + remote_async_ops.to_store_registers = remote_store_registers; + remote_async_ops.to_prepare_to_store = remote_prepare_to_store; + remote_async_ops.to_xfer_memory = remote_xfer_memory; + remote_async_ops.to_files_info = remote_files_info; + remote_async_ops.to_insert_breakpoint = remote_insert_breakpoint; + remote_async_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_async_ops.to_kill = remote_async_kill; + remote_async_ops.to_load = generic_load; + remote_async_ops.to_mourn_inferior = remote_mourn; + remote_async_ops.to_thread_alive = remote_thread_alive; + remote_async_ops.to_find_new_threads = remote_threads_info; + remote_async_ops.to_stop = remote_stop; + remote_async_ops.to_query = remote_query; + remote_async_ops.to_stratum = process_stratum; + remote_async_ops.to_has_all_memory = 1; + remote_async_ops.to_has_memory = 1; + remote_async_ops.to_has_stack = 1; + remote_async_ops.to_has_registers = 1; + remote_async_ops.to_has_execution = 1; + remote_async_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */ + remote_async_ops.to_has_async_exec = 1; + remote_async_ops.to_magic = OPS_MAGIC; +} + +/* Set up the async extended remote vector by making a copy of the standard + remote vector and adding to it. */ + +static void +init_extended_async_remote_ops () +{ + extended_async_remote_ops = remote_async_ops; + + extended_async_remote_ops.to_shortname = "extended-async"; + extended_async_remote_ops.to_longname = + "Extended remote serial target in async gdb-specific protocol"; + extended_async_remote_ops.to_doc = + "Use a remote computer via a serial line, using an async gdb-specific protocol.\n\ +Specify the serial device it is connected to (e.g. /dev/ttya).", + extended_async_remote_ops.to_open = extended_remote_async_open; + extended_async_remote_ops.to_create_inferior = extended_remote_async_create_inferior; + extended_async_remote_ops.to_mourn_inferior = extended_remote_mourn; +} + static void build_remote_gdbarch_data () { tty_input = xmalloc (PBUFSIZ); } - void _initialize_remote () { @@ -4128,6 +4778,12 @@ _initialize_remote () init_extended_remote_ops (); add_target (&extended_remote_ops); + init_remote_async_ops (); + add_target (&remote_async_ops); + + init_extended_async_remote_ops (); + add_target (&extended_async_remote_ops); + init_remote_cisco_ops (); add_target (&remote_cisco_ops); diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c index e6443a08f5c..86c7f5ae701 100644 --- a/gdb/ser-tcp.c +++ b/gdb/ser-tcp.c @@ -1,5 +1,5 @@ /* Serial interface for raw TCP connections on Un*x like systems - Copyright 1992, 1993, 1998 Free Software Foundation, Inc. + Copyright 1992, 1993, 1998, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -33,6 +33,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif + #include "signals.h" #include "gdb_string.h" diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c index dc5236fbe66..50f28066176 100644 --- a/gdb/ser-unix.c +++ b/gdb/ser-unix.c @@ -1,5 +1,5 @@ /* Serial interface for local (hardwired) serial ports on Un*x like systems - Copyright 1992, 1993, 1994, 1998 Free Software Foundation, Inc. + Copyright 1992, 1993, 1994, 1998, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -26,6 +26,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif + #ifdef HAVE_TERMIOS struct hardwire_ttystate diff --git a/gdb/source.c b/gdb/source.c index 2d80b770646..ae5a9d0fbd4 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -276,7 +276,7 @@ directory_command (dirname, from_tty) /* FIXME, this goes to "delete dir"... */ if (dirname == 0) { - if (query ("Reinitialize source path to empty? ")) + if (from_tty && query ("Reinitialize source path to empty? ")) { free (source_path); init_source_path (); diff --git a/gdb/sparcl-tdep.c b/gdb/sparcl-tdep.c index e39bf306ec9..4c8ff97dc3e 100644 --- a/gdb/sparcl-tdep.c +++ b/gdb/sparcl-tdep.c @@ -1,5 +1,5 @@ /* Target dependent code for the Fujitsu SPARClite for GDB, the GNU debugger. - Copyright 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright 1994, 1995, 1996, 1999 Free Software Foundation, Inc. This file is part of GDB. @@ -24,6 +24,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "serial.h" #include +#ifdef HAVE_SYS_SELECT_H +#include +#endif + #if (!defined(__GO32__) && !defined(_WIN32)) || defined(__CYGWIN32__) #define HAVE_SOCKETS #include diff --git a/gdb/target.c b/gdb/target.c index d8899439660..a9217d887b2 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -535,6 +535,7 @@ update_current_target () INHERIT (to_has_registers, t); INHERIT (to_has_execution, t); INHERIT (to_has_thread_control, t); + INHERIT (to_has_async_exec, t); INHERIT (to_sections, t); INHERIT (to_sections_end, t); INHERIT (to_magic, t); diff --git a/gdb/target.h b/gdb/target.h index 30d33a2101d..16b2517aeaa 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -381,6 +381,7 @@ struct target_ops int to_has_registers; int to_has_execution; int to_has_thread_control; /* control thread execution */ + int to_has_async_exec; struct section_table *to_sections; struct section_table @@ -984,6 +985,10 @@ print_section_info PARAMS ((struct target_ops *, bfd *)); #define target_can_switch_threads \ (current_target.to_has_thread_control & tc_switch) +/* Does the target support asynchronous execution? */ +#define target_has_async \ + (current_target.to_has_async_exec) + extern void target_link PARAMS ((char *, CORE_ADDR *)); /* Converts a process id to a string. Usually, the string just contains diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 376c575e281..6e53b6743de 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +Tue Jun 29 11:56:06 1999 Andrew Cagney + + * lib/gdb.exp (gdb_expect_list): Output one message per pattern in + a consistent format. + 1999-06-25 Stan Shebs From Jimmy Guo and others at HP: diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index cb277bed822..3e71adcae6b 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -1105,38 +1105,44 @@ proc gdb_expect { args } { proc gdb_expect_list {test sentinal list} { global gdb_prompt set index 0 - while { ${index} >= 0 && ${index} < [llength ${list}] } { + set ok 1 + while { ${index} < [llength ${list}] } { set pattern [lindex ${list} ${index}] set index [expr ${index} + 1] if { ${index} == [llength ${list}] } { - gdb_expect { - -re "${pattern}${sentinal}" { - pass "${test} (sentinal)" - } - timeout { - fail "(timeout on sentinal) ${test}" - set index -1 + if { ${ok} } { + gdb_expect { + -re "${pattern}${sentinal}" { + pass "${test}, pattern ${index} + sentinal" + } + timeout { + fail "${test}, pattern ${index} + sentinal (timeout)" + set ok 0 + } } + } else { + fail "${test}, pattern ${index} + sentinal" } } else { - gdb_expect { - -re "${pattern}" { - pass "${test} (line ${index})" - } - -re "${sentinal}" { - fail "${test} (line ${index})" - set index -1 - } - timeout { - fail "(timeout on line ${index}) ${test}" - set index -1 + if { ${ok} } { + gdb_expect { + -re "${pattern}" { + pass "${test}, pattern ${index}" + } + -re "${sentinal}" { + fail "${test}, pattern ${index}" + set ok 0 + } + timeout { + fail "${test}, pattern ${index} (timeout)" + set ok 0 + } } + } else { + fail "${test}, pattern ${index}" } } } - if { ${index} >= 0 } { - pass "${test}" - } } # diff --git a/gdb/top.c b/gdb/top.c index fa0c9d0f01c..12b63754b8b 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -322,6 +322,12 @@ int remote_timeout = 20; /* Set default to 20 */ int remote_debug = 0; +/* Non-zero means the target is running. Note: this is different from + saying that there is an active target and we are stopped at a + breakpoint, for instance. This is a real indicator whether the + target is off and running, which gdb is doing something else. */ +int target_executing = 0; + /* Level of control structure. */ static int control_level; @@ -383,11 +389,6 @@ void (*command_loop_hook) PARAMS ((void)); void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, GDB_FILE *stream)); -/* Called when the target says something to the host, which may - want to appear in a different window. */ - -void (*target_output_hook) PARAMS ((char *)); - /* Called from print_frame_info to list the line we stopped in. */ void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, int line, @@ -486,6 +487,8 @@ return_to_top_level (reason) disable_current_display (); do_cleanups (ALL_CLEANUPS); + if (async_p && target_has_async) + do_exec_cleanups (ALL_CLEANUPS); if (annotation_level > 1) switch (reason) @@ -1266,6 +1269,16 @@ execute_command (p, from_tty) char *arg; c = lookup_cmd (&p, cmdlist, "", 0, 1); + + /* If the target is running, we allow only a limited set of + commands. */ + if (async_p && target_has_async && target_executing) + if (!strcmp (c->name, "help") + && !strcmp (c->name, "pwd") + && !strcmp (c->name, "show") + && !strcmp (c->name, "stop")) + error ("Cannot execute this command while the target is running."); + /* Pass null arg rather than an empty one. */ arg = *p ? p : 0; diff --git a/gdb/top.h b/gdb/top.h index 65085d93a1d..e05140ada9d 100644 --- a/gdb/top.h +++ b/gdb/top.h @@ -82,7 +82,6 @@ extern void set_prompt PARAMS ((char *)); /* From random places. */ extern int mapped_symbol_files; extern int readnow_symbol_files; -#define ALL_CLEANUPS ((struct cleanup *)0) /* Perform _initialize initialization */ extern void gdb_init PARAMS ((char *)); diff --git a/gdb/utils.c b/gdb/utils.c index 03f0aa4d996..26f05a75e01 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -92,6 +92,13 @@ set_width PARAMS ((void)); static struct cleanup *cleanup_chain; /* cleaned up after a failed command */ static struct cleanup *final_cleanup_chain; /* cleaned up when gdb exits */ static struct cleanup *run_cleanup_chain; /* cleaned up on each 'run' */ +static struct cleanup *exec_cleanup_chain; /* cleaned up on each execution command */ + +/* Pointer to what is left to do for an execution command after the + target stops. Used only in asynchronous mode, by targets that + support async execution. The finish and until commands use it. So + does the target extended-remote command. */ +struct continuation *cmd_continuation; /* Nonzero if we have job control. */ @@ -175,6 +182,14 @@ make_run_cleanup (function, arg) return make_my_cleanup (&run_cleanup_chain, function, arg); } +struct cleanup * +make_exec_cleanup (function, arg) + void (*function) PARAMS ((PTR)); + PTR arg; +{ + return make_my_cleanup (&exec_cleanup_chain, function, arg); +} + static void do_freeargv (arg) void *arg; @@ -231,6 +246,13 @@ do_run_cleanups (old_chain) do_my_cleanups (&run_cleanup_chain, old_chain); } +void +do_exec_cleanups (old_chain) + register struct cleanup *old_chain; +{ + do_my_cleanups (&exec_cleanup_chain, old_chain); +} + void do_my_cleanups (pmy_chain, old_chain) register struct cleanup **pmy_chain; @@ -350,6 +372,38 @@ null_cleanup (arg) { } +/* Add a continuation to the continuation list, the gloabl list + cmd_continuation. */ +void +add_continuation (continuation_hook, arg_list) + void (*continuation_hook) PARAMS ((struct continuation_arg *)); + struct continuation_arg *arg_list; +{ + struct continuation *continuation_ptr; + + continuation_ptr = (struct continuation *) xmalloc (sizeof (struct continuation)); + continuation_ptr->continuation_hook = continuation_hook; + continuation_ptr->arg_list = arg_list; + continuation_ptr->next = cmd_continuation; + cmd_continuation = continuation_ptr; +} + +/* Walk down the cmd_continuation list, and execute all the + continuations. */ +void +do_all_continuations () +{ + struct continuation *continuation_ptr; + + while (cmd_continuation) + { + (cmd_continuation->continuation_hook) (cmd_continuation->arg_list); + continuation_ptr = cmd_continuation; + cmd_continuation = continuation_ptr->next; + free (continuation_ptr); + } +} + /* Print a warning message. Way to use this is to call warning_begin, output the warning message (use unfiltered output to gdb_stderr), diff --git a/gdb/valops.c b/gdb/valops.c index 74dae8de231..c7db8361b6f 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1636,6 +1636,10 @@ You must use a pointer to function type variable. Command ignored.", arg_name); wouldn't happen. (See store_inferior_registers in sparc-nat.c.) */ write_sp (sp); +#ifdef SAVE_DUMMY_FRAME_TOS + SAVE_DUMMY_FRAME_TOS (sp); +#endif + { char retbuf[REGISTER_BYTES]; char *name; diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index d585aa6dbb6..d8847c605a0 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,16 @@ +1999-07-05 Doug Evans + + * Make-common.in (CGEN_MAIN_CPU_DEPS): Add cgen-fpu.h. + (cgen-fpu.o,cgen-accfp.o): Add rules for. + * cgen-fpu.c: New file. + * cgen-fpu.h: New file. + * cgen-accfp.c: New file. + * cgen-cpu.h (CGEN_CPU): New member fpu. + * cgen-mem.h: Redo fp support. + * cgen-ops.h: Delete k&r support. Redo fp support. + * cgen-sim.h: Include cgen-fpu.h. + * cgen-types.h (SF,DF,XF,TF): Moved to cgen-fpu.h. + 1999-06-23 Doug Evans * cgen-engine.h (TARGET_SEM_BRANCH_FINI): Remove cruft at end of diff --git a/sim/common/Make-common.in b/sim/common/Make-common.in index 71b4f69a612..b8e98eb9dfb 100644 --- a/sim/common/Make-common.in +++ b/sim/common/Make-common.in @@ -556,7 +556,8 @@ CGEN_MAIN_CPU_DEPS = \ $(SIM_MAIN_DEPS) \ $(CGEN_INCLUDE_DEPS) \ $(srccom)/cgen-ops.h \ - $(srccom)/cgen-mem.h + $(srccom)/cgen-mem.h \ + $(srccom)/cgen-fpu.h cgen-run.o: $(srccom)/cgen-run.c $(sim_main_headers) $(CC) -c $(srccom)/cgen-run.c $(ALL_CFLAGS) @@ -567,6 +568,12 @@ cgen-scache.o: $(srccom)/cgen-scache.c $(sim_main_headers) cgen-trace.o: $(srccom)/cgen-trace.c $(sim_main_headers) $(CC) -c $(srccom)/cgen-trace.c $(ALL_CFLAGS) +cgen-fpu.o: $(srccom)/cgen-fpu.c $(sim_main_headers) $(sim-fpu_h) + $(CC) -c $(srccom)/cgen-fpu.c $(ALL_CFLAGS) + +cgen-accfp.o: $(srccom)/cgen-accfp.c $(sim_main_headers) $(sim-fpu_h) + $(CC) -c $(srccom)/cgen-accfp.c $(ALL_CFLAGS) + cgen-utils.o: $(srccom)/cgen-utils.c $(sim_main_headers) \ $(srccom)/cgen-mem.h $(srccom)/cgen-ops.h $(srccom)/cgen-engine.h $(CC) -c $(srccom)/cgen-utils.c $(ALL_CFLAGS) diff --git a/sim/common/cgen-cpu.h b/sim/common/cgen-cpu.h index b2121009033..c807182bbc0 100644 --- a/sim/common/cgen-cpu.h +++ b/sim/common/cgen-cpu.h @@ -82,6 +82,10 @@ typedef struct { const CGEN_INSN * (*get_idata) (SIM_CPU *, int); #define CPU_GET_IDATA(cpu) ((cpu)->cgen_cpu.get_idata) + /* Floating point support. */ + CGEN_FPU fpu; +#define CGEN_CPU_FPU(cpu) (& (cpu)->cgen_cpu.fpu) + /* Disassembler. */ CGEN_DISASSEMBLER *disassembler; #define CPU_DISASSEMBLER(cpu) ((cpu)->cgen_cpu.disassembler) diff --git a/sim/common/cgen-mem.h b/sim/common/cgen-mem.h index c91ccb3f688..b424bba18a8 100644 --- a/sim/common/cgen-mem.h +++ b/sim/common/cgen-mem.h @@ -1,5 +1,5 @@ /* Memory ops header for CGEN-based simulators. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. Contributed by Cygnus Solutions. This file is part of the GNU Simulators. @@ -27,7 +27,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MEMOPS_INLINE extern inline #endif -/* Memory read support. */ +/* Integer memory read support. + + There is no floating point support. In this context there are no + floating point modes, only floating point operations (whose arguments + and results are arrays of bits that we treat as integer modes). */ #if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) #define DECLARE_GETMEM(mode, size) \ @@ -52,29 +56,9 @@ DECLARE_GETMEM (USI, 4) DECLARE_GETMEM (DI, 8) DECLARE_GETMEM (UDI, 8) -#undef DECLARE_GETMEM - -#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) -#define DECLARE_GETMEM(mode, size) \ -MEMOPS_INLINE mode \ -XCONCAT2 (GETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a) \ -{ \ - PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode)); \ - /* Don't read anything into "unaligned" here. Bad name choice. */\ - return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, pc, read_map, a); \ -} -#else -#define DECLARE_GETMEM(mode, size) \ -extern mode XCONCAT2 (GETMEM,mode) (SIM_CPU *, IADDR, ADDR); -#endif - -DECLARE_GETMEM (SF, 4) -DECLARE_GETMEM (DF, 8) -/*DECLARE_GETMEM (TF, 16)*/ - #undef DECLARE_GETMEM -/* Memory write support. */ +/* Integer memory write support. */ #if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) #define DECLARE_SETMEM(mode, size) \ @@ -99,12 +83,6 @@ DECLARE_SETMEM (USI, 4) DECLARE_SETMEM (DI, 8) DECLARE_SETMEM (UDI, 8) -/* -DECLARE_SETMEM (SF, 4) -DECLARE_SETMEM (DF, 8) -DECLARE_SETMEM (TF, 16) -*/ - #undef DECLARE_SETMEM /* Instruction read support. */ @@ -130,6 +108,54 @@ DECLARE_GETIMEM (UDI, 8) #undef DECLARE_GETIMEM +/* Floating point support. + + ??? One can specify that the integer memory ops should be used instead, + and treat fp values as just a series of bits. One might even bubble + that notion up into the description language. However, that departs from + gcc. One could cross over from gcc's notion and a "series of bits" notion + between there and here, and thus still not require these routines. However, + that's a complication of its own (not that having these fns isn't). + But for now, we do things this way. */ + +#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) +#define DECLARE_GETMEM(mode, size) \ +MEMOPS_INLINE mode \ +XCONCAT2 (GETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a) \ +{ \ + PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode)); \ + /* Don't read anything into "unaligned" here. Bad name choice. */\ + return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, pc, read_map, a); \ +} +#else +#define DECLARE_GETMEM(mode, size) \ +extern mode XCONCAT2 (GETMEM,mode) (SIM_CPU *, IADDR, ADDR); +#endif + +DECLARE_GETMEM (SF, 4) +DECLARE_GETMEM (DF, 8) + +#undef DECLARE_GETMEM + +#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) +#define DECLARE_SETMEM(mode, size) \ +MEMOPS_INLINE void \ +XCONCAT2 (SETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a, mode val) \ +{ \ + PROFILE_COUNT_WRITE (cpu, a, XCONCAT2 (MODE_,mode)); \ + /* Don't read anything into "unaligned" here. Bad name choice. */ \ + XCONCAT2 (sim_core_write_unaligned_,size) (cpu, pc, write_map, a, val); \ +} +#else +#define DECLARE_SETMEM(mode, size) \ +extern void XCONCAT2 (SETMEM,mode) (SIM_CPU *, IADDR, ADDR, mode); +#endif + +DECLARE_SETMEM (SF, 4) +DECLARE_SETMEM (DF, 8) + +#undef DECLARE_SETMEM + /* GETT: translate target value at P to host value. This needn't be very efficient (i.e. can call memcpy) as this is only used when interfacing with the outside world (e.g. gdb). */ @@ -157,7 +183,7 @@ DECLARE_GETT (USI, 4) DECLARE_GETT (DI, 8) DECLARE_GETT (UDI, 8) -/* +/* ??? defered until necessary DECLARE_GETT (SF, 4) DECLARE_GETT (DF, 8) DECLARE_GETT (TF, 16) @@ -192,7 +218,7 @@ DECLARE_SETT (USI, 4) DECLARE_SETT (DI, 8) DECLARE_SETT (UDI, 8) -/* +/* ??? defered until necessary DECLARE_SETT (SF, 4) DECLARE_SETT (DF, 8) DECLARE_SETT (TF, 16) diff --git a/sim/common/cgen-ops.h b/sim/common/cgen-ops.h index 6b89859160a..326102f6a3c 100644 --- a/sim/common/cgen-ops.h +++ b/sim/common/cgen-ops.h @@ -1,3 +1,4 @@ + /* Semantics ops support for CGEN-based simulators. Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. Contributed by Cygnus Solutions. @@ -33,6 +34,8 @@ with this program; if not, write to the Free Software Foundation, Inc., /* Semantic operations. At one point this file was machine generated. Maybe it will be again. */ +/* TODO: Lazy encoding/decoding of fp values. */ + /* These don't really have a mode. */ #define ANDIF(x, y) ((x) && (y)) #define ORIF(x, y) ((x) || (y)) @@ -53,7 +56,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define LEUBI(x, y) ((BI) (x) <= (BI) (y)) #define GTUBI(x, y) ((BI) (x) > (BI) (y)) #define GEUBI(x, y) ((BI) (x) >= (BI) (y)) - + #define ADDQI(x, y) ((x) + (y)) #define SUBQI(x, y) ((x) - (y)) #define MULQI(x, y) ((x) * (y)) @@ -64,8 +67,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #define SRAQI(x, y) ((QI) (x) >> (y)) #define SRLQI(x, y) ((UQI) (x) >> (y)) #define SLLQI(x, y) ((UQI) (x) << (y)) -extern QI RORQI PARAMS ((QI, int)); -extern QI ROLQI PARAMS ((QI, int)); +extern QI RORQI (QI, int); +extern QI ROLQI (QI, int); #define ANDQI(x, y) ((x) & (y)) #define ORQI(x, y) ((x) | (y)) #define XORQI(x, y) ((x) ^ (y)) @@ -82,7 +85,7 @@ extern QI ROLQI PARAMS ((QI, int)); #define LEUQI(x, y) ((UQI) (x) <= (UQI) (y)) #define GTUQI(x, y) ((UQI) (x) > (UQI) (y)) #define GEUQI(x, y) ((UQI) (x) >= (UQI) (y)) - + #define ADDHI(x, y) ((x) + (y)) #define SUBHI(x, y) ((x) - (y)) #define MULHI(x, y) ((x) * (y)) @@ -93,8 +96,8 @@ extern QI ROLQI PARAMS ((QI, int)); #define SRAHI(x, y) ((HI) (x) >> (y)) #define SRLHI(x, y) ((UHI) (x) >> (y)) #define SLLHI(x, y) ((UHI) (x) << (y)) -extern HI RORHI PARAMS ((HI, int)); -extern HI ROLHI PARAMS ((HI, int)); +extern HI RORHI (HI, int); +extern HI ROLHI (HI, int); #define ANDHI(x, y) ((x) & (y)) #define ORHI(x, y) ((x) | (y)) #define XORHI(x, y) ((x) ^ (y)) @@ -111,7 +114,7 @@ extern HI ROLHI PARAMS ((HI, int)); #define LEUHI(x, y) ((UHI) (x) <= (UHI) (y)) #define GTUHI(x, y) ((UHI) (x) > (UHI) (y)) #define GEUHI(x, y) ((UHI) (x) >= (UHI) (y)) - + #define ADDSI(x, y) ((x) + (y)) #define SUBSI(x, y) ((x) - (y)) #define MULSI(x, y) ((x) * (y)) @@ -122,8 +125,8 @@ extern HI ROLHI PARAMS ((HI, int)); #define SRASI(x, y) ((SI) (x) >> (y)) #define SRLSI(x, y) ((USI) (x) >> (y)) #define SLLSI(x, y) ((USI) (x) << (y)) -extern SI RORSI PARAMS ((SI, int)); -extern SI ROLSI PARAMS ((SI, int)); +extern SI RORSI (SI, int); +extern SI ROLSI (SI, int); #define ANDSI(x, y) ((x) & (y)) #define ORSI(x, y) ((x) | (y)) #define XORSI(x, y) ((x) ^ (y)) @@ -140,36 +143,36 @@ extern SI ROLSI PARAMS ((SI, int)); #define LEUSI(x, y) ((USI) (x) <= (USI) (y)) #define GTUSI(x, y) ((USI) (x) > (USI) (y)) #define GEUSI(x, y) ((USI) (x) >= (USI) (y)) - + #ifdef DI_FN_SUPPORT -extern DI ADDDI PARAMS ((DI, DI)); -extern DI SUBDI PARAMS ((DI, DI)); -extern DI MULDI PARAMS ((DI, DI)); -extern DI DIVDI PARAMS ((DI, DI)); -extern DI UDIVDI PARAMS ((DI, DI)); -extern DI MODDI PARAMS ((DI, DI)); -extern DI UMODDI PARAMS ((DI, DI)); -extern DI SRADI PARAMS ((DI, int)); -extern UDI SRLDI PARAMS ((UDI, int)); -extern UDI SLLDI PARAMS ((UDI, int)); -extern DI RORDI PARAMS ((DI, int)); -extern DI ROLDI PARAMS ((DI, int)); -extern DI ANDDI PARAMS ((DI, DI)); -extern DI ORDI PARAMS ((DI, DI)); -extern DI XORDI PARAMS ((DI, DI)); -extern DI NEGDI PARAMS ((DI)); -extern int NOTDI PARAMS ((DI)); -extern DI INVDI PARAMS ((DI)); -extern int EQDI PARAMS ((DI, DI)); -extern int NEDI PARAMS ((DI, DI)); -extern int LTDI PARAMS ((DI, DI)); -extern int LEDI PARAMS ((DI, DI)); -extern int GTDI PARAMS ((DI, DI)); -extern int GEDI PARAMS ((DI, DI)); -extern int LTUDI PARAMS ((UDI, UDI)); -extern int LEUDI PARAMS ((UDI, UDI)); -extern int GTUDI PARAMS ((UDI, UDI)); -extern int GEUDI PARAMS ((UDI, UDI)); +extern DI ADDDI (DI, DI); +extern DI SUBDI (DI, DI); +extern DI MULDI (DI, DI); +extern DI DIVDI (DI, DI); +extern DI UDIVDI (DI, DI); +extern DI MODDI (DI, DI); +extern DI UMODDI (DI, DI); +extern DI SRADI (DI, int); +extern UDI SRLDI (UDI, int); +extern UDI SLLDI (UDI, int); +extern DI RORDI (DI, int); +extern DI ROLDI (DI, int); +extern DI ANDDI (DI, DI); +extern DI ORDI (DI, DI); +extern DI XORDI (DI, DI); +extern DI NEGDI (DI); +extern int NOTDI (DI); +extern DI INVDI (DI); +extern int EQDI (DI, DI); +extern int NEDI (DI, DI); +extern int LTDI (DI, DI); +extern int LEDI (DI, DI); +extern int GTDI (DI, DI); +extern int GEDI (DI, DI); +extern int LTUDI (UDI, UDI); +extern int LEUDI (UDI, UDI); +extern int GTUDI (UDI, UDI); +extern int GEUDI (UDI, UDI); #else /* ! DI_FN_SUPPORT */ #define ADDDI(x, y) ((x) + (y)) #define SUBDI(x, y) ((x) - (y)) @@ -181,8 +184,8 @@ extern int GEUDI PARAMS ((UDI, UDI)); #define SRADI(x, y) ((DI) (x) >> (y)) #define SRLDI(x, y) ((UDI) (x) >> (y)) #define SLLDI(x, y) ((UDI) (x) << (y)) -extern DI RORDI PARAMS ((DI, int)); -extern DI ROLDI PARAMS ((DI, int)); +extern DI RORDI (DI, int); +extern DI ROLDI (DI, int); #define ANDDI(x, y) ((x) & (y)) #define ORDI(x, y) ((x) | (y)) #define XORDI(x, y) ((x) ^ (y)) @@ -200,229 +203,61 @@ extern DI ROLDI PARAMS ((DI, int)); #define GTUDI(x, y) ((UDI) (x) > (UDI) (y)) #define GEUDI(x, y) ((UDI) (x) >= (UDI) (y)) #endif /* DI_FN_SUPPORT */ - -#ifdef SF_FN_SUPPORT -extern SF ADDSF PARAMS ((SF, SF)); -extern SF SUBSF PARAMS ((SF, SF)); -extern SF NEGSF PARAMS ((SF)); -extern SF MULSF PARAMS ((SF, SF)); -extern SF DIVSF PARAMS ((SF, SF)); -extern int EQSF PARAMS ((SF, SF)); -extern int NESF PARAMS ((SF, SF)); -extern int LTSF PARAMS ((SF, SF)); -extern int LESF PARAMS ((SF, SF)); -extern int GTSF PARAMS ((SF, SF)); -extern int GESF PARAMS ((SF, SF)); -extern SF ABSSF PARAMS ((SF)); -extern SF SQRTSF PARAMS ((SF)); -extern SF COSSF PARAMS ((SF)); -extern SF SINSF PARAMS ((SF)); -#else /* ! SF_FN_SUPPORT */ -#define ADDSF(x, y) ((x) + (y)) -#define SUBSF(x, y) ((x) - (y)) -#define NEGSF(x) (- (x)) -#define MULSF(x, y) ((x) * (y)) -#define DIVSF(x, y) ((x) / (y)) -#define EQSF(x, y) ((SF) (x) == (SF) (y)) -#define NESF(x, y) ((SF) (x) != (SF) (y)) -#define LTSF(x, y) ((SF) (x) < (SF) (y)) -#define LESF(x, y) ((SF) (x) <= (SF) (y)) -#define GTSF(x, y) ((SF) (x) > (SF) (y)) -#define GESF(x, y) ((SF) (x) >= (SF) (y)) -extern SF ABSSF PARAMS ((SF)); -extern SF SQRTSF PARAMS ((SF)); -extern SF COSSF PARAMS ((SF)); -extern SF SINSF PARAMS ((SF)); -#endif /* SF_FN_SUPPORT */ - -#ifdef DF_FN_SUPPORT -extern DF ADDDF PARAMS ((DF, DF)); -extern DF SUBDF PARAMS ((DF, DF)); -extern DF NEGDF PARAMS ((DF)); -extern DF MULDF PARAMS ((DF, DF)); -extern DF DIVDF PARAMS ((DF, DF)); -extern int EQDF PARAMS ((DF, DF)); -extern int NEDF PARAMS ((DF, DF)); -extern int LTDF PARAMS ((DF, DF)); -extern int LEDF PARAMS ((DF, DF)); -extern int GTDF PARAMS ((DF, DF)); -extern int GEDF PARAMS ((DF, DF)); -extern DF ABSDF PARAMS ((DF)); -extern DF SQRTDF PARAMS ((DF)); -extern DF COSDF PARAMS ((DF)); -extern DF SINDF PARAMS ((DF)); -#else /* ! DF_FN_SUPPORT */ -#define ADDDF(x, y) ((x) + (y)) -#define SUBDF(x, y) ((x) - (y)) -#define NEGDF(x) (- (x)) -#define MULDF(x, y) ((x) * (y)) -#define DIVDF(x, y) ((x) / (y)) -#define EQDF(x, y) ((DF) (x) == (DF) (y)) -#define NEDF(x, y) ((DF) (x) != (DF) (y)) -#define LTDF(x, y) ((DF) (x) < (DF) (y)) -#define LEDF(x, y) ((DF) (x) <= (DF) (y)) -#define GTDF(x, y) ((DF) (x) > (DF) (y)) -#define GEDF(x, y) ((DF) (x) >= (DF) (y)) -extern DF ABSDF PARAMS ((DF)); -extern DF SQRTDF PARAMS ((DF)); -extern DF COSDF PARAMS ((DF)); -extern DF SINDF PARAMS ((DF)); -#endif /* DF_FN_SUPPORT */ - -#ifdef XF_FN_SUPPORT -extern XF ADDXF PARAMS ((XF, XF)); -extern XF SUBXF PARAMS ((XF, XF)); -extern XF NEGXF PARAMS ((XF)); -extern XF MULXF PARAMS ((XF, XF)); -extern XF DIVXF PARAMS ((XF, XF)); -extern int EQXF PARAMS ((XF, XF)); -extern int NEXF PARAMS ((XF, XF)); -extern int LTXF PARAMS ((XF, XF)); -extern int LEXF PARAMS ((XF, XF)); -extern int GTXF PARAMS ((XF, XF)); -extern int GEXF PARAMS ((XF, XF)); -extern XF ABSXF PARAMS ((XF)); -extern XF SQRTXF PARAMS ((XF)); -extern XF COSXF PARAMS ((XF)); -extern XF SINXF PARAMS ((XF)); -#else /* ! XF_FN_SUPPORT */ -#define ADDXF(x, y) ((x) + (y)) -#define SUBXF(x, y) ((x) - (y)) -#define NEGXF(x) (- (x)) -#define MULXF(x, y) ((x) * (y)) -#define DIVXF(x, y) ((x) / (y)) -#define EQXF(x, y) ((XF) (x) == (XF) (y)) -#define NEXF(x, y) ((XF) (x) != (XF) (y)) -#define LTXF(x, y) ((XF) (x) < (XF) (y)) -#define LEXF(x, y) ((XF) (x) <= (XF) (y)) -#define GTXF(x, y) ((XF) (x) > (XF) (y)) -#define GEXF(x, y) ((XF) (x) >= (XF) (y)) -extern XF ABSXF PARAMS ((XF)); -extern XF SQRTXF PARAMS ((XF)); -extern XF COSXF PARAMS ((XF)); -extern XF SINXF PARAMS ((XF)); -#endif /* XF_FN_SUPPORT */ - -#ifdef TF_FN_SUPPORT -extern TF ADDTF PARAMS ((TF, TF)); -extern TF SUBTF PARAMS ((TF, TF)); -extern TF NEGTF PARAMS ((TF)); -extern TF MULTF PARAMS ((TF, TF)); -extern TF DIVTF PARAMS ((TF, TF)); -extern int EQTF PARAMS ((TF, TF)); -extern int NETF PARAMS ((TF, TF)); -extern int LTTF PARAMS ((TF, TF)); -extern int LETF PARAMS ((TF, TF)); -extern int GTTF PARAMS ((TF, TF)); -extern int GETF PARAMS ((TF, TF)); -extern TF ABSTF PARAMS ((TF)); -extern TF SQRTTF PARAMS ((TF)); -extern TF COSTF PARAMS ((TF)); -extern TF SINTF PARAMS ((TF)); -#else /* ! TF_FN_SUPPORT */ -#define ADDTF(x, y) ((x) + (y)) -#define SUBTF(x, y) ((x) - (y)) -#define NEGTF(x) (- (x)) -#define MULTF(x, y) ((x) * (y)) -#define DIVTF(x, y) ((x) / (y)) -#define EQTF(x, y) ((TF) (x) == (TF) (y)) -#define NETF(x, y) ((TF) (x) != (TF) (y)) -#define LTTF(x, y) ((TF) (x) < (TF) (y)) -#define LETF(x, y) ((TF) (x) <= (TF) (y)) -#define GTTF(x, y) ((TF) (x) > (TF) (y)) -#define GETF(x, y) ((TF) (x) >= (TF) (y)) -extern TF ABSTF PARAMS ((TF)); -extern TF SQRTTF PARAMS ((TF)); -extern TF COSTF PARAMS ((TF)); -extern TF SINTF PARAMS ((TF)); -#endif /* TF_FN_SUPPORT */ - - + #define EXTBIQI(x) ((QI) (BI) (x)) #define EXTBIHI(x) ((HI) (BI) (x)) #define EXTBISI(x) ((SI) (BI) (x)) #if defined (DI_FN_SUPPORT) -extern DI EXTBIDI PARAMS ((BI)); +extern DI EXTBIDI (BI); #else #define EXTBIDI(x) ((DI) (BI) (x)) #endif #define EXTQIHI(x) ((HI) (QI) (x)) #define EXTQISI(x) ((SI) (QI) (x)) #if defined (DI_FN_SUPPORT) -extern DI EXTQIDI PARAMS ((QI)); +extern DI EXTQIDI (QI); #else #define EXTQIDI(x) ((DI) (QI) (x)) #endif #define EXTHISI(x) ((SI) (HI) (x)) #if defined (DI_FN_SUPPORT) -extern DI EXTHIDI PARAMS ((HI)); +extern DI EXTHIDI (HI); #else #define EXTHIDI(x) ((DI) (HI) (x)) #endif #if defined (DI_FN_SUPPORT) -extern DI EXTSIDI PARAMS ((SI)); +extern DI EXTSIDI (SI); #else #define EXTSIDI(x) ((DI) (SI) (x)) #endif - -#if defined (SF_FN_SUPPORT) || defined (DF_FN_SUPPORT) -extern DF EXTSFDF PARAMS ((SF)); -#else -#define EXTSFDF(x) ((DF) (SF) (x)) -#endif -#if defined (SF_FN_SUPPORT) || defined (XF_FN_SUPPORT) -extern XF EXTSFXF PARAMS ((SF)); -#else -#define EXTSFXF(x) ((XF) (SF) (x)) -#endif -#if defined (SF_FN_SUPPORT) || defined (TF_FN_SUPPORT) -extern TF EXTSFTF PARAMS ((SF)); -#else -#define EXTSFTF(x) ((TF) (SF) (x)) -#endif -#if defined (DF_FN_SUPPORT) || defined (XF_FN_SUPPORT) -extern XF EXTDFXF PARAMS ((DF)); -#else -#define EXTDFXF(x) ((XF) (DF) (x)) -#endif -#if defined (DF_FN_SUPPORT) || defined (TF_FN_SUPPORT) -extern TF EXTDFTF PARAMS ((DF)); -#else -#define EXTDFTF(x) ((TF) (DF) (x)) -#endif -#if defined (XF_FN_SUPPORT) || defined (TF_FN_SUPPORT) -extern TF EXTXFTF PARAMS ((XF)); -#else -#define EXTXFTF(x) ((TF) (XF) (x)) -#endif - + #define ZEXTBIQI(x) ((QI) (BI) (x)) #define ZEXTBIHI(x) ((HI) (BI) (x)) #define ZEXTBISI(x) ((SI) (BI) (x)) #if defined (DI_FN_SUPPORT) -extern DI ZEXTBIDI PARAMS ((BI)); +extern DI ZEXTBIDI (BI); #else #define ZEXTBIDI(x) ((DI) (BI) (x)) #endif #define ZEXTQIHI(x) ((HI) (UQI) (x)) #define ZEXTQISI(x) ((SI) (UQI) (x)) #if defined (DI_FN_SUPPORT) -extern DI ZEXTQIDI PARAMS ((QI)); +extern DI ZEXTQIDI (QI); #else #define ZEXTQIDI(x) ((DI) (UQI) (x)) #endif #define ZEXTHISI(x) ((SI) (UHI) (x)) #if defined (DI_FN_SUPPORT) -extern DI ZEXTHIDI PARAMS ((HI)); +extern DI ZEXTHIDI (HI); #else #define ZEXTHIDI(x) ((DI) (UHI) (x)) #endif #if defined (DI_FN_SUPPORT) -extern DI ZEXTSIDI PARAMS ((SI)); +extern DI ZEXTSIDI (SI); #else #define ZEXTSIDI(x) ((DI) (USI) (x)) #endif - + #define TRUNCQIBI(x) ((BI) (QI) (x)) #define TRUNCHIBI(x) ((BI) (HI) (x)) #define TRUNCHIQI(x) ((QI) (HI) (x)) @@ -430,403 +265,31 @@ extern DI ZEXTSIDI PARAMS ((SI)); #define TRUNCSIQI(x) ((QI) (SI) (x)) #define TRUNCSIHI(x) ((HI) (SI) (x)) #if defined (DI_FN_SUPPORT) -extern BI TRUNCDIBI PARAMS ((DI)); +extern BI TRUNCDIBI (DI); #else #define TRUNCDIBI(x) ((BI) (DI) (x)) #endif #if defined (DI_FN_SUPPORT) -extern QI TRUNCDIQI PARAMS ((DI)); +extern QI TRUNCDIQI (DI); #else #define TRUNCDIQI(x) ((QI) (DI) (x)) #endif #if defined (DI_FN_SUPPORT) -extern HI TRUNCDIHI PARAMS ((DI)); +extern HI TRUNCDIHI (DI); #else #define TRUNCDIHI(x) ((HI) (DI) (x)) #endif #if defined (DI_FN_SUPPORT) -extern SI TRUNCDISI PARAMS ((DI)); +extern SI TRUNCDISI (DI); #else #define TRUNCDISI(x) ((SI) (DI) (x)) #endif - -#if defined (DF_FN_SUPPORT) || defined (SF_FN_SUPPORT) -extern SF TRUNCDFSF PARAMS ((DF)); -#else -#define TRUNCDFSF(x) ((SF) (DF) (x)) -#endif -#if defined (XF_FN_SUPPORT) || defined (SF_FN_SUPPORT) -extern SF TRUNCXFSF PARAMS ((XF)); -#else -#define TRUNCXFSF(x) ((SF) (XF) (x)) -#endif -#if defined (XF_FN_SUPPORT) || defined (DF_FN_SUPPORT) -extern DF TRUNCXFDF PARAMS ((XF)); -#else -#define TRUNCXFDF(x) ((DF) (XF) (x)) -#endif -#if defined (TF_FN_SUPPORT) || defined (SF_FN_SUPPORT) -extern SF TRUNCTFSF PARAMS ((TF)); -#else -#define TRUNCTFSF(x) ((SF) (TF) (x)) -#endif -#if defined (TF_FN_SUPPORT) || defined (DF_FN_SUPPORT) -extern DF TRUNCTFDF PARAMS ((TF)); -#else -#define TRUNCTFDF(x) ((DF) (TF) (x)) -#endif -#if defined (TF_FN_SUPPORT) || defined (XF_FN_SUPPORT) -extern XF TRUNCTFXF PARAMS ((TF)); -#else -#define TRUNCTFXF(x) ((XF) (TF) (x)) -#endif - -#if defined (SF_FN_SUPPORT) -extern SF FLOATQISF PARAMS ((QI)); -#else -#define FLOATQISF(x) ((SF) (QI) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern DF FLOATQIDF PARAMS ((QI)); -#else -#define FLOATQIDF(x) ((DF) (QI) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern XF FLOATQIXF PARAMS ((QI)); -#else -#define FLOATQIXF(x) ((XF) (QI) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern TF FLOATQITF PARAMS ((QI)); -#else -#define FLOATQITF(x) ((TF) (QI) (x)) -#endif -#if defined (SF_FN_SUPPORT) -extern SF FLOATHISF PARAMS ((HI)); -#else -#define FLOATHISF(x) ((SF) (HI) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern DF FLOATHIDF PARAMS ((HI)); -#else -#define FLOATHIDF(x) ((DF) (HI) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern XF FLOATHIXF PARAMS ((HI)); -#else -#define FLOATHIXF(x) ((XF) (HI) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern TF FLOATHITF PARAMS ((HI)); -#else -#define FLOATHITF(x) ((TF) (HI) (x)) -#endif -#if defined (SF_FN_SUPPORT) -extern SF FLOATSISF PARAMS ((SI)); -#else -#define FLOATSISF(x) ((SF) (SI) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern DF FLOATSIDF PARAMS ((SI)); -#else -#define FLOATSIDF(x) ((DF) (SI) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern XF FLOATSIXF PARAMS ((SI)); -#else -#define FLOATSIXF(x) ((XF) (SI) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern TF FLOATSITF PARAMS ((SI)); -#else -#define FLOATSITF(x) ((TF) (SI) (x)) -#endif -#if defined (DI_FN_SUPPORT) || defined (SF_FN_SUPPORT) -extern SF FLOATDISF PARAMS ((DI)); -#else -#define FLOATDISF(x) ((SF) (DI) (x)) -#endif -#if defined (DI_FN_SUPPORT) || defined (DF_FN_SUPPORT) -extern DF FLOATDIDF PARAMS ((DI)); -#else -#define FLOATDIDF(x) ((DF) (DI) (x)) -#endif -#if defined (DI_FN_SUPPORT) || defined (XF_FN_SUPPORT) -extern XF FLOATDIXF PARAMS ((DI)); -#else -#define FLOATDIXF(x) ((XF) (DI) (x)) -#endif -#if defined (DI_FN_SUPPORT) || defined (TF_FN_SUPPORT) -extern TF FLOATDITF PARAMS ((DI)); -#else -#define FLOATDITF(x) ((TF) (DI) (x)) -#endif - -#if defined (SF_FN_SUPPORT) -extern SF UFLOATQISF PARAMS ((QI)); -#else -#define UFLOATQISF(x) ((SF) (UQI) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern DF UFLOATQIDF PARAMS ((QI)); -#else -#define UFLOATQIDF(x) ((DF) (UQI) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern XF UFLOATQIXF PARAMS ((QI)); -#else -#define UFLOATQIXF(x) ((XF) (UQI) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern TF UFLOATQITF PARAMS ((QI)); -#else -#define UFLOATQITF(x) ((TF) (UQI) (x)) -#endif -#if defined (SF_FN_SUPPORT) -extern SF UFLOATHISF PARAMS ((HI)); -#else -#define UFLOATHISF(x) ((SF) (UHI) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern DF UFLOATHIDF PARAMS ((HI)); -#else -#define UFLOATHIDF(x) ((DF) (UHI) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern XF UFLOATHIXF PARAMS ((HI)); -#else -#define UFLOATHIXF(x) ((XF) (UHI) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern TF UFLOATHITF PARAMS ((HI)); -#else -#define UFLOATHITF(x) ((TF) (UHI) (x)) -#endif -#if defined (SF_FN_SUPPORT) -extern SF UFLOATSISF PARAMS ((SI)); -#else -#define UFLOATSISF(x) ((SF) (USI) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern DF UFLOATSIDF PARAMS ((SI)); -#else -#define UFLOATSIDF(x) ((DF) (USI) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern XF UFLOATSIXF PARAMS ((SI)); -#else -#define UFLOATSIXF(x) ((XF) (USI) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern TF UFLOATSITF PARAMS ((SI)); -#else -#define UFLOATSITF(x) ((TF) (USI) (x)) -#endif -#if defined (DI_FN_SUPPORT) || defined (SF_FN_SUPPORT) -extern SF UFLOATDISF PARAMS ((DI)); -#else -#define UFLOATDISF(x) ((SF) (UDI) (x)) -#endif -#if defined (DI_FN_SUPPORT) || defined (DF_FN_SUPPORT) -extern DF UFLOATDIDF PARAMS ((DI)); -#else -#define UFLOATDIDF(x) ((DF) (UDI) (x)) -#endif -#if defined (DI_FN_SUPPORT) || defined (XF_FN_SUPPORT) -extern XF UFLOATDIXF PARAMS ((DI)); -#else -#define UFLOATDIXF(x) ((XF) (UDI) (x)) -#endif -#if defined (DI_FN_SUPPORT) || defined (TF_FN_SUPPORT) -extern TF UFLOATDITF PARAMS ((DI)); -#else -#define UFLOATDITF(x) ((TF) (UDI) (x)) -#endif - -#if defined (SF_FN_SUPPORT) -extern BI FIXSFBI PARAMS ((SF)); -#else -#define FIXSFBI(x) ((BI) (SF) (x)) -#endif -#if defined (SF_FN_SUPPORT) -extern QI FIXSFQI PARAMS ((SF)); -#else -#define FIXSFQI(x) ((QI) (SF) (x)) -#endif -#if defined (SF_FN_SUPPORT) -extern HI FIXSFHI PARAMS ((SF)); -#else -#define FIXSFHI(x) ((HI) (SF) (x)) -#endif -#if defined (SF_FN_SUPPORT) -extern SI FIXSFSI PARAMS ((SF)); -#else -#define FIXSFSI(x) ((SI) (SF) (x)) -#endif -#if defined (SF_FN_SUPPORT) || defined (DI_FN_SUPPORT) -extern DI FIXSFDI PARAMS ((SF)); -#else -#define FIXSFDI(x) ((DI) (SF) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern BI FIXDFBI PARAMS ((DF)); -#else -#define FIXDFBI(x) ((BI) (DF) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern QI FIXDFQI PARAMS ((DF)); -#else -#define FIXDFQI(x) ((QI) (DF) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern HI FIXDFHI PARAMS ((DF)); -#else -#define FIXDFHI(x) ((HI) (DF) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern SI FIXDFSI PARAMS ((DF)); -#else -#define FIXDFSI(x) ((SI) (DF) (x)) -#endif -#if defined (DF_FN_SUPPORT) || defined (DI_FN_SUPPORT) -extern DI FIXDFDI PARAMS ((DF)); -#else -#define FIXDFDI(x) ((DI) (DF) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern BI FIXXFBI PARAMS ((XF)); -#else -#define FIXXFBI(x) ((BI) (XF) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern QI FIXXFQI PARAMS ((XF)); -#else -#define FIXXFQI(x) ((QI) (XF) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern HI FIXXFHI PARAMS ((XF)); -#else -#define FIXXFHI(x) ((HI) (XF) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern SI FIXXFSI PARAMS ((XF)); -#else -#define FIXXFSI(x) ((SI) (XF) (x)) -#endif -#if defined (XF_FN_SUPPORT) || defined (DI_FN_SUPPORT) -extern DI FIXXFDI PARAMS ((XF)); -#else -#define FIXXFDI(x) ((DI) (XF) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern BI FIXTFBI PARAMS ((TF)); -#else -#define FIXTFBI(x) ((BI) (TF) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern QI FIXTFQI PARAMS ((TF)); -#else -#define FIXTFQI(x) ((QI) (TF) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern HI FIXTFHI PARAMS ((TF)); -#else -#define FIXTFHI(x) ((HI) (TF) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern SI FIXTFSI PARAMS ((TF)); -#else -#define FIXTFSI(x) ((SI) (TF) (x)) -#endif -#if defined (TF_FN_SUPPORT) || defined (DI_FN_SUPPORT) -extern DI FIXTFDI PARAMS ((TF)); -#else -#define FIXTFDI(x) ((DI) (TF) (x)) -#endif - -#if defined (SF_FN_SUPPORT) -extern QI UFIXSFQI PARAMS ((SF)); -#else -#define UFIXSFQI(x) ((UQI) (SF) (x)) -#endif -#if defined (SF_FN_SUPPORT) -extern HI UFIXSFHI PARAMS ((SF)); -#else -#define UFIXSFHI(x) ((UHI) (SF) (x)) -#endif -#if defined (SF_FN_SUPPORT) -extern SI UFIXSFSI PARAMS ((SF)); -#else -#define UFIXSFSI(x) ((USI) (SF) (x)) -#endif -#if defined (SF_FN_SUPPORT) || defined (DI_FN_SUPPORT) -extern DI UFIXSFDI PARAMS ((SF)); -#else -#define UFIXSFDI(x) ((UDI) (SF) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern QI UFIXDFQI PARAMS ((DF)); -#else -#define UFIXDFQI(x) ((UQI) (DF) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern HI UFIXDFHI PARAMS ((DF)); -#else -#define UFIXDFHI(x) ((UHI) (DF) (x)) -#endif -#if defined (DF_FN_SUPPORT) -extern SI UFIXDFSI PARAMS ((DF)); -#else -#define UFIXDFSI(x) ((USI) (DF) (x)) -#endif -#if defined (DF_FN_SUPPORT) || defined (DI_FN_SUPPORT) -extern DI UFIXDFDI PARAMS ((DF)); -#else -#define UFIXDFDI(x) ((UDI) (DF) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern QI UFIXXFQI PARAMS ((XF)); -#else -#define UFIXXFQI(x) ((UQI) (XF) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern HI UFIXXFHI PARAMS ((XF)); -#else -#define UFIXXFHI(x) ((UHI) (XF) (x)) -#endif -#if defined (XF_FN_SUPPORT) -extern SI UFIXXFSI PARAMS ((XF)); -#else -#define UFIXXFSI(x) ((USI) (XF) (x)) -#endif -#if defined (XF_FN_SUPPORT) || defined (DI_FN_SUPPORT) -extern DI UFIXXFDI PARAMS ((XF)); -#else -#define UFIXXFDI(x) ((UDI) (XF) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern QI UFIXTFQI PARAMS ((TF)); -#else -#define UFIXTFQI(x) ((UQI) (TF) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern HI UFIXTFHI PARAMS ((TF)); -#else -#define UFIXTFHI(x) ((UHI) (TF) (x)) -#endif -#if defined (TF_FN_SUPPORT) -extern SI UFIXTFSI PARAMS ((TF)); -#else -#define UFIXTFSI(x) ((USI) (TF) (x)) -#endif -#if defined (TF_FN_SUPPORT) || defined (DI_FN_SUPPORT) -extern DI UFIXTFDI PARAMS ((TF)); -#else -#define UFIXTFDI(x) ((UDI) (TF) (x)) -#endif /* Composing/decomposing the various types. */ +/* ??? endianness issues undecided */ +/* ??? CURRENT_TARGET_BYTE_ORDER usage wip */ + #ifdef SEMOPS_DEFINE_INLINE SEMOPS_INLINE SF @@ -848,7 +311,6 @@ SUBWORDSFSI (SIM_CPU *cpu, SF in) SEMOPS_INLINE SI SUBWORDDISI (SIM_CPU *cpu, DI in, int word) { - /* ??? endianness issues undecided */ if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) { if (word == 0) @@ -868,7 +330,6 @@ SUBWORDDISI (SIM_CPU *cpu, DI in, int word) SEMOPS_INLINE SI SUBWORDDFSI (SIM_CPU *cpu, DF in, int word) { - /* ??? endianness issues undecided */ union { DF in; SI out[2]; } x; x.in = in; if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) @@ -877,16 +338,26 @@ SUBWORDDFSI (SIM_CPU *cpu, DF in, int word) return x.out[!word]; } +SEMOPS_INLINE SI +SUBWORDXFSI (SIM_CPU *cpu, XF in, int word) +{ + union { XF in; SI out[3]; } x; + x.in = in; + if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) + return x.out[word]; + else + return x.out[2 - word]; +} + SEMOPS_INLINE SI SUBWORDTFSI (SIM_CPU *cpu, TF in, int word) { - /* ??? endianness issues undecided */ union { TF in; SI out[4]; } x; x.in = in; if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) return x.out[word]; else - return x.out[word ^ 3]; + return x.out[3 - word]; } SEMOPS_INLINE DI @@ -909,6 +380,17 @@ JOINSIDF (SIM_CPU *cpu, SI x0, SI x1) return x.out; } +SEMOPS_INLINE XF +JOINSIXF (SIM_CPU *cpu, SI x0, SI x1, SI x2) +{ + union { SI in[3]; XF out; } x; + if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) + x.in[0] = x0, x.in[1] = x1, x.in[2] = x2; + else + x.in[2] = x0, x.in[1] = x1, x.in[0] = x2; + return x.out; +} + SEMOPS_INLINE TF JOINSITF (SIM_CPU *cpu, SI x0, SI x1, SI x2, SI x3) { @@ -926,10 +408,12 @@ SF SUBWORDSISF (SIM_CPU *, SI); SI SUBWORDSFSI (SIM_CPU *, SF); SI SUBWORDDISI (SIM_CPU *, DI, int); SI SUBWORDDFSI (SIM_CPU *, DF, int); +SI SUBWORDXFSI (SIM_CPU *, XF, int); SI SUBWORDTFSI (SIM_CPU *, TF, int); DI JOINSIDI (SIM_CPU *, SI, SI); DF JOINSIDF (SIM_CPU *, SI, SI); +XF JOINSIXF (SIM_CPU *, SI, SI, SI); TF JOINSITF (SIM_CPU *, SI, SI, SI, SI); #endif /* SUBWORD,JOIN */ diff --git a/sim/common/cgen-sim.h b/sim/common/cgen-sim.h index 748015f5724..6b177ec40bc 100644 --- a/sim/common/cgen-sim.h +++ b/sim/common/cgen-sim.h @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cgen-defs.h" #include "cgen-scache.h" +#include "cgen-fpu.h" #include "cgen-cpu.h" #include "cgen-trace.h" diff --git a/sim/common/cgen-types.h b/sim/common/cgen-types.h index 28c7205ad60..289c7bd1f08 100644 --- a/sim/common/cgen-types.h +++ b/sim/common/cgen-types.h @@ -98,13 +98,6 @@ extern DI make_struct_di (SI, SI); #define MAKEDI(hi, lo) (make_struct_di ((hi), (lo))) #endif -/* FIXME: Need to provide libraries if these aren't appropriate for target, - or user's needs. */ -typedef float SF; /* FIXME: struct */ -typedef double DF; /* FIXME: struct */ -typedef struct { SI parts[3]; } XF; /* FIXME: configure, provide library */ -typedef struct { SI parts[4]; } TF; /* FIXME: configure, provide library */ - /* These are used to record extracted raw data from an instruction, among other things. It must be a host data type, and not a target one. */ typedef int INT; @@ -113,4 +106,6 @@ typedef unsigned int UINT; typedef unsigned_address ADDR; /* FIXME: wip*/ typedef unsigned_address IADDR; /* FIXME: wip*/ +/* fp types are in cgen-fpu.h */ + #endif /* CGEN_TYPES_H */ -- 2.30.2