/[qemu]/qemu/target-ppc/op_helper.c
ViewVC logotype

Diff of /qemu/target-ppc/op_helper.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.15 by bellard, Sat Jul 2 22:09:27 2005 UTC revision 1.16 by bellard, Mon Jul 4 22:17:05 2005 UTC
# Line 29  Line 29 
29  #include "op_helper_mem.h"  #include "op_helper_mem.h"
30  #endif  #endif
31    
32    //#define DEBUG_OP
33    //#define DEBUG_EXCEPTIONS
34    //#define FLUSH_ALL_TLBS
35    
36    #define Ts0 (long)((target_long)T0)
37    #define Ts1 (long)((target_long)T1)
38    #define Ts2 (long)((target_long)T2)
39    
40  /*****************************************************************************/  /*****************************************************************************/
41  /* Exceptions processing helpers */  /* Exceptions processing helpers */
42  void cpu_loop_exit(void)  void cpu_loop_exit(void)
# Line 60  void do_raise_exception (uint32_t except Line 68  void do_raise_exception (uint32_t except
68  }  }
69    
70  /*****************************************************************************/  /*****************************************************************************/
71  /* Helpers for "fat" micro operations */  /* Fixed point operations helpers */
72    void do_addo (void)
73    {
74        T2 = T0;
75        T0 += T1;
76        if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
77            xer_ov = 0;
78        } else {
79            xer_so = 1;
80            xer_ov = 1;
81        }
82    }
83    
84    void do_addco (void)
85    {
86        T2 = T0;
87        T0 += T1;
88        if (likely(T0 >= T2)) {
89            xer_ca = 0;
90        } else {
91            xer_ca = 1;
92        }
93        if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
94            xer_ov = 0;
95        } else {
96            xer_so = 1;
97            xer_ov = 1;
98        }
99    }
100    
101    void do_adde (void)
102    {
103        T2 = T0;
104        T0 += T1 + xer_ca;
105        if (likely(!(T0 < T2 || (xer_ca == 1 && T0 == T2)))) {
106            xer_ca = 0;
107        } else {
108            xer_ca = 1;
109        }
110    }
111    
112    void do_addeo (void)
113    {
114        T2 = T0;
115        T0 += T1 + xer_ca;
116        if (likely(!(T0 < T2 || (xer_ca == 1 && T0 == T2)))) {
117            xer_ca = 0;
118        } else {
119            xer_ca = 1;
120        }
121        if (likely(!((T2 ^ T1 ^ (-1)) & (T2 ^ T0) & (1 << 31)))) {
122            xer_ov = 0;
123        } else {
124            xer_so = 1;
125            xer_ov = 1;
126        }
127    }
128    
129    void do_addmeo (void)
130    {
131        T1 = T0;
132        T0 += xer_ca + (-1);
133        if (likely(!(T1 & (T1 ^ T0) & (1 << 31)))) {
134            xer_ov = 0;
135        } else {
136            xer_so = 1;
137            xer_ov = 1;
138        }
139        if (likely(T1 != 0))
140            xer_ca = 1;
141    }
142    
143    void do_addzeo (void)
144    {
145        T1 = T0;
146        T0 += xer_ca;
147        if (likely(!((T1 ^ (-1)) & (T1 ^ T0) & (1 << 31)))) {
148            xer_ov = 0;
149        } else {
150            xer_so = 1;
151            xer_ov = 1;
152        }
153        if (likely(T0 >= T1)) {
154            xer_ca = 0;
155        } else {
156            xer_ca = 1;
157        }
158    }
159    
160    void do_divwo (void)
161    {
162        if (likely(!((Ts0 == INT32_MIN && Ts1 == -1) || Ts1 == 0))) {
163            xer_ov = 0;
164            T0 = (Ts0 / Ts1);
165        } else {
166            xer_so = 1;
167            xer_ov = 1;
168            T0 = (-1) * ((uint32_t)T0 >> 31);
169        }
170    }
171    
172    void do_divwuo (void)
173    {
174        if (likely((uint32_t)T1 != 0)) {
175            xer_ov = 0;
176            T0 = (uint32_t)T0 / (uint32_t)T1;
177        } else {
178            xer_so = 1;
179            xer_ov = 1;
180            T0 = 0;
181        }
182    }
183    
184    void do_mullwo (void)
185    {
186        int64_t res = (int64_t)Ts0 * (int64_t)Ts1;
187    
188        if (likely((int32_t)res == res)) {
189            xer_ov = 0;
190        } else {
191            xer_ov = 1;
192            xer_so = 1;
193        }
194        T0 = (int32_t)res;
195    }
196    
197    void do_nego (void)
198    {
199        if (likely(T0 != INT32_MIN)) {
200            xer_ov = 0;
201            T0 = -Ts0;
202        } else {
203            xer_ov = 1;
204            xer_so = 1;
205        }
206    }
207    
208    void do_subfo (void)
209    {
210        T2 = T0;
211        T0 = T1 - T0;
212        if (likely(!(((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)))) {
213            xer_ov = 0;
214        } else {
215            xer_so = 1;
216            xer_ov = 1;
217        }
218        RETURN();
219    }
220    
221    void do_subfco (void)
222    {
223        T2 = T0;
224        T0 = T1 - T0;
225        if (likely(T0 > T1)) {
226            xer_ca = 0;
227        } else {
228            xer_ca = 1;
229        }
230        if (likely(!(((~T2) ^ T1 ^ (-1)) & ((~T2) ^ T0) & (1 << 31)))) {
231            xer_ov = 0;
232        } else {
233            xer_so = 1;
234            xer_ov = 1;
235        }
236    }
237    
238    void do_subfe (void)
239    {
240        T0 = T1 + ~T0 + xer_ca;
241        if (likely(T0 >= T1 && (xer_ca == 0 || T0 != T1))) {
242            xer_ca = 0;
243        } else {
244            xer_ca = 1;
245        }
246    }
247    
248    void do_subfeo (void)
249    {
250        T2 = T0;
251        T0 = T1 + ~T0 + xer_ca;
252        if (likely(!((~T2 ^ T1 ^ (-1)) & (~T2 ^ T0) & (1 << 31)))) {
253            xer_ov = 0;
254        } else {
255            xer_so = 1;
256            xer_ov = 1;
257        }
258        if (likely(T0 >= T1 && (xer_ca == 0 || T0 != T1))) {
259            xer_ca = 0;
260        } else {
261            xer_ca = 1;
262        }
263    }
264    
265    void do_subfmeo (void)
266    {
267        T1 = T0;
268        T0 = ~T0 + xer_ca - 1;
269        if (likely(!(~T1 & (~T1 ^ T0) & (1 << 31)))) {
270            xer_ov = 0;
271        } else {
272            xer_so = 1;
273            xer_ov = 1;
274        }
275        if (likely(T1 != -1))
276            xer_ca = 1;
277    }
278    
279    void do_subfzeo (void)
280    {
281        T1 = T0;
282        T0 = ~T0 + xer_ca;
283        if (likely(!((~T1 ^ (-1)) & ((~T1) ^ T0) & (1 << 31)))) {
284            xer_ov = 0;
285        } else {
286            xer_ov = 1;
287            xer_so = 1;
288        }
289        if (likely(T0 >= ~T1)) {
290            xer_ca = 0;
291        } else {
292            xer_ca = 1;
293        }
294    }
295    
296  /* shift right arithmetic helper */  /* shift right arithmetic helper */
297  void do_sraw (void)  void do_sraw (void)
298  {  {
299      int32_t ret;      int32_t ret;
300    
301        if (likely(!(T1 & 0x20UL))) {
302            if (likely(T1 != 0)) {
303                ret = (int32_t)T0 >> (T1 & 0x1fUL);
304                if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
305      xer_ca = 0;      xer_ca = 0;
306      if (T1 & 0x20) {              } else {
         ret = (-1) * (T0 >> 31);  
         if (ret < 0 && (T0 & ~0x80000000) != 0)  
307              xer_ca = 1;              xer_ca = 1;
308  #if 1 // TRY              }
309      } else if (T1 == 0) {          } else {
310          ret = T0;          ret = T0;
311  #endif              xer_ca = 0;
312            }
313        } else {
314            ret = (-1) * ((uint32_t)T0 >> 31);
315            if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
316                xer_ca = 0;
317      } else {      } else {
         ret = (int32_t)T0 >> (T1 & 0x1f);  
         if (ret < 0 && ((int32_t)T0 & ((1 << T1) - 1)) != 0)  
318              xer_ca = 1;              xer_ca = 1;
319      }      }
320        }
321      T0 = ret;      T0 = ret;
322  }  }
323    
324    /*****************************************************************************/
325  /* Floating point operations helpers */  /* Floating point operations helpers */
326  void do_fctiw (void)  void do_fctiw (void)
327  {  {
# Line 116  void do_fctiwz (void) Line 355  void do_fctiwz (void)
355    
356  void do_fnmadd (void)  void do_fnmadd (void)
357  {  {
358      FT0 = (FT0 * FT1) + FT2;      FT0 = float64_mul(FT0, FT1, &env->fp_status);
359      if (!isnan(FT0))      FT0 = float64_add(FT0, FT2, &env->fp_status);
360          FT0 = -FT0;      if (likely(!isnan(FT0)))
361            FT0 = float64_chs(FT0);
362  }  }
363    
364  void do_fnmsub (void)  void do_fnmsub (void)
365  {  {
366      FT0 = (FT0 * FT1) - FT2;      FT0 = float64_mul(FT0, FT1, &env->fp_status);
367      if (!isnan(FT0))      FT0 = float64_sub(FT0, FT2, &env->fp_status);
368          FT0 = -FT0;      if (likely(!isnan(FT0)))
369  }          FT0 = float64_chs(FT0);
   
 void do_fdiv (void)  
 {  
     if (FT0 == -0.0 && FT1 == -0.0)  
         FT0 = 0.0 / 0.0;  
     else  
         FT0 /= FT1;  
370  }  }
371    
372  void do_fsqrt (void)  void do_fsqrt (void)
373  {  {
374      FT0 = sqrt(FT0);      FT0 = float64_sqrt(FT0, &env->fp_status);
375  }  }
376    
377  void do_fres (void)  void do_fres (void)
# Line 148  void do_fres (void) Line 381  void do_fres (void)
381          uint64_t i;          uint64_t i;
382      } p;      } p;
383    
384      if (isnormal(FT0)) {      if (likely(isnormal(FT0))) {
385          FT0 = (float)(1.0 / FT0);          FT0 = (float)(1.0 / FT0);
386      } else {      } else {
387          p.d = FT0;          p.d = FT0;
# Line 174  void do_frsqrte (void) Line 407  void do_frsqrte (void)
407          uint64_t i;          uint64_t i;
408      } p;      } p;
409    
410      if (isnormal(FT0) && FT0 > 0.0) {      if (likely(isnormal(FT0) && FT0 > 0.0)) {
411          FT0 = (float)(1.0 / sqrt(FT0));          FT0 = float64_sqrt(FT0, &env->fp_status);
412            FT0 = float32_div(1.0, FT0, &env->fp_status);
413      } else {      } else {
414          p.d = FT0;          p.d = FT0;
415          if (p.i == 0x8000000000000000ULL) {          if (p.i == 0x8000000000000000ULL) {
# Line 204  void do_fsel (void) Line 438  void do_fsel (void)
438    
439  void do_fcmpu (void)  void do_fcmpu (void)
440  {  {
441      if (isnan(FT0) || isnan(FT1)) {      if (likely(!isnan(FT0) && !isnan(FT1))) {
442          T0 = 0x01;          if (float64_lt(FT0, FT1, &env->fp_status)) {
443                T0 = 0x08UL;
444            } else if (!float64_le(FT0, FT1, &env->fp_status)) {
445                T0 = 0x04UL;
446            } else {
447                T0 = 0x02UL;
448            }
449        } else {
450            T0 = 0x01UL;
451          env->fpscr[4] |= 0x1;          env->fpscr[4] |= 0x1;
452          env->fpscr[6] |= 0x1;          env->fpscr[6] |= 0x1;
     } else if (FT0 < FT1) {  
         T0 = 0x08;  
     } else if (FT0 > FT1) {  
         T0 = 0x04;  
     } else {  
         T0 = 0x02;  
453      }      }
454      env->fpscr[3] = T0;      env->fpscr[3] = T0;
455  }  }
# Line 221  void do_fcmpu (void) Line 457  void do_fcmpu (void)
457  void do_fcmpo (void)  void do_fcmpo (void)
458  {  {
459      env->fpscr[4] &= ~0x1;      env->fpscr[4] &= ~0x1;
460      if (isnan(FT0) || isnan(FT1)) {      if (likely(!isnan(FT0) && !isnan(FT1))) {
461          T0 = 0x01;          if (float64_lt(FT0, FT1, &env->fp_status)) {
462                T0 = 0x08UL;
463            } else if (!float64_le(FT0, FT1, &env->fp_status)) {
464                T0 = 0x04UL;
465            } else {
466                T0 = 0x02UL;
467            }
468        } else {
469            T0 = 0x01UL;
470          env->fpscr[4] |= 0x1;          env->fpscr[4] |= 0x1;
471          /* I don't know how to test "quiet" nan... */          /* I don't know how to test "quiet" nan... */
472          if (0 /* || ! quiet_nan(...) */) {          if (0 /* || ! quiet_nan(...) */) {
# Line 232  void do_fcmpo (void) Line 476  void do_fcmpo (void)
476          } else {          } else {
477              env->fpscr[4] |= 0x8;              env->fpscr[4] |= 0x8;
478          }          }
     } else if (FT0 < FT1) {  
         T0 = 0x08;  
     } else if (FT0 > FT1) {  
         T0 = 0x04;  
     } else {  
         T0 = 0x02;  
479      }      }
480      env->fpscr[3] = T0;      env->fpscr[3] = T0;
481  }  }
482    
483  void do_fabs (void)  void do_rfi (void)
484  {  {
485      union {      env->nip = env->spr[SPR_SRR0] & ~0x00000003;
486          double d;      T0 = env->spr[SPR_SRR1] & ~0xFFFF0000UL;
487          uint64_t i;      do_store_msr(env, T0);
488      } p;  #if defined (DEBUG_OP)
489        dump_rfi();
490      p.d = FT0;  #endif
491      p.i &= ~0x8000000000000000ULL;      env->interrupt_request |= CPU_INTERRUPT_EXITTB;
     FT0 = p.d;  
492  }  }
493    
494  void do_fnabs (void)  void do_tw (uint32_t cmp, int flags)
495  {  {
496      union {      if (!likely(!((Ts0 < (int32_t)cmp && (flags & 0x10)) ||
497          double d;                    (Ts0 > (int32_t)cmp && (flags & 0x08)) ||
498          uint64_t i;                    (Ts0 == (int32_t)cmp && (flags & 0x04)) ||
499      } p;                    (T0 < cmp && (flags & 0x02)) ||
500                      (T0 > cmp && (flags & 0x01)))))
501      p.d = FT0;          do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
     p.i |= 0x8000000000000000ULL;  
     FT0 = p.d;  
502  }  }
503    
504  /* Instruction cache invalidation helper */  /* Instruction cache invalidation helper */
 #define ICACHE_LINE_SIZE 32  
   
 void do_check_reservation (void)  
 {  
     if ((env->reserve & ~0x03) == T0)  
         env->reserve = -1;  
 }  
   
505  void do_icbi (void)  void do_icbi (void)
506  {  {
507      /* Invalidate one cache line */      uint32_t tmp;
508        /* Invalidate one cache line :
509         * PowerPC specification says this is to be treated like a load
510         * (not a fetch) by the MMU. To be sure it will be so,
511         * do the load "by hand".
512         */
513    #if defined(TARGET_PPC64)
514        if (!msr_sf)
515            T0 &= 0xFFFFFFFFULL;
516    #endif
517        tmp = ldl_kernel(T0);
518      T0 &= ~(ICACHE_LINE_SIZE - 1);      T0 &= ~(ICACHE_LINE_SIZE - 1);
519      tb_invalidate_page_range(T0, T0 + ICACHE_LINE_SIZE);      tb_invalidate_page_range(T0, T0 + ICACHE_LINE_SIZE);
520  }  }
521    
522    /*****************************************************************************/
523    /* MMU related helpers */
524  /* TLB invalidation helpers */  /* TLB invalidation helpers */
525  void do_tlbia (void)  void do_tlbia (void)
526  {  {
# Line 290  void do_tlbia (void) Line 529  void do_tlbia (void)
529    
530  void do_tlbie (void)  void do_tlbie (void)
531  {  {
532    #if !defined(FLUSH_ALL_TLBS)
533      tlb_flush_page(env, T0);      tlb_flush_page(env, T0);
534    #else
535        do_tlbia();
536    #endif
537    }
538    
539    /*****************************************************************************/
540    /* Softmmu support */
541    #if !defined (CONFIG_USER_ONLY)
542    
543    #define MMUSUFFIX _mmu
544    #define GETPC() (__builtin_return_address(0))
545    
546    #define SHIFT 0
547    #include "softmmu_template.h"
548    
549    #define SHIFT 1
550    #include "softmmu_template.h"
551    
552    #define SHIFT 2
553    #include "softmmu_template.h"
554    
555    #define SHIFT 3
556    #include "softmmu_template.h"
557    
558    /* try to fill the TLB and return an exception if error. If retaddr is
559       NULL, it means that the function was called in C code (i.e. not
560       from generated code or from helper.c) */
561    /* XXX: fix it to restore all registers */
562    void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
563    {
564        TranslationBlock *tb;
565        CPUState *saved_env;
566        target_phys_addr_t pc;
567        int ret;
568    
569        /* XXX: hack to restore env in all cases, even if not called from
570           generated code */
571        saved_env = env;
572        env = cpu_single_env;
573        ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, is_user, 1);
574        if (!likely(ret == 0)) {
575            if (likely(retaddr)) {
576                /* now we have a real cpu fault */
577                pc = (target_phys_addr_t)retaddr;
578                tb = tb_find_pc(pc);
579                if (likely(tb)) {
580                    /* the PC is inside the translated code. It means that we have
581                       a virtual CPU fault */
582                    cpu_restore_state(tb, env, pc, NULL);
583    }
584            }
585            do_raise_exception_err(env->exception_index, env->error_code);
586        }
587        env = saved_env;
588  }  }
589    #endif /* !CONFIG_USER_ONLY */
590    

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.16

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26