Alpha architecture emulation core.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2597 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
j_mayer 2007-04-05 06:58:33 +00:00
parent 6fa4cea9e8
commit 4c9649a967
10 changed files with 5869 additions and 0 deletions

385
target-alpha/cpu.h Normal file
View File

@ -0,0 +1,385 @@
/*
* Alpha emulation cpu definitions for qemu.
*
* Copyright (c) 2007 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined (__CPU_ALPHA_H__)
#define __CPU_ALPHA_H__
#include "config.h"
#define TARGET_LONG_BITS 64
#include "cpu-defs.h"
#include <setjmp.h>
#include "softfloat.h"
/* XXX: put this in a common place */
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define TARGET_HAS_ICE 1
#define ELF_MACHINE EM_ALPHA
#define ICACHE_LINE_SIZE 32
#define DCACHE_LINE_SIZE 32
#define TARGET_PAGE_BITS 12
#define VA_BITS 43
/* Alpha major type */
enum {
ALPHA_EV3 = 1,
ALPHA_EV4 = 2,
ALPHA_SIM = 3,
ALPHA_LCA = 4,
ALPHA_EV5 = 5, /* 21164 */
ALPHA_EV45 = 6, /* 21064A */
ALPHA_EV56 = 7, /* 21164A */
};
/* EV4 minor type */
enum {
ALPHA_EV4_2 = 0,
ALPHA_EV4_3 = 1,
};
/* LCA minor type */
enum {
ALPHA_LCA_1 = 1, /* 21066 */
ALPHA_LCA_2 = 2, /* 20166 */
ALPHA_LCA_3 = 3, /* 21068 */
ALPHA_LCA_4 = 4, /* 21068 */
ALPHA_LCA_5 = 5, /* 21066A */
ALPHA_LCA_6 = 6, /* 21068A */
};
/* EV5 minor type */
enum {
ALPHA_EV5_1 = 1, /* Rev BA, CA */
ALPHA_EV5_2 = 2, /* Rev DA, EA */
ALPHA_EV5_3 = 3, /* Pass 3 */
ALPHA_EV5_4 = 4, /* Pass 3.2 */
ALPHA_EV5_5 = 5, /* Pass 4 */
};
/* EV45 minor type */
enum {
ALPHA_EV45_1 = 1, /* Pass 1 */
ALPHA_EV45_2 = 2, /* Pass 1.1 */
ALPHA_EV45_3 = 3, /* Pass 2 */
};
/* EV56 minor type */
enum {
ALPHA_EV56_1 = 1, /* Pass 1 */
ALPHA_EV56_2 = 2, /* Pass 2 */
};
enum {
IMPLVER_2106x = 0, /* EV4, EV45 & LCA45 */
IMPLVER_21164 = 1, /* EV5, EV56 & PCA45 */
IMPLVER_21264 = 2, /* EV6, EV67 & EV68x */
IMPLVER_21364 = 3, /* EV7 & EV79 */
};
enum {
AMASK_BWX = 0x00000001,
AMASK_FIX = 0x00000002,
AMASK_CIX = 0x00000004,
AMASK_MVI = 0x00000100,
AMASK_TRAP = 0x00000200,
AMASK_PREFETCH = 0x00001000,
};
enum {
VAX_ROUND_NORMAL = 0,
VAX_ROUND_CHOPPED,
};
enum {
IEEE_ROUND_NORMAL = 0,
IEEE_ROUND_DYNAMIC,
IEEE_ROUND_PLUS,
IEEE_ROUND_MINUS,
IEEE_ROUND_CHOPPED,
};
/* IEEE floating-point operations encoding */
/* Trap mode */
enum {
FP_TRAP_I = 0x0,
FP_TRAP_U = 0x1,
FP_TRAP_S = 0x4,
FP_TRAP_SU = 0x5,
FP_TRAP_SUI = 0x7,
};
/* Rounding mode */
enum {
FP_ROUND_CHOPPED = 0x0,
FP_ROUND_MINUS = 0x1,
FP_ROUND_NORMAL = 0x2,
FP_ROUND_DYNAMIC = 0x3,
};
/* Internal processor registers */
/* XXX: TOFIX: most of those registers are implementation dependant */
enum {
/* Ebox IPRs */
IPR_CC = 0xC0,
IPR_CC_CTL = 0xC1,
IPR_VA = 0xC2,
IPR_VA_CTL = 0xC4,
IPR_VA_FORM = 0xC3,
/* Ibox IPRs */
IPR_ITB_TAG = 0x00,
IPR_ITB_PTE = 0x01,
IPT_ITB_IAP = 0x02,
IPT_ITB_IA = 0x03,
IPT_ITB_IS = 0x04,
IPR_PMPC = 0x05,
IPR_EXC_ADDR = 0x06,
IPR_IVA_FORM = 0x07,
IPR_CM = 0x09,
IPR_IER = 0x0A,
IPR_SIRR = 0x0C,
IPR_ISUM = 0x0D,
IPR_HW_INT_CLR = 0x0E,
IPR_EXC_SUM = 0x0F,
IPR_PAL_BASE = 0x10,
IPR_I_CTL = 0x11,
IPR_I_STAT = 0x16,
IPR_IC_FLUSH = 0x13,
IPR_IC_FLUSH_ASM = 0x12,
IPR_CLR_MAP = 0x15,
IPR_SLEEP = 0x17,
IPR_PCTX = 0x40,
IPR_PCTR_CTL = 0x14,
/* Mbox IPRs */
IPR_DTB_TAG0 = 0x20,
IPR_DTB_TAG1 = 0xA0,
IPR_DTB_PTE0 = 0x21,
IPR_DTB_PTE1 = 0xA1,
IPR_DTB_ALTMODE = 0xA6,
IPR_DTB_IAP = 0xA2,
IPR_DTB_IA = 0xA3,
IPR_DTB_IS0 = 0x24,
IPR_DTB_IS1 = 0xA4,
IPR_DTB_ASN0 = 0x25,
IPR_DTB_ASN1 = 0xA5,
IPR_MM_STAT = 0x27,
IPR_M_CTL = 0x28,
IPR_DC_CTL = 0x29,
IPR_DC_STAT = 0x2A,
/* Cbox IPRs */
IPR_C_DATA = 0x2B,
IPR_C_SHIFT = 0x2C,
IPR_ASN,
IPR_ASTEN,
IPR_ASTSR,
IPR_DATFX,
IPR_ESP,
IPR_FEN,
IPR_IPIR,
IPR_IPL,
IPR_KSP,
IPR_MCES,
IPR_PERFMON,
IPR_PCBB,
IPR_PRBR,
IPR_PTBR,
IPR_SCBB,
IPR_SISR,
IPR_SSP,
IPR_SYSPTBR,
IPR_TBCHK,
IPR_TBIA,
IPR_TBIAP,
IPR_TBIS,
IPR_TBISD,
IPR_TBISI,
IPR_USP,
IPR_VIRBND,
IPR_VPTB,
IPR_WHAMI,
IPR_ALT_MODE,
IPR_LAST,
};
typedef struct CPUAlphaState CPUAlphaState;
typedef struct pal_handler_t pal_handler_t;
struct pal_handler_t {
/* Reset */
void (*reset)(CPUAlphaState *env);
/* Uncorrectable hardware error */
void (*machine_check)(CPUAlphaState *env);
/* Arithmetic exception */
void (*arithmetic)(CPUAlphaState *env);
/* Interrupt / correctable hardware error */
void (*interrupt)(CPUAlphaState *env);
/* Data fault */
void (*dfault)(CPUAlphaState *env);
/* DTB miss pal */
void (*dtb_miss_pal)(CPUAlphaState *env);
/* DTB miss native */
void (*dtb_miss_native)(CPUAlphaState *env);
/* Unaligned access */
void (*unalign)(CPUAlphaState *env);
/* ITB miss */
void (*itb_miss)(CPUAlphaState *env);
/* Instruction stream access violation */
void (*itb_acv)(CPUAlphaState *env);
/* Reserved or privileged opcode */
void (*opcdec)(CPUAlphaState *env);
/* Floating point exception */
void (*fen)(CPUAlphaState *env);
/* Call pal instruction */
void (*call_pal)(CPUAlphaState *env, uint32_t palcode);
};
struct CPUAlphaState {
uint64_t ir[31];
float64 fir[31];
float_status fp_status;
uint64_t fpcr;
uint64_t pc;
uint64_t lock;
uint32_t pcc[2];
uint64_t ipr[IPR_LAST];
uint64_t ps;
uint64_t unique;
int saved_mode; /* Used for HW_LD / HW_ST */
/* */
double ft0, ft1, ft2;
/* Those resources are used only in Qemu core */
CPU_COMMON
jmp_buf jmp_env;
int user_mode_only; /* user mode only simulation */
uint32_t hflags;
int halted;
int exception_index;
int error_code;
int interrupt_request;
uint32_t features;
uint32_t amask;
int implver;
pal_handler_t *pal_handler;
};
#include "cpu-all.h"
enum {
FEATURE_ASN = 0x00000001,
FEATURE_SPS = 0x00000002,
FEATURE_VIRBND = 0x00000004,
FEATURE_TBCHK = 0x00000008,
};
enum {
EXCP_RESET = 0x0000,
EXCP_MCHK = 0x0020,
EXCP_ARITH = 0x0060,
EXCP_HW_INTERRUPT = 0x00E0,
EXCP_DFAULT = 0x01E0,
EXCP_DTB_MISS_PAL = 0x09E0,
EXCP_ITB_MISS = 0x03E0,
EXCP_ITB_ACV = 0x07E0,
EXCP_DTB_MISS_NATIVE = 0x08E0,
EXCP_UNALIGN = 0x11E0,
EXCP_OPCDEC = 0x13E0,
EXCP_FEN = 0x17E0,
EXCP_CALL_PAL = 0x2000,
EXCP_CALL_PALP = 0x3000,
EXCP_CALL_PALE = 0x4000,
/* Pseudo exception for console */
EXCP_CONSOLE_DISPATCH = 0x4001,
EXCP_CONSOLE_FIXUP = 0x4002,
};
/* Arithmetic exception */
enum {
EXCP_ARITH_OVERFLOW,
};
enum {
PALCODE_CALL = 0x00000000,
PALCODE_LD = 0x01000000,
PALCODE_ST = 0x02000000,
PALCODE_MFPR = 0x03000000,
PALCODE_MTPR = 0x04000000,
PALCODE_REI = 0x05000000,
PALCODE_INIT = 0xF0000000,
};
enum {
IR_V0 = 0,
IR_T0 = 1,
IR_T1 = 2,
IR_T2 = 3,
IR_T3 = 4,
IR_T4 = 5,
IR_T5 = 6,
IR_T6 = 7,
IR_T7 = 8,
IR_S0 = 9,
IR_S1 = 10,
IR_S2 = 11,
IR_S3 = 12,
IR_S4 = 13,
IR_S5 = 14,
IR_S6 = 15,
#define IR_FP IR_S6
IR_A0 = 16,
IR_A1 = 17,
IR_A2 = 18,
IR_A3 = 19,
IR_A4 = 20,
IR_A5 = 21,
IR_T8 = 22,
IR_T9 = 23,
IR_T10 = 24,
IR_T11 = 25,
IR_RA = 26,
IR_T12 = 27,
#define IR_PV IR_T12
IR_AT = 28,
IR_GP = 29,
IR_SP = 30,
IR_ZERO = 31,
};
int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
void cpu_loop_exit (void);
void pal_init (CPUState *env);
void call_pal (CPUState *env, int palcode);
#endif /* !defined (__CPU_ALPHA_H__) */

82
target-alpha/exec.h Normal file
View File

@ -0,0 +1,82 @@
/*
* Alpha emulation cpu run-time definitions for qemu.
*
* Copyright (c) 2007 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined (__ALPHA_EXEC_H__)
#define __ALPHA_EXEC_H__
#include "config.h"
#include "dyngen-exec.h"
#define TARGET_LONG_BITS 64
register struct CPUAlphaState *env asm(AREG0);
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* no registers can be used */
#define T0 (env->t0)
#define T1 (env->t1)
#define T2 (env->t2)
#else
register uint64_t T0 asm(AREG1);
register uint64_t T1 asm(AREG2);
register uint64_t T2 asm(AREG3);
#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
#define PARAM(n) ((uint64_t)PARAM##n)
#define SPARAM(n) ((int32_t)PARAM##n)
#define FT0 (env->ft0)
#define FT1 (env->ft1)
#define FT2 (env->ft2)
#define FP_STATUS (env->fp_status)
#if defined (DEBUG_OP)
#define RETURN() __asm__ __volatile__("nop" : : : "memory");
#else
#define RETURN() __asm__ __volatile__("" : : : "memory");
#endif
#include "cpu.h"
#include "exec-all.h"
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
#endif /* !defined(CONFIG_USER_ONLY) */
static inline void env_to_regs(void)
{
}
static inline void regs_to_env(void)
{
}
int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw,
int is_user, int is_softmmu);
int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
void do_interrupt (CPUState *env);
#endif /* !defined (__ALPHA_EXEC_H__) */

454
target-alpha/helper.c Normal file
View File

@ -0,0 +1,454 @@
/*
* Alpha emulation cpu helpers for qemu.
*
* Copyright (c) 2007 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "cpu.h"
#include "exec-all.h"
#if defined(CONFIG_USER_ONLY)
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int is_user, int is_softmmu)
{
if (rw == 2)
env->exception_index = EXCP_ITB_MISS;
else
env->exception_index = EXCP_DFAULT;
env->ipr[IPR_EXC_ADDR] = address;
return 1;
}
target_ulong cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
{
return addr;
}
void do_interrupt (CPUState *env)
{
env->exception_index = -1;
}
#else
target_ulong cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
{
return -1;
}
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int is_user, int is_softmmu)
{
uint32_t opc;
if (rw == 2) {
/* Instruction translation buffer miss */
env->exception_index = EXCP_ITB_MISS;
} else {
if (env->ipr[IPR_EXC_ADDR] & 1)
env->exception_index = EXCP_DTB_MISS_PAL;
else
env->exception_index = EXCP_DTB_MISS_NATIVE;
opc = (ldl_code(env->pc) >> 21) << 4;
if (rw) {
opc |= 0x9;
} else {
opc |= 0x4;
}
env->ipr[IPR_MM_STAT] = opc;
}
return 1;
}
int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
{
uint64_t hwpcb;
int ret = 0;
hwpcb = env->ipr[IPR_PCBB];
switch (iprn) {
case IPR_ASN:
if (env->features & FEATURE_ASN)
*valp = env->ipr[IPR_ASN];
else
*valp = 0;
break;
case IPR_ASTEN:
*valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60;
break;
case IPR_ASTSR:
*valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60;
break;
case IPR_DATFX:
/* Write only */
ret = -1;
break;
case IPR_ESP:
if (env->features & FEATURE_SPS)
*valp = env->ipr[IPR_ESP];
else
*valp = ldq_raw(hwpcb + 8);
break;
case IPR_FEN:
*valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63;
break;
case IPR_IPIR:
/* Write-only */
ret = -1;
break;
case IPR_IPL:
*valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
break;
case IPR_KSP:
if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
ret = -1;
} else {
if (env->features & FEATURE_SPS)
*valp = env->ipr[IPR_KSP];
else
*valp = ldq_raw(hwpcb + 0);
}
break;
case IPR_MCES:
*valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
break;
case IPR_PERFMON:
/* Implementation specific */
*valp = 0;
break;
case IPR_PCBB:
*valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
break;
case IPR_PRBR:
*valp = env->ipr[IPR_PRBR];
break;
case IPR_PTBR:
*valp = env->ipr[IPR_PTBR];
break;
case IPR_SCBB:
*valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
break;
case IPR_SIRR:
/* Write-only */
ret = -1;
break;
case IPR_SISR:
*valp = (int64_t)((int16_t)env->ipr[IPR_SISR]);
case IPR_SSP:
if (env->features & FEATURE_SPS)
*valp = env->ipr[IPR_SSP];
else
*valp = ldq_raw(hwpcb + 16);
break;
case IPR_SYSPTBR:
if (env->features & FEATURE_VIRBND)
*valp = env->ipr[IPR_SYSPTBR];
else
ret = -1;
break;
case IPR_TBCHK:
if ((env->features & FEATURE_TBCHK)) {
/* XXX: TODO */
*valp = 0;
ret = -1;
} else {
ret = -1;
}
break;
case IPR_TBIA:
/* Write-only */
ret = -1;
break;
case IPR_TBIAP:
/* Write-only */
ret = -1;
break;
case IPR_TBIS:
/* Write-only */
ret = -1;
break;
case IPR_TBISD:
/* Write-only */
ret = -1;
break;
case IPR_TBISI:
/* Write-only */
ret = -1;
break;
case IPR_USP:
if (env->features & FEATURE_SPS)
*valp = env->ipr[IPR_USP];
else
*valp = ldq_raw(hwpcb + 24);
break;
case IPR_VIRBND:
if (env->features & FEATURE_VIRBND)
*valp = env->ipr[IPR_VIRBND];
else
ret = -1;
break;
case IPR_VPTB:
*valp = env->ipr[IPR_VPTB];
break;
case IPR_WHAMI:
*valp = env->ipr[IPR_WHAMI];
break;
default:
/* Invalid */
ret = -1;
break;
}
return ret;
}
int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
{
uint64_t hwpcb, tmp64;
uint8_t tmp8;
int ret = 0;
hwpcb = env->ipr[IPR_PCBB];
switch (iprn) {
case IPR_ASN:
/* Read-only */
ret = -1;
break;
case IPR_ASTEN:
tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4;
*oldvalp = tmp8;
tmp8 &= val & 0xF;
tmp8 |= (val >> 4) & 0xF;
env->ipr[IPR_ASTEN] &= ~0xF;
env->ipr[IPR_ASTEN] |= tmp8;
ret = 1;
break;
case IPR_ASTSR:
tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4;
*oldvalp = tmp8;
tmp8 &= val & 0xF;
tmp8 |= (val >> 4) & 0xF;
env->ipr[IPR_ASTSR] &= ~0xF;
env->ipr[IPR_ASTSR] |= tmp8;
ret = 1;
case IPR_DATFX:
env->ipr[IPR_DATFX] &= ~0x1;
env->ipr[IPR_DATFX] |= val & 1;
tmp64 = ldq_raw(hwpcb + 56);
tmp64 &= ~0x8000000000000000ULL;
tmp64 |= (val & 1) << 63;
stq_raw(hwpcb + 56, tmp64);
break;
case IPR_ESP:
if (env->features & FEATURE_SPS)
env->ipr[IPR_ESP] = val;
else
stq_raw(hwpcb + 8, val);
break;
case IPR_FEN:
env->ipr[IPR_FEN] = val & 1;
tmp64 = ldq_raw(hwpcb + 56);
tmp64 &= ~1;
tmp64 |= val & 1;
stq_raw(hwpcb + 56, tmp64);
break;
case IPR_IPIR:
/* XXX: TODO: Send IRQ to CPU #ir[16] */
break;
case IPR_IPL:
*oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
env->ipr[IPR_IPL] &= ~0x1F;
env->ipr[IPR_IPL] |= val & 0x1F;
/* XXX: may issue an interrupt or ASR _now_ */
ret = 1;
break;
case IPR_KSP:
if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
ret = -1;
} else {
if (env->features & FEATURE_SPS)
env->ipr[IPR_KSP] = val;
else
stq_raw(hwpcb + 0, val);
}
break;
case IPR_MCES:
env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18);
env->ipr[IPR_MCES] |= val & 0x18;
break;
case IPR_PERFMON:
/* Implementation specific */
*oldvalp = 0;
ret = 1;
break;
case IPR_PCBB:
/* Read-only */
ret = -1;
break;
case IPR_PRBR:
env->ipr[IPR_PRBR] = val;
break;
case IPR_PTBR:
/* Read-only */
ret = -1;
break;
case IPR_SCBB:
env->ipr[IPR_SCBB] = (uint32_t)val;
break;
case IPR_SIRR:
if (val & 0xF) {
env->ipr[IPR_SISR] |= 1 << (val & 0xF);
/* XXX: request a software interrupt _now_ */
}
break;
case IPR_SISR:
/* Read-only */
ret = -1;
break;
case IPR_SSP:
if (env->features & FEATURE_SPS)
env->ipr[IPR_SSP] = val;
else
stq_raw(hwpcb + 16, val);
break;
case IPR_SYSPTBR:
if (env->features & FEATURE_VIRBND)
env->ipr[IPR_SYSPTBR] = val;
else
ret = -1;
case IPR_TBCHK:
/* Read-only */
ret = -1;
break;
case IPR_TBIA:
tlb_flush(env, 1);
break;
case IPR_TBIAP:
tlb_flush(env, 1);
break;
case IPR_TBIS:
tlb_flush_page(env, val);
break;
case IPR_TBISD:
tlb_flush_page(env, val);
break;
case IPR_TBISI:
tlb_flush_page(env, val);
break;
case IPR_USP:
if (env->features & FEATURE_SPS)
env->ipr[IPR_USP] = val;
else
stq_raw(hwpcb + 24, val);
break;
case IPR_VIRBND:
if (env->features & FEATURE_VIRBND)
env->ipr[IPR_VIRBND] = val;
else
ret = -1;
break;
case IPR_VPTB:
env->ipr[IPR_VPTB] = val;
break;
case IPR_WHAMI:
/* Read-only */
ret = -1;
break;
default:
/* Invalid */
ret = -1;
break;
}
return ret;
}
void do_interrupt (CPUState *env)
{
int excp;
env->ipr[IPR_EXC_ADDR] = env->pc | 1;
excp = env->exception_index;
env->exception_index = 0;
env->error_code = 0;
/* XXX: disable interrupts and memory mapping */
if (env->ipr[IPR_PAL_BASE] != -1ULL) {
/* We use native PALcode */
env->pc = env->ipr[IPR_PAL_BASE] + excp;
} else {
/* We use emulated PALcode */
call_pal(env);
/* Emulate REI */
env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
/* XXX: re-enable interrupts and memory mapping */
}
}
#endif
void cpu_dump_state (CPUState *env, FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
int flags)
{
static unsigned char *linux_reg_names[] = {
"v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
"t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
"a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
"t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
};
int i;
cpu_fprintf(f, " PC " TARGET_FMT_lx " PS " TARGET_FMT_lx "\n",
env->pc, env->ps);
for (i = 0; i < 31; i++) {
cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
linux_reg_names[i], env->ir[i]);
if ((i % 3) == 2)
cpu_fprintf(f, "\n");
}
cpu_fprintf(f, "\n");
for (i = 0; i < 31; i++) {
cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i,
*((uint64_t *)(&env->fir[i])));
if ((i % 3) == 2)
cpu_fprintf(f, "\n");
}
cpu_fprintf(f, "FT " TARGET_FMT_lx " " TARGET_FMT_lx " " TARGET_FMT_lx,
*((uint64_t *)(&env->ft0)), *((uint64_t *)(&env->ft1)),
*((uint64_t *)(&env->ft2)));
cpu_fprintf(f, "\nMEM " TARGET_FMT_lx " %d %d\n",
ldq_raw(0x000000004007df60ULL),
(uint8_t *)(&env->ft0), (uint8_t *)(&env->fir[0]));
}
void cpu_dump_EA (target_ulong EA)
{
FILE *f;
if (logfile)
f = logfile;
else
f = stdout;
fprintf(f, "Memory access at address " TARGET_FMT_lx "\n", EA);
}

1103
target-alpha/op.c Normal file

File diff suppressed because it is too large Load Diff

1255
target-alpha/op_helper.c Normal file

File diff suppressed because it is too large Load Diff

141
target-alpha/op_helper.h Normal file
View File

@ -0,0 +1,141 @@
/*
* Alpha emulation cpu micro-operations helpers definitions for qemu.
*
* Copyright (c) 2007 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
void helper_call_pal (uint32_t palcode);
void helper_excp (uint32_t excp, uint32_t error);
void helper_amask (void);
void helper_load_pcc (void);
void helper_load_implver (void);
void helper_load_fpcr (void);
void helper_store_fpcr (void);
void helper_load_irf (void);
void helper_set_irf (void);
void helper_clear_irf (void);
void helper_addqv (void);
void helper_addlv (void);
void helper_subqv (void);
void helper_sublv (void);
void helper_mullv (void);
void helper_mulqv (void);
void helper_umulh (void);
void helper_ctpop (void);
void helper_ctlz (void);
void helper_cttz (void);
void helper_mskbl (void);
void helper_extbl (void);
void helper_insbl (void);
void helper_mskwl (void);
void helper_extwl (void);
void helper_inswl (void);
void helper_mskll (void);
void helper_extll (void);
void helper_insll (void);
void helper_zap (void);
void helper_zapnot (void);
void helper_mskql (void);
void helper_extql (void);
void helper_insql (void);
void helper_mskwh (void);
void helper_inswh (void);
void helper_extwh (void);
void helper_msklh (void);
void helper_inslh (void);
void helper_extlh (void);
void helper_mskqh (void);
void helper_insqh (void);
void helper_extqh (void);
void helper_cmpbge (void);
void helper_cmov_fir (int freg);
double helper_ldff_raw (target_ulong ea);
void helper_stff_raw (target_ulong ea, double op);
double helper_ldfg_raw (target_ulong ea);
void helper_stfg_raw (target_ulong ea, double op);
#if !defined(CONFIG_USER_ONLY)
double helper_ldff_user (target_ulong ea);
void helper_stff_user (target_ulong ea, double op);
double helper_ldff_kernel (target_ulong ea);
void helper_stff_kernel (target_ulong ea, double op);
double helper_ldff_data (target_ulong ea);
void helper_stff_data (target_ulong ea, double op);
double helper_ldfg_user (target_ulong ea);
void helper_stfg_user (target_ulong ea, double op);
double helper_ldfg_kernel (target_ulong ea);
void helper_stfg_kernel (target_ulong ea, double op);
double helper_ldfg_data (target_ulong ea);
void helper_stfg_data (target_ulong ea, double op);
#endif
void helper_sqrts (void);
void helper_cpys (void);
void helper_cpysn (void);
void helper_cpyse (void);
void helper_itofs (void);
void helper_ftois (void);
void helper_sqrtt (void);
void helper_cmptun (void);
void helper_cmpteq (void);
void helper_cmptle (void);
void helper_cmptlt (void);
void helper_itoft (void);
void helper_ftoit (void);
void helper_addf (void);
void helper_subf (void);
void helper_mulf (void);
void helper_divf (void);
void helper_sqrtf (void);
void helper_cmpfeq (void);
void helper_cmpfne (void);
void helper_cmpflt (void);
void helper_cmpfle (void);
void helper_cmpfgt (void);
void helper_cmpfge (void);
void helper_itoff (void);
void helper_addg (void);
void helper_subg (void);
void helper_mulg (void);
void helper_divg (void);
void helper_sqrtg (void);
void helper_cmpgeq (void);
void helper_cmpglt (void);
void helper_cmpgle (void);
void helper_cvtqs (void);
void helper_cvttq (void);
void helper_cvtqt (void);
void helper_cvtqf (void);
void helper_cvtgf (void);
void helper_cvtgd (void);
void helper_cvtgq (void);
void helper_cvtqg (void);
void helper_cvtdg (void);
void helper_cvtlq (void);
void helper_cvtql (void);
void helper_cvtqlv (void);
void helper_cvtqlsv (void);
void helper_mfpr (int iprn);
void helper_mtpr (int iprn);
void helper_ld_phys_to_virt (void);
void helper_st_phys_to_virt (void);
void helper_tb_flush (void);

View File

@ -0,0 +1,40 @@
/*
* Alpha emulation cpu micro-operations helpers for memory accesses for qemu.
*
* Copyright (c) 2007 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* XXX: TODO */
double glue(helper_ldff, MEMSUFFIX) (target_ulong ea)
{
return 0;
}
void glue(helper_stff, MEMSUFFIX) (target_ulong ea, double op)
{
}
double glue(helper_ldfg, MEMSUFFIX) (target_ulong ea)
{
return 0;
}
void glue(helper_stfg, MEMSUFFIX) (target_ulong ea, double op)
{
}
#undef MEMSUFFIX

125
target-alpha/op_mem.h Normal file
View File

@ -0,0 +1,125 @@
/*
* Alpha emulation cpu micro-operations for memory accesses for qemu.
*
* Copyright (c) 2007 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define DEBUG_MEM_ACCESSES
#if defined (DEBUG_MEM_ACCESSES)
void helper_print_mem_EA (target_ulong EA);
#define print_mem_EA(EA) do { helper_print_mem_EA(EA); } while (0)
#else
#define print_mem_EA(EA) do { } while (0)
#endif
static inline uint32_t glue(ldl_l, MEMSUFFIX) (target_ulong EA)
{
env->lock = EA;
return glue(ldl, MEMSUFFIX)(EA);
}
static inline uint32_t glue(ldq_l, MEMSUFFIX) (target_ulong EA)
{
env->lock = EA;
return glue(ldq, MEMSUFFIX)(EA);
}
static inline void glue(stl_c, MEMSUFFIX) (target_ulong EA, uint32_t data)
{
if (EA == env->lock) {
glue(stl, MEMSUFFIX)(EA, data);
T0 = 0;
} else {
T0 = 1;
}
env->lock = -1;
}
static inline void glue(stq_c, MEMSUFFIX) (target_ulong EA, uint64_t data)
{
if (EA == env->lock) {
glue(stq, MEMSUFFIX)(EA, data);
T0 = 0;
} else {
T0 = 1;
}
env->lock = -1;
}
#define ALPHA_LD_OP(name, op) \
void OPPROTO glue(glue(op_ld, name), MEMSUFFIX) (void) \
{ \
print_mem_EA(T0); \
T1 = glue(op, MEMSUFFIX)(T0); \
RETURN(); \
}
#define ALPHA_ST_OP(name, op) \
void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void) \
{ \
print_mem_EA(T0); \
glue(op, MEMSUFFIX)(T0, T1); \
RETURN(); \
}
ALPHA_LD_OP(bu, ldub);
ALPHA_ST_OP(b, stb);
ALPHA_LD_OP(wu, lduw);
ALPHA_ST_OP(w, stw);
ALPHA_LD_OP(l, ldl);
ALPHA_ST_OP(l, stl);
ALPHA_LD_OP(q, ldq);
ALPHA_ST_OP(q, stq);
ALPHA_LD_OP(q_u, ldq);
ALPHA_ST_OP(q_u, stq);
ALPHA_LD_OP(l_l, ldl_l);
ALPHA_LD_OP(q_l, ldq_l);
ALPHA_ST_OP(l_c, stl_c);
ALPHA_ST_OP(q_c, stq_c);
#define ALPHA_LDF_OP(name, op) \
void OPPROTO glue(glue(op_ld, name), MEMSUFFIX) (void) \
{ \
print_mem_EA(T0); \
FT1 = glue(op, MEMSUFFIX)(T0); \
RETURN(); \
}
#define ALPHA_STF_OP(name, op) \
void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void) \
{ \
print_mem_EA(T0); \
glue(op, MEMSUFFIX)(T0, FT1); \
RETURN(); \
}
ALPHA_LDF_OP(t, ldfq);
ALPHA_STF_OP(t, stfq);
ALPHA_LDF_OP(s, ldfl);
ALPHA_STF_OP(s, stfl);
/* VAX floating point */
ALPHA_LDF_OP(f, helper_ldff);
ALPHA_STF_OP(f, helper_stff);
ALPHA_LDF_OP(g, helper_ldfg);
ALPHA_STF_OP(g, helper_stfg);
#undef MEMSUFFIX

167
target-alpha/op_template.h Normal file
View File

@ -0,0 +1,167 @@
/*
* Alpha emulation cpu micro-operations templates for qemu.
*
* Copyright (c) 2007 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Optimized constant loads */
#if REG < 3
void OPPROTO glue(op_reset_T, REG) (void)
{
glue(T, REG) = 0;
RETURN();
}
void OPPROTO glue(op_reset_FT, REG) (void)
{
glue(FT, REG) = 0;
RETURN();
}
/* XXX: This can be great on most RISC machines */
#if !defined(__i386__) && !defined(__x86_64__)
void OPPROTO glue(op_set_s16_T, REG) (void)
{
glue(T, REG) = (int16_t)PARAM(1);
RETURN();
}
void OPPROTO glue(op_set_u16_T, REG) (void)
{
glue(T, REG) = (uint16_t)PARAM(1);
RETURN();
}
#endif
void OPPROTO glue(op_set_s32_T, REG) (void)
{
glue(T, REG) = (int32_t)PARAM(1);
RETURN();
}
void OPPROTO glue(op_set_u32_T, REG) (void)
{
glue(T, REG) = (uint32_t)PARAM(1);
RETURN();
}
#if 0 // Qemu does not know how to do this...
void OPPROTO glue(op_set_64_T, REG) (void)
{
glue(T, REG) = (int64_t)PARAM(1);
RETURN();
}
#else
void OPPROTO glue(op_set_64_T, REG) (void)
{
glue(T, REG) = ((int64_t)PARAM(1) << 32) | (int64_t)PARAM(2);
RETURN();
}
#endif
#endif /* REG < 3 */
/* Fixed-point register moves */
#if REG < 31
void OPPROTO glue(op_load_T0_ir, REG) (void)
{
T0 = env->ir[REG];
RETURN();
}
void OPPROTO glue(op_load_T1_ir, REG) (void)
{
T1 = env->ir[REG];
RETURN();
}
void OPPROTO glue(op_load_T2_ir, REG) (void)
{
T2 = env->ir[REG];
RETURN();
}
void OPPROTO glue(op_store_T0_ir, REG) (void)
{
env->ir[REG] = T0;
RETURN();
}
void OPPROTO glue(op_store_T1_ir, REG) (void)
{
env->ir[REG] = T1;
RETURN();
}
void OPPROTO glue(op_store_T2_ir, REG) (void)
{
env->ir[REG] = T2;
RETURN();
}
void OPPROTO glue(op_cmov_ir, REG) (void)
{
if (T0)
env->ir[REG] = T1;
RETURN();
}
/* floating point registers moves */
void OPPROTO glue(op_load_FT0_fir, REG) (void)
{
FT0 = env->fir[REG];
RETURN();
}
void OPPROTO glue(op_load_FT1_fir, REG) (void)
{
FT1 = env->fir[REG];
RETURN();
}
void OPPROTO glue(op_load_FT2_fir, REG) (void)
{
FT2 = env->fir[REG];
RETURN();
}
void OPPROTO glue(op_store_FT0_fir, REG) (void)
{
env->fir[REG] = FT0;
RETURN();
}
void OPPROTO glue(op_store_FT1_fir, REG) (void)
{
env->fir[REG] = FT1;
RETURN();
}
void OPPROTO glue(op_store_FT2_fir, REG) (void)
{
env->fir[REG] = FT2;
RETURN();
}
void OPPROTO glue(op_cmov_fir, REG) (void)
{
helper_cmov_fir(REG);
RETURN();
}
#endif /* REG < 31 */
#undef REG

2117
target-alpha/translate.c Normal file

File diff suppressed because it is too large Load Diff