Annotation of coherent/b/kernel/emulator/get_address.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.