|
|
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 ! 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: ! 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: ! 30: int 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: ! 42: target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr) ! 43: { ! 44: return addr; ! 45: } ! 46: ! 47: void do_interrupt (CPUState *env) ! 48: { ! 49: env->exception_index = -1; ! 50: } ! 51: ! 52: #else ! 53: ! 54: target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr) ! 55: { ! 56: return -1; ! 57: } ! 58: ! 59: int 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: ! 84: int 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: ! 226: int 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: ! 387: void 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: ! 410: void cpu_dump_state (CPUState *env, FILE *f, ! 411: int (*cpu_fprintf)(FILE *f, const char *fmt, ...), ! 412: int flags) ! 413: { ! 414: static unsigned 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, "FT " TARGET_FMT_lx " " TARGET_FMT_lx " " TARGET_FMT_lx, ! 438: *((uint64_t *)(&env->ft0)), *((uint64_t *)(&env->ft1)), ! 439: *((uint64_t *)(&env->ft2))); ! 440: cpu_fprintf(f, "\nMEM " TARGET_FMT_lx " %d %d\n", ! 441: ldq_raw(0x000000004007df60ULL), ! 442: (uint8_t *)(&env->ft0), (uint8_t *)(&env->fir[0])); ! 443: } ! 444: ! 445: void cpu_dump_EA (target_ulong EA) ! 446: { ! 447: FILE *f; ! 448: ! 449: if (logfile) ! 450: f = logfile; ! 451: else ! 452: f = stdout; ! 453: fprintf(f, "Memory access at address " TARGET_FMT_lx "\n", EA); ! 454: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.