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

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

unix.superglobalmegacorp.com

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