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

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: 
                    540: void cpu_dump_state (CPUState *env, FILE *f,
                    541:                      int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                    542:                      int flags)
                    543: {
1.1.1.2   root      544:     static const char *linux_reg_names[] = {
1.1       root      545:         "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
                    546:         "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
                    547:         "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
                    548:         "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
                    549:     };
                    550:     int i;
                    551: 
                    552:     cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      PS  " TARGET_FMT_lx "\n",
                    553:                 env->pc, env->ps);
                    554:     for (i = 0; i < 31; i++) {
                    555:         cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
                    556:                     linux_reg_names[i], env->ir[i]);
                    557:         if ((i % 3) == 2)
                    558:             cpu_fprintf(f, "\n");
                    559:     }
1.1.1.4 ! root      560: 
        !           561:     cpu_fprintf(f, "lock_a   " TARGET_FMT_lx " lock_v   " TARGET_FMT_lx "\n",
        !           562:                 env->lock_addr, env->lock_value);
        !           563: 
1.1       root      564:     for (i = 0; i < 31; i++) {
                    565:         cpu_fprintf(f, "FIR%02d    " TARGET_FMT_lx " ", i,
                    566:                     *((uint64_t *)(&env->fir[i])));
                    567:         if ((i % 3) == 2)
                    568:             cpu_fprintf(f, "\n");
                    569:     }
1.1.1.4 ! root      570:     cpu_fprintf(f, "\n");
1.1       root      571: }

unix.superglobalmegacorp.com

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