root/drivers/FPU-emu/get_address.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sib
  2. get_address

   1 /*---------------------------------------------------------------------------+
   2  |  get_address.c                                                            |
   3  |                                                                           |
   4  | Get the effective address from an FPU instruction.                        |
   5  |                                                                           |
   6  | Copyright (C) 1992,1993,1994                                              |
   7  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
   8  |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
   9  |                                                                           |
  10  |                                                                           |
  11  +---------------------------------------------------------------------------*/
  12 
  13 /*---------------------------------------------------------------------------+
  14  | Note:                                                                     |
  15  |    The file contains code which accesses user memory.                     |
  16  |    Emulator static data may change when user memory is accessed, due to   |
  17  |    other processes using the emulator while swapping is in progress.      |
  18  +---------------------------------------------------------------------------*/
  19 
  20 
  21 #include <linux/stddef.h>
  22 
  23 #include <asm/segment.h>
  24 
  25 #include "fpu_system.h"
  26 #include "exception.h"
  27 #include "fpu_emu.h"
  28 
  29 static int reg_offset[] = {
  30         offsetof(struct info,___eax),
  31         offsetof(struct info,___ecx),
  32         offsetof(struct info,___edx),
  33         offsetof(struct info,___ebx),
  34         offsetof(struct info,___esp),
  35         offsetof(struct info,___ebp),
  36         offsetof(struct info,___esi),
  37         offsetof(struct info,___edi)
  38 };
  39 
  40 #define REG_(x) (*(long *)(reg_offset[(x)]+(char *) FPU_info))
  41 
  42 
  43 /* Decode the SIB byte. This function assumes mod != 0 */
  44 static void *sib(int mod)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46   unsigned char ss,index,base;
  47   long offset;
  48 
  49   RE_ENTRANT_CHECK_OFF;
  50   FPU_code_verify_area(1);
  51   base = get_fs_byte((char *) FPU_EIP);   /* The SIB byte */
  52   RE_ENTRANT_CHECK_ON;
  53   FPU_EIP++;
  54   ss = base >> 6;
  55   index = (base >> 3) & 7;
  56   base &= 7;
  57 
  58   if ((mod == 0) && (base == 5))
  59     offset = 0;              /* No base register */
  60   else
  61     offset = REG_(base);
  62 
  63   if (index == 4)
  64     {
  65       /* No index register */
  66       /* A non-zero ss is illegal */
  67       if ( ss )
  68         EXCEPTION(EX_Invalid);
  69     }
  70   else
  71     {
  72       offset += (REG_(index)) << ss;
  73     }
  74 
  75   if (mod == 1)
  76     {
  77       /* 8 bit signed displacement */
  78       RE_ENTRANT_CHECK_OFF;
  79       FPU_code_verify_area(1);
  80       offset += (signed char) get_fs_byte((char *) FPU_EIP);
  81       RE_ENTRANT_CHECK_ON;
  82       FPU_EIP++;
  83     }
  84   else if (mod == 2 || base == 5) /* The second condition also has mod==0 */
  85     {
  86       /* 32 bit displacment */
  87       RE_ENTRANT_CHECK_OFF;
  88       FPU_code_verify_area(4);
  89       offset += (signed) get_fs_long((unsigned long *) FPU_EIP);
  90       RE_ENTRANT_CHECK_ON;
  91       FPU_EIP += 4;
  92     }
  93 
  94   return (void *) offset;
  95 }
  96 
  97 
  98 /*
  99        MOD R/M byte:  MOD == 3 has a special use for the FPU
 100                       SIB byte used iff R/M = 100b
 101 
 102        7   6   5   4   3   2   1   0
 103        .....   .........   .........
 104         MOD    OPCODE(2)     R/M
 105 
 106 
 107        SIB byte
 108 
 109        7   6   5   4   3   2   1   0
 110        .....   .........   .........
 111         SS      INDEX        BASE
 112 
 113 */
 114 
 115 void get_address(unsigned char FPU_modrm)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117   unsigned char mod;
 118   long *cpu_reg_ptr;
 119   int offset = 0;     /* Initialized just to stop compiler warnings. */
 120 
 121 #ifndef PECULIAR_486
 122   /* This is a reasonable place to do this */
 123   FPU_data_selector = FPU_DS;
 124 #endif PECULIAR_486
 125 
 126   mod = (FPU_modrm >> 6) & 3;
 127 
 128   if (FPU_rm == 4 && mod != 3)
 129     {
 130       FPU_data_address = sib(mod);
 131       return;
 132     }
 133 
 134   cpu_reg_ptr = & REG_(FPU_rm);
 135   switch (mod)
 136     {
 137     case 0:
 138       if (FPU_rm == 5)
 139         {
 140           /* Special case: disp32 */
 141           RE_ENTRANT_CHECK_OFF;
 142           FPU_code_verify_area(4);
 143           offset = get_fs_long((unsigned long *) FPU_EIP);
 144           RE_ENTRANT_CHECK_ON;
 145           FPU_EIP += 4;
 146           FPU_data_address = (void *) offset;
 147           return;
 148         }
 149       else
 150         {
 151           FPU_data_address = (void *)*cpu_reg_ptr;  /* Just return the contents
 152                                                    of the cpu register */
 153           return;
 154         }
 155     case 1:
 156       /* 8 bit signed displacement */
 157       RE_ENTRANT_CHECK_OFF;
 158       FPU_code_verify_area(1);
 159       offset = (signed char) get_fs_byte((char *) FPU_EIP);
 160       RE_ENTRANT_CHECK_ON;
 161       FPU_EIP++;
 162       break;
 163     case 2:
 164       /* 32 bit displacement */
 165       RE_ENTRANT_CHECK_OFF;
 166       FPU_code_verify_area(4);
 167       offset = (signed) get_fs_long((unsigned long *) FPU_EIP);
 168       RE_ENTRANT_CHECK_ON;
 169       FPU_EIP += 4;
 170       break;
 171     case 3:
 172       /* Not legal for the FPU */
 173       EXCEPTION(EX_Invalid);
 174     }
 175 
 176   FPU_data_address = offset + (char *)*cpu_reg_ptr;
 177 }

/* [previous][next][first][last][top][bottom][index][help] */