/[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 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_mips_instr.c,v 1.104 2006/08/14 17:45:47 debug Exp $   *  $Id: cpu_mips_instr.c,v 1.133 2007/06/13 02:08:03 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     *  ins: Insert bitfield.
1153     *
1154     *  arg[0] = pointer to rt
1155     *  arg[1] = pointer to rs
1156     *  arg[2] = (msb << 5) + lsb
1157     */
1158    X(ins)
1159    {
1160            int msb = ic->arg[2] >> 5, pos = ic->arg[2] & 0x1f;
1161            int size = msb + 1 - pos;
1162            uint32_t rt = reg(ic->arg[0]);
1163            uint32_t rs = reg(ic->arg[1]);
1164            uint32_t mask = (-1) << pos;
1165    
1166            mask <<= (32 - pos - size);
1167            mask >>= (32 - pos - size);
1168    
1169            reg(ic->arg[0]) = (int32_t) ((rt & ~mask) | ((rs << pos) & mask));
1170    }
1171    
1172    
1173    /*
1174     *  ext:  Extract bitfield.
1175     *
1176     *  arg[0] = pointer to rt
1177     *  arg[1] = pointer to rs
1178     *  arg[2] = (msbd << 5) + lsb
1179     */
1180    X(ext)
1181    {
1182            int msbd = ic->arg[2] >> 5, lsb = ic->arg[2] & 0x1f;
1183            int size = msbd + 1;
1184            uint32_t rs = reg(ic->arg[1]);
1185            uint32_t x = (rs << (32-lsb-size)) >> (32-lsb-size);
1186            reg(ic->arg[0]) = (int32_t) (x >> lsb);
1187    }
1188    
1189    
1190    /*
1191     *  dext:  Extract bitfield (64-bit).
1192     *
1193     *  arg[0] = pointer to rt
1194     *  arg[1] = pointer to rs
1195     *  arg[2] = (msbd << 6) + lsb
1196     */
1197    X(dext)
1198    {
1199            int msbd = ic->arg[2] >> 6, lsb = ic->arg[2] & 0x3f;
1200            int size = msbd + 1;
1201            uint64_t rs = reg(ic->arg[1]);
1202            uint64_t x = (rs << (uint64_t)(64-lsb-size)) >> (uint64_t)(64-lsb-size);
1203            reg(ic->arg[0]) = x >> lsb;
1204    }
1205    
1206    
1207    /*
1208     *  dsbh:  Doubleword swap bytes within half-word
1209     *  dshd:  Doubleword swap half-words within double-word
1210     *  wsbh:  Word swap bytes within half-word
1211     *  seb:   Sign-extend byte
1212     *  seh:   Sign-extend half-word
1213     *
1214     *  arg[0] = pointer to rt
1215     *  arg[1] = pointer to rd
1216     */
1217    X(dsbh)
1218    {
1219            uint64_t x = reg(ic->arg[0]);
1220            x = ((x & 0x00ff00ff00ff00ffULL) << 8)
1221              | ((x & 0xff00ff00ff00ff00ULL) >> 8);
1222            reg(ic->arg[1]) = x;
1223    }
1224    X(dshd)
1225    {
1226            uint64_t x = reg(ic->arg[0]);
1227            x = ((x & 0x000000000000ffffULL) << 48)
1228              | ((x & 0x00000000ffff0000ULL) << 16)
1229              | ((x & 0x0000ffff00000000ULL) >> 16)
1230              | ((x & 0xffff000000000000ULL) >> 48);
1231            reg(ic->arg[1]) = x;
1232    }
1233    X(wsbh)
1234    {
1235            uint32_t x = reg(ic->arg[0]);
1236            x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
1237            reg(ic->arg[1]) = (int32_t) x;
1238    }
1239    X(seb) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); }
1240    X(seh) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); }
1241    
1242    
1243    /*
1244   *  2-register + immediate:   *  2-register + immediate:
1245   *   *
1246   *  arg[0] = pointer to rs   *  arg[0] = pointer to rs
# Line 1096  X(div) Line 1266  X(div)
1266                  res = 0, rem = a;                  res = 0, rem = a;
1267          else          else
1268                  res = a / b, rem = a - b*res;                  res = a / b, rem = a - b*res;
1269          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1270          reg(&cpu->cd.mips.hi) = (int32_t)rem;          cpu->cd.mips.hi = (int32_t)rem;
1271  }  }
1272  X(divu)  X(divu)
1273  {  {
# Line 1107  X(divu) Line 1277  X(divu)
1277                  res = 0, rem = a;                  res = 0, rem = a;
1278          else          else
1279                  res = a / b, rem = a - b*res;                  res = a / b, rem = a - b*res;
1280          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1281          reg(&cpu->cd.mips.hi) = (int32_t)rem;          cpu->cd.mips.hi = (int32_t)rem;
1282  }  }
1283  X(ddiv)  X(ddiv)
1284  {  {
# Line 1119  X(ddiv) Line 1289  X(ddiv)
1289          else          else
1290                  res = a / b;                  res = a / b;
1291          rem = a - b*res;          rem = a - b*res;
1292          reg(&cpu->cd.mips.lo) = res;          cpu->cd.mips.lo = res;
1293          reg(&cpu->cd.mips.hi) = rem;          cpu->cd.mips.hi = rem;
1294  }  }
1295  X(ddivu)  X(ddivu)
1296  {  {
# Line 1131  X(ddivu) Line 1301  X(ddivu)
1301          else          else
1302                  res = a / b;                  res = a / b;
1303          rem = a - b*res;          rem = a - b*res;
1304          reg(&cpu->cd.mips.lo) = res;          cpu->cd.mips.lo = res;
1305          reg(&cpu->cd.mips.hi) = rem;          cpu->cd.mips.hi = rem;
1306  }  }
1307  X(mult)  X(mult)
1308  {  {
1309          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1310          int64_t res = (int64_t)a * (int64_t)b;          int64_t res = (int64_t)a * (int64_t)b;
1311          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1312          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1313  }  }
1314  X(mult_r5900)  X(mult_r5900)
1315  {  {
# Line 1147  X(mult_r5900) Line 1317  X(mult_r5900)
1317              hi, lo, and a third register  */              hi, lo, and a third register  */
1318          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1319          int64_t res = (int64_t)a * (int64_t)b;          int64_t res = (int64_t)a * (int64_t)b;
1320          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1321          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1322          reg(ic->arg[2]) = (int32_t)res;          reg(ic->arg[2]) = (int32_t)res;
1323  }  }
1324  X(multu)  X(multu)
1325  {  {
1326          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1327          uint64_t res = (uint64_t)a * (uint64_t)b;          uint64_t res = (uint64_t)a * (uint64_t)b;
1328          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1329          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1330  }  }
1331  X(multu_r5900)  X(multu_r5900)
1332  {  {
# Line 1164  X(multu_r5900) Line 1334  X(multu_r5900)
1334              hi, lo, and a third register  */              hi, lo, and a third register  */
1335          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1336          uint64_t res = (uint64_t)a * (uint64_t)b;          uint64_t res = (uint64_t)a * (uint64_t)b;
1337          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1338          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1339          reg(ic->arg[2]) = (int32_t)res;          reg(ic->arg[2]) = (int32_t)res;
1340  }  }
1341  X(dmult)  X(dmult)
# Line 1194  X(dmult) Line 1364  X(dmult)
1364                  hi ^= (int64_t) -1;                  hi ^= (int64_t) -1;
1365                  lo ^= (int64_t) -1;                  lo ^= (int64_t) -1;
1366          }          }
1367          reg(&cpu->cd.mips.lo) = lo;          cpu->cd.mips.lo = lo;
1368          reg(&cpu->cd.mips.hi) = hi;          cpu->cd.mips.hi = hi;
1369  }  }
1370  X(dmultu)  X(dmultu)
1371  {  {
# Line 1211  X(dmultu) Line 1381  X(dmultu)
1381                  }                  }
1382                  c = (c << 1) | (b >> 63); b <<= 1;                  c = (c << 1) | (b >> 63); b <<= 1;
1383          }          }
1384          reg(&cpu->cd.mips.lo) = lo;          cpu->cd.mips.lo = lo;
1385          reg(&cpu->cd.mips.hi) = hi;          cpu->cd.mips.hi = hi;
1386  }  }
1387  X(tge)  X(tge)
1388  {  {
# Line 1621  X(sltiu) Line 1791  X(sltiu)
1791    
1792  /*  /*
1793   *  set:  Set a register to an immediate (signed) 32-bit value.   *  set:  Set a register to an immediate (signed) 32-bit value.
1794     *        (This is the actual implementation of the lui instruction.)
1795   *   *
1796   *  arg[0] = pointer to the register   *  arg[0] = pointer to the register
1797   *  arg[1] = (int32_t) immediate value   *  arg[1] = (int32_t) immediate value
# Line 1659  X(mfc0) Line 1830  X(mfc0)
1830          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);
1831          reg(ic->arg[0]) = (int32_t)tmp;          reg(ic->arg[0]) = (int32_t)tmp;
1832  }  }
1833    X(mfc0_select0)
1834    {
1835            /*  Fast int32_t read, with no side effects:  */
1836            int rd = ic->arg[1] & 31;
1837    #if 0
1838            uint64_t tmp;
1839            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1840            cpu->pc |= ic->arg[2];
1841            /*  TODO: cause exception if necessary  */
1842    #endif
1843            reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->reg[rd];
1844    }
1845  X(mtc0)  X(mtc0)
1846  {  {
1847          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 1885  X(dmfc0)
1885          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1886              (uint64_t *)ic->arg[0], select);              (uint64_t *)ic->arg[0], select);
1887  }  }
1888    X(dmfc0_select0)
1889    {
1890            /*  Fast int64_t read, with no side effects:  */
1891            int rd = ic->arg[1] & 31;
1892    #if 0
1893            uint64_t tmp;
1894            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1895            cpu->pc |= ic->arg[2];
1896            /*  TODO: cause exception if necessary  */
1897    #endif
1898            reg(ic->arg[0]) = cpu->cd.mips.coproc[0]->reg[rd];
1899    }
1900  X(dmtc0)  X(dmtc0)
1901  {  {
1902          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 1918  X(dmtc0)
1918  X(cop1_bc)  X(cop1_bc)
1919  {  {
1920          MODE_int_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
1921          const int cpnr = 1;          int x, cc = ic->arg[0];
         int x, low_pc, cc = ic->arg[0];  
1922    
1923          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;  
         }  
1924    
1925          /*  Get the correct condition code bit:  */          /*  Get the correct condition code bit:  */
1926          if (cc == 0)          if (cc == 0)
# Line 1774  X(cop1_bc) Line 1960  X(cop1_bc)
1960   */   */
1961  X(cop1_slow)  X(cop1_slow)
1962  {  {
1963          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;  
         }  
1964    
1965          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);
1966  }  }
# Line 1811  X(break) Line 1987  X(break)
1987  }  }
1988  X(reboot)  X(reboot)
1989  {  {
1990            if (!cop0_availability_check(cpu, ic))
1991                    return;
1992    
1993          cpu->running = 0;          cpu->running = 0;
1994          debugger_n_steps_left_before_interaction = 0;          debugger_n_steps_left_before_interaction = 0;
1995          cpu->cd.mips.next_ic = &nothing_call;          cpu->cd.mips.next_ic = &nothing_call;
# Line 1873  X(promemul) Line 2052  X(promemul)
2052   */   */
2053  X(tlbw)  X(tlbw)
2054  {  {
2055            if (!cop0_availability_check(cpu, ic))
2056                    return;
2057    
2058          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2059          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
2060          coproc_tlbwri(cpu, ic->arg[0]);          coproc_tlbwri(cpu, ic->arg[0]);
# Line 1887  X(tlbw) Line 2069  X(tlbw)
2069   */   */
2070  X(tlbp)  X(tlbp)
2071  {  {
2072            if (!cop0_availability_check(cpu, ic))
2073                    return;
2074    
2075          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2076          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
2077          coproc_tlbpr(cpu, 0);          coproc_tlbpr(cpu, 0);
2078  }  }
2079  X(tlbr)  X(tlbr)
2080  {  {
2081            if (!cop0_availability_check(cpu, ic))
2082                    return;
2083    
2084          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2085          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
2086          coproc_tlbpr(cpu, 1);          coproc_tlbpr(cpu, 1);
# Line 1900  X(tlbr) Line 2088  X(tlbr)
2088    
2089    
2090  /*  /*
2091     *  ei_or_di:  MIPS32/64 rev 2, Enable or disable interrupts
2092     *
2093     *  arg[0] = ptr to rt
2094     *  arg[1] = non-zero to enable interrupts
2095     */
2096    X(ei_or_di)
2097    {
2098            reg(ic->arg[0]) = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2099            if (ic->arg[1])
2100                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= STATUS_IE;
2101            else
2102                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_IE;
2103    }
2104    
2105    
2106    /*
2107   *  rfe: Return from exception handler (R2000/R3000)   *  rfe: Return from exception handler (R2000/R3000)
2108   */   */
2109  X(rfe)  X(rfe)
2110  {  {
2111            if (!cop0_availability_check(cpu, ic))
2112                    return;
2113    
2114          /*  Just rotate the interrupt/user bits:  */          /*  Just rotate the interrupt/user bits:  */
2115          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2116              (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |              (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
# Line 1922  X(rfe) Line 2129  X(rfe)
2129   */   */
2130  X(eret)  X(eret)
2131  {  {
2132            if (!cop0_availability_check(cpu, ic))
2133                    return;
2134    
2135          if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {          if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2136                  cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];                  cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2137                  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 2152  X(eret)
2152   */   */
2153  X(deret)  X(deret)
2154  {  {
2155            if (!cop0_availability_check(cpu, ic))
2156                    return;
2157    
2158          /*          /*
2159           *  According to the MIPS64 manual, deret loads PC from the DEPC cop0           *  According to the MIPS64 manual, deret loads PC from the DEPC cop0
2160           *  register, and jumps there immediately. No delay slot.           *  register, and jumps there immediately. No delay slot.
# Line 1960  X(deret) Line 2173  X(deret)
2173    
2174    
2175  /*  /*
2176   *  wait: Wait for external interrupt.   *  idle:  Called from the implementation of wait, or netbsd_pmax_idle.
2177   */   */
2178  X(wait)  X(idle)
2179  {  {
2180          /*          /*
2181           *  If there is an interrupt, then just return. Otherwise           *  If there is an interrupt, then just return. Otherwise
# Line 1971  X(wait) Line 2184  X(wait)
2184          uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];          uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2185          uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];          uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
2186    
         /*  NOTE: STATUS_IE happens to match the enable bit also  
             on R2000/R3000, so this is ok.  */  
2187          if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {          if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2188                  if (status & (STATUS_EXL | STATUS_ERL))                  if (status & (STATUS_EXL | STATUS_ERL))
2189                          status &= ~STATUS_IE;                          status &= ~STATUS_IE;
2190          }          }
2191    
2192          /*  Ugly R5900 special case:  (TODO: move this?)  */          /*  Ugly R5900 special case:  (TODO: move this?)  */
2193          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&          if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
2194              !(status & R5900_STATUS_EIE))              !(status & R5900_STATUS_EIE))
# Line 1986  X(wait) Line 2198  X(wait)
2198    
2199          cpu->cd.mips.next_ic = ic;          cpu->cd.mips.next_ic = ic;
2200          cpu->is_halted = 1;          cpu->is_halted = 1;
2201            cpu->has_been_idling = 1;
2202    
2203          /*          /*
2204           *  There was no interrupt. Go to sleep.           *  There was no interrupt. Go to sleep.
# Line 1999  X(wait) Line 2212  X(wait)
2212          if (cpu->machine->ncpus == 1) {          if (cpu->machine->ncpus == 1) {
2213                  static int x = 0;                  static int x = 0;
2214                  if ((++x) == 600) {                  if ((++x) == 600) {
2215                          usleep(1);                          usleep(10);
2216                          x = 0;                          x = 0;
2217                  }                  }
2218                  cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;                  cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
# Line 2008  X(wait) Line 2221  X(wait)
2221    
2222    
2223  /*  /*
2224     *  wait: Wait for external interrupt.
2225     */
2226    X(wait)
2227    {
2228            if (!cop0_availability_check(cpu, ic))
2229                    return;
2230    
2231            instr(idle)(cpu, ic);
2232    }
2233    
2234    
2235    /*
2236   *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).   *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2237   *   *
2238   *  arg[0] = ptr to rt (destination register)   *  arg[0] = ptr to rt (destination register)
# Line 2244  X(scd) Line 2469  X(scd)
2469   */   */
2470  X(lwc1)  X(lwc1)
2471  {  {
2472          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;  
         }  
2473    
2474  #ifdef MODE32  #ifdef MODE32
2475          mips32_loadstore          mips32_loadstore
# Line 2270  X(lwc1) Line 2481  X(lwc1)
2481  }  }
2482  X(swc1)  X(swc1)
2483  {  {
2484          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;  
         }  
2485    
2486  #ifdef MODE32  #ifdef MODE32
2487          mips32_loadstore          mips32_loadstore
# Line 2296  X(swc1) Line 2493  X(swc1)
2493  }  }
2494  X(ldc1)  X(ldc1)
2495  {  {
         const int cpnr = 1;  
2496          int use_fp_pairs =          int use_fp_pairs =
2497              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2498          uint64_t fpr, *backup_ptr;          uint64_t fpr, *backup_ptr;
2499    
2500          /*  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;  
         }  
2501    
2502          backup_ptr = (uint64_t *) ic->arg[0];          backup_ptr = (uint64_t *) ic->arg[0];
2503          ic->arg[0] = (size_t) &fpr;          ic->arg[0] = (size_t) &fpr;
# Line 2337  X(ldc1) Line 2521  X(ldc1)
2521  }  }
2522  X(sdc1)  X(sdc1)
2523  {  {
         const int cpnr = 1;  
2524          int use_fp_pairs =          int use_fp_pairs =
2525              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2526          uint64_t fpr, *backup_ptr;          uint64_t fpr, *backup_ptr;
2527    
2528          /*  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;  
         }  
2529    
2530          backup_ptr = (uint64_t *) ic->arg[0];          backup_ptr = (uint64_t *) ic->arg[0];
2531          ic->arg[0] = (size_t) &fpr;          ic->arg[0] = (size_t) &fpr;
# Line 2405  X(sdr) { mips_unaligned_loadstore(cpu, i Line 2576  X(sdr) { mips_unaligned_loadstore(cpu, i
2576   */   */
2577  X(di_r5900)  X(di_r5900)
2578  {  {
2579            if (!cop0_availability_check(cpu, ic))
2580                    return;
2581    
2582          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2583  }  }
2584  X(ei_r5900)  X(ei_r5900)
2585  {  {
2586            if (!cop0_availability_check(cpu, ic))
2587                    return;
2588    
2589          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2590  }  }
2591    
# Line 2467  X(sw_loop) Line 2644  X(sw_loop)
2644    
2645    
2646  #ifdef MODE32  #ifdef MODE32
2647  /*  /*  multi_{l,s}w_2, _3, etc.  */
2648   *  multi_sw_2, _3, _4:  #include "tmp_mips_loadstore_multi.c"
  *  
  *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]  
  */  
 X(multi_sw_2_le)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_store[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             index0 != index1) {  
                 /*  Normal safe sw:  */  
                 mips32_loadstore[8 + 2 * 2](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
   
         r1 = reg(ic[0].arg[0]);  
         r2 = reg(ic[1].arg[0]);  
   
         r1 = LE32_TO_HOST(r1);  
         r2 = LE32_TO_HOST(r2);  
   
         page[addr0] = r1;  
         page[addr1] = r2;  
   
         cpu->n_translated_instrs ++;  
         cpu->cd.mips.next_ic ++;  
 }  
 X(multi_sw_2_be)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_store[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             index0 != index1) {  
                 /*  Normal safe sw:  */  
                 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
   
         r1 = reg(ic[0].arg[0]);  
         r2 = reg(ic[1].arg[0]);  
   
         r1 = BE32_TO_HOST(r1);  
         r2 = BE32_TO_HOST(r2);  
   
         page[addr0] = r1;  
         page[addr1] = r2;  
   
         cpu->n_translated_instrs ++;  
         cpu->cd.mips.next_ic ++;  
 }  
 X(multi_sw_3_le)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,  
             index2 = addr2 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_store[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {  
                 /*  Normal safe sw:  */  
                 mips32_loadstore[8 + 2 * 2](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
         addr2 = (addr2 >> 2) & 0x3ff;  
   
         /*  printf("addr0=%x 1=%x 2=%x\n",  
             (int)addr0, (int)addr1, (int)addr2);  */  
   
         r1 = reg(ic[0].arg[0]);  
         r2 = reg(ic[1].arg[0]);  
         r3 = reg(ic[2].arg[0]);  
   
         r1 = LE32_TO_HOST(r1);  
         r2 = LE32_TO_HOST(r2);  
         r3 = LE32_TO_HOST(r3);  
   
         page[addr0] = r1;  
         page[addr1] = r2;  
         page[addr2] = r3;  
   
         cpu->n_translated_instrs += 2;  
         cpu->cd.mips.next_ic += 2;  
 }  
 X(multi_sw_3_be)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,  
             index2 = addr2 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_store[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {  
                 /*  Normal safe sw:  */  
                 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
         addr2 = (addr2 >> 2) & 0x3ff;  
   
         /*  printf("addr0=%x 1=%x 2=%x\n",  
             (int)addr0, (int)addr1, (int)addr2);  */  
   
         r1 = reg(ic[0].arg[0]);  
         r2 = reg(ic[1].arg[0]);  
         r3 = reg(ic[2].arg[0]);  
   
         r1 = BE32_TO_HOST(r1);  
         r2 = BE32_TO_HOST(r2);  
         r3 = BE32_TO_HOST(r3);  
   
         page[addr0] = r1;  
         page[addr1] = r2;  
         page[addr2] = r3;  
   
         cpu->n_translated_instrs += 2;  
         cpu->cd.mips.next_ic += 2;  
 }  
 X(multi_sw_4_le)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];  
         MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,  
             index2 = addr2 >> 12, index3 = addr3 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_store[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||  
             index0 != index2 || index0 != index3) {  
                 /*  Normal safe sw:  */  
                 mips32_loadstore[8 + 2 * 2](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
         addr2 = (addr2 >> 2) & 0x3ff;  
         addr3 = (addr3 >> 2) & 0x3ff;  
   
         r1 = reg(ic[0].arg[0]);  
         r2 = reg(ic[1].arg[0]);  
         r3 = reg(ic[2].arg[0]);  
         r4 = reg(ic[3].arg[0]);  
   
         r1 = LE32_TO_HOST(r1);  
         r2 = LE32_TO_HOST(r2);  
         r3 = LE32_TO_HOST(r3);  
         r4 = LE32_TO_HOST(r4);  
   
         page[addr0] = r1;  
         page[addr1] = r2;  
         page[addr2] = r3;  
         page[addr3] = r4;  
   
         cpu->n_translated_instrs += 3;  
         cpu->cd.mips.next_ic += 3;  
 }  
 X(multi_sw_4_be)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];  
         MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,  
             index2 = addr2 >> 12, index3 = addr3 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_store[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||  
             index0 != index2 || index0 != index3) {  
                 /*  Normal safe sw:  */  
                 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
         addr2 = (addr2 >> 2) & 0x3ff;  
         addr3 = (addr3 >> 2) & 0x3ff;  
   
         r1 = reg(ic[0].arg[0]);  
         r2 = reg(ic[1].arg[0]);  
         r3 = reg(ic[2].arg[0]);  
         r4 = reg(ic[3].arg[0]);  
   
         r1 = BE32_TO_HOST(r1);  
         r2 = BE32_TO_HOST(r2);  
         r3 = BE32_TO_HOST(r3);  
         r4 = BE32_TO_HOST(r4);  
   
         page[addr0] = r1;  
         page[addr1] = r2;  
         page[addr2] = r3;  
         page[addr3] = r4;  
   
         cpu->n_translated_instrs += 3;  
         cpu->cd.mips.next_ic += 3;  
 }  
 #endif  
   
   
 #ifdef MODE32  
 /*  
  *  multi_lw_2, _3, _4:  
  *  
  *      lw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]  
  */  
 X(multi_lw_2_le)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_load[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             index0 != index1) {  
                 /*  Normal safe lw:  */  
                 mips32_loadstore[2 * 2 + 1](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
   
         r1 = page[addr0];  
         r2 = page[addr1];  
   
         r1 = LE32_TO_HOST(r1);  
         r2 = LE32_TO_HOST(r2);  
   
         reg(ic[0].arg[0]) = r1;  
         reg(ic[1].arg[0]) = r2;  
   
         cpu->n_translated_instrs ++;  
         cpu->cd.mips.next_ic ++;  
 }  
 X(multi_lw_2_be)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_load[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             index0 != index1) {  
                 /*  Normal safe lw:  */  
                 mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
   
         r1 = page[addr0];  
         r2 = page[addr1];  
   
         r1 = BE32_TO_HOST(r1);  
         r2 = BE32_TO_HOST(r2);  
   
         reg(ic[0].arg[0]) = r1;  
         reg(ic[1].arg[0]) = r2;  
   
         cpu->n_translated_instrs ++;  
         cpu->cd.mips.next_ic ++;  
 }  
 X(multi_lw_3_le)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,  
             index2 = addr2 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_load[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {  
                 /*  Normal safe lw:  */  
                 mips32_loadstore[2 * 2 + 1](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
         addr2 = (addr2 >> 2) & 0x3ff;  
   
         /*  printf("addr0=%x 1=%x 2=%x\n",  
             (int)addr0, (int)addr1, (int)addr2);  */  
   
         r1 = page[addr0];  
         r2 = page[addr1];  
         r3 = page[addr2];  
   
         r1 = LE32_TO_HOST(r1);  
         r2 = LE32_TO_HOST(r2);  
         r3 = LE32_TO_HOST(r3);  
   
         reg(ic[0].arg[0]) = r1;  
         reg(ic[1].arg[0]) = r2;  
         reg(ic[2].arg[0]) = r3;  
   
         cpu->n_translated_instrs += 2;  
         cpu->cd.mips.next_ic += 2;  
 }  
 X(multi_lw_3_be)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,  
             index2 = addr2 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_load[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {  
                 /*  Normal safe lw:  */  
                 mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
         addr2 = (addr2 >> 2) & 0x3ff;  
   
         /*  printf("addr0=%x 1=%x 2=%x\n",  
             (int)addr0, (int)addr1, (int)addr2);  */  
   
         r1 = page[addr0];  
         r2 = page[addr1];  
         r3 = page[addr2];  
   
         r1 = BE32_TO_HOST(r1);  
         r2 = BE32_TO_HOST(r2);  
         r3 = BE32_TO_HOST(r3);  
   
         reg(ic[0].arg[0]) = r1;  
         reg(ic[1].arg[0]) = r2;  
         reg(ic[2].arg[0]) = r3;  
   
         cpu->n_translated_instrs += 2;  
         cpu->cd.mips.next_ic += 2;  
 }  
 X(multi_lw_4_le)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];  
         MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,  
             index2 = addr2 >> 12, index3 = addr3 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_load[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             (addr2 & 3) != 0 || (addr3 & 3) != 0 ||  
             index0 != index1 || index0 != index2 || index0 != index3) {  
                 /*  Normal safe lw:  */  
                 mips32_loadstore[2 * 2 + 1](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
         addr2 = (addr2 >> 2) & 0x3ff;  
         addr3 = (addr3 >> 2) & 0x3ff;  
   
         r1 = page[addr0];  
         r2 = page[addr1];  
         r3 = page[addr2];  
         r4 = page[addr3];  
   
         r1 = LE32_TO_HOST(r1);  
         r2 = LE32_TO_HOST(r2);  
         r3 = LE32_TO_HOST(r3);  
         r4 = LE32_TO_HOST(r4);  
   
         reg(ic[0].arg[0]) = r1;  
         reg(ic[1].arg[0]) = r2;  
         reg(ic[2].arg[0]) = r3;  
         reg(ic[3].arg[0]) = r4;  
   
         cpu->n_translated_instrs += 3;  
         cpu->cd.mips.next_ic += 3;  
 }  
 X(multi_lw_4_be)  
 {  
         uint32_t *page;  
         MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;  
         MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];  
         MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];  
         MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];  
         MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];  
         uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,  
             index2 = addr2 >> 12, index3 = addr3 >> 12;  
   
         page = (uint32_t *) cpu->cd.mips.host_load[index0];  
   
         /*  Fallback:  */  
         if (cpu->delay_slot ||  
             page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||  
             (addr2 & 3) != 0 || (addr3 & 3) != 0 ||  
             index0 != index1 || index0 != index2 || index0 != index3) {  
                 /*  Normal safe lw:  */  
                 mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);  
                 return;  
         }  
   
         addr0 = (addr0 >> 2) & 0x3ff;  
         addr1 = (addr1 >> 2) & 0x3ff;  
         addr2 = (addr2 >> 2) & 0x3ff;  
         addr3 = (addr3 >> 2) & 0x3ff;  
   
         r1 = page[addr0];  
         r2 = page[addr1];  
         r3 = page[addr2];  
         r4 = page[addr3];  
   
         r1 = BE32_TO_HOST(r1);  
         r2 = BE32_TO_HOST(r2);  
         r3 = BE32_TO_HOST(r3);  
         r4 = BE32_TO_HOST(r4);  
   
         reg(ic[0].arg[0]) = r1;  
         reg(ic[1].arg[0]) = r2;  
         reg(ic[2].arg[0]) = r3;  
         reg(ic[3].arg[0]) = r4;  
   
         cpu->n_translated_instrs += 3;  
         cpu->cd.mips.next_ic += 3;  
 }  
2649  #endif  #endif
2650    
2651    
# Line 3029  X(netbsd_r3k_picache_do_inv) Line 2702  X(netbsd_r3k_picache_do_inv)
2702    
2703  #ifdef MODE32  #ifdef MODE32
2704  /*  /*
2705     *  netbsd_pmax_idle():
2706     *
2707     *  s:  lui     rX, hi
2708     *      lw      rY, lo(rX)
2709     *      nop
2710     *      beq     zr, rY, s
2711     *      nop
2712     */
2713    X(netbsd_pmax_idle)
2714    {
2715            uint32_t addr, pageindex, i;
2716            int32_t *page;
2717    
2718            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2719    
2720            addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
2721            pageindex = addr >> 12;
2722            i = (addr & 0xfff) >> 2;
2723            page = (int32_t *) cpu->cd.mips.host_load[pageindex];
2724    
2725            /*  Fallback:  */
2726            if (cpu->delay_slot || page == NULL || page[i] != 0)
2727                    return;
2728    
2729            instr(idle)(cpu, ic);
2730    }
2731    
2732    
2733    /*
2734     *  linux_pmax_idle():
2735     *
2736     *  s:  lui     rX, hi
2737     *      lw      rX, lo(rX)
2738     *      nop
2739     *      bne     zr, rX, ...
2740     *      nop
2741     *      lw      rX, ofs(gp)
2742     *      nop
2743     *      beq     zr, rX, s
2744     *      nop
2745     */
2746    X(linux_pmax_idle)
2747    {
2748            uint32_t addr, addr2, pageindex, pageindex2, i, i2;
2749            int32_t *page, *page2;
2750    
2751            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2752    
2753            addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
2754            pageindex = addr >> 12;
2755            i = (addr & 0xfff) >> 2;
2756            page = (int32_t *) cpu->cd.mips.host_load[pageindex];
2757    
2758            addr2 = reg(ic[5].arg[1]) + (int32_t)ic[5].arg[2];
2759            pageindex2 = addr2 >> 12;
2760            i2 = (addr2 & 0xfff) >> 2;
2761            page2 = (int32_t *) cpu->cd.mips.host_load[pageindex2];
2762    
2763            /*  Fallback:  */
2764            if (cpu->delay_slot || page == NULL || page[i] != 0 || page2[i2] != 0)
2765                    return;
2766    
2767            instr(idle)(cpu, ic);
2768    }
2769    
2770    
2771    /*
2772   *  netbsd_strlen():   *  netbsd_strlen():
2773   *   *
2774   *      lb      rV,0(rX)   *      lb      rV,0(rX)
# Line 3468  void COMBINE(netbsd_r3k_cache_inv)(struc Line 3208  void COMBINE(netbsd_r3k_cache_inv)(struc
3208   *   *
3209   *      NetBSD's strlen core.   *      NetBSD's strlen core.
3210   *      [Conditional] branch, followed by nop.   *      [Conditional] branch, followed by nop.
3211     *      NetBSD/pmax' idle loop (and possibly others as well).
3212     *      Linux/pmax' idle loop.
3213   */   */
3214  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)
3215  {  {
3216          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3217              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3218    
3219            if (n_back < 8)
3220                    return;
3221    
3222  #ifdef MODE32  #ifdef MODE32
3223          if (n_back < 3)          if (ic[-8].f == instr(set) &&
3224                ic[-7].f == mips32_loadstore[4 + 1] &&
3225                ic[-7].arg[0] == ic[-1].arg[0] &&
3226                ic[-7].arg[0] == ic[-3].arg[0] &&
3227                ic[-7].arg[0] == ic[-5].arg[0] &&
3228                ic[-7].arg[0] == ic[-7].arg[1] &&
3229                ic[-7].arg[0] == ic[-8].arg[0] &&
3230                ic[-6].f == instr(nop) &&
3231                ic[-5].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3232                ic[-5].f == instr(bne_samepage_nop) &&
3233                ic[-4].f == instr(nop) &&
3234                ic[-3].f == mips32_loadstore[4 + 1] &&
3235                ic[-2].f == instr(nop) &&
3236                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3237                ic[-1].arg[2] == (size_t) &ic[-8] &&
3238                ic[-1].f == instr(beq_samepage)) {
3239                    ic[-8].f = instr(linux_pmax_idle);
3240                  return;                  return;
3241            }
3242    
3243            if (ic[-4].f == instr(set) &&
3244                ic[-3].f == mips32_loadstore[4 + 1] &&
3245                ic[-3].arg[0] == ic[-1].arg[0] &&
3246                ic[-3].arg[1] == ic[-4].arg[0] &&
3247                ic[-2].f == instr(nop) &&
3248                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3249                ic[-1].arg[2] == (size_t) &ic[-4] &&
3250                ic[-1].f == instr(beq_samepage)) {
3251                    ic[-4].f = instr(netbsd_pmax_idle);
3252                    return;
3253            }
3254    
3255          if ((ic[-3].f == mips32_loadstore[1] ||          if ((ic[-3].f == mips32_loadstore[1] ||
3256              ic[-3].f == mips32_loadstore[16 + 1]) &&              ic[-3].f == mips32_loadstore[16 + 1]) &&
# Line 3491  void COMBINE(nop)(struct cpu *cpu, struc Line 3265  void COMBINE(nop)(struct cpu *cpu, struc
3265          }          }
3266  #endif  #endif
3267    
         if (n_back < 1)  
                 return;  
   
3268          if (ic[-1].f == instr(bne_samepage)) {          if (ic[-1].f == instr(bne_samepage)) {
3269                  ic[-1].f = instr(bne_samepage_nop);                  ic[-1].f = instr(bne_samepage_nop);
3270                  return;                  return;
# Line 3660  X(to_be_translated) Line 3431  X(to_be_translated)
3431          uint32_t iword, imm;          uint32_t iword, imm;
3432          unsigned char *page;          unsigned char *page;
3433          unsigned char ib[4];          unsigned char ib[4];
3434          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;          int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10;
3435          int in_crosspage_delayslot = 0;          int in_crosspage_delayslot = 0;
3436          void (*samepage_function)(struct cpu *, struct mips_instr_call *);          void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3437          int store, signedness, size;          int store, signedness, size;
# Line 3741  X(to_be_translated) Line 3512  X(to_be_translated)
3512          sa = (iword >>  6) & 31;          sa = (iword >>  6) & 31;
3513          imm = (int16_t)iword;          imm = (int16_t)iword;
3514          s6 = iword & 63;          s6 = iword & 63;
3515            s10 = (rs << 5) | sa;
3516    
3517          switch (main_opcode) {          switch (main_opcode) {
3518    
# Line 3795  X(to_be_translated) Line 3567  X(to_be_translated)
3567                                  ic->f = instr(nop);                                  ic->f = instr(nop);
3568                          if (ic->f == instr(sll))                          if (ic->f == instr(sll))
3569                                  cpu->cd.mips.combination_check = COMBINE(sll);                                  cpu->cd.mips.combination_check = COMBINE(sll);
3570                            if (ic->f == instr(nop))
3571                                    cpu->cd.mips.combination_check = COMBINE(nop);
3572    
3573                            /*  Special checks for MIPS32/64 revision 2 opcodes,
3574                                such as rotation instructions:  */
3575                            if (sa >= 0 && rs != 0x00) {
3576                                    switch (rs) {
3577                                    /*  TODO: [d]ror, etc.  */
3578                                    default:goto bad;
3579                                    }
3580                            }
3581                            if (sa < 0 && (s10 & 0x1f) != 0) {
3582                                    switch (s10 & 0x1f) {
3583                                    /*  TODO: [d]rorv, etc.  */
3584                                    default:goto bad;
3585                                    }
3586                            }
3587                          break;                          break;
3588    
3589                  case SPECIAL_ADD:                  case SPECIAL_ADD:
# Line 3918  X(to_be_translated) Line 3707  X(to_be_translated)
3707                                          }                                          }
3708                                  }                                  }
3709                                  if (rd != MIPS_GPR_ZERO) {                                  if (rd != MIPS_GPR_ZERO) {
3710                                          fatal("TODO: rd NON-zero\n");                                          if (!cpu->translation_readahead)
3711                                                    fatal("TODO: rd NON-zero\n");
3712                                          goto bad;                                          goto bad;
3713                                  }                                  }
3714                                  /*  These instructions don't use rd.  */                                  /*  These instructions don't use rd.  */
# Line 3929  X(to_be_translated) Line 3719  X(to_be_translated)
3719    
3720                          if (ic->f == instr(addu))                          if (ic->f == instr(addu))
3721                                  cpu->cd.mips.combination_check = COMBINE(addu);                                  cpu->cd.mips.combination_check = COMBINE(addu);
3722    
3723                          break;                          break;
3724    
3725                  case SPECIAL_JR:                  case SPECIAL_JR:
# Line 3948  X(to_be_translated) Line 3739  X(to_be_translated)
3739                                  } else {                                  } else {
3740                                          ic->f = instr(jr);                                          ic->f = instr(jr);
3741                                  }                                  }
3742                                    if (cpu->translation_readahead > 2)
3743                                            cpu->translation_readahead = 2;
3744                                  break;                                  break;
3745                          case SPECIAL_JALR:                          case SPECIAL_JALR:
3746                                  if (cpu->machine->show_trace_tree)                                  if (cpu->machine->show_trace_tree)
# Line 3957  X(to_be_translated) Line 3750  X(to_be_translated)
3750                                  break;                                  break;
3751                          }                          }
3752                          if (cpu->delay_slot) {                          if (cpu->delay_slot) {
3753                                  fatal("TODO: branch in delay slot? (1)\n");                                  if (!cpu->translation_readahead)
3754                                            fatal("TODO: branch in delay "
3755                                                "slot? (1)\n");
3756                                  goto bad;                                  goto bad;
3757                          }                          }
3758                          break;                          break;
# Line 4055  X(to_be_translated) Line 3850  X(to_be_translated)
3850                          ic->f = samepage_function;                          ic->f = samepage_function;
3851                  }                  }
3852                  if (cpu->delay_slot) {                  if (cpu->delay_slot) {
3853                          fatal("TODO: branch in delay slot? (2)\n");                          if (!cpu->translation_readahead)
3854                                    fatal("TODO: branch in delay slot? (2)\n");
3855                          goto bad;                          goto bad;
3856                  }                  }
3857                  break;                  break;
# Line 4127  X(to_be_translated) Line 3923  X(to_be_translated)
3923                  switch (main_opcode) {                  switch (main_opcode) {
3924                  case HI6_J:                  case HI6_J:
3925                          ic->f = instr(j);                          ic->f = instr(j);
3926                            if (cpu->translation_readahead > 2)
3927                                    cpu->translation_readahead = 2;
3928                          break;                          break;
3929                  case HI6_JAL:                  case HI6_JAL:
3930                          if (cpu->machine->show_trace_tree)                          if (cpu->machine->show_trace_tree)
# Line 4138  X(to_be_translated) Line 3936  X(to_be_translated)
3936                  ic->arg[0] = (iword & 0x03ffffff) << 2;                  ic->arg[0] = (iword & 0x03ffffff) << 2;
3937                  ic->arg[1] = (addr & 0xffc) + 8;                  ic->arg[1] = (addr & 0xffc) + 8;
3938                  if (cpu->delay_slot) {                  if (cpu->delay_slot) {
3939                          fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"                          if (!cpu->translation_readahead)
3940                              PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,                                  fatal("TODO: branch in delay slot (=%i)? (3);"
3941                              (uint64_t)addr, iword);                                      " addr=%016"PRIx64" iword=%08"PRIx32"\n",
3942                                        cpu->delay_slot, (uint64_t)addr, iword);
3943                          goto bad;                          goto bad;
3944                  }                  }
3945                  break;                  break;
# Line 4177  X(to_be_translated) Line 3976  X(to_be_translated)
3976                                      cpu->cd.mips.cpu_type.isa_level < 32) {                                      cpu->cd.mips.cpu_type.isa_level < 32) {
3977                                          static int warned = 0;                                          static int warned = 0;
3978                                          ic->f = instr(reserved);                                          ic->f = instr(reserved);
3979                                          if (!warned) {                                          if (!warned &&
3980                                                !cpu->translation_readahead) {
3981                                                  fatal("{ WARNING: Attempt to "                                                  fatal("{ WARNING: Attempt to "
3982                                                      "execute the WAIT instruct"                                                      "execute the WAIT instruct"
3983                                                      "ion, but the emulated CPU "                                                      "ion, but the emulated CPU "
# Line 4188  X(to_be_translated) Line 3988  X(to_be_translated)
3988                                  }                                  }
3989                                  break;                                  break;
3990                          case COP0_STANDBY:                          case COP0_STANDBY:
3991                          case COP0_SUSPEND:                                  /*  NOTE: Reusing the 'wait' instruction:  */
3992                                    ic->f = instr(wait);
3993                                    if (cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
3994                                            static int warned = 0;
3995                                            ic->f = instr(reserved);
3996                                            if (!warned &&
3997                                                !cpu->translation_readahead) {
3998                                                    fatal("{ WARNING: Attempt to "
3999                                                        "execute a R41xx instruct"
4000                                                        "ion, but the emulated CPU "
4001                                                        "doesn't support it! }\n");
4002                                                    warned = 1;
4003                                            }
4004                                    }
4005                                    break;
4006                          case COP0_HIBERNATE:                          case COP0_HIBERNATE:
4007                                  /*  TODO  */                                  /*  TODO  */
4008                                  ic->f = instr(nop);                                  goto bad;
4009                            case COP0_SUSPEND:
4010                                    /*  Used by NetBSD on HPCmips (VR41xx) to
4011                                        halt the machine.  */
4012                                    ic->f = instr(reboot);
4013                                  break;                                  break;
4014                          case COP0_EI:                          case COP0_EI:
4015                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
# Line 4205  X(to_be_translated) Line 4023  X(to_be_translated)
4023                                  } else                                  } else
4024                                          goto bad;                                          goto bad;
4025                                  break;                                  break;
4026                          default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",                          default:if (!cpu->translation_readahead)
4027                                      iword & 0xff);                                          fatal("UNIMPLEMENTED cop0 (func "
4028                                                "0x%02x)\n", iword & 0xff);
4029                                  goto bad;                                  goto bad;
4030                          }                          }
4031                          break;                          break;
# Line 4228  X(to_be_translated) Line 4047  X(to_be_translated)
4047                          ic->arg[1] = rd + ((iword & 7) << 5);                          ic->arg[1] = rd + ((iword & 7) << 5);
4048                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
4049                          ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);                          ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
4050                            if (rs == COPz_MFCz && (iword & 7) == 0 &&
4051                                rd != COP0_COUNT)
4052                                    ic->f = instr(mfc0_select0);
4053                            if (rs == COPz_DMFCz && (iword & 7) == 0 &&
4054                                rd != COP0_COUNT)
4055                                    ic->f = instr(dmfc0_select0);
4056                          if (rt == MIPS_GPR_ZERO)                          if (rt == MIPS_GPR_ZERO)
4057                                  ic->f = instr(nop);                                  ic->f = instr(nop);
4058                          break;                          break;
# Line 4244  X(to_be_translated) Line 4069  X(to_be_translated)
4069                                      COMBINE(netbsd_r3k_cache_inv);                                      COMBINE(netbsd_r3k_cache_inv);
4070    
4071                          break;                          break;
4072                  case 8: if (iword == 0x4100ffff) {                  case COPz_MFMCz:
4073                            if ((iword & 0xffdf) == 0x6000) {
4074                                    /*  MIPS32/64 rev 2 "ei" or "di":   */
4075                                    if (cpu->cd.mips.cpu_type.isa_level < 32 ||
4076                                        cpu->cd.mips.cpu_type.isa_revision < 2) {
4077                                            static int warning_ei_di = 0;
4078                                            if (!warning_ei_di &&
4079                                                !cpu->translation_readahead) {
4080                                                    fatal("[ WARNING! MIPS32/64 "
4081                                                        "revision 2 di or ei opcode"
4082                                                        " used, but the %s process"
4083                                                        "or does not implement "
4084                                                        "such instructions. Only "
4085                                                        "printing this "
4086                                                        "warning once. ]\n",
4087                                                        cpu->cd.mips.cpu_type.name);
4088                                                    warning_ei_di = 1;
4089                                            }
4090                                            ic->f = instr(reserved);
4091                                            break;
4092                                    }
4093                                    ic->f = instr(ei_or_di);
4094                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4095                                    if (rt == MIPS_GPR_ZERO)
4096                                            ic->arg[0] =
4097                                                (size_t)&cpu->cd.mips.scratch;
4098                                    ic->arg[1] = iword & 0x20;
4099                            } else {
4100                                    if (!cpu->translation_readahead)
4101                                            fatal("Unimplemented COP0_MFMCz\n");
4102                                    goto bad;
4103                            }
4104                            break;
4105                    case COPz_BCzc:
4106                            if (iword == 0x4100ffff) {
4107                                  /*  R2020 DECstation write-loop thingy.  */                                  /*  R2020 DECstation write-loop thingy.  */
4108                                  ic->f = instr(nop);                                  ic->f = instr(nop);
4109                          } else {                          } else {
4110                                  fatal("Unimplemented blah blah zzzz...\n");                                  if (!cpu->translation_readahead)
4111                                            fatal("Unimplemented COP0_BCzc\n");
4112                                  goto bad;                                  goto bad;
4113                          }                          }
4114                          break;                          break;
4115                                    
4116                  default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);                  default:if (!cpu->translation_readahead)
4117                                    fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4118                          goto bad;                          goto bad;
4119                  }                  }
4120                  break;                  break;
# Line 4280  X(to_be_translated) Line 4141  X(to_be_translated)
4141                          ic->arg[2] = (int32_t) ((imm <<                          ic->arg[2] = (int32_t) ((imm <<
4142                              MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);                              MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
4143                          if (cpu->delay_slot) {                          if (cpu->delay_slot) {
4144                                  fatal("TODO: branch in delay slot? (4)\n");                                  if (!cpu->translation_readahead)
4145                                            fatal("TODO: branch in delay slot 4\n");
4146                                  goto bad;                                  goto bad;
4147                          }                          }
4148                          if (cpu->cd.mips.cpu_type.isa_level <= 3 &&                          if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
4149                              ic->arg[0] != 0) {                              ic->arg[0] != 0) {
4150                                  fatal("Attempt to execute a non-cc-0 BC*"                                  if (!cpu->translation_readahead)
4151                                      " instruction on an isa level %i cpu. "                                          fatal("Attempt to execute a non-cc-0 "
4152                                      "TODO: How should this be handled?\n",                                              "BC* instruction on an isa level "
4153                                      cpu->cd.mips.cpu_type.isa_level);                                              "%i cpu. TODO: How should this be "
4154                                                "handled?\n",
4155                                                cpu->cd.mips.cpu_type.isa_level);
4156                                  goto bad;                                  goto bad;
4157                          }                          }
4158    
# Line 4313  X(to_be_translated) Line 4177  X(to_be_translated)
4177                          ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);                          ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
4178                          break;                          break;
4179    
4180                  default:fatal("COP1 floating point opcode = 0x%02x\n", rs);                  default:if (!cpu->translation_readahead)
4181                                fatal("COP1 floating point opcode = 0x%02x\n", rs);
4182                          goto bad;                          goto bad;
4183                  }                  }
4184                  break;                  break;
# Line 4326  X(to_be_translated) Line 4191  X(to_be_translated)
4191                          ic->arg[0] = 2;                          ic->arg[0] = 2;
4192                          break;                          break;
4193                  }                  }
4194                  fatal("COP2 functionality not yet implemented\n");                  if (!cpu->translation_readahead)
4195                            fatal("COP2 functionality not yet implemented\n");
4196                  goto bad;                  goto bad;
4197                  break;                  break;
4198    
4199            case HI6_COP3:
4200                    /*  Always cause a coprocessor unusable exception if
4201                        there is no coprocessor 3:  */
4202                    if (cpu->cd.mips.coproc[3] == NULL) {
4203                            ic->f = instr(cpu);
4204                            ic->arg[0] = 3;
4205                            break;
4206                    }
4207    
4208                    if (iword == 0x4d00ffff) {
4209                            /*  R2020 writeback thing, used by e.g. NetBSD/pmax
4210                                on MIPSMATE.  */
4211                            ic->f = instr(nop);
4212                    } else {
4213                            if (!cpu->translation_readahead)
4214                                    fatal("COP3 iword=0x%08x\n", iword);
4215                            goto bad;
4216                    }
4217                    break;
4218    
4219          case HI6_SPECIAL2:          case HI6_SPECIAL2:
4220                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4221                          /*  R5900, TX79/C790, have MMI instead of SPECIAL2:  */                          /*  R5900, TX79/C790, have MMI instead of SPECIAL2:  */
# Line 4509  X(to_be_translated) Line 4395  X(to_be_translated)
4395                                  ic->f = samepage_function;                                  ic->f = samepage_function;
4396                          }                          }
4397                          if (cpu->delay_slot) {                          if (cpu->delay_slot) {
4398                                  fatal("TODO: branch in delay slot? (5)\n");                                  if (!cpu->translation_readahead)
4399                                            fatal("TODO: branch in delay slot:5\n");
4400                                  goto bad;                                  goto bad;
4401                          }                          }
4402                          break;                          break;
4403                  default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);  
4404                    default:if (!cpu->translation_readahead)
4405                                    fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
4406                          goto bad;                          goto bad;
4407                  }                  }
4408                  break;                  break;
# Line 4593  X(to_be_translated) Line 4482  X(to_be_translated)
4482                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];                  ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4483                  ic->arg[2] = (int32_t)imm;                  ic->arg[2] = (int32_t)imm;
4484                  if (!store && rt == MIPS_GPR_ZERO) {                  if (!store && rt == MIPS_GPR_ZERO) {
4485                          fatal("HM... unusual load linked\n");                          if (!cpu->translation_readahead)
4486                                    fatal("HM... unusual load linked\n");
4487                          goto bad;                          goto bad;
4488                  }                  }
4489                  break;                  break;
# Line 4663  X(to_be_translated) Line 4553  X(to_be_translated)
4553                          /*  Treat as nop for now:  */                          /*  Treat as nop for now:  */
4554                          ic->f = instr(nop);                          ic->f = instr(nop);
4555                  } else {                  } else {
4556                          fatal("TODO: lwc3 not implemented yet\n");                          if (!cpu->translation_readahead)
4557                                    fatal("TODO: lwc3 not implemented yet\n");
4558                          goto bad;                          goto bad;
4559                  }                  }
4560                  break;                  break;
4561    
4562          case HI6_LQ_MDMX:          case HI6_LQ_MDMX:
4563                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4564                          fatal("TODO: R5900 128-bit loads\n");                          if (!cpu->translation_readahead)
4565                                    fatal("TODO: R5900 128-bit loads\n");
4566                          goto bad;                          goto bad;
4567                  }                  }
4568    
4569                  fatal("TODO: MDMX\n");                  if (!cpu->translation_readahead)
4570                            fatal("TODO: MDMX\n");
4571    
4572                  goto bad;                  goto bad;
4573                  /*  break  */                  /*  break  */
4574    
4575          case HI6_SQ_SPECIAL3:          case HI6_SQ_SPECIAL3:
4576                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4577                          fatal("TODO: R5900 128-bit stores\n");                          if (!cpu->translation_readahead)
4578                                    fatal("TODO: R5900 128-bit stores\n");
4579                          goto bad;                          goto bad;
4580                  }                  }
4581    
4582                  if (cpu->cd.mips.cpu_type.isa_level < 32 ||                  if (cpu->cd.mips.cpu_type.isa_level < 32 ||
4583                      cpu->cd.mips.cpu_type.isa_revision < 2) {                      cpu->cd.mips.cpu_type.isa_revision < 2) {
4584                          static int warning = 0;                          static int warning = 0;
4585                          if (!warning) {                          if (!warning && !cpu->translation_readahead) {
4586                                  fatal("[ WARNING! SPECIAL3 opcode used, but"                                  fatal("[ WARNING! SPECIAL3 opcode used, but"
4587                                      " the %s processor does not implement "                                      " the %s processor does not implement "
4588                                      "such instructions. Only printing this "                                      "such instructions. Only printing this "
# Line 4701  X(to_be_translated) Line 4596  X(to_be_translated)
4596    
4597                  switch (s6) {                  switch (s6) {
4598    
4599                    case SPECIAL3_EXT:
4600                            {
4601                                    int msbd = rd, lsb = (iword >> 6) & 0x1f;
4602                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4603                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4604                                    ic->arg[2] = (msbd << 5) + lsb;
4605                                    ic->f = instr(ext);
4606                                    if (rt == MIPS_GPR_ZERO)
4607                                            ic->f = instr(nop);
4608                            }
4609                            break;
4610    
4611                    case SPECIAL3_DEXT:
4612                    case SPECIAL3_DEXTM:
4613                    case SPECIAL3_DEXTU:
4614                            {
4615                                    int msbd = rd, lsb = (iword >> 6) & 0x1f;
4616                                    if (s6 == SPECIAL3_DEXTM)
4617                                            msbd += 32;
4618                                    if (s6 == SPECIAL3_DEXTU)
4619                                            lsb += 32;
4620                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4621                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4622                                    ic->arg[2] = (msbd << 6) + lsb;
4623                                    ic->f = instr(dext);
4624                                    if (rt == MIPS_GPR_ZERO)
4625                                            ic->f = instr(nop);
4626                            }
4627                            break;
4628    
4629                    case SPECIAL3_INS:
4630                            {
4631                                    int msb = rd, lsb = (iword >> 6) & 0x1f;
4632                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4633                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4634                                    ic->arg[2] = (msb << 5) + lsb;
4635                                    ic->f = instr(ins);
4636                                    if (rt == MIPS_GPR_ZERO)
4637                                            ic->f = instr(nop);
4638                            }
4639                            break;
4640    
4641                    case SPECIAL3_BSHFL:
4642                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4643                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4644                            switch (s10) {
4645                            case BSHFL_WSBH:
4646                                    ic->f = instr(wsbh);
4647                                    break;
4648                            case BSHFL_SEB:
4649                                    ic->f = instr(seb);
4650                                    break;
4651                            case BSHFL_SEH:
4652                                    ic->f = instr(seh);
4653                                    break;
4654                            default:goto bad;
4655                            }
4656                            break;
4657    
4658                    case SPECIAL3_DBSHFL:
4659                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4660                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4661                            switch (s10) {
4662                            case BSHFL_DSBH:
4663                                    ic->f = instr(dsbh);
4664                                    break;
4665                            case BSHFL_DSHD:
4666                                    ic->f = instr(dshd);
4667                                    break;
4668                            default:goto bad;
4669                            }
4670                            break;
4671    
4672                  case SPECIAL3_RDHWR:                  case SPECIAL3_RDHWR:
4673                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4674    
# Line 4711  X(to_be_translated) Line 4679  X(to_be_translated)
4679                                          ic->f = instr(nop);                                          ic->f = instr(nop);
4680                                  break;                                  break;
4681    
4682                          default:fatal("unimplemented rdhwr register rd=%i\n",                          default:if (!cpu->translation_readahead)
4683                                      rd);                                          fatal("unimplemented rdhwr "
4684                                                "register rd=%i\n", rd);
4685                                  goto bad;                                  goto bad;
4686                          }                          }
4687                          break;                          break;
# Line 4729  X(to_be_translated) Line 4698  X(to_be_translated)
4698          default:goto bad;          default:goto bad;
4699          }          }
4700    
4701    
4702  #ifdef MODE32  #ifdef MODE32
4703          if (x64) {          if (x64) {
4704                  static int has_warned = 0;                  static int has_warned = 0;
4705                  if (!has_warned)                  if (!has_warned && !cpu->translation_readahead) {
4706                          fatal("[ WARNING/NOTE: attempt to execute a 64-bit"                          fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
4707                              " instruction on an emulated 32-bit processor; "                              " instruction on an emulated 32-bit processor; "
4708                              "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);                              "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
4709                  has_warned = 1;                          has_warned = 1;
4710                  ic->f = instr(reserved);                  }
4711                    if (cpu->translation_readahead)
4712                            goto bad;
4713                    else
4714                            ic->f = instr(reserved);
4715          }          }
4716  #endif  #endif
4717    
         if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL)  
                 cpu->cd.mips.combination_check = COMBINE(nop);  
   
4718    
4719  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4720  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"

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

  ViewVC Help
Powered by ViewVC 1.1.26