qemu/target-alpha/helper.c
<<
>>
Prefs
   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
  17 * License along with this library; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
  19 */
  20
  21#include <stdint.h>
  22#include <stdlib.h>
  23#include <stdio.h>
  24
  25#include "cpu.h"
  26#include "exec-all.h"
  27
  28#if defined(CONFIG_USER_ONLY)
  29
  30int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
  31                                int mmu_idx, int is_softmmu)
  32{
  33    if (rw == 2)
  34        env->exception_index = EXCP_ITB_MISS;
  35    else
  36        env->exception_index = EXCP_DFAULT;
  37    env->ipr[IPR_EXC_ADDR] = address;
  38
  39    return 1;
  40}
  41
  42target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
  43{
  44    return addr;
  45}
  46
  47void do_interrupt (CPUState *env)
  48{
  49    env->exception_index = -1;
  50}
  51
  52#else
  53
  54target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
  55{
  56    return -1;
  57}
  58
  59int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
  60                                int mmu_idx, int is_softmmu)
  61{
  62    uint32_t opc;
  63
  64    if (rw == 2) {
  65        /* Instruction translation buffer miss */
  66        env->exception_index = EXCP_ITB_MISS;
  67    } else {
  68        if (env->ipr[IPR_EXC_ADDR] & 1)
  69            env->exception_index = EXCP_DTB_MISS_PAL;
  70        else
  71            env->exception_index = EXCP_DTB_MISS_NATIVE;
  72        opc = (ldl_code(env->pc) >> 21) << 4;
  73        if (rw) {
  74            opc |= 0x9;
  75        } else {
  76            opc |= 0x4;
  77        }
  78        env->ipr[IPR_MM_STAT] = opc;
  79    }
  80
  81    return 1;
  82}
  83
  84int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
  85{
  86    uint64_t hwpcb;
  87    int ret = 0;
  88
  89    hwpcb = env->ipr[IPR_PCBB];
  90    switch (iprn) {
  91    case IPR_ASN:
  92        if (env->features & FEATURE_ASN)
  93            *valp = env->ipr[IPR_ASN];
  94        else
  95            *valp = 0;
  96        break;
  97    case IPR_ASTEN:
  98        *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60;
  99        break;
 100    case IPR_ASTSR:
 101        *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60;
 102        break;
 103    case IPR_DATFX:
 104        /* Write only */
 105        ret = -1;
 106        break;
 107    case IPR_ESP:
 108        if (env->features & FEATURE_SPS)
 109            *valp = env->ipr[IPR_ESP];
 110        else
 111            *valp = ldq_raw(hwpcb + 8);
 112        break;
 113    case IPR_FEN:
 114        *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63;
 115        break;
 116    case IPR_IPIR:
 117        /* Write-only */
 118        ret = -1;
 119        break;
 120    case IPR_IPL:
 121        *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
 122        break;
 123    case IPR_KSP:
 124        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
 125            ret = -1;
 126        } else {
 127            if (env->features & FEATURE_SPS)
 128                *valp = env->ipr[IPR_KSP];
 129            else
 130                *valp = ldq_raw(hwpcb + 0);
 131        }
 132        break;
 133    case IPR_MCES:
 134        *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
 135        break;
 136    case IPR_PERFMON:
 137        /* Implementation specific */
 138        *valp = 0;
 139        break;
 140    case IPR_PCBB:
 141        *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
 142        break;
 143    case IPR_PRBR:
 144        *valp = env->ipr[IPR_PRBR];
 145        break;
 146    case IPR_PTBR:
 147        *valp = env->ipr[IPR_PTBR];
 148        break;
 149    case IPR_SCBB:
 150        *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
 151        break;
 152    case IPR_SIRR:
 153        /* Write-only */
 154        ret = -1;
 155        break;
 156    case IPR_SISR:
 157        *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]);
 158    case IPR_SSP:
 159        if (env->features & FEATURE_SPS)
 160            *valp = env->ipr[IPR_SSP];
 161        else
 162            *valp = ldq_raw(hwpcb + 16);
 163        break;
 164    case IPR_SYSPTBR:
 165        if (env->features & FEATURE_VIRBND)
 166            *valp = env->ipr[IPR_SYSPTBR];
 167        else
 168            ret = -1;
 169        break;
 170    case IPR_TBCHK:
 171        if ((env->features & FEATURE_TBCHK)) {
 172            /* XXX: TODO */
 173            *valp = 0;
 174            ret = -1;
 175        } else {
 176            ret = -1;
 177        }
 178        break;
 179    case IPR_TBIA:
 180        /* Write-only */
 181        ret = -1;
 182        break;
 183    case IPR_TBIAP:
 184        /* Write-only */
 185        ret = -1;
 186        break;
 187    case IPR_TBIS:
 188        /* Write-only */
 189        ret = -1;
 190        break;
 191    case IPR_TBISD:
 192        /* Write-only */
 193        ret = -1;
 194        break;
 195    case IPR_TBISI:
 196        /* Write-only */
 197        ret = -1;
 198        break;
 199    case IPR_USP:
 200        if (env->features & FEATURE_SPS)
 201            *valp = env->ipr[IPR_USP];
 202        else
 203            *valp = ldq_raw(hwpcb + 24);
 204        break;
 205    case IPR_VIRBND:
 206        if (env->features & FEATURE_VIRBND)
 207            *valp = env->ipr[IPR_VIRBND];
 208        else
 209            ret = -1;
 210        break;
 211    case IPR_VPTB:
 212        *valp = env->ipr[IPR_VPTB];
 213        break;
 214    case IPR_WHAMI:
 215        *valp = env->ipr[IPR_WHAMI];
 216        break;
 217    default:
 218        /* Invalid */
 219        ret = -1;
 220        break;
 221    }
 222
 223    return ret;
 224}
 225
 226int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
 227{
 228    uint64_t hwpcb, tmp64;
 229    uint8_t tmp8;
 230    int ret = 0;
 231
 232    hwpcb = env->ipr[IPR_PCBB];
 233    switch (iprn) {
 234    case IPR_ASN:
 235        /* Read-only */
 236        ret = -1;
 237        break;
 238    case IPR_ASTEN:
 239        tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4;
 240        *oldvalp = tmp8;
 241        tmp8 &= val & 0xF;
 242        tmp8 |= (val >> 4) & 0xF;
 243        env->ipr[IPR_ASTEN] &= ~0xF;
 244        env->ipr[IPR_ASTEN] |= tmp8;
 245        ret = 1;
 246        break;
 247    case IPR_ASTSR:
 248        tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4;
 249        *oldvalp = tmp8;
 250        tmp8 &= val & 0xF;
 251        tmp8 |= (val >> 4) & 0xF;
 252        env->ipr[IPR_ASTSR] &= ~0xF;
 253        env->ipr[IPR_ASTSR] |= tmp8;
 254        ret = 1;
 255    case IPR_DATFX:
 256        env->ipr[IPR_DATFX] &= ~0x1;
 257        env->ipr[IPR_DATFX] |= val & 1;
 258        tmp64 = ldq_raw(hwpcb + 56);
 259        tmp64 &= ~0x8000000000000000ULL;
 260        tmp64 |= (val & 1) << 63;
 261        stq_raw(hwpcb + 56, tmp64);
 262        break;
 263    case IPR_ESP:
 264        if (env->features & FEATURE_SPS)
 265            env->ipr[IPR_ESP] = val;
 266        else
 267            stq_raw(hwpcb + 8, val);
 268        break;
 269    case IPR_FEN:
 270        env->ipr[IPR_FEN] = val & 1;
 271        tmp64 = ldq_raw(hwpcb + 56);
 272        tmp64 &= ~1;
 273        tmp64 |= val & 1;
 274        stq_raw(hwpcb + 56, tmp64);
 275        break;
 276    case IPR_IPIR:
 277        /* XXX: TODO: Send IRQ to CPU #ir[16] */
 278        break;
 279    case IPR_IPL:
 280        *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
 281        env->ipr[IPR_IPL] &= ~0x1F;
 282        env->ipr[IPR_IPL] |= val & 0x1F;
 283        /* XXX: may issue an interrupt or ASR _now_ */
 284        ret = 1;
 285        break;
 286    case IPR_KSP:
 287        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
 288            ret = -1;
 289        } else {
 290            if (env->features & FEATURE_SPS)
 291                env->ipr[IPR_KSP] = val;
 292            else
 293                stq_raw(hwpcb + 0, val);
 294        }
 295        break;
 296    case IPR_MCES:
 297        env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18);
 298        env->ipr[IPR_MCES] |= val & 0x18;
 299        break;
 300    case IPR_PERFMON:
 301        /* Implementation specific */
 302        *oldvalp = 0;
 303        ret = 1;
 304        break;
 305    case IPR_PCBB:
 306        /* Read-only */
 307        ret = -1;
 308        break;
 309    case IPR_PRBR:
 310        env->ipr[IPR_PRBR] = val;
 311        break;
 312    case IPR_PTBR:
 313        /* Read-only */
 314        ret = -1;
 315        break;
 316    case IPR_SCBB:
 317        env->ipr[IPR_SCBB] = (uint32_t)val;
 318        break;
 319    case IPR_SIRR:
 320        if (val & 0xF) {
 321            env->ipr[IPR_SISR] |= 1 << (val & 0xF);
 322            /* XXX: request a software interrupt _now_ */
 323        }
 324        break;
 325    case IPR_SISR:
 326        /* Read-only */
 327        ret = -1;
 328        break;
 329    case IPR_SSP:
 330        if (env->features & FEATURE_SPS)
 331            env->ipr[IPR_SSP] = val;
 332        else
 333            stq_raw(hwpcb + 16, val);
 334        break;
 335    case IPR_SYSPTBR:
 336        if (env->features & FEATURE_VIRBND)
 337            env->ipr[IPR_SYSPTBR] = val;
 338        else
 339            ret = -1;
 340    case IPR_TBCHK:
 341        /* Read-only */
 342        ret = -1;
 343        break;
 344    case IPR_TBIA:
 345        tlb_flush(env, 1);
 346        break;
 347    case IPR_TBIAP:
 348        tlb_flush(env, 1);
 349        break;
 350    case IPR_TBIS:
 351        tlb_flush_page(env, val);
 352        break;
 353    case IPR_TBISD:
 354        tlb_flush_page(env, val);
 355        break;
 356    case IPR_TBISI:
 357        tlb_flush_page(env, val);
 358        break;
 359    case IPR_USP:
 360        if (env->features & FEATURE_SPS)
 361            env->ipr[IPR_USP] = val;
 362        else
 363            stq_raw(hwpcb + 24, val);
 364        break;
 365    case IPR_VIRBND:
 366        if (env->features & FEATURE_VIRBND)
 367            env->ipr[IPR_VIRBND] = val;
 368        else
 369            ret = -1;
 370        break;
 371    case IPR_VPTB:
 372        env->ipr[IPR_VPTB] = val;
 373        break;
 374    case IPR_WHAMI:
 375        /* Read-only */
 376        ret = -1;
 377        break;
 378    default:
 379        /* Invalid */
 380        ret = -1;
 381        break;
 382    }
 383
 384    return ret;
 385}
 386
 387void do_interrupt (CPUState *env)
 388{
 389    int excp;
 390
 391    env->ipr[IPR_EXC_ADDR] = env->pc | 1;
 392    excp = env->exception_index;
 393    env->exception_index = 0;
 394    env->error_code = 0;
 395    /* XXX: disable interrupts and memory mapping */
 396    if (env->ipr[IPR_PAL_BASE] != -1ULL) {
 397        /* We use native PALcode */
 398        env->pc = env->ipr[IPR_PAL_BASE] + excp;
 399    } else {
 400        /* We use emulated PALcode */
 401        call_pal(env);
 402        /* Emulate REI */
 403        env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
 404        env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
 405        /* XXX: re-enable interrupts and memory mapping */
 406    }
 407}
 408#endif
 409
 410void cpu_dump_state (CPUState *env, FILE *f,
 411                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
 412                     int flags)
 413{
 414    static const char *linux_reg_names[] = {
 415        "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
 416        "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
 417        "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
 418        "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
 419    };
 420    int i;
 421
 422    cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      PS  " TARGET_FMT_lx "\n",
 423                env->pc, env->ps);
 424    for (i = 0; i < 31; i++) {
 425        cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
 426                    linux_reg_names[i], env->ir[i]);
 427        if ((i % 3) == 2)
 428            cpu_fprintf(f, "\n");
 429    }
 430    cpu_fprintf(f, "\n");
 431    for (i = 0; i < 31; i++) {
 432        cpu_fprintf(f, "FIR%02d    " TARGET_FMT_lx " ", i,
 433                    *((uint64_t *)(&env->fir[i])));
 434        if ((i % 3) == 2)
 435            cpu_fprintf(f, "\n");
 436    }
 437    cpu_fprintf(f, "\nlock     " TARGET_FMT_lx "\n", env->lock);
 438}
 439