root/kernel/math/ea.c

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

DEFINITIONS

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

   1 /*
   2  * linux/kernel/math/ea.c
   3  *
   4  * Copyright (C) 1991, 1992 Linus Torvalds
   5  */
   6 
   7 /*
   8  * Calculate the effective address.
   9  */
  10 
  11 #include <linux/stddef.h>
  12 #include <linux/math_emu.h>
  13 
  14 #include <asm/segment.h>
  15 
  16 static int __regoffset[] = {
  17         offsetof(struct info,___eax),
  18         offsetof(struct info,___ecx),
  19         offsetof(struct info,___edx),
  20         offsetof(struct info,___ebx),
  21         offsetof(struct info,___esp),
  22         offsetof(struct info,___ebp),
  23         offsetof(struct info,___esi),
  24         offsetof(struct info,___edi)
  25 };
  26 
  27 #define REG(x) (*(long *)(__regoffset[(x)]+(char *) info))
  28 
  29 static char * sib(struct info * info, int mod)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31         unsigned char ss,index,base;
  32         long offset = 0;
  33 
  34         base = get_fs_byte((char *) EIP);
  35         EIP++;
  36         ss = base >> 6;
  37         index = (base >> 3) & 7;
  38         base &= 7;
  39         if (index == 4)
  40                 offset = 0;
  41         else
  42                 offset = REG(index);
  43         offset <<= ss;
  44         if (mod || base != 5)
  45                 offset += REG(base);
  46         if (mod == 1) {
  47                 offset += (signed char) get_fs_byte((char *) EIP);
  48                 EIP++;
  49         } else if (mod == 2 || base == 5) {
  50                 offset += (signed) get_fs_long((unsigned long *) EIP);
  51                 EIP += 4;
  52         }
  53         I387.foo = offset;
  54         I387.fos = 0x17;
  55         return (char *) offset;
  56 }
  57 
  58 char * ea(struct info * info, unsigned short code)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         unsigned char mod,rm;
  61         long * tmp;
  62         int offset = 0;
  63 
  64         mod = (code >> 6) & 3;
  65         rm = code & 7;
  66         if (rm == 4 && mod != 3)
  67                 return sib(info,mod);
  68         if (rm == 5 && !mod) {
  69                 offset = get_fs_long((unsigned long *) EIP);
  70                 EIP += 4;
  71                 I387.foo = offset;
  72                 I387.fos = 0x17;
  73                 return (char *) offset;
  74         }
  75         tmp = & REG(rm);
  76         switch (mod) {
  77                 case 0: offset = 0; break;
  78                 case 1:
  79                         offset = (signed char) get_fs_byte((char *) EIP);
  80                         EIP++;
  81                         break;
  82                 case 2:
  83                         offset = (signed) get_fs_long((unsigned long *) EIP);
  84                         EIP += 4;
  85                         break;
  86                 case 3:
  87                         math_abort(info,SIGILL);
  88         }
  89         I387.foo = offset;
  90         I387.fos = 0x17;
  91         return offset + (char *) *tmp;
  92 }

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