Bochs/bochs/fpu/fpu_system.h
Bryce Denney f850a6df1f These changes are from "portable1" patch.
- put /*comments symbols*/ around any chars after #endif.  Other compilers
  do not get it.
- fix cases in which a pointer is cast to a 32-bit int, then back to a
  pointer.  This breaks on a machine with 64-bit pointers.  Examples:
  FPU_sub arg 2 and FPU_div arg 2.  The int->ptr->int conversions are
  now done more safely by macros REGNO2PTR and PTR2INT.
- use GCC_ATTRIBUTE macro instead of __attribute__.  For compilers that
  do not support __attribute__, the macro can be defined to be nothing.
- in fpu_entry.c, arg1 of FPU_load_int32 is (s32*), but the calls to
  it cast their data to (u32*).
- if compiler does NOT inline functions in poly.h, the "extern inline"
  setting caused duplicate symbols to be created.  Changed them to
  "static inline" so that the mul_32_32 from different .c files do not
  conflict.
- implemented setcc so that it doesn't use curly brackets inside parens
- comment out sigcontext structure definition, which conflicts with
  non-linux or non-intel operating systems.  It's not used by bochs anyway.
2001-04-10 01:43:09 +00:00

219 lines
7.2 KiB
C

/*---------------------------------------------------------------------------+
| fpu_system.h |
| |
| Copyright (C) 1992,1994,1997 |
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
| Australia. E-mail billm@suburbia.net |
| |
+---------------------------------------------------------------------------*/
#ifndef _FPU_SYSTEM_H
#define _FPU_SYSTEM_H
#ifndef USE_WITH_CPU_SIM
/* system dependent definitions */
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
/* This sets the pointer FPU_info to point to the argument part
of the stack frame of math_emulate() */
#define SETUP_DATA_AREA(arg) FPU_info = (struct info *) &arg
#define LDT_DESCRIPTOR(s) (((struct desc_struct *)current->mm->segments)[(s) >> 3])
#define SEG_D_SIZE(x) ((x).b & (3 << 21))
#define SEG_G_BIT(x) ((x).b & (1 << 23))
#define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1)
#define SEG_286_MODE(x) ((x).b & ( 0xff000000 | 0xf0000 | (1 << 23)))
#define SEG_BASE_ADDR(s) (((s).b & 0xff000000) \
| (((s).b & 0xff) << 16) | ((s).a >> 16))
#define SEG_LIMIT(s) (((s).b & 0xff0000) | ((s).a & 0xffff))
#define SEG_EXECUTE_ONLY(s) (((s).b & ((1 << 11) | (1 << 9))) == (1 << 11))
#define SEG_WRITE_PERM(s) (((s).b & ((1 << 11) | (1 << 9))) == (1 << 9))
#define SEG_EXPAND_DOWN(s) (((s).b & ((1 << 11) | (1 << 10))) \
== (1 << 10))
#define I387 (current->tss.i387)
#define FPU_info (I387.soft.info)
#define FPU_CS (*(u16 *) &(FPU_info->___cs))
#define FPU_SS (*(u16 *) &(FPU_info->___ss))
#define FPU_DS (*(u16 *) &(FPU_info->___ds))
#define FPU_EAX (FPU_info->___eax)
#define FPU_EFLAGS (FPU_info->___eflags)
#define FPU_EIP (FPU_info->___eip)
#define FPU_ORIG_EIP (FPU_info->___orig_eip)
#define FPU_lookahead (I387.soft.lookahead)
#define SET_AX(val16) *(s16 *) &FPU_EAX = val16
/* nz if ip_offset and cs_selector are not to be set for the current
instruction. */
#define no_ip_update (*(u_char *)&(I387.soft.no_update))
#define FPU_rm (*(u_char *)&(I387.soft.rm))
/* Number of bytes of data which can be legally accessed by the current
instruction. This only needs to hold a number <= 108, so a byte will do. */
#define access_limit (*(u_char *)&(I387.soft.alimit))
#define partial_status (I387.soft.swd)
#define control_word (I387.soft.cwd)
#define fpu_tag_word (I387.soft.twd)
#define registers (I387.soft.st_space)
#define top (I387.soft.ftop)
#define instruction_address (*(struct address *)&I387.soft.fip)
#define operand_address (*(struct address *)&I387.soft.foo)
#define FPU_verify_area(x,y,z) if ( verify_area(x,y,z) ) \
math_abort(FPU_info,SIGSEGV)
#undef FPU_IGNORE_CODE_SEGV
#ifdef FPU_IGNORE_CODE_SEGV
/* verify_area() is very expensive, and causes the emulator to run
about 20% slower if applied to the code. Anyway, errors due to bad
code addresses should be much rarer than errors due to bad data
addresses. */
#define FPU_code_verify_area(z)
#else
/* A simpler test than verify_area() can probably be done for
FPU_code_verify_area() because the only possible error is to step
past the upper boundary of a legal code area. */
#define FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void *)FPU_EIP,z)
#endif
#define FPU_get_user(x,y) get_user((x),(y))
#define FPU_put_user(x,y) put_user((x),(y))
#else /* USE_WITH_CPU_SIM */
/* -----------------------------------------------------------
* Slimmed down version used to compile against a CPU simulator
* rather than a kernel (ported by Kevin Lawton)
* ------------------------------------------------------------ */
/* Get data sizes from config.h generated from simulator's
* configure script
*/
#include "config.h"
typedef Bit8u u8;
typedef Bit8s s8;
typedef Bit16u u16;
typedef Bit16s s16;
typedef Bit32u u32;
typedef Bit32s s32;
typedef Bit64u u64;
typedef Bit64s s64;
/* bbd: include ported linux headers after config.h for GCC_ATTRIBUTE macro */
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/math_emu.h>
#include <linux/types.h>
#ifndef WORDS_BIGENDIAN
#error "WORDS_BIGENDIAN not defined in config.h"
#elif WORDS_BIGENDIAN == 1
#define EMU_BIG_ENDIAN 1
#else
/* Nothing needed. Lack of defining EMU_BIG_ENDIAN means
* small endian
*/
#endif
extern unsigned fpu_get_user(void *ptr, unsigned len);
extern void fpu_put_user(unsigned val, void *ptr, unsigned len);
extern void fpu_verify_area(unsigned what, void *ptr, unsigned n);
extern void math_emulate_init(void);
extern unsigned fpu_get_ds(void);
extern void fpu_set_ax(u16);
#ifndef __ASSEMBLY__
struct info {
#ifdef BX_NO_EMPTY_STRUCTS
unsigned char donotindexme;
#endif
};
#define FPU_info ((struct info *) NULL)
//
// Minimal i387 structure, pruned from the linux headers. Only
// the fields which were necessary are included.
//
typedef struct {
struct {
s32 cwd;
s32 swd;
s32 twd;
s32 fip;
s32 fcs;
s32 foo;
s32 fos;
u32 fill0; /* to make sure the following aligns on an 8byte boundary */
u64 st_space[16]; /* 8*16 bytes per FP-reg (aligned) = 128 bytes */
unsigned char ftop;
unsigned char no_update;
unsigned char rm;
unsigned char alimit;
} GCC_ATTRIBUTE((aligned(16), packed)) soft;
} i387_t;
extern i387_t i387;
#endif
#define SIGSEGV 11
#define I387 i387
#define SET_AX(val16) fpu_set_ax(val16);
#define no_ip_update (*(u_char *)&(I387.soft.no_update))
#define FPU_rm (*(u_char *)&(I387.soft.rm))
/* Number of bytes of data which can be legally accessed by the current
instruction. This only needs to hold a number <= 108, so a byte will do. */
#define access_limit (*(u_char *)&(I387.soft.alimit))
#define partial_status (I387.soft.swd)
#define control_word (I387.soft.cwd)
#define fpu_tag_word (I387.soft.twd)
#define registers (I387.soft.st_space)
#define top (I387.soft.ftop)
#define instruction_address (*(struct address *)&I387.soft.fip)
#define operand_address (*(struct address *)&I387.soft.foo)
#define FPU_verify_area(x,y,z) fpu_verify_area(x,y,z)
#define FPU_get_user(x,y) ((x) = fpu_get_user((y), sizeof(*(y))))
#define FPU_put_user(val,ptr) fpu_put_user((val),(ptr),sizeof(*(ptr)))
#define FPU_DS (fpu_get_ds())
#endif /* USE_WITH_CPU_SIM */
// bbd: Change a pointer to an int, with type conversions that make it legal.
// First make it a void pointer, then convert to an integer of the same
// size as the pointer. Otherwise, on machines with 64-bit pointers,
// compilers complain when you typecast a 64-bit pointer into a 32-bit integer.
#define PTR2INT(x) ((bx_ptr_equiv_t)(void *)(x))
// bbd: Change an int to a pointer, with type conversions that make it legal.
// Same strategy as PTR2INT: change to bx_ptr_equiv_t which is an integer
// type of the same size as FPU_REG*. Then the conversion to pointer
// is legal.
#define REGNO2PTR(x) ((FPU_REG*)((bx_ptr_equiv_t)(x)))
#endif