Annotation of qemu/target-alpha/helper.c, revision 1.1.1.5

1.1       root        1: /*
                      2:  *  Alpha emulation cpu helpers for qemu.
                      3:  *
                      4:  *  Copyright (c) 2007 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
1.1.1.3   root       17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1       root       18:  */
                     19: 
                     20: #include <stdint.h>
                     21: #include <stdlib.h>
                     22: #include <stdio.h>
                     23: 
                     24: #include "cpu.h"
                     25: #include "exec-all.h"
1.1.1.4   root       26: #include "softfloat.h"
                     27: 
                     28: uint64_t cpu_alpha_load_fpcr (CPUState *env)
                     29: {
                     30:     uint64_t r = 0;
                     31:     uint8_t t;
                     32: 
                     33:     t = env->fpcr_exc_status;
                     34:     if (t) {
                     35:         r = FPCR_SUM;
                     36:         if (t & float_flag_invalid) {
                     37:             r |= FPCR_INV;
                     38:         }
                     39:         if (t & float_flag_divbyzero) {
                     40:             r |= FPCR_DZE;
                     41:         }
                     42:         if (t & float_flag_overflow) {
                     43:             r |= FPCR_OVF;
                     44:         }
                     45:         if (t & float_flag_underflow) {
                     46:             r |= FPCR_UNF;
                     47:         }
                     48:         if (t & float_flag_inexact) {
                     49:             r |= FPCR_INE;
                     50:         }
                     51:     }
                     52: 
                     53:     t = env->fpcr_exc_mask;
                     54:     if (t & float_flag_invalid) {
                     55:         r |= FPCR_INVD;
                     56:     }
                     57:     if (t & float_flag_divbyzero) {
                     58:         r |= FPCR_DZED;
                     59:     }
                     60:     if (t & float_flag_overflow) {
                     61:         r |= FPCR_OVFD;
                     62:     }
                     63:     if (t & float_flag_underflow) {
                     64:         r |= FPCR_UNFD;
                     65:     }
                     66:     if (t & float_flag_inexact) {
                     67:         r |= FPCR_INED;
                     68:     }
                     69: 
                     70:     switch (env->fpcr_dyn_round) {
                     71:     case float_round_nearest_even:
                     72:         r |= FPCR_DYN_NORMAL;
                     73:         break;
                     74:     case float_round_down:
                     75:         r |= FPCR_DYN_MINUS;
                     76:         break;
                     77:     case float_round_up:
                     78:         r |= FPCR_DYN_PLUS;
                     79:         break;
                     80:     case float_round_to_zero:
                     81:         r |= FPCR_DYN_CHOPPED;
                     82:         break;
                     83:     }
                     84: 
                     85:     if (env->fpcr_dnz) {
                     86:         r |= FPCR_DNZ;
                     87:     }
                     88:     if (env->fpcr_dnod) {
                     89:         r |= FPCR_DNOD;
                     90:     }
                     91:     if (env->fpcr_undz) {
                     92:         r |= FPCR_UNDZ;
                     93:     }
                     94: 
                     95:     return r;
                     96: }
                     97: 
                     98: void cpu_alpha_store_fpcr (CPUState *env, uint64_t val)
                     99: {
                    100:     uint8_t t;
                    101: 
                    102:     t = 0;
                    103:     if (val & FPCR_INV) {
                    104:         t |= float_flag_invalid;
                    105:     }
                    106:     if (val & FPCR_DZE) {
                    107:         t |= float_flag_divbyzero;
                    108:     }
                    109:     if (val & FPCR_OVF) {
                    110:         t |= float_flag_overflow;
                    111:     }
                    112:     if (val & FPCR_UNF) {
                    113:         t |= float_flag_underflow;
                    114:     }
                    115:     if (val & FPCR_INE) {
                    116:         t |= float_flag_inexact;
                    117:     }
                    118:     env->fpcr_exc_status = t;
                    119: 
                    120:     t = 0;
                    121:     if (val & FPCR_INVD) {
                    122:         t |= float_flag_invalid;
                    123:     }
                    124:     if (val & FPCR_DZED) {
                    125:         t |= float_flag_divbyzero;
                    126:     }
                    127:     if (val & FPCR_OVFD) {
                    128:         t |= float_flag_overflow;
                    129:     }
                    130:     if (val & FPCR_UNFD) {
                    131:         t |= float_flag_underflow;
                    132:     }
                    133:     if (val & FPCR_INED) {
                    134:         t |= float_flag_inexact;
                    135:     }
                    136:     env->fpcr_exc_mask = t;
                    137: 
                    138:     switch (val & FPCR_DYN_MASK) {
                    139:     case FPCR_DYN_CHOPPED:
                    140:         t = float_round_to_zero;
                    141:         break;
                    142:     case FPCR_DYN_MINUS:
                    143:         t = float_round_down;
                    144:         break;
                    145:     case FPCR_DYN_NORMAL:
                    146:         t = float_round_nearest_even;
                    147:         break;
                    148:     case FPCR_DYN_PLUS:
                    149:         t = float_round_up;
                    150:         break;
                    151:     }
                    152:     env->fpcr_dyn_round = t;
                    153: 
                    154:     env->fpcr_flush_to_zero
                    155:       = (val & (FPCR_UNDZ|FPCR_UNFD)) == (FPCR_UNDZ|FPCR_UNFD);
                    156: 
                    157:     env->fpcr_dnz = (val & FPCR_DNZ) != 0;
                    158:     env->fpcr_dnod = (val & FPCR_DNOD) != 0;
                    159:     env->fpcr_undz = (val & FPCR_UNDZ) != 0;
                    160: }
1.1       root      161: 
                    162: #if defined(CONFIG_USER_ONLY)
                    163: 
                    164: int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                    165:                                 int mmu_idx, int is_softmmu)
                    166: {
                    167:     if (rw == 2)
                    168:         env->exception_index = EXCP_ITB_MISS;
                    169:     else
                    170:         env->exception_index = EXCP_DFAULT;
                    171:     env->ipr[IPR_EXC_ADDR] = address;
                    172: 
                    173:     return 1;
                    174: }
                    175: 
                    176: void do_interrupt (CPUState *env)
                    177: {
                    178:     env->exception_index = -1;
                    179: }
                    180: 
                    181: #else
                    182: 
                    183: target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
                    184: {
                    185:     return -1;
                    186: }
                    187: 
                    188: int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                    189:                                 int mmu_idx, int is_softmmu)
                    190: {
                    191:     uint32_t opc;
                    192: 
                    193:     if (rw == 2) {
                    194:         /* Instruction translation buffer miss */
                    195:         env->exception_index = EXCP_ITB_MISS;
                    196:     } else {
                    197:         if (env->ipr[IPR_EXC_ADDR] & 1)
                    198:             env->exception_index = EXCP_DTB_MISS_PAL;
                    199:         else
                    200:             env->exception_index = EXCP_DTB_MISS_NATIVE;
                    201:         opc = (ldl_code(env->pc) >> 21) << 4;
                    202:         if (rw) {
                    203:             opc |= 0x9;
                    204:         } else {
                    205:             opc |= 0x4;
                    206:         }
                    207:         env->ipr[IPR_MM_STAT] = opc;
                    208:     }
                    209: 
                    210:     return 1;
                    211: }
                    212: 
                    213: int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
                    214: {
                    215:     uint64_t hwpcb;
                    216:     int ret = 0;
                    217: 
                    218:     hwpcb = env->ipr[IPR_PCBB];
                    219:     switch (iprn) {
                    220:     case IPR_ASN:
                    221:         if (env->features & FEATURE_ASN)
                    222:             *valp = env->ipr[IPR_ASN];
                    223:         else
                    224:             *valp = 0;
                    225:         break;
                    226:     case IPR_ASTEN:
                    227:         *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60;
                    228:         break;
                    229:     case IPR_ASTSR:
                    230:         *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60;
                    231:         break;
                    232:     case IPR_DATFX:
                    233:         /* Write only */
                    234:         ret = -1;
                    235:         break;
                    236:     case IPR_ESP:
                    237:         if (env->features & FEATURE_SPS)
                    238:             *valp = env->ipr[IPR_ESP];
                    239:         else
                    240:             *valp = ldq_raw(hwpcb + 8);
                    241:         break;
                    242:     case IPR_FEN:
                    243:         *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63;
                    244:         break;
                    245:     case IPR_IPIR:
                    246:         /* Write-only */
                    247:         ret = -1;
                    248:         break;
                    249:     case IPR_IPL:
                    250:         *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
                    251:         break;
                    252:     case IPR_KSP:
                    253:         if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
                    254:             ret = -1;
                    255:         } else {
                    256:             if (env->features & FEATURE_SPS)
                    257:                 *valp = env->ipr[IPR_KSP];
                    258:             else
                    259:                 *valp = ldq_raw(hwpcb + 0);
                    260:         }
                    261:         break;
                    262:     case IPR_MCES:
                    263:         *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
                    264:         break;
                    265:     case IPR_PERFMON:
                    266:         /* Implementation specific */
                    267:         *valp = 0;
                    268:         break;
                    269:     case IPR_PCBB:
                    270:         *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
                    271:         break;
                    272:     case IPR_PRBR:
                    273:         *valp = env->ipr[IPR_PRBR];
                    274:         break;
                    275:     case IPR_PTBR:
                    276:         *valp = env->ipr[IPR_PTBR];
                    277:         break;
                    278:     case IPR_SCBB:
                    279:         *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
                    280:         break;
                    281:     case IPR_SIRR:
                    282:         /* Write-only */
                    283:         ret = -1;
                    284:         break;
                    285:     case IPR_SISR:
                    286:         *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]);
                    287:     case IPR_SSP:
                    288:         if (env->features & FEATURE_SPS)
                    289:             *valp = env->ipr[IPR_SSP];
                    290:         else
                    291:             *valp = ldq_raw(hwpcb + 16);
                    292:         break;
                    293:     case IPR_SYSPTBR:
                    294:         if (env->features & FEATURE_VIRBND)
                    295:             *valp = env->ipr[IPR_SYSPTBR];
                    296:         else
                    297:             ret = -1;
                    298:         break;
                    299:     case IPR_TBCHK:
                    300:         if ((env->features & FEATURE_TBCHK)) {
                    301:             /* XXX: TODO */
                    302:             *valp = 0;
                    303:             ret = -1;
                    304:         } else {
                    305:             ret = -1;
                    306:         }
                    307:         break;
                    308:     case IPR_TBIA:
                    309:         /* Write-only */
                    310:         ret = -1;
                    311:         break;
                    312:     case IPR_TBIAP:
                    313:         /* Write-only */
                    314:         ret = -1;
                    315:         break;
                    316:     case IPR_TBIS:
                    317:         /* Write-only */
                    318:         ret = -1;
                    319:         break;
                    320:     case IPR_TBISD:
                    321:         /* Write-only */
                    322:         ret = -1;
                    323:         break;
                    324:     case IPR_TBISI:
                    325:         /* Write-only */
                    326:         ret = -1;
                    327:         break;
                    328:     case IPR_USP:
                    329:         if (env->features & FEATURE_SPS)
                    330:             *valp = env->ipr[IPR_USP];
                    331:         else
                    332:             *valp = ldq_raw(hwpcb + 24);
                    333:         break;
                    334:     case IPR_VIRBND:
                    335:         if (env->features & FEATURE_VIRBND)
                    336:             *valp = env->ipr[IPR_VIRBND];
                    337:         else
                    338:             ret = -1;
                    339:         break;
                    340:     case IPR_VPTB:
                    341:         *valp = env->ipr[IPR_VPTB];
                    342:         break;
                    343:     case IPR_WHAMI:
                    344:         *valp = env->ipr[IPR_WHAMI];
                    345:         break;
                    346:     default:
                    347:         /* Invalid */
                    348:         ret = -1;
                    349:         break;
                    350:     }
                    351: 
                    352:     return ret;
                    353: }
                    354: 
                    355: int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
                    356: {
                    357:     uint64_t hwpcb, tmp64;
                    358:     uint8_t tmp8;
                    359:     int ret = 0;
                    360: 
                    361:     hwpcb = env->ipr[IPR_PCBB];
                    362:     switch (iprn) {
                    363:     case IPR_ASN:
                    364:         /* Read-only */
                    365:         ret = -1;
                    366:         break;
                    367:     case IPR_ASTEN:
                    368:         tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4;
                    369:         *oldvalp = tmp8;
                    370:         tmp8 &= val & 0xF;
                    371:         tmp8 |= (val >> 4) & 0xF;
                    372:         env->ipr[IPR_ASTEN] &= ~0xF;
                    373:         env->ipr[IPR_ASTEN] |= tmp8;
                    374:         ret = 1;
                    375:         break;
                    376:     case IPR_ASTSR:
                    377:         tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4;
                    378:         *oldvalp = tmp8;
                    379:         tmp8 &= val & 0xF;
                    380:         tmp8 |= (val >> 4) & 0xF;
                    381:         env->ipr[IPR_ASTSR] &= ~0xF;
                    382:         env->ipr[IPR_ASTSR] |= tmp8;
                    383:         ret = 1;
                    384:     case IPR_DATFX:
                    385:         env->ipr[IPR_DATFX] &= ~0x1;
                    386:         env->ipr[IPR_DATFX] |= val & 1;
                    387:         tmp64 = ldq_raw(hwpcb + 56);
                    388:         tmp64 &= ~0x8000000000000000ULL;
                    389:         tmp64 |= (val & 1) << 63;
                    390:         stq_raw(hwpcb + 56, tmp64);
                    391:         break;
                    392:     case IPR_ESP:
                    393:         if (env->features & FEATURE_SPS)
                    394:             env->ipr[IPR_ESP] = val;
                    395:         else
                    396:             stq_raw(hwpcb + 8, val);
                    397:         break;
                    398:     case IPR_FEN:
                    399:         env->ipr[IPR_FEN] = val & 1;
                    400:         tmp64 = ldq_raw(hwpcb + 56);
                    401:         tmp64 &= ~1;
                    402:         tmp64 |= val & 1;
                    403:         stq_raw(hwpcb + 56, tmp64);
                    404:         break;
                    405:     case IPR_IPIR:
                    406:         /* XXX: TODO: Send IRQ to CPU #ir[16] */
                    407:         break;
                    408:     case IPR_IPL:
                    409:         *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
                    410:         env->ipr[IPR_IPL] &= ~0x1F;
                    411:         env->ipr[IPR_IPL] |= val & 0x1F;
                    412:         /* XXX: may issue an interrupt or ASR _now_ */
                    413:         ret = 1;
                    414:         break;
                    415:     case IPR_KSP:
                    416:         if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
                    417:             ret = -1;
                    418:         } else {
                    419:             if (env->features & FEATURE_SPS)
                    420:                 env->ipr[IPR_KSP] = val;
                    421:             else
                    422:                 stq_raw(hwpcb + 0, val);
                    423:         }
                    424:         break;
                    425:     case IPR_MCES:
                    426:         env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18);
                    427:         env->ipr[IPR_MCES] |= val & 0x18;
                    428:         break;
                    429:     case IPR_PERFMON:
                    430:         /* Implementation specific */
                    431:         *oldvalp = 0;
                    432:         ret = 1;
                    433:         break;
                    434:     case IPR_PCBB:
                    435:         /* Read-only */
                    436:         ret = -1;
                    437:         break;
                    438:     case IPR_PRBR:
                    439:         env->ipr[IPR_PRBR] = val;
                    440:         break;
                    441:     case IPR_PTBR:
                    442:         /* Read-only */
                    443:         ret = -1;
                    444:         break;
                    445:     case IPR_SCBB:
                    446:         env->ipr[IPR_SCBB] = (uint32_t)val;
                    447:         break;
                    448:     case IPR_SIRR:
                    449:         if (val & 0xF) {
                    450:             env->ipr[IPR_SISR] |= 1 << (val & 0xF);
                    451:             /* XXX: request a software interrupt _now_ */
                    452:         }
                    453:         break;
                    454:     case IPR_SISR:
                    455:         /* Read-only */
                    456:         ret = -1;
                    457:         break;
                    458:     case IPR_SSP:
                    459:         if (env->features & FEATURE_SPS)
                    460:             env->ipr[IPR_SSP] = val;
                    461:         else
                    462:             stq_raw(hwpcb + 16, val);
                    463:         break;
                    464:     case IPR_SYSPTBR:
                    465:         if (env->features & FEATURE_VIRBND)
                    466:             env->ipr[IPR_SYSPTBR] = val;
                    467:         else
                    468:             ret = -1;
1.1.1.4   root      469:         break;
1.1       root      470:     case IPR_TBCHK:
                    471:         /* Read-only */
                    472:         ret = -1;
                    473:         break;
                    474:     case IPR_TBIA:
                    475:         tlb_flush(env, 1);
                    476:         break;
                    477:     case IPR_TBIAP:
                    478:         tlb_flush(env, 1);
                    479:         break;
                    480:     case IPR_TBIS:
                    481:         tlb_flush_page(env, val);
                    482:         break;
                    483:     case IPR_TBISD:
                    484:         tlb_flush_page(env, val);
                    485:         break;
                    486:     case IPR_TBISI:
                    487:         tlb_flush_page(env, val);
                    488:         break;
                    489:     case IPR_USP:
                    490:         if (env->features & FEATURE_SPS)
                    491:             env->ipr[IPR_USP] = val;
                    492:         else
                    493:             stq_raw(hwpcb + 24, val);
                    494:         break;
                    495:     case IPR_VIRBND:
                    496:         if (env->features & FEATURE_VIRBND)
                    497:             env->ipr[IPR_VIRBND] = val;
                    498:         else
                    499:             ret = -1;
                    500:         break;
                    501:     case IPR_VPTB:
                    502:         env->ipr[IPR_VPTB] = val;
                    503:         break;
                    504:     case IPR_WHAMI:
                    505:         /* Read-only */
                    506:         ret = -1;
                    507:         break;
                    508:     default:
                    509:         /* Invalid */
                    510:         ret = -1;
                    511:         break;
                    512:     }
                    513: 
                    514:     return ret;
                    515: }
                    516: 
                    517: void do_interrupt (CPUState *env)
                    518: {
                    519:     int excp;
                    520: 
                    521:     env->ipr[IPR_EXC_ADDR] = env->pc | 1;
                    522:     excp = env->exception_index;
1.1.1.4   root      523:     env->exception_index = -1;
1.1       root      524:     env->error_code = 0;
                    525:     /* XXX: disable interrupts and memory mapping */
                    526:     if (env->ipr[IPR_PAL_BASE] != -1ULL) {
                    527:         /* We use native PALcode */
                    528:         env->pc = env->ipr[IPR_PAL_BASE] + excp;
                    529:     } else {
                    530:         /* We use emulated PALcode */
                    531:         call_pal(env);
                    532:         /* Emulate REI */
                    533:         env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
                    534:         env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
                    535:         /* XXX: re-enable interrupts and memory mapping */
                    536:     }
                    537: }
                    538: #endif
                    539: 
1.1.1.5 ! root      540: void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
1.1       root      541:                      int flags)
                    542: {
1.1.1.2   root      543:     static const char *linux_reg_names[] = {
1.1       root      544:         "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
                    545:         "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
                    546:         "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
                    547:         "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
                    548:     };
                    549:     int i;
                    550: 
                    551:     cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      PS  " TARGET_FMT_lx "\n",
                    552:                 env->pc, env->ps);
                    553:     for (i = 0; i < 31; i++) {
                    554:         cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
                    555:                     linux_reg_names[i], env->ir[i]);
                    556:         if ((i % 3) == 2)
                    557:             cpu_fprintf(f, "\n");
                    558:     }
1.1.1.4   root      559: 
                    560:     cpu_fprintf(f, "lock_a   " TARGET_FMT_lx " lock_v   " TARGET_FMT_lx "\n",
                    561:                 env->lock_addr, env->lock_value);
                    562: 
1.1       root      563:     for (i = 0; i < 31; i++) {
                    564:         cpu_fprintf(f, "FIR%02d    " TARGET_FMT_lx " ", i,
                    565:                     *((uint64_t *)(&env->fir[i])));
                    566:         if ((i % 3) == 2)
                    567:             cpu_fprintf(f, "\n");
                    568:     }
1.1.1.4   root      569:     cpu_fprintf(f, "\n");
1.1       root      570: }

unix.superglobalmegacorp.com

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