/[gxemul]/trunk/src/cpus/cpu_mips_instr.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_instr.c

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

revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips_instr.c,v 1.104 2006/08/14 17:45:47 debug Exp $   *  $Id: cpu_mips_instr.c,v 1.118 2006/10/29 05:10:27 debug Exp $
29   *   *
30   *  MIPS instructions.   *  MIPS instructions.
31   *   *
# Line 37  Line 37 
37    
38    
39  /*  /*
40     *  COPROC_AVAILABILITY_CHECK(n) checks for the coprocessor available bit for
41     *  coprocessor number n, and causes a CoProcessor Unusable exception if it
42     *  is not set.  (Note: For coprocessor 0 checks, use cop0_availability_check!)
43     */
44    #ifndef COPROC_AVAILABILITY_CHECK
45    #define COPROC_AVAILABILITY_CHECK(x)            {               \
46                    const int cpnr = (x);                                   \
47                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) \
48                        / sizeof(struct mips_instr_call);                   \
49                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)               \
50                        << MIPS_INSTR_ALIGNMENT_SHIFT);                     \
51                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);      \
52                    if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &        \
53                        ((1 << cpnr) << STATUS_CU_SHIFT)) ) {               \
54                            mips_cpu_exception(cpu, EXCEPTION_CPU,          \
55                                0, 0, cpnr, 0, 0, 0);                       \
56                            return;                                         \
57                    }                                                       \
58            }
59    #endif
60    
61    
62    #ifndef COP0_AVAILABILITY_CHECK_INCLUDED
63    #define COP0_AVAILABILITY_CHECK_INCLUDED
64    /*
65     *  cop0_availability_check() causes a CoProcessor Unusable exception if
66     *  we are currently running in usermode, and the coprocessor available bit
67     *  for coprocessor 0 is not set.
68     *
69     *  Returns 1 if ok (i.e. if the coprocessor was usable), 0 on exceptions.
70     */
71    int cop0_availability_check(struct cpu *cpu, struct mips_instr_call *ic)
72    {
73            int in_usermode = 0;
74            struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
75    
76            switch (cpu->cd.mips.cpu_type.exc_model) {
77            case EXC3K:
78                    /*
79                     *  NOTE: If the KU bit is checked, Linux crashes.
80                     *  It is the PC that counts.
81                     *
82                     *  TODO: Check whether this is true or not for R4000 as well.
83                     */
84                    /*  TODO: if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR)  */
85                    if (cpu->pc <= 0x7fffffff)
86                            in_usermode = 1;
87                    break;
88            default:
89                    /*  R4000 etc:  (TODO: How about supervisor mode?)  */
90                    if (((cp0->reg[COP0_STATUS] &
91                        STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
92                            in_usermode = 1;
93                    if (cp0->reg[COP0_STATUS] & (STATUS_ERL | STATUS_EXL))
94                            in_usermode = 0;
95                    break;
96            }
97    
98            if (in_usermode) {
99                    int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
100                        / sizeof(struct mips_instr_call);
101                    cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
102                        << MIPS_INSTR_ALIGNMENT_SHIFT);
103                    cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
104                    if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &
105                        (1 << STATUS_CU_SHIFT)) ) {
106                            mips_cpu_exception(cpu, EXCEPTION_CPU,
107                                0, 0, /* cpnr */ 0, 0, 0, 0);
108                            return 0;
109                    }
110            }
111    
112            return 1;
113    }
114    #endif
115    
116    
117    /*
118   *  invalid:  For catching bugs.   *  invalid:  For catching bugs.
119   */   */
120  X(invalid)  X(invalid)
# Line 1071  X(cache) Line 1149  X(cache)
1149    
1150    
1151  /*  /*
1152     *  ext:  Extract bitfield.
1153     *
1154     *  arg[0] = pointer to rt
1155     *  arg[1] = pointer to rs
1156     *  arg[2] = (msbd << 5) + lsb
1157     */
1158    X(ext)
1159    {
1160            fatal("ext: todo\n");
1161            exit(1);
1162    }
1163    
1164    
1165    /*
1166     *  dsbh:  Doubleword swap bytes within half-word
1167     *  dshd:  Doubleword swap half-words within double-word
1168     *  wsbh:  Word swap bytes within half-word
1169     *  seb:   Sign-extend byte
1170     *  seh:   Sign-extend half-word
1171     *
1172     *  arg[0] = pointer to rt
1173     *  arg[1] = pointer to rd
1174     */
1175    X(dsbh)
1176    {
1177            uint64_t x = reg(ic->arg[0]);
1178            x = ((x & 0x00ff00ff00ff00ffULL) << 8)
1179              | ((x & 0xff00ff00ff00ff00ULL) >> 8);
1180            reg(ic->arg[1]) = x;
1181    }
1182    X(dshd)
1183    {
1184            uint64_t x = reg(ic->arg[0]);
1185            x = ((x & 0x000000000000ffffULL) << 48)
1186              | ((x & 0x00000000ffff0000ULL) << 16)
1187              | ((x & 0x0000ffff00000000ULL) >> 16)
1188              | ((x & 0xffff000000000000ULL) >> 48);
1189            reg(ic->arg[1]) = x;
1190    }
1191    X(wsbh)
1192    {
1193            uint32_t x = reg(ic->arg[0]);
1194            x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
1195            reg(ic->arg[1]) = (int32_t) x;
1196    }
1197    X(seb) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); }
1198    X(seh) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); }
1199    
1200    
1201    /*
1202   *  2-register + immediate:   *  2-register + immediate:
1203   *   *
1204   *  arg[0] = pointer to rs   *  arg[0] = pointer to rs
# Line 1096  X(div) Line 1224  X(div)
1224                  res = 0, rem = a;                  res = 0, rem = a;
1225          else          else
1226                  res = a / b, rem = a - b*res;                  res = a / b, rem = a - b*res;
1227          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1228          reg(&cpu->cd.mips.hi) = (int32_t)rem;          cpu->cd.mips.hi = (int32_t)rem;
1229  }  }
1230  X(divu)  X(divu)
1231  {  {
# Line 1107  X(divu) Line 1235  X(divu)
1235                  res = 0, rem = a;                  res = 0, rem = a;
1236          else          else
1237                  res = a / b, rem = a - b*res;                  res = a / b, rem = a - b*res;
1238          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1239          reg(&cpu->cd.mips.hi) = (int32_t)rem;          cpu->cd.mips.hi = (int32_t)rem;
1240  }  }
1241  X(ddiv)  X(ddiv)
1242  {  {
# Line 1119  X(ddiv) Line 1247  X(ddiv)
1247          else          else
1248                  res = a / b;                  res = a / b;
1249          rem = a - b*res;          rem = a - b*res;
1250          reg(&cpu->cd.mips.lo) = res;          cpu->cd.mips.lo = res;
1251          reg(&cpu->cd.mips.hi) = rem;          cpu->cd.mips.hi = rem;
1252  }  }
1253  X(ddivu)  X(ddivu)
1254  {  {
# Line 1131  X(ddivu) Line 1259  X(ddivu)
1259          else          else
1260                  res = a / b;                  res = a / b;
1261          rem = a - b*res;          rem = a - b*res;
1262          reg(&cpu->cd.mips.lo) = res;          cpu->cd.mips.lo = res;
1263          reg(&cpu->cd.mips.hi) = rem;          cpu->cd.mips.hi = rem;
1264  }  }
1265  X(mult)  X(mult)
1266  {  {
1267          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1268          int64_t res = (int64_t)a * (int64_t)b;          int64_t res = (int64_t)a * (int64_t)b;
1269          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1270          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1271  }  }
1272  X(mult_r5900)  X(mult_r5900)
1273  {  {
# Line 1147  X(mult_r5900) Line 1275  X(mult_r5900)
1275              hi, lo, and a third register  */              hi, lo, and a third register  */
1276          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1277          int64_t res = (int64_t)a * (int64_t)b;          int64_t res = (int64_t)a * (int64_t)b;
1278          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1279          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1280          reg(ic->arg[2]) = (int32_t)res;          reg(ic->arg[2]) = (int32_t)res;
1281  }  }
1282  X(multu)  X(multu)
1283  {  {
1284          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1285          uint64_t res = (uint64_t)a * (uint64_t)b;          uint64_t res = (uint64_t)a * (uint64_t)b;
1286          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1287          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1288  }  }
1289  X(multu_r5900)  X(multu_r5900)
1290  {  {
# Line 1164  X(multu_r5900) Line 1292  X(multu_r5900)
1292              hi, lo, and a third register  */              hi, lo, and a third register  */
1293          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1294          uint64_t res = (uint64_t)a * (uint64_t)b;          uint64_t res = (uint64_t)a * (uint64_t)b;
1295          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1296          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1297          reg(ic->arg[2]) = (int32_t)res;          reg(ic->arg[2]) = (int32_t)res;
1298  }  }
1299  X(dmult)  X(dmult)
# Line 1194  X(dmult) Line 1322  X(dmult)
1322                  hi ^= (int64_t) -1;                  hi ^= (int64_t) -1;
1323                  lo ^= (int64_t) -1;                  lo ^= (int64_t) -1;
1324          }          }
1325          reg(&cpu->cd.mips.lo) = lo;          cpu->cd.mips.lo = lo;
1326          reg(&cpu->cd.mips.hi) = hi;          cpu->cd.mips.hi = hi;
1327  }  }
1328  X(dmultu)  X(dmultu)
1329  {  {
# Line 1211  X(dmultu) Line 1339  X(dmultu)
1339                  }                  }
1340                  c = (c << 1) | (b >> 63); b <<= 1;                  c = (c << 1) | (b >> 63); b <<= 1;
1341          }          }
1342          reg(&cpu->cd.mips.lo) = lo;          cpu->cd.mips.lo = lo;
1343          reg(&cpu->cd.mips.hi) = hi;          cpu->cd.mips.hi = hi;
1344  }  }
1345  X(tge)  X(tge)
1346  {  {
# Line 1621  X(sltiu) Line 1749  X(sltiu)
1749    
1750  /*  /*
1751   *  set:  Set a register to an immediate (signed) 32-bit value.   *  set:  Set a register to an immediate (signed) 32-bit value.
1752     *        (This is the actual implementation of the lui instruction.)
1753   *   *
1754   *  arg[0] = pointer to the register   *  arg[0] = pointer to the register
1755   *  arg[1] = (int32_t) immediate value   *  arg[1] = (int32_t) immediate value
# Line 1659  X(mfc0) Line 1788  X(mfc0)
1788          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);
1789          reg(ic->arg[0]) = (int32_t)tmp;          reg(ic->arg[0]) = (int32_t)tmp;
1790  }  }
1791    X(mfc0_select0)
1792    {
1793            /*  Fast int32_t read, with no side effects:  */
1794            int rd = ic->arg[1] & 31;
1795    #if 0
1796            uint64_t tmp;
1797            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1798            cpu->pc |= ic->arg[2];
1799            /*  TODO: cause exception if necessary  */
1800    #endif
1801            reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->reg[rd];
1802    }
1803  X(mtc0)  X(mtc0)
1804  {  {
1805          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
# Line 1702  X(dmfc0) Line 1843  X(dmfc0)
1843          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1844              (uint64_t *)ic->arg[0], select);              (uint64_t *)ic->arg[0], select);
1845  }  }
1846    X(dmfc0_select0)
1847    {
1848            /*  Fast int64_t read, with no side effects:  */
1849            int rd = ic->arg[1] & 31;
1850    #if 0
1851            uint64_t tmp;
1852            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1853            cpu->pc |= ic->arg[2];
1854            /*  TODO: cause exception if necessary  */
1855    #endif
1856            reg(ic->arg[0]) = cpu->cd.mips.coproc[0]->reg[rd];
1857    }
1858  X(dmtc0)  X(dmtc0)
1859  {  {
1860          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
# Line 1723  X(dmtc0) Line 1876  X(dmtc0)
1876  X(cop1_bc)  X(cop1_bc)
1877  {  {
1878          MODE_int_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
1879          const int cpnr = 1;          int x, cc = ic->arg[0];
         int x, low_pc, cc = ic->arg[0];  
1880    
1881          low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)          COPROC_AVAILABILITY_CHECK(1);
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
1882    
1883          /*  Get the correct condition code bit:  */          /*  Get the correct condition code bit:  */
1884          if (cc == 0)          if (cc == 0)
# Line 1774  X(cop1_bc) Line 1918  X(cop1_bc)
1918   */   */
1919  X(cop1_slow)  X(cop1_slow)
1920  {  {
1921          const int cpnr = 1;          COPROC_AVAILABILITY_CHECK(1);
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
1922    
1923          coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);          coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1924  }  }
# Line 1811  X(break) Line 1945  X(break)
1945  }  }
1946  X(reboot)  X(reboot)
1947  {  {
1948            if (!cop0_availability_check(cpu, ic))
1949                    return;
1950    
1951          cpu->running = 0;          cpu->running = 0;
1952          debugger_n_steps_left_before_interaction = 0;          debugger_n_steps_left_before_interaction = 0;
1953          cpu->cd.mips.next_ic = &nothing_call;          cpu->cd.mips.next_ic = &nothing_call;
# Line 1873  X(promemul) Line 2010  X(promemul)
2010   */   */
2011  X(tlbw)  X(tlbw)
2012  {  {
2013            if (!cop0_availability_check(cpu, ic))
2014                    return;
2015    
2016          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2017          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
2018          coproc_tlbwri(cpu, ic->arg[0]);          coproc_tlbwri(cpu, ic->arg[0]);
# Line 1887  X(tlbw) Line 2027  X(tlbw)
2027   */   */
2028  X(tlbp)  X(tlbp)
2029  {  {
2030            if (!cop0_availability_check(cpu, ic))
2031                    return;
2032    
2033          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2034          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
2035          coproc_tlbpr(cpu, 0);          coproc_tlbpr(cpu, 0);
2036  }  }
2037  X(tlbr)  X(tlbr)
2038  {  {
2039            if (!cop0_availability_check(cpu, ic))
2040                    return;
2041    
2042          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2043          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
2044          coproc_tlbpr(cpu, 1);          coproc_tlbpr(cpu, 1);
# Line 1904  X(tlbr) Line 2050  X(tlbr)
2050   */   */
2051  X(rfe)  X(rfe)
2052  {  {
2053            if (!cop0_availability_check(cpu, ic))
2054                    return;
2055    
2056          /*  Just rotate the interrupt/user bits:  */          /*  Just rotate the interrupt/user bits:  */
2057          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2058              (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |              (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
# Line 1922  X(rfe) Line 2071  X(rfe)
2071   */   */
2072  X(eret)  X(eret)
2073  {  {
2074            if (!cop0_availability_check(cpu, ic))
2075                    return;
2076    
2077          if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {          if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2078                  cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];                  cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2079                  cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;                  cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
# Line 1942  X(eret) Line 2094  X(eret)
2094   */   */
2095  X(deret)  X(deret)
2096  {  {
2097            if (!cop0_availability_check(cpu, ic))
2098                    return;
2099    
2100          /*          /*
2101           *  According to the MIPS64 manual, deret loads PC from the DEPC cop0           *  According to the MIPS64 manual, deret loads PC from the DEPC cop0
2102           *  register, and jumps there immediately. No delay slot.           *  register, and jumps there immediately. No delay slot.
# Line 1960  X(deret) Line 2115  X(deret)
2115    
2116    
2117  /*  /*
2118   *  wait: Wait for external interrupt.   *  idle:  Called from the implementation of wait, or netbsd_pmax_idle.
2119   */   */
2120  X(wait)  X(idle)
2121  {  {
2122          /*          /*
2123           *  If there is an interrupt, then just return. Otherwise           *  If there is an interrupt, then just return. Otherwise
# Line 1971  X(wait) Line 2126  X(wait)
2126          uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];          uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2127          uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];          uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
2128    
         /*  NOTE: STATUS_IE happens to match the enable bit also  
             on R2000/R3000, so this is ok.  */  
2129          if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {          if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2130                  if (status & (STATUS_EXL | STATUS_ERL))                  if (status & (STATUS_EXL | STATUS_ERL))
2131                          status &= ~STATUS_IE;                          status &= ~STATUS_IE;
2132          }          }
2133    
2134          /*  Ugly R5900 special case:  (TODO: move this?)  */          /*  Ugly R5900 special case:  (TODO: move this?)  */
2135          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
2136              !(status & R5900_STATUS_EIE))              !(status & R5900_STATUS_EIE))
# Line 1986  X(wait) Line 2140  X(wait)
2140    
2141          cpu->cd.mips.next_ic = ic;          cpu->cd.mips.next_ic = ic;
2142          cpu->is_halted = 1;          cpu->is_halted = 1;
2143            cpu->has_been_idling = 1;
2144    
2145          /*          /*
2146           *  There was no interrupt. Go to sleep.           *  There was no interrupt. Go to sleep.
# Line 1999  X(wait) Line 2154  X(wait)
2154          if (cpu->machine->ncpus == 1) {          if (cpu->machine->ncpus == 1) {
2155                  static int x = 0;                  static int x = 0;
2156                  if ((++x) == 600) {                  if ((++x) == 600) {
2157                          usleep(1);                          usleep(10);
2158                          x = 0;                          x = 0;
2159                  }                  }
2160                  cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;                  cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
# Line 2008  X(wait) Line 2163  X(wait)
2163    
2164    
2165  /*  /*
2166     *  wait: Wait for external interrupt.
2167     */
2168    X(wait)
2169    {
2170            if (!cop0_availability_check(cpu, ic))
2171                    return;
2172    
2173            instr(idle)(cpu, ic);
2174    }
2175    
2176    
2177    /*
2178   *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).   *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2179   *   *
2180   *  arg[0] = ptr to rt (destination register)   *  arg[0] = ptr to rt (destination register)
# Line 2244  X(scd) Line 2411  X(scd)
2411   */   */
2412  X(lwc1)  X(lwc1)
2413  {  {
2414          const int cpnr = 1;          COPROC_AVAILABILITY_CHECK(1);
   
         /*  Synch. PC and call the generic load/store function:  */  
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)  
             << MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         /*  ... but first, let's see if the coprocessor is available:  */  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
2415    
2416  #ifdef MODE32  #ifdef MODE32
2417          mips32_loadstore          mips32_loadstore
# Line 2270  X(lwc1) Line 2423  X(lwc1)
2423  }  }
2424  X(swc1)  X(swc1)
2425  {  {
2426          const int cpnr = 1;          COPROC_AVAILABILITY_CHECK(1);
   
         /*  Synch. PC and call the generic load/store function:  */  
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)  
             << MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         /*  ... but first, let's see if the coprocessor is available:  */  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
2427    
2428  #ifdef MODE32  #ifdef MODE32
2429          mips32_loadstore          mips32_loadstore
# Line 2296  X(swc1) Line 2435  X(swc1)
2435  }  }
2436  X(ldc1)  X(ldc1)
2437  {  {
         const int cpnr = 1;  
2438          int use_fp_pairs =          int use_fp_pairs =
2439              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2440          uint64_t fpr, *backup_ptr;          uint64_t fpr, *backup_ptr;
2441    
2442          /*  Synch. PC and call the generic load/store function:  */          COPROC_AVAILABILITY_CHECK(1);
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)  
             << MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         /*  ... but first, let's see if the coprocessor is available:  */  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
2443    
2444          backup_ptr = (uint64_t *) ic->arg[0];          backup_ptr = (uint64_t *) ic->arg[0];
2445          ic->arg[0] = (size_t) &fpr;          ic->arg[0] = (size_t) &fpr;
# Line 2337  X(ldc1) Line 2463  X(ldc1)
2463  }  }
2464  X(sdc1)  X(sdc1)
2465  {  {
         const int cpnr = 1;  
2466          int use_fp_pairs =          int use_fp_pairs =
2467              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2468          uint64_t fpr, *backup_ptr;          uint64_t fpr, *backup_ptr;
2469    
2470          /*  Synch. PC and call the generic load/store function:  */          COPROC_AVAILABILITY_CHECK(1);
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)  
             << MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         /*  ... but first, let's see if the coprocessor is available:  */  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
2471    
2472          backup_ptr = (uint64_t *) ic->arg[0];          backup_ptr = (uint64_t *) ic->arg[0];
2473          ic->arg[0] = (size_t) &fpr;          ic->arg[0] = (size_t) &fpr;
# Line 2405  X(sdr) { mips_unaligned_loadstore(cpu, i Line 2518  X(sdr) { mips_unaligned_loadstore(cpu, i
2518   */   */
2519  X(di_r5900)  X(di_r5900)
2520  {  {
2521            if (!cop0_availability_check(cpu, ic))
2522                    return;
2523    
2524          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2525  }  }
2526  X(ei_r5900)  X(ei_r5900)
2527  {  {
2528            if (!cop0_availability_check(cpu, ic))
2529                    return;
2530    
2531          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2532  }  }
2533    
# Line 3029  X(netbsd_r3k_picache_do_inv) Line 3148  X(netbsd_r3k_picache_do_inv)
3148    
3149  #ifdef MODE32  #ifdef MODE32
3150  /*  /*
3151     *  netbsd_pmax_idle():
3152     *
3153     *  s:  lui     rX, hi
3154     *      lw      rY, lo(rX)
3155     *      nop
3156     *      beq     zr, rY, s
3157     *      nop
3158     */
3159    X(netbsd_pmax_idle)
3160    {
3161            uint32_t addr, pageindex, i;
3162            int32_t *page;
3163    
3164            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3165    
3166            addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
3167            pageindex = addr >> 12;
3168            i = (addr & 0xfff) >> 2;
3169            page = (int32_t *) cpu->cd.mips.host_load[pageindex];
3170    
3171            /*  Fallback:  */
3172            if (cpu->delay_slot || page == NULL || page[i] != 0)
3173                    return;
3174    
3175            instr(idle)(cpu, ic);
3176    }
3177    
3178    
3179    /*
3180     *  linux_pmax_idle():
3181     *
3182     *  s:  lui     rX, hi
3183     *      lw      rX, lo(rX)
3184     *      nop
3185     *      bne     zr, rX, ...
3186     *      nop
3187     *      lw      rX, ofs(gp)
3188     *      nop
3189     *      beq     zr, rX, s
3190     *      nop
3191     */
3192    X(linux_pmax_idle)
3193    {
3194            uint32_t addr, addr2, pageindex, pageindex2, i, i2;
3195            int32_t *page, *page2;
3196    
3197            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3198    
3199            addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
3200            pageindex = addr >> 12;
3201            i = (addr & 0xfff) >> 2;
3202            page = (int32_t *) cpu->cd.mips.host_load[pageindex];
3203    
3204            addr2 = reg(ic[5].arg[1]) + (int32_t)ic[5].arg[2];
3205            pageindex2 = addr2 >> 12;
3206            i2 = (addr2 & 0xfff) >> 2;
3207            page2 = (int32_t *) cpu->cd.mips.host_load[pageindex2];
3208    
3209            /*  Fallback:  */
3210            if (cpu->delay_slot || page == NULL || page[i] != 0 || page2[i2] != 0)
3211                    return;
3212    
3213            instr(idle)(cpu, ic);
3214    }
3215    
3216    
3217    /*
3218   *  netbsd_strlen():   *  netbsd_strlen():
3219   *   *
3220   *      lb      rV,0(rX)   *      lb      rV,0(rX)
# Line 3468  void COMBINE(netbsd_r3k_cache_inv)(struc Line 3654  void COMBINE(netbsd_r3k_cache_inv)(struc
3654   *   *
3655   *      NetBSD's strlen core.   *      NetBSD's strlen core.
3656   *      [Conditional] branch, followed by nop.   *      [Conditional] branch, followed by nop.
3657     *      NetBSD/pmax' idle loop (and possibly others as well).
3658     *      Linux/pmax' idle loop.
3659   */   */
3660  void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)  void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3661  {  {
3662          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3663              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3664    
3665            if (n_back < 8)
3666                    return;
3667    
3668  #ifdef MODE32  #ifdef MODE32
3669          if (n_back < 3)          if (ic[-8].f == instr(set) &&
3670                ic[-7].f == mips32_loadstore[4 + 1] &&
3671                ic[-7].arg[0] == ic[-1].arg[0] &&
3672                ic[-7].arg[0] == ic[-3].arg[0] &&
3673                ic[-7].arg[0] == ic[-5].arg[0] &&
3674                ic[-7].arg[0] == ic[-7].arg[1] &&
3675                ic[-7].arg[0] == ic[-8].arg[0] &&
3676                ic[-6].f == instr(nop) &&
3677                ic[-5].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3678                ic[-5].f == instr(bne_samepage_nop) &&
3679                ic[-4].f == instr(nop) &&
3680                ic[-3].f == mips32_loadstore[4 + 1] &&
3681                ic[-2].f == instr(nop) &&
3682                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3683                ic[-1].arg[2] == (size_t) &ic[-8] &&
3684                ic[-1].f == instr(beq_samepage)) {
3685                    ic[-8].f = instr(linux_pmax_idle);
3686                    return;
3687            }
3688    
3689            if (ic[-4].f == instr(set) &&
3690                ic[-3].f == mips32_loadstore[4 + 1] &&
3691                ic[-3].arg[0] == ic[-1].arg[0] &&
3692                ic[-3].arg[1] == ic[-4].arg[0] &&
3693                ic[-2].f == instr(nop) &&
3694                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3695                ic[-1].arg[2] == (size_t) &ic[-4] &&
3696                ic[-1].f == instr(beq_samepage)) {
3697                    ic[-4].f = instr(netbsd_pmax_idle);
3698                  return;                  return;
3699            }
3700    
3701          if ((ic[-3].f == mips32_loadstore[1] ||          if ((ic[-3].f == mips32_loadstore[1] ||
3702              ic[-3].f == mips32_loadstore[16 + 1]) &&              ic[-3].f == mips32_loadstore[16 + 1]) &&
# Line 3491  void COMBINE(nop)(struct cpu *cpu, struc Line 3711  void COMBINE(nop)(struct cpu *cpu, struc
3711          }          }
3712  #endif  #endif
3713    
         if (n_back < 1)  
                 return;  
   
3714          if (ic[-1].f == instr(bne_samepage)) {          if (ic[-1].f == instr(bne_samepage)) {
3715                  ic[-1].f = instr(bne_samepage_nop);                  ic[-1].f = instr(bne_samepage_nop);
3716                  return;                  return;
# Line 3660  X(to_be_translated) Line 3877  X(to_be_translated)
3877          uint32_t iword, imm;          uint32_t iword, imm;
3878          unsigned char *page;          unsigned char *page;
3879          unsigned char ib[4];          unsigned char ib[4];
3880          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;          int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10;
3881          int in_crosspage_delayslot = 0;          int in_crosspage_delayslot = 0;
3882          void (*samepage_function)(struct cpu *, struct mips_instr_call *);          void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3883          int store, signedness, size;          int store, signedness, size;
# Line 3741  X(to_be_translated) Line 3958  X(to_be_translated)
3958          sa = (iword >>  6) & 31;          sa = (iword >>  6) & 31;
3959          imm = (int16_t)iword;          imm = (int16_t)iword;
3960          s6 = iword & 63;          s6 = iword & 63;
3961            s10 = (rs << 5) | sa;
3962    
3963          switch (main_opcode) {          switch (main_opcode) {
3964    
# Line 3795  X(to_be_translated) Line 4013  X(to_be_translated)
4013                                  ic->f = instr(nop);                                  ic->f = instr(nop);
4014                          if (ic->f == instr(sll))                          if (ic->f == instr(sll))
4015                                  cpu->cd.mips.combination_check = COMBINE(sll);                                  cpu->cd.mips.combination_check = COMBINE(sll);
4016                            if (ic->f == instr(nop))
4017                                    cpu->cd.mips.combination_check = COMBINE(nop);
4018    
4019                            /*  Special checks for MIPS32/64 revision 2 opcodes,
4020                                such as rotation instructions:  */
4021                            if (sa >= 0 && rs != 0x00) {
4022                                    switch (rs) {
4023                                    /*  TODO: [d]ror, etc.  */
4024                                    default:goto bad;
4025                                    }
4026                            }
4027                            if (sa < 0 && (s10 & 0x1f) != 0) {
4028                                    switch (s10 & 0x1f) {
4029                                    /*  TODO: [d]rorv, etc.  */
4030                                    default:goto bad;
4031                                    }
4032                            }
4033                          break;                          break;
4034    
4035                  case SPECIAL_ADD:                  case SPECIAL_ADD:
# Line 4188  X(to_be_translated) Line 4423  X(to_be_translated)
4423                                  }                                  }
4424                                  break;                                  break;
4425                          case COP0_STANDBY:                          case COP0_STANDBY:
4426                          case COP0_SUSPEND:                                  /*  NOTE: Reusing the 'wait' instruction:  */
4427                                    ic->f = instr(wait);
4428                                    if (cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
4429                                            static int warned = 0;
4430                                            ic->f = instr(reserved);
4431                                            if (!warned) {
4432                                                    fatal("{ WARNING: Attempt to "
4433                                                        "execute a R41xx instruct"
4434                                                        "ion, but the emulated CPU "
4435                                                        "doesn't support it! }\n");
4436                                                    warned = 1;
4437                                            }
4438                                    }
4439                                    break;
4440                          case COP0_HIBERNATE:                          case COP0_HIBERNATE:
4441                                  /*  TODO  */                                  /*  TODO  */
4442                                  ic->f = instr(nop);                                  goto bad;
4443                            case COP0_SUSPEND:
4444                                    /*  Used by NetBSD on HPCmips (VR41xx) to
4445                                        halt the machine.  */
4446                                    ic->f = instr(reboot);
4447                                  break;                                  break;
4448                          case COP0_EI:                          case COP0_EI:
4449                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
# Line 4228  X(to_be_translated) Line 4480  X(to_be_translated)
4480                          ic->arg[1] = rd + ((iword & 7) << 5);                          ic->arg[1] = rd + ((iword & 7) << 5);
4481                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
4482                          ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);                          ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
4483                            if (rs == COPz_MFCz && (iword & 7) == 0 &&
4484                                rd != COP0_COUNT)
4485                                    ic->f = instr(mfc0_select0);
4486                            if (rs == COPz_DMFCz && (iword & 7) == 0 &&
4487                                rd != COP0_COUNT)
4488                                    ic->f = instr(dmfc0_select0);
4489                          if (rt == MIPS_GPR_ZERO)                          if (rt == MIPS_GPR_ZERO)
4490                                  ic->f = instr(nop);                                  ic->f = instr(nop);
4491                          break;                          break;
# Line 4701  X(to_be_translated) Line 4959  X(to_be_translated)
4959    
4960                  switch (s6) {                  switch (s6) {
4961    
4962                    case SPECIAL3_EXT:
4963                            /*  TODO: Cleanup and extend to DEXT... etc  */
4964                            {
4965                                    int msbd = rd, lsb = (iword >> 6) & 0x1f;
4966                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4967                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4968                                    ic->arg[2] = (msbd << 5) + lsb;
4969                                    ic->f = instr(ext);
4970                                    if (rt == MIPS_GPR_ZERO)
4971                                            ic->f = instr(nop);
4972                            }
4973                            break;
4974    
4975                    case SPECIAL3_BSHFL:
4976                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4977                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4978                            switch (s10) {
4979                            case BSHFL_WSBH:
4980                                    ic->f = instr(wsbh);
4981                                    break;
4982                            case BSHFL_SEB:
4983                                    ic->f = instr(seb);
4984                                    break;
4985                            case BSHFL_SEH:
4986                                    ic->f = instr(seh);
4987                                    break;
4988                            default:goto bad;
4989                            }
4990                            break;
4991    
4992                    case SPECIAL3_DBSHFL:
4993                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4994                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4995                            switch (s10) {
4996                            case BSHFL_DSBH:
4997                                    ic->f = instr(dsbh);
4998                                    break;
4999                            case BSHFL_DSHD:
5000                                    ic->f = instr(dshd);
5001                                    break;
5002                            default:goto bad;
5003                            }
5004                            break;
5005    
5006                  case SPECIAL3_RDHWR:                  case SPECIAL3_RDHWR:
5007                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
5008    
# Line 4741  X(to_be_translated) Line 5043  X(to_be_translated)
5043          }          }
5044  #endif  #endif
5045    
         if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL)  
                 cpu->cd.mips.combination_check = COMBINE(nop);  
   
5046    
5047  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
5048  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"

Legend:
Removed from v.30  
changed lines
  Added in v.32

  ViewVC Help
Powered by ViewVC 1.1.26