- add get_erx() method to bx_gen_reg_t which returns the erx field of the
structure (which is has a different name in cpu and cpu64). Providing
an accessor is one strategy for avoiding igly "#ifdef BX_SUPPORT_X86_64"
statements in the rest of the code.
- cpu64/init.cc: the "eflags" before get_flag and set_flag is no longer
correct. removed.
- modified files: load32bitOShack.cc logio.cc cpu/cpu.h cpu64/apic.cc
cpu64/cpu.h cpu64/init.cc cpu64/proc_ctrl.cc debug/dbg_main.cc
cpu64 directories. Instead of using the macros introduced in cpu.h rev 1.37
such as GetEFlagsDFLogical and SetEFlagsDF and ClearEFlagsDF, I made inline
methods on the BX_CPU_C object that access the eflags fields. The problem
with the macros is that they cannot be used outside the BX_CPU_C object. The
macros have now been removed, and all references to eflags now use these new
accessors.
- I debated whether to put the accessors as members of the BX_CPU_C object
or members of the bx_flags_reg_t struct. I chose to make them members
of BX_CPU_C for two reasons: 1. the lazy flags are implemented as
members of BX_CPU_C, and 2. the eflags are referenced in many many places
and it is more compact without having to put eflags in front of each. (The
real problem with compactness is having to write BX_CPU_THIS_PTR in front of
everything, but that's another story.)
- Kevin pointed out a major bug in my set accessor code. What a difference a
little tilde can make! That is fixed now.
- modified: load32bitOShack.cc debug/dbg_main.cc
and in both cpu and cpu64 directories:
cpu.cc cpu.h ctrl_xfer_pro.cc debugstuff.cc exception.cc flag_ctrl.cc
flag_ctrl_pro.cc init.cc io.cc io_pro.cc proc_ctrl.cc soft_int.cc
string.cc vm8086.cc
This adds a whole new directory cpu64 with the new emulation code.
Very few changes were necessary outside cpu64. To try it, configure
with --enable-x86-64 and make.
- also this adds Peter Tattam's external debugger interface.
- modified files: Makefile.in bochs.h config.h.in configure.in
load32bitOShack.cc logio.cc cpu/Makefile.in cpu/cpu.cc debug/dbg_main.cc
- added files: cpu/extdb.cc cpu/extdb.h and cpu64/*
a consistent way of accessing these flags that works both inside and
outside the BX_CPU class, I added inline accessor methods for each
flag: assert_FLAG(), clear_FLAG(), set_FLAG(value), and get_FLAG ()
that returns its value. I use assert to mean "set the value to one"
to avoid confusion, since there's also a set method that takes a value.
- the eflags access macros (e.g. GetEFlagsDFLogical, ClearEFlagsTF) are
now defined in terms of the inline accessors. In most cases it will
result in the same code anyway. The major advantage of the accesors
is that they can be used from inside or outside the BX_CPU object, while
the macros can only be used from inside.
- since almost all eflags were stored in val32 now, I went ahead and
removed the if_, rf, and vm fields. Now the val32 bit is the
"official" value for these flags, and they have accessors just like
everything else.
- init.cc: move the registration of registers until after they have been
initialized so that the initial value of each parameter is correct.
Modified files:
debug/dbg_main.cc cpu/cpu.h cpu/debugstuff.cc cpu/flag_ctrl.cc
cpu/flag_ctrl_pro.cc cpu/init.cc
Kevin Lawton says he doesn't get a performance benefit.
I'm not sure if I do. Either way, the difference isn't
very large.
This code may get removed if it turns out to be useless.
- modified files: config.h.in cpu/init.cc debug/dbg_main.cc gui/control.cc
gui/siminterface.cc gui/siminterface.h gui/wxdialog.cc gui/wxdialog.h
gui/wxmain.cc gui/wxmain.h iodev/keyboard.cc
----------------------------------------------------------------------
Patch name: patch.wx-show-cpu2
Author: Bryce Denney
Date: Fri Sep 6 12:13:28 EDT 2002
Description:
Second try at implementing the "Debug:Show Cpu" and "Debug:Show
Keyboard" dialog with values that change as the simulation proceeds.
(Nobody gets to see the first try.) This is the first step toward
making something resembling a wxWindows debugger.
First, variables which are going to be visible in the CI must be
registered as parameters. For some variables, it might be acceptable
to change them from Bit32u into bx_param_num_c and access them only
with set/get methods, but for most variables it would be a horrible
pain and wreck performance.
To deal with this, I introduced the concept of a shadow parameter. A
normal parameter has its value stored inside the struct, but a shadow
parameter has only a pointer to the value. Shadow params allow you to
treat any variable as if it was a parameter, without having to change
its type and access it using get/set methods. Of course, a shadow
param's value is controlled by someone else, so it can change at any
time.
To demonstrate and test the registration of shadow parameters, I
added code in cpu/init.cc to register a few CPU registers and
code in iodev/keyboard.cc to register a few keyboard state values.
Now these parameters are visible in the Debug:Show CPU and
Debug:Show Keyboard dialog boxes.
The Debug:Show* dialog boxes are created by the ParamDialog class,
which already understands how to display each type of parameter,
including the new shadow parameters (because they are just a subclass
of a normal parameter class). I have added a ParamDialog::Refresh()
method, which rereads the value from every parameter that it is
displaying and changes the displayed value. At the moment, in the
Debug:Show CPU dialog, changing the values has no effect. However
this is trivial to add when it's time (just call CommitChanges!). It
wouldn't really make sense to change the values unless you have paused
the simulation, for example when single stepping with the debugger.
The Refresh() method must be called periodically or else the dialog
will show the initial values forever. At the moment, Refresh() is
called when the simulator sends an async event called
BX_ASYNC_EVT_REFRESH, created by a call to SIM->refresh_ci ().
Details:
- implement shadow parameter class for Bit32s, called bx_shadow_num_c.
implement shadow parameter class for Boolean, called bx_shadow_bool_c.
more to follow (I need one for every type!)
- now the simulator thread can request that the config interface refresh
its display. For now, the refresh event causes the CI to check every
parameter it is watching and change the display value. Later, it may
be worth the trouble to keep track of which parameters have actually
changed. Code in the simulator thread calls SIM->refresh_ci(), which
creates an async event called BX_ASYNC_EVT_REFRESH and sends it to
the config interface. When it arrives in the wxWindows gui thread,
it calls RefreshDialogs(), which calls the Refresh() method on any
dialogs that might need it.
- in the debugger, SIM->refresh_ci() is called before every prompt
is printed. Otherwise, the refresh would wait until the next
SIM->periodic(), which might be thousands of cycles. This way,
when you're single stepping, the dialogs update with every step.
- To improve performance, the CI has a flag (MyFrame::WantRefresh())
which tells whether it has any need for refresh events. If no
dialogs are showing that need refresh events, then no event is sent
between threads.
- add a few defaults to the param classes that affect the settings of
newly created parameters. When declaring a lot of params with
similar settings it's more compact to set the default for new params
rather than to change each one separately. default_text_format is
the printf format string for displaying numbers. default_base is
the default base for displaying numbers (0, 16, 2, etc.)
- I added to ParamDialog to make it able to display modeless dialog
boxes such as "Debug:Show CPU". The new Refresh() method queries
all the parameters for their current value and changes the value in
the wxWindows control. The ParamDialog class still needs a little
work; for example, if it's modal it should have Cancel/Ok buttons,
but if it's going to be modeless it should maybe have Apply (commit
any changes) and Close.
problems with control-C handling if you enable readline, because readline()
installs its own signal handlers every time you call it. I'm having
good luck with "--with-wx --enable-debugger --disable-readline" now.
mode uses the notion of the guest-to-host TLB. This has the
benefit of allowing more uniform and streamlined acceleration
code in access.cc which does not have to check if CR0.PG
is set, eliminating a few instructions per guest access.
Shaved just a little off execution time, as expected.
Also, access_linear now breaks accesses which span two pages,
into two calls the the physical memory routines, when paging
is off, just like it always has for paging on. Besides
being more uniform, this allows the physical memory access
routines to known the complete data item is contained
within a single physical page, and stop reapplying the
A20ADDR() macro to pointers as it increments them.
Perhaps things can be optimized a little more now there too...
I renamed the routines to {read,write}PhysicalPage() as
a reminder that these routines now operate on data
solely within one page.
I also added a little code so that the paging module is
notified when the A20 line is tweaked, so it can dump
whatever mappings it wants to.
as no symbol. Now they will be relative to the last symbol.
- when anything was looked up in a segment with a nonzero base address,
it would print "non-zero base" and abort the lookup. I disabled this
behavior so that it would look up the symbol based on the EIP despite
the base. This change makes it possible to trace user processes, in
which the base is 0xc0000000.
- symbol lookup also used to fail in 16-bit code. Since the address
translations rules for 16-bit code are simple enough, I just compute
the 20-bit linear address and look up the symbol with it. Now I
can load a symbol table of the ROMBIOS and it works.
BEFORE it is executed. Print the registers at this time, BEFORE the
instruction, since they are the values BEFORE the instruction is executed.
The important result of this is that in TRACE output, both the instruction
causing an exception and the first instruction of the exception handler
are BOTH printed.
I'm working on getting this behavior in the debugger user-interface.
Modified Files:
cpu/cpu.cc debug/dbg_main.cc
in performance, but I did not check the debugger carefully enough while
testing them. Part of the performance gain in main.cc revision 1.33 and
cpu.cc revision 1.9 was to allow bochs to stay in the cpu loop forever
in a single processor simulation. (In a multiprocessor simulation it must
quit the loop periodically to give the other procs a chance to simulate
too. Cooperative multiprocessing?) In the process, I restored calls
to BX_TICK in the cpu loop for 1-proc simulation only, and removed them
from the outer loop. (See main.cc, since it was done right.) However
I never made the equivalent change in the debugger code, so in the
debugger, there were ticks coming from the cpu loop and then an
equivalent number of ticks coming from the debugger code just outside
the cpu loop. The result was, of course, that simulation time went
at 2x the correct rate. This simulation time speedup was made even
worse because the continue loop in the debugger would increment ticks
by one quantum (5 at the time) no matter how many instructions had
actually been executed. So in trace mode in particular, the way it was
implemented before today, cpu loop would run only one instruction at
a time and the simulation time would get incremented 1+5=6 times! One
tick from the cpu loop, then 5 erroneous ticks from the continue loop.
Anyway, much of this nonsense should be fixed now. For uniprocessor
simulations, only the cpu loop does ticks (for best performance). For
multiprocessor simulations, the cpu loop exits after one quantum and
the code that calls the cpu loop gets to increment ticks instead.
> This patch fixes a number of debugger problems.
> - with trace-on, simulation time would pass 5x faster than usual, so
> interrupts and other timed events would happen at different times
> - with trace-on, breakpoints were ignored
> - with trace-on, control-C would not stop the processor and return to the
> debugger.
>
> This patch changes the execution quantum for the debugger to 1, which means
> that cpu_loop is asked to do one instruction at a time. This may cause
> bochs with the debugger to be slower than before.
>
> I haven't tested without the debugger yet, so I don't know if the timing
> of events matches or not.
in an output format similar to gdb (when you do info all-registers).
Also, if you do "info all" you get the CPU registers and the FPU
registers.
- added bx_cpu_c method called fpu_print_regs, which is implemented
in wmFPUemu_glue.cc
bochs debugger needed to be updated in the same way. Instead of
using "bx_options.rom.path" as a string, it's now
bx_options.rom.path->getptr () to get the value of the parameter.
when main.cc no longer had one. Now compiling with debugger is working
with the control panel. To get the control panel, you have to click
the snapshot button, and to get the debugger, you have to press ^C.
These should be better integrated (maybe a control panel menu choice
that jumps into the debugger and a debugger command that starts the
runtime control panel...)
BX_SUPPORT_APIC were used. To follow the pattern used by other
names like this, I changed them all to BX_SUPPORT_APIC.
Thanks to Tom Lindström for chasing this down!