/[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 28 by dpavlin, Mon Oct 8 16:20:26 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.97 2006/07/20 03:20:03 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 1679  X(mtc0) Line 1820  X(mtc0)
1820                  uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];                  uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1821                  /*  NOTE: STATUS_IE happens to match the enable bit also                  /*  NOTE: STATUS_IE happens to match the enable bit also
1822                      on R2000/R3000, so this is ok.  */                      on R2000/R3000, so this is ok.  */
1823                  if (status & (STATUS_EXL | STATUS_ERL))                  if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1824                          status &= ~STATUS_IE;                          if (status & (STATUS_EXL | STATUS_ERL))
1825                                    status &= ~STATUS_IE;
1826                    }
1827                  /*  Ugly R5900 special case:  (TODO: move this?)  */                  /*  Ugly R5900 special case:  (TODO: move this?)  */
1828                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1829                      !(status & R5900_STATUS_EIE))                      !(status & R5900_STATUS_EIE))
# Line 1700  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 1721  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 1772  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 1807  X(break) Line 1943  X(break)
1943          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1944          mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);          mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1945  }  }
1946    X(reboot)
1947    {
1948            if (!cop0_availability_check(cpu, ic))
1949                    return;
1950    
1951            cpu->running = 0;
1952            debugger_n_steps_left_before_interaction = 0;
1953            cpu->cd.mips.next_ic = &nothing_call;
1954    }
1955    
1956    
1957  /*  /*
# Line 1865  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 1879  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 1896  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 1914  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 1934  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 1952  X(deret) Line 2115  X(deret)
2115    
2116    
2117  /*  /*
2118     *  idle:  Called from the implementation of wait, or netbsd_pmax_idle.
2119     */
2120    X(idle)
2121    {
2122            /*
2123             *  If there is an interrupt, then just return. Otherwise
2124             *  re-run the wait instruction (after a delay).
2125             */
2126            uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2127            uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
2128    
2129            if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2130                    if (status & (STATUS_EXL | STATUS_ERL))
2131                            status &= ~STATUS_IE;
2132            }
2133    
2134            /*  Ugly R5900 special case:  (TODO: move this?)  */
2135            if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
2136                !(status & R5900_STATUS_EIE))
2137                    status &= ~STATUS_IE;
2138            if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
2139                    return;
2140    
2141            cpu->cd.mips.next_ic = ic;
2142            cpu->is_halted = 1;
2143            cpu->has_been_idling = 1;
2144    
2145            /*
2146             *  There was no interrupt. Go to sleep.
2147             *
2148             *  TODO:
2149             *
2150             *  Think about how to actually implement this usleep stuff,
2151             *  in an SMP and/or timing accurate environment.
2152             */
2153    
2154            if (cpu->machine->ncpus == 1) {
2155                    static int x = 0;
2156                    if ((++x) == 600) {
2157                            usleep(10);
2158                            x = 0;
2159                    }
2160                    cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2161            }
2162    }
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 2188  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 2214  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 2240  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 2281  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 2349  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 2381  X(sw_loop) Line 2556  X(sw_loop)
2556          if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {          if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2557                  instr(addiu)(cpu, ic);                  instr(addiu)(cpu, ic);
2558                  return;                  return;
2559          }          }
2560    
2561          if (rYp == (uint64_t *) ic->arg[0])          if (rYp == (uint64_t *) ic->arg[0])
2562                  rYp = (uint64_t *) ic[1].arg[1];                  rYp = (uint64_t *) ic[1].arg[1];
# Line 2410  X(sw_loop) Line 2585  X(sw_loop)
2585  }  }
2586    
2587    
2588    #ifdef MODE32
2589  /*  /*
2590   *  multi_sw_3:   *  multi_sw_2, _3, _4:
2591   *   *
2592   *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]   *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
  *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]  
  *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]  
2593   */   */
2594    X(multi_sw_2_le)
2595    {
2596            uint32_t *page;
2597            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2598            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2599            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2600            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2601    
2602            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2603    
2604            /*  Fallback:  */
2605            if (cpu->delay_slot ||
2606                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2607                index0 != index1) {
2608                    /*  Normal safe sw:  */
2609                    mips32_loadstore[8 + 2 * 2](cpu, ic);
2610                    return;
2611            }
2612    
2613            addr0 = (addr0 >> 2) & 0x3ff;
2614            addr1 = (addr1 >> 2) & 0x3ff;
2615    
2616            r1 = reg(ic[0].arg[0]);
2617            r2 = reg(ic[1].arg[0]);
2618    
2619            r1 = LE32_TO_HOST(r1);
2620            r2 = LE32_TO_HOST(r2);
2621    
2622            page[addr0] = r1;
2623            page[addr1] = r2;
2624    
2625            cpu->n_translated_instrs ++;
2626            cpu->cd.mips.next_ic ++;
2627    }
2628    X(multi_sw_2_be)
2629    {
2630            uint32_t *page;
2631            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2632            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2633            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2634            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2635    
2636            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2637    
2638            /*  Fallback:  */
2639            if (cpu->delay_slot ||
2640                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2641                index0 != index1) {
2642                    /*  Normal safe sw:  */
2643                    mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2644                    return;
2645            }
2646    
2647            addr0 = (addr0 >> 2) & 0x3ff;
2648            addr1 = (addr1 >> 2) & 0x3ff;
2649    
2650            r1 = reg(ic[0].arg[0]);
2651            r2 = reg(ic[1].arg[0]);
2652    
2653            r1 = BE32_TO_HOST(r1);
2654            r2 = BE32_TO_HOST(r2);
2655    
2656            page[addr0] = r1;
2657            page[addr1] = r2;
2658    
2659            cpu->n_translated_instrs ++;
2660            cpu->cd.mips.next_ic ++;
2661    }
2662  X(multi_sw_3_le)  X(multi_sw_3_le)
2663  {  {
2664          uint32_t *page;          uint32_t *page;
# Line 2434  X(multi_sw_3_le) Line 2676  X(multi_sw_3_le)
2676              page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||              page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2677              (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {              (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2678                  /*  Normal safe sw:  */                  /*  Normal safe sw:  */
2679                  ic[1].f(cpu, ic);                  mips32_loadstore[8 + 2 * 2](cpu, ic);
2680                  return;                  return;
2681          }          }
2682    
# Line 2458  X(multi_sw_3_le) Line 2700  X(multi_sw_3_le)
2700          page[addr2] = r3;          page[addr2] = r3;
2701    
2702          cpu->n_translated_instrs += 2;          cpu->n_translated_instrs += 2;
2703          cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];          cpu->cd.mips.next_ic += 2;
2704  }  }
2705  X(multi_sw_3_be)  X(multi_sw_3_be)
2706  {  {
# Line 2477  X(multi_sw_3_be) Line 2719  X(multi_sw_3_be)
2719              page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||              page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2720              (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {              (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2721                  /*  Normal safe sw:  */                  /*  Normal safe sw:  */
2722                  ic[1].f(cpu, ic);                  mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2723                  return;                  return;
2724          }          }
2725    
# Line 2501  X(multi_sw_3_be) Line 2743  X(multi_sw_3_be)
2743          page[addr2] = r3;          page[addr2] = r3;
2744    
2745          cpu->n_translated_instrs += 2;          cpu->n_translated_instrs += 2;
2746          cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];          cpu->cd.mips.next_ic += 2;
2747    }
2748    X(multi_sw_4_le)
2749    {
2750            uint32_t *page;
2751            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2752            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2753            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2754            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2755            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2756            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2757                index2 = addr2 >> 12, index3 = addr3 >> 12;
2758    
2759            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2760    
2761            /*  Fallback:  */
2762            if (cpu->delay_slot ||
2763                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2764                (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2765                index0 != index2 || index0 != index3) {
2766                    /*  Normal safe sw:  */
2767                    mips32_loadstore[8 + 2 * 2](cpu, ic);
2768                    return;
2769            }
2770    
2771            addr0 = (addr0 >> 2) & 0x3ff;
2772            addr1 = (addr1 >> 2) & 0x3ff;
2773            addr2 = (addr2 >> 2) & 0x3ff;
2774            addr3 = (addr3 >> 2) & 0x3ff;
2775    
2776            r1 = reg(ic[0].arg[0]);
2777            r2 = reg(ic[1].arg[0]);
2778            r3 = reg(ic[2].arg[0]);
2779            r4 = reg(ic[3].arg[0]);
2780    
2781            r1 = LE32_TO_HOST(r1);
2782            r2 = LE32_TO_HOST(r2);
2783            r3 = LE32_TO_HOST(r3);
2784            r4 = LE32_TO_HOST(r4);
2785    
2786            page[addr0] = r1;
2787            page[addr1] = r2;
2788            page[addr2] = r3;
2789            page[addr3] = r4;
2790    
2791            cpu->n_translated_instrs += 3;
2792            cpu->cd.mips.next_ic += 3;
2793    }
2794    X(multi_sw_4_be)
2795    {
2796            uint32_t *page;
2797            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2798            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2799            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2800            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2801            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2802            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2803                index2 = addr2 >> 12, index3 = addr3 >> 12;
2804    
2805            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2806    
2807            /*  Fallback:  */
2808            if (cpu->delay_slot ||
2809                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2810                (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2811                index0 != index2 || index0 != index3) {
2812                    /*  Normal safe sw:  */
2813                    mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2814                    return;
2815            }
2816    
2817            addr0 = (addr0 >> 2) & 0x3ff;
2818            addr1 = (addr1 >> 2) & 0x3ff;
2819            addr2 = (addr2 >> 2) & 0x3ff;
2820            addr3 = (addr3 >> 2) & 0x3ff;
2821    
2822            r1 = reg(ic[0].arg[0]);
2823            r2 = reg(ic[1].arg[0]);
2824            r3 = reg(ic[2].arg[0]);
2825            r4 = reg(ic[3].arg[0]);
2826    
2827            r1 = BE32_TO_HOST(r1);
2828            r2 = BE32_TO_HOST(r2);
2829            r3 = BE32_TO_HOST(r3);
2830            r4 = BE32_TO_HOST(r4);
2831    
2832            page[addr0] = r1;
2833            page[addr1] = r2;
2834            page[addr2] = r3;
2835            page[addr3] = r4;
2836    
2837            cpu->n_translated_instrs += 3;
2838            cpu->cd.mips.next_ic += 3;
2839    }
2840    #endif
2841    
2842    
2843    #ifdef MODE32
2844    /*
2845     *  multi_lw_2, _3, _4:
2846     *
2847     *      lw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2848     */
2849    X(multi_lw_2_le)
2850    {
2851            uint32_t *page;
2852            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2853            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2854            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2855            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2856    
2857            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2858    
2859            /*  Fallback:  */
2860            if (cpu->delay_slot ||
2861                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2862                index0 != index1) {
2863                    /*  Normal safe lw:  */
2864                    mips32_loadstore[2 * 2 + 1](cpu, ic);
2865                    return;
2866            }
2867    
2868            addr0 = (addr0 >> 2) & 0x3ff;
2869            addr1 = (addr1 >> 2) & 0x3ff;
2870    
2871            r1 = page[addr0];
2872            r2 = page[addr1];
2873    
2874            r1 = LE32_TO_HOST(r1);
2875            r2 = LE32_TO_HOST(r2);
2876    
2877            reg(ic[0].arg[0]) = r1;
2878            reg(ic[1].arg[0]) = r2;
2879    
2880            cpu->n_translated_instrs ++;
2881            cpu->cd.mips.next_ic ++;
2882    }
2883    X(multi_lw_2_be)
2884    {
2885            uint32_t *page;
2886            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2887            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2888            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2889            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2890    
2891            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2892    
2893            /*  Fallback:  */
2894            if (cpu->delay_slot ||
2895                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2896                index0 != index1) {
2897                    /*  Normal safe lw:  */
2898                    mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2899                    return;
2900            }
2901    
2902            addr0 = (addr0 >> 2) & 0x3ff;
2903            addr1 = (addr1 >> 2) & 0x3ff;
2904    
2905            r1 = page[addr0];
2906            r2 = page[addr1];
2907    
2908            r1 = BE32_TO_HOST(r1);
2909            r2 = BE32_TO_HOST(r2);
2910    
2911            reg(ic[0].arg[0]) = r1;
2912            reg(ic[1].arg[0]) = r2;
2913    
2914            cpu->n_translated_instrs ++;
2915            cpu->cd.mips.next_ic ++;
2916    }
2917    X(multi_lw_3_le)
2918    {
2919            uint32_t *page;
2920            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2921            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2922            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2923            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2924            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2925                index2 = addr2 >> 12;
2926    
2927            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2928    
2929            /*  Fallback:  */
2930            if (cpu->delay_slot ||
2931                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2932                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2933                    /*  Normal safe lw:  */
2934                    mips32_loadstore[2 * 2 + 1](cpu, ic);
2935                    return;
2936            }
2937    
2938            addr0 = (addr0 >> 2) & 0x3ff;
2939            addr1 = (addr1 >> 2) & 0x3ff;
2940            addr2 = (addr2 >> 2) & 0x3ff;
2941    
2942            /*  printf("addr0=%x 1=%x 2=%x\n",
2943                (int)addr0, (int)addr1, (int)addr2);  */
2944    
2945            r1 = page[addr0];
2946            r2 = page[addr1];
2947            r3 = page[addr2];
2948    
2949            r1 = LE32_TO_HOST(r1);
2950            r2 = LE32_TO_HOST(r2);
2951            r3 = LE32_TO_HOST(r3);
2952    
2953            reg(ic[0].arg[0]) = r1;
2954            reg(ic[1].arg[0]) = r2;
2955            reg(ic[2].arg[0]) = r3;
2956    
2957            cpu->n_translated_instrs += 2;
2958            cpu->cd.mips.next_ic += 2;
2959    }
2960    X(multi_lw_3_be)
2961    {
2962            uint32_t *page;
2963            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2964            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2965            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2966            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2967            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2968                index2 = addr2 >> 12;
2969    
2970            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2971    
2972            /*  Fallback:  */
2973            if (cpu->delay_slot ||
2974                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2975                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2976                    /*  Normal safe lw:  */
2977                    mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2978                    return;
2979            }
2980    
2981            addr0 = (addr0 >> 2) & 0x3ff;
2982            addr1 = (addr1 >> 2) & 0x3ff;
2983            addr2 = (addr2 >> 2) & 0x3ff;
2984    
2985            /*  printf("addr0=%x 1=%x 2=%x\n",
2986                (int)addr0, (int)addr1, (int)addr2);  */
2987    
2988            r1 = page[addr0];
2989            r2 = page[addr1];
2990            r3 = page[addr2];
2991    
2992            r1 = BE32_TO_HOST(r1);
2993            r2 = BE32_TO_HOST(r2);
2994            r3 = BE32_TO_HOST(r3);
2995    
2996            reg(ic[0].arg[0]) = r1;
2997            reg(ic[1].arg[0]) = r2;
2998            reg(ic[2].arg[0]) = r3;
2999    
3000            cpu->n_translated_instrs += 2;
3001            cpu->cd.mips.next_ic += 2;
3002    }
3003    X(multi_lw_4_le)
3004    {
3005            uint32_t *page;
3006            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
3007            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
3008            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
3009            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
3010            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
3011            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
3012                index2 = addr2 >> 12, index3 = addr3 >> 12;
3013    
3014            page = (uint32_t *) cpu->cd.mips.host_load[index0];
3015    
3016            /*  Fallback:  */
3017            if (cpu->delay_slot ||
3018                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
3019                (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
3020                index0 != index1 || index0 != index2 || index0 != index3) {
3021                    /*  Normal safe lw:  */
3022                    mips32_loadstore[2 * 2 + 1](cpu, ic);
3023                    return;
3024            }
3025    
3026            addr0 = (addr0 >> 2) & 0x3ff;
3027            addr1 = (addr1 >> 2) & 0x3ff;
3028            addr2 = (addr2 >> 2) & 0x3ff;
3029            addr3 = (addr3 >> 2) & 0x3ff;
3030    
3031            r1 = page[addr0];
3032            r2 = page[addr1];
3033            r3 = page[addr2];
3034            r4 = page[addr3];
3035    
3036            r1 = LE32_TO_HOST(r1);
3037            r2 = LE32_TO_HOST(r2);
3038            r3 = LE32_TO_HOST(r3);
3039            r4 = LE32_TO_HOST(r4);
3040    
3041            reg(ic[0].arg[0]) = r1;
3042            reg(ic[1].arg[0]) = r2;
3043            reg(ic[2].arg[0]) = r3;
3044            reg(ic[3].arg[0]) = r4;
3045    
3046            cpu->n_translated_instrs += 3;
3047            cpu->cd.mips.next_ic += 3;
3048    }
3049    X(multi_lw_4_be)
3050    {
3051            uint32_t *page;
3052            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
3053            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
3054            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
3055            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
3056            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
3057            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
3058                index2 = addr2 >> 12, index3 = addr3 >> 12;
3059    
3060            page = (uint32_t *) cpu->cd.mips.host_load[index0];
3061    
3062            /*  Fallback:  */
3063            if (cpu->delay_slot ||
3064                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
3065                (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
3066                index0 != index1 || index0 != index2 || index0 != index3) {
3067                    /*  Normal safe lw:  */
3068                    mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
3069                    return;
3070            }
3071    
3072            addr0 = (addr0 >> 2) & 0x3ff;
3073            addr1 = (addr1 >> 2) & 0x3ff;
3074            addr2 = (addr2 >> 2) & 0x3ff;
3075            addr3 = (addr3 >> 2) & 0x3ff;
3076    
3077            r1 = page[addr0];
3078            r2 = page[addr1];
3079            r3 = page[addr2];
3080            r4 = page[addr3];
3081    
3082            r1 = BE32_TO_HOST(r1);
3083            r2 = BE32_TO_HOST(r2);
3084            r3 = BE32_TO_HOST(r3);
3085            r4 = BE32_TO_HOST(r4);
3086    
3087            reg(ic[0].arg[0]) = r1;
3088            reg(ic[1].arg[0]) = r2;
3089            reg(ic[2].arg[0]) = r3;
3090            reg(ic[3].arg[0]) = r4;
3091    
3092            cpu->n_translated_instrs += 3;
3093            cpu->cd.mips.next_ic += 3;
3094    }
3095    #endif
3096    
3097    
3098    /*
3099     *  multi_addu_3:
3100     */
3101    X(multi_addu_3)
3102    {
3103            /*  Fallback:  */
3104            if (cpu->delay_slot) {
3105                    instr(addu)(cpu, ic);
3106                    return;
3107            }
3108    
3109            reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
3110            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
3111            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
3112            cpu->n_translated_instrs += 2;
3113            cpu->cd.mips.next_ic += 2;
3114  }  }
3115    
3116    
# Line 2539  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 2592  X(netbsd_strlen) Line 3268  X(netbsd_strlen)
3268    
3269    
3270  /*  /*
3271   *  lui_32bit:   *  addiu_bne_samepage_addiu:
  *  
  *  Combination of lui and addiu.  
  *  Note: All 32 bits of arg[2] of the lui instr_call are used.  
3272   */   */
3273  X(lui_32bit)  X(addiu_bne_samepage_addiu)
3274  {  {
3275          reg(ic[0].arg[0]) = (int32_t) ic[0].arg[2];          MODE_uint_t rs, rt;
3276    
3277            if (cpu->delay_slot) {
3278                    instr(addiu)(cpu, ic);
3279                    return;
3280            }
3281    
3282            cpu->n_translated_instrs += 2;
3283            reg(ic[0].arg[1]) = (int32_t)
3284                ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
3285            rs = reg(ic[1].arg[0]);
3286            rt = reg(ic[1].arg[1]);
3287            reg(ic[2].arg[1]) = (int32_t)
3288                ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
3289            if (rs != rt)
3290                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
3291            else
3292                    cpu->cd.mips.next_ic += 2;
3293    }
3294    
3295    
3296    /*
3297     *  xor_andi_sll:
3298     */
3299    X(xor_andi_sll)
3300    {
3301            /*  Fallback:  */
3302            if (cpu->delay_slot) {
3303                    instr(xor)(cpu, ic);
3304                    return;
3305            }
3306    
3307            reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
3308            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
3309            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
3310    
3311            cpu->n_translated_instrs += 2;
3312            cpu->cd.mips.next_ic += 2;
3313    }
3314    
3315    
3316    /*
3317     *  andi_sll:
3318     */
3319    X(andi_sll)
3320    {
3321            /*  Fallback:  */
3322            if (cpu->delay_slot) {
3323                    instr(andi)(cpu, ic);
3324                    return;
3325            }
3326    
3327            reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
3328            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
3329    
3330            cpu->n_translated_instrs ++;
3331            cpu->cd.mips.next_ic ++;
3332    }
3333    
3334    
3335    /*
3336     *  lui_ori:
3337     */
3338    X(lui_ori)
3339    {
3340            /*  Fallback:  */
3341            if (cpu->delay_slot) {
3342                    instr(set)(cpu, ic);
3343                    return;
3344            }
3345    
3346            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3347            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
3348    
3349            cpu->n_translated_instrs ++;
3350            cpu->cd.mips.next_ic ++;
3351    }
3352    
3353    
3354    /*
3355     *  lui_addiu:
3356     */
3357    X(lui_addiu)
3358    {
3359            /*  Fallback:  */
3360            if (cpu->delay_slot) {
3361                    instr(set)(cpu, ic);
3362                    return;
3363            }
3364    
3365            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3366            reg(ic[1].arg[1]) = (int32_t)
3367                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
3368    
3369          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
3370          cpu->cd.mips.next_ic ++;          cpu->cd.mips.next_ic ++;
3371  }  }
# Line 2739  void COMBINE(sw_loop)(struct cpu *cpu, s Line 3505  void COMBINE(sw_loop)(struct cpu *cpu, s
3505              ic[0].arg[0] != ic[0].arg[1] &&              ic[0].arg[0] != ic[0].arg[1] &&
3506              ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {              ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3507                  ic[-2].f = instr(sw_loop);                  ic[-2].f = instr(sw_loop);
                 combined;  
3508          }          }
3509  }  }
3510    
3511    
3512    /*  Only for 32-bit virtual address translation so far.  */
3513    #ifdef MODE32
3514  /*  /*
3515   *  Combine:  Multiple SW in a row using the same base register   *  Combine:  Multiple SW in a row using the same base register
3516   *   *
# Line 2758  void COMBINE(multi_sw)(struct cpu *cpu, Line 3525  void COMBINE(multi_sw)(struct cpu *cpu,
3525          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3526              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3527    
3528          /*  Only for 32-bit virtual address translation so far.  */          if (n_back < 3)
         if (!cpu->is_32bit)  
3529                  return;                  return;
3530    
3531          if (n_back < 4)          /*  Convert a multi_sw_3 to a multi_sw_4:  */
3532                  return;          if ((ic[-3].f == instr(multi_sw_3_be) ||
3533                ic[-3].f == instr(multi_sw_3_le)) &&
3534                ic[-3].arg[1] == ic[0].arg[1]) {
3535                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3536                            ic[-3].f = instr(multi_sw_4_le);
3537                    else
3538                            ic[-3].f = instr(multi_sw_4_be);
3539            }
3540    
3541          /*  Avoid "overlapping" instruction combinations:  */          /*  Convert a multi_sw_2 to a multi_sw_3:  */
3542          if (ic[-4].f == instr(multi_sw_3_be)||ic[-3].f == instr(multi_sw_3_be)||          if ((ic[-2].f == instr(multi_sw_2_be) ||
3543              ic[-4].f == instr(multi_sw_3_le)||ic[-3].f == instr(multi_sw_3_le))              ic[-2].f == instr(multi_sw_2_le)) &&
3544                ic[-2].arg[1] == ic[0].arg[1]) {
3545                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3546                            ic[-2].f = instr(multi_sw_3_le);
3547                    else
3548                            ic[-2].f = instr(multi_sw_3_be);
3549            }
3550    
3551            if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3552                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3553                            ic[-1].f = instr(multi_sw_2_le);
3554                    else
3555                            ic[-1].f = instr(multi_sw_2_be);
3556            }
3557    }
3558    #endif
3559    
3560    
3561    /*  Only for 32-bit virtual address translation so far.  */
3562    #ifdef MODE32
3563    /*
3564     *  Combine:  Multiple LW in a row using the same base register
3565     *
3566     *      lw      r?,???(rX)
3567     *      lw      r?,???(rX)
3568     *      lw      r?,???(rX)
3569     *      ...
3570     */
3571    void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3572            int low_addr)
3573    {
3574            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3575                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3576    
3577            if (n_back < 3)
3578                  return;                  return;
3579    
3580          if (ic[-2].f == ic[0].f && ic[-1].f == ic[0].f &&          /*  Convert a multi_lw_3 to a multi_lw_4:  */
3581            if ((ic[-3].f == instr(multi_lw_3_be) ||
3582                ic[-3].f == instr(multi_lw_3_le)) &&
3583                ic[-3].arg[1] == ic[0].arg[1] &&
3584                ic[-1].arg[0] != ic[0].arg[1]) {
3585                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3586                            ic[-3].f = instr(multi_lw_4_le);
3587                    else
3588                            ic[-3].f = instr(multi_lw_4_be);
3589            }
3590    
3591            /*  Convert a multi_lw_2 to a multi_lw_3:  */
3592            if ((ic[-2].f == instr(multi_lw_2_be) ||
3593                ic[-2].f == instr(multi_lw_2_le)) &&
3594              ic[-2].arg[1] == ic[0].arg[1] &&              ic[-2].arg[1] == ic[0].arg[1] &&
3595              ic[-1].arg[1] == ic[0].arg[1]) {              ic[-1].arg[0] != ic[0].arg[1]) {
3596                  if (cpu->byte_order == EMUL_LITTLE_ENDIAN)                  if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3597                          ic[-2].f = instr(multi_sw_3_le);                          ic[-2].f = instr(multi_lw_3_le);
3598                  else                  else
3599                          ic[-2].f = instr(multi_sw_3_be);                          ic[-2].f = instr(multi_lw_3_be);
3600                  combined;          }
3601    
3602            /*  Note: Loads to the base register are not allowed in slot -1.  */
3603            if (ic[-1].f == ic[0].f &&
3604                ic[-1].arg[1] == ic[0].arg[1] &&
3605                ic[-1].arg[0] != ic[0].arg[1]) {
3606                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3607                            ic[-1].f = instr(multi_lw_2_le);
3608                    else
3609                            ic[-1].f = instr(multi_lw_2_be);
3610          }          }
3611  }  }
3612    #endif
3613    
3614    
3615  /*  /*
# Line 2815  void COMBINE(netbsd_r3k_cache_inv)(struc Line 3645  void COMBINE(netbsd_r3k_cache_inv)(struc
3645              ic[-3].arg[1] == ic[-5].arg[0] &&              ic[-3].arg[1] == ic[-5].arg[0] &&
3646              ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {              ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3647                  ic[-8].f = instr(netbsd_r3k_picache_do_inv);                  ic[-8].f = instr(netbsd_r3k_picache_do_inv);
                 combined;  
3648          }          }
3649  }  }
3650    
# Line 2825  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 2844  void COMBINE(nop)(struct cpu *cpu, struc Line 3707  void COMBINE(nop)(struct cpu *cpu, struc
3707              ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&              ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3708              ic[-1].f == instr(bne_samepage)) {              ic[-1].f == instr(bne_samepage)) {
3709                  ic[-3].f = instr(netbsd_strlen);                  ic[-3].f = instr(netbsd_strlen);
                 combined;  
3710                  return;                  return;
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);
                 combined;  
3716                  return;                  return;
3717          }          }
3718    
3719          if (ic[-1].f == instr(beq_samepage)) {          if (ic[-1].f == instr(beq_samepage)) {
3720                  ic[-1].f = instr(beq_samepage_nop);                  ic[-1].f = instr(beq_samepage_nop);
                 combined;  
3721                  return;                  return;
3722          }          }
3723    
# Line 2871  void COMBINE(nop)(struct cpu *cpu, struc Line 3728  void COMBINE(nop)(struct cpu *cpu, struc
3728  /*  /*
3729   *  Combine:   *  Combine:
3730   *   *
3731     *      xor + andi + sll
3732     *      andi + sll
3733     */
3734    void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3735    {
3736            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3737                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3738    
3739            if (n_back < 2)
3740                    return;
3741    
3742            if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3743                    ic[-2].f = instr(xor_andi_sll);
3744                    return;
3745            }
3746    
3747            if (ic[-1].f == instr(andi)) {
3748                    ic[-1].f = instr(andi_sll);
3749                    return;
3750            }
3751    }
3752    
3753    
3754    /*
3755     *  lui + ori
3756     */
3757    void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3758    {
3759            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3760                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3761    
3762            if (n_back < 1)
3763                    return;
3764    
3765            if (ic[-1].f == instr(set)) {
3766                    ic[-1].f = instr(lui_ori);
3767                    return;
3768            }
3769    }
3770    
3771    
3772    /*
3773     *  addu + addu + addu
3774     */
3775    void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3776    {
3777            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3778                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3779    
3780            if (n_back < 4)
3781                    return;
3782    
3783            /*  Avoid "overlapping" instruction combinations:  */
3784            if (ic[-4].f == instr(multi_addu_3) ||
3785                ic[-3].f == instr(multi_addu_3))
3786                    return;
3787    
3788            if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3789                    ic[-2].f = instr(multi_addu_3);
3790                    return;
3791            }
3792    }
3793    
3794    
3795    /*
3796     *  Combine:
3797     *
3798   *      [Conditional] branch, followed by addiu.   *      [Conditional] branch, followed by addiu.
  *      lui + addiu.  
3799   */   */
3800  void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)  void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3801  {  {
3802          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3803              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3804    
3805          if (n_back < 1)          if (n_back < 2)
3806                  return;                  return;
3807    
3808          if (ic[-1].f == instr(set) && ic[-1].arg[0] == ic[0].arg[0] &&          if (ic[-2].f == instr(addiu) &&
3809              ic[0].arg[0] == ic[0].arg[1]) {              ic[-1].f == instr(bne_samepage)) {
3810                  ic[-1].f = instr(lui_32bit);                  ic[-2].f = instr(addiu_bne_samepage_addiu);
3811                  ic[-1].arg[2] = (int32_t) (ic[-1].arg[1] + ic[0].arg[2]);                  return;
3812                  combined;          }
3813    
3814            if (ic[-1].f == instr(set)) {
3815                    ic[-1].f = instr(lui_addiu);
3816                  return;                  return;
3817          }          }
3818    
3819          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
3820                  ic[-1].f = instr(b_samepage_addiu);                  ic[-1].f = instr(b_samepage_addiu);
                 combined;  
3821                  return;                  return;
3822          }          }
3823    
3824          if (ic[-1].f == instr(beq_samepage)) {          if (ic[-1].f == instr(beq_samepage)) {
3825                  ic[-1].f = instr(beq_samepage_addiu);                  ic[-1].f = instr(beq_samepage_addiu);
                 combined;  
3826                  return;                  return;
3827          }          }
3828    
3829          if (ic[-1].f == instr(bne_samepage)) {          if (ic[-1].f == instr(bne_samepage)) {
3830                  ic[-1].f = instr(bne_samepage_addiu);                  ic[-1].f = instr(bne_samepage_addiu);
                 combined;  
3831                  return;                  return;
3832          }          }
3833    
3834          if (ic[-1].f == instr(jr_ra)) {          if (ic[-1].f == instr(jr_ra)) {
3835                  ic[-1].f = instr(jr_ra_addiu);                  ic[-1].f = instr(jr_ra_addiu);
                 combined;  
3836                  return;                  return;
3837          }          }
3838    
# Line 2932  void COMBINE(b_daddiu)(struct cpu *cpu, Line 3854  void COMBINE(b_daddiu)(struct cpu *cpu,
3854    
3855          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
3856                  ic[-1].f = instr(b_samepage_daddiu);                  ic[-1].f = instr(b_samepage_daddiu);
                 combined;  
3857          }          }
3858    
3859          /*  TODO: other branches that are followed by daddiu should be here  */          /*  TODO: other branches that are followed by daddiu should be here  */
# Line 2956  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 3037  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 3089  X(to_be_translated) Line 4011  X(to_be_translated)
4011                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4012                          if (rd == MIPS_GPR_ZERO)                          if (rd == MIPS_GPR_ZERO)
4013                                  ic->f = instr(nop);                                  ic->f = instr(nop);
4014                            if (ic->f == instr(sll))
4015                                    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 3220  X(to_be_translated) Line 4161  X(to_be_translated)
4161                          default:if (rd == MIPS_GPR_ZERO)                          default:if (rd == MIPS_GPR_ZERO)
4162                                          ic->f = instr(nop);                                          ic->f = instr(nop);
4163                          }                          }
4164    
4165                            if (ic->f == instr(addu))
4166                                    cpu->cd.mips.combination_check = COMBINE(addu);
4167                          break;                          break;
4168    
4169                  case SPECIAL_JR:                  case SPECIAL_JR:
# Line 3263  X(to_be_translated) Line 4207  X(to_be_translated)
4207                          break;                          break;
4208    
4209                  case SPECIAL_BREAK:                  case SPECIAL_BREAK:
4210                          ic->f = instr(break);                          if (((iword >> 6) & 0xfffff) == 0x30378) {
4211                                    /*  "Magic trap" for REBOOT:  */
4212                                    ic->f = instr(reboot);
4213                            } else {
4214                                    ic->f = instr(break);
4215                            }
4216                          break;                          break;
4217    
4218                  case SPECIAL_SYNC:                  case SPECIAL_SYNC:
# Line 3390  X(to_be_translated) Line 4339  X(to_be_translated)
4339                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
4340                          ic->f = instr(nop);                          ic->f = instr(nop);
4341    
4342                    if (ic->f == instr(ori))
4343                            cpu->cd.mips.combination_check = COMBINE(ori);
4344                  if (ic->f == instr(addiu))                  if (ic->f == instr(addiu))
4345                          cpu->cd.mips.combination_check = COMBINE(addiu);                          cpu->cd.mips.combination_check = COMBINE(addiu);
4346                  if (ic->f == instr(daddiu))                  if (ic->f == instr(daddiu))
# Line 3455  X(to_be_translated) Line 4406  X(to_be_translated)
4406                          case COP0_DERET:                          case COP0_DERET:
4407                                  ic->f = instr(deret);                                  ic->f = instr(deret);
4408                                  break;                                  break;
4409                          case COP0_IDLE:                          case COP0_WAIT:
4410                                    ic->f = instr(wait);
4411                                    if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
4412                                        cpu->cd.mips.cpu_type.isa_level < 32) {
4413                                            static int warned = 0;
4414                                            ic->f = instr(reserved);
4415                                            if (!warned) {
4416                                                    fatal("{ WARNING: Attempt to "
4417                                                        "execute the WAIT instruct"
4418                                                        "ion, but the emulated CPU "
4419                                                        "is neither RM52xx, nor "
4420                                                        "MIPS32/64! }\n");
4421                                                    warned = 1;
4422                                            }
4423                                    }
4424                                    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 3497  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 3830  X(to_be_translated) Line 4819  X(to_be_translated)
4819                  if (!store && rt == MIPS_GPR_ZERO)                  if (!store && rt == MIPS_GPR_ZERO)
4820                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4821    
4822                  /*  Check for multiple stores in a row using the same                  /*  Check for multiple loads or stores in a row using the same
4823                      base register:  */                      base register:  */
4824                  if (main_opcode == HI6_SW && rs == MIPS_GPR_SP)  #ifdef MODE32
4825                    if (main_opcode == HI6_LW)
4826                            cpu->cd.mips.combination_check = COMBINE(multi_lw);
4827                    if (main_opcode == HI6_SW)
4828                          cpu->cd.mips.combination_check = COMBINE(multi_sw);                          cpu->cd.mips.combination_check = COMBINE(multi_sw);
4829    #endif
4830                  break;                  break;
4831    
4832          case HI6_LL:          case HI6_LL:
# Line 3967  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 4007  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.28  
changed lines
  Added in v.32

  ViewVC Help
Powered by ViewVC 1.1.26