#include "defs.h"
#include "inferior.h"
#include "floatformat.h"
#include "regcache.h"
#include <stdio.h>
#include <mach.h>
#include <mach/message.h>
#include <mach/exception.h>
#include <mach_error.h>
#include <target.h>
#include <sys/param.h>
#if UPAGES == 16
#define UAREA_SIZE ctob(UPAGES)
#elif UPAGES == 2
#define UAREA_SIZE (NBPG*UPAGES)
#else
FIXME ! !UPAGES is neither 2 nor 16
#endif
extern void print_387_control_word ();
extern void print_387_status_word ();
#define private static
#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
static int reg_offset[] =
{
REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
};
#define REG_ADDRESS(state,regnum) ((char *)(state)+reg_offset[regnum])
#define FETCH_REGS(state, regnum, count) \
memcpy (®isters[REGISTER_BYTE (regnum)], \
REG_ADDRESS (state, regnum), \
count*REGISTER_SIZE)
#define STORE_REGS(state, regnum, count) \
memcpy (REG_ADDRESS (state, regnum), \
®isters[REGISTER_BYTE (regnum)], \
count*REGISTER_SIZE)
void
fetch_inferior_registers (int regno)
{
kern_return_t ret;
thread_state_data_t state;
unsigned int stateCnt = i386_THREAD_STATE_COUNT;
int index;
if (!MACH_PORT_VALID (current_thread))
error ("fetch inferior registers: Invalid thread");
if (must_suspend_thread)
setup_thread (current_thread, 1);
ret = thread_get_state (current_thread,
i386_THREAD_STATE,
state,
&stateCnt);
if (ret != KERN_SUCCESS)
warning ("fetch_inferior_registers: %s ",
mach_error_string (ret));
#if 0
else if (regno != -1)
supply_register (regno, (char *) state + reg_offset[regno]);
#endif
else
{
for (index = 0; index < NUM_REGS; index++)
supply_register (index, (char *) state + reg_offset[index]);
}
if (must_suspend_thread)
setup_thread (current_thread, 0);
}
void
store_inferior_registers (int regno)
{
kern_return_t ret;
thread_state_data_t state;
unsigned int stateCnt = i386_THREAD_STATE_COUNT;
register int index;
if (!MACH_PORT_VALID (current_thread))
error ("store inferior registers: Invalid thread");
if (must_suspend_thread)
setup_thread (current_thread, 1);
ret = thread_get_state (current_thread,
i386_THREAD_STATE,
state,
&stateCnt);
if (ret != KERN_SUCCESS)
{
warning ("store_inferior_registers (get): %s",
mach_error_string (ret));
if (must_suspend_thread)
setup_thread (current_thread, 0);
return;
}
#if 0
if (regno != -1)
STORE_REGS (state, regno, 1);
else
#endif
{
for (index = 0; index < NUM_REGS; index++)
STORE_REGS (state, index, 1);
}
ret = thread_set_state (current_thread,
i386_THREAD_STATE,
state,
i386_THREAD_STATE_COUNT);
if (ret != KERN_SUCCESS)
warning ("store_inferior_registers (set): %s",
mach_error_string (ret));
if (must_suspend_thread)
setup_thread (current_thread, 0);
}
CORE_ADDR
register_addr (int regno, CORE_ADDR blockend)
{
CORE_ADDR addr;
if (regno < 0 || regno >= NUM_REGS)
error ("Invalid register number %d.", regno);
addr = (unsigned int) REG_ADDRESS (UAREA_SIZE - sizeof (struct i386_thread_state), regno);
return addr;
}
struct env387
{
unsigned short control;
unsigned short r0;
unsigned short status;
unsigned short r1;
unsigned short tag;
unsigned short r2;
unsigned long eip;
unsigned short code_seg;
unsigned short opcode;
unsigned long operand;
unsigned short operand_seg;
unsigned short r3;
unsigned char regs[8][10];
};
private
print_387_status (unsigned short status, struct env387 *ep)
{
int i;
int bothstatus;
int top;
int fpreg;
unsigned char *p;
bothstatus = ((status != 0) && (ep->status != 0));
if (status != 0)
{
if (bothstatus)
printf_unfiltered ("u: ");
print_387_status_word (status);
}
if (ep->status != 0)
{
if (bothstatus)
printf_unfiltered ("e: ");
print_387_status_word (ep->status);
}
print_387_control_word (ep->control);
printf_unfiltered ("last exception: ");
printf_unfiltered ("opcode %s; ", local_hex_string (ep->opcode));
printf_unfiltered ("pc %s:", local_hex_string (ep->code_seg));
printf_unfiltered ("%s; ", local_hex_string (ep->eip));
printf_unfiltered ("operand %s", local_hex_string (ep->operand_seg));
printf_unfiltered (":%s\n", local_hex_string (ep->operand));
top = (ep->status >> 11) & 7;
printf_unfiltered ("regno tag msb lsb value\n");
for (fpreg = 7; fpreg >= 0; fpreg--)
{
double val;
printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
switch ((ep->tag >> (fpreg * 2)) & 3)
{
case 0:
printf_unfiltered ("valid ");
break;
case 1:
printf_unfiltered ("zero ");
break;
case 2:
printf_unfiltered ("trap ");
break;
case 3:
printf_unfiltered ("empty ");
break;
}
for (i = 9; i >= 0; i--)
printf_unfiltered ("%02x", ep->regs[fpreg][i]);
floatformat_to_double (&floatformat_i387_ext, (char *) ep->regs[fpreg],
&val);
printf_unfiltered (" %g\n", val);
}
if (ep->r0)
printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string (ep->r0));
if (ep->r1)
printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string (ep->r1));
if (ep->r2)
printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string (ep->r2));
if (ep->r3)
printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string (ep->r3));
}
#define FP_NO 0
#define FP_SW 1
#define FP_HW 2
#define FP_287 2
#define FP_387 3
typedef struct fpstate
{
#if 1
unsigned char state[FP_STATE_BYTES];
#else
struct env387 state;
#endif
int status;
}
*fpstate_t;
private boolean_t
get_i387_state (struct fpstate *fstate)
{
kern_return_t ret;
thread_state_data_t state;
unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
struct i386_float_state *fsp;
ret = thread_get_state (current_thread,
i386_FLOAT_STATE,
state,
&fsCnt);
if (ret != KERN_SUCCESS)
{
warning ("Can not get live floating point state: %s",
mach_error_string (ret));
return FALSE;
}
fsp = (struct i386_float_state *) state;
if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
return FALSE;
memset (fstate, 0, sizeof (struct fpstate));
fstate->status = fsp->exc_status;
memcpy (fstate->state, (char *) &fsp->hw_state, FP_STATE_BYTES);
return TRUE;
}
private boolean_t
get_i387_core_state (struct fpstate *fstate)
{
return FALSE;
}
void
i386_mach3_float_info (void)
{
char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
boolean_t valid = FALSE;
fpstate_t fps;
if (target_has_execution)
valid = get_i387_state (buf);
#if 0
else if (WE HAVE CORE FILE)
valid = get_i387_core_state (buf);
#endif
if (!valid)
{
warning ("no floating point status saved");
return;
}
fps = (fpstate_t) buf;
print_387_status (fps->status, (struct env387 *) fps->state);
}