CTC++ Coverage Report - Execution Profile    #3/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: arch/x86_64/ia32/fpu32.c
Instrumentation mode: function-decision-multicondition
TER: 45 % ( 33/ 73)

Start/ End/    
True False - Line Source

  1 /* 
  2  * Copyright 2002 Andi Kleen, SuSE Labs.
  3  * FXSAVE<->i387 conversion support. Based on code by Gareth Hughes.
  4  * This is used for ptrace, signals and coredumps in 32bit emulation.
  5  * $Id: fpu32.c,v 1.1 2002/03/21 14:16:32 ak Exp $
  6  */ 
  7 
  8 #include <linux/sched.h>
  9 #include <asm/sigcontext32.h>
  10 #include <asm/processor.h>
  11 #include <asm/uaccess.h>
  12 #include <asm/i387.h>
  13 
 
112   14 static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
  15 {
  16    unsigned int tmp; /* to avoid 16 bit prefixes in the code */
  17  
  18    /* Transform each pair of bits into 01 (valid) or 00 (empty) */
  19         tmp = ~twd;
  20         tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
  21         /* and move the valid bits to the lower byte. */
  22         tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
  23         tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
  24         tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
112    25         return tmp;
  26 }
  27 
 
114   28 static inline unsigned long twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave)
  29 {
  30    struct _fpxreg *st = NULL;
  31    unsigned long tos = (fxsave->swd >> 11) & 7;
  32    unsigned long twd = (unsigned long) fxsave->twd;
  33    unsigned long tag;
  34    unsigned long ret = 0xffff0000;
  35    int i;
  36 
  37 #define FPREG_ADDR(f, n)   ((void *)&(f)->st_space + (n) * 16);
  38 
912 114   39    for (i = 0 ; i < 8 ; i++) {
912 - 40       if (twd & 0x1) {
  41          st = FPREG_ADDR( fxsave, (i - tos) & 7 );
  42 
    43          switch (st->exponent & 0x7fff) {
 - 44          case 0x7fff:
  45             tag = 2;      /* Special */
 - 46             break;
 - 47          case 0x0000:
  48             if ( !st->significand[0] &&
  49                  !st->significand[1] &&
  50                  !st->significand[2] &&
- 51                  !st->significand[3] ) {
 - 51         T && T && T && T
 - 51         T && T && T && F
 - 51         T && T && F && _
 - 51         T && F && _ && _
 - 51         F && _ && _ && _
  52                tag = 1;   /* Zero */
    53             } else {
  54                tag = 2;   /* Special */
  55             }
 - 56             break;
 - 57          default:
- 58             if (st->significand[3] & 0x8000) {
  59                tag = 0;   /* Valid */
    60             } else {
  61                tag = 2;   /* Special */
  62             }
 - 63             break;
  64          }
    65       } else {
  66          tag = 3;         /* Empty */
  67       }
  68       ret |= (tag << (2 * i));
  69       twd = twd >> 1;
  70    }
114    71    return ret;
  72 }
  73 
  74 
 
112   75 static inline int convert_fxsr_from_user(struct i387_fxsave_struct *fxsave,
  76                 struct _fpstate_ia32 __user *buf)
  77 {
  78    struct _fpxreg *to;
  79    struct _fpreg __user *from;
  80    int i;
  81    u32 v;
  82    int err = 0;
  83 
  84 #define G(num,val) err |= __get_user(val, num + (u32 __user *)buf)
  85    G(0, fxsave->cwd);
  86    G(1, fxsave->swd);
  87    G(2, fxsave->twd);
  88    fxsave->twd = twd_i387_to_fxsr(fxsave->twd);
  89    G(3, fxsave->rip);
  90    G(4, v);
  91    fxsave->fop = v>>16;   /* cs ignored */
  92    G(5, fxsave->rdp);
  93    /* 6: ds ignored */
  94 #undef G
112 - 95    if (err) 
 - 96       return -1; 
  97 
  98    to = (struct _fpxreg *)&fxsave->st_space[0];
  99    from = &buf->_st[0];
896 112   100    for (i = 0 ; i < 8 ; i++, to++, from++) {
896 - 101       if (__copy_from_user(to, from, sizeof(*from)))
 - 102          return -1;
  103    }
112    104    return 0;
  105 }
  106 
  107 
 
114   108 static inline int convert_fxsr_to_user(struct _fpstate_ia32 __user *buf,
  109                    struct i387_fxsave_struct *fxsave,
  110                    struct pt_regs *regs,
  111                    struct task_struct *tsk)
  112 {
  113    struct _fpreg __user *to;
  114    struct _fpxreg *from;
  115    int i;
  116    u16 cs,ds; 
  117    int err = 0; 
  118 
114 - 119    if (tsk == current) {
  120       /* should be actually ds/cs at fpu exception time,
  121          but that information is not available in 64bit mode. */
  122       asm("movw %%ds,%0 " : "=r" (ds)); 
  123       asm("movw %%cs,%0 " : "=r" (cs));       
    124    } else { /* ptrace. task has stopped. */
  125       ds = tsk->thread.ds;
  126       cs = regs->cs;
  127    } 
  128 
  129 #define P(num,val) err |= __put_user(val, num + (u32 __user *)buf)
  130    P(0, (u32)fxsave->cwd | 0xffff0000);
  131    P(1, (u32)fxsave->swd | 0xffff0000);
  132    P(2, twd_fxsr_to_i387(fxsave));
  133    P(3, (u32)fxsave->rip);
  134    P(4,  cs | ((u32)fxsave->fop) << 16); 
  135    P(5, fxsave->rdp);
  136    P(6, 0xffff0000 | ds);
  137 #undef P
  138 
114 - 139    if (err) 
 - 140       return -1; 
  141 
  142    to = &buf->_st[0];
  143    from = (struct _fpxreg *) &fxsave->st_space[0];
912 114   144    for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
912 - 145       if (__copy_to_user(to, from, sizeof(*to)))
 - 146          return -1;
  147    }
114    148    return 0;
  149 }
  150 
 
112   151 int restore_i387_ia32(struct task_struct *tsk, struct _fpstate_ia32 __user *buf, int fsave) 
  152 
    153    clear_fpu(tsk);
112 - 153   if (( tsk ) -> thread_info -> status & 0x0001)
112 - 153 do-while (0)
112 - 154    if (!fsave) { 
  155       if (__copy_from_user(&tsk->thread.i387.fxsave, 
  156                  &buf->_fxsr_env[0],
112 - 157                  sizeof(struct i387_fxsave_struct)))
 - 158          return -1;
  159       tsk->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
    160       set_stopped_child_used_math(tsk);
112 - 160   do-while (0)
  161    } 
112    162    return convert_fxsr_from_user(&tsk->thread.i387.fxsave, buf);
  163 }  
  164 
 
114   165 int save_i387_ia32(struct task_struct *tsk, 
  166          struct _fpstate_ia32 __user *buf, 
  167          struct pt_regs *regs,
  168          int fsave)
  169 {
  170    int err = 0;
  171 
  172    init_fpu(tsk);
114 - 173    if (convert_fxsr_to_user(buf, &tsk->thread.i387.fxsave, regs, tsk))
 - 174       return -1;
114 - 175    if (fsave)
 - 176       return 0;
  177    err |= __put_user(tsk->thread.i387.fxsave.swd, &buf->status);
114 - 178    if (fsave) 
    179       return err ? -1 : 1;    
- 179   ternary-?: err
 - 179   return err ? - 1 : 1
  180    err |= __put_user(X86_FXSR_MAGIC, &buf->magic);
  181    err |= __copy_to_user(&buf->_fxsr_env[0], &tsk->thread.i387.fxsave,
  182                sizeof(struct i387_fxsave_struct));
    183    return err ? -1 : 1;
114 - 183 ternary-?: err
114    183 return err ? - 1 : 1
  184 }
***TER 45% (33/73) of SOURCE FILE fpu32.c

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last | Top