Annotation of qemu/target-mips/op_helper.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  *  MIPS emulation helpers for qemu.
                      3:  * 
                      4:  *  Copyright (c) 2004-2005 Jocelyn Mayer
                      5:  *
                      6:  * This library is free software; you can redistribute it and/or
                      7:  * modify it under the terms of the GNU Lesser General Public
                      8:  * License as published by the Free Software Foundation; either
                      9:  * version 2 of the License, or (at your option) any later version.
                     10:  *
                     11:  * This library is distributed in the hope that it will be useful,
                     12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * Lesser General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU Lesser General Public
                     17:  * License along with this library; if not, write to the Free Software
                     18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     19:  */
                     20: #include <math.h>
                     21: #include "exec.h"
                     22: 
                     23: #define MIPS_DEBUG_DISAS
                     24: 
1.1.1.2 ! root       25: #define GETPC() (__builtin_return_address(0))
        !            26: 
1.1       root       27: /*****************************************************************************/
                     28: /* Exceptions processing helpers */
                     29: void cpu_loop_exit(void)
                     30: {
                     31:     longjmp(env->jmp_env, 1);
                     32: }
                     33: 
                     34: void do_raise_exception_err (uint32_t exception, int error_code)
                     35: {
                     36: #if 1
                     37:     if (logfile && exception < 0x100)
                     38:         fprintf(logfile, "%s: %d %d\n", __func__, exception, error_code);
                     39: #endif
                     40:     env->exception_index = exception;
                     41:     env->error_code = error_code;
                     42:     T0 = 0;
                     43:     cpu_loop_exit();
                     44: }
                     45: 
                     46: void do_raise_exception (uint32_t exception)
                     47: {
                     48:     do_raise_exception_err(exception, 0);
                     49: }
                     50: 
1.1.1.2 ! root       51: void do_restore_state (void *pc_ptr)
        !            52: {
        !            53:   TranslationBlock *tb;
        !            54:   unsigned long pc = (unsigned long) pc_ptr;
        !            55: 
        !            56:   tb = tb_find_pc (pc);
        !            57:   cpu_restore_state (tb, env, pc, NULL);
        !            58: }
        !            59: 
        !            60: void do_raise_exception_direct (uint32_t exception)
        !            61: {
        !            62:     do_restore_state (GETPC ());
        !            63:     do_raise_exception_err (exception, 0);
        !            64: }
        !            65: 
1.1       root       66: #define MEMSUFFIX _raw
                     67: #include "op_helper_mem.c"
                     68: #undef MEMSUFFIX
                     69: #if !defined(CONFIG_USER_ONLY)
                     70: #define MEMSUFFIX _user
                     71: #include "op_helper_mem.c"
                     72: #undef MEMSUFFIX
                     73: #define MEMSUFFIX _kernel
                     74: #include "op_helper_mem.c"
                     75: #undef MEMSUFFIX
                     76: #endif
                     77: 
                     78: /* 64 bits arithmetic for 32 bits hosts */
                     79: #if (HOST_LONG_BITS == 32)
                     80: static inline uint64_t get_HILO (void)
                     81: {
                     82:     return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
                     83: }
                     84: 
                     85: static inline void set_HILO (uint64_t HILO)
                     86: {
                     87:     env->LO = HILO & 0xFFFFFFFF;
                     88:     env->HI = HILO >> 32;
                     89: }
                     90: 
                     91: void do_mult (void)
                     92: {
1.1.1.2 ! root       93:     set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1       root       94: }
                     95: 
                     96: void do_multu (void)
                     97: {
                     98:     set_HILO((uint64_t)T0 * (uint64_t)T1);
                     99: }
                    100: 
                    101: void do_madd (void)
                    102: {
                    103:     int64_t tmp;
                    104: 
1.1.1.2 ! root      105:     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1       root      106:     set_HILO((int64_t)get_HILO() + tmp);
                    107: }
                    108: 
                    109: void do_maddu (void)
                    110: {
                    111:     uint64_t tmp;
                    112: 
                    113:     tmp = ((uint64_t)T0 * (uint64_t)T1);
                    114:     set_HILO(get_HILO() + tmp);
                    115: }
                    116: 
                    117: void do_msub (void)
                    118: {
                    119:     int64_t tmp;
                    120: 
1.1.1.2 ! root      121:     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1       root      122:     set_HILO((int64_t)get_HILO() - tmp);
                    123: }
                    124: 
                    125: void do_msubu (void)
                    126: {
                    127:     uint64_t tmp;
                    128: 
                    129:     tmp = ((uint64_t)T0 * (uint64_t)T1);
                    130:     set_HILO(get_HILO() - tmp);
                    131: }
                    132: #endif
                    133: 
1.1.1.2 ! root      134: #if defined(CONFIG_USER_ONLY) 
        !           135: void do_mfc0 (int reg, int sel)
        !           136: {
        !           137:     cpu_abort(env, "mfc0 reg=%d sel=%d\n", reg, sel);
        !           138: }
        !           139: void do_mtc0 (int reg, int sel)
        !           140: {
        !           141:     cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel);
        !           142: }
        !           143: 
        !           144: void do_tlbwi (void)
        !           145: {
        !           146:     cpu_abort(env, "tlbwi\n");
        !           147: }
        !           148: 
        !           149: void do_tlbwr (void)
        !           150: {
        !           151:     cpu_abort(env, "tlbwr\n");
        !           152: }
        !           153: 
        !           154: void do_tlbp (void)
        !           155: {
        !           156:     cpu_abort(env, "tlbp\n");
        !           157: }
        !           158: 
        !           159: void do_tlbr (void)
        !           160: {
        !           161:     cpu_abort(env, "tlbr\n");
        !           162: }
        !           163: #else
        !           164: 
1.1       root      165: /* CP0 helpers */
                    166: void do_mfc0 (int reg, int sel)
                    167: {
                    168:     const unsigned char *rn;
                    169: 
                    170:     if (sel != 0 && reg != 16 && reg != 28) {
                    171:         rn = "invalid";
                    172:         goto print;
                    173:     }
                    174:     switch (reg) {
                    175:     case 0:
                    176:         T0 = env->CP0_index;
                    177:         rn = "Index";
                    178:         break;
                    179:     case 1:
                    180:         T0 = cpu_mips_get_random(env);
                    181:         rn = "Random";
                    182:         break;
                    183:     case 2:
                    184:         T0 = env->CP0_EntryLo0;
                    185:         rn = "EntryLo0";
                    186:         break;
                    187:     case 3:
                    188:         T0 = env->CP0_EntryLo1;
                    189:         rn = "EntryLo1";
                    190:         break;
                    191:     case 4:
                    192:         T0 = env->CP0_Context;
                    193:         rn = "Context";
                    194:         break;
                    195:     case 5:
                    196:         T0 = env->CP0_PageMask;
                    197:         rn = "PageMask";
                    198:         break;
                    199:     case 6:
                    200:         T0 = env->CP0_Wired;
                    201:         rn = "Wired";
                    202:         break;
                    203:     case 8:
                    204:         T0 = env->CP0_BadVAddr;
                    205:         rn = "BadVaddr";
                    206:         break;
                    207:     case 9:
                    208:         T0 = cpu_mips_get_count(env);
                    209:         rn = "Count";
                    210:         break;
                    211:     case 10:
                    212:         T0 = env->CP0_EntryHi;
                    213:         rn = "EntryHi";
                    214:         break;
                    215:     case 11:
                    216:         T0 = env->CP0_Compare;
                    217:         rn = "Compare";
                    218:         break;
                    219:     case 12:
                    220:         T0 = env->CP0_Status;
                    221:         if (env->hflags & MIPS_HFLAG_UM)
                    222:             T0 |= (1 << CP0St_UM);
                    223:         if (env->hflags & MIPS_HFLAG_ERL)
                    224:             T0 |= (1 << CP0St_ERL);
                    225:         if (env->hflags & MIPS_HFLAG_EXL)
                    226:             T0 |= (1 << CP0St_EXL);
                    227:         rn = "Status";
                    228:         break;
                    229:     case 13:
                    230:         T0 = env->CP0_Cause;
                    231:         rn = "Cause";
                    232:         break;
                    233:     case 14:
                    234:         T0 = env->CP0_EPC;
                    235:         rn = "EPC";
                    236:         break;
                    237:     case 15:
                    238:         T0 = env->CP0_PRid;
                    239:         rn = "PRid";
                    240:         break;
                    241:     case 16:
                    242:         switch (sel) {
                    243:         case 0:
                    244:             T0 = env->CP0_Config0;
                    245:             rn = "Config";
                    246:             break;
                    247:         case 1:
                    248:             T0 = env->CP0_Config1;
                    249:             rn = "Config1";
                    250:             break;
                    251:         default:
                    252:             rn = "Unknown config register";
                    253:             break;
                    254:         }
                    255:         break;
                    256:     case 17:
                    257:         T0 = env->CP0_LLAddr >> 4;
                    258:         rn = "LLAddr";
                    259:         break;
                    260:     case 18:
                    261:         T0 = env->CP0_WatchLo;
                    262:         rn = "WatchLo";
                    263:         break;
                    264:     case 19:
                    265:         T0 = env->CP0_WatchHi;
                    266:         rn = "WatchHi";
                    267:         break;
                    268:     case 23:
                    269:         T0 = env->CP0_Debug;
                    270:         if (env->hflags & MIPS_HFLAG_DM)
                    271:             T0 |= 1 << CP0DB_DM;
                    272:         rn = "Debug";
                    273:         break;
                    274:     case 24:
                    275:         T0 = env->CP0_DEPC;
                    276:         rn = "DEPC";
                    277:         break;
                    278:     case 28:
                    279:         switch (sel) {
                    280:         case 0:
                    281:             T0 = env->CP0_TagLo;
                    282:             rn = "TagLo";
                    283:             break;
                    284:         case 1:
                    285:             T0 = env->CP0_DataLo;
                    286:             rn = "DataLo";
                    287:             break;
                    288:         default:
                    289:             rn = "unknown sel";
                    290:             break;
                    291:         }
                    292:         break;
                    293:     case 30:
                    294:         T0 = env->CP0_ErrorEPC;
                    295:         rn = "ErrorEPC";
                    296:         break;
                    297:     case 31:
                    298:         T0 = env->CP0_DESAVE;
                    299:         rn = "DESAVE";
                    300:         break;
                    301:     default:
                    302:         rn = "unknown";
                    303:         break;
                    304:     }
                    305:  print:
                    306: #if defined MIPS_DEBUG_DISAS
                    307:     if (loglevel & CPU_LOG_TB_IN_ASM) {
                    308:         fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n",
                    309:                 env->PC, rn, T0, reg, sel);
                    310:     }
                    311: #endif
                    312:     return;
                    313: }
                    314: 
                    315: void do_mtc0 (int reg, int sel)
                    316: {
                    317:     const unsigned char *rn;
                    318:     uint32_t val, old, mask;
                    319: 
                    320:     if (sel != 0 && reg != 16 && reg != 28) {
                    321:         val = -1;
                    322:         old = -1;
                    323:         rn = "invalid";
                    324:         goto print;
                    325:     }
                    326:     switch (reg) {
                    327:     case 0:
                    328:         val = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F);
                    329:         old = env->CP0_index;
                    330:         env->CP0_index = val;
                    331:         rn = "Index";
                    332:         break;
                    333:     case 2:
                    334:         val = T0 & 0x03FFFFFFF;
                    335:         old = env->CP0_EntryLo0;
                    336:         env->CP0_EntryLo0 = val;
                    337:         rn = "EntryLo0";
                    338:         break;
                    339:     case 3:
                    340:         val = T0 & 0x03FFFFFFF;
                    341:         old = env->CP0_EntryLo1;
                    342:         env->CP0_EntryLo1 = val;
                    343:         rn = "EntryLo1";
                    344:         break;
                    345:     case 4:
                    346:         val = (env->CP0_Context & 0xFF000000) | (T0 & 0x00FFFFF0);
                    347:         old = env->CP0_Context;
                    348:         env->CP0_Context = val;
                    349:         rn = "Context";
                    350:         break;
                    351:     case 5:
                    352:         val = T0 & 0x01FFE000;
                    353:         old = env->CP0_PageMask;
                    354:         env->CP0_PageMask = val;
                    355:         rn = "PageMask";
                    356:         break;
                    357:     case 6:
                    358:         val = T0 & 0x0000000F;
                    359:         old = env->CP0_Wired;
                    360:         env->CP0_Wired = val;
                    361:         rn = "Wired";
                    362:         break;
                    363:     case 9:
                    364:         val = T0;
                    365:         old = cpu_mips_get_count(env);
                    366:         cpu_mips_store_count(env, val);
                    367:         rn = "Count";
                    368:         break;
                    369:     case 10:
                    370:         val = T0 & 0xFFFFF0FF;
                    371:         old = env->CP0_EntryHi;
                    372:         env->CP0_EntryHi = val;
1.1.1.2 ! root      373:        /* If the ASID changes, flush qemu's TLB.  */
        !           374:        if ((old & 0xFF) != (val & 0xFF))
        !           375:          tlb_flush (env, 1);
1.1       root      376:         rn = "EntryHi";
                    377:         break;
                    378:     case 11:
                    379:         val = T0;
                    380:         old = env->CP0_Compare;
                    381:         cpu_mips_store_compare(env, val);
                    382:         rn = "Compare";
                    383:         break;
                    384:     case 12:
                    385:         val = T0 & 0xFA78FF01;
                    386:         if (T0 & (1 << CP0St_UM))
                    387:             env->hflags |= MIPS_HFLAG_UM;
                    388:         else
                    389:             env->hflags &= ~MIPS_HFLAG_UM;
                    390:         if (T0 & (1 << CP0St_ERL))
                    391:             env->hflags |= MIPS_HFLAG_ERL;
                    392:         else
                    393:             env->hflags &= ~MIPS_HFLAG_ERL;
                    394:         if (T0 & (1 << CP0St_EXL))
                    395:             env->hflags |= MIPS_HFLAG_EXL;
                    396:         else
                    397:             env->hflags &= ~MIPS_HFLAG_EXL;
                    398:         old = env->CP0_Status;
                    399:         env->CP0_Status = val;
                    400:         /* If we unmasked an asserted IRQ, raise it */
                    401:         mask = 0x0000FF00;
                    402:         if (loglevel & CPU_LOG_TB_IN_ASM) {
                    403:             fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n",
                    404:                     old, val, env->CP0_Cause, old & mask, val & mask,
                    405:                     env->CP0_Cause & mask);
                    406:         }
                    407: #if 1
                    408:         if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) &&
                    409:             !(env->hflags & MIPS_HFLAG_EXL) &&
                    410:             !(env->hflags & MIPS_HFLAG_ERL) &&
                    411:             !(env->hflags & MIPS_HFLAG_DM) && 
                    412:             (env->CP0_Status & env->CP0_Cause & mask)) {
                    413:             if (logfile)
                    414:                 fprintf(logfile, "Raise pending IRQs\n");
                    415:             env->interrupt_request |= CPU_INTERRUPT_HARD;
                    416:             do_raise_exception(EXCP_EXT_INTERRUPT);
                    417:         } else if (!(val & 0x00000001) && (old & 0x00000001)) {
                    418:             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
                    419:         }
                    420: #endif
                    421:         rn = "Status";
                    422:         break;
                    423:     case 13:
                    424:         val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300);
                    425:         old = env->CP0_Cause;
                    426:         env->CP0_Cause = val;
                    427: #if 0
                    428:         {
                    429:             int i;
                    430:             /* Check if we ever asserted a software IRQ */
                    431:             for (i = 0; i < 2; i++) {
                    432:                 mask = 0x100 << i;
                    433:                 if ((val & mask) & !(old & mask))
                    434:                     mips_set_irq(i);
                    435:             }
                    436:         }
                    437: #endif
                    438:         rn = "Cause";
                    439:         break;
                    440:     case 14:
                    441:         val = T0;
                    442:         old = env->CP0_EPC;
                    443:         env->CP0_EPC = val;
                    444:         rn = "EPC";
                    445:         break;
                    446:     case 16:
                    447:         switch (sel) {
                    448:         case 0:
                    449: #if defined(MIPS_USES_R4K_TLB)
                    450:             val = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001);
                    451: #else
                    452:             val = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001);
                    453: #endif
                    454:             old = env->CP0_Config0;
                    455:             env->CP0_Config0 = val;
                    456:             rn = "Config0";
                    457:             break;
                    458:         default:
                    459:             val = -1;
                    460:             old = -1;
                    461:             rn = "bad config selector";
                    462:             break;
                    463:         }
                    464:         break;
                    465:     case 18:
                    466:         val = T0;
                    467:         old = env->CP0_WatchLo;
                    468:         env->CP0_WatchLo = val;
                    469:         rn = "WatchLo";
                    470:         break;
                    471:     case 19:
                    472:         val = T0 & 0x40FF0FF8;
                    473:         old = env->CP0_WatchHi;
                    474:         env->CP0_WatchHi = val;
                    475:         rn = "WatchHi";
                    476:         break;
                    477:     case 23:
                    478:         val = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120);
                    479:         if (T0 & (1 << CP0DB_DM))
                    480:             env->hflags |= MIPS_HFLAG_DM;
                    481:         else
                    482:             env->hflags &= ~MIPS_HFLAG_DM;
                    483:         old = env->CP0_Debug;
                    484:         env->CP0_Debug = val;
                    485:         rn = "Debug";
                    486:         break;
                    487:     case 24:
                    488:         val = T0;
                    489:         old = env->CP0_DEPC;
                    490:         env->CP0_DEPC = val;
                    491:         rn = "DEPC";
                    492:         break;
                    493:     case 28:
                    494:         switch (sel) {
                    495:         case 0:
                    496:             val = T0 & 0xFFFFFCF6;
                    497:             old = env->CP0_TagLo;
                    498:             env->CP0_TagLo = val;
                    499:             rn = "TagLo";
                    500:             break;
                    501:         default:
                    502:             val = -1;
                    503:             old = -1;
                    504:             rn = "invalid sel";
                    505:             break;
                    506:         }
                    507:         break;
                    508:     case 30:
                    509:         val = T0;
                    510:         old = env->CP0_ErrorEPC;
                    511:         env->CP0_ErrorEPC = val;
                    512:         rn = "EPC";
                    513:         break;
                    514:     case 31:
                    515:         val = T0;
                    516:         old = env->CP0_DESAVE;
                    517:         env->CP0_DESAVE = val;
                    518:         rn = "DESAVE";
                    519:         break;
                    520:     default:
                    521:         val = -1;
                    522:         old = -1;
                    523:         rn = "unknown";
                    524:         break;
                    525:     }
                    526:  print:
                    527: #if defined MIPS_DEBUG_DISAS
                    528:     if (loglevel & CPU_LOG_TB_IN_ASM) {
                    529:         fprintf(logfile, "%08x mtc0 %s %08x => %08x (%d %d %08x)\n",
                    530:                 env->PC, rn, T0, val, reg, sel, old);
                    531:     }
                    532: #endif
                    533:     return;
                    534: }
                    535: 
                    536: /* TLB management */
                    537: #if defined(MIPS_USES_R4K_TLB)
                    538: static void invalidate_tb (int idx)
                    539: {
                    540:     tlb_t *tlb;
                    541:     target_ulong addr, end;
                    542: 
                    543:     tlb = &env->tlb[idx];
                    544:     if (tlb->V[0]) {
                    545:         addr = tlb->PFN[0];
                    546:         end = addr + (tlb->end - tlb->VPN);
                    547:         tb_invalidate_page_range(addr, end);
1.1.1.2 ! root      548:         /* FIXME: Might be faster to just invalidate the whole "tlb" here
        !           549:            and refill it on demand from our simulated TLB.  */
        !           550:         addr = tlb->VPN;
        !           551:         while (addr < tlb->end) {
        !           552:             tlb_flush_page (env, addr);
        !           553:             addr += TARGET_PAGE_SIZE;
        !           554:         }
1.1       root      555:     }
                    556:     if (tlb->V[1]) {
                    557:         addr = tlb->PFN[1];
                    558:         end = addr + (tlb->end - tlb->VPN);
                    559:         tb_invalidate_page_range(addr, end);
1.1.1.2 ! root      560:         /* FIXME: Might be faster to just invalidate the whole "tlb" here
        !           561:            and refill it on demand from our simulated TLB.  */
        !           562:         addr = tlb->end;
        !           563:         while (addr < tlb->end2) {
        !           564:             tlb_flush_page (env, addr);
        !           565:             addr += TARGET_PAGE_SIZE;
        !           566:         }
1.1       root      567:     }
                    568: }
                    569: 
                    570: static void fill_tb (int idx)
                    571: {
                    572:     tlb_t *tlb;
                    573:     int size;
                    574: 
                    575:     /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
                    576:     tlb = &env->tlb[idx];
                    577:     tlb->VPN = env->CP0_EntryHi & 0xFFFFE000;
                    578:     tlb->ASID = env->CP0_EntryHi & 0x000000FF;
                    579:     size = env->CP0_PageMask >> 13;
                    580:     size = 4 * (size + 1);
                    581:     tlb->end = tlb->VPN + (1 << (8 + size));
1.1.1.2 ! root      582:     tlb->end2 = tlb->end + (1 << (8 + size));
1.1       root      583:     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
                    584:     tlb->V[0] = env->CP0_EntryLo0 & 2;
                    585:     tlb->D[0] = env->CP0_EntryLo0 & 4;
                    586:     tlb->C[0] = (env->CP0_EntryLo0 >> 3) & 0x7;
                    587:     tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
                    588:     tlb->V[1] = env->CP0_EntryLo1 & 2;
                    589:     tlb->D[1] = env->CP0_EntryLo1 & 4;
                    590:     tlb->C[1] = (env->CP0_EntryLo1 >> 3) & 0x7;
                    591:     tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
                    592: }
                    593: 
                    594: void do_tlbwi (void)
                    595: {
                    596:     /* Wildly undefined effects for CP0_index containing a too high value and
                    597:        MIPS_TLB_NB not being a power of two.  But so does real silicon.  */
                    598:     invalidate_tb(env->CP0_index & (MIPS_TLB_NB - 1));
                    599:     fill_tb(env->CP0_index & (MIPS_TLB_NB - 1));
                    600: }
                    601: 
                    602: void do_tlbwr (void)
                    603: {
                    604:     int r = cpu_mips_get_random(env);
                    605: 
                    606:     invalidate_tb(r);
                    607:     fill_tb(r);
                    608: }
                    609: 
                    610: void do_tlbp (void)
                    611: {
                    612:     tlb_t *tlb;
                    613:     target_ulong tag;
                    614:     uint8_t ASID;
                    615:     int i;
                    616: 
                    617:     tag = (env->CP0_EntryHi & 0xFFFFE000);
                    618:     ASID = env->CP0_EntryHi & 0x000000FF;
                    619:         for (i = 0; i < MIPS_TLB_NB; i++) {
                    620:         tlb = &env->tlb[i];
                    621:         /* Check ASID, virtual page number & size */
                    622:         if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
                    623:             /* TLB match */
                    624:             env->CP0_index = i;
                    625:             break;
                    626:         }
                    627:     }
                    628:     if (i == MIPS_TLB_NB) {
                    629:         env->CP0_index |= 0x80000000;
                    630:     }
                    631: }
                    632: 
                    633: void do_tlbr (void)
                    634: {
                    635:     tlb_t *tlb;
                    636:     int size;
                    637: 
                    638:     tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)];
1.1.1.2 ! root      639: 
        !           640:     /* If this will change the current ASID, flush qemu's TLB.  */
        !           641:     /* FIXME: Could avoid flushing things which match global entries... */
        !           642:     if ((env->CP0_EntryHi & 0xFF) != tlb->ASID)
        !           643:       tlb_flush (env, 1);
        !           644: 
1.1       root      645:     env->CP0_EntryHi = tlb->VPN | tlb->ASID;
                    646:     size = (tlb->end - tlb->VPN) >> 12;
                    647:     env->CP0_PageMask = (size - 1) << 13;
                    648:     env->CP0_EntryLo0 = tlb->V[0] | tlb->D[0] | (tlb->C[0] << 3) |
                    649:         (tlb->PFN[0] >> 6);
                    650:     env->CP0_EntryLo1 = tlb->V[1] | tlb->D[1] | (tlb->C[1] << 3) |
                    651:         (tlb->PFN[1] >> 6);
                    652: }
                    653: #endif
                    654: 
1.1.1.2 ! root      655: #endif /* !CONFIG_USER_ONLY */
        !           656: 
1.1       root      657: void op_dump_ldst (const unsigned char *func)
                    658: {
                    659:     if (loglevel)
                    660:         fprintf(logfile, "%s => %08x %08x\n", __func__, T0, T1);
                    661: }
                    662: 
                    663: void dump_sc (void)
                    664: {
                    665:     if (loglevel) {
                    666:         fprintf(logfile, "%s %08x at %08x (%08x)\n", __func__,
                    667:                 T1, T0, env->CP0_LLAddr);
                    668:     }
                    669: }
                    670: 
                    671: void debug_eret (void)
                    672: {
                    673:     if (loglevel) {
                    674:         fprintf(logfile, "ERET: pc %08x EPC %08x ErrorEPC %08x (%d)\n",
                    675:                 env->PC, env->CP0_EPC, env->CP0_ErrorEPC,
                    676:                 env->hflags & MIPS_HFLAG_ERL ? 1 : 0);
                    677:     }
                    678: }
                    679: 
                    680: void do_pmon (int function)
                    681: {
                    682:     function /= 2;
                    683:     switch (function) {
                    684:     case 2: /* TODO: char inbyte(int waitflag); */
                    685:         if (env->gpr[4] == 0)
                    686:             env->gpr[2] = -1;
                    687:         /* Fall through */
                    688:     case 11: /* TODO: char inbyte (void); */
                    689:         env->gpr[2] = -1;
                    690:         break;
                    691:     case 3:
                    692:     case 12:
                    693:         printf("%c", env->gpr[4] & 0xFF);
                    694:         break;
                    695:     case 17:
                    696:         break;
                    697:     case 158:
                    698:         {
                    699:             unsigned char *fmt = (void *)env->gpr[4];
                    700:             printf("%s", fmt);
                    701:         }
                    702:         break;
                    703:     }
                    704: }
                    705: 
                    706: #if !defined(CONFIG_USER_ONLY) 
                    707: 
1.1.1.2 ! root      708: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
        !           709: 
1.1       root      710: #define MMUSUFFIX _mmu
1.1.1.2 ! root      711: #define ALIGNED_ONLY
1.1       root      712: 
                    713: #define SHIFT 0
                    714: #include "softmmu_template.h"
                    715: 
                    716: #define SHIFT 1
                    717: #include "softmmu_template.h"
                    718: 
                    719: #define SHIFT 2
                    720: #include "softmmu_template.h"
                    721: 
                    722: #define SHIFT 3
                    723: #include "softmmu_template.h"
                    724: 
1.1.1.2 ! root      725: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
        !           726: {
        !           727:     env->CP0_BadVAddr = addr;
        !           728:     do_restore_state (retaddr);
        !           729:     do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
        !           730: }
        !           731: 
1.1       root      732: void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
                    733: {
                    734:     TranslationBlock *tb;
                    735:     CPUState *saved_env;
                    736:     unsigned long pc;
                    737:     int ret;
                    738: 
                    739:     /* XXX: hack to restore env in all cases, even if not called from
                    740:        generated code */
                    741:     saved_env = env;
                    742:     env = cpu_single_env;
                    743:     ret = cpu_mips_handle_mmu_fault(env, addr, is_write, is_user, 1);
                    744:     if (ret) {
                    745:         if (retaddr) {
                    746:             /* now we have a real cpu fault */
                    747:             pc = (unsigned long)retaddr;
                    748:             tb = tb_find_pc(pc);
                    749:             if (tb) {
                    750:                 /* the PC is inside the translated code. It means that we have
                    751:                    a virtual CPU fault */
                    752:                 cpu_restore_state(tb, env, pc, NULL);
                    753:             }
                    754:         }
                    755:         do_raise_exception_err(env->exception_index, env->error_code);
                    756:     }
                    757:     env = saved_env;
                    758: }
                    759: 
                    760: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.