Annotation of coherent/b/kernel/emulator/get_address.c, revision 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.