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

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

unix.superglobalmegacorp.com

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