/[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 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC
# 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.104 2006/08/14 17:45:47 debug Exp $
29   *   *
30   *  MIPS instructions.   *  MIPS instructions.
31   *   *
# Line 135  X(beq_samepage) Line 135  X(beq_samepage)
135          }          }
136          cpu->delay_slot = NOT_DELAYED;          cpu->delay_slot = NOT_DELAYED;
137  }  }
138    X(beq_samepage_addiu)
139    {
140            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
141            cpu->n_translated_instrs ++;
142            reg(ic[1].arg[1]) = (int32_t)
143                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
144            if (rs == rt)
145                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
146            else
147                    cpu->cd.mips.next_ic ++;
148    }
149    X(beq_samepage_nop)
150    {
151            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
152            cpu->n_translated_instrs ++;
153            if (rs == rt)
154                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
155            else
156                    cpu->cd.mips.next_ic ++;
157    }
158  X(bne)  X(bne)
159  {  {
160          MODE_int_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
# Line 172  X(bne_samepage) Line 192  X(bne_samepage)
192          }          }
193          cpu->delay_slot = NOT_DELAYED;          cpu->delay_slot = NOT_DELAYED;
194  }  }
195    X(bne_samepage_addiu)
196    {
197            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
198            cpu->n_translated_instrs ++;
199            reg(ic[1].arg[1]) = (int32_t)
200                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
201            if (rs != rt)
202                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
203            else
204                    cpu->cd.mips.next_ic ++;
205    }
206    X(bne_samepage_nop)
207    {
208            MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
209            cpu->n_translated_instrs ++;
210            if (rs != rt)
211                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
212            else
213                    cpu->cd.mips.next_ic ++;
214    }
215  X(b)  X(b)
216  {  {
217          MODE_int_t old_pc = cpu->pc;          MODE_int_t old_pc = cpu->pc;
# Line 896  X(jr_ra) Line 936  X(jr_ra)
936          } else          } else
937                  cpu->delay_slot = NOT_DELAYED;                  cpu->delay_slot = NOT_DELAYED;
938  }  }
939    X(jr_ra_addiu)
940    {
941            /*  jr ra, followed by an addiu  */
942            MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
943            reg(ic[1].arg[1]) = (int32_t)
944                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
945            cpu->pc = rs;
946            quick_pc_to_pointers(cpu);
947            cpu->n_translated_instrs ++;
948    }
949  X(jr_ra_trace)  X(jr_ra_trace)
950  {  {
951          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 1063  X(jal_trace)
1063   */   */
1064  X(cache)  X(cache)
1065  {  {
1066          /*  TODO. For now, just clear the rmw bit:  */          /*  TODO: Implement cache operations.  */
         cpu->cd.mips.rmw = 0;  
1067    
1068  /*  TODO: fix  */          /*  Make sure the rmw bit is cleared:  */
1069  cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);          cpu->cd.mips.rmw = 0;
 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);  
 /* cpu_create_or_reset_tc(cpu); */  
1070  }  }
1071    
1072    
# Line 1632  X(mtc0) Line 1679  X(mtc0)
1679                  uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];                  uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1680                  /*  NOTE: STATUS_IE happens to match the enable bit also                  /*  NOTE: STATUS_IE happens to match the enable bit also
1681                      on R2000/R3000, so this is ok.  */                      on R2000/R3000, so this is ok.  */
1682                  if (status & (STATUS_EXL | STATUS_ERL))                  if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1683                          status &= ~STATUS_IE;                          if (status & (STATUS_EXL | STATUS_ERL))
1684                                    status &= ~STATUS_IE;
1685                    }
1686                  /*  Ugly R5900 special case:  (TODO: move this?)  */                  /*  Ugly R5900 special case:  (TODO: move this?)  */
1687                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&                  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1688                      !(status & R5900_STATUS_EIE))                      !(status & R5900_STATUS_EIE))
# Line 1760  X(break) Line 1809  X(break)
1809          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1810          mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);          mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1811  }  }
1812    X(reboot)
1813    {
1814            cpu->running = 0;
1815            debugger_n_steps_left_before_interaction = 0;
1816            cpu->cd.mips.next_ic = &nothing_call;
1817    }
1818    
1819    
1820  /*  /*
# Line 1849  X(tlbr) Line 1904  X(tlbr)
1904   */   */
1905  X(rfe)  X(rfe)
1906  {  {
1907          coproc_rfe(cpu);          /*  Just rotate the interrupt/user bits:  */
1908            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
1909                (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
1910                ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
1911    
1912          /*  Note: no pc to pointers conversion is necessary here.  */          /*
1913             *  Note: no pc to pointers conversion is necessary here. Usually the
1914             *  rfe instruction resides in the delay slot of a jr k0/k1, and
1915             *  it is up to that instruction to do the pointer conversion.
1916             */
1917  }  }
1918    
1919    
1920  /*  /*
1921   *  eret: Return from exception handler   *  eret: Return from exception handler (non-R3000 style)
1922   */   */
1923  X(eret)  X(eret)
1924  {  {
1925          coproc_eret(cpu);          if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1926                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1927                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1928            } else {
1929                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1930                    cpu->delay_slot = 0;            
1931                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1932            }
1933    
1934          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
1935    
1936            cpu->cd.mips.rmw = 0;   /*  the "LL bit"  */
1937  }  }
1938    
1939    
# Line 1888  X(deret) Line 1960  X(deret)
1960    
1961    
1962  /*  /*
1963     *  wait: Wait for external interrupt.
1964     */
1965    X(wait)
1966    {
1967            /*
1968             *  If there is an interrupt, then just return. Otherwise
1969             *  re-run the wait instruction (after a delay).
1970             */
1971            uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1972            uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1973    
1974            /*  NOTE: STATUS_IE happens to match the enable bit also
1975                on R2000/R3000, so this is ok.  */
1976            if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1977                    if (status & (STATUS_EXL | STATUS_ERL))
1978                            status &= ~STATUS_IE;
1979            }
1980            /*  Ugly R5900 special case:  (TODO: move this?)  */
1981            if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1982                !(status & R5900_STATUS_EIE))
1983                    status &= ~STATUS_IE;
1984            if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
1985                    return;
1986    
1987            cpu->cd.mips.next_ic = ic;
1988            cpu->is_halted = 1;
1989    
1990            /*
1991             *  There was no interrupt. Go to sleep.
1992             *
1993             *  TODO:
1994             *
1995             *  Think about how to actually implement this usleep stuff,
1996             *  in an SMP and/or timing accurate environment.
1997             */
1998    
1999            if (cpu->machine->ncpus == 1) {
2000                    static int x = 0;
2001                    if ((++x) == 600) {
2002                            usleep(1);
2003                            x = 0;
2004                    }
2005                    cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2006            }
2007    }
2008    
2009    
2010    /*
2011   *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).   *  rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2012   *   *
2013   *  arg[0] = ptr to rt (destination register)   *  arg[0] = ptr to rt (destination register)
# Line 2297  X(ei_r5900) Line 2417  X(ei_r5900)
2417    
2418    
2419  /*  /*
2420     *  sw_loop:
2421     *
2422     *  s:  addiu   rX,rX,4                 rX = arg[0] and arg[1]
2423     *      bne     rY,rX,s  (or rX,rY,s)   rt=arg[1], rs=arg[0]
2424     *      sw      rZ,-4(rX)               rt=arg[0], rs=arg[1]
2425     */
2426    X(sw_loop)
2427    {
2428            MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2429            uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2430            MODE_uint_t rY, bytes_to_write;
2431            unsigned char *page;
2432            int partial = 0;
2433    
2434            page = cpu->cd.mips.host_store[rX >> 12];
2435    
2436            /*  Fallback:  */
2437            if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2438                    instr(addiu)(cpu, ic);
2439                    return;
2440            }
2441    
2442            if (rYp == (uint64_t *) ic->arg[0])
2443                    rYp = (uint64_t *) ic[1].arg[1];
2444    
2445            rY = reg(rYp);
2446    
2447            bytes_to_write = rY - rX;
2448            if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2449                    bytes_to_write = 0x1000 - (rX & 0xfff);
2450                    partial = 1;
2451            }
2452    
2453            /*  printf("rX = %08x\n", (int)rX);
2454                printf("rY = %08x\n", (int)rY);
2455                printf("rZ = %08x\n", (int)rZ);
2456                printf("%i bytes\n", (int)bytes_to_write);  */
2457    
2458            memset(page + (rX & 0xfff), 0, bytes_to_write);
2459    
2460            reg(ic->arg[0]) = rX + bytes_to_write;
2461    
2462            cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2463            cpu->cd.mips.next_ic = partial?
2464                (struct mips_instr_call *) &ic[0] :
2465                (struct mips_instr_call *) &ic[3];
2466    }
2467    
2468    
2469    #ifdef MODE32
2470    /*
2471     *  multi_sw_2, _3, _4:
2472     *
2473     *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2474     */
2475    X(multi_sw_2_le)
2476    {
2477            uint32_t *page;
2478            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2479            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2480            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2481            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2482    
2483            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2484    
2485            /*  Fallback:  */
2486            if (cpu->delay_slot ||
2487                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2488                index0 != index1) {
2489                    /*  Normal safe sw:  */
2490                    mips32_loadstore[8 + 2 * 2](cpu, ic);
2491                    return;
2492            }
2493    
2494            addr0 = (addr0 >> 2) & 0x3ff;
2495            addr1 = (addr1 >> 2) & 0x3ff;
2496    
2497            r1 = reg(ic[0].arg[0]);
2498            r2 = reg(ic[1].arg[0]);
2499    
2500            r1 = LE32_TO_HOST(r1);
2501            r2 = LE32_TO_HOST(r2);
2502    
2503            page[addr0] = r1;
2504            page[addr1] = r2;
2505    
2506            cpu->n_translated_instrs ++;
2507            cpu->cd.mips.next_ic ++;
2508    }
2509    X(multi_sw_2_be)
2510    {
2511            uint32_t *page;
2512            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2513            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2514            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2515            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2516    
2517            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2518    
2519            /*  Fallback:  */
2520            if (cpu->delay_slot ||
2521                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2522                index0 != index1) {
2523                    /*  Normal safe sw:  */
2524                    mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2525                    return;
2526            }
2527    
2528            addr0 = (addr0 >> 2) & 0x3ff;
2529            addr1 = (addr1 >> 2) & 0x3ff;
2530    
2531            r1 = reg(ic[0].arg[0]);
2532            r2 = reg(ic[1].arg[0]);
2533    
2534            r1 = BE32_TO_HOST(r1);
2535            r2 = BE32_TO_HOST(r2);
2536    
2537            page[addr0] = r1;
2538            page[addr1] = r2;
2539    
2540            cpu->n_translated_instrs ++;
2541            cpu->cd.mips.next_ic ++;
2542    }
2543    X(multi_sw_3_le)
2544    {
2545            uint32_t *page;
2546            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2547            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2548            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2549            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2550            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2551                index2 = addr2 >> 12;
2552    
2553            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2554    
2555            /*  Fallback:  */
2556            if (cpu->delay_slot ||
2557                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2558                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2559                    /*  Normal safe sw:  */
2560                    mips32_loadstore[8 + 2 * 2](cpu, ic);
2561                    return;
2562            }
2563    
2564            addr0 = (addr0 >> 2) & 0x3ff;
2565            addr1 = (addr1 >> 2) & 0x3ff;
2566            addr2 = (addr2 >> 2) & 0x3ff;
2567    
2568            /*  printf("addr0=%x 1=%x 2=%x\n",
2569                (int)addr0, (int)addr1, (int)addr2);  */
2570    
2571            r1 = reg(ic[0].arg[0]);
2572            r2 = reg(ic[1].arg[0]);
2573            r3 = reg(ic[2].arg[0]);
2574    
2575            r1 = LE32_TO_HOST(r1);
2576            r2 = LE32_TO_HOST(r2);
2577            r3 = LE32_TO_HOST(r3);
2578    
2579            page[addr0] = r1;
2580            page[addr1] = r2;
2581            page[addr2] = r3;
2582    
2583            cpu->n_translated_instrs += 2;
2584            cpu->cd.mips.next_ic += 2;
2585    }
2586    X(multi_sw_3_be)
2587    {
2588            uint32_t *page;
2589            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2590            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2591            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2592            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2593            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2594                index2 = addr2 >> 12;
2595    
2596            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2597    
2598            /*  Fallback:  */
2599            if (cpu->delay_slot ||
2600                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2601                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2602                    /*  Normal safe sw:  */
2603                    mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2604                    return;
2605            }
2606    
2607            addr0 = (addr0 >> 2) & 0x3ff;
2608            addr1 = (addr1 >> 2) & 0x3ff;
2609            addr2 = (addr2 >> 2) & 0x3ff;
2610    
2611            /*  printf("addr0=%x 1=%x 2=%x\n",
2612                (int)addr0, (int)addr1, (int)addr2);  */
2613    
2614            r1 = reg(ic[0].arg[0]);
2615            r2 = reg(ic[1].arg[0]);
2616            r3 = reg(ic[2].arg[0]);
2617    
2618            r1 = BE32_TO_HOST(r1);
2619            r2 = BE32_TO_HOST(r2);
2620            r3 = BE32_TO_HOST(r3);
2621    
2622            page[addr0] = r1;
2623            page[addr1] = r2;
2624            page[addr2] = r3;
2625    
2626            cpu->n_translated_instrs += 2;
2627            cpu->cd.mips.next_ic += 2;
2628    }
2629    X(multi_sw_4_le)
2630    {
2631            uint32_t *page;
2632            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2633            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2634            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2635            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2636            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2637            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2638                index2 = addr2 >> 12, index3 = addr3 >> 12;
2639    
2640            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2641    
2642            /*  Fallback:  */
2643            if (cpu->delay_slot ||
2644                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2645                (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2646                index0 != index2 || index0 != index3) {
2647                    /*  Normal safe sw:  */
2648                    mips32_loadstore[8 + 2 * 2](cpu, ic);
2649                    return;
2650            }
2651    
2652            addr0 = (addr0 >> 2) & 0x3ff;
2653            addr1 = (addr1 >> 2) & 0x3ff;
2654            addr2 = (addr2 >> 2) & 0x3ff;
2655            addr3 = (addr3 >> 2) & 0x3ff;
2656    
2657            r1 = reg(ic[0].arg[0]);
2658            r2 = reg(ic[1].arg[0]);
2659            r3 = reg(ic[2].arg[0]);
2660            r4 = reg(ic[3].arg[0]);
2661    
2662            r1 = LE32_TO_HOST(r1);
2663            r2 = LE32_TO_HOST(r2);
2664            r3 = LE32_TO_HOST(r3);
2665            r4 = LE32_TO_HOST(r4);
2666    
2667            page[addr0] = r1;
2668            page[addr1] = r2;
2669            page[addr2] = r3;
2670            page[addr3] = r4;
2671    
2672            cpu->n_translated_instrs += 3;
2673            cpu->cd.mips.next_ic += 3;
2674    }
2675    X(multi_sw_4_be)
2676    {
2677            uint32_t *page;
2678            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2679            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2680            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2681            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2682            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2683            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2684                index2 = addr2 >> 12, index3 = addr3 >> 12;
2685    
2686            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2687    
2688            /*  Fallback:  */
2689            if (cpu->delay_slot ||
2690                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2691                (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2692                index0 != index2 || index0 != index3) {
2693                    /*  Normal safe sw:  */
2694                    mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2695                    return;
2696            }
2697    
2698            addr0 = (addr0 >> 2) & 0x3ff;
2699            addr1 = (addr1 >> 2) & 0x3ff;
2700            addr2 = (addr2 >> 2) & 0x3ff;
2701            addr3 = (addr3 >> 2) & 0x3ff;
2702    
2703            r1 = reg(ic[0].arg[0]);
2704            r2 = reg(ic[1].arg[0]);
2705            r3 = reg(ic[2].arg[0]);
2706            r4 = reg(ic[3].arg[0]);
2707    
2708            r1 = BE32_TO_HOST(r1);
2709            r2 = BE32_TO_HOST(r2);
2710            r3 = BE32_TO_HOST(r3);
2711            r4 = BE32_TO_HOST(r4);
2712    
2713            page[addr0] = r1;
2714            page[addr1] = r2;
2715            page[addr2] = r3;
2716            page[addr3] = r4;
2717    
2718            cpu->n_translated_instrs += 3;
2719            cpu->cd.mips.next_ic += 3;
2720    }
2721    #endif
2722    
2723    
2724    #ifdef MODE32
2725    /*
2726     *  multi_lw_2, _3, _4:
2727     *
2728     *      lw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2729     */
2730    X(multi_lw_2_le)
2731    {
2732            uint32_t *page;
2733            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2734            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2735            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2736            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2737    
2738            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2739    
2740            /*  Fallback:  */
2741            if (cpu->delay_slot ||
2742                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2743                index0 != index1) {
2744                    /*  Normal safe lw:  */
2745                    mips32_loadstore[2 * 2 + 1](cpu, ic);
2746                    return;
2747            }
2748    
2749            addr0 = (addr0 >> 2) & 0x3ff;
2750            addr1 = (addr1 >> 2) & 0x3ff;
2751    
2752            r1 = page[addr0];
2753            r2 = page[addr1];
2754    
2755            r1 = LE32_TO_HOST(r1);
2756            r2 = LE32_TO_HOST(r2);
2757    
2758            reg(ic[0].arg[0]) = r1;
2759            reg(ic[1].arg[0]) = r2;
2760    
2761            cpu->n_translated_instrs ++;
2762            cpu->cd.mips.next_ic ++;
2763    }
2764    X(multi_lw_2_be)
2765    {
2766            uint32_t *page;
2767            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2768            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2769            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2770            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2771    
2772            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2773    
2774            /*  Fallback:  */
2775            if (cpu->delay_slot ||
2776                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2777                index0 != index1) {
2778                    /*  Normal safe lw:  */
2779                    mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2780                    return;
2781            }
2782    
2783            addr0 = (addr0 >> 2) & 0x3ff;
2784            addr1 = (addr1 >> 2) & 0x3ff;
2785    
2786            r1 = page[addr0];
2787            r2 = page[addr1];
2788    
2789            r1 = BE32_TO_HOST(r1);
2790            r2 = BE32_TO_HOST(r2);
2791    
2792            reg(ic[0].arg[0]) = r1;
2793            reg(ic[1].arg[0]) = r2;
2794    
2795            cpu->n_translated_instrs ++;
2796            cpu->cd.mips.next_ic ++;
2797    }
2798    X(multi_lw_3_le)
2799    {
2800            uint32_t *page;
2801            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2802            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2803            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2804            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2805            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2806                index2 = addr2 >> 12;
2807    
2808            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2809    
2810            /*  Fallback:  */
2811            if (cpu->delay_slot ||
2812                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2813                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2814                    /*  Normal safe lw:  */
2815                    mips32_loadstore[2 * 2 + 1](cpu, ic);
2816                    return;
2817            }
2818    
2819            addr0 = (addr0 >> 2) & 0x3ff;
2820            addr1 = (addr1 >> 2) & 0x3ff;
2821            addr2 = (addr2 >> 2) & 0x3ff;
2822    
2823            /*  printf("addr0=%x 1=%x 2=%x\n",
2824                (int)addr0, (int)addr1, (int)addr2);  */
2825    
2826            r1 = page[addr0];
2827            r2 = page[addr1];
2828            r3 = page[addr2];
2829    
2830            r1 = LE32_TO_HOST(r1);
2831            r2 = LE32_TO_HOST(r2);
2832            r3 = LE32_TO_HOST(r3);
2833    
2834            reg(ic[0].arg[0]) = r1;
2835            reg(ic[1].arg[0]) = r2;
2836            reg(ic[2].arg[0]) = r3;
2837    
2838            cpu->n_translated_instrs += 2;
2839            cpu->cd.mips.next_ic += 2;
2840    }
2841    X(multi_lw_3_be)
2842    {
2843            uint32_t *page;
2844            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2845            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2846            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2847            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2848            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2849                index2 = addr2 >> 12;
2850    
2851            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2852    
2853            /*  Fallback:  */
2854            if (cpu->delay_slot ||
2855                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2856                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2857                    /*  Normal safe lw:  */
2858                    mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2859                    return;
2860            }
2861    
2862            addr0 = (addr0 >> 2) & 0x3ff;
2863            addr1 = (addr1 >> 2) & 0x3ff;
2864            addr2 = (addr2 >> 2) & 0x3ff;
2865    
2866            /*  printf("addr0=%x 1=%x 2=%x\n",
2867                (int)addr0, (int)addr1, (int)addr2);  */
2868    
2869            r1 = page[addr0];
2870            r2 = page[addr1];
2871            r3 = page[addr2];
2872    
2873            r1 = BE32_TO_HOST(r1);
2874            r2 = BE32_TO_HOST(r2);
2875            r3 = BE32_TO_HOST(r3);
2876    
2877            reg(ic[0].arg[0]) = r1;
2878            reg(ic[1].arg[0]) = r2;
2879            reg(ic[2].arg[0]) = r3;
2880    
2881            cpu->n_translated_instrs += 2;
2882            cpu->cd.mips.next_ic += 2;
2883    }
2884    X(multi_lw_4_le)
2885    {
2886            uint32_t *page;
2887            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2888            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2889            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2890            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2891            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2892            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2893                index2 = addr2 >> 12, index3 = addr3 >> 12;
2894    
2895            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2896    
2897            /*  Fallback:  */
2898            if (cpu->delay_slot ||
2899                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2900                (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
2901                index0 != index1 || index0 != index2 || index0 != index3) {
2902                    /*  Normal safe lw:  */
2903                    mips32_loadstore[2 * 2 + 1](cpu, ic);
2904                    return;
2905            }
2906    
2907            addr0 = (addr0 >> 2) & 0x3ff;
2908            addr1 = (addr1 >> 2) & 0x3ff;
2909            addr2 = (addr2 >> 2) & 0x3ff;
2910            addr3 = (addr3 >> 2) & 0x3ff;
2911    
2912            r1 = page[addr0];
2913            r2 = page[addr1];
2914            r3 = page[addr2];
2915            r4 = page[addr3];
2916    
2917            r1 = LE32_TO_HOST(r1);
2918            r2 = LE32_TO_HOST(r2);
2919            r3 = LE32_TO_HOST(r3);
2920            r4 = LE32_TO_HOST(r4);
2921    
2922            reg(ic[0].arg[0]) = r1;
2923            reg(ic[1].arg[0]) = r2;
2924            reg(ic[2].arg[0]) = r3;
2925            reg(ic[3].arg[0]) = r4;
2926    
2927            cpu->n_translated_instrs += 3;
2928            cpu->cd.mips.next_ic += 3;
2929    }
2930    X(multi_lw_4_be)
2931    {
2932            uint32_t *page;
2933            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2934            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2935            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2936            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2937            MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2938            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2939                index2 = addr2 >> 12, index3 = addr3 >> 12;
2940    
2941            page = (uint32_t *) cpu->cd.mips.host_load[index0];
2942    
2943            /*  Fallback:  */
2944            if (cpu->delay_slot ||
2945                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2946                (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
2947                index0 != index1 || index0 != index2 || index0 != index3) {
2948                    /*  Normal safe lw:  */
2949                    mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2950                    return;
2951            }
2952    
2953            addr0 = (addr0 >> 2) & 0x3ff;
2954            addr1 = (addr1 >> 2) & 0x3ff;
2955            addr2 = (addr2 >> 2) & 0x3ff;
2956            addr3 = (addr3 >> 2) & 0x3ff;
2957    
2958            r1 = page[addr0];
2959            r2 = page[addr1];
2960            r3 = page[addr2];
2961            r4 = page[addr3];
2962    
2963            r1 = BE32_TO_HOST(r1);
2964            r2 = BE32_TO_HOST(r2);
2965            r3 = BE32_TO_HOST(r3);
2966            r4 = BE32_TO_HOST(r4);
2967    
2968            reg(ic[0].arg[0]) = r1;
2969            reg(ic[1].arg[0]) = r2;
2970            reg(ic[2].arg[0]) = r3;
2971            reg(ic[3].arg[0]) = r4;
2972    
2973            cpu->n_translated_instrs += 3;
2974            cpu->cd.mips.next_ic += 3;
2975    }
2976    #endif
2977    
2978    
2979    /*
2980     *  multi_addu_3:
2981     */
2982    X(multi_addu_3)
2983    {
2984            /*  Fallback:  */
2985            if (cpu->delay_slot) {
2986                    instr(addu)(cpu, ic);
2987                    return;
2988            }
2989    
2990            reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
2991            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
2992            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
2993            cpu->n_translated_instrs += 2;
2994            cpu->cd.mips.next_ic += 2;
2995    }
2996    
2997    
2998    /*
2999     *  netbsd_r3k_picache_do_inv:
3000     *
3001     *  ic[0]       mtc0    rV,status
3002     *     1        nop
3003     *     2        nop
3004     *     3  s:    addiu   rX,rX,4
3005     *     4        bne     rY,rX,s
3006     *     5        sb      zr,-4(rX)
3007     *     6        nop
3008     *     7        nop
3009     *     8        mtc0    rT,status
3010     */
3011    X(netbsd_r3k_picache_do_inv)
3012    {
3013            MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
3014    
3015            /*  Fallback if the environment isn't exactly right:  */
3016            if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
3017                (rx & 3) || (ry & 3) || cpu->delay_slot) {
3018                    instr(mtc0)(cpu, ic);
3019                    return;
3020            }
3021    
3022            reg(ic[3].arg[0]) = ry;
3023            cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
3024    
3025            /*  Run the last mtc0 instruction:  */
3026            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
3027    }
3028    
3029    
3030    #ifdef MODE32
3031    /*
3032     *  netbsd_strlen():
3033     *
3034     *      lb      rV,0(rX)
3035     *   s: addiu   rX,rX,1
3036     *      bne     zr,rV,s
3037     *      nop
3038     */
3039    X(netbsd_strlen)
3040    {
3041            MODE_uint_t rx = reg(ic[0].arg[1]);
3042            MODE_int_t rv;
3043            signed char *page;
3044            uint32_t pageindex = rx >> 12;
3045            int i;
3046    
3047            page = (signed char *) cpu->cd.mips.host_load[pageindex];
3048    
3049            /*  Fallback:  */
3050            if (cpu->delay_slot || page == NULL) {
3051                    /*
3052                     *  Normal lb:  NOTE: It doesn't matter whether [1] or
3053                     *  [16+1] is called here, because endianness for 8-bit
3054                     *  loads is irrelevant. :-)
3055                     */
3056                    mips32_loadstore[1](cpu, ic);
3057                    return;
3058            }
3059    
3060            i = rx & 0xfff;
3061    
3062            /*
3063             *  TODO: This loop can be optimized further for optimal
3064             *  performance on the host, e.g. by reading full words...
3065             */
3066            do {
3067                    rv = page[i ++];
3068            } while (i < 0x1000 && rv != 0);
3069    
3070            cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
3071    
3072            reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
3073            reg(ic[2].arg[0]) = rv;
3074    
3075            /*  Done with the loop? Or continue on the next rx page?  */
3076            if (rv == 0)
3077                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
3078            else
3079                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
3080    }
3081    #endif
3082    
3083    
3084    /*
3085     *  addiu_bne_samepage_addiu:
3086     */
3087    X(addiu_bne_samepage_addiu)
3088    {
3089            MODE_uint_t rs, rt;
3090    
3091            if (cpu->delay_slot) {
3092                    instr(addiu)(cpu, ic);
3093                    return;
3094            }
3095    
3096            cpu->n_translated_instrs += 2;
3097            reg(ic[0].arg[1]) = (int32_t)
3098                ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
3099            rs = reg(ic[1].arg[0]);
3100            rt = reg(ic[1].arg[1]);
3101            reg(ic[2].arg[1]) = (int32_t)
3102                ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
3103            if (rs != rt)
3104                    cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
3105            else
3106                    cpu->cd.mips.next_ic += 2;
3107    }
3108    
3109    
3110    /*
3111     *  xor_andi_sll:
3112     */
3113    X(xor_andi_sll)
3114    {
3115            /*  Fallback:  */
3116            if (cpu->delay_slot) {
3117                    instr(xor)(cpu, ic);
3118                    return;
3119            }
3120    
3121            reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
3122            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
3123            reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
3124    
3125            cpu->n_translated_instrs += 2;
3126            cpu->cd.mips.next_ic += 2;
3127    }
3128    
3129    
3130    /*
3131     *  andi_sll:
3132     */
3133    X(andi_sll)
3134    {
3135            /*  Fallback:  */
3136            if (cpu->delay_slot) {
3137                    instr(andi)(cpu, ic);
3138                    return;
3139            }
3140    
3141            reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
3142            reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
3143    
3144            cpu->n_translated_instrs ++;
3145            cpu->cd.mips.next_ic ++;
3146    }
3147    
3148    
3149    /*
3150     *  lui_ori:
3151     */
3152    X(lui_ori)
3153    {
3154            /*  Fallback:  */
3155            if (cpu->delay_slot) {
3156                    instr(set)(cpu, ic);
3157                    return;
3158            }
3159    
3160            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3161            reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
3162    
3163            cpu->n_translated_instrs ++;
3164            cpu->cd.mips.next_ic ++;
3165    }
3166    
3167    
3168    /*
3169     *  lui_addiu:
3170     */
3171    X(lui_addiu)
3172    {
3173            /*  Fallback:  */
3174            if (cpu->delay_slot) {
3175                    instr(set)(cpu, ic);
3176                    return;
3177            }
3178    
3179            reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3180            reg(ic[1].arg[1]) = (int32_t)
3181                ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
3182    
3183            cpu->n_translated_instrs ++;
3184            cpu->cd.mips.next_ic ++;
3185    }
3186    
3187    
3188    /*
3189   *  b_samepage_addiu:   *  b_samepage_addiu:
3190   *   *
3191   *  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 3291  X(end_of_page2)
3291    
3292    
3293  /*  /*
3294   *  Combine: [Conditional] branch, followed by addiu.   *  Combine:  Memory fill loop (addiu, bne, sw)
3295     *
3296     *  s:  addiu   rX,rX,4
3297     *      bne     rY,rX,s
3298     *      sw      rZ,-4(rX)
3299   */   */
3300  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)
3301    {
3302            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3303                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3304    
3305            /*  Only for 32-bit virtual address translation so far.  */
3306            if (!cpu->is_32bit)
3307                    return;
3308    
3309            if (n_back < 2)
3310                    return;
3311    
3312            if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
3313                (int32_t)ic[-2].arg[2] == 4 &&
3314                ic[-1].f == instr(bne_samepage) &&
3315                (ic[-1].arg[0] == ic[-2].arg[0] ||
3316                    ic[-1].arg[1] == ic[-2].arg[0]) &&
3317                ic[-1].arg[0] != ic[-1].arg[1] &&
3318                ic[-1].arg[2] == (size_t) &ic[-2] &&
3319                ic[0].arg[0] != ic[0].arg[1] &&
3320                ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3321                    ic[-2].f = instr(sw_loop);
3322            }
3323    }
3324    
3325    
3326    /*  Only for 32-bit virtual address translation so far.  */
3327    #ifdef MODE32
3328    /*
3329     *  Combine:  Multiple SW in a row using the same base register
3330     *
3331     *      sw      r?,???(rX)
3332     *      sw      r?,???(rX)
3333     *      sw      r?,???(rX)
3334     *      ...
3335     */
3336    void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
3337          int low_addr)          int low_addr)
3338  {  {
3339          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3340              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3341    
3342            if (n_back < 3)
3343                    return;
3344    
3345            /*  Convert a multi_sw_3 to a multi_sw_4:  */
3346            if ((ic[-3].f == instr(multi_sw_3_be) ||
3347                ic[-3].f == instr(multi_sw_3_le)) &&
3348                ic[-3].arg[1] == ic[0].arg[1]) {
3349                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3350                            ic[-3].f = instr(multi_sw_4_le);
3351                    else
3352                            ic[-3].f = instr(multi_sw_4_be);
3353            }
3354    
3355            /*  Convert a multi_sw_2 to a multi_sw_3:  */
3356            if ((ic[-2].f == instr(multi_sw_2_be) ||
3357                ic[-2].f == instr(multi_sw_2_le)) &&
3358                ic[-2].arg[1] == ic[0].arg[1]) {
3359                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3360                            ic[-2].f = instr(multi_sw_3_le);
3361                    else
3362                            ic[-2].f = instr(multi_sw_3_be);
3363            }
3364    
3365            if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3366                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3367                            ic[-1].f = instr(multi_sw_2_le);
3368                    else
3369                            ic[-1].f = instr(multi_sw_2_be);
3370            }
3371    }
3372    #endif
3373    
3374    
3375    /*  Only for 32-bit virtual address translation so far.  */
3376    #ifdef MODE32
3377    /*
3378     *  Combine:  Multiple LW in a row using the same base register
3379     *
3380     *      lw      r?,???(rX)
3381     *      lw      r?,???(rX)
3382     *      lw      r?,???(rX)
3383     *      ...
3384     */
3385    void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3386            int low_addr)
3387    {
3388            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3389                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3390    
3391            if (n_back < 3)
3392                    return;
3393    
3394            /*  Convert a multi_lw_3 to a multi_lw_4:  */
3395            if ((ic[-3].f == instr(multi_lw_3_be) ||
3396                ic[-3].f == instr(multi_lw_3_le)) &&
3397                ic[-3].arg[1] == ic[0].arg[1] &&
3398                ic[-1].arg[0] != ic[0].arg[1]) {
3399                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3400                            ic[-3].f = instr(multi_lw_4_le);
3401                    else
3402                            ic[-3].f = instr(multi_lw_4_be);
3403            }
3404    
3405            /*  Convert a multi_lw_2 to a multi_lw_3:  */
3406            if ((ic[-2].f == instr(multi_lw_2_be) ||
3407                ic[-2].f == instr(multi_lw_2_le)) &&
3408                ic[-2].arg[1] == ic[0].arg[1] &&
3409                ic[-1].arg[0] != ic[0].arg[1]) {
3410                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3411                            ic[-2].f = instr(multi_lw_3_le);
3412                    else
3413                            ic[-2].f = instr(multi_lw_3_be);
3414            }
3415    
3416            /*  Note: Loads to the base register are not allowed in slot -1.  */
3417            if (ic[-1].f == ic[0].f &&
3418                ic[-1].arg[1] == ic[0].arg[1] &&
3419                ic[-1].arg[0] != ic[0].arg[1]) {
3420                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3421                            ic[-1].f = instr(multi_lw_2_le);
3422                    else
3423                            ic[-1].f = instr(multi_lw_2_be);
3424            }
3425    }
3426    #endif
3427    
3428    
3429    /*
3430     *  Combine:  NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
3431     *
3432     *  Instruction cache loop:
3433     *
3434     *  ic[-8]      mtc0    rV,status
3435     *     -7       nop
3436     *     -6       nop
3437     *     -5  s:   addiu   rX,rX,4
3438     *     -4       bne     rY,rX,s
3439     *     -3       sb      zr,-4(rX)
3440     *     -2       nop
3441     *     -1       nop
3442     *      0       mtc0    rT,status
3443     */
3444    void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
3445            struct mips_instr_call *ic, int low_addr)
3446    {
3447            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3448                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3449    
3450            if (n_back < 8)
3451                    return;
3452    
3453            if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
3454                ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
3455                ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
3456                (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
3457                ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
3458                ic[-4].arg[2] == (size_t) &ic[-5] &&
3459                ic[-3].arg[1] == ic[-5].arg[0] &&
3460                ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3461                    ic[-8].f = instr(netbsd_r3k_picache_do_inv);
3462            }
3463    }
3464    
3465    
3466    /*
3467     *  Combine: something ending with a nop.
3468     *
3469     *      NetBSD's strlen core.
3470     *      [Conditional] branch, followed by nop.
3471     */
3472    void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3473    {
3474            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3475                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3476    
3477    #ifdef MODE32
3478            if (n_back < 3)
3479                    return;
3480    
3481            if ((ic[-3].f == mips32_loadstore[1] ||
3482                ic[-3].f == mips32_loadstore[16 + 1]) &&
3483                ic[-3].arg[2] == 0 &&
3484                ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
3485                ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
3486                ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
3487                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3488                ic[-1].f == instr(bne_samepage)) {
3489                    ic[-3].f = instr(netbsd_strlen);
3490                    return;
3491            }
3492    #endif
3493    
3494            if (n_back < 1)
3495                    return;
3496    
3497            if (ic[-1].f == instr(bne_samepage)) {
3498                    ic[-1].f = instr(bne_samepage_nop);
3499                    return;
3500            }
3501    
3502            if (ic[-1].f == instr(beq_samepage)) {
3503                    ic[-1].f = instr(beq_samepage_nop);
3504                    return;
3505            }
3506    
3507            /*  TODO: other branches that are followed by nop should be here  */
3508    }
3509    
3510    
3511    /*
3512     *  Combine:
3513     *
3514     *      xor + andi + sll
3515     *      andi + sll
3516     */
3517    void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3518    {
3519            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3520                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3521    
3522            if (n_back < 2)
3523                    return;
3524    
3525            if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3526                    ic[-2].f = instr(xor_andi_sll);
3527                    return;
3528            }
3529    
3530            if (ic[-1].f == instr(andi)) {
3531                    ic[-1].f = instr(andi_sll);
3532                    return;
3533            }
3534    }
3535    
3536    
3537    /*
3538     *  lui + ori
3539     */
3540    void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3541    {
3542            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3543                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3544    
3545          if (n_back < 1)          if (n_back < 1)
3546                  return;                  return;
3547    
3548            if (ic[-1].f == instr(set)) {
3549                    ic[-1].f = instr(lui_ori);
3550                    return;
3551            }
3552    }
3553    
3554    
3555    /*
3556     *  addu + addu + addu
3557     */
3558    void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3559    {
3560            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3561                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3562    
3563            if (n_back < 4)
3564                    return;
3565    
3566            /*  Avoid "overlapping" instruction combinations:  */
3567            if (ic[-4].f == instr(multi_addu_3) ||
3568                ic[-3].f == instr(multi_addu_3))
3569                    return;
3570    
3571            if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3572                    ic[-2].f = instr(multi_addu_3);
3573                    return;
3574            }
3575    }
3576    
3577    
3578    /*
3579     *  Combine:
3580     *
3581     *      [Conditional] branch, followed by addiu.
3582     */
3583    void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3584    {
3585            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3586                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3587    
3588            if (n_back < 2)
3589                    return;
3590    
3591            if (ic[-2].f == instr(addiu) &&
3592                ic[-1].f == instr(bne_samepage)) {
3593                    ic[-2].f = instr(addiu_bne_samepage_addiu);
3594                    return;
3595            }
3596    
3597            if (ic[-1].f == instr(set)) {
3598                    ic[-1].f = instr(lui_addiu);
3599                    return;
3600            }
3601    
3602          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
3603                  ic[-1].f = instr(b_samepage_addiu);                  ic[-1].f = instr(b_samepage_addiu);
3604                  combined;                  return;
3605            }
3606    
3607            if (ic[-1].f == instr(beq_samepage)) {
3608                    ic[-1].f = instr(beq_samepage_addiu);
3609                    return;
3610            }
3611    
3612            if (ic[-1].f == instr(bne_samepage)) {
3613                    ic[-1].f = instr(bne_samepage_addiu);
3614                    return;
3615            }
3616    
3617            if (ic[-1].f == instr(jr_ra)) {
3618                    ic[-1].f = instr(jr_ra_addiu);
3619                    return;
3620          }          }
3621    
3622          /*  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 3637  void COMBINE(b_daddiu)(struct cpu *cpu,
3637    
3638          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
3639                  ic[-1].f = instr(b_samepage_daddiu);                  ic[-1].f = instr(b_samepage_daddiu);
                 combined;  
3640          }          }
3641    
3642          /*  TODO: other branches that are followed by daddiu should be here  */          /*  TODO: other branches that are followed by daddiu should be here  */
# Line 2593  X(to_be_translated) Line 3793  X(to_be_translated)
3793                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];                          ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3794                          if (rd == MIPS_GPR_ZERO)                          if (rd == MIPS_GPR_ZERO)
3795                                  ic->f = instr(nop);                                  ic->f = instr(nop);
3796                            if (ic->f == instr(sll))
3797                                    cpu->cd.mips.combination_check = COMBINE(sll);
3798                          break;                          break;
3799    
3800                  case SPECIAL_ADD:                  case SPECIAL_ADD:
# Line 2724  X(to_be_translated) Line 3926  X(to_be_translated)
3926                          default:if (rd == MIPS_GPR_ZERO)                          default:if (rd == MIPS_GPR_ZERO)
3927                                          ic->f = instr(nop);                                          ic->f = instr(nop);
3928                          }                          }
3929    
3930                            if (ic->f == instr(addu))
3931                                    cpu->cd.mips.combination_check = COMBINE(addu);
3932                          break;                          break;
3933    
3934                  case SPECIAL_JR:                  case SPECIAL_JR:
# Line 2767  X(to_be_translated) Line 3972  X(to_be_translated)
3972                          break;                          break;
3973    
3974                  case SPECIAL_BREAK:                  case SPECIAL_BREAK:
3975                          ic->f = instr(break);                          if (((iword >> 6) & 0xfffff) == 0x30378) {
3976                                    /*  "Magic trap" for REBOOT:  */
3977                                    ic->f = instr(reboot);
3978                            } else {
3979                                    ic->f = instr(break);
3980                            }
3981                          break;                          break;
3982    
3983                  case SPECIAL_SYNC:                  case SPECIAL_SYNC:
# Line 2883  X(to_be_translated) Line 4093  X(to_be_translated)
4093                  case HI6_XORI:    ic->f = instr(xori); break;                  case HI6_XORI:    ic->f = instr(xori); break;
4094                  }                  }
4095    
4096                    if (ic->arg[2] == 0) {
4097                            if ((cpu->is_32bit && ic->f == instr(addiu)) ||
4098                                (!cpu->is_32bit && ic->f == instr(daddiu))) {
4099                                    ic->f = instr(mov);
4100                                    ic->arg[2] = ic->arg[1];
4101                            }
4102                    }
4103    
4104                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
4105                          ic->f = instr(nop);                          ic->f = instr(nop);
4106    
4107                    if (ic->f == instr(ori))
4108                            cpu->cd.mips.combination_check = COMBINE(ori);
4109                  if (ic->f == instr(addiu))                  if (ic->f == instr(addiu))
4110                          cpu->cd.mips.combination_check = COMBINE(b_addiu);                          cpu->cd.mips.combination_check = COMBINE(addiu);
4111                  if (ic->f == instr(daddiu))                  if (ic->f == instr(daddiu))
4112                          cpu->cd.mips.combination_check = COMBINE(b_daddiu);                          cpu->cd.mips.combination_check = COMBINE(b_daddiu);
4113                  break;                  break;
# Line 2896  X(to_be_translated) Line 4116  X(to_be_translated)
4116                  ic->f = instr(set);                  ic->f = instr(set);
4117                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4118                  ic->arg[1] = (int32_t) (imm << 16);                  ic->arg[1] = (int32_t) (imm << 16);
4119                    /*  NOTE: Don't use arg[2] here. It can be used with
4120                        instruction combinations, to do lui + addiu, etc.  */
4121                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
4122                          ic->f = instr(nop);                          ic->f = instr(nop);
4123                  break;                  break;
# Line 2949  X(to_be_translated) Line 4171  X(to_be_translated)
4171                          case COP0_DERET:                          case COP0_DERET:
4172                                  ic->f = instr(deret);                                  ic->f = instr(deret);
4173                                  break;                                  break;
4174                          case COP0_IDLE:                          case COP0_WAIT:
4175                                    ic->f = instr(wait);
4176                                    if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
4177                                        cpu->cd.mips.cpu_type.isa_level < 32) {
4178                                            static int warned = 0;
4179                                            ic->f = instr(reserved);
4180                                            if (!warned) {
4181                                                    fatal("{ WARNING: Attempt to "
4182                                                        "execute the WAIT instruct"
4183                                                        "ion, but the emulated CPU "
4184                                                        "is neither RM52xx, nor "
4185                                                        "MIPS32/64! }\n");
4186                                                    warned = 1;
4187                                            }
4188                                    }
4189                                    break;
4190                          case COP0_STANDBY:                          case COP0_STANDBY:
4191                          case COP0_SUSPEND:                          case COP0_SUSPEND:
4192                          case COP0_HIBERNATE:                          case COP0_HIBERNATE:
# Line 3000  X(to_be_translated) Line 4237  X(to_be_translated)
4237                          ic->arg[1] = rd + ((iword & 7) << 5);                          ic->arg[1] = rd + ((iword & 7) << 5);
4238                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
4239                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
4240    
4241                            if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
4242                                rs == COPz_MTCz && rd == COP0_STATUS)
4243                                    cpu->cd.mips.combination_check =
4244                                        COMBINE(netbsd_r3k_cache_inv);
4245    
4246                          break;                          break;
4247                  case 8: if (iword == 0x4100ffff) {                  case 8: if (iword == 0x4100ffff) {
4248                                  /*  R2020 DECstation write-loop thingy.  */                                  /*  R2020 DECstation write-loop thingy.  */
# Line 3317  X(to_be_translated) Line 4560  X(to_be_translated)
4560                  /*  Load into the dummy scratch register, if rt = zero  */                  /*  Load into the dummy scratch register, if rt = zero  */
4561                  if (!store && rt == MIPS_GPR_ZERO)                  if (!store && rt == MIPS_GPR_ZERO)
4562                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4563    
4564                    /*  Check for multiple loads or stores in a row using the same
4565                        base register:  */
4566    #ifdef MODE32
4567                    if (main_opcode == HI6_LW)
4568                            cpu->cd.mips.combination_check = COMBINE(multi_lw);
4569                    if (main_opcode == HI6_SW)
4570                            cpu->cd.mips.combination_check = COMBINE(multi_sw);
4571    #endif
4572                  break;                  break;
4573    
4574          case HI6_LL:          case HI6_LL:
# Line 3436  X(to_be_translated) Line 4688  X(to_be_translated)
4688                      cpu->cd.mips.cpu_type.isa_revision < 2) {                      cpu->cd.mips.cpu_type.isa_revision < 2) {
4689                          static int warning = 0;                          static int warning = 0;
4690                          if (!warning) {                          if (!warning) {
4691                                  fatal("[ WARNING! SPECIAL3 opcode used on a"                                  fatal("[ WARNING! SPECIAL3 opcode used, but"
4692                                      " cpu which doesn't implement it ]\n");                                      " the %s processor does not implement "
4693                                        "such instructions. Only printing this "
4694                                        "warning once. ]\n",
4695                                        cpu->cd.mips.cpu_type.name);
4696                                  warning = 1;                                  warning = 1;
4697                          }                          }
4698                          ic->f = instr(reserved);                          ic->f = instr(reserved);
# Line 3486  X(to_be_translated) Line 4741  X(to_be_translated)
4741          }          }
4742  #endif  #endif
4743    
4744            if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL)
4745                    cpu->cd.mips.combination_check = COMBINE(nop);
4746    
4747    
4748  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4749  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"

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

  ViewVC Help
Powered by ViewVC 1.1.26