/[gxemul]/trunk/src/cpus/cpu_mips.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/cpus/cpu_mips.c

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

revision 28 by dpavlin, Mon Oct 8 16:20:26 2007 UTC revision 34 by dpavlin, Mon Oct 8 16:21:17 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips.c,v 1.61 2006/07/16 13:32:26 debug Exp $   *  $Id: cpu_mips.c,v 1.75 2007/02/18 09:19:47 debug Exp $
29   *   *
30   *  MIPS core CPU emulation.   *  MIPS core CPU emulation.
31   */   */
# Line 35  Line 35 
35  #include <string.h>  #include <string.h>
36  #include <sys/types.h>  #include <sys/types.h>
37  #include <ctype.h>  #include <ctype.h>
38    #include <unistd.h>
39    
40  #include "../../config.h"  #include "../../config.h"
41    
# Line 49  Line 50 
50  #include "memory.h"  #include "memory.h"
51  #include "mips_cpu_types.h"  #include "mips_cpu_types.h"
52  #include "opcodes_mips.h"  #include "opcodes_mips.h"
53    #include "settings.h"
54  #include "symbol.h"  #include "symbol.h"
55    
56    
# Line 59  static char *exception_names[] = EXCEPTI Line 61  static char *exception_names[] = EXCEPTI
61  static char *hi6_names[] = HI6_NAMES;  static char *hi6_names[] = HI6_NAMES;
62  static char *regimm_names[] = REGIMM_NAMES;  static char *regimm_names[] = REGIMM_NAMES;
63  static char *special_names[] = SPECIAL_NAMES;  static char *special_names[] = SPECIAL_NAMES;
64    static char *special_rot_names[] = SPECIAL_ROT_NAMES;
65  static char *special2_names[] = SPECIAL2_NAMES;  static char *special2_names[] = SPECIAL2_NAMES;
66  static char *mmi_names[] = MMI_NAMES;  static char *mmi_names[] = MMI_NAMES;
67  static char *mmi0_names[] = MMI0_NAMES;  static char *mmi0_names[] = MMI0_NAMES;
# Line 85  void mips32_pc_to_pointers(struct cpu *) Line 88  void mips32_pc_to_pointers(struct cpu *)
88   *  Convert a register number into either 'r0', 'r31' etc, or a symbolic   *  Convert a register number into either 'r0', 'r31' etc, or a symbolic
89   *  name, depending on machine->show_symbolic_register_names.   *  name, depending on machine->show_symbolic_register_names.
90   *   *
91   *  NOTE: _NOT_ reentrant.   *  NOTE: This helper function is _NOT_ reentrant.
92   */   */
93  static char *regname(struct machine *machine, int r)  static char *regname(struct machine *machine, int r)
94  {  {
# Line 301  int mips_cpu_new(struct cpu *cpu, struct Line 304  int mips_cpu_new(struct cpu *cpu, struct
304                  debug(")");                  debug(")");
305          }          }
306    
307            /*  Register the CPU's interrupts:  */
308            for (i=2; i<8; i++) {
309                    struct interrupt template;
310                    char name[50];
311                    snprintf(name, sizeof(name), "%s.%i", cpu->path, i);
312                    memset(&template, 0, sizeof(template));
313                    template.line = 1 << (STATUS_IM_SHIFT + i);
314                    template.name = name;
315                    template.extra = cpu;
316                    template.interrupt_assert = mips_cpu_interrupt_assert;
317                    template.interrupt_deassert = mips_cpu_interrupt_deassert;
318                    interrupt_handler_register(&template);
319    
320                    if (i == 7)
321                            INTERRUPT_CONNECT(name, cpu->cd.mips.irq_compare);
322            }
323    
324          /*  System coprocessor (0), and FPU (1):  */          /*  System coprocessor (0), and FPU (1):  */
325          cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);          cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);
326          cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);          cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);
# Line 322  int mips_cpu_new(struct cpu *cpu, struct Line 342  int mips_cpu_new(struct cpu *cpu, struct
342                          cpu->translate_v2p = translate_v2p_generic;                          cpu->translate_v2p = translate_v2p_generic;
343          }          }
344    
345            if (cpu->machine->prom_emulation) {
346                    /*
347                     *  Default behaviour of jumping to 0xbfc00000 should be
348                     *  a reboot, unless machine-specific initialization code
349                     *  overrides this.
350                     *
351                     *  Note: Specifically big-endian machines should override
352                     *  this, since the default MIPS CPU is little-endian!
353                     */
354                    store_32bit_word(cpu, 0xffffffff9fc00000ULL, 0x00c0de0d);
355            }
356    
357            /*  Add all register names to the settings:  */
358            CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
359            CPU_SETTINGS_ADD_REGISTER64("hi", cpu->cd.mips.hi);
360            CPU_SETTINGS_ADD_REGISTER64("lo", cpu->cd.mips.lo);
361            for (i=0; i<N_MIPS_GPRS; i++)
362                    CPU_SETTINGS_ADD_REGISTER64(regnames[i], cpu->cd.mips.gpr[i]);
363            /*  TODO: Write via special handler function!  */
364            for (i=0; i<N_MIPS_COPROC_REGS; i++)
365                    CPU_SETTINGS_ADD_REGISTER64(cop0_names[i],
366                        cpu->cd.mips.coproc[0]->reg[i]);
367    
368          return 1;          return 1;
369  }  }
370    
# Line 605  void mips_cpu_tlbdump(struct machine *m, Line 648  void mips_cpu_tlbdump(struct machine *m,
648                                  printf("\n");                                  printf("\n");
649                                  break;                                  break;
650                          default:switch (m->cpus[i]->cd.mips.cpu_type.mmu_model){                          default:switch (m->cpus[i]->cd.mips.cpu_type.mmu_model){
                                 case MMU10K:  
                                         printf("vaddr=0x%1x..%011"PRIx64" ",  
                                             (int) (hi >> 60), (uint64_t)  
                                             (hi&ENTRYHI_VPN2_MASK_R10K));  
                                         break;  
651                                  case MMU32:                                  case MMU32:
652                                          printf("vaddr=0x%08"PRIx32" ",                                          printf("vaddr=0x%08"PRIx32" ",
653                                              (uint32_t)(hi&ENTRYHI_VPN2_MASK));                                              (uint32_t) hi);
654                                          break;                                          break;
655                                    case MMU10K:
656                                  default:/*  R4000 etc.  */                                  default:/*  R4000 etc.  */
657                                          printf("vaddr=0x%1x..%010"PRIx64" ",                                          printf("vaddr=%016"PRIx64" ",
658                                              (int) (hi >> 60),                                              (uint64_t) hi);
                                             (uint64_t) (hi&ENTRYHI_VPN2_MASK));  
659                                  }                                  }
660                                  if (hi & TLB_G)                                  if (hi & TLB_G)
661                                          printf("(global): ");                                          printf("(global): ");
# Line 663  void mips_cpu_tlbdump(struct machine *m, Line 701  void mips_cpu_tlbdump(struct machine *m,
701    
702    
703  /*  /*
  *  mips_cpu_register_match():  
  */  
 void mips_cpu_register_match(struct machine *m, char *name,  
         int writeflag, uint64_t *valuep, int *match_register)  
 {  
         int cpunr = 0;  
   
         /*  CPU number:  */  
   
         /*  TODO  */  
   
         /*  Register name:  */  
         if (strcasecmp(name, "pc") == 0) {  
                 if (writeflag) {  
                         m->cpus[cpunr]->pc = *valuep;  
                         if (m->cpus[cpunr]->delay_slot) {  
                                 printf("NOTE: Clearing the delay slot"  
                                     " flag! (It was set before.)\n");  
                                 m->cpus[cpunr]->delay_slot = 0;  
                         }  
                         if (m->cpus[cpunr]->cd.mips.nullify_next) {  
                                 printf("NOTE: Clearing the nullify-ne"  
                                     "xt flag! (It was set before.)\n");  
                                 m->cpus[cpunr]->cd.mips.nullify_next = 0;  
                         }  
                 } else  
                         *valuep = m->cpus[cpunr]->pc;  
                 *match_register = 1;  
         } else if (strcasecmp(name, "hi") == 0) {  
                 if (writeflag)  
                         m->cpus[cpunr]->cd.mips.hi = *valuep;  
                 else  
                         *valuep = m->cpus[cpunr]->cd.mips.hi;  
                 *match_register = 1;  
         } else if (strcasecmp(name, "lo") == 0) {  
                 if (writeflag)  
                         m->cpus[cpunr]->cd.mips.lo = *valuep;  
                 else  
                         *valuep = m->cpus[cpunr]->cd.mips.lo;  
                 *match_register = 1;  
         } else if (name[0] == 'r' && isdigit((int)name[1])) {  
                 int nr = atoi(name + 1);  
                 if (nr >= 0 && nr < N_MIPS_GPRS) {  
                         if (writeflag) {  
                                 if (nr != 0)  
                                         m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;  
                                 else  
                                         printf("WARNING: Attempt to modify r0.\n");  
                         } else  
                                 *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];  
                         *match_register = 1;  
                 }  
         } else {  
                 /*  Check for a symbolic name such as "t6" or "at":  */  
                 int nr;  
                 for (nr=0; nr<N_MIPS_GPRS; nr++)  
                         if (strcmp(name, regnames[nr]) == 0) {  
                                 if (writeflag) {  
                                         if (nr != 0)  
                                                 m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;  
                                         else  
                                                 printf("WARNING: Attempt to modify r0.\n");  
                                 } else  
                                         *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];  
                                 *match_register = 1;  
                         }  
         }  
   
         if (!(*match_register)) {  
                 /*  Check for a symbolic coproc0 name:  */  
                 int nr;  
                 for (nr=0; nr<32; nr++)  
                         if (strcmp(name, cop0_names[nr]) == 0) {  
                                 if (writeflag) {  
                                         coproc_register_write(m->cpus[cpunr],  
                                             m->cpus[cpunr]->cd.mips.coproc[0], nr,  
                                             valuep, 1, 0);  
                                 } else {  
                                         /*  TODO: Use coproc_register_read instead?  */  
                                         *valuep = m->cpus[cpunr]->cd.mips.coproc[0]->reg[nr];  
                                 }  
                                 *match_register = 1;  
                         }  
         }  
   
         /*  TODO: Coprocessor 1,2,3 registers.  */  
   
         /*  Only return lowest 32 bits when doing 32-bit emulation:  */  
         if (!writeflag && m->cpus[cpunr]->is_32bit)  
                 *valuep = (uint32_t) (*valuep);  
 }  
   
   
 /*  
  *  cpu_flags():  
  *  
  *  Returns a pointer to a string containing "(d)" "(j)" "(dj)" or "",  
  *  depending on the cpu's current delay_slot and last_was_jumptoself  
  *  flags.  
  */  
 static const char *cpu_flags(struct cpu *cpu)  
 {  
         if (cpu->delay_slot) {  
                 if (cpu->cd.mips.last_was_jumptoself)  
                         return " (dj)";  
                 else  
                         return " (d)";  
         } else {  
                 if (cpu->cd.mips.last_was_jumptoself)  
                         return " (j)";  
                 else  
                         return "";  
         }  
 }  
   
   
 /*  
704   *  mips_cpu_disassemble_instr():   *  mips_cpu_disassemble_instr():
705   *   *
706   *  Convert an instruction word into human readable format, for instruction   *  Convert an instruction word into human readable format, for instruction
# Line 796  static const char *cpu_flags(struct cpu Line 717  static const char *cpu_flags(struct cpu
717  int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,  int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,
718          int running, uint64_t dumpaddr)          int running, uint64_t dumpaddr)
719  {  {
720          int hi6, special6, regimm5;          int hi6, special6, regimm5, sub;
721          int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;          int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;
722          uint64_t addr, offset;          uint64_t addr, offset;
723          uint32_t instrword;          uint32_t instrword;
# Line 838  int mips_cpu_disassemble_instr(struct cp Line 759  int mips_cpu_disassemble_instr(struct cp
759          debug(": %02x%02x%02x%02x",          debug(": %02x%02x%02x%02x",
760              instr[3], instr[2], instr[1], instr[0]);              instr[3], instr[2], instr[1], instr[0]);
761    
762          if (running)          if (running && cpu->delay_slot)
763                  debug("%s", cpu_flags(cpu));                  debug(" (d)");
764    
765          debug("\t");          debug("\t");
766    
# Line 847  int mips_cpu_disassemble_instr(struct cp Line 768  int mips_cpu_disassemble_instr(struct cp
768           *  Decode the instruction:           *  Decode the instruction:
769           */           */
770    
         if (cpu->cd.mips.nullify_next && running) {  
                 debug("(nullified)");  
                 goto disasm_ret;  
         }  
   
771          hi6 = (instr[3] >> 2) & 0x3f;          hi6 = (instr[3] >> 2) & 0x3f;
772    
773          switch (hi6) {          switch (hi6) {
# Line 867  int mips_cpu_disassemble_instr(struct cp Line 783  int mips_cpu_disassemble_instr(struct cp
783                  case SPECIAL_DSLL32:                  case SPECIAL_DSLL32:
784                  case SPECIAL_DSRL32:                  case SPECIAL_DSRL32:
785                  case SPECIAL_DSRA32:                  case SPECIAL_DSRA32:
786                            sub = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
787                          rt = instr[2] & 31;                          rt = instr[2] & 31;
788                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
789                          sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);                          sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
# Line 880  int mips_cpu_disassemble_instr(struct cp Line 797  int mips_cpu_disassemble_instr(struct cp
797                                          debug("ehb");                                          debug("ehb");
798                                  else                                  else
799                                          debug("nop (weird, sa=%i)", sa);                                          debug("nop (weird, sa=%i)", sa);
800                                  goto disasm_ret;                                  break;
801                          } else                          }
802    
803                            switch (sub) {
804                            case 0x00:
805                                  debug("%s\t%s,",                                  debug("%s\t%s,",
806                                      special_names[special6],                                      special_names[special6],
807                                      regname(cpu->machine, rd));                                      regname(cpu->machine, rd));
808                                  debug("%s,%i", regname(cpu->machine, rt), sa);                                  debug("%s,%i", regname(cpu->machine, rt), sa);
809                                    break;
810                            case 0x01:
811                                    debug("%s\t%s,",
812                                        special_rot_names[special6],
813                                        regname(cpu->machine, rd));
814                                    debug("%s,%i", regname(cpu->machine, rt), sa);
815                                    break;
816                            default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
817                                        sub);
818                            }
819                          break;                          break;
820                  case SPECIAL_DSRLV:                  case SPECIAL_DSRLV:
821                  case SPECIAL_DSRAV:                  case SPECIAL_DSRAV:
# Line 896  int mips_cpu_disassemble_instr(struct cp Line 826  int mips_cpu_disassemble_instr(struct cp
826                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
827                          rt = instr[2] & 31;                          rt = instr[2] & 31;
828                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
829                          debug("%s\t%s",                          sub = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
830                              special_names[special6], regname(cpu->machine, rd));  
831                          debug(",%s", regname(cpu->machine, rt));                          switch (sub) {
832                          debug(",%s", regname(cpu->machine, rs));                          case 0x00:
833                                    debug("%s\t%s", special_names[special6],
834                                        regname(cpu->machine, rd));
835                                    debug(",%s", regname(cpu->machine, rt));
836                                    debug(",%s", regname(cpu->machine, rs));
837                                    break;
838                            case 0x01:
839                                    debug("%s\t%s", special_rot_names[special6],
840                                        regname(cpu->machine, rd));
841                                    debug(",%s", regname(cpu->machine, rt));
842                                    debug(",%s", regname(cpu->machine, rs));
843                                    break;
844                            default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
845                                        sub);
846                            }
847                          break;                          break;
848                  case SPECIAL_JR:                  case SPECIAL_JR:
849                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
850                          symbol = get_symbol_name(&cpu->machine->symbol_context,                          symbol = get_symbol_name(&cpu->machine->symbol_context,
851                              cpu->cd.mips.gpr[rs], &offset);                              cpu->cd.mips.gpr[rs], &offset);
852                          debug("jr\t%s", regname(cpu->machine, rs));                          /*  .hb = hazard barrier hint on MIPS32/64 rev 2  */
853                            debug("jr%s\t%s",
854                                (instr[1] & 0x04) ? ".hb" : "",
855                                regname(cpu->machine, rs));
856                          if (running && symbol != NULL)                          if (running && symbol != NULL)
857                                  debug("\t<%s>", symbol);                                  debug("\t<%s>", symbol);
858                          break;                          break;
# Line 914  int mips_cpu_disassemble_instr(struct cp Line 861  int mips_cpu_disassemble_instr(struct cp
861                          rd = (instr[1] >> 3) & 31;                          rd = (instr[1] >> 3) & 31;
862                          symbol = get_symbol_name(&cpu->machine->symbol_context,                          symbol = get_symbol_name(&cpu->machine->symbol_context,
863                              cpu->cd.mips.gpr[rs], &offset);                              cpu->cd.mips.gpr[rs], &offset);
864                          debug("jalr\t%s", regname(cpu->machine, rd));                          /*  .hb = hazard barrier hint on MIPS32/64 rev 2  */
865                            debug("jalr%s\t%s",
866                                (instr[1] & 0x04) ? ".hb" : "",
867                                regname(cpu->machine, rd));
868                          debug(",%s", regname(cpu->machine, rs));                          debug(",%s", regname(cpu->machine, rs));
869                          if (running && symbol != NULL)                          if (running && symbol != NULL)
870                                  debug("\t<%s>", symbol);                                  debug("\t<%s>", symbol);
# Line 1151  int mips_cpu_disassemble_instr(struct cp Line 1101  int mips_cpu_disassemble_instr(struct cp
1101                  }                  }
1102                  if (hi6 == HI6_SQ_SPECIAL3 &&                  if (hi6 == HI6_SQ_SPECIAL3 &&
1103                      cpu->cd.mips.cpu_type.rev != MIPS_R5900) {                      cpu->cd.mips.cpu_type.rev != MIPS_R5900) {
1104                            int msbd, lsb, sub10;
1105                          special6 = instr[0] & 0x3f;                          special6 = instr[0] & 0x3f;
                         debug("%s", special3_names[special6]);  
1106                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);                          rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1107                          rt = instr[2] & 31;                          rt = instr[2] & 31;
1108                          rd = (instr[1] >> 3) & 31;                          rd = msbd = (instr[1] >> 3) & 31;
1109                            lsb = ((instr[1] & 7) << 2) | (instr[0] >> 6);
1110                            sub10 = (rs << 5) | lsb;
1111    
1112                          switch (special6) {                          switch (special6) {
1113    
1114                            case SPECIAL3_EXT:
1115                            case SPECIAL3_DEXT:
1116                            case SPECIAL3_DEXTM:
1117                            case SPECIAL3_DEXTU:
1118                                    debug("%s", special3_names[special6]);
1119                                    if (special6 == SPECIAL3_DEXTM)
1120                                            msbd += 32;
1121                                    if (special6 == SPECIAL3_DEXTU)
1122                                            lsb += 32;
1123                                    debug("\t%s", regname(cpu->machine, rt));
1124                                    debug(",%s", regname(cpu->machine, rs));
1125                                    debug(",%i,%i", lsb, msbd + 1);
1126                                    break;
1127    
1128                            case SPECIAL3_INS:
1129                            case SPECIAL3_DINS:
1130                            case SPECIAL3_DINSM:
1131                            case SPECIAL3_DINSU:
1132                                    debug("%s", special3_names[special6]);
1133                                    if (special6 == SPECIAL3_DINSM)
1134                                            msbd += 32;
1135                                    if (special6 == SPECIAL3_DINSU) {
1136                                            lsb += 32;
1137                                            msbd += 32;
1138                                    }
1139                                    msbd -= lsb;
1140                                    debug("\t%s", regname(cpu->machine, rt));
1141                                    debug(",%s", regname(cpu->machine, rs));
1142                                    debug(",%i,%i", lsb, msbd + 1);
1143                                    break;
1144    
1145                            case SPECIAL3_BSHFL:
1146                                    switch (sub10) {
1147                                    case BSHFL_WSBH:
1148                                    case BSHFL_SEB:
1149                                    case BSHFL_SEH:
1150                                            switch (sub10) {
1151                                            case BSHFL_WSBH: debug("wsbh"); break;
1152                                            case BSHFL_SEB:  debug("seb"); break;
1153                                            case BSHFL_SEH:  debug("seh"); break;
1154                                            }
1155                                            debug("\t%s", regname(cpu->machine,rd));
1156                                            debug(",%s", regname(cpu->machine,rt));
1157                                            break;
1158                                    default:debug("%s", special3_names[special6]);
1159                                            debug("\t(UNIMPLEMENTED)");
1160                                    }
1161                                    break;
1162    
1163                            case SPECIAL3_DBSHFL:
1164                                    switch (sub10) {
1165                                    case BSHFL_DSBH:
1166                                    case BSHFL_DSHD:
1167                                            switch (sub10) {
1168                                            case BSHFL_DSBH: debug("dsbh"); break;
1169                                            case BSHFL_DSHD: debug("dshd"); break;
1170                                            }
1171                                            debug("\t%s", regname(cpu->machine,rd));
1172                                            debug(",%s", regname(cpu->machine,rt));
1173                                            break;
1174                                    default:debug("%s", special3_names[special6]);
1175                                            debug("\t(UNIMPLEMENTED)");
1176                                    }
1177                                    break;
1178    
1179                          case SPECIAL3_RDHWR:                          case SPECIAL3_RDHWR:
1180                                    debug("%s", special3_names[special6]);
1181                                  debug("\t%s", regname(cpu->machine, rt));                                  debug("\t%s", regname(cpu->machine, rt));
1182                                  debug(",hwr%i", rd);                                  debug(",hwr%i", rd);
1183                                  break;                                  break;
1184    
1185                          default:                          default:debug("%s", special3_names[special6]);
1186                                  debug("\t(UNIMPLEMENTED)");                                  debug("\t(UNIMPLEMENTED)");
1187                          }                          }
1188                          break;                          break;
# Line 1449  int mips_cpu_disassemble_instr(struct cp Line 1467  int mips_cpu_disassemble_instr(struct cp
1467    
1468          case HI6_REGIMM:          case HI6_REGIMM:
1469                  regimm5 = instr[2] & 0x1f;                  regimm5 = instr[2] & 0x1f;
1470                    rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1471                    imm = (instr[1] << 8) + instr[0];
1472                    if (imm >= 32768)              
1473                            imm -= 65536;
1474    
1475                  switch (regimm5) {                  switch (regimm5) {
1476    
1477                  case REGIMM_BLTZ:                  case REGIMM_BLTZ:
1478                  case REGIMM_BGEZ:                  case REGIMM_BGEZ:
1479                  case REGIMM_BLTZL:                  case REGIMM_BLTZL:
# Line 1458  int mips_cpu_disassemble_instr(struct cp Line 1482  int mips_cpu_disassemble_instr(struct cp
1482                  case REGIMM_BLTZALL:                  case REGIMM_BLTZALL:
1483                  case REGIMM_BGEZAL:                  case REGIMM_BGEZAL:
1484                  case REGIMM_BGEZALL:                  case REGIMM_BGEZALL:
                         rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);  
                         imm = (instr[1] << 8) + instr[0];  
                         if (imm >= 32768)                
                                 imm -= 65536;  
   
1485                          debug("%s\t%s,", regimm_names[regimm5],                          debug("%s\t%s,", regimm_names[regimm5],
1486                              regname(cpu->machine, rs));                              regname(cpu->machine, rs));
1487    
# Line 1473  int mips_cpu_disassemble_instr(struct cp Line 1492  int mips_cpu_disassemble_instr(struct cp
1492                          else                          else
1493                                  debug("0x%016"PRIx64, (uint64_t) addr);                                  debug("0x%016"PRIx64, (uint64_t) addr);
1494                          break;                          break;
1495    
1496                    case REGIMM_SYNCI:
1497                            debug("%s\t%i(%s)", regimm_names[regimm5],
1498                                imm, regname(cpu->machine, rs));
1499                            break;
1500    
1501                  default:                  default:
1502                          debug("unimplemented regimm5 = 0x%02x", regimm5);                          debug("unimplemented regimm5 = 0x%02x", regimm5);
1503                  }                  }
# Line 1796  char *mips_cpu_gdb_stub(struct cpu *cpu, Line 1821  char *mips_cpu_gdb_stub(struct cpu *cpu,
1821    
1822    
1823  /*  /*
1824   *  mips_cpu_interrupt():   *  mips_cpu_interrupt_assert(), mips_cpu_interrupt_deassert():
  *  
  *  Cause an interrupt. If irq_nr is 2..7, then it is a MIPS hardware  
  *  interrupt. 0 and 1 are ignored (software interrupts).  
1825   *   *
1826   *  If irq_nr is >= 8, then this function calls md_interrupt().   *  Assert or deassert a MIPS CPU interrupt by masking in or out bits
1827     *  in the CAUSE register of coprocessor 0.
1828   */   */
1829  int mips_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)  void mips_cpu_interrupt_assert(struct interrupt *interrupt)
1830  {  {
1831          if (irq_nr >= 8) {          struct cpu *cpu = interrupt->extra;
1832                  if (cpu->machine->md_interrupt != NULL)          cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |= interrupt->line;
                         cpu->machine->md_interrupt(cpu->machine,  
                             cpu, irq_nr, 1);  
                 else  
                         fatal("mips_cpu_interrupt(): irq_nr = %i, "  
                             "but md_interrupt = NULL ?\n", irq_nr);  
                 return 1;  
         }  
   
         if (irq_nr < 2)  
                 return 0;  
   
         cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |=  
             ((1 << irq_nr) << STATUS_IM_SHIFT);  
   
         return 1;  
1833  }  }
1834    void mips_cpu_interrupt_deassert(struct interrupt *interrupt)
   
 /*  
  *  mips_cpu_interrupt_ack():  
  *  
  *  Acknowledge an interrupt. If irq_nr is 2..7, then it is a MIPS hardware  
  *  interrupt.  Interrupts 0..1 are ignored (software interrupts).  
  *  
  *  If irq_nr is >= 8, then it is machine dependent, and md_interrupt() is  
  *  called.  
  */  
 int mips_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)  
1835  {  {
1836          if (irq_nr >= 8) {          struct cpu *cpu = interrupt->extra;
1837                  if (cpu->machine->md_interrupt != NULL)          cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &= ~interrupt->line;
                         cpu->machine->md_interrupt(cpu->machine, cpu,  
                             irq_nr, 0);  
                 else  
                         fatal("mips_cpu_interrupt_ack(): irq_nr = %i, "  
                             "but md_interrupt = NULL ?\n", irq_nr);  
                 return 1;  
         }  
   
         if (irq_nr < 2)  
                 return 0;  
   
         cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &=  
             ~((1 << irq_nr) << STATUS_IM_SHIFT);  
   
         return 1;  
1838  }  }
1839    
1840    
# Line 1878  void mips_cpu_exception(struct cpu *cpu, Line 1860  void mips_cpu_exception(struct cpu *cpu,
1860          uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];          uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];
1861          int exc_model = cpu->cd.mips.cpu_type.exc_model;          int exc_model = cpu->cd.mips.cpu_type.exc_model;
1862    
1863            if (cpu->is_halted) {
1864                    /*
1865                     *  If the exception occurred on a 'wait' instruction, then let
1866                     *  the instruction following the wait instruction be the one
1867                     *  we continue at when the interrupt service routine returns.
1868                     */
1869                    cpu->is_halted = 0;
1870                    cpu->pc += sizeof(uint32_t);
1871            }
1872    
1873          if (!quiet_mode) {          if (!quiet_mode) {
1874                  uint64_t offset;                  uint64_t offset;
1875                  int x;                  int x;
# Line 2035  void mips_cpu_exception(struct cpu *cpu, Line 2027  void mips_cpu_exception(struct cpu *cpu,
2027                  /*  debug("[ warning: cpu%i exception while EXL is set,"                  /*  debug("[ warning: cpu%i exception while EXL is set,"
2028                      " not setting EPC ]\n", cpu->cpu_id);  */                      " not setting EPC ]\n", cpu->cpu_id);  */
2029          } else {          } else {
2030                  if (cpu->delay_slot || cpu->cd.mips.nullify_next) {                  if (cpu->delay_slot) {
2031                          reg[COP0_EPC] = cpu->pc - 4;                          reg[COP0_EPC] = cpu->pc - 4;
2032                          reg[COP0_CAUSE] |= CAUSE_BD;                          reg[COP0_CAUSE] |= CAUSE_BD;
   
                         /*  TODO: Should the BD flag actually be set  
                             on nullified slots?  */  
2033                  } else {                  } else {
2034                          reg[COP0_EPC] = cpu->pc;                          reg[COP0_EPC] = cpu->pc;
2035                          reg[COP0_CAUSE] &= ~CAUSE_BD;                          reg[COP0_CAUSE] &= ~CAUSE_BD;
# Line 2052  void mips_cpu_exception(struct cpu *cpu, Line 2041  void mips_cpu_exception(struct cpu *cpu,
2041          else          else
2042                  cpu->delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
2043    
         cpu->cd.mips.nullify_next = 0;  
   
2044          /*  TODO: This is true for MIPS64, but how about others?  */          /*  TODO: This is true for MIPS64, but how about others?  */
2045          if (reg[COP0_STATUS] & STATUS_BEV)          if (reg[COP0_STATUS] & STATUS_BEV)
2046                  base = 0xffffffffbfc00200ULL;                  base = 0xffffffffbfc00200ULL;

Legend:
Removed from v.28  
changed lines
  Added in v.34

  ViewVC Help
Powered by ViewVC 1.1.26