/[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 24 by dpavlin, Mon Oct 8 16:19:56 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.85 2006/06/22 13:22:41 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 135  X(beq_samepage) Line 213  X(beq_samepage)
213          }          }
214          cpu->delay_slot = NOT_DELAYED;          cpu->delay_slot = NOT_DELAYED;
215  }  }
216    X(beq_samepage_addiu)
217    {
218            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
219            cpu->n_translated_instrs ++;
220            reg(ic[1].arg[1]) = (int32_t)
221                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
222            if (rs == rt)
223                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
224            else
225                    cpu->cd.mips.next_ic ++;
226    }
227    X(beq_samepage_nop)
228    {
229            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
230            cpu->n_translated_instrs ++;
231            if (rs == rt)
232                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
233            else
234                    cpu->cd.mips.next_ic ++;
235    }
236  X(bne)  X(bne)
237  {  {
238          MODE_int_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
# Line 172  X(bne_samepage) Line 270  X(bne_samepage)
270          }          }
271          cpu->delay_slot = NOT_DELAYED;          cpu->delay_slot = NOT_DELAYED;
272  }  }
273    X(bne_samepage_addiu)
274    {
275            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
276            cpu->n_translated_instrs ++;
277            reg(ic[1].arg[1]) = (int32_t)
278                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
279            if (rs != rt)
280                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
281            else
282                    cpu->cd.mips.next_ic ++;
283    }
284    X(bne_samepage_nop)
285    {
286            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
287            cpu->n_translated_instrs ++;
288            if (rs != rt)
289                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
290            else
291                    cpu->cd.mips.next_ic ++;
292    }
293  X(b)  X(b)
294  {  {
295          MODE_int_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
# Line 896  X(jr_ra) Line 1014  X(jr_ra)
1014          } else          } else
1015                  cpu->delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
1016  }  }
1017    X(jr_ra_addiu)
1018    {
1019            /*  jr ra, followed by an addiu  */
1020            MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1021            reg(ic[1].arg[1]) = (int32_t)
1022                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
1023            cpu->pc = rs;
1024            quick_pc_to_pointers(cpu);
1025            cpu->n_translated_instrs ++;
1026    }
1027  X(jr_ra_trace)  X(jr_ra_trace)
1028  {  {
1029          MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];          MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
# Line 1013  X(jal_trace) Line 1141  X(jal_trace)
1141   */   */
1142  X(cache)  X(cache)
1143  {  {
1144          /*  TODO. For now, just clear the rmw bit:  */          /*  TODO: Implement cache operations.  */
1145    
1146            /*  Make sure the rmw bit is cleared:  */
1147          cpu->cd.mips.rmw = 0;          cpu->cd.mips.rmw = 0;
1148    }
1149    
1150    
1151  /*  TODO: fix  */  /*
1152  cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);   *  ins: Insert bitfield.
1153  cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);   *
1154  /* cpu_create_or_reset_tc(cpu); */   *  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 1049  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 1060  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 1072  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 1084  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 1100  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 1117  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 1147  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 1164  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 1574  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 1612  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;
1848          uint64_t tmp = (int32_t) reg(ic->arg[0]);          uint64_t tmp = (int32_t) reg(ic->arg[0]);
1849  #if 0  
         uint32_t oldstatus = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];  
 #endif  
1850          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1851          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
1852    
1853          /*  TODO: cause exception if necessary  */          /*  TODO: cause exception if necessary  */
1854          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1855    
1856  #if 0          /*
1857          /*  Interrupts enabled, and any interrupt pending?  */           *  Interrupts enabled, and any interrupt pending? (Note/TODO: This
1858          if (rd == COP0_STATUS && !(oldstatus & STATUS_IE)) {           *  code is duplicated in cpu_dyntrans.c. Fix this?)
1859             */
1860            if (rd == COP0_STATUS && !cpu->delay_slot) {
1861                  uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];                  uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
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_IE && (status & cause & STATUS_IM_MASK))                  if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1866                          cpu->running_translated = 0;                          if (status & (STATUS_EXL | STATUS_ERL))
1867                                    status &= ~STATUS_IE;
1868                    }
1869                    /*  Ugly R5900 special case:  (TODO: move this?)  */
1870                    if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1871                        !(status & R5900_STATUS_EIE))
1872                            status &= ~STATUS_IE;
1873                    if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1874                            cpu->pc += sizeof(uint32_t);
1875                            mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1876                    }
1877          }          }
 #endif  
1878  }  }
1879  X(dmfc0)  X(dmfc0)
1880  {  {
# Line 1646  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 1654  X(dmtc0) Line 1905  X(dmtc0)
1905          /*  TODO: cause exception if necessary  */          /*  TODO: cause exception if necessary  */
1906          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1907              (uint64_t *)ic->arg[0], 1, select);              (uint64_t *)ic->arg[0], 1, select);
   
 /*  TODO: fix/remove these!  */  
 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);  
1908  }  }
1909    
1910    
# Line 1670  cpu->invalidate_translation_caches(cpu, Line 1918  cpu->invalidate_translation_caches(cpu,
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 1721  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 1756  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 1814  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 1828  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 1841  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          coproc_rfe(cpu);          if (!cop0_availability_check(cpu, ic))
2112                    return;
2113    
2114          /*  Note: no pc to pointers conversion is necessary here.  */          /*  Just rotate the interrupt/user bits:  */
2115            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2116                (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
2117                ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
2118    
2119            /*
2120             *  Note: no pc to pointers conversion is necessary here. Usually the
2121             *  rfe instruction resides in the delay slot of a jr k0/k1, and
2122             *  it is up to that instruction to do the pointer conversion.
2123             */
2124  }  }
2125    
2126    
2127  /*  /*
2128   *  eret: Return from exception handler   *  eret: Return from exception handler (non-R3000 style)
2129   */   */
2130  X(eret)  X(eret)
2131  {  {
2132          coproc_eret(cpu);          if (!cop0_availability_check(cpu, ic))
2133                    return;
2134    
2135            if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2136                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2137                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
2138            } else {
2139                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
2140                    cpu->delay_slot = 0;            
2141                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2142            }
2143    
2144          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
2145    
2146            cpu->cd.mips.rmw = 0;   /*  the "LL bit"  */
2147  }  }
2148    
2149    
# Line 1866  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 1884  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 2120  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 2146  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 2172  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 2213  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 2281  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 2293  X(ei_r5900) Line 2594  X(ei_r5900)
2594    
2595    
2596  /*  /*
2597     *  sw_loop:
2598     *
2599     *  s:  addiu   rX,rX,4                 rX = arg[0] and arg[1]
2600     *      bne     rY,rX,s  (or rX,rY,s)   rt=arg[1], rs=arg[0]
2601     *      sw      rZ,-4(rX)               rt=arg[0], rs=arg[1]
2602     */
2603    X(sw_loop)
2604    {
2605            MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2606            uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2607            MODE_uint_t rY, bytes_to_write;
2608            unsigned char *page;
2609            int partial = 0;
2610    
2611            page = cpu->cd.mips.host_store[rX >> 12];
2612    
2613            /*  Fallback:  */
2614            if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2615                    instr(addiu)(cpu, ic);
2616                    return;
2617            }
2618    
2619            if (rYp == (uint64_t *) ic->arg[0])
2620                    rYp = (uint64_t *) ic[1].arg[1];
2621    
2622            rY = reg(rYp);
2623    
2624            bytes_to_write = rY - rX;
2625            if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2626                    bytes_to_write = 0x1000 - (rX & 0xfff);
2627                    partial = 1;
2628            }
2629    
2630            /*  printf("rX = %08x\n", (int)rX);
2631                printf("rY = %08x\n", (int)rY);
2632                printf("rZ = %08x\n", (int)rZ);
2633                printf("%i bytes\n", (int)bytes_to_write);  */
2634    
2635            memset(page + (rX & 0xfff), 0, bytes_to_write);
2636    
2637            reg(ic->arg[0]) = rX + bytes_to_write;
2638    
2639            cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2640            cpu->cd.mips.next_ic = partial?
2641                (struct mips_instr_call *) &ic[0] :
2642                (struct mips_instr_call *) &ic[3];
2643    }
2644    
2645    
2646    #ifdef MODE32
2647    /*  multi_{l,s}w_2, _3, etc.  */
2648    #include "tmp_mips_loadstore_multi.c"
2649    #endif
2650    
2651    
2652    /*
2653     *  multi_addu_3:
2654     */
2655    X(multi_addu_3)
2656    {
2657            /*  Fallback:  */
2658            if (cpu->delay_slot) {
2659                    instr(addu)(cpu, ic);
2660                    return;
2661            }
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;
2667            cpu->cd.mips.next_ic += 2;
2668    }
2669    
2670    
2671    /*
2672     *  netbsd_r3k_picache_do_inv:
2673     *
2674     *  ic[0]       mtc0    rV,status
2675     *     1        nop
2676     *     2        nop
2677     *     3  s:    addiu   rX,rX,4
2678     *     4        bne     rY,rX,s
2679     *     5        sb      zr,-4(rX)
2680     *     6        nop
2681     *     7        nop
2682     *     8        mtc0    rT,status
2683     */
2684    X(netbsd_r3k_picache_do_inv)
2685    {
2686            MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
2687    
2688            /*  Fallback if the environment isn't exactly right:  */
2689            if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
2690                (rx & 3) || (ry & 3) || cpu->delay_slot) {
2691                    instr(mtc0)(cpu, ic);
2692                    return;
2693            }
2694    
2695            reg(ic[3].arg[0]) = ry;
2696            cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
2697    
2698            /*  Run the last mtc0 instruction:  */
2699            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
2700    }
2701    
2702    
2703    #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():
2773     *
2774     *      lb      rV,0(rX)
2775     *   s: addiu   rX,rX,1
2776     *      bne     zr,rV,s
2777     *      nop
2778     */
2779    X(netbsd_strlen)
2780    {
2781            MODE_uint_t rx = reg(ic[0].arg[1]);
2782            MODE_int_t rv;
2783            signed char *page;
2784            uint32_t pageindex = rx >> 12;
2785            int i;
2786    
2787            page = (signed char *) cpu->cd.mips.host_load[pageindex];
2788    
2789            /*  Fallback:  */
2790            if (cpu->delay_slot || page == NULL) {
2791                    /*
2792                     *  Normal lb:  NOTE: It doesn't matter whether [1] or
2793                     *  [16+1] is called here, because endianness for 8-bit
2794                     *  loads is irrelevant. :-)
2795                     */
2796                    mips32_loadstore[1](cpu, ic);
2797                    return;
2798            }
2799    
2800            i = rx & 0xfff;
2801    
2802            /*
2803             *  TODO: This loop can be optimized further for optimal
2804             *  performance on the host, e.g. by reading full words...
2805             */
2806            do {
2807                    rv = page[i ++];
2808            } while (i < 0x1000 && rv != 0);
2809    
2810            cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
2811    
2812            reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
2813            reg(ic[2].arg[0]) = rv;
2814    
2815            /*  Done with the loop? Or continue on the next rx page?  */
2816            if (rv == 0)
2817                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
2818            else
2819                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
2820    }
2821    #endif
2822    
2823    
2824    /*
2825     *  addiu_bne_samepage_addiu:
2826     */
2827    X(addiu_bne_samepage_addiu)
2828    {
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(andi_sll)
2874    {
2875            /*  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 ++;
2924            cpu->cd.mips.next_ic ++;
2925    }
2926    
2927    
2928    /*
2929   *  b_samepage_addiu:   *  b_samepage_addiu:
2930   *   *
2931   *  Combination of branch within the same page, followed by addiu.   *  Combination of branch within the same page, followed by addiu.
# Line 2398  X(end_of_page2) Line 3031  X(end_of_page2)
3031    
3032    
3033  /*  /*
3034   *  Combine: [Conditional] branch, followed by addiu.   *  Combine:  Memory fill loop (addiu, bne, sw)
3035     *
3036     *  s:  addiu   rX,rX,4
3037     *      bne     rY,rX,s
3038     *      sw      rZ,-4(rX)
3039   */   */
3040  void COMBINE(b_addiu)(struct cpu *cpu, struct mips_instr_call *ic,  void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3041    {
3042            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3043                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3044    
3045            /*  Only for 32-bit virtual address translation so far.  */
3046            if (!cpu->is_32bit)
3047                    return;
3048    
3049            if (n_back < 2)
3050                    return;
3051    
3052            if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
3053                (int32_t)ic[-2].arg[2] == 4 &&
3054                ic[-1].f == instr(bne_samepage) &&
3055                (ic[-1].arg[0] == ic[-2].arg[0] ||
3056                    ic[-1].arg[1] == ic[-2].arg[0]) &&
3057                ic[-1].arg[0] != ic[-1].arg[1] &&
3058                ic[-1].arg[2] == (size_t) &ic[-2] &&
3059                ic[0].arg[0] != ic[0].arg[1] &&
3060                ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3061                    ic[-2].f = instr(sw_loop);
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
3070     *
3071     *      sw      r?,???(rX)
3072     *      sw      r?,???(rX)
3073     *      sw      r?,???(rX)
3074     *      ...
3075     */
3076    void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
3077          int low_addr)          int low_addr)
3078  {  {
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            if (n_back < 3)
3083                    return;
3084    
3085            /*  Convert a multi_sw_3 to a multi_sw_4:  */
3086            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            /*  Convert a multi_sw_2 to a multi_sw_3:  */
3096            if ((ic[-2].f == instr(multi_sw_2_be) ||
3097                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;
3133    
3134            /*  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] &&
3149                ic[-1].arg[0] != ic[0].arg[1]) {
3150                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3151                            ic[-2].f = instr(multi_lw_3_le);
3152                    else
3153                            ic[-2].f = instr(multi_lw_3_be);
3154            }
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    /*
3170     *  Combine:  NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
3171     *
3172     *  Instruction cache loop:
3173     *
3174     *  ic[-8]      mtc0    rV,status
3175     *     -7       nop
3176     *     -6       nop
3177     *     -5  s:   addiu   rX,rX,4
3178     *     -4       bne     rY,rX,s
3179     *     -3       sb      zr,-4(rX)
3180     *     -2       nop
3181     *     -1       nop
3182     *      0       mtc0    rT,status
3183     */
3184    void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
3185            struct mips_instr_call *ic, int low_addr)
3186    {
3187            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3188                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3189    
3190            if (n_back < 8)
3191                    return;
3192    
3193            if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
3194                ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
3195                ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
3196                (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
3197                ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
3198                ic[-4].arg[2] == (size_t) &ic[-5] &&
3199                ic[-3].arg[1] == ic[-5].arg[0] &&
3200                ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3201                    ic[-8].f = instr(netbsd_r3k_picache_do_inv);
3202            }
3203    }
3204    
3205    
3206    /*
3207     *  Combine: something ending with a nop.
3208     *
3209     *      NetBSD's strlen core.
3210     *      [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)
3215    {
3216            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3217                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3218    
3219            if (n_back < 8)
3220                    return;
3221    
3222    #ifdef MODE32
3223            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;
3253            }
3254    
3255            if ((ic[-3].f == mips32_loadstore[1] ||
3256                ic[-3].f == mips32_loadstore[16 + 1]) &&
3257                ic[-3].arg[2] == 0 &&
3258                ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
3259                ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
3260                ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
3261                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3262                ic[-1].f == instr(bne_samepage)) {
3263                    ic[-3].f = instr(netbsd_strlen);
3264                    return;
3265            }
3266    #endif
3267    
3268            if (ic[-1].f == instr(bne_samepage)) {
3269                    ic[-1].f = instr(bne_samepage_nop);
3270                    return;
3271            }
3272    
3273            if (ic[-1].f == instr(beq_samepage)) {
3274                    ic[-1].f = instr(beq_samepage_nop);
3275                    return;
3276            }
3277    
3278            /*  TODO: other branches that are followed by nop should be here  */
3279    }
3280    
3281    
3282    /*
3283     *  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)          if (n_back < 1)
3317                  return;                  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.
3353     */
3354    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)
3357                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3358    
3359            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;
3366            }
3367    
3368            if (ic[-1].f == instr(set)) {
3369                    ic[-1].f = instr(lui_addiu);
3370                    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);
3375                  combined;                  return;
3376            }
3377    
3378            if (ic[-1].f == instr(beq_samepage)) {
3379                    ic[-1].f = instr(beq_samepage_addiu);
3380                    return;
3381            }
3382    
3383            if (ic[-1].f == instr(bne_samepage)) {
3384                    ic[-1].f = instr(bne_samepage_addiu);
3385                    return;
3386            }
3387    
3388            if (ic[-1].f == instr(jr_ra)) {
3389                    ic[-1].f = instr(jr_ra_addiu);
3390                    return;
3391          }          }
3392    
3393          /*  TODO: other branches that are followed by addiu should be here  */          /*  TODO: other branches that are followed by addiu should be here  */
# Line 2432  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 2456  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 2537  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 2589  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 2712  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 2720  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 2739  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 2748  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 2763  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 2841  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 2879  X(to_be_translated) Line 3889  X(to_be_translated)
3889                  case HI6_XORI:    ic->f = instr(xori); break;                  case HI6_XORI:    ic->f = instr(xori); break;
3890                  }                  }
3891    
3892                    if (ic->arg[2] == 0) {
3893                            if ((cpu->is_32bit && ic->f == instr(addiu)) ||
3894                                (!cpu->is_32bit && ic->f == instr(daddiu))) {
3895                                    ic->f = instr(mov);
3896                                    ic->arg[2] = ic->arg[1];
3897                            }
3898                    }
3899    
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(b_addiu);                          cpu->cd.mips.combination_check = COMBINE(addiu);
3907                  if (ic->f == instr(daddiu))                  if (ic->f == instr(daddiu))
3908                          cpu->cd.mips.combination_check = COMBINE(b_daddiu);                          cpu->cd.mips.combination_check = COMBINE(b_daddiu);
3909                  break;                  break;
# Line 2892  X(to_be_translated) Line 3912  X(to_be_translated)
3912                  ic->f = instr(set);                  ic->f = instr(set);
3913                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3914                  ic->arg[1] = (int32_t) (imm << 16);                  ic->arg[1] = (int32_t) (imm << 16);
3915                    /*  NOTE: Don't use arg[2] here. It can be used with
3916                        instruction combinations, to do lui + addiu, etc.  */
3917                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
3918                          ic->f = instr(nop);                          ic->f = instr(nop);
3919                  break;                  break;
# Line 2901  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 2912  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 2945  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 2964  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 2987  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 2996  X(to_be_translated) Line 4062  X(to_be_translated)
4062                          ic->arg[1] = rd + ((iword & 7) << 5);                          ic->arg[1] = rd + ((iword & 7) << 5);
4063                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
4064                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
4065    
4066                            if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
4067                                rs == COPz_MTCz && rd == COP0_STATUS)
4068                                    cpu->cd.mips.combination_check =
4069                                        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 3033  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 3066  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 3079  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 3262  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 3313  X(to_be_translated) Line 4449  X(to_be_translated)
4449                  /*  Load into the dummy scratch register, if rt = zero  */                  /*  Load into the dummy scratch register, if rt = zero  */
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 loads or stores in a row using the same
4454                        base register:  */
4455    #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);
4460    #endif
4461                  break;                  break;
4462    
4463          case HI6_LL:          case HI6_LL:
# Line 3337  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 3407  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 on a"                                  fatal("[ WARNING! SPECIAL3 opcode used, but"
4587                                      " cpu which doesn't implement it ]\n");                                      " the %s processor does not implement "
4588                                        "such instructions. Only printing this "
4589                                        "warning once. ]\n",
4590                                        cpu->cd.mips.cpu_type.name);
4591                                  warning = 1;                                  warning = 1;
4592                          }                          }
4593                          ic->f = instr(reserved);                          ic->f = instr(reserved);
# Line 3442  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 3452  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 3470  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    

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

  ViewVC Help
Powered by ViewVC 1.1.26