/[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 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.97 2006/07/20 03:20:03 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 1679  X(mtc0) Line 1862  X(mtc0)
1862                  uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];                  uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1863                  /*  NOTE: STATUS_IE happens to match the enable bit also                  /*  NOTE: STATUS_IE happens to match the enable bit also
1864                      on R2000/R3000, so this is ok.  */                      on R2000/R3000, so this is ok.  */
1865                  if (status & (STATUS_EXL | STATUS_ERL))                  if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1866                          status &= ~STATUS_IE;                          if (status & (STATUS_EXL | STATUS_ERL))
1867                                    status &= ~STATUS_IE;
1868                    }
1869                  /*  Ugly R5900 special case:  (TODO: move this?)  */                  /*  Ugly R5900 special case:  (TODO: move this?)  */
1870                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1871                      !(status & R5900_STATUS_EIE))                      !(status & R5900_STATUS_EIE))
# Line 1700  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 1721  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 1772  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 1807  X(break) Line 1985  X(break)
1985          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1986          mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);          mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1987  }  }
1988    X(reboot)
1989    {
1990            if (!cop0_availability_check(cpu, ic))
1991                    return;
1992    
1993            cpu->running = 0;
1994            debugger_n_steps_left_before_interaction = 0;
1995            cpu->cd.mips.next_ic = &nothing_call;
1996    }
1997    
1998    
1999  /*  /*
# Line 1865  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 1879  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 1892  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 1914  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 1934  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 1952  X(deret) Line 2173  X(deret)
2173    
2174    
2175  /*  /*
2176     *  idle:  Called from the implementation of wait, or netbsd_pmax_idle.
2177     */
2178    X(idle)
2179    {
2180            /*
2181             *  If there is an interrupt, then just return. Otherwise
2182             *  re-run the wait instruction (after a delay).
2183             */
2184            uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2185            uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
2186    
2187            if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2188                    if (status & (STATUS_EXL | STATUS_ERL))
2189                            status &= ~STATUS_IE;
2190            }
2191    
2192            /*  Ugly R5900 special case:  (TODO: move this?)  */
2193            if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
2194                !(status & R5900_STATUS_EIE))
2195                    status &= ~STATUS_IE;
2196            if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
2197                    return;
2198    
2199            cpu->cd.mips.next_ic = ic;
2200            cpu->is_halted = 1;
2201            cpu->has_been_idling = 1;
2202    
2203            /*
2204             *  There was no interrupt. Go to sleep.
2205             *
2206             *  TODO:
2207             *
2208             *  Think about how to actually implement this usleep stuff,
2209             *  in an SMP and/or timing accurate environment.
2210             */
2211    
2212            if (cpu->machine->ncpus == 1) {
2213                    static int x = 0;
2214                    if ((++x) == 600) {
2215                            usleep(10);
2216                            x = 0;
2217                    }
2218                    cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2219            }
2220    }
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 2188  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 2214  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 2240  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 2281  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 2349  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 2381  X(sw_loop) Line 2614  X(sw_loop)
2614          if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {          if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2615                  instr(addiu)(cpu, ic);                  instr(addiu)(cpu, ic);
2616                  return;                  return;
2617          }          }
2618    
2619          if (rYp == (uint64_t *) ic->arg[0])          if (rYp == (uint64_t *) ic->arg[0])
2620                  rYp = (uint64_t *) ic[1].arg[1];                  rYp = (uint64_t *) ic[1].arg[1];
# Line 2410  X(sw_loop) Line 2643  X(sw_loop)
2643  }  }
2644    
2645    
2646  /*  #ifdef MODE32
2647   *  multi_sw_3:  /*  multi_{l,s}w_2, _3, etc.  */
2648   *  #include "tmp_mips_loadstore_multi.c"
2649   *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]  #endif
  *      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]  
  */  
 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:  */  
                 ic[1].f(cpu, ic);  
                 return;  
         }  
2650    
         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;  
2651    
2652          cpu->n_translated_instrs += 2;  /*
2653          cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];   *  multi_addu_3:
2654  }   */
2655  X(multi_sw_3_be)  X(multi_addu_3)
2656  {  {
         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];  
   
2657          /*  Fallback:  */          /*  Fallback:  */
2658          if (cpu->delay_slot ||          if (cpu->delay_slot) {
2659              page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||                  instr(addu)(cpu, ic);
             (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {  
                 /*  Normal safe sw:  */  
                 ic[1].f(cpu, ic);  
2660                  return;                  return;
2661          }          }
   
         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;  
2662    
2663            reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
2664            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
2665            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
2666          cpu->n_translated_instrs += 2;          cpu->n_translated_instrs += 2;
2667          cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];          cpu->cd.mips.next_ic += 2;
2668  }  }
2669    
2670    
# Line 2539  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 2592  X(netbsd_strlen) Line 2822  X(netbsd_strlen)
2822    
2823    
2824  /*  /*
2825   *  lui_32bit:   *  addiu_bne_samepage_addiu:
2826   *   */
2827   *  Combination of lui and addiu.  X(addiu_bne_samepage_addiu)
2828   *  Note: All 32 bits of arg[2] of the lui instr_call are used.  {
2829            MODE_uint_t rs, rt;
2830    
2831            if (cpu->delay_slot) {
2832                    instr(addiu)(cpu, ic);
2833                    return;
2834            }
2835    
2836            cpu->n_translated_instrs += 2;
2837            reg(ic[0].arg[1]) = (int32_t)
2838                ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
2839            rs = reg(ic[1].arg[0]);
2840            rt = reg(ic[1].arg[1]);
2841            reg(ic[2].arg[1]) = (int32_t)
2842                ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
2843            if (rs != rt)
2844                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
2845            else
2846                    cpu->cd.mips.next_ic += 2;
2847    }
2848    
2849    
2850    /*
2851     *  xor_andi_sll:
2852     */
2853    X(xor_andi_sll)
2854    {
2855            /*  Fallback:  */
2856            if (cpu->delay_slot) {
2857                    instr(xor)(cpu, ic);
2858                    return;
2859            }
2860    
2861            reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
2862            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
2863            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
2864    
2865            cpu->n_translated_instrs += 2;
2866            cpu->cd.mips.next_ic += 2;
2867    }
2868    
2869    
2870    /*
2871     *  andi_sll:
2872   */   */
2873  X(lui_32bit)  X(andi_sll)
2874  {  {
2875          reg(ic[0].arg[0]) = (int32_t) ic[0].arg[2];          /*  Fallback:  */
2876            if (cpu->delay_slot) {
2877                    instr(andi)(cpu, ic);
2878                    return;
2879            }
2880    
2881            reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
2882            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
2883    
2884            cpu->n_translated_instrs ++;
2885            cpu->cd.mips.next_ic ++;
2886    }
2887    
2888    
2889    /*
2890     *  lui_ori:
2891     */
2892    X(lui_ori)
2893    {
2894            /*  Fallback:  */
2895            if (cpu->delay_slot) {
2896                    instr(set)(cpu, ic);
2897                    return;
2898            }
2899    
2900            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2901            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
2902    
2903            cpu->n_translated_instrs ++;
2904            cpu->cd.mips.next_ic ++;
2905    }
2906    
2907    
2908    /*
2909     *  lui_addiu:
2910     */
2911    X(lui_addiu)
2912    {
2913            /*  Fallback:  */
2914            if (cpu->delay_slot) {
2915                    instr(set)(cpu, ic);
2916                    return;
2917            }
2918    
2919            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2920            reg(ic[1].arg[1]) = (int32_t)
2921                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
2922    
2923          cpu->n_translated_instrs ++;          cpu->n_translated_instrs ++;
2924          cpu->cd.mips.next_ic ++;          cpu->cd.mips.next_ic ++;
2925  }  }
# Line 2739  void COMBINE(sw_loop)(struct cpu *cpu, s Line 3059  void COMBINE(sw_loop)(struct cpu *cpu, s
3059              ic[0].arg[0] != ic[0].arg[1] &&              ic[0].arg[0] != ic[0].arg[1] &&
3060              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) {
3061                  ic[-2].f = instr(sw_loop);                  ic[-2].f = instr(sw_loop);
                 combined;  
3062          }          }
3063  }  }
3064    
3065    
3066    /*  Only for 32-bit virtual address translation so far.  */
3067    #ifdef MODE32
3068  /*  /*
3069   *  Combine:  Multiple SW in a row using the same base register   *  Combine:  Multiple SW in a row using the same base register
3070   *   *
# Line 2758  void COMBINE(multi_sw)(struct cpu *cpu, Line 3079  void COMBINE(multi_sw)(struct cpu *cpu,
3079          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3080              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3081    
3082          /*  Only for 32-bit virtual address translation so far.  */          if (n_back < 3)
         if (!cpu->is_32bit)  
3083                  return;                  return;
3084    
3085          if (n_back < 4)          /*  Convert a multi_sw_3 to a multi_sw_4:  */
3086                  return;          if ((ic[-3].f == instr(multi_sw_3_be) ||
3087                ic[-3].f == instr(multi_sw_3_le)) &&
3088                ic[-3].arg[1] == ic[0].arg[1]) {
3089                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3090                            ic[-3].f = instr(multi_sw_4_le);
3091                    else
3092                            ic[-3].f = instr(multi_sw_4_be);
3093            }
3094    
3095          /*  Avoid "overlapping" instruction combinations:  */          /*  Convert a multi_sw_2 to a multi_sw_3:  */
3096          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) ||
3097              ic[-4].f == instr(multi_sw_3_le)||ic[-3].f == instr(multi_sw_3_le))              ic[-2].f == instr(multi_sw_2_le)) &&
3098                ic[-2].arg[1] == ic[0].arg[1]) {
3099                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3100                            ic[-2].f = instr(multi_sw_3_le);
3101                    else
3102                            ic[-2].f = instr(multi_sw_3_be);
3103            }
3104    
3105            if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3106                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3107                            ic[-1].f = instr(multi_sw_2_le);
3108                    else
3109                            ic[-1].f = instr(multi_sw_2_be);
3110            }
3111    }
3112    #endif
3113    
3114    
3115    /*  Only for 32-bit virtual address translation so far.  */
3116    #ifdef MODE32
3117    /*
3118     *  Combine:  Multiple LW in a row using the same base register
3119     *
3120     *      lw      r?,???(rX)
3121     *      lw      r?,???(rX)
3122     *      lw      r?,???(rX)
3123     *      ...
3124     */
3125    void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3126            int low_addr)
3127    {
3128            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3129                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3130    
3131            if (n_back < 3)
3132                  return;                  return;
3133    
3134          if (ic[-2].f == ic[0].f && ic[-1].f == ic[0].f &&          /*  Convert a multi_lw_3 to a multi_lw_4:  */
3135            if ((ic[-3].f == instr(multi_lw_3_be) ||
3136                ic[-3].f == instr(multi_lw_3_le)) &&
3137                ic[-3].arg[1] == ic[0].arg[1] &&
3138                ic[-1].arg[0] != ic[0].arg[1]) {
3139                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3140                            ic[-3].f = instr(multi_lw_4_le);
3141                    else
3142                            ic[-3].f = instr(multi_lw_4_be);
3143            }
3144    
3145            /*  Convert a multi_lw_2 to a multi_lw_3:  */
3146            if ((ic[-2].f == instr(multi_lw_2_be) ||
3147                ic[-2].f == instr(multi_lw_2_le)) &&
3148              ic[-2].arg[1] == ic[0].arg[1] &&              ic[-2].arg[1] == ic[0].arg[1] &&
3149              ic[-1].arg[1] == ic[0].arg[1]) {              ic[-1].arg[0] != ic[0].arg[1]) {
3150                  if (cpu->byte_order == EMUL_LITTLE_ENDIAN)                  if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3151                          ic[-2].f = instr(multi_sw_3_le);                          ic[-2].f = instr(multi_lw_3_le);
3152                  else                  else
3153                          ic[-2].f = instr(multi_sw_3_be);                          ic[-2].f = instr(multi_lw_3_be);
3154                  combined;          }
3155    
3156            /*  Note: Loads to the base register are not allowed in slot -1.  */
3157            if (ic[-1].f == ic[0].f &&
3158                ic[-1].arg[1] == ic[0].arg[1] &&
3159                ic[-1].arg[0] != ic[0].arg[1]) {
3160                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3161                            ic[-1].f = instr(multi_lw_2_le);
3162                    else
3163                            ic[-1].f = instr(multi_lw_2_be);
3164          }          }
3165  }  }
3166    #endif
3167    
3168    
3169  /*  /*
# Line 2815  void COMBINE(netbsd_r3k_cache_inv)(struc Line 3199  void COMBINE(netbsd_r3k_cache_inv)(struc
3199              ic[-3].arg[1] == ic[-5].arg[0] &&              ic[-3].arg[1] == ic[-5].arg[0] &&
3200              ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {              ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3201                  ic[-8].f = instr(netbsd_r3k_picache_do_inv);                  ic[-8].f = instr(netbsd_r3k_picache_do_inv);
                 combined;  
3202          }          }
3203  }  }
3204    
# Line 2825  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;
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;                  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 2844  void COMBINE(nop)(struct cpu *cpu, struc Line 3261  void COMBINE(nop)(struct cpu *cpu, struc
3261              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] &&
3262              ic[-1].f == instr(bne_samepage)) {              ic[-1].f == instr(bne_samepage)) {
3263                  ic[-3].f = instr(netbsd_strlen);                  ic[-3].f = instr(netbsd_strlen);
                 combined;  
3264                  return;                  return;
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);
                 combined;  
3270                  return;                  return;
3271          }          }
3272    
3273          if (ic[-1].f == instr(beq_samepage)) {          if (ic[-1].f == instr(beq_samepage)) {
3274                  ic[-1].f = instr(beq_samepage_nop);                  ic[-1].f = instr(beq_samepage_nop);
                 combined;  
3275                  return;                  return;
3276          }          }
3277    
# Line 2871  void COMBINE(nop)(struct cpu *cpu, struc Line 3282  void COMBINE(nop)(struct cpu *cpu, struc
3282  /*  /*
3283   *  Combine:   *  Combine:
3284   *   *
3285     *      xor + andi + sll
3286     *      andi + sll
3287     */
3288    void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3289    {
3290            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3291                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3292    
3293            if (n_back < 2)
3294                    return;
3295    
3296            if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3297                    ic[-2].f = instr(xor_andi_sll);
3298                    return;
3299            }
3300    
3301            if (ic[-1].f == instr(andi)) {
3302                    ic[-1].f = instr(andi_sll);
3303                    return;
3304            }
3305    }
3306    
3307    
3308    /*
3309     *  lui + ori
3310     */
3311    void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3312    {
3313            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3314                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3315    
3316            if (n_back < 1)
3317                    return;
3318    
3319            if (ic[-1].f == instr(set)) {
3320                    ic[-1].f = instr(lui_ori);
3321                    return;
3322            }
3323    }
3324    
3325    
3326    /*
3327     *  addu + addu + addu
3328     */
3329    void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3330    {
3331            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3332                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3333    
3334            if (n_back < 4)
3335                    return;
3336    
3337            /*  Avoid "overlapping" instruction combinations:  */
3338            if (ic[-4].f == instr(multi_addu_3) ||
3339                ic[-3].f == instr(multi_addu_3))
3340                    return;
3341    
3342            if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3343                    ic[-2].f = instr(multi_addu_3);
3344                    return;
3345            }
3346    }
3347    
3348    
3349    /*
3350     *  Combine:
3351     *
3352   *      [Conditional] branch, followed by addiu.   *      [Conditional] branch, followed by addiu.
  *      lui + addiu.  
3353   */   */
3354  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)
3355  {  {
3356          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3357              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3358    
3359          if (n_back < 1)          if (n_back < 2)
3360                    return;
3361    
3362            if (ic[-2].f == instr(addiu) &&
3363                ic[-1].f == instr(bne_samepage)) {
3364                    ic[-2].f = instr(addiu_bne_samepage_addiu);
3365                  return;                  return;
3366            }
3367    
3368          if (ic[-1].f == instr(set) && ic[-1].arg[0] == ic[0].arg[0] &&          if (ic[-1].f == instr(set)) {
3369              ic[0].arg[0] == ic[0].arg[1]) {                  ic[-1].f = instr(lui_addiu);
                 ic[-1].f = instr(lui_32bit);  
                 ic[-1].arg[2] = (int32_t) (ic[-1].arg[1] + ic[0].arg[2]);  
                 combined;  
3370                  return;                  return;
3371          }          }
3372    
3373          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
3374                  ic[-1].f = instr(b_samepage_addiu);                  ic[-1].f = instr(b_samepage_addiu);
                 combined;  
3375                  return;                  return;
3376          }          }
3377    
3378          if (ic[-1].f == instr(beq_samepage)) {          if (ic[-1].f == instr(beq_samepage)) {
3379                  ic[-1].f = instr(beq_samepage_addiu);                  ic[-1].f = instr(beq_samepage_addiu);
                 combined;  
3380                  return;                  return;
3381          }          }
3382    
3383          if (ic[-1].f == instr(bne_samepage)) {          if (ic[-1].f == instr(bne_samepage)) {
3384                  ic[-1].f = instr(bne_samepage_addiu);                  ic[-1].f = instr(bne_samepage_addiu);
                 combined;  
3385                  return;                  return;
3386          }          }
3387    
3388          if (ic[-1].f == instr(jr_ra)) {          if (ic[-1].f == instr(jr_ra)) {
3389                  ic[-1].f = instr(jr_ra_addiu);                  ic[-1].f = instr(jr_ra_addiu);
                 combined;  
3390                  return;                  return;
3391          }          }
3392    
# Line 2932  void COMBINE(b_daddiu)(struct cpu *cpu, Line 3408  void COMBINE(b_daddiu)(struct cpu *cpu,
3408    
3409          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
3410                  ic[-1].f = instr(b_samepage_daddiu);                  ic[-1].f = instr(b_samepage_daddiu);
                 combined;  
3411          }          }
3412    
3413          /*  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 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 3037  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 3089  X(to_be_translated) Line 3565  X(to_be_translated)
3565                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3566                          if (rd == MIPS_GPR_ZERO)                          if (rd == MIPS_GPR_ZERO)
3567                                  ic->f = instr(nop);                                  ic->f = instr(nop);
3568                            if (ic->f == instr(sll))
3569                                    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 3212  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 3220  X(to_be_translated) Line 3716  X(to_be_translated)
3716                          default:if (rd == MIPS_GPR_ZERO)                          default:if (rd == MIPS_GPR_ZERO)
3717                                          ic->f = instr(nop);                                          ic->f = instr(nop);
3718                          }                          }
3719    
3720                            if (ic->f == instr(addu))
3721                                    cpu->cd.mips.combination_check = COMBINE(addu);
3722    
3723                          break;                          break;
3724    
3725                  case SPECIAL_JR:                  case SPECIAL_JR:
# Line 3239  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 3248  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 3263  X(to_be_translated) Line 3767  X(to_be_translated)
3767                          break;                          break;
3768    
3769                  case SPECIAL_BREAK:                  case SPECIAL_BREAK:
3770                          ic->f = instr(break);                          if (((iword >> 6) & 0xfffff) == 0x30378) {
3771                                    /*  "Magic trap" for REBOOT:  */
3772                                    ic->f = instr(reboot);
3773                            } else {
3774                                    ic->f = instr(break);
3775                            }
3776                          break;                          break;
3777    
3778                  case SPECIAL_SYNC:                  case SPECIAL_SYNC:
# Line 3341  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 3390  X(to_be_translated) Line 3900  X(to_be_translated)
3900                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
3901                          ic->f = instr(nop);                          ic->f = instr(nop);
3902    
3903                    if (ic->f == instr(ori))
3904                            cpu->cd.mips.combination_check = COMBINE(ori);
3905                  if (ic->f == instr(addiu))                  if (ic->f == instr(addiu))
3906                          cpu->cd.mips.combination_check = COMBINE(addiu);                          cpu->cd.mips.combination_check = COMBINE(addiu);
3907                  if (ic->f == instr(daddiu))                  if (ic->f == instr(daddiu))
# Line 3411  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 3422  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 3455  X(to_be_translated) Line 3970  X(to_be_translated)
3970                          case COP0_DERET:                          case COP0_DERET:
3971                                  ic->f = instr(deret);                                  ic->f = instr(deret);
3972                                  break;                                  break;
3973                          case COP0_IDLE:                          case COP0_WAIT:
3974                                    ic->f = instr(wait);
3975                                    if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
3976                                        cpu->cd.mips.cpu_type.isa_level < 32) {
3977                                            static int warned = 0;
3978                                            ic->f = instr(reserved);
3979                                            if (!warned &&
3980                                                !cpu->translation_readahead) {
3981                                                    fatal("{ WARNING: Attempt to "
3982                                                        "execute the WAIT instruct"
3983                                                        "ion, but the emulated CPU "
3984                                                        "is neither RM52xx, nor "
3985                                                        "MIPS32/64! }\n");
3986                                                    warned = 1;
3987                                            }
3988                                    }
3989                                    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 3474  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 3497  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 3513  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 3549  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 3582  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 3595  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 3778  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 3830  X(to_be_translated) Line 4450  X(to_be_translated)
4450                  if (!store && rt == MIPS_GPR_ZERO)                  if (!store && rt == MIPS_GPR_ZERO)
4451                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4452    
4453                  /*  Check for multiple stores in a row using the same                  /*  Check for multiple loads or stores in a row using the same
4454                      base register:  */                      base register:  */
4455                  if (main_opcode == HI6_SW && rs == MIPS_GPR_SP)  #ifdef MODE32
4456                    if (main_opcode == HI6_LW)
4457                            cpu->cd.mips.combination_check = COMBINE(multi_lw);
4458                    if (main_opcode == HI6_SW)
4459                          cpu->cd.mips.combination_check = COMBINE(multi_sw);                          cpu->cd.mips.combination_check = COMBINE(multi_sw);
4460    #endif
4461                  break;                  break;
4462    
4463          case HI6_LL:          case HI6_LL:
# Line 3859  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 3929  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 3967  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 3977  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 3995  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.28  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26