mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 20:14:06 +08:00
import gdb-1999-07-05 snapshot
This commit is contained in:
parent
f11523b013
commit
43ff13b418
201
gdb/ChangeLog
201
gdb/ChangeLog
@ -1,3 +1,203 @@
|
||||
1999-07-05 Jason Molenda (jsm@bugshack.cygnus.com)
|
||||
|
||||
* remote.c: Include <sys/select.h> 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 <cagney@b1.cygnus.com>
|
||||
|
||||
* 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 <ezannoni@kwikemart.cygnus.com>
|
||||
|
||||
* 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 <cagney@b1.cygnus.com>
|
||||
|
||||
* 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 <fnasser@totem.to.cygnus.com>
|
||||
|
||||
* source.c (directory_command): Add missing test for from_tty.
|
||||
|
||||
1999-06-29 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
|
||||
|
||||
* 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 <jimb@zwingli.cygnus.com>
|
||||
|
||||
* solib.c (clear_solib): Don't disable breakpoints if we're
|
||||
@ -136,6 +336,7 @@ Wed Jun 23 15:30:46 1999 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
* 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 <readline.h>.
|
||||
|
||||
* event-loop.h: Get rid of nested #include's.
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 ;;
|
||||
|
||||
|
39
gdb/defs.h
39
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 *, ...));
|
||||
|
@ -1,3 +1,7 @@
|
||||
Tue Jun 29 11:43:55 1999 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* gdbint.texinfo (SAVE_DUMMY_FRAME_TOS): Define.
|
||||
|
||||
Fri Jun 25 11:47:06 1999 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* remote.texi (Communication Protocol): ``v'' is in use. Fix
|
||||
|
@ -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.
|
||||
|
@ -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? */
|
||||
|
@ -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.
|
||||
|
103
gdb/event-top.c
103
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. 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;
|
||||
|
||||
/* Do any commands attached to breakpoint we stopped at. */
|
||||
bpstat_do_actions (&stop_bpstat);
|
||||
do_cleanups (old_chain);
|
||||
|
||||
/*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;
|
||||
{
|
||||
|
@ -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)
|
||||
|
375
gdb/infcmd.c
375
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 <location>\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)));
|
||||
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 */
|
||||
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.");
|
||||
|
@ -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));
|
||||
|
123
gdb/infrun.c
123
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 <signal.h>
|
||||
#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.
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
@ -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 <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include "gdb_string.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "gdb_string.h"
|
||||
#include "command.h"
|
||||
#include "serial.h"
|
||||
#include "monitor.h"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include "gdb_string.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "gdb_string.h"
|
||||
#include "serial.h"
|
||||
|
||||
extern struct target_ops st2000_ops; /* Forward declaration */
|
||||
|
676
gdb/remote.c
676
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 <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include "event-loop.h"
|
||||
|
||||
#include <signal.h>
|
||||
#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);
|
||||
|
||||
|
@ -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 <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include "signals.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
|
@ -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 <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TERMIOS
|
||||
|
||||
struct hardwire_ttystate
|
||||
|
@ -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 ();
|
||||
|
@ -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 <sys/types.h>
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#if (!defined(__GO32__) && !defined(_WIN32)) || defined(__CYGWIN32__)
|
||||
#define HAVE_SOCKETS
|
||||
#include <sys/time.h>
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1,3 +1,8 @@
|
||||
Tue Jun 29 11:56:06 1999 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* lib/gdb.exp (gdb_expect_list): Output one message per pattern in
|
||||
a consistent format.
|
||||
|
||||
1999-06-25 Stan Shebs <shebs@andros.cygnus.com>
|
||||
|
||||
From Jimmy Guo <guo@cup.hp.com> and others at HP:
|
||||
|
@ -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}"
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
|
23
gdb/top.c
23
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;
|
||||
|
||||
|
@ -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 *));
|
||||
|
54
gdb/utils.c
54
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),
|
||||
|
@ -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;
|
||||
|
@ -1,3 +1,16 @@
|
||||
1999-07-05 Doug Evans <devans@casey.cygnus.com>
|
||||
|
||||
* 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 <devans@casey.cygnus.com>
|
||||
|
||||
* cgen-engine.h (TARGET_SEM_BRANCH_FINI): Remove cruft at end of
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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<mode>: 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)
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user