/[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 27 by dpavlin, Mon Oct 8 16:20:10 2007 UTC revision 28 by dpavlin, Mon Oct 8 16:20:26 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.97 2006/07/20 03:20:03 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 1849  X(tlbr) Line 1896  X(tlbr)
1896   */   */
1897  X(rfe)  X(rfe)
1898  {  {
1899          coproc_rfe(cpu);          /*  Just rotate the interrupt/user bits:  */
1900            cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
1901                (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
1902                ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
1903    
1904          /*  Note: no pc to pointers conversion is necessary here.  */          /*
1905             *  Note: no pc to pointers conversion is necessary here. Usually the
1906             *  rfe instruction resides in the delay slot of a jr k0/k1, and
1907             *  it is up to that instruction to do the pointer conversion.
1908             */
1909  }  }
1910    
1911    
1912  /*  /*
1913   *  eret: Return from exception handler   *  eret: Return from exception handler (non-R3000 style)
1914   */   */
1915  X(eret)  X(eret)
1916  {  {
1917          coproc_eret(cpu);          if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1918                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1919                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1920            } else {
1921                    cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1922                    cpu->delay_slot = 0;            
1923                    cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1924            }
1925    
1926          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
1927    
1928            cpu->cd.mips.rmw = 0;   /*  the "LL bit"  */
1929  }  }
1930    
1931    
# Line 2297  X(ei_r5900) Line 2361  X(ei_r5900)
2361    
2362    
2363  /*  /*
2364     *  sw_loop:
2365     *
2366     *  s:  addiu   rX,rX,4                 rX = arg[0] and arg[1]
2367     *      bne     rY,rX,s  (or rX,rY,s)   rt=arg[1], rs=arg[0]
2368     *      sw      rZ,-4(rX)               rt=arg[0], rs=arg[1]
2369     */
2370    X(sw_loop)
2371    {
2372            MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2373            uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2374            MODE_uint_t rY, bytes_to_write;
2375            unsigned char *page;
2376            int partial = 0;
2377    
2378            page = cpu->cd.mips.host_store[rX >> 12];
2379    
2380            /*  Fallback:  */
2381            if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2382                    instr(addiu)(cpu, ic);
2383                    return;
2384            }
2385    
2386            if (rYp == (uint64_t *) ic->arg[0])
2387                    rYp = (uint64_t *) ic[1].arg[1];
2388    
2389            rY = reg(rYp);
2390    
2391            bytes_to_write = rY - rX;
2392            if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2393                    bytes_to_write = 0x1000 - (rX & 0xfff);
2394                    partial = 1;
2395            }
2396    
2397            /*  printf("rX = %08x\n", (int)rX);
2398                printf("rY = %08x\n", (int)rY);
2399                printf("rZ = %08x\n", (int)rZ);
2400                printf("%i bytes\n", (int)bytes_to_write);  */
2401    
2402            memset(page + (rX & 0xfff), 0, bytes_to_write);
2403    
2404            reg(ic->arg[0]) = rX + bytes_to_write;
2405    
2406            cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2407            cpu->cd.mips.next_ic = partial?
2408                (struct mips_instr_call *) &ic[0] :
2409                (struct mips_instr_call *) &ic[3];
2410    }
2411    
2412    
2413    /*
2414     *  multi_sw_3:
2415     *
2416     *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2417     *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2418     *      sw      r?,ofs(rX)              r?=arg[0], rX=arg[1], ofs=arg[2]
2419     */
2420    X(multi_sw_3_le)
2421    {
2422            uint32_t *page;
2423            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2424            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2425            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2426            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2427            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2428                index2 = addr2 >> 12;
2429    
2430            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2431    
2432            /*  Fallback:  */
2433            if (cpu->delay_slot ||
2434                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2435                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2436                    /*  Normal safe sw:  */
2437                    ic[1].f(cpu, ic);
2438                    return;
2439            }
2440    
2441            addr0 = (addr0 >> 2) & 0x3ff;
2442            addr1 = (addr1 >> 2) & 0x3ff;
2443            addr2 = (addr2 >> 2) & 0x3ff;
2444    
2445            /*  printf("addr0=%x 1=%x 2=%x\n",
2446                (int)addr0, (int)addr1, (int)addr2);  */
2447    
2448            r1 = reg(ic[0].arg[0]);
2449            r2 = reg(ic[1].arg[0]);
2450            r3 = reg(ic[2].arg[0]);
2451    
2452            r1 = LE32_TO_HOST(r1);
2453            r2 = LE32_TO_HOST(r2);
2454            r3 = LE32_TO_HOST(r3);
2455    
2456            page[addr0] = r1;
2457            page[addr1] = r2;
2458            page[addr2] = r3;
2459    
2460            cpu->n_translated_instrs += 2;
2461            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];
2462    }
2463    X(multi_sw_3_be)
2464    {
2465            uint32_t *page;
2466            MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2467            MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2468            MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2469            MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2470            uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2471                index2 = addr2 >> 12;
2472    
2473            page = (uint32_t *) cpu->cd.mips.host_store[index0];
2474    
2475            /*  Fallback:  */
2476            if (cpu->delay_slot ||
2477                page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2478                (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2479                    /*  Normal safe sw:  */
2480                    ic[1].f(cpu, ic);
2481                    return;
2482            }
2483    
2484            addr0 = (addr0 >> 2) & 0x3ff;
2485            addr1 = (addr1 >> 2) & 0x3ff;
2486            addr2 = (addr2 >> 2) & 0x3ff;
2487    
2488            /*  printf("addr0=%x 1=%x 2=%x\n",
2489                (int)addr0, (int)addr1, (int)addr2);  */
2490    
2491            r1 = reg(ic[0].arg[0]);
2492            r2 = reg(ic[1].arg[0]);
2493            r3 = reg(ic[2].arg[0]);
2494    
2495            r1 = BE32_TO_HOST(r1);
2496            r2 = BE32_TO_HOST(r2);
2497            r3 = BE32_TO_HOST(r3);
2498    
2499            page[addr0] = r1;
2500            page[addr1] = r2;
2501            page[addr2] = r3;
2502    
2503            cpu->n_translated_instrs += 2;
2504            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[3];
2505    }
2506    
2507    
2508    /*
2509     *  netbsd_r3k_picache_do_inv:
2510     *
2511     *  ic[0]       mtc0    rV,status
2512     *     1        nop
2513     *     2        nop
2514     *     3  s:    addiu   rX,rX,4
2515     *     4        bne     rY,rX,s
2516     *     5        sb      zr,-4(rX)
2517     *     6        nop
2518     *     7        nop
2519     *     8        mtc0    rT,status
2520     */
2521    X(netbsd_r3k_picache_do_inv)
2522    {
2523            MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
2524    
2525            /*  Fallback if the environment isn't exactly right:  */
2526            if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
2527                (rx & 3) || (ry & 3) || cpu->delay_slot) {
2528                    instr(mtc0)(cpu, ic);
2529                    return;
2530            }
2531    
2532            reg(ic[3].arg[0]) = ry;
2533            cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
2534    
2535            /*  Run the last mtc0 instruction:  */
2536            cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
2537    }
2538    
2539    
2540    #ifdef MODE32
2541    /*
2542     *  netbsd_strlen():
2543     *
2544     *      lb      rV,0(rX)
2545     *   s: addiu   rX,rX,1
2546     *      bne     zr,rV,s
2547     *      nop
2548     */
2549    X(netbsd_strlen)
2550    {
2551            MODE_uint_t rx = reg(ic[0].arg[1]);
2552            MODE_int_t rv;
2553            signed char *page;
2554            uint32_t pageindex = rx >> 12;
2555            int i;
2556    
2557            page = (signed char *) cpu->cd.mips.host_load[pageindex];
2558    
2559            /*  Fallback:  */
2560            if (cpu->delay_slot || page == NULL) {
2561                    /*
2562                     *  Normal lb:  NOTE: It doesn't matter whether [1] or
2563                     *  [16+1] is called here, because endianness for 8-bit
2564                     *  loads is irrelevant. :-)
2565                     */
2566                    mips32_loadstore[1](cpu, ic);
2567                    return;
2568            }
2569    
2570            i = rx & 0xfff;
2571    
2572            /*
2573             *  TODO: This loop can be optimized further for optimal
2574             *  performance on the host, e.g. by reading full words...
2575             */
2576            do {
2577                    rv = page[i ++];
2578            } while (i < 0x1000 && rv != 0);
2579    
2580            cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
2581    
2582            reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
2583            reg(ic[2].arg[0]) = rv;
2584    
2585            /*  Done with the loop? Or continue on the next rx page?  */
2586            if (rv == 0)
2587                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
2588            else
2589                    cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
2590    }
2591    #endif
2592    
2593    
2594    /*
2595     *  lui_32bit:
2596     *
2597     *  Combination of lui and addiu.
2598     *  Note: All 32 bits of arg[2] of the lui instr_call are used.
2599     */
2600    X(lui_32bit)
2601    {
2602            reg(ic[0].arg[0]) = (int32_t) ic[0].arg[2];
2603            cpu->n_translated_instrs ++;
2604            cpu->cd.mips.next_ic ++;
2605    }
2606    
2607    
2608    /*
2609   *  b_samepage_addiu:   *  b_samepage_addiu:
2610   *   *
2611   *  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 2711  X(end_of_page2)
2711    
2712    
2713  /*  /*
2714   *  Combine: [Conditional] branch, followed by addiu.   *  Combine:  Memory fill loop (addiu, bne, sw)
2715     *
2716     *  s:  addiu   rX,rX,4
2717     *      bne     rY,rX,s
2718     *      sw      rZ,-4(rX)
2719   */   */
2720  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)
2721    {
2722            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2723                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2724    
2725            /*  Only for 32-bit virtual address translation so far.  */
2726            if (!cpu->is_32bit)
2727                    return;
2728    
2729            if (n_back < 2)
2730                    return;
2731    
2732            if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
2733                (int32_t)ic[-2].arg[2] == 4 &&
2734                ic[-1].f == instr(bne_samepage) &&
2735                (ic[-1].arg[0] == ic[-2].arg[0] ||
2736                    ic[-1].arg[1] == ic[-2].arg[0]) &&
2737                ic[-1].arg[0] != ic[-1].arg[1] &&
2738                ic[-1].arg[2] == (size_t) &ic[-2] &&
2739                ic[0].arg[0] != ic[0].arg[1] &&
2740                ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
2741                    ic[-2].f = instr(sw_loop);
2742                    combined;
2743            }
2744    }
2745    
2746    
2747    /*
2748     *  Combine:  Multiple SW in a row using the same base register
2749     *
2750     *      sw      r?,???(rX)
2751     *      sw      r?,???(rX)
2752     *      sw      r?,???(rX)
2753     *      ...
2754     */
2755    void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
2756          int low_addr)          int low_addr)
2757  {  {
2758          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2759              & (MIPS_IC_ENTRIES_PER_PAGE - 1);              & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2760    
2761            /*  Only for 32-bit virtual address translation so far.  */
2762            if (!cpu->is_32bit)
2763                    return;
2764    
2765            if (n_back < 4)
2766                    return;
2767    
2768            /*  Avoid "overlapping" instruction combinations:  */
2769            if (ic[-4].f == instr(multi_sw_3_be)||ic[-3].f == instr(multi_sw_3_be)||
2770                ic[-4].f == instr(multi_sw_3_le)||ic[-3].f == instr(multi_sw_3_le))
2771                    return;
2772    
2773            if (ic[-2].f == ic[0].f && ic[-1].f == ic[0].f &&
2774                ic[-2].arg[1] == ic[0].arg[1] &&
2775                ic[-1].arg[1] == ic[0].arg[1]) {
2776                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2777                            ic[-2].f = instr(multi_sw_3_le);
2778                    else
2779                            ic[-2].f = instr(multi_sw_3_be);
2780                    combined;
2781            }
2782    }
2783    
2784    
2785    /*
2786     *  Combine:  NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
2787     *
2788     *  Instruction cache loop:
2789     *
2790     *  ic[-8]      mtc0    rV,status
2791     *     -7       nop
2792     *     -6       nop
2793     *     -5  s:   addiu   rX,rX,4
2794     *     -4       bne     rY,rX,s
2795     *     -3       sb      zr,-4(rX)
2796     *     -2       nop
2797     *     -1       nop
2798     *      0       mtc0    rT,status
2799     */
2800    void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
2801            struct mips_instr_call *ic, int low_addr)
2802    {
2803            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2804                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2805    
2806            if (n_back < 8)
2807                    return;
2808    
2809            if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
2810                ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
2811                ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
2812                (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
2813                ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
2814                ic[-4].arg[2] == (size_t) &ic[-5] &&
2815                ic[-3].arg[1] == ic[-5].arg[0] &&
2816                ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
2817                    ic[-8].f = instr(netbsd_r3k_picache_do_inv);
2818                    combined;
2819            }
2820    }
2821    
2822    
2823    /*
2824     *  Combine: something ending with a nop.
2825     *
2826     *      NetBSD's strlen core.
2827     *      [Conditional] branch, followed by nop.
2828     */
2829    void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2830    {
2831            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2832                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2833    
2834    #ifdef MODE32
2835            if (n_back < 3)
2836                    return;
2837    
2838            if ((ic[-3].f == mips32_loadstore[1] ||
2839                ic[-3].f == mips32_loadstore[16 + 1]) &&
2840                ic[-3].arg[2] == 0 &&
2841                ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
2842                ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
2843                ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
2844                ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
2845                ic[-1].f == instr(bne_samepage)) {
2846                    ic[-3].f = instr(netbsd_strlen);
2847                    combined;
2848                    return;
2849            }
2850    #endif
2851    
2852          if (n_back < 1)          if (n_back < 1)
2853                  return;                  return;
2854    
2855            if (ic[-1].f == instr(bne_samepage)) {
2856                    ic[-1].f = instr(bne_samepage_nop);
2857                    combined;
2858                    return;
2859            }
2860    
2861            if (ic[-1].f == instr(beq_samepage)) {
2862                    ic[-1].f = instr(beq_samepage_nop);
2863                    combined;
2864                    return;
2865            }
2866    
2867            /*  TODO: other branches that are followed by nop should be here  */
2868    }
2869    
2870    
2871    /*
2872     *  Combine:
2873     *
2874     *      [Conditional] branch, followed by addiu.
2875     *      lui + addiu.
2876     */
2877    void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2878    {
2879            int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2880                & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2881    
2882            if (n_back < 1)
2883                    return;
2884    
2885            if (ic[-1].f == instr(set) && ic[-1].arg[0] == ic[0].arg[0] &&
2886                ic[0].arg[0] == ic[0].arg[1]) {
2887                    ic[-1].f = instr(lui_32bit);
2888                    ic[-1].arg[2] = (int32_t) (ic[-1].arg[1] + ic[0].arg[2]);
2889                    combined;
2890                    return;
2891            }
2892    
2893          if (ic[-1].f == instr(b_samepage)) {          if (ic[-1].f == instr(b_samepage)) {
2894                  ic[-1].f = instr(b_samepage_addiu);                  ic[-1].f = instr(b_samepage_addiu);
2895                  combined;                  combined;
2896                    return;
2897            }
2898    
2899            if (ic[-1].f == instr(beq_samepage)) {
2900                    ic[-1].f = instr(beq_samepage_addiu);
2901                    combined;
2902                    return;
2903            }
2904    
2905            if (ic[-1].f == instr(bne_samepage)) {
2906                    ic[-1].f = instr(bne_samepage_addiu);
2907                    combined;
2908                    return;
2909            }
2910    
2911            if (ic[-1].f == instr(jr_ra)) {
2912                    ic[-1].f = instr(jr_ra_addiu);
2913                    combined;
2914                    return;
2915          }          }
2916    
2917          /*  TODO: other branches that are followed by addiu should be here  */          /*  TODO: other branches that are followed by addiu should be here  */
# Line 2883  X(to_be_translated) Line 3379  X(to_be_translated)
3379                  case HI6_XORI:    ic->f = instr(xori); break;                  case HI6_XORI:    ic->f = instr(xori); break;
3380                  }                  }
3381    
3382                    if (ic->arg[2] == 0) {
3383                            if ((cpu->is_32bit && ic->f == instr(addiu)) ||
3384                                (!cpu->is_32bit && ic->f == instr(daddiu))) {
3385                                    ic->f = instr(mov);
3386                                    ic->arg[2] = ic->arg[1];
3387                            }
3388                    }
3389    
3390                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
3391                          ic->f = instr(nop);                          ic->f = instr(nop);
3392    
3393                  if (ic->f == instr(addiu))                  if (ic->f == instr(addiu))
3394                          cpu->cd.mips.combination_check = COMBINE(b_addiu);                          cpu->cd.mips.combination_check = COMBINE(addiu);
3395                  if (ic->f == instr(daddiu))                  if (ic->f == instr(daddiu))
3396                          cpu->cd.mips.combination_check = COMBINE(b_daddiu);                          cpu->cd.mips.combination_check = COMBINE(b_daddiu);
3397                  break;                  break;
# Line 2896  X(to_be_translated) Line 3400  X(to_be_translated)
3400                  ic->f = instr(set);                  ic->f = instr(set);
3401                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];                  ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3402                  ic->arg[1] = (int32_t) (imm << 16);                  ic->arg[1] = (int32_t) (imm << 16);
3403                    /*  NOTE: Don't use arg[2] here. It can be used with
3404                        instruction combinations, to do lui + addiu, etc.  */
3405                  if (rt == MIPS_GPR_ZERO)                  if (rt == MIPS_GPR_ZERO)
3406                          ic->f = instr(nop);                          ic->f = instr(nop);
3407                  break;                  break;
# Line 3000  X(to_be_translated) Line 3506  X(to_be_translated)
3506                          ic->arg[1] = rd + ((iword & 7) << 5);                          ic->arg[1] = rd + ((iword & 7) << 5);
3507                          ic->arg[2] = addr & 0xffc;                          ic->arg[2] = addr & 0xffc;
3508                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);                          ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
3509    
3510                            if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
3511                                rs == COPz_MTCz && rd == COP0_STATUS)
3512                                    cpu->cd.mips.combination_check =
3513                                        COMBINE(netbsd_r3k_cache_inv);
3514    
3515                          break;                          break;
3516                  case 8: if (iword == 0x4100ffff) {                  case 8: if (iword == 0x4100ffff) {
3517                                  /*  R2020 DECstation write-loop thingy.  */                                  /*  R2020 DECstation write-loop thingy.  */
# Line 3317  X(to_be_translated) Line 3829  X(to_be_translated)
3829                  /*  Load into the dummy scratch register, if rt = zero  */                  /*  Load into the dummy scratch register, if rt = zero  */
3830                  if (!store && rt == MIPS_GPR_ZERO)                  if (!store && rt == MIPS_GPR_ZERO)
3831                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;                          ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3832    
3833                    /*  Check for multiple stores in a row using the same
3834                        base register:  */
3835                    if (main_opcode == HI6_SW && rs == MIPS_GPR_SP)
3836                            cpu->cd.mips.combination_check = COMBINE(multi_sw);
3837    
3838                  break;                  break;
3839    
3840          case HI6_LL:          case HI6_LL:
# Line 3436  X(to_be_translated) Line 3954  X(to_be_translated)
3954                      cpu->cd.mips.cpu_type.isa_revision < 2) {                      cpu->cd.mips.cpu_type.isa_revision < 2) {
3955                          static int warning = 0;                          static int warning = 0;
3956                          if (!warning) {                          if (!warning) {
3957                                  fatal("[ WARNING! SPECIAL3 opcode used on a"                                  fatal("[ WARNING! SPECIAL3 opcode used, but"
3958                                      " cpu which doesn't implement it ]\n");                                      " the %s processor does not implement "
3959                                        "such instructions. Only printing this "
3960                                        "warning once. ]\n",
3961                                        cpu->cd.mips.cpu_type.name);
3962                                  warning = 1;                                  warning = 1;
3963                          }                          }
3964                          ic->f = instr(reserved);                          ic->f = instr(reserved);
# Line 3486  X(to_be_translated) Line 4007  X(to_be_translated)
4007          }          }
4008  #endif  #endif
4009    
4010            if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL)
4011                    cpu->cd.mips.combination_check = COMBINE(nop);
4012    
4013    
4014  #define DYNTRANS_TO_BE_TRANSLATED_TAIL  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4015  #include "cpu_dyntrans.c"  #include "cpu_dyntrans.c"

Legend:
Removed from v.27  
changed lines
  Added in v.28

  ViewVC Help
Powered by ViewVC 1.1.26