/[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 26 by dpavlin, Mon Oct 8 16:20:10 2007 UTC revision 40 by dpavlin, Mon Oct 8 16:22:11 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.87 2006/06/25 02:46:08 debug Exp $   *  $Id: cpu_mips_instr.c,v 1.127 2007/04/28 09:19:51 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    /*
1152     *  ext:  Extract bitfield.
1153     *
1154     *  arg[0] = pointer to rt
1155     *  arg[1] = pointer to rs
1156     *  arg[2] = (msbd << 5) + lsb
1157     */
1158    X(ext)
1159    {
1160            fatal("ext: todo\n");
1161            exit(1);
1162    }
1163    
1164    
1165  /*  TODO: fix  */  /*
1166  cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);   *  dsbh:  Doubleword swap bytes within half-word
1167  cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);   *  dshd:  Doubleword swap half-words within double-word
1168  /* cpu_create_or_reset_tc(cpu); */   *  wsbh:  Word swap bytes within half-word
1169     *  seb:   Sign-extend byte
1170     *  seh:   Sign-extend half-word
1171     *
1172     *  arg[0] = pointer to rt
1173     *  arg[1] = pointer to rd
1174     */
1175    X(dsbh)
1176    {
1177            uint64_t x = reg(ic->arg[0]);
1178            x = ((x & 0x00ff00ff00ff00ffULL) << 8)
1179              | ((x & 0xff00ff00ff00ff00ULL) >> 8);
1180            reg(ic->arg[1]) = x;
1181    }
1182    X(dshd)
1183    {
1184            uint64_t x = reg(ic->arg[0]);
1185            x = ((x & 0x000000000000ffffULL) << 48)
1186              | ((x & 0x00000000ffff0000ULL) << 16)
1187              | ((x & 0x0000ffff00000000ULL) >> 16)
1188              | ((x & 0xffff000000000000ULL) >> 48);
1189            reg(ic->arg[1]) = x;
1190    }
1191    X(wsbh)
1192    {
1193            uint32_t x = reg(ic->arg[0]);
1194            x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
1195            reg(ic->arg[1]) = (int32_t) x;
1196  }  }
1197    X(seb) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); }
1198    X(seh) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); }
1199    
1200    
1201  /*  /*
# Line 1049  X(div) Line 1224  X(div)
1224                  res = 0, rem = a;                  res = 0, rem = a;
1225          else          else
1226                  res = a / b, rem = a - b*res;                  res = a / b, rem = a - b*res;
1227          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1228          reg(&cpu->cd.mips.hi) = (int32_t)rem;          cpu->cd.mips.hi = (int32_t)rem;
1229  }  }
1230  X(divu)  X(divu)
1231  {  {
# Line 1060  X(divu) Line 1235  X(divu)
1235                  res = 0, rem = a;                  res = 0, rem = a;
1236          else          else
1237                  res = a / b, rem = a - b*res;                  res = a / b, rem = a - b*res;
1238          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1239          reg(&cpu->cd.mips.hi) = (int32_t)rem;          cpu->cd.mips.hi = (int32_t)rem;
1240  }  }
1241  X(ddiv)  X(ddiv)
1242  {  {
# Line 1072  X(ddiv) Line 1247  X(ddiv)
1247          else          else
1248                  res = a / b;                  res = a / b;
1249          rem = a - b*res;          rem = a - b*res;
1250          reg(&cpu->cd.mips.lo) = res;          cpu->cd.mips.lo = res;
1251          reg(&cpu->cd.mips.hi) = rem;          cpu->cd.mips.hi = rem;
1252  }  }
1253  X(ddivu)  X(ddivu)
1254  {  {
# Line 1084  X(ddivu) Line 1259  X(ddivu)
1259          else          else
1260                  res = a / b;                  res = a / b;
1261          rem = a - b*res;          rem = a - b*res;
1262          reg(&cpu->cd.mips.lo) = res;          cpu->cd.mips.lo = res;
1263          reg(&cpu->cd.mips.hi) = rem;          cpu->cd.mips.hi = rem;
1264  }  }
1265  X(mult)  X(mult)
1266  {  {
1267          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1268          int64_t res = (int64_t)a * (int64_t)b;          int64_t res = (int64_t)a * (int64_t)b;
1269          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1270          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1271  }  }
1272  X(mult_r5900)  X(mult_r5900)
1273  {  {
# Line 1100  X(mult_r5900) Line 1275  X(mult_r5900)
1275              hi, lo, and a third register  */              hi, lo, and a third register  */
1276          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1277          int64_t res = (int64_t)a * (int64_t)b;          int64_t res = (int64_t)a * (int64_t)b;
1278          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1279          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1280          reg(ic->arg[2]) = (int32_t)res;          reg(ic->arg[2]) = (int32_t)res;
1281  }  }
1282  X(multu)  X(multu)
1283  {  {
1284          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1285          uint64_t res = (uint64_t)a * (uint64_t)b;          uint64_t res = (uint64_t)a * (uint64_t)b;
1286          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1287          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1288  }  }
1289  X(multu_r5900)  X(multu_r5900)
1290  {  {
# Line 1117  X(multu_r5900) Line 1292  X(multu_r5900)
1292              hi, lo, and a third register  */              hi, lo, and a third register  */
1293          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);          uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1294          uint64_t res = (uint64_t)a * (uint64_t)b;          uint64_t res = (uint64_t)a * (uint64_t)b;
1295          reg(&cpu->cd.mips.lo) = (int32_t)res;          cpu->cd.mips.lo = (int32_t)res;
1296          reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);          cpu->cd.mips.hi = (int32_t)(res >> 32);
1297          reg(ic->arg[2]) = (int32_t)res;          reg(ic->arg[2]) = (int32_t)res;
1298  }  }
1299  X(dmult)  X(dmult)
# Line 1147  X(dmult) Line 1322  X(dmult)
1322                  hi ^= (int64_t) -1;                  hi ^= (int64_t) -1;
1323                  lo ^= (int64_t) -1;                  lo ^= (int64_t) -1;
1324          }          }
1325          reg(&cpu->cd.mips.lo) = lo;          cpu->cd.mips.lo = lo;
1326          reg(&cpu->cd.mips.hi) = hi;          cpu->cd.mips.hi = hi;
1327  }  }
1328  X(dmultu)  X(dmultu)
1329  {  {
# Line 1164  X(dmultu) Line 1339  X(dmultu)
1339                  }                  }
1340                  c = (c << 1) | (b >> 63); b <<= 1;                  c = (c << 1) | (b >> 63); b <<= 1;
1341          }          }
1342          reg(&cpu->cd.mips.lo) = lo;          cpu->cd.mips.lo = lo;
1343          reg(&cpu->cd.mips.hi) = hi;          cpu->cd.mips.hi = hi;
1344  }  }
1345  X(tge)  X(tge)
1346  {  {
# Line 1574  X(sltiu) Line 1749  X(sltiu)
1749    
1750  /*  /*
1751   *  set:  Set a register to an immediate (signed) 32-bit value.   *  set:  Set a register to an immediate (signed) 32-bit value.
1752     *        (This is the actual implementation of the lui instruction.)
1753   *   *
1754   *  arg[0] = pointer to the register   *  arg[0] = pointer to the register
1755   *  arg[1] = (int32_t) immediate value   *  arg[1] = (int32_t) immediate value
# Line 1612  X(mfc0) Line 1788  X(mfc0)
1788          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);
1789          reg(ic->arg[0]) = (int32_t)tmp;          reg(ic->arg[0]) = (int32_t)tmp;
1790  }  }
1791    X(mfc0_select0)
1792    {
1793            /*  Fast int32_t read, with no side effects:  */
1794            int rd = ic->arg[1] & 31;
1795    #if 0
1796            uint64_t tmp;
1797            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1798            cpu->pc |= ic->arg[2];
1799            /*  TODO: cause exception if necessary  */
1800    #endif
1801            reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->reg[rd];
1802    }
1803  X(mtc0)  X(mtc0)
1804  {  {
1805          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
# Line 1632  X(mtc0) Line 1820  X(mtc0)
1820                  uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];                  uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1821                  /*  NOTE: STATUS_IE happens to match the enable bit also                  /*  NOTE: STATUS_IE happens to match the enable bit also
1822                      on R2000/R3000, so this is ok.  */                      on R2000/R3000, so this is ok.  */
1823                  if (status & (STATUS_EXL | STATUS_ERL))                  if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1824                          status &= ~STATUS_IE;                          if (status & (STATUS_EXL | STATUS_ERL))
1825                                    status &= ~STATUS_IE;
1826                    }
1827                  /*  Ugly R5900 special case:  (TODO: move this?)  */                  /*  Ugly R5900 special case:  (TODO: move this?)  */
1828                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1829                      !(status & R5900_STATUS_EIE))                      !(status & R5900_STATUS_EIE))
# Line 1653  X(dmfc0) Line 1843  X(dmfc0)
1843          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,          coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1844              (uint64_t *)ic->arg[0], select);              (uint64_t *)ic->arg[0], select);
1845  }  }
1846    X(dmfc0_select0)
1847    {
1848            /*  Fast int64_t read, with no side effects:  */
1849            int rd = ic->arg[1] & 31;
1850    #if 0
1851            uint64_t tmp;
1852            cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1853            cpu->pc |= ic->arg[2];
1854            /*  TODO: cause exception if necessary  */
1855    #endif
1856            reg(ic->arg[0]) = cpu->cd.mips.coproc[0]->reg[rd];
1857    }
1858  X(dmtc0)  X(dmtc0)
1859  {  {
1860          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;          int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
# Line 1674  X(dmtc0) Line 1876  X(dmtc0)
1876  X(cop1_bc)  X(cop1_bc)
1877  {  {
1878          MODE_int_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
1879          const int cpnr = 1;          int x, cc = ic->arg[0];
         int x, low_pc, cc = ic->arg[0];  
1880    
1881          low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)          COPROC_AVAILABILITY_CHECK(1);
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
1882    
1883          /*  Get the correct condition code bit:  */          /*  Get the correct condition code bit:  */
1884          if (cc == 0)          if (cc == 0)
# Line 1725  X(cop1_bc) Line 1918  X(cop1_bc)
1918   */   */
1919  X(cop1_slow)  X(cop1_slow)
1920  {  {
1921          const int cpnr = 1;          COPROC_AVAILABILITY_CHECK(1);
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
1922    
1923          coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);          coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1924  }  }
# Line 1760  X(break) Line 1943  X(break)
1943          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1944          mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);          mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1945  }  }
1946    X(reboot)
1947    {
1948            if (!cop0_availability_check(cpu, ic))
1949                    return;
1950    
1951            cpu->running = 0;
1952            debugger_n_steps_left_before_interaction = 0;
1953            cpu->cd.mips.next_ic = &nothing_call;
1954    }
1955    
1956    
1957  /*  /*
# Line 1818  X(promemul) Line 2010  X(promemul)
2010   */   */
2011  X(tlbw)  X(tlbw)
2012  {  {
2013            if (!cop0_availability_check(cpu, ic))
2014                    return;
2015    
2016          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2017          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
2018          coproc_tlbwri(cpu, ic->arg[0]);          coproc_tlbwri(cpu, ic->arg[0]);
# Line 1832  X(tlbw) Line 2027  X(tlbw)
2027   */   */
2028  X(tlbp)  X(tlbp)
2029  {  {
2030            if (!cop0_availability_check(cpu, ic))
2031                    return;
2032    
2033          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2034          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
2035          coproc_tlbpr(cpu, 0);          coproc_tlbpr(cpu, 0);
2036  }  }
2037  X(tlbr)  X(tlbr)
2038  {  {
2039            if (!cop0_availability_check(cpu, ic))
2040                    return;
2041    
2042          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2043          cpu->pc |= ic->arg[2];          cpu->pc |= ic->arg[2];
2044          coproc_tlbpr(cpu, 1);          coproc_tlbpr(cpu, 1);
# Line 1849  X(tlbr) Line 2050  X(tlbr)
2050   */   */
2051  X(rfe)  X(rfe)
2052  {  {
2053          coproc_rfe(cpu);          if (!cop0_availability_check(cpu, ic))
2054                    return;
2055    
2056            /*  Just rotate the interrupt/user bits:  */
2057            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2058                (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
2059                ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
2060    
2061          /*  Note: no pc to pointers conversion is necessary here.  */          /*
2062             *  Note: no pc to pointers conversion is necessary here. Usually the
2063             *  rfe instruction resides in the delay slot of a jr k0/k1, and
2064             *  it is up to that instruction to do the pointer conversion.
2065             */
2066  }  }
2067    
2068    
2069  /*  /*
2070   *  eret: Return from exception handler   *  eret: Return from exception handler (non-R3000 style)
2071   */   */
2072  X(eret)  X(eret)
2073  {  {
2074          coproc_eret(cpu);          if (!cop0_availability_check(cpu, ic))
2075                    return;
2076    
2077            if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2078                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2079                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
2080            } else {
2081                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
2082                    cpu->delay_slot = 0;            
2083                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2084            }
2085    
2086          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
2087    
2088            cpu->cd.mips.rmw = 0;   /*  the "LL bit"  */
2089  }  }
2090    
2091    
# Line 1870  X(eret) Line 2094  X(eret)
2094   */   */
2095  X(deret)  X(deret)
2096  {  {
2097            if (!cop0_availability_check(cpu, ic))
2098                    return;
2099    
2100          /*          /*
2101           *  According to the MIPS64 manual, deret loads PC from the DEPC cop0           *  According to the MIPS64 manual, deret loads PC from the DEPC cop0
2102           *  register, and jumps there immediately. No delay slot.           *  register, and jumps there immediately. No delay slot.
# Line 1888  X(deret) Line 2115  X(deret)
2115    
2116    
2117  /*  /*
2118     *  idle:  Called from the implementation of wait, or netbsd_pmax_idle.
2119     */
2120    X(idle)
2121    {
2122            /*
2123             *  If there is an interrupt, then just return. Otherwise
2124             *  re-run the wait instruction (after a delay).
2125             */
2126            uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2127            uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
2128    
2129            if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2130                    if (status & (STATUS_EXL | STATUS_ERL))
2131                            status &= ~STATUS_IE;
2132            }
2133    
2134            /*  Ugly R5900 special case:  (TODO: move this?)  */
2135            if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
2136                !(status & R5900_STATUS_EIE))
2137                    status &= ~STATUS_IE;
2138            if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
2139                    return;
2140    
2141            cpu->cd.mips.next_ic = ic;
2142            cpu->is_halted = 1;
2143            cpu->has_been_idling = 1;
2144    
2145            /*
2146             *  There was no interrupt. Go to sleep.
2147             *
2148             *  TODO:
2149             *
2150             *  Think about how to actually implement this usleep stuff,
2151             *  in an SMP and/or timing accurate environment.
2152             */
2153    
2154            if (cpu->machine->ncpus == 1) {
2155                    static int x = 0;
2156                    if ((++x) == 600) {
2157                            usleep(10);
2158                            x = 0;
2159                    }
2160                    cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2161            }
2162    }
2163    
2164    
2165    /*
2166     *  wait: Wait for external interrupt.
2167     */
2168    X(wait)
2169    {
2170            if (!cop0_availability_check(cpu, ic))
2171                    return;
2172    
2173            instr(idle)(cpu, ic);
2174    }
2175    
2176    
2177    /*
2178   *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).   *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2179   *   *
2180   *  arg[0] = ptr to rt (destination register)   *  arg[0] = ptr to rt (destination register)
# Line 1996  X(lld) Line 2283  X(lld)
2283  }  }
2284  X(sc)  X(sc)
2285  {  {
2286          MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];          MODE_uint_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2287          uint64_t r = reg(ic->arg[0]);          uint64_t r = reg(ic->arg[0]);
2288          int low_pc, i;          int low_pc, i;
2289          uint8_t word[sizeof(uint32_t)];          uint8_t word[sizeof(uint32_t)];
# Line 2054  X(sc) Line 2341  X(sc)
2341  }  }
2342  X(scd)  X(scd)
2343  {  {
2344          MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];          MODE_uint_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2345          uint64_t r = reg(ic->arg[0]);          uint64_t r = reg(ic->arg[0]);
2346          int low_pc, i;          int low_pc, i;
2347          uint8_t word[sizeof(uint64_t)];          uint8_t word[sizeof(uint64_t)];
# Line 2124  X(scd) Line 2411  X(scd)
2411   */   */
2412  X(lwc1)  X(lwc1)
2413  {  {
2414          const int cpnr = 1;          COPROC_AVAILABILITY_CHECK(1);
   
         /*  Synch. PC and call the generic load/store function:  */  
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)  
             << MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         /*  ... but first, let's see if the coprocessor is available:  */  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
2415    
2416  #ifdef MODE32  #ifdef MODE32
2417          mips32_loadstore          mips32_loadstore
# Line 2150  X(lwc1) Line 2423  X(lwc1)
2423  }  }
2424  X(swc1)  X(swc1)
2425  {  {
2426          const int cpnr = 1;          COPROC_AVAILABILITY_CHECK(1);
   
         /*  Synch. PC and call the generic load/store function:  */  
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)  
             << MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         /*  ... but first, let's see if the coprocessor is available:  */  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
2427    
2428  #ifdef MODE32  #ifdef MODE32
2429          mips32_loadstore          mips32_loadstore
# Line 2176  X(swc1) Line 2435  X(swc1)
2435  }  }
2436  X(ldc1)  X(ldc1)
2437  {  {
         const int cpnr = 1;  
2438          int use_fp_pairs =          int use_fp_pairs =
2439              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2440          uint64_t fpr, *backup_ptr;          uint64_t fpr, *backup_ptr;
2441    
2442          /*  Synch. PC and call the generic load/store function:  */          COPROC_AVAILABILITY_CHECK(1);
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)  
             << MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         /*  ... but first, let's see if the coprocessor is available:  */  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
2443    
2444          backup_ptr = (uint64_t *) ic->arg[0];          backup_ptr = (uint64_t *) ic->arg[0];
2445          ic->arg[0] = (size_t) &fpr;          ic->arg[0] = (size_t) &fpr;
# Line 2217  X(ldc1) Line 2463  X(ldc1)
2463  }  }
2464  X(sdc1)  X(sdc1)
2465  {  {
         const int cpnr = 1;  
2466          int use_fp_pairs =          int use_fp_pairs =
2467              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2468          uint64_t fpr, *backup_ptr;          uint64_t fpr, *backup_ptr;
2469    
2470          /*  Synch. PC and call the generic load/store function:  */          COPROC_AVAILABILITY_CHECK(1);
         int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)  
             / sizeof(struct mips_instr_call);  
         cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)  
             << MIPS_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);  
   
         /*  ... but first, let's see if the coprocessor is available:  */  
         if (!(cpu->cd.mips.coproc[0]->  
             reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {  
                 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);  
                 return;  
         }  
2471    
2472          backup_ptr = (uint64_t *) ic->arg[0];          backup_ptr = (uint64_t *) ic->arg[0];
2473          ic->arg[0] = (size_t) &fpr;          ic->arg[0] = (size_t) &fpr;
# Line 2285  X(sdr) { mips_unaligned_loadstore(cpu, i Line 2518  X(sdr) { mips_unaligned_loadstore(cpu, i
2518   */   */
2519  X(di_r5900)  X(di_r5900)
2520  {  {
2521            if (!cop0_availability_check(cpu, ic))
2522                    return;
2523    
2524          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2525  }  }
2526  X(ei_r5900)  X(ei_r5900)
2527  {  {
2528            if (!cop0_availability_check(cpu, ic))
2529                    return;
2530    
2531          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;          cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2532  }  }
2533    
# Line 2297  X(ei_r5900) Line 2536  X(ei_r5900)
2536    
2537    
2538  /*  /*
2539     *  sw_loop:
2540     *
2541     *  s:  addiu   rX,rX,4                 rX = arg[0] and arg[1]
2542     *      bne     rY,rX,s  (or rX,rY,s)   rt=arg[1], rs=arg[0]
2543     *      sw      rZ,-4(rX)               rt=arg[0], rs=arg[1]
2544     */
2545    X(sw_loop)
2546    {
2547            MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2548            uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2549            MODE_uint_t rY, bytes_to_write;
2550            unsigned char *page;
2551            int partial = 0;
2552    
2553            page = cpu->cd.mips.host_store[rX >> 12];
2554    
2555            /*  Fallback:  */
2556            if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2557                    instr(addiu)(cpu, ic);
2558                    return;
2559            }
2560    
2561            if (rYp == (uint64_t *) ic->arg[0])
2562                    rYp = (uint64_t *) ic[1].arg[1];
2563    
2564            rY = reg(rYp);
2565    
2566            bytes_to_write = rY - rX;
2567            if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2568                    bytes_to_write = 0x1000 - (rX & 0xfff);
2569                    partial = 1;
2570            }
2571    
2572            /*  printf("rX = %08x\n", (int)rX);
2573                printf("rY = %08x\n", (int)rY);
2574                printf("rZ = %08x\n", (int)rZ);
2575                printf("%i bytes\n", (int)bytes_to_write);  */
2576    
2577            memset(page + (rX & 0xfff), 0, bytes_to_write);
2578    
2579            reg(ic->arg[0]) = rX + bytes_to_write;
2580    
2581            cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2582            cpu->cd.mips.next_ic = partial?
2583                (struct mips_instr_call *) &ic[0] :
2584                (struct mips_instr_call *) &ic[3];
2585    }
2586    
2587    
2588    #ifdef MODE32
2589    /*  multi_{l,s}w_2, _3, etc.  */
2590    #include "tmp_mips_loadstore_multi.c"
2591    #endif
2592    
2593    
2594    /*
2595     *  multi_addu_3:
2596     */
2597    X(multi_addu_3)
2598    {
2599            /*  Fallback:  */
2600            if (cpu->delay_slot) {
2601                    instr(addu)(cpu, ic);
2602                    return;
2603            }
2604    
2605            reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
2606            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
2607            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
2608            cpu->n_translated_instrs += 2;
2609            cpu->cd.mips.next_ic += 2;
2610    }
2611    
2612    
2613    /*
2614     *  netbsd_r3k_picache_do_inv:
2615     *
2616     *  ic[0]       mtc0    rV,status
2617     *     1        nop
2618     *     2        nop
2619     *     3  s:    addiu   rX,rX,4
2620     *     4        bne     rY,rX,s
2621     *     5        sb      zr,-4(rX)
2622     *     6        nop
2623     *     7        nop
2624     *     8        mtc0    rT,status
2625     */
2626    X(netbsd_r3k_picache_do_inv)
2627    {
2628            MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
2629    
2630            /*  Fallback if the environment isn't exactly right:  */
2631            if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
2632                (rx & 3) || (ry & 3) || cpu->delay_slot) {
2633                    instr(mtc0)(cpu, ic);
2634                    return;
2635            }
2636    
2637            reg(ic[3].arg[0]) = ry;
2638            cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
2639    
2640            /*  Run the last mtc0 instruction:  */
2641            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
2642    }
2643    
2644    
2645    #ifdef MODE32
2646    /*
2647     *  netbsd_pmax_idle():
2648     *
2649     *  s:  lui     rX, hi
2650     *      lw      rY, lo(rX)
2651     *      nop
2652     *      beq     zr, rY, s
2653     *      nop
2654     */
2655    X(netbsd_pmax_idle)
2656    {
2657            uint32_t addr, pageindex, i;
2658            int32_t *page;
2659    
2660            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2661    
2662            addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
2663            pageindex = addr >> 12;
2664            i = (addr & 0xfff) >> 2;
2665            page = (int32_t *) cpu->cd.mips.host_load[pageindex];
2666    
2667            /*  Fallback:  */
2668            if (cpu->delay_slot || page == NULL || page[i] != 0)
2669                    return;
2670    
2671            instr(idle)(cpu, ic);
2672    }
2673    
2674    
2675    /*
2676     *  linux_pmax_idle():
2677     *
2678     *  s:  lui     rX, hi
2679     *      lw      rX, lo(rX)
2680     *      nop
2681     *      bne     zr, rX, ...
2682     *      nop
2683     *      lw      rX, ofs(gp)
2684     *      nop
2685     *      beq     zr, rX, s
2686     *      nop
2687     */
2688    X(linux_pmax_idle)
2689    {
2690            uint32_t addr, addr2, pageindex, pageindex2, i, i2;
2691            int32_t *page, *page2;
2692    
2693            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2694    
2695            addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
2696            pageindex = addr >> 12;
2697            i = (addr & 0xfff) >> 2;
2698            page = (int32_t *) cpu->cd.mips.host_load[pageindex];
2699    
2700            addr2 = reg(ic[5].arg[1]) + (int32_t)ic[5].arg[2];
2701            pageindex2 = addr2 >> 12;
2702            i2 = (addr2 & 0xfff) >> 2;
2703            page2 = (int32_t *) cpu->cd.mips.host_load[pageindex2];
2704    
2705            /*  Fallback:  */
2706            if (cpu->delay_slot || page == NULL || page[i] != 0 || page2[i2] != 0)
2707                    return;
2708    
2709            instr(idle)(cpu, ic);
2710    }
2711    
2712    
2713    /*
2714     *  netbsd_strlen():
2715     *
2716     *      lb      rV,0(rX)
2717     *   s: addiu   rX,rX,1
2718     *      bne     zr,rV,s
2719     *      nop
2720     */
2721    X(netbsd_strlen)
2722    {
2723            MODE_uint_t rx = reg(ic[0].arg[1]);
2724            MODE_int_t rv;
2725            signed char *page;
2726            uint32_t pageindex = rx >> 12;
2727            int i;
2728    
2729            page = (signed char *) cpu->cd.mips.host_load[pageindex];
2730    
2731            /*  Fallback:  */
2732            if (cpu->delay_slot || page == NULL) {
2733                    /*
2734                     *  Normal lb:  NOTE: It doesn't matter whether [1] or
2735                     *  [16+1] is called here, because endianness for 8-bit
2736                     *  loads is irrelevant. :-)
2737                     */
2738                    mips32_loadstore[1](cpu, ic);
2739                    return;
2740            }
2741    
2742            i = rx & 0xfff;
2743    
2744            /*
2745             *  TODO: This loop can be optimized further for optimal
2746             *  performance on the host, e.g. by reading full words...
2747             */
2748            do {
2749                    rv = page[i ++];
2750            } while (i < 0x1000 && rv != 0);
2751    
2752            cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
2753    
2754            reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
2755            reg(ic[2].arg[0]) = rv;
2756    
2757            /*  Done with the loop? Or continue on the next rx page?  */
2758            if (rv == 0)
2759                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
2760            else
2761                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
2762    }
2763    #endif
2764    
2765    
2766    /*
2767     *  addiu_bne_samepage_addiu:
2768     */
2769    X(addiu_bne_samepage_addiu)
2770    {
2771            MODE_uint_t rs, rt;
2772    
2773            if (cpu->delay_slot) {
2774                    instr(addiu)(cpu, ic);
2775                    return;
2776            }
2777    
2778            cpu->n_translated_instrs += 2;
2779            reg(ic[0].arg[1]) = (int32_t)
2780                ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
2781            rs = reg(ic[1].arg[0]);
2782            rt = reg(ic[1].arg[1]);
2783            reg(ic[2].arg[1]) = (int32_t)
2784                ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
2785            if (rs != rt)
2786                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
2787            else
2788                    cpu->cd.mips.next_ic += 2;
2789    }
2790    
2791    
2792    /*
2793     *  xor_andi_sll:
2794     */
2795    X(xor_andi_sll)
2796    {
2797            /*  Fallback:  */
2798            if (cpu->delay_slot) {
2799                    instr(xor)(cpu, ic);
2800                    return;
2801            }
2802    
2803            reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
2804            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
2805            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
2806    
2807            cpu->n_translated_instrs += 2;
2808            cpu->cd.mips.next_ic += 2;
2809    }
2810    
2811    
2812    /*
2813     *  andi_sll:
2814     */
2815    X(andi_sll)
2816    {
2817            /*  Fallback:  */
2818            if (cpu->delay_slot) {
2819                    instr(andi)(cpu, ic);
2820                    return;
2821            }
2822    
2823            reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
2824            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
2825    
2826            cpu->n_translated_instrs ++;
2827            cpu->cd.mips.next_ic ++;
2828    }
2829    
2830    
2831    /*
2832     *  lui_ori:
2833     */
2834    X(lui_ori)
2835    {
2836            /*  Fallback:  */
2837            if (cpu->delay_slot) {
2838                    instr(set)(cpu, ic);
2839                    return;
2840            }
2841    
2842            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2843            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
2844    
2845            cpu->n_translated_instrs ++;
2846            cpu->cd.mips.next_ic ++;
2847    }
2848    
2849    
2850    /*
2851     *  lui_addiu:
2852     */
2853    X(lui_addiu)
2854    {
2855            /*  Fallback:  */
2856            if (cpu->delay_slot) {
2857                    instr(set)(cpu, ic);
2858                    return;
2859            }
2860    
2861            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2862            reg(ic[1].arg[1]) = (int32_t)
2863                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
2864    
2865            cpu->n_translated_instrs ++;
2866            cpu->cd.mips.next_ic ++;
2867    }
2868    
2869    
2870    /*
2871   *  b_samepage_addiu:   *  b_samepage_addiu:
2872   *   *
2873   *  Combination of branch within the same page, followed by addiu.   *  Combination of branch within the same page, followed by addiu.
# Line 2402  X(end_of_page2) Line 2973  X(end_of_page2)
2973    
2974    
2975  /*  /*
2976   *  Combine: [Conditional] branch, followed by addiu.   *  Combine:  Memory fill loop (addiu, bne, sw)
2977     *
2978     *  s:  addiu   rX,rX,4
2979     *      bne     rY,rX,s
2980     *      sw      rZ,-4(rX)
2981     */
2982    void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2983    {
2984            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2985                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2986    
2987            /*  Only for 32-bit virtual address translation so far.  */
2988            if (!cpu->is_32bit)
2989                    return;
2990    
2991            if (n_back < 2)
2992                    return;
2993    
2994            if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
2995                (int32_t)ic[-2].arg[2] == 4 &&
2996                ic[-1].f == instr(bne_samepage) &&
2997                (ic[-1].arg[0] == ic[-2].arg[0] ||
2998                    ic[-1].arg[1] == ic[-2].arg[0]) &&
2999                ic[-1].arg[0] != ic[-1].arg[1] &&
3000                ic[-1].arg[2] == (size_t) &ic[-2] &&
3001                ic[0].arg[0] != ic[0].arg[1] &&
3002                ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3003                    ic[-2].f = instr(sw_loop);
3004            }
3005    }
3006    
3007    
3008    /*  Only for 32-bit virtual address translation so far.  */
3009    #ifdef MODE32
3010    /*
3011     *  Combine:  Multiple SW in a row using the same base register
3012     *
3013     *      sw      r?,???(rX)
3014     *      sw      r?,???(rX)
3015     *      sw      r?,???(rX)
3016     *      ...
3017     */
3018    void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
3019            int low_addr)
3020    {
3021            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3022                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3023    
3024            if (n_back < 3)
3025                    return;
3026    
3027            /*  Convert a multi_sw_3 to a multi_sw_4:  */
3028            if ((ic[-3].f == instr(multi_sw_3_be) ||
3029                ic[-3].f == instr(multi_sw_3_le)) &&
3030                ic[-3].arg[1] == ic[0].arg[1]) {
3031                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3032                            ic[-3].f = instr(multi_sw_4_le);
3033                    else
3034                            ic[-3].f = instr(multi_sw_4_be);
3035            }
3036    
3037            /*  Convert a multi_sw_2 to a multi_sw_3:  */
3038            if ((ic[-2].f == instr(multi_sw_2_be) ||
3039                ic[-2].f == instr(multi_sw_2_le)) &&
3040                ic[-2].arg[1] == ic[0].arg[1]) {
3041                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3042                            ic[-2].f = instr(multi_sw_3_le);
3043                    else
3044                            ic[-2].f = instr(multi_sw_3_be);
3045            }
3046    
3047            if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3048                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3049                            ic[-1].f = instr(multi_sw_2_le);
3050                    else
3051                            ic[-1].f = instr(multi_sw_2_be);
3052            }
3053    }
3054    #endif
3055    
3056    
3057    /*  Only for 32-bit virtual address translation so far.  */
3058    #ifdef MODE32
3059    /*
3060     *  Combine:  Multiple LW in a row using the same base register
3061     *
3062     *      lw      r?,???(rX)
3063     *      lw      r?,???(rX)
3064     *      lw      r?,???(rX)
3065     *      ...
3066   */   */
3067  void COMBINE(b_addiu)(struct cpu *cpu, struct mips_instr_call *ic,  void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3068          int low_addr)          int low_addr)
3069  {  {
3070          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3071              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3072    
3073            if (n_back < 3)
3074                    return;
3075    
3076            /*  Convert a multi_lw_3 to a multi_lw_4:  */
3077            if ((ic[-3].f == instr(multi_lw_3_be) ||
3078                ic[-3].f == instr(multi_lw_3_le)) &&
3079                ic[-3].arg[1] == ic[0].arg[1] &&
3080                ic[-1].arg[0] != ic[0].arg[1]) {
3081                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3082                            ic[-3].f = instr(multi_lw_4_le);
3083                    else
3084                            ic[-3].f = instr(multi_lw_4_be);
3085            }
3086    
3087            /*  Convert a multi_lw_2 to a multi_lw_3:  */
3088            if ((ic[-2].f == instr(multi_lw_2_be) ||
3089                ic[-2].f == instr(multi_lw_2_le)) &&
3090                ic[-2].arg[1] == ic[0].arg[1] &&
3091                ic[-1].arg[0] != ic[0].arg[1]) {
3092                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3093                            ic[-2].f = instr(multi_lw_3_le);
3094                    else
3095                            ic[-2].f = instr(multi_lw_3_be);
3096            }
3097    
3098            /*  Note: Loads to the base register are not allowed in slot -1.  */
3099            if (ic[-1].f == ic[0].f &&
3100                ic[-1].arg[1] == ic[0].arg[1] &&
3101                ic[-1].arg[0] != ic[0].arg[1]) {
3102                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3103                            ic[-1].f = instr(multi_lw_2_le);
3104                    else
3105                            ic[-1].f = instr(multi_lw_2_be);
3106            }
3107    }
3108    #endif
3109    
3110    
3111    /*
3112     *  Combine:  NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
3113     *
3114     *  Instruction cache loop:
3115     *
3116     *  ic[-8]      mtc0    rV,status
3117     *     -7       nop
3118     *     -6       nop
3119     *     -5  s:   addiu   rX,rX,4
3120     *     -4       bne     rY,rX,s
3121     *     -3       sb      zr,-4(rX)
3122     *     -2       nop
3123     *     -1       nop
3124     *      0       mtc0    rT,status
3125     */
3126    void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
3127            struct mips_instr_call *ic, int low_addr)
3128    {
3129            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3130                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3131    
3132            if (n_back < 8)
3133                    return;
3134    
3135            if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
3136                ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
3137                ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
3138                (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
3139                ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
3140                ic[-4].arg[2] == (size_t) &ic[-5] &&
3141                ic[-3].arg[1] == ic[-5].arg[0] &&
3142                ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3143                    ic[-8].f = instr(netbsd_r3k_picache_do_inv);
3144            }
3145    }
3146    
3147    
3148    /*
3149     *  Combine: something ending with a nop.
3150     *
3151     *      NetBSD's strlen core.
3152     *      [Conditional] branch, followed by nop.
3153     *      NetBSD/pmax' idle loop (and possibly others as well).
3154     *      Linux/pmax' idle loop.
3155     */
3156    void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3157    {
3158            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3159                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3160    
3161            if (n_back < 8)
3162                    return;
3163    
3164    #ifdef MODE32
3165            if (ic[-8].f == instr(set) &&
3166                ic[-7].f == mips32_loadstore[4 + 1] &&
3167                ic[-7].arg[0] == ic[-1].arg[0] &&
3168                ic[-7].arg[0] == ic[-3].arg[0] &&
3169                ic[-7].arg[0] == ic[-5].arg[0] &&
3170                ic[-7].arg[0] == ic[-7].arg[1] &&
3171                ic[-7].arg[0] == ic[-8].arg[0] &&
3172                ic[-6].f == instr(nop) &&
3173                ic[-5].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3174                ic[-5].f == instr(bne_samepage_nop) &&
3175                ic[-4].f == instr(nop) &&
3176                ic[-3].f == mips32_loadstore[4 + 1] &&
3177                ic[-2].f == instr(nop) &&
3178                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3179                ic[-1].arg[2] == (size_t) &ic[-8] &&
3180                ic[-1].f == instr(beq_samepage)) {
3181                    ic[-8].f = instr(linux_pmax_idle);
3182                    return;
3183            }
3184    
3185            if (ic[-4].f == instr(set) &&
3186                ic[-3].f == mips32_loadstore[4 + 1] &&
3187                ic[-3].arg[0] == ic[-1].arg[0] &&
3188                ic[-3].arg[1] == ic[-4].arg[0] &&
3189                ic[-2].f == instr(nop) &&
3190                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3191                ic[-1].arg[2] == (size_t) &ic[-4] &&
3192                ic[-1].f == instr(beq_samepage)) {
3193                    ic[-4].f = instr(netbsd_pmax_idle);
3194                    return;
3195            }
3196    
3197            if ((ic[-3].f == mips32_loadstore[1] ||
3198                ic[-3].f == mips32_loadstore[16 + 1]) &&
3199                ic[-3].arg[2] == 0 &&
3200                ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
3201                ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
3202                ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
3203                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3204                ic[-1].f == instr(bne_samepage)) {
3205                    ic[-3].f = instr(netbsd_strlen);
3206                    return;
3207            }
3208    #endif
3209    
3210            if (ic[-1].f == instr(bne_samepage)) {
3211                    ic[-1].f = instr(bne_samepage_nop);
3212                    return;
3213            }
3214    
3215            if (ic[-1].f == instr(beq_samepage)) {
3216                    ic[-1].f = instr(beq_samepage_nop);
3217                    return;
3218            }
3219    
3220            /*  TODO: other branches that are followed by nop should be here  */
3221    }
3222    
3223    
3224    /*
3225     *  Combine:
3226     *
3227     *      xor + andi + sll
3228     *      andi + sll
3229     */
3230    void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3231    {
3232            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3233                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3234    
3235            if (n_back < 2)
3236                    return;
3237    
3238            if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3239                    ic[-2].f = instr(xor_andi_sll);
3240                    return;
3241            }
3242    
3243            if (ic[-1].f == instr(andi)) {
3244                    ic[-1].f = instr(andi_sll);
3245                    return;
3246            }
3247    }
3248    
3249    
3250    /*
3251     *  lui + ori
3252     */
3253    void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3254    {
3255            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3256                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3257    
3258          if (n_back < 1)          if (n_back < 1)
3259                  return;                  return;
3260    
3261            if (ic[-1].f == instr(set)) {
3262                    ic[-1].f = instr(lui_ori);
3263                    return;
3264            }
3265    }
3266    
3267    
3268    /*
3269     *  addu + addu + addu
3270     */
3271    void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3272    {
3273            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3274                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3275    
3276            if (n_back < 4)
3277                    return;
3278    
3279            /*  Avoid "overlapping" instruction combinations:  */
3280            if (ic[-4].f == instr(multi_addu_3) ||
3281                ic[-3].f == instr(multi_addu_3))
3282                    return;
3283    
3284            if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3285                    ic[-2].f = instr(multi_addu_3);
3286                    return;
3287            }
3288    }
3289    
3290    
3291    /*
3292     *  Combine:
3293     *
3294     *      [Conditional] branch, followed by addiu.
3295     */
3296    void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3297    {
3298            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3299                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3300    
3301            if (n_back < 2)
3302                    return;
3303    
3304            if (ic[-2].f == instr(addiu) &&
3305                ic[-1].f == instr(bne_samepage)) {
3306                    ic[-2].f = instr(addiu_bne_samepage_addiu);
3307                    return;
3308            }
3309    
3310            if (ic[-1].f == instr(set)) {
3311                    ic[-1].f = instr(lui_addiu);
3312                    return;
3313            }
3314    
3315          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
3316                  ic[-1].f = instr(b_samepage_addiu);                  ic[-1].f = instr(b_samepage_addiu);
3317                  combined;                  return;
3318            }
3319    
3320            if (ic[-1].f == instr(beq_samepage)) {
3321                    ic[-1].f = instr(beq_samepage_addiu);
3322                    return;
3323            }
3324    
3325            if (ic[-1].f == instr(bne_samepage)) {
3326                    ic[-1].f = instr(bne_samepage_addiu);
3327                    return;
3328            }
3329    
3330            if (ic[-1].f == instr(jr_ra)) {
3331                    ic[-1].f = instr(jr_ra_addiu);
3332                    return;
3333          }          }
3334    
3335          /*  TODO: other branches that are followed by addiu should be here  */          /*  TODO: other branches that are followed by addiu should be here  */
# Line 2436  void COMBINE(b_daddiu)(struct cpu *cpu, Line 3350  void COMBINE(b_daddiu)(struct cpu *cpu,
3350    
3351          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
3352                  ic[-1].f = instr(b_samepage_daddiu);                  ic[-1].f = instr(b_samepage_daddiu);
                 combined;  
3353          }          }
3354    
3355          /*  TODO: other branches that are followed by daddiu should be here  */          /*  TODO: other branches that are followed by daddiu should be here  */
# Line 2456  void COMBINE(b_daddiu)(struct cpu *cpu, Line 3369  void COMBINE(b_daddiu)(struct cpu *cpu,
3369   */   */
3370  X(to_be_translated)  X(to_be_translated)
3371  {  {
3372    #ifdef NATIVE_CODE_GENERATION
3373            int native = 0;
3374    #endif
3375          uint64_t addr, low_pc;          uint64_t addr, low_pc;
3376          uint32_t iword, imm;          uint32_t iword, imm;
3377          unsigned char *page;          unsigned char *page;
3378          unsigned char ib[4];          unsigned char ib[4];
3379          int main_opcode, rt, rs, rd, sa, s6, x64 = 0;          int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10;
3380          int in_crosspage_delayslot = 0;          int in_crosspage_delayslot = 0;
3381          void (*samepage_function)(struct cpu *, struct mips_instr_call *);          void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3382          int store, signedness, size;          int store, signedness, size;
# Line 2541  X(to_be_translated) Line 3457  X(to_be_translated)
3457          sa = (iword >>  6) & 31;          sa = (iword >>  6) & 31;
3458          imm = (int16_t)iword;          imm = (int16_t)iword;
3459          s6 = iword & 63;          s6 = iword & 63;
3460            s10 = (rs << 5) | sa;
3461    
3462          switch (main_opcode) {          switch (main_opcode) {
3463    
# Line 2593  X(to_be_translated) Line 3510  X(to_be_translated)
3510                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3511                          if (rd == MIPS_GPR_ZERO)                          if (rd == MIPS_GPR_ZERO)
3512                                  ic->f = instr(nop);                                  ic->f = instr(nop);
3513                            if (ic->f == instr(sll))
3514                                    cpu->cd.mips.combination_check = COMBINE(sll);
3515                            if (ic->f == instr(nop))
3516                                    cpu->cd.mips.combination_check = COMBINE(nop);
3517    
3518                            /*  Special checks for MIPS32/64 revision 2 opcodes,
3519                                such as rotation instructions:  */
3520                            if (sa >= 0 && rs != 0x00) {
3521                                    switch (rs) {
3522                                    /*  TODO: [d]ror, etc.  */
3523                                    default:goto bad;
3524                                    }
3525                            }
3526                            if (sa < 0 && (s10 & 0x1f) != 0) {
3527                                    switch (s10 & 0x1f) {
3528                                    /*  TODO: [d]rorv, etc.  */
3529                                    default:goto bad;
3530                                    }
3531                            }
3532                          break;                          break;
3533    
3534                  case SPECIAL_ADD:                  case SPECIAL_ADD:
# Line 2724  X(to_be_translated) Line 3660  X(to_be_translated)
3660                          default:if (rd == MIPS_GPR_ZERO)                          default:if (rd == MIPS_GPR_ZERO)
3661                                          ic->f = instr(nop);                                          ic->f = instr(nop);
3662                          }                          }
3663    
3664                            if (ic->f == instr(addu))
3665                                    cpu->cd.mips.combination_check = COMBINE(addu);
3666    
3667                          break;                          break;
3668    
3669                  case SPECIAL_JR:                  case SPECIAL_JR:
# Line 2767  X(to_be_translated) Line 3707  X(to_be_translated)
3707                          break;                          break;
3708    
3709                  case SPECIAL_BREAK:                  case SPECIAL_BREAK:
3710                          ic->f = instr(break);                          if (((iword >> 6) & 0xfffff) == 0x30378) {
3711                                    /*  "Magic trap" for REBOOT:  */
3712                                    ic->f = instr(reboot);
3713                            } else {
3714                                    ic->f = instr(break);
3715                            }
3716                          break;                          break;
3717    
3718                  case SPECIAL_SYNC:                  case SPECIAL_SYNC:
# Line 2883  X(to_be_translated) Line 3828  X(to_be_translated)
3828                  case HI6_XORI:    ic->f = instr(xori); break;                  case HI6_XORI:    ic->f = instr(xori); break;
3829                  }                  }
3830    
3831                    if (ic->arg[2] == 0) {
3832                            if ((cpu->is_32bit && ic->f == instr(addiu)) ||
3833                                (!cpu->is_32bit && ic->f == instr(daddiu))) {
3834                                    ic->f = instr(mov);
3835                                    ic->arg[2] = ic->arg[1];
3836                            }
3837                    }
3838    
3839                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
3840                          ic->f = instr(nop);                          ic->f = instr(nop);
3841    
3842                    if (ic->f == instr(ori))
3843                            cpu->cd.mips.combination_check = COMBINE(ori);
3844                  if (ic->f == instr(addiu))                  if (ic->f == instr(addiu))
3845                          cpu->cd.mips.combination_check = COMBINE(b_addiu);                          cpu->cd.mips.combination_check = COMBINE(addiu);
3846                  if (ic->f == instr(daddiu))                  if (ic->f == instr(daddiu))
3847                          cpu->cd.mips.combination_check = COMBINE(b_daddiu);                          cpu->cd.mips.combination_check = COMBINE(b_daddiu);
3848                  break;                  break;
# Line 2896  X(to_be_translated) Line 3851  X(to_be_translated)
3851                  ic->f = instr(set);                  ic->f = instr(set);
3852                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3853                  ic->arg[1] = (int32_t) (imm << 16);                  ic->arg[1] = (int32_t) (imm << 16);
3854                    /*  NOTE: Don't use arg[2] here. It can be used with
3855                        instruction combinations, to do lui + addiu, etc.  */
3856                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
3857                          ic->f = instr(nop);                          ic->f = instr(nop);
3858                  break;                  break;
# Line 2949  X(to_be_translated) Line 3906  X(to_be_translated)
3906                          case COP0_DERET:                          case COP0_DERET:
3907                                  ic->f = instr(deret);                                  ic->f = instr(deret);
3908                                  break;                                  break;
3909                          case COP0_IDLE:                          case COP0_WAIT:
3910                                    ic->f = instr(wait);
3911                                    if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
3912                                        cpu->cd.mips.cpu_type.isa_level < 32) {
3913                                            static int warned = 0;
3914                                            ic->f = instr(reserved);
3915                                            if (!warned) {
3916                                                    fatal("{ WARNING: Attempt to "
3917                                                        "execute the WAIT instruct"
3918                                                        "ion, but the emulated CPU "
3919                                                        "is neither RM52xx, nor "
3920                                                        "MIPS32/64! }\n");
3921                                                    warned = 1;
3922                                            }
3923                                    }
3924                                    break;
3925                          case COP0_STANDBY:                          case COP0_STANDBY:
3926                          case COP0_SUSPEND:                                  /*  NOTE: Reusing the 'wait' instruction:  */
3927                                    ic->f = instr(wait);
3928                                    if (cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
3929                                            static int warned = 0;
3930                                            ic->f = instr(reserved);
3931                                            if (!warned) {
3932                                                    fatal("{ WARNING: Attempt to "
3933                                                        "execute a R41xx instruct"
3934                                                        "ion, but the emulated CPU "
3935                                                        "doesn't support it! }\n");
3936                                                    warned = 1;
3937                                            }
3938                                    }
3939                                    break;
3940                          case COP0_HIBERNATE:                          case COP0_HIBERNATE:
3941                                  /*  TODO  */                                  /*  TODO  */
3942                                  ic->f = instr(nop);                                  goto bad;
3943                            case COP0_SUSPEND:
3944                                    /*  Used by NetBSD on HPCmips (VR41xx) to
3945                                        halt the machine.  */
3946                                    ic->f = instr(reboot);
3947                                  break;                                  break;
3948                          case COP0_EI:                          case COP0_EI:
3949                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
# Line 2991  X(to_be_translated) Line 3980  X(to_be_translated)
3980                          ic->arg[1] = rd + ((iword & 7) << 5);                          ic->arg[1] = rd + ((iword & 7) << 5);
3981                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
3982                          ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);                          ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
3983                            if (rs == COPz_MFCz && (iword & 7) == 0 &&
3984                                rd != COP0_COUNT)
3985                                    ic->f = instr(mfc0_select0);
3986                            if (rs == COPz_DMFCz && (iword & 7) == 0 &&
3987                                rd != COP0_COUNT)
3988                                    ic->f = instr(dmfc0_select0);
3989                          if (rt == MIPS_GPR_ZERO)                          if (rt == MIPS_GPR_ZERO)
3990                                  ic->f = instr(nop);                                  ic->f = instr(nop);
3991                          break;                          break;
# Line 3000  X(to_be_translated) Line 3995  X(to_be_translated)
3995                          ic->arg[1] = rd + ((iword & 7) << 5);                          ic->arg[1] = rd + ((iword & 7) << 5);
3996                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
3997                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
3998    
3999                            if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
4000                                rs == COPz_MTCz && rd == COP0_STATUS)
4001                                    cpu->cd.mips.combination_check =
4002                                        COMBINE(netbsd_r3k_cache_inv);
4003    
4004                          break;                          break;
4005                  case 8: if (iword == 0x4100ffff) {                  case 8: if (iword == 0x4100ffff) {
4006                                  /*  R2020 DECstation write-loop thingy.  */                                  /*  R2020 DECstation write-loop thingy.  */
# Line 3087  X(to_be_translated) Line 4088  X(to_be_translated)
4088                  goto bad;                  goto bad;
4089                  break;                  break;
4090    
4091            case HI6_COP3:
4092                    /*  Always cause a coprocessor unusable exception if
4093                        there is no coprocessor 3:  */
4094                    if (cpu->cd.mips.coproc[3] == NULL) {
4095                            ic->f = instr(cpu);
4096                            ic->arg[0] = 3;
4097                            break;
4098                    }
4099    
4100                    if (iword == 0x4d00ffff) {
4101                            /*  R2020 writeback thing, used by e.g. NetBSD/pmax
4102                                on MIPSMATE.  */
4103                            ic->f = instr(nop);
4104                    } else {
4105                            fatal("COP3 iword=0x%08x\n", iword);
4106                            goto bad;
4107                    }
4108                    break;
4109    
4110          case HI6_SPECIAL2:          case HI6_SPECIAL2:
4111                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4112                          /*  R5900, TX79/C790, have MMI instead of SPECIAL2:  */                          /*  R5900, TX79/C790, have MMI instead of SPECIAL2:  */
# Line 3317  X(to_be_translated) Line 4337  X(to_be_translated)
4337                  /*  Load into the dummy scratch register, if rt = zero  */                  /*  Load into the dummy scratch register, if rt = zero  */
4338                  if (!store && rt == MIPS_GPR_ZERO)                  if (!store && rt == MIPS_GPR_ZERO)
4339                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4340    
4341                    /*  Check for multiple loads or stores in a row using the same
4342                        base register:  */
4343    #ifdef MODE32
4344                    if (main_opcode == HI6_LW)
4345                            cpu->cd.mips.combination_check = COMBINE(multi_lw);
4346                    if (main_opcode == HI6_SW)
4347                            cpu->cd.mips.combination_check = COMBINE(multi_sw);
4348    #endif
4349                  break;                  break;
4350    
4351          case HI6_LL:          case HI6_LL:
# Line 3436  X(to_be_translated) Line 4465  X(to_be_translated)
4465                      cpu->cd.mips.cpu_type.isa_revision < 2) {                      cpu->cd.mips.cpu_type.isa_revision < 2) {
4466                          static int warning = 0;                          static int warning = 0;
4467                          if (!warning) {                          if (!warning) {
4468                                  fatal("[ WARNING! SPECIAL3 opcode used on a"                                  fatal("[ WARNING! SPECIAL3 opcode used, but"
4469                                      " cpu which doesn't implement it ]\n");                                      " the %s processor does not implement "
4470                                        "such instructions. Only printing this "
4471                                        "warning once. ]\n",
4472                                        cpu->cd.mips.cpu_type.name);
4473                                  warning = 1;                                  warning = 1;
4474                          }                          }
4475                          ic->f = instr(reserved);                          ic->f = instr(reserved);
# Line 3446  X(to_be_translated) Line 4478  X(to_be_translated)
4478    
4479                  switch (s6) {                  switch (s6) {
4480    
4481                    case SPECIAL3_EXT:
4482                            /*  TODO: Cleanup and extend to DEXT... etc  */
4483                            {
4484                                    int msbd = rd, lsb = (iword >> 6) & 0x1f;
4485                                    ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4486                                    ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4487                                    ic->arg[2] = (msbd << 5) + lsb;
4488                                    ic->f = instr(ext);
4489                                    if (rt == MIPS_GPR_ZERO)
4490                                            ic->f = instr(nop);
4491                            }
4492                            break;
4493    
4494                    case SPECIAL3_BSHFL:
4495                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4496                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4497                            switch (s10) {
4498                            case BSHFL_WSBH:
4499                                    ic->f = instr(wsbh);
4500                                    break;
4501                            case BSHFL_SEB:
4502                                    ic->f = instr(seb);
4503                                    break;
4504                            case BSHFL_SEH:
4505                                    ic->f = instr(seh);
4506                                    break;
4507                            default:goto bad;
4508                            }
4509                            break;
4510    
4511                    case SPECIAL3_DBSHFL:
4512                            ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4513                            ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4514                            switch (s10) {
4515                            case BSHFL_DSBH:
4516                                    ic->f = instr(dsbh);
4517                                    break;
4518                            case BSHFL_DSHD:
4519                                    ic->f = instr(dshd);
4520                                    break;
4521                            default:goto bad;
4522                            }
4523                            break;
4524    
4525                  case SPECIAL3_RDHWR:                  case SPECIAL3_RDHWR:
4526                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                          ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4527    
# Line 3474  X(to_be_translated) Line 4550  X(to_be_translated)
4550          default:goto bad;          default:goto bad;
4551          }          }
4552    
4553    
4554  #ifdef MODE32  #ifdef MODE32
4555          if (x64) {          if (x64) {
4556                  static int has_warned = 0;                  static int has_warned = 0;
# Line 3486  X(to_be_translated) Line 4563  X(to_be_translated)
4563          }          }
4564  #endif  #endif
4565    
4566    
4567    #ifdef NATIVE_CODE_GENERATION
4568            if (native == 0 || (addr & 0xffc) == 0xffc ||
4569                ic[1].f != instr(to_be_translated)) {
4570                    /*  TODO  */
4571                    /*  flush etc.  */
4572            }
4573    #endif
4574    
4575    
4576  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4577  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"

Legend:
Removed from v.26  
changed lines
  Added in v.40

  ViewVC Help
Powered by ViewVC 1.1.26