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

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

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

revision 1.14 by bellard, Mon Jul 4 22:18:23 2005 UTC revision 1.15 by bellard, Sat Jul 23 14:27:54 2005 UTC
# Line 1  Line 1 
1  #include "exec.h"  #include "exec.h"
2    
3    //#define DEBUG_PCALL
4  //#define DEBUG_MMU  //#define DEBUG_MMU
5    
6  void raise_exception(int tt)  void raise_exception(int tt)
# Line 223  void do_fcmpd_fcc3 (void) Line 224  void do_fcmpd_fcc3 (void)
224  #ifndef TARGET_SPARC64  #ifndef TARGET_SPARC64
225  void helper_ld_asi(int asi, int size, int sign)  void helper_ld_asi(int asi, int size, int sign)
226  {  {
227      uint32_t ret;      uint32_t ret = 0;
228    
229      switch (asi) {      switch (asi) {
230      case 3: /* MMU probe */      case 3: /* MMU probe */
# Line 299  void helper_st_asi(int asi, int size, in Line 300  void helper_st_asi(int asi, int size, in
300          }          }
301      case 4: /* write MMU regs */      case 4: /* write MMU regs */
302          {          {
303              int reg = (T0 >> 8) & 0xf, oldreg;              int reg = (T0 >> 8) & 0xf;
304                uint32_t oldreg;
305                            
306              oldreg = env->mmuregs[reg];              oldreg = env->mmuregs[reg];
307              switch(reg) {              switch(reg) {
# Line 339  void helper_st_asi(int asi, int size, in Line 341  void helper_st_asi(int asi, int size, in
341              // value (T1) = src              // value (T1) = src
342              // address (T0) = dst              // address (T0) = dst
343              // copy 32 bytes              // copy 32 bytes
344              int src = T1, dst = T0;              uint32_t src = T1, dst = T0;
345              uint8_t temp[32];              uint8_t temp[32];
346                            
347              tswap32s(&src);              tswap32s(&src);
# Line 353  void helper_st_asi(int asi, int size, in Line 355  void helper_st_asi(int asi, int size, in
355              // value (T1, T2)              // value (T1, T2)
356              // address (T0) = dst              // address (T0) = dst
357              // fill 32 bytes              // fill 32 bytes
358              int i, dst = T0;              int i;
359                uint32_t dst = T0;
360              uint64_t val;              uint64_t val;
361                            
362              val = (((uint64_t)T1) << 32) | T2;              val = (((uint64_t)T1) << 32) | T2;
# Line 366  void helper_st_asi(int asi, int size, in Line 369  void helper_st_asi(int asi, int size, in
369          return;          return;
370      case 0x20 ... 0x2f: /* MMU passthrough */      case 0x20 ... 0x2f: /* MMU passthrough */
371          {          {
372              int temp = T1;              uint32_t temp = T1;
373              if (size == 4)              if (size == 4)
374                  tswap32s(&temp);                  tswap32s(&temp);
375              else if (size == 2)              else if (size == 2)
# Line 383  void helper_st_asi(int asi, int size, in Line 386  void helper_st_asi(int asi, int size, in
386    
387  void helper_ld_asi(int asi, int size, int sign)  void helper_ld_asi(int asi, int size, int sign)
388  {  {
389      uint64_t ret;      uint64_t ret = 0;
390    
391      if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)      if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
392          raise_exception(TT_PRIV_INSN);          raise_exception(TT_PRIV_ACT);
393    
394      switch (asi) {      switch (asi) {
395      case 0x14: // Bypass      case 0x14: // Bypass
# Line 401  void helper_ld_asi(int asi, int size, in Line 404  void helper_ld_asi(int asi, int size, in
404                  tswap16s((uint16_t *)&ret);                  tswap16s((uint16_t *)&ret);
405              break;              break;
406          }          }
407        case 0x04: // Nucleus
408        case 0x0c: // Nucleus Little Endian (LE)
409        case 0x10: // As if user primary
410        case 0x11: // As if user secondary
411        case 0x18: // As if user primary LE
412        case 0x19: // As if user secondary LE
413      case 0x1c: // Bypass LE      case 0x1c: // Bypass LE
414      case 0x1d: // Bypass, non-cacheable LE      case 0x1d: // Bypass, non-cacheable LE
415        case 0x24: // Nucleus quad LDD 128 bit atomic
416        case 0x2c: // Nucleus quad LDD 128 bit atomic
417        case 0x4a: // UPA config
418        case 0x82: // Primary no-fault
419        case 0x83: // Secondary no-fault
420        case 0x88: // Primary LE
421        case 0x89: // Secondary LE
422        case 0x8a: // Primary no-fault LE
423        case 0x8b: // Secondary no-fault LE
424          // XXX          // XXX
425          break;          break;
426      case 0x45: // LSU      case 0x45: // LSU
# Line 418  void helper_ld_asi(int asi, int size, in Line 436  void helper_ld_asi(int asi, int size, in
436      case 0x51: // I-MMU 8k TSB pointer      case 0x51: // I-MMU 8k TSB pointer
437      case 0x52: // I-MMU 64k TSB pointer      case 0x52: // I-MMU 64k TSB pointer
438      case 0x55: // I-MMU data access      case 0x55: // I-MMU data access
439      case 0x56: // I-MMU tag read          // XXX
440          break;          break;
441        case 0x56: // I-MMU tag read
442            {
443                unsigned int i;
444                
445                for (i = 0; i < 64; i++) {
446                    // Valid, ctx match, vaddr match
447                    if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
448                        env->itlb_tag[i] == T0) {
449                        ret = env->itlb_tag[i];
450                        break;
451                    }
452                }
453                break;
454            }
455      case 0x58: // D-MMU regs      case 0x58: // D-MMU regs
456          {          {
457              int reg = (T0 >> 3) & 0xf;              int reg = (T0 >> 3) & 0xf;
# Line 427  void helper_ld_asi(int asi, int size, in Line 459  void helper_ld_asi(int asi, int size, in
459              ret = env->dmmuregs[reg];              ret = env->dmmuregs[reg];
460              break;              break;
461          }          }
462        case 0x5e: // D-MMU tag read
463            {
464                unsigned int i;
465                
466                for (i = 0; i < 64; i++) {
467                    // Valid, ctx match, vaddr match
468                    if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
469                        env->dtlb_tag[i] == T0) {
470                        ret = env->dtlb_tag[i];
471                        break;
472                    }
473                }
474                break;
475            }
476      case 0x59: // D-MMU 8k TSB pointer      case 0x59: // D-MMU 8k TSB pointer
477      case 0x5a: // D-MMU 64k TSB pointer      case 0x5a: // D-MMU 64k TSB pointer
478      case 0x5b: // D-MMU data pointer      case 0x5b: // D-MMU data pointer
479      case 0x5d: // D-MMU data access      case 0x5d: // D-MMU data access
480      case 0x5e: // D-MMU tag read      case 0x48: // Interrupt dispatch, RO
481        case 0x49: // Interrupt data receive
482        case 0x7f: // Incoming interrupt vector, RO
483            // XXX
484          break;          break;
485      case 0x54: // I-MMU data in, WO      case 0x54: // I-MMU data in, WO
486      case 0x57: // I-MMU demap, WO      case 0x57: // I-MMU demap, WO
487      case 0x5c: // D-MMU data in, WO      case 0x5c: // D-MMU data in, WO
488      case 0x5f: // D-MMU demap, WO      case 0x5f: // D-MMU demap, WO
489        case 0x77: // Interrupt vector, WO
490      default:      default:
491          ret = 0;          ret = 0;
492          break;          break;
# Line 447  void helper_ld_asi(int asi, int size, in Line 497  void helper_ld_asi(int asi, int size, in
497  void helper_st_asi(int asi, int size, int sign)  void helper_st_asi(int asi, int size, int sign)
498  {  {
499      if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)      if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
500          raise_exception(TT_PRIV_INSN);          raise_exception(TT_PRIV_ACT);
501    
502      switch(asi) {      switch(asi) {
503      case 0x14: // Bypass      case 0x14: // Bypass
# Line 463  void helper_st_asi(int asi, int size, in Line 513  void helper_st_asi(int asi, int size, in
513              cpu_physical_memory_write(T0, (void *) &temp, size);              cpu_physical_memory_write(T0, (void *) &temp, size);
514          }          }
515          return;          return;
516        case 0x04: // Nucleus
517        case 0x0c: // Nucleus Little Endian (LE)
518        case 0x10: // As if user primary
519        case 0x11: // As if user secondary
520        case 0x18: // As if user primary LE
521        case 0x19: // As if user secondary LE
522      case 0x1c: // Bypass LE      case 0x1c: // Bypass LE
523      case 0x1d: // Bypass, non-cacheable LE      case 0x1d: // Bypass, non-cacheable LE
524        case 0x24: // Nucleus quad LDD 128 bit atomic
525        case 0x2c: // Nucleus quad LDD 128 bit atomic
526        case 0x4a: // UPA config
527        case 0x88: // Primary LE
528        case 0x89: // Secondary LE
529          // XXX          // XXX
530          return;          return;
531      case 0x45: // LSU      case 0x45: // LSU
# Line 475  void helper_st_asi(int asi, int size, in Line 536  void helper_st_asi(int asi, int size, in
536              env->lsu = T1 & (DMMU_E | IMMU_E);              env->lsu = T1 & (DMMU_E | IMMU_E);
537              // Mappings generated during D/I MMU disabled mode are              // Mappings generated during D/I MMU disabled mode are
538              // invalid in normal mode              // invalid in normal mode
539              if (oldreg != env->lsu)              if (oldreg != env->lsu) {
540    #ifdef DEBUG_MMU
541                    printf("LSU change: 0x%llx -> 0x%llx\n", oldreg, env->lsu);
542                    dump_mmu(env);
543    #endif
544                  tlb_flush(env, 1);                  tlb_flush(env, 1);
545                }
546              return;              return;
547          }          }
548      case 0x50: // I-MMU regs      case 0x50: // I-MMU regs
# Line 506  void helper_st_asi(int asi, int size, in Line 572  void helper_st_asi(int asi, int size, in
572              env->immuregs[reg] = T1;              env->immuregs[reg] = T1;
573  #ifdef DEBUG_MMU  #ifdef DEBUG_MMU
574              if (oldreg != env->immuregs[reg]) {              if (oldreg != env->immuregs[reg]) {
575                  printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->immuregs[reg]);                  printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->immuregs[reg]);
576              }              }
577              dump_mmu(env);              dump_mmu(env);
578  #endif  #endif
# Line 544  void helper_st_asi(int asi, int size, in Line 610  void helper_st_asi(int asi, int size, in
610              return;              return;
611          }          }
612      case 0x57: // I-MMU demap      case 0x57: // I-MMU demap
613            // XXX
614          return;          return;
615      case 0x58: // D-MMU regs      case 0x58: // D-MMU regs
616          {          {
# Line 574  void helper_st_asi(int asi, int size, in Line 641  void helper_st_asi(int asi, int size, in
641              env->dmmuregs[reg] = T1;              env->dmmuregs[reg] = T1;
642  #ifdef DEBUG_MMU  #ifdef DEBUG_MMU
643              if (oldreg != env->dmmuregs[reg]) {              if (oldreg != env->dmmuregs[reg]) {
644                  printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->dmmuregs[reg]);                  printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->dmmuregs[reg]);
645              }              }
646              dump_mmu(env);              dump_mmu(env);
647  #endif  #endif
# Line 612  void helper_st_asi(int asi, int size, in Line 679  void helper_st_asi(int asi, int size, in
679              return;              return;
680          }          }
681      case 0x5f: // D-MMU demap      case 0x5f: // D-MMU demap
682        case 0x49: // Interrupt data receive
683            // XXX
684          return;          return;
685      case 0x51: // I-MMU 8k TSB pointer, RO      case 0x51: // I-MMU 8k TSB pointer, RO
686      case 0x52: // I-MMU 64k TSB pointer, RO      case 0x52: // I-MMU 64k TSB pointer, RO
# Line 620  void helper_st_asi(int asi, int size, in Line 689  void helper_st_asi(int asi, int size, in
689      case 0x5a: // D-MMU 64k TSB pointer, RO      case 0x5a: // D-MMU 64k TSB pointer, RO
690      case 0x5b: // D-MMU data pointer, RO      case 0x5b: // D-MMU data pointer, RO
691      case 0x5e: // D-MMU tag read, RO      case 0x5e: // D-MMU tag read, RO
692        case 0x48: // Interrupt dispatch, RO
693        case 0x7f: // Incoming interrupt vector, RO
694        case 0x82: // Primary no-fault, RO
695        case 0x83: // Secondary no-fault, RO
696        case 0x8a: // Primary no-fault LE, RO
697        case 0x8b: // Secondary no-fault LE, RO
698      default:      default:
699          return;          return;
700      }      }
# Line 704  void do_popc() Line 779  void do_popc()
779      T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);      T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
780      T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);      T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
781  }  }
782    
783    static inline uint64_t *get_gregset(uint64_t pstate)
784    {
785        switch (pstate) {
786        default:
787        case 0:
788            return env->bgregs;
789        case PS_AG:
790            return env->agregs;
791        case PS_MG:
792            return env->mgregs;
793        case PS_IG:
794            return env->igregs;
795        }
796    }
797    
798    void do_wrpstate()
799    {
800        uint64_t new_pstate, pstate_regs, new_pstate_regs;
801        uint64_t *src, *dst;
802    
803        new_pstate = T0 & 0xf3f;
804        pstate_regs = env->pstate & 0xc01;
805        new_pstate_regs = new_pstate & 0xc01;
806        if (new_pstate_regs != pstate_regs) {
807            // Switch global register bank
808            src = get_gregset(new_pstate_regs);
809            dst = get_gregset(pstate_regs);
810            memcpy32(dst, env->gregs);
811            memcpy32(env->gregs, src);
812        }
813        env->pstate = new_pstate;
814    }
815    
816    void do_done(void)
817    {
818        env->tl--;
819        env->pc = env->tnpc[env->tl];
820        env->npc = env->tnpc[env->tl] + 4;
821        PUT_CCR(env, env->tstate[env->tl] >> 32);
822        env->asi = (env->tstate[env->tl] >> 24) & 0xff;
823        env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
824        set_cwp(env->tstate[env->tl] & 0xff);
825    }
826    
827    void do_retry(void)
828    {
829        env->tl--;
830        env->pc = env->tpc[env->tl];
831        env->npc = env->tnpc[env->tl];
832        PUT_CCR(env, env->tstate[env->tl] >> 32);
833        env->asi = (env->tstate[env->tl] >> 24) & 0xff;
834        env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
835        set_cwp(env->tstate[env->tl] & 0xff);
836    }
837  #endif  #endif
838    
839  void set_cwp(int new_cwp)  void set_cwp(int new_cwp)
# Line 744  void do_interrupt(int intno) Line 874  void do_interrupt(int intno)
874  #ifdef DEBUG_PCALL  #ifdef DEBUG_PCALL
875      if (loglevel & CPU_LOG_INT) {      if (loglevel & CPU_LOG_INT) {
876          static int count;          static int count;
877          fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",          fprintf(logfile, "%6d: v=%04x pc=%016llx npc=%016llx SP=%016llx\n",
878                  count, intno,                  count, intno,
879                  env->pc,                  env->pc,
880                  env->npc, env->regwptr[6]);                  env->npc, env->regwptr[6]);
# Line 766  void do_interrupt(int intno) Line 896  void do_interrupt(int intno)
896      }      }
897  #endif  #endif
898  #if !defined(CONFIG_USER_ONLY)  #if !defined(CONFIG_USER_ONLY)
899      if (env->pstate & PS_IE) {      if (env->tl == MAXTL) {
900          cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);          cpu_abort(cpu_single_env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
901          return;          return;
902      }      }
903  #endif  #endif
# Line 776  void do_interrupt(int intno) Line 906  void do_interrupt(int intno)
906      env->tpc[env->tl] = env->pc;      env->tpc[env->tl] = env->pc;
907      env->tnpc[env->tl] = env->npc;      env->tnpc[env->tl] = env->npc;
908      env->tt[env->tl] = intno;      env->tt[env->tl] = intno;
909      env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4);      env->pstate = PS_PEF | PS_PRIV | PS_AG;
910      env->tl++;      env->tbr &= ~0x7fffULL;
911        env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
912        if (env->tl < MAXTL - 1) {
913            env->tl++;
914        } else {
915            env->pstate |= PS_RED;
916            if (env->tl != MAXTL)
917                env->tl++;
918        }
919      env->pc = env->tbr;      env->pc = env->tbr;
920      env->npc = env->pc + 4;      env->npc = env->pc + 4;
921      env->exception_index = 0;      env->exception_index = 0;

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

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