|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.