Commit 4c9649a967e45bc3086d2e752871878e08d6cdf2

Authored by j_mayer
1 parent 6fa4cea9

Alpha architecture emulation core.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2597 c046a42c-6fe2-441c-8c8c-71466251a162
target-alpha/cpu.h 0 → 100644
  1 +/*
  2 + * Alpha emulation cpu definitions 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 +#if !defined (__CPU_ALPHA_H__)
  22 +#define __CPU_ALPHA_H__
  23 +
  24 +#include "config.h"
  25 +
  26 +#define TARGET_LONG_BITS 64
  27 +
  28 +#include "cpu-defs.h"
  29 +
  30 +
  31 +#include <setjmp.h>
  32 +
  33 +#include "softfloat.h"
  34 +
  35 +/* XXX: put this in a common place */
  36 +#define likely(x) __builtin_expect(!!(x), 1)
  37 +#define unlikely(x) __builtin_expect(!!(x), 0)
  38 +
  39 +#define TARGET_HAS_ICE 1
  40 +
  41 +#define ELF_MACHINE EM_ALPHA
  42 +
  43 +#define ICACHE_LINE_SIZE 32
  44 +#define DCACHE_LINE_SIZE 32
  45 +
  46 +#define TARGET_PAGE_BITS 12
  47 +
  48 +#define VA_BITS 43
  49 +
  50 +/* Alpha major type */
  51 +enum {
  52 + ALPHA_EV3 = 1,
  53 + ALPHA_EV4 = 2,
  54 + ALPHA_SIM = 3,
  55 + ALPHA_LCA = 4,
  56 + ALPHA_EV5 = 5, /* 21164 */
  57 + ALPHA_EV45 = 6, /* 21064A */
  58 + ALPHA_EV56 = 7, /* 21164A */
  59 +};
  60 +
  61 +/* EV4 minor type */
  62 +enum {
  63 + ALPHA_EV4_2 = 0,
  64 + ALPHA_EV4_3 = 1,
  65 +};
  66 +
  67 +/* LCA minor type */
  68 +enum {
  69 + ALPHA_LCA_1 = 1, /* 21066 */
  70 + ALPHA_LCA_2 = 2, /* 20166 */
  71 + ALPHA_LCA_3 = 3, /* 21068 */
  72 + ALPHA_LCA_4 = 4, /* 21068 */
  73 + ALPHA_LCA_5 = 5, /* 21066A */
  74 + ALPHA_LCA_6 = 6, /* 21068A */
  75 +};
  76 +
  77 +/* EV5 minor type */
  78 +enum {
  79 + ALPHA_EV5_1 = 1, /* Rev BA, CA */
  80 + ALPHA_EV5_2 = 2, /* Rev DA, EA */
  81 + ALPHA_EV5_3 = 3, /* Pass 3 */
  82 + ALPHA_EV5_4 = 4, /* Pass 3.2 */
  83 + ALPHA_EV5_5 = 5, /* Pass 4 */
  84 +};
  85 +
  86 +/* EV45 minor type */
  87 +enum {
  88 + ALPHA_EV45_1 = 1, /* Pass 1 */
  89 + ALPHA_EV45_2 = 2, /* Pass 1.1 */
  90 + ALPHA_EV45_3 = 3, /* Pass 2 */
  91 +};
  92 +
  93 +/* EV56 minor type */
  94 +enum {
  95 + ALPHA_EV56_1 = 1, /* Pass 1 */
  96 + ALPHA_EV56_2 = 2, /* Pass 2 */
  97 +};
  98 +
  99 +enum {
  100 + IMPLVER_2106x = 0, /* EV4, EV45 & LCA45 */
  101 + IMPLVER_21164 = 1, /* EV5, EV56 & PCA45 */
  102 + IMPLVER_21264 = 2, /* EV6, EV67 & EV68x */
  103 + IMPLVER_21364 = 3, /* EV7 & EV79 */
  104 +};
  105 +
  106 +enum {
  107 + AMASK_BWX = 0x00000001,
  108 + AMASK_FIX = 0x00000002,
  109 + AMASK_CIX = 0x00000004,
  110 + AMASK_MVI = 0x00000100,
  111 + AMASK_TRAP = 0x00000200,
  112 + AMASK_PREFETCH = 0x00001000,
  113 +};
  114 +
  115 +enum {
  116 + VAX_ROUND_NORMAL = 0,
  117 + VAX_ROUND_CHOPPED,
  118 +};
  119 +
  120 +enum {
  121 + IEEE_ROUND_NORMAL = 0,
  122 + IEEE_ROUND_DYNAMIC,
  123 + IEEE_ROUND_PLUS,
  124 + IEEE_ROUND_MINUS,
  125 + IEEE_ROUND_CHOPPED,
  126 +};
  127 +
  128 +/* IEEE floating-point operations encoding */
  129 +/* Trap mode */
  130 +enum {
  131 + FP_TRAP_I = 0x0,
  132 + FP_TRAP_U = 0x1,
  133 + FP_TRAP_S = 0x4,
  134 + FP_TRAP_SU = 0x5,
  135 + FP_TRAP_SUI = 0x7,
  136 +};
  137 +
  138 +/* Rounding mode */
  139 +enum {
  140 + FP_ROUND_CHOPPED = 0x0,
  141 + FP_ROUND_MINUS = 0x1,
  142 + FP_ROUND_NORMAL = 0x2,
  143 + FP_ROUND_DYNAMIC = 0x3,
  144 +};
  145 +
  146 +/* Internal processor registers */
  147 +/* XXX: TOFIX: most of those registers are implementation dependant */
  148 +enum {
  149 + /* Ebox IPRs */
  150 + IPR_CC = 0xC0,
  151 + IPR_CC_CTL = 0xC1,
  152 + IPR_VA = 0xC2,
  153 + IPR_VA_CTL = 0xC4,
  154 + IPR_VA_FORM = 0xC3,
  155 + /* Ibox IPRs */
  156 + IPR_ITB_TAG = 0x00,
  157 + IPR_ITB_PTE = 0x01,
  158 + IPT_ITB_IAP = 0x02,
  159 + IPT_ITB_IA = 0x03,
  160 + IPT_ITB_IS = 0x04,
  161 + IPR_PMPC = 0x05,
  162 + IPR_EXC_ADDR = 0x06,
  163 + IPR_IVA_FORM = 0x07,
  164 + IPR_CM = 0x09,
  165 + IPR_IER = 0x0A,
  166 + IPR_SIRR = 0x0C,
  167 + IPR_ISUM = 0x0D,
  168 + IPR_HW_INT_CLR = 0x0E,
  169 + IPR_EXC_SUM = 0x0F,
  170 + IPR_PAL_BASE = 0x10,
  171 + IPR_I_CTL = 0x11,
  172 + IPR_I_STAT = 0x16,
  173 + IPR_IC_FLUSH = 0x13,
  174 + IPR_IC_FLUSH_ASM = 0x12,
  175 + IPR_CLR_MAP = 0x15,
  176 + IPR_SLEEP = 0x17,
  177 + IPR_PCTX = 0x40,
  178 + IPR_PCTR_CTL = 0x14,
  179 + /* Mbox IPRs */
  180 + IPR_DTB_TAG0 = 0x20,
  181 + IPR_DTB_TAG1 = 0xA0,
  182 + IPR_DTB_PTE0 = 0x21,
  183 + IPR_DTB_PTE1 = 0xA1,
  184 + IPR_DTB_ALTMODE = 0xA6,
  185 + IPR_DTB_IAP = 0xA2,
  186 + IPR_DTB_IA = 0xA3,
  187 + IPR_DTB_IS0 = 0x24,
  188 + IPR_DTB_IS1 = 0xA4,
  189 + IPR_DTB_ASN0 = 0x25,
  190 + IPR_DTB_ASN1 = 0xA5,
  191 + IPR_MM_STAT = 0x27,
  192 + IPR_M_CTL = 0x28,
  193 + IPR_DC_CTL = 0x29,
  194 + IPR_DC_STAT = 0x2A,
  195 + /* Cbox IPRs */
  196 + IPR_C_DATA = 0x2B,
  197 + IPR_C_SHIFT = 0x2C,
  198 +
  199 + IPR_ASN,
  200 + IPR_ASTEN,
  201 + IPR_ASTSR,
  202 + IPR_DATFX,
  203 + IPR_ESP,
  204 + IPR_FEN,
  205 + IPR_IPIR,
  206 + IPR_IPL,
  207 + IPR_KSP,
  208 + IPR_MCES,
  209 + IPR_PERFMON,
  210 + IPR_PCBB,
  211 + IPR_PRBR,
  212 + IPR_PTBR,
  213 + IPR_SCBB,
  214 + IPR_SISR,
  215 + IPR_SSP,
  216 + IPR_SYSPTBR,
  217 + IPR_TBCHK,
  218 + IPR_TBIA,
  219 + IPR_TBIAP,
  220 + IPR_TBIS,
  221 + IPR_TBISD,
  222 + IPR_TBISI,
  223 + IPR_USP,
  224 + IPR_VIRBND,
  225 + IPR_VPTB,
  226 + IPR_WHAMI,
  227 + IPR_ALT_MODE,
  228 + IPR_LAST,
  229 +};
  230 +
  231 +typedef struct CPUAlphaState CPUAlphaState;
  232 +
  233 +typedef struct pal_handler_t pal_handler_t;
  234 +struct pal_handler_t {
  235 + /* Reset */
  236 + void (*reset)(CPUAlphaState *env);
  237 + /* Uncorrectable hardware error */
  238 + void (*machine_check)(CPUAlphaState *env);
  239 + /* Arithmetic exception */
  240 + void (*arithmetic)(CPUAlphaState *env);
  241 + /* Interrupt / correctable hardware error */
  242 + void (*interrupt)(CPUAlphaState *env);
  243 + /* Data fault */
  244 + void (*dfault)(CPUAlphaState *env);
  245 + /* DTB miss pal */
  246 + void (*dtb_miss_pal)(CPUAlphaState *env);
  247 + /* DTB miss native */
  248 + void (*dtb_miss_native)(CPUAlphaState *env);
  249 + /* Unaligned access */
  250 + void (*unalign)(CPUAlphaState *env);
  251 + /* ITB miss */
  252 + void (*itb_miss)(CPUAlphaState *env);
  253 + /* Instruction stream access violation */
  254 + void (*itb_acv)(CPUAlphaState *env);
  255 + /* Reserved or privileged opcode */
  256 + void (*opcdec)(CPUAlphaState *env);
  257 + /* Floating point exception */
  258 + void (*fen)(CPUAlphaState *env);
  259 + /* Call pal instruction */
  260 + void (*call_pal)(CPUAlphaState *env, uint32_t palcode);
  261 +};
  262 +
  263 +struct CPUAlphaState {
  264 + uint64_t ir[31];
  265 + float64 fir[31];
  266 + float_status fp_status;
  267 + uint64_t fpcr;
  268 + uint64_t pc;
  269 + uint64_t lock;
  270 + uint32_t pcc[2];
  271 + uint64_t ipr[IPR_LAST];
  272 + uint64_t ps;
  273 + uint64_t unique;
  274 + int saved_mode; /* Used for HW_LD / HW_ST */
  275 +
  276 + /* */
  277 + double ft0, ft1, ft2;
  278 +
  279 + /* Those resources are used only in Qemu core */
  280 + CPU_COMMON
  281 +
  282 + jmp_buf jmp_env;
  283 + int user_mode_only; /* user mode only simulation */
  284 + uint32_t hflags;
  285 + int halted;
  286 +
  287 + int exception_index;
  288 + int error_code;
  289 + int interrupt_request;
  290 +
  291 + uint32_t features;
  292 + uint32_t amask;
  293 + int implver;
  294 + pal_handler_t *pal_handler;
  295 +};
  296 +
  297 +#include "cpu-all.h"
  298 +
  299 +enum {
  300 + FEATURE_ASN = 0x00000001,
  301 + FEATURE_SPS = 0x00000002,
  302 + FEATURE_VIRBND = 0x00000004,
  303 + FEATURE_TBCHK = 0x00000008,
  304 +};
  305 +
  306 +enum {
  307 + EXCP_RESET = 0x0000,
  308 + EXCP_MCHK = 0x0020,
  309 + EXCP_ARITH = 0x0060,
  310 + EXCP_HW_INTERRUPT = 0x00E0,
  311 + EXCP_DFAULT = 0x01E0,
  312 + EXCP_DTB_MISS_PAL = 0x09E0,
  313 + EXCP_ITB_MISS = 0x03E0,
  314 + EXCP_ITB_ACV = 0x07E0,
  315 + EXCP_DTB_MISS_NATIVE = 0x08E0,
  316 + EXCP_UNALIGN = 0x11E0,
  317 + EXCP_OPCDEC = 0x13E0,
  318 + EXCP_FEN = 0x17E0,
  319 + EXCP_CALL_PAL = 0x2000,
  320 + EXCP_CALL_PALP = 0x3000,
  321 + EXCP_CALL_PALE = 0x4000,
  322 + /* Pseudo exception for console */
  323 + EXCP_CONSOLE_DISPATCH = 0x4001,
  324 + EXCP_CONSOLE_FIXUP = 0x4002,
  325 +};
  326 +
  327 +/* Arithmetic exception */
  328 +enum {
  329 + EXCP_ARITH_OVERFLOW,
  330 +};
  331 +
  332 +enum {
  333 + PALCODE_CALL = 0x00000000,
  334 + PALCODE_LD = 0x01000000,
  335 + PALCODE_ST = 0x02000000,
  336 + PALCODE_MFPR = 0x03000000,
  337 + PALCODE_MTPR = 0x04000000,
  338 + PALCODE_REI = 0x05000000,
  339 + PALCODE_INIT = 0xF0000000,
  340 +};
  341 +
  342 +enum {
  343 + IR_V0 = 0,
  344 + IR_T0 = 1,
  345 + IR_T1 = 2,
  346 + IR_T2 = 3,
  347 + IR_T3 = 4,
  348 + IR_T4 = 5,
  349 + IR_T5 = 6,
  350 + IR_T6 = 7,
  351 + IR_T7 = 8,
  352 + IR_S0 = 9,
  353 + IR_S1 = 10,
  354 + IR_S2 = 11,
  355 + IR_S3 = 12,
  356 + IR_S4 = 13,
  357 + IR_S5 = 14,
  358 + IR_S6 = 15,
  359 +#define IR_FP IR_S6
  360 + IR_A0 = 16,
  361 + IR_A1 = 17,
  362 + IR_A2 = 18,
  363 + IR_A3 = 19,
  364 + IR_A4 = 20,
  365 + IR_A5 = 21,
  366 + IR_T8 = 22,
  367 + IR_T9 = 23,
  368 + IR_T10 = 24,
  369 + IR_T11 = 25,
  370 + IR_RA = 26,
  371 + IR_T12 = 27,
  372 +#define IR_PV IR_T12
  373 + IR_AT = 28,
  374 + IR_GP = 29,
  375 + IR_SP = 30,
  376 + IR_ZERO = 31,
  377 +};
  378 +
  379 +int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
  380 +int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
  381 +void cpu_loop_exit (void);
  382 +void pal_init (CPUState *env);
  383 +void call_pal (CPUState *env, int palcode);
  384 +
  385 +#endif /* !defined (__CPU_ALPHA_H__) */
target-alpha/exec.h 0 → 100644
  1 +/*
  2 + * Alpha emulation cpu run-time definitions 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 +#if !defined (__ALPHA_EXEC_H__)
  22 +#define __ALPHA_EXEC_H__
  23 +
  24 +#include "config.h"
  25 +
  26 +#include "dyngen-exec.h"
  27 +
  28 +#define TARGET_LONG_BITS 64
  29 +
  30 +register struct CPUAlphaState *env asm(AREG0);
  31 +
  32 +#if TARGET_LONG_BITS > HOST_LONG_BITS
  33 +
  34 +/* no registers can be used */
  35 +#define T0 (env->t0)
  36 +#define T1 (env->t1)
  37 +#define T2 (env->t2)
  38 +
  39 +#else
  40 +
  41 +register uint64_t T0 asm(AREG1);
  42 +register uint64_t T1 asm(AREG2);
  43 +register uint64_t T2 asm(AREG3);
  44 +
  45 +#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
  46 +
  47 +#define PARAM(n) ((uint64_t)PARAM##n)
  48 +#define SPARAM(n) ((int32_t)PARAM##n)
  49 +#define FT0 (env->ft0)
  50 +#define FT1 (env->ft1)
  51 +#define FT2 (env->ft2)
  52 +#define FP_STATUS (env->fp_status)
  53 +
  54 +#if defined (DEBUG_OP)
  55 +#define RETURN() __asm__ __volatile__("nop" : : : "memory");
  56 +#else
  57 +#define RETURN() __asm__ __volatile__("" : : : "memory");
  58 +#endif
  59 +
  60 +#include "cpu.h"
  61 +#include "exec-all.h"
  62 +
  63 +#if !defined(CONFIG_USER_ONLY)
  64 +#include "softmmu_exec.h"
  65 +#endif /* !defined(CONFIG_USER_ONLY) */
  66 +
  67 +static inline void env_to_regs(void)
  68 +{
  69 +}
  70 +
  71 +static inline void regs_to_env(void)
  72 +{
  73 +}
  74 +
  75 +int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw,
  76 + int is_user, int is_softmmu);
  77 +int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
  78 +int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
  79 +
  80 +void do_interrupt (CPUState *env);
  81 +
  82 +#endif /* !defined (__ALPHA_EXEC_H__) */
target-alpha/helper.c 0 → 100644
  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 is_user, 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_ulong 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_ulong 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 is_user, 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 +}
target-alpha/op.c 0 → 100644
  1 +/*
  2 + * Alpha emulation cpu micro-operations 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 +#define DEBUG_OP
  22 +
  23 +#include "config.h"
  24 +#include "exec.h"
  25 +
  26 +#include "op_helper.h"
  27 +
  28 +#define REG 0
  29 +#include "op_template.h"
  30 +
  31 +#define REG 1
  32 +#include "op_template.h"
  33 +
  34 +#define REG 2
  35 +#include "op_template.h"
  36 +
  37 +#define REG 3
  38 +#include "op_template.h"
  39 +
  40 +#define REG 4
  41 +#include "op_template.h"
  42 +
  43 +#define REG 5
  44 +#include "op_template.h"
  45 +
  46 +#define REG 6
  47 +#include "op_template.h"
  48 +
  49 +#define REG 7
  50 +#include "op_template.h"
  51 +
  52 +#define REG 8
  53 +#include "op_template.h"
  54 +
  55 +#define REG 9
  56 +#include "op_template.h"
  57 +
  58 +#define REG 10
  59 +#include "op_template.h"
  60 +
  61 +#define REG 11
  62 +#include "op_template.h"
  63 +
  64 +#define REG 12
  65 +#include "op_template.h"
  66 +
  67 +#define REG 13
  68 +#include "op_template.h"
  69 +
  70 +#define REG 14
  71 +#include "op_template.h"
  72 +
  73 +#define REG 15
  74 +#include "op_template.h"
  75 +
  76 +#define REG 16
  77 +#include "op_template.h"
  78 +
  79 +#define REG 17
  80 +#include "op_template.h"
  81 +
  82 +#define REG 18
  83 +#include "op_template.h"
  84 +
  85 +#define REG 19
  86 +#include "op_template.h"
  87 +
  88 +#define REG 20
  89 +#include "op_template.h"
  90 +
  91 +#define REG 21
  92 +#include "op_template.h"
  93 +
  94 +#define REG 22
  95 +#include "op_template.h"
  96 +
  97 +#define REG 23
  98 +#include "op_template.h"
  99 +
  100 +#define REG 24
  101 +#include "op_template.h"
  102 +
  103 +#define REG 25
  104 +#include "op_template.h"
  105 +
  106 +#define REG 26
  107 +#include "op_template.h"
  108 +
  109 +#define REG 27
  110 +#include "op_template.h"
  111 +
  112 +#define REG 28
  113 +#include "op_template.h"
  114 +
  115 +#define REG 29
  116 +#include "op_template.h"
  117 +
  118 +#define REG 30
  119 +#include "op_template.h"
  120 +
  121 +#define REG 31
  122 +#include "op_template.h"
  123 +
  124 +/* Debug stuff */
  125 +void OPPROTO op_no_op (void)
  126 +{
  127 +#if !defined (DEBUG_OP)
  128 + __asm__ __volatile__("nop" : : : "memory");
  129 +#endif
  130 + RETURN();
  131 +}
  132 +
  133 +void OPPROTO op_tb_flush (void)
  134 +{
  135 + helper_tb_flush();
  136 + RETURN();
  137 +}
  138 +
  139 +/* Load and stores */
  140 +#define MEMSUFFIX _raw
  141 +#include "op_mem.h"
  142 +#if !defined(CONFIG_USER_ONLY)
  143 +#define MEMSUFFIX _user
  144 +#include "op_mem.h"
  145 +#define MEMSUFFIX _kernel
  146 +#include "op_mem.h"
  147 +/* Those are used for supervisor, executive and pal modes */
  148 +#define MEMSUFFIX _data
  149 +#include "op_mem.h"
  150 +#endif
  151 +
  152 +/* Special operation for load and store */
  153 +void OPPROTO op_n7 (void)
  154 +{
  155 + T0 &= ~(uint64_t)0x7;
  156 + RETURN();
  157 +}
  158 +
  159 +/* Misc */
  160 +void OPPROTO op_excp (void)
  161 +{
  162 + helper_excp(PARAM(1), PARAM(2));
  163 + RETURN();
  164 +}
  165 +
  166 +void OPPROTO op_load_amask (void)
  167 +{
  168 + helper_amask();
  169 + RETURN();
  170 +}
  171 +
  172 +void OPPROTO op_load_pcc (void)
  173 +{
  174 + helper_load_pcc();
  175 + RETURN();
  176 +}
  177 +
  178 +void OPPROTO op_load_implver (void)
  179 +{
  180 + helper_load_implver();
  181 + RETURN();
  182 +}
  183 +
  184 +void OPPROTO op_load_fpcr (void)
  185 +{
  186 + helper_load_fpcr();
  187 + RETURN();
  188 +}
  189 +
  190 +void OPPROTO op_store_fpcr (void)
  191 +{
  192 + helper_store_fpcr();
  193 + RETURN();
  194 +}
  195 +
  196 +void OPPROTO op_load_irf (void)
  197 +{
  198 + helper_load_irf();
  199 + RETURN();
  200 +}
  201 +
  202 +void OPPROTO op_set_irf (void)
  203 +{
  204 + helper_set_irf();
  205 + RETURN();
  206 +}
  207 +
  208 +void OPPROTO op_clear_irf (void)
  209 +{
  210 + helper_clear_irf();
  211 + RETURN();
  212 +}
  213 +
  214 +void OPPROTO op_exit_tb (void)
  215 +{
  216 + EXIT_TB();
  217 +}
  218 +
  219 +/* Arithmetic */
  220 +void OPPROTO op_addq (void)
  221 +{
  222 + T0 += T1;
  223 + RETURN();
  224 +}
  225 +
  226 +void OPPROTO op_addqv (void)
  227 +{
  228 + helper_addqv();
  229 + RETURN();
  230 +}
  231 +
  232 +void OPPROTO op_addl (void)
  233 +{
  234 + T0 = (int64_t)((int32_t)(T0 + T1));
  235 + RETURN();
  236 +}
  237 +
  238 +void OPPROTO op_addlv (void)
  239 +{
  240 + helper_addlv();
  241 + RETURN();
  242 +}
  243 +
  244 +void OPPROTO op_subq (void)
  245 +{
  246 + T0 -= T1;
  247 + RETURN();
  248 +}
  249 +
  250 +void OPPROTO op_subqv (void)
  251 +{
  252 + helper_subqv();
  253 + RETURN();
  254 +}
  255 +
  256 +void OPPROTO op_subl (void)
  257 +{
  258 + T0 = (int64_t)((int32_t)(T0 - T1));
  259 + RETURN();
  260 +}
  261 +
  262 +void OPPROTO op_sublv (void)
  263 +{
  264 + helper_sublv();
  265 + RETURN();
  266 +}
  267 +
  268 +void OPPROTO op_s4 (void)
  269 +{
  270 + T0 <<= 2;
  271 + RETURN();
  272 +}
  273 +
  274 +void OPPROTO op_s8 (void)
  275 +{
  276 + T0 <<= 3;
  277 + RETURN();
  278 +}
  279 +
  280 +void OPPROTO op_mull (void)
  281 +{
  282 + T0 = (int64_t)((int32_t)T0 * (int32_t)T1);
  283 + RETURN();
  284 +}
  285 +
  286 +void OPPROTO op_mullv (void)
  287 +{
  288 + helper_mullv();
  289 + RETURN();
  290 +}
  291 +
  292 +void OPPROTO op_mulq (void)
  293 +{
  294 + T0 *= T1;
  295 + RETURN();
  296 +}
  297 +
  298 +void OPPROTO op_mulqv (void)
  299 +{
  300 + helper_mulqv();
  301 + RETURN();
  302 +}
  303 +
  304 +void OPPROTO op_umulh (void)
  305 +{
  306 + helper_umulh();
  307 + RETURN();
  308 +}
  309 +
  310 +/* Logical */
  311 +void OPPROTO op_and (void)
  312 +{
  313 + T0 &= T1;
  314 + RETURN();
  315 +}
  316 +
  317 +void OPPROTO op_bic (void)
  318 +{
  319 + T0 &= ~T1;
  320 + RETURN();
  321 +}
  322 +
  323 +void OPPROTO op_bis (void)
  324 +{
  325 + T0 |= T1;
  326 + RETURN();
  327 +}
  328 +
  329 +void OPPROTO op_eqv (void)
  330 +{
  331 + T0 ^= ~T1;
  332 + RETURN();
  333 +}
  334 +
  335 +void OPPROTO op_ornot (void)
  336 +{
  337 + T0 |= ~T1;
  338 + RETURN();
  339 +}
  340 +
  341 +void OPPROTO op_xor (void)
  342 +{
  343 + T0 ^= T1;
  344 + RETURN();
  345 +}
  346 +
  347 +void OPPROTO op_sll (void)
  348 +{
  349 + T0 <<= T1;
  350 + RETURN();
  351 +}
  352 +
  353 +void OPPROTO op_srl (void)
  354 +{
  355 + T0 >>= T1;
  356 + RETURN();
  357 +}
  358 +
  359 +void OPPROTO op_sra (void)
  360 +{
  361 + T0 = (int64_t)T0 >> T1;
  362 + RETURN();
  363 +}
  364 +
  365 +void OPPROTO op_sextb (void)
  366 +{
  367 + T0 = (int64_t)((int8_t)T0);
  368 + RETURN();
  369 +}
  370 +
  371 +void OPPROTO op_sextw (void)
  372 +{
  373 + T0 = (int64_t)((int16_t)T0);
  374 + RETURN();
  375 +
  376 +}
  377 +
  378 +void OPPROTO op_ctpop (void)
  379 +{
  380 + helper_ctpop();
  381 + RETURN();
  382 +}
  383 +
  384 +void OPPROTO op_ctlz (void)
  385 +{
  386 + helper_ctlz();
  387 + RETURN();
  388 +}
  389 +
  390 +void OPPROTO op_cttz (void)
  391 +{
  392 + helper_cttz();
  393 + RETURN();
  394 +}
  395 +
  396 +void OPPROTO op_mskbl (void)
  397 +{
  398 + helper_mskbl();
  399 + RETURN();
  400 +}
  401 +
  402 +void OPPROTO op_extbl (void)
  403 +{
  404 + helper_extbl();
  405 + RETURN();
  406 +}
  407 +
  408 +void OPPROTO op_insbl (void)
  409 +{
  410 + helper_insbl();
  411 + RETURN();
  412 +}
  413 +
  414 +void OPPROTO op_mskwl (void)
  415 +{
  416 + helper_mskwl();
  417 + RETURN();
  418 +}
  419 +
  420 +void OPPROTO op_extwl (void)
  421 +{
  422 + helper_extwl();
  423 + RETURN();
  424 +}
  425 +
  426 +void OPPROTO op_inswl (void)
  427 +{
  428 + helper_inswl();
  429 + RETURN();
  430 +}
  431 +
  432 +void OPPROTO op_mskll (void)
  433 +{
  434 + helper_mskll();
  435 + RETURN();
  436 +}
  437 +
  438 +void OPPROTO op_extll (void)
  439 +{
  440 + helper_extll();
  441 + RETURN();
  442 +}
  443 +
  444 +void OPPROTO op_insll (void)
  445 +{
  446 + helper_insll();
  447 + RETURN();
  448 +}
  449 +
  450 +void OPPROTO op_zap (void)
  451 +{
  452 + helper_zap();
  453 + RETURN();
  454 +}
  455 +
  456 +void OPPROTO op_zapnot (void)
  457 +{
  458 + helper_zapnot();
  459 + RETURN();
  460 +}
  461 +
  462 +void OPPROTO op_mskql (void)
  463 +{
  464 + helper_mskql();
  465 + RETURN();
  466 +}
  467 +
  468 +void OPPROTO op_extql (void)
  469 +{
  470 + helper_extql();
  471 + RETURN();
  472 +}
  473 +
  474 +void OPPROTO op_insql (void)
  475 +{
  476 + helper_insql();
  477 + RETURN();
  478 +}
  479 +
  480 +void OPPROTO op_mskwh (void)
  481 +{
  482 + helper_mskwh();
  483 + RETURN();
  484 +}
  485 +
  486 +void OPPROTO op_inswh (void)
  487 +{
  488 + helper_inswh();
  489 + RETURN();
  490 +}
  491 +
  492 +void OPPROTO op_extwh (void)
  493 +{
  494 + helper_extwh();
  495 + RETURN();
  496 +}
  497 +
  498 +void OPPROTO op_msklh (void)
  499 +{
  500 + helper_msklh();
  501 + RETURN();
  502 +}
  503 +
  504 +void OPPROTO op_inslh (void)
  505 +{
  506 + helper_inslh();
  507 + RETURN();
  508 +}
  509 +
  510 +void OPPROTO op_extlh (void)
  511 +{
  512 + helper_extlh();
  513 + RETURN();
  514 +}
  515 +
  516 +void OPPROTO op_mskqh (void)
  517 +{
  518 + helper_mskqh();
  519 + RETURN();
  520 +}
  521 +
  522 +void OPPROTO op_insqh (void)
  523 +{
  524 + helper_insqh();
  525 + RETURN();
  526 +}
  527 +
  528 +void OPPROTO op_extqh (void)
  529 +{
  530 + helper_extqh();
  531 + RETURN();
  532 +}
  533 +
  534 +/* Tests */
  535 +void OPPROTO op_cmpult (void)
  536 +{
  537 + if (T0 < T1)
  538 + T0 = 1;
  539 + else
  540 + T0 = 0;
  541 + RETURN();
  542 +}
  543 +
  544 +void OPPROTO op_cmpule (void)
  545 +{
  546 + if (T0 <= T1)
  547 + T0 = 1;
  548 + else
  549 + T0 = 0;
  550 + RETURN();
  551 +}
  552 +
  553 +void OPPROTO op_cmpeq (void)
  554 +{
  555 + if (T0 == T1)
  556 + T0 = 1;
  557 + else
  558 + T0 = 0;
  559 + RETURN();
  560 +}
  561 +
  562 +void OPPROTO op_cmplt (void)
  563 +{
  564 + if ((int64_t)T0 < (int64_t)T1)
  565 + T0 = 1;
  566 + else
  567 + T0 = 0;
  568 + RETURN();
  569 +}
  570 +
  571 +void OPPROTO op_cmple (void)
  572 +{
  573 + if ((int64_t)T0 <= (int64_t)T1)
  574 + T0 = 1;
  575 + else
  576 + T0 = 0;
  577 + RETURN();
  578 +}
  579 +
  580 +void OPPROTO op_cmpbge (void)
  581 +{
  582 + helper_cmpbge();
  583 + RETURN();
  584 +}
  585 +
  586 +void OPPROTO op_cmpeqz (void)
  587 +{
  588 + if (T0 == 0)
  589 + T0 = 1;
  590 + else
  591 + T0 = 0;
  592 + RETURN();
  593 +}
  594 +
  595 +void OPPROTO op_cmpnez (void)
  596 +{
  597 + if (T0 != 0)
  598 + T0 = 1;
  599 + else
  600 + T0 = 0;
  601 + RETURN();
  602 +}
  603 +
  604 +void OPPROTO op_cmpltz (void)
  605 +{
  606 + if ((int64_t)T0 < 0)
  607 + T0 = 1;
  608 + else
  609 + T0 = 0;
  610 + RETURN();
  611 +}
  612 +
  613 +void OPPROTO op_cmplez (void)
  614 +{
  615 + if ((int64_t)T0 <= 0)
  616 + T0 = 1;
  617 + else
  618 + T0 = 0;
  619 + RETURN();
  620 +}
  621 +
  622 +void OPPROTO op_cmpgtz (void)
  623 +{
  624 + if ((int64_t)T0 > 0)
  625 + T0 = 1;
  626 + else
  627 + T0 = 0;
  628 + RETURN();
  629 +}
  630 +
  631 +void OPPROTO op_cmpgez (void)
  632 +{
  633 + if ((int64_t)T0 >= 0)
  634 + T0 = 1;
  635 + else
  636 + T0 = 0;
  637 + RETURN();
  638 +}
  639 +
  640 +void OPPROTO op_cmplbs (void)
  641 +{
  642 + T0 &= 1;
  643 + RETURN();
  644 +}
  645 +
  646 +void OPPROTO op_cmplbc (void)
  647 +{
  648 + T0 = (~T0) & 1;
  649 + RETURN();
  650 +}
  651 +
  652 +/* Branches */
  653 +void OPPROTO op_branch (void)
  654 +{
  655 + env->pc = T0 & ~3;
  656 + RETURN();
  657 +}
  658 +
  659 +void OPPROTO op_addq1 (void)
  660 +{
  661 + T1 += T0;
  662 + RETURN();
  663 +}
  664 +
  665 +#if 0 // Qemu does not know how to do this...
  666 +void OPPROTO op_bcond (void)
  667 +{
  668 + if (T0)
  669 + env->pc = T1 & ~3;
  670 + else
  671 + env->pc = PARAM(1);
  672 + RETURN();
  673 +}
  674 +#else
  675 +void OPPROTO op_bcond (void)
  676 +{
  677 + if (T0)
  678 + env->pc = T1 & ~3;
  679 + else
  680 + env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2);
  681 + RETURN();
  682 +}
  683 +#endif
  684 +
  685 +#if 0 // Qemu does not know how to do this...
  686 +void OPPROTO op_update_pc (void)
  687 +{
  688 + env->pc = PARAM(1);
  689 + RETURN();
  690 +}
  691 +#else
  692 +void OPPROTO op_update_pc (void)
  693 +{
  694 + env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2);
  695 + RETURN();
  696 +}
  697 +#endif
  698 +
  699 +/* Optimization for 32 bits hosts architectures */
  700 +void OPPROTO op_update_pc32 (void)
  701 +{
  702 + env->pc = (uint64_t)PARAM(1);
  703 + RETURN();
  704 +}
  705 +
  706 +/* IEEE floating point arithmetic */
  707 +/* S floating (single) */
  708 +void OPPROTO op_adds (void)
  709 +{
  710 + FT0 = float32_add(FT0, FT1, &FP_STATUS);
  711 + RETURN();
  712 +}
  713 +
  714 +void OPPROTO op_subs (void)
  715 +{
  716 + FT0 = float32_sub(FT0, FT1, &FP_STATUS);
  717 + RETURN();
  718 +}
  719 +
  720 +void OPPROTO op_muls (void)
  721 +{
  722 + FT0 = float32_mul(FT0, FT1, &FP_STATUS);
  723 + RETURN();
  724 +}
  725 +
  726 +void OPPROTO op_divs (void)
  727 +{
  728 + FT0 = float32_div(FT0, FT1, &FP_STATUS);
  729 + RETURN();
  730 +}
  731 +
  732 +void OPPROTO op_sqrts (void)
  733 +{
  734 + helper_sqrts();
  735 + RETURN();
  736 +}
  737 +
  738 +void OPPROTO op_cpys (void)
  739 +{
  740 + helper_cpys();
  741 + RETURN();
  742 +}
  743 +
  744 +void OPPROTO op_cpysn (void)
  745 +{
  746 + helper_cpysn();
  747 + RETURN();
  748 +}
  749 +
  750 +void OPPROTO op_cpyse (void)
  751 +{
  752 + helper_cpyse();
  753 + RETURN();
  754 +}
  755 +
  756 +void OPPROTO op_itofs (void)
  757 +{
  758 + helper_itofs();
  759 + RETURN();
  760 +}
  761 +
  762 +void OPPROTO op_ftois (void)
  763 +{
  764 + helper_ftois();
  765 + RETURN();
  766 +}
  767 +
  768 +/* T floating (double) */
  769 +void OPPROTO op_addt (void)
  770 +{
  771 + FT0 = float64_add(FT0, FT1, &FP_STATUS);
  772 + RETURN();
  773 +}
  774 +
  775 +void OPPROTO op_subt (void)
  776 +{
  777 + FT0 = float64_sub(FT0, FT1, &FP_STATUS);
  778 + RETURN();
  779 +}
  780 +
  781 +void OPPROTO op_mult (void)
  782 +{
  783 + FT0 = float64_mul(FT0, FT1, &FP_STATUS);
  784 + RETURN();
  785 +}
  786 +
  787 +void OPPROTO op_divt (void)
  788 +{
  789 + FT0 = float64_div(FT0, FT1, &FP_STATUS);
  790 + RETURN();
  791 +}
  792 +
  793 +void OPPROTO op_sqrtt (void)
  794 +{
  795 + helper_sqrtt();
  796 + RETURN();
  797 +}
  798 +
  799 +void OPPROTO op_cmptun (void)
  800 +{
  801 + helper_cmptun();
  802 + RETURN();
  803 +}
  804 +
  805 +void OPPROTO op_cmpteq (void)
  806 +{
  807 + helper_cmpteq();
  808 + RETURN();
  809 +}
  810 +
  811 +void OPPROTO op_cmptle (void)
  812 +{
  813 + helper_cmptle();
  814 + RETURN();
  815 +}
  816 +
  817 +void OPPROTO op_cmptlt (void)
  818 +{
  819 + helper_cmptlt();
  820 + RETURN();
  821 +}
  822 +
  823 +void OPPROTO op_itoft (void)
  824 +{
  825 + helper_itoft();
  826 + RETURN();
  827 +}
  828 +
  829 +void OPPROTO op_ftoit (void)
  830 +{
  831 + helper_ftoit();
  832 + RETURN();
  833 +}
  834 +
  835 +/* VAX floating point arithmetic */
  836 +/* F floating */
  837 +void OPPROTO op_addf (void)
  838 +{
  839 + helper_addf();
  840 + RETURN();
  841 +}
  842 +
  843 +void OPPROTO op_subf (void)
  844 +{
  845 + helper_subf();
  846 + RETURN();
  847 +}
  848 +
  849 +void OPPROTO op_mulf (void)
  850 +{
  851 + helper_mulf();
  852 + RETURN();
  853 +}
  854 +
  855 +void OPPROTO op_divf (void)
  856 +{
  857 + helper_divf();
  858 + RETURN();
  859 +}
  860 +
  861 +void OPPROTO op_sqrtf (void)
  862 +{
  863 + helper_sqrtf();
  864 + RETURN();
  865 +}
  866 +
  867 +void OPPROTO op_cmpfeq (void)
  868 +{
  869 + helper_cmpfeq();
  870 + RETURN();
  871 +}
  872 +
  873 +void OPPROTO op_cmpfne (void)
  874 +{
  875 + helper_cmpfne();
  876 + RETURN();
  877 +}
  878 +
  879 +void OPPROTO op_cmpflt (void)
  880 +{
  881 + helper_cmpflt();
  882 + RETURN();
  883 +}
  884 +
  885 +void OPPROTO op_cmpfle (void)
  886 +{
  887 + helper_cmpfle();
  888 + RETURN();
  889 +}
  890 +
  891 +void OPPROTO op_cmpfgt (void)
  892 +{
  893 + helper_cmpfgt();
  894 + RETURN();
  895 +}
  896 +
  897 +void OPPROTO op_cmpfge (void)
  898 +{
  899 + helper_cmpfge();
  900 + RETURN();
  901 +}
  902 +
  903 +void OPPROTO op_itoff (void)
  904 +{
  905 + helper_itoff();
  906 + RETURN();
  907 +}
  908 +
  909 +/* G floating */
  910 +void OPPROTO op_addg (void)
  911 +{
  912 + helper_addg();
  913 + RETURN();
  914 +}
  915 +
  916 +void OPPROTO op_subg (void)
  917 +{
  918 + helper_subg();
  919 + RETURN();
  920 +}
  921 +
  922 +void OPPROTO op_mulg (void)
  923 +{
  924 + helper_mulg();
  925 + RETURN();
  926 +}
  927 +
  928 +void OPPROTO op_divg (void)
  929 +{
  930 + helper_divg();
  931 + RETURN();
  932 +}
  933 +
  934 +void OPPROTO op_sqrtg (void)
  935 +{
  936 + helper_sqrtg();
  937 + RETURN();
  938 +}
  939 +
  940 +void OPPROTO op_cmpgeq (void)
  941 +{
  942 + helper_cmpgeq();
  943 + RETURN();
  944 +}
  945 +
  946 +void OPPROTO op_cmpglt (void)
  947 +{
  948 + helper_cmpglt();
  949 + RETURN();
  950 +}
  951 +
  952 +void OPPROTO op_cmpgle (void)
  953 +{
  954 + helper_cmpgle();
  955 + RETURN();
  956 +}
  957 +
  958 +/* Floating point format conversion */
  959 +void OPPROTO op_cvtst (void)
  960 +{
  961 + FT0 = (float)FT0;
  962 + RETURN();
  963 +}
  964 +
  965 +void OPPROTO op_cvtqs (void)
  966 +{
  967 + helper_cvtqs();
  968 + RETURN();
  969 +}
  970 +
  971 +void OPPROTO op_cvtts (void)
  972 +{
  973 + FT0 = (float)FT0;
  974 + RETURN();
  975 +}
  976 +
  977 +void OPPROTO op_cvttq (void)
  978 +{
  979 + helper_cvttq();
  980 + RETURN();
  981 +}
  982 +
  983 +void OPPROTO op_cvtqt (void)
  984 +{
  985 + helper_cvtqt();
  986 + RETURN();
  987 +}
  988 +
  989 +void OPPROTO op_cvtqf (void)
  990 +{
  991 + helper_cvtqf();
  992 + RETURN();
  993 +}
  994 +
  995 +void OPPROTO op_cvtgf (void)
  996 +{
  997 + helper_cvtgf();
  998 + RETURN();
  999 +}
  1000 +
  1001 +void OPPROTO op_cvtgd (void)
  1002 +{
  1003 + helper_cvtgd();
  1004 + RETURN();
  1005 +}
  1006 +
  1007 +void OPPROTO op_cvtgq (void)
  1008 +{
  1009 + helper_cvtgq();
  1010 + RETURN();
  1011 +}
  1012 +
  1013 +void OPPROTO op_cvtqg (void)
  1014 +{
  1015 + helper_cvtqg();
  1016 + RETURN();
  1017 +}
  1018 +
  1019 +void OPPROTO op_cvtdg (void)
  1020 +{
  1021 + helper_cvtdg();
  1022 + RETURN();
  1023 +}
  1024 +
  1025 +void OPPROTO op_cvtlq (void)
  1026 +{
  1027 + helper_cvtlq();
  1028 + RETURN();
  1029 +}
  1030 +
  1031 +void OPPROTO op_cvtql (void)
  1032 +{
  1033 + helper_cvtql();
  1034 + RETURN();
  1035 +}
  1036 +
  1037 +void OPPROTO op_cvtqlv (void)
  1038 +{
  1039 + helper_cvtqlv();
  1040 + RETURN();
  1041 +}
  1042 +
  1043 +void OPPROTO op_cvtqlsv (void)
  1044 +{
  1045 + helper_cvtqlsv();
  1046 + RETURN();
  1047 +}
  1048 +
  1049 +/* PALcode support special instructions */
  1050 +#if !defined (CONFIG_USER_ONLY)
  1051 +void OPPROTO op_hw_rei (void)
  1052 +{
  1053 + env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
  1054 + env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
  1055 + /* XXX: re-enable interrupts and memory mapping */
  1056 + RETURN();
  1057 +}
  1058 +
  1059 +void OPPROTO op_hw_ret (void)
  1060 +{
  1061 + env->pc = T0 & ~3;
  1062 + env->ipr[IPR_EXC_ADDR] = T0 & 1;
  1063 + /* XXX: re-enable interrupts and memory mapping */
  1064 + RETURN();
  1065 +}
  1066 +
  1067 +void OPPROTO op_mfpr (void)
  1068 +{
  1069 + helper_mfpr(PARAM(1));
  1070 + RETURN();
  1071 +}
  1072 +
  1073 +void OPPROTO op_mtpr (void)
  1074 +{
  1075 + helper_mtpr(PARAM(1));
  1076 + RETURN();
  1077 +}
  1078 +
  1079 +void OPPROTO op_set_alt_mode (void)
  1080 +{
  1081 + env->saved_mode = env->ps & 0xC;
  1082 + env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
  1083 + RETURN();
  1084 +}
  1085 +
  1086 +void OPPROTO op_restore_mode (void)
  1087 +{
  1088 + env->ps = (env->ps & ~0xC) | env->saved_mode;
  1089 + RETURN();
  1090 +}
  1091 +
  1092 +void OPPROTO op_ld_phys_to_virt (void)
  1093 +{
  1094 + helper_ld_phys_to_virt();
  1095 + RETURN();
  1096 +}
  1097 +
  1098 +void OPPROTO op_st_phys_to_virt (void)
  1099 +{
  1100 + helper_st_phys_to_virt();
  1101 + RETURN();
  1102 +}
  1103 +#endif /* !defined (CONFIG_USER_ONLY) */
target-alpha/op_helper.c 0 → 100644
  1 +/*
  2 + * Alpha emulation cpu micro-operations 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 "exec.h"
  22 +#include "softfloat.h"
  23 +
  24 +#include "op_helper.h"
  25 +
  26 +#define MEMSUFFIX _raw
  27 +#include "op_helper_mem.h"
  28 +
  29 +#if !defined(CONFIG_USER_ONLY)
  30 +#define MEMSUFFIX _user
  31 +#include "op_helper_mem.h"
  32 +
  33 +#define MEMSUFFIX _kernel
  34 +#include "op_helper_mem.h"
  35 +
  36 +/* Those are used for supervisor and executive modes */
  37 +#define MEMSUFFIX _data
  38 +#include "op_helper_mem.h"
  39 +#endif
  40 +
  41 +void helper_tb_flush (void)
  42 +{
  43 + tlb_flush(env, 1);
  44 +}
  45 +
  46 +void cpu_dump_EA (target_ulong EA);
  47 +void helper_print_mem_EA (target_ulong EA)
  48 +{
  49 + cpu_dump_EA(EA);
  50 +}
  51 +
  52 +/*****************************************************************************/
  53 +/* Exceptions processing helpers */
  54 +void helper_excp (uint32_t excp, uint32_t error)
  55 +{
  56 + env->exception_index = excp;
  57 + env->error_code = error;
  58 + cpu_loop_exit();
  59 +}
  60 +
  61 +void helper_amask (void)
  62 +{
  63 + switch (env->implver) {
  64 + case IMPLVER_2106x:
  65 + /* EV4, EV45, LCA, LCA45 & EV5 */
  66 + break;
  67 + case IMPLVER_21164:
  68 + case IMPLVER_21264:
  69 + case IMPLVER_21364:
  70 + T0 &= ~env->amask;
  71 + break;
  72 + }
  73 +}
  74 +
  75 +void helper_load_pcc (void)
  76 +{
  77 + /* XXX: TODO */
  78 + T0 = 0;
  79 +}
  80 +
  81 +void helper_load_implver (void)
  82 +{
  83 + T0 = env->implver;
  84 +}
  85 +
  86 +void helper_load_fpcr (void)
  87 +{
  88 + T0 = 0;
  89 +#ifdef CONFIG_SOFTFLOAT
  90 + T0 |= env->fp_status.float_exception_flags << 52;
  91 + if (env->fp_status.float_exception_flags)
  92 + T0 |= 1ULL << 63;
  93 + env->ipr[IPR_EXC_SUM] &= ~0x3E:
  94 + env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1;
  95 +#endif
  96 + switch (env->fp_status.float_rounding_mode) {
  97 + case float_round_nearest_even:
  98 + T0 |= 2ULL << 58;
  99 + break;
  100 + case float_round_down:
  101 + T0 |= 1ULL << 58;
  102 + break;
  103 + case float_round_up:
  104 + T0 |= 3ULL << 58;
  105 + break;
  106 + case float_round_to_zero:
  107 + break;
  108 + }
  109 +}
  110 +
  111 +void helper_store_fpcr (void)
  112 +{
  113 +#ifdef CONFIG_SOFTFLOAT
  114 + set_float_exception_flags((T0 >> 52) & 0x3F, &FP_STATUS);
  115 +#endif
  116 + switch ((T0 >> 58) & 3) {
  117 + case 0:
  118 + set_float_rounding_mode(float_round_to_zero, &FP_STATUS);
  119 + break;
  120 + case 1:
  121 + set_float_rounding_mode(float_round_down, &FP_STATUS);
  122 + break;
  123 + case 2:
  124 + set_float_rounding_mode(float_round_nearest_even, &FP_STATUS);
  125 + break;
  126 + case 3:
  127 + set_float_rounding_mode(float_round_up, &FP_STATUS);
  128 + break;
  129 + }
  130 +}
  131 +
  132 +void helper_load_irf (void)
  133 +{
  134 + /* XXX: TODO */
  135 + T0 = 0;
  136 +}
  137 +
  138 +void helper_set_irf (void)
  139 +{
  140 + /* XXX: TODO */
  141 +}
  142 +
  143 +void helper_clear_irf (void)
  144 +{
  145 + /* XXX: TODO */
  146 +}
  147 +
  148 +void helper_addqv (void)
  149 +{
  150 + T2 = T0;
  151 + T0 += T1;
  152 + if (unlikely((T2 ^ T1 ^ (-1ULL)) & (T2 ^ T0) & (1ULL << 63))) {
  153 + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
  154 + }
  155 +}
  156 +
  157 +void helper_addlv (void)
  158 +{
  159 + T2 = T0;
  160 + T0 = (uint32_t)(T0 + T1);
  161 + if (unlikely((T2 ^ T1 ^ (-1UL)) & (T2 ^ T0) & (1UL << 31))) {
  162 + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
  163 + }
  164 +}
  165 +
  166 +void helper_subqv (void)
  167 +{
  168 + T2 = T0;
  169 + T0 -= T1;
  170 + if (unlikely(((~T2) ^ T0 ^ (-1ULL)) & ((~T2) ^ T1) & (1ULL << 63))) {
  171 + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
  172 + }
  173 +}
  174 +
  175 +void helper_sublv (void)
  176 +{
  177 + T2 = T0;
  178 + T0 = (uint32_t)(T0 - T1);
  179 + if (unlikely(((~T2) ^ T0 ^ (-1UL)) & ((~T2) ^ T1) & (1UL << 31))) {
  180 + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
  181 + }
  182 +}
  183 +
  184 +void helper_mullv (void)
  185 +{
  186 + int64_t res = (int64_t)T0 * (int64_t)T1;
  187 +
  188 + if (unlikely((int32_t)res != res)) {
  189 + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
  190 + }
  191 + T0 = (int64_t)((int32_t)res);
  192 +}
  193 +
  194 +void helper_mulqv ()
  195 +{
  196 + uint64_t res, tmp0, tmp1;
  197 +
  198 + res = (T0 >> 32) * (T1 >> 32);
  199 + tmp0 = ((T0 & 0xFFFFFFFF) * (T1 >> 32)) +
  200 + ((T0 >> 32) * (T1 & 0xFFFFFFFF));
  201 + tmp1 = (T0 & 0xFFFFFFFF) * (T1 & 0xFFFFFFFF);
  202 + tmp0 += tmp1 >> 32;
  203 + res += tmp0 >> 32;
  204 + T0 *= T1;
  205 + if (unlikely(res != 0)) {
  206 + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
  207 + }
  208 +}
  209 +
  210 +void helper_umulh (void)
  211 +{
  212 + uint64_t tmp0, tmp1;
  213 +
  214 + tmp0 = ((T0 & 0xFFFFFFFF) * (T1 >> 32)) +
  215 + ((T0 >> 32) * (T1 & 0xFFFFFFFF));
  216 + tmp1 = (T0 & 0xFFFFFFFF) * (T1 & 0xFFFFFFFF);
  217 + tmp0 += tmp1 >> 32;
  218 + T0 = (T0 >> 32) * (T0 >> 32);
  219 + T0 += tmp0 >> 32;
  220 +}
  221 +
  222 +void helper_ctpop (void)
  223 +{
  224 + int n;
  225 +
  226 + for (n = 0; T0 != 0; n++)
  227 + T0 = T0 ^ (T0 - 1);
  228 + T0 = n;
  229 +}
  230 +
  231 +void helper_ctlz (void)
  232 +{
  233 + uint32_t op32;
  234 + int n;
  235 +
  236 + n = 0;
  237 + if (!(T0 & 0xFFFFFFFF00000000ULL)) {
  238 + n += 32;
  239 + T0 <<= 32;
  240 + }
  241 + /* Make it easier for 32 bits hosts */
  242 + op32 = T0 >> 32;
  243 + if (!(op32 & 0xFFFF0000UL)) {
  244 + n += 16;
  245 + op32 <<= 16;
  246 + }
  247 + if (!(op32 & 0xFF000000UL)) {
  248 + n += 8;
  249 + op32 <<= 8;
  250 + }
  251 + if (!(op32 & 0xF0000000UL)) {
  252 + n += 4;
  253 + op32 <<= 4;
  254 + }
  255 + if (!(op32 & 0xC0000000UL)) {
  256 + n += 2;
  257 + op32 <<= 2;
  258 + }
  259 + if (!(op32 & 0x80000000UL)) {
  260 + n++;
  261 + op32 <<= 1;
  262 + }
  263 + if (!(op32 & 0x80000000UL)) {
  264 + n++;
  265 + }
  266 + T0 = n;
  267 +}
  268 +
  269 +void helper_cttz (void)
  270 +{
  271 + uint32_t op32;
  272 + int n;
  273 +
  274 + n = 0;
  275 + if (!(T0 & 0x00000000FFFFFFFFULL)) {
  276 + n += 32;
  277 + T0 >>= 32;
  278 + }
  279 + /* Make it easier for 32 bits hosts */
  280 + op32 = T0;
  281 + if (!(op32 & 0x0000FFFFUL)) {
  282 + n += 16;
  283 + op32 >>= 16;
  284 + }
  285 + if (!(op32 & 0x000000FFUL)) {
  286 + n += 8;
  287 + op32 >>= 8;
  288 + }
  289 + if (!(op32 & 0x0000000FUL)) {
  290 + n += 4;
  291 + op32 >>= 4;
  292 + }
  293 + if (!(op32 & 0x00000003UL)) {
  294 + n += 2;
  295 + op32 >>= 2;
  296 + }
  297 + if (!(op32 & 0x00000001UL)) {
  298 + n++;
  299 + op32 >>= 1;
  300 + }
  301 + if (!(op32 & 0x00000001UL)) {
  302 + n++;
  303 + }
  304 + T0 = n;
  305 +}
  306 +
  307 +static inline uint64_t byte_zap (uint64_t op, uint8_t mskb)
  308 +{
  309 + uint64_t mask;
  310 +
  311 + mask = 0;
  312 + mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
  313 + mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
  314 + mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
  315 + mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
  316 + mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
  317 + mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
  318 + mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
  319 + mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
  320 +
  321 + return op & ~mask;
  322 +}
  323 +
  324 +void helper_mskbl (void)
  325 +{
  326 + T0 = byte_zap(T0, 0x01 << (T1 & 7));
  327 +}
  328 +
  329 +void helper_extbl (void)
  330 +{
  331 + T0 >>= (T1 & 7) * 8;
  332 + T0 = byte_zap(T0, 0xFE);
  333 +}
  334 +
  335 +void helper_insbl (void)
  336 +{
  337 + T0 <<= (T1 & 7) * 8;
  338 + T0 = byte_zap(T0, ~(0x01 << (T1 & 7)));
  339 +}
  340 +
  341 +void helper_mskwl (void)
  342 +{
  343 + T0 = byte_zap(T0, 0x03 << (T1 & 7));
  344 +}
  345 +
  346 +void helper_extwl (void)
  347 +{
  348 + T0 >>= (T1 & 7) * 8;
  349 + T0 = byte_zap(T0, 0xFC);
  350 +}
  351 +
  352 +void helper_inswl (void)
  353 +{
  354 + T0 <<= (T1 & 7) * 8;
  355 + T0 = byte_zap(T0, ~(0x03 << (T1 & 7)));
  356 +}
  357 +
  358 +void helper_mskll (void)
  359 +{
  360 + T0 = byte_zap(T0, 0x0F << (T1 & 7));
  361 +}
  362 +
  363 +void helper_extll (void)
  364 +{
  365 + T0 >>= (T1 & 7) * 8;
  366 + T0 = byte_zap(T0, 0xF0);
  367 +}
  368 +
  369 +void helper_insll (void)
  370 +{
  371 + T0 <<= (T1 & 7) * 8;
  372 + T0 = byte_zap(T0, ~(0x0F << (T1 & 7)));
  373 +}
  374 +
  375 +void helper_zap (void)
  376 +{
  377 + T0 = byte_zap(T0, T1);
  378 +}
  379 +
  380 +void helper_zapnot (void)
  381 +{
  382 + T0 = byte_zap(T0, ~T1);
  383 +}
  384 +
  385 +void helper_mskql (void)
  386 +{
  387 + T0 = byte_zap(T0, 0xFF << (T1 & 7));
  388 +}
  389 +
  390 +void helper_extql (void)
  391 +{
  392 + T0 >>= (T1 & 7) * 8;
  393 + T0 = byte_zap(T0, 0x00);
  394 +}
  395 +
  396 +void helper_insql (void)
  397 +{
  398 + T0 <<= (T1 & 7) * 8;
  399 + T0 = byte_zap(T0, ~(0xFF << (T1 & 7)));
  400 +}
  401 +
  402 +void helper_mskwh (void)
  403 +{
  404 + T0 = byte_zap(T0, (0x03 << (T1 & 7)) >> 8);
  405 +}
  406 +
  407 +void helper_inswh (void)
  408 +{
  409 + T0 >>= 64 - ((T1 & 7) * 8);
  410 + T0 = byte_zap(T0, ~((0x03 << (T1 & 7)) >> 8));
  411 +}
  412 +
  413 +void helper_extwh (void)
  414 +{
  415 + T0 <<= 64 - ((T1 & 7) * 8);
  416 + T0 = byte_zap(T0, ~0x07);
  417 +}
  418 +
  419 +void helper_msklh (void)
  420 +{
  421 + T0 = byte_zap(T0, (0x0F << (T1 & 7)) >> 8);
  422 +}
  423 +
  424 +void helper_inslh (void)
  425 +{
  426 + T0 >>= 64 - ((T1 & 7) * 8);
  427 + T0 = byte_zap(T0, ~((0x0F << (T1 & 7)) >> 8));
  428 +}
  429 +
  430 +void helper_extlh (void)
  431 +{
  432 + T0 <<= 64 - ((T1 & 7) * 8);
  433 + T0 = byte_zap(T0, ~0x0F);
  434 +}
  435 +
  436 +void helper_mskqh (void)
  437 +{
  438 + T0 = byte_zap(T0, (0xFF << (T1 & 7)) >> 8);
  439 +}
  440 +
  441 +void helper_insqh (void)
  442 +{
  443 + T0 >>= 64 - ((T1 & 7) * 8);
  444 + T0 = byte_zap(T0, ~((0xFF << (T1 & 7)) >> 8));
  445 +}
  446 +
  447 +void helper_extqh (void)
  448 +{
  449 + T0 <<= 64 - ((T1 & 7) * 8);
  450 + T0 = byte_zap(T0, 0x00);
  451 +}
  452 +
  453 +void helper_cmpbge (void)
  454 +{
  455 + uint8_t opa, opb, res;
  456 + int i;
  457 +
  458 + res = 0;
  459 + for (i = 0; i < 7; i++) {
  460 + opa = T0 >> (i * 8);
  461 + opb = T1 >> (i * 8);
  462 + if (opa >= opb)
  463 + res |= 1 << i;
  464 + }
  465 + T0 = res;
  466 +}
  467 +
  468 +void helper_cmov_fir (int freg)
  469 +{
  470 + if (FT0 != 0)
  471 + env->fir[freg] = FT1;
  472 +}
  473 +
  474 +void helper_sqrts (void)
  475 +{
  476 + FT0 = float32_sqrt(FT0, &FP_STATUS);
  477 +}
  478 +
  479 +void helper_cpys (void)
  480 +{
  481 + union {
  482 + double d;
  483 + uint64_t i;
  484 + } p, q, r;
  485 +
  486 + p.d = FT0;
  487 + q.d = FT1;
  488 + r.i = p.i & 0x8000000000000000ULL;
  489 + r.i |= q.i & ~0x8000000000000000ULL;
  490 + FT0 = r.d;
  491 +}
  492 +
  493 +void helper_cpysn (void)
  494 +{
  495 + union {
  496 + double d;
  497 + uint64_t i;
  498 + } p, q, r;
  499 +
  500 + p.d = FT0;
  501 + q.d = FT1;
  502 + r.i = (~p.i) & 0x8000000000000000ULL;
  503 + r.i |= q.i & ~0x8000000000000000ULL;
  504 + FT0 = r.d;
  505 +}
  506 +
  507 +void helper_cpyse (void)
  508 +{
  509 + union {
  510 + double d;
  511 + uint64_t i;
  512 + } p, q, r;
  513 +
  514 + p.d = FT0;
  515 + q.d = FT1;
  516 + r.i = p.i & 0xFFF0000000000000ULL;
  517 + r.i |= q.i & ~0xFFF0000000000000ULL;
  518 + FT0 = r.d;
  519 +}
  520 +
  521 +void helper_itofs (void)
  522 +{
  523 + union {
  524 + double d;
  525 + uint64_t i;
  526 + } p;
  527 +
  528 + p.d = FT0;
  529 + FT0 = int64_to_float32(p.i, &FP_STATUS);
  530 +}
  531 +
  532 +void helper_ftois (void)
  533 +{
  534 + union {
  535 + double d;
  536 + uint64_t i;
  537 + } p;
  538 +
  539 + p.i = float32_to_int64(FT0, &FP_STATUS);
  540 + FT0 = p.d;
  541 +}
  542 +
  543 +void helper_sqrtt (void)
  544 +{
  545 + FT0 = float64_sqrt(FT0, &FP_STATUS);
  546 +}
  547 +
  548 +void helper_cmptun (void)
  549 +{
  550 + union {
  551 + double d;
  552 + uint64_t i;
  553 + } p;
  554 +
  555 + p.i = 0;
  556 + if (float64_is_nan(FT0) || float64_is_nan(FT1))
  557 + p.i = 0x4000000000000000ULL;
  558 + FT0 = p.d;
  559 +}
  560 +
  561 +void helper_cmpteq (void)
  562 +{
  563 + union {
  564 + double d;
  565 + uint64_t i;
  566 + } p;
  567 +
  568 + p.i = 0;
  569 + if (float64_eq(FT0, FT1, &FP_STATUS))
  570 + p.i = 0x4000000000000000ULL;
  571 + FT0 = p.d;
  572 +}
  573 +
  574 +void helper_cmptle (void)
  575 +{
  576 + union {
  577 + double d;
  578 + uint64_t i;
  579 + } p;
  580 +
  581 + p.i = 0;
  582 + if (float64_le(FT0, FT1, &FP_STATUS))
  583 + p.i = 0x4000000000000000ULL;
  584 + FT0 = p.d;
  585 +}
  586 +
  587 +void helper_cmptlt (void)
  588 +{
  589 + union {
  590 + double d;
  591 + uint64_t i;
  592 + } p;
  593 +
  594 + p.i = 0;
  595 + if (float64_lt(FT0, FT1, &FP_STATUS))
  596 + p.i = 0x4000000000000000ULL;
  597 + FT0 = p.d;
  598 +}
  599 +
  600 +void helper_itoft (void)
  601 +{
  602 + union {
  603 + double d;
  604 + uint64_t i;
  605 + } p;
  606 +
  607 + p.d = FT0;
  608 + FT0 = int64_to_float64(p.i, &FP_STATUS);
  609 +}
  610 +
  611 +void helper_ftoit (void)
  612 +{
  613 + union {
  614 + double d;
  615 + uint64_t i;
  616 + } p;
  617 +
  618 + p.i = float64_to_int64(FT0, &FP_STATUS);
  619 + FT0 = p.d;
  620 +}
  621 +
  622 +static int vaxf_is_valid (float ff)
  623 +{
  624 + union {
  625 + float f;
  626 + uint32_t i;
  627 + } p;
  628 + uint32_t exp, mant;
  629 +
  630 + p.f = ff;
  631 + exp = (p.i >> 23) & 0xFF;
  632 + mant = p.i & 0x007FFFFF;
  633 + if (exp == 0 && ((p.i & 0x80000000) || mant != 0)) {
  634 + /* Reserved operands / Dirty zero */
  635 + return 0;
  636 + }
  637 +
  638 + return 1;
  639 +}
  640 +
  641 +static float vaxf_to_ieee32 (float ff)
  642 +{
  643 + union {
  644 + float f;
  645 + uint32_t i;
  646 + } p;
  647 + uint32_t exp;
  648 +
  649 + p.f = ff;
  650 + exp = (p.i >> 23) & 0xFF;
  651 + if (exp < 3) {
  652 + /* Underflow */
  653 + p.f = 0.0;
  654 + } else {
  655 + p.f *= 0.25;
  656 + }
  657 +
  658 + return p.f;
  659 +}
  660 +
  661 +static float ieee32_to_vaxf (float fi)
  662 +{
  663 + union {
  664 + float f;
  665 + uint32_t i;
  666 + } p;
  667 + uint32_t exp, mant;
  668 +
  669 + p.f = fi;
  670 + exp = (p.i >> 23) & 0xFF;
  671 + mant = p.i & 0x007FFFFF;
  672 + if (exp == 255) {
  673 + /* NaN or infinity */
  674 + p.i = 1;
  675 + } else if (exp == 0) {
  676 + if (mant == 0) {
  677 + /* Zero */
  678 + p.i = 0;
  679 + } else {
  680 + /* Denormalized */
  681 + p.f *= 2.0;
  682 + }
  683 + } else {
  684 + if (exp >= 253) {
  685 + /* Overflow */
  686 + p.i = 1;
  687 + } else {
  688 + p.f *= 4.0;
  689 + }
  690 + }
  691 +
  692 + return p.f;
  693 +}
  694 +
  695 +void helper_addf (void)
  696 +{
  697 + float ft0, ft1, ft2;
  698 +
  699 + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
  700 + /* XXX: TODO */
  701 + }
  702 + ft0 = vaxf_to_ieee32(FT0);
  703 + ft1 = vaxf_to_ieee32(FT1);
  704 + ft2 = float32_add(ft0, ft1, &FP_STATUS);
  705 + FT0 = ieee32_to_vaxf(ft2);
  706 +}
  707 +
  708 +void helper_subf (void)
  709 +{
  710 + float ft0, ft1, ft2;
  711 +
  712 + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
  713 + /* XXX: TODO */
  714 + }
  715 + ft0 = vaxf_to_ieee32(FT0);
  716 + ft1 = vaxf_to_ieee32(FT1);
  717 + ft2 = float32_sub(ft0, ft1, &FP_STATUS);
  718 + FT0 = ieee32_to_vaxf(ft2);
  719 +}
  720 +
  721 +void helper_mulf (void)
  722 +{
  723 + float ft0, ft1, ft2;
  724 +
  725 + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
  726 + /* XXX: TODO */
  727 + }
  728 + ft0 = vaxf_to_ieee32(FT0);
  729 + ft1 = vaxf_to_ieee32(FT1);
  730 + ft2 = float32_mul(ft0, ft1, &FP_STATUS);
  731 + FT0 = ieee32_to_vaxf(ft2);
  732 +}
  733 +
  734 +void helper_divf (void)
  735 +{
  736 + float ft0, ft1, ft2;
  737 +
  738 + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
  739 + /* XXX: TODO */
  740 + }
  741 + ft0 = vaxf_to_ieee32(FT0);
  742 + ft1 = vaxf_to_ieee32(FT1);
  743 + ft2 = float32_div(ft0, ft1, &FP_STATUS);
  744 + FT0 = ieee32_to_vaxf(ft2);
  745 +}
  746 +
  747 +void helper_sqrtf (void)
  748 +{
  749 + float ft0, ft1;
  750 +
  751 + if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
  752 + /* XXX: TODO */
  753 + }
  754 + ft0 = vaxf_to_ieee32(FT0);
  755 + ft1 = float32_sqrt(ft0, &FP_STATUS);
  756 + FT0 = ieee32_to_vaxf(ft1);
  757 +}
  758 +
  759 +void helper_itoff (void)
  760 +{
  761 + /* XXX: TODO */
  762 +}
  763 +
  764 +static int vaxg_is_valid (double ff)
  765 +{
  766 + union {
  767 + double f;
  768 + uint64_t i;
  769 + } p;
  770 + uint64_t exp, mant;
  771 +
  772 + p.f = ff;
  773 + exp = (p.i >> 52) & 0x7FF;
  774 + mant = p.i & 0x000FFFFFFFFFFFFFULL;
  775 + if (exp == 0 && ((p.i & 0x8000000000000000ULL) || mant != 0)) {
  776 + /* Reserved operands / Dirty zero */
  777 + return 0;
  778 + }
  779 +
  780 + return 1;
  781 +}
  782 +
  783 +static double vaxg_to_ieee64 (double fg)
  784 +{
  785 + union {
  786 + double f;
  787 + uint64_t i;
  788 + } p;
  789 + uint32_t exp;
  790 +
  791 + p.f = fg;
  792 + exp = (p.i >> 52) & 0x7FF;
  793 + if (exp < 3) {
  794 + /* Underflow */
  795 + p.f = 0.0;
  796 + } else {
  797 + p.f *= 0.25;
  798 + }
  799 +
  800 + return p.f;
  801 +}
  802 +
  803 +static double ieee64_to_vaxg (double fi)
  804 +{
  805 + union {
  806 + double f;
  807 + uint64_t i;
  808 + } p;
  809 + uint64_t mant;
  810 + uint32_t exp;
  811 +
  812 + p.f = fi;
  813 + exp = (p.i >> 52) & 0x7FF;
  814 + mant = p.i & 0x000FFFFFFFFFFFFFULL;
  815 + if (exp == 255) {
  816 + /* NaN or infinity */
  817 + p.i = 1; /* VAX dirty zero */
  818 + } else if (exp == 0) {
  819 + if (mant == 0) {
  820 + /* Zero */
  821 + p.i = 0;
  822 + } else {
  823 + /* Denormalized */
  824 + p.f *= 2.0;
  825 + }
  826 + } else {
  827 + if (exp >= 2045) {
  828 + /* Overflow */
  829 + p.i = 1; /* VAX dirty zero */
  830 + } else {
  831 + p.f *= 4.0;
  832 + }
  833 + }
  834 +
  835 + return p.f;
  836 +}
  837 +
  838 +void helper_addg (void)
  839 +{
  840 + double ft0, ft1, ft2;
  841 +
  842 + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
  843 + /* XXX: TODO */
  844 + }
  845 + ft0 = vaxg_to_ieee64(FT0);
  846 + ft1 = vaxg_to_ieee64(FT1);
  847 + ft2 = float64_add(ft0, ft1, &FP_STATUS);
  848 + FT0 = ieee64_to_vaxg(ft2);
  849 +}
  850 +
  851 +void helper_subg (void)
  852 +{
  853 + double ft0, ft1, ft2;
  854 +
  855 + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
  856 + /* XXX: TODO */
  857 + }
  858 + ft0 = vaxg_to_ieee64(FT0);
  859 + ft1 = vaxg_to_ieee64(FT1);
  860 + ft2 = float64_sub(ft0, ft1, &FP_STATUS);
  861 + FT0 = ieee64_to_vaxg(ft2);
  862 +}
  863 +
  864 +void helper_mulg (void)
  865 +{
  866 + double ft0, ft1, ft2;
  867 +
  868 + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
  869 + /* XXX: TODO */
  870 + }
  871 + ft0 = vaxg_to_ieee64(FT0);
  872 + ft1 = vaxg_to_ieee64(FT1);
  873 + ft2 = float64_mul(ft0, ft1, &FP_STATUS);
  874 + FT0 = ieee64_to_vaxg(ft2);
  875 +}
  876 +
  877 +void helper_divg (void)
  878 +{
  879 + double ft0, ft1, ft2;
  880 +
  881 + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
  882 + /* XXX: TODO */
  883 + }
  884 + ft0 = vaxg_to_ieee64(FT0);
  885 + ft1 = vaxg_to_ieee64(FT1);
  886 + ft2 = float64_div(ft0, ft1, &FP_STATUS);
  887 + FT0 = ieee64_to_vaxg(ft2);
  888 +}
  889 +
  890 +void helper_sqrtg (void)
  891 +{
  892 + double ft0, ft1;
  893 +
  894 + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
  895 + /* XXX: TODO */
  896 + }
  897 + ft0 = vaxg_to_ieee64(FT0);
  898 + ft1 = float64_sqrt(ft0, &FP_STATUS);
  899 + FT0 = ieee64_to_vaxg(ft1);
  900 +}
  901 +
  902 +void helper_cmpgeq (void)
  903 +{
  904 + union {
  905 + double d;
  906 + uint64_t u;
  907 + } p;
  908 + double ft0, ft1;
  909 +
  910 + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
  911 + /* XXX: TODO */
  912 + }
  913 + ft0 = vaxg_to_ieee64(FT0);
  914 + ft1 = vaxg_to_ieee64(FT1);
  915 + p.u = 0;
  916 + if (float64_eq(ft0, ft1, &FP_STATUS))
  917 + p.u = 0x4000000000000000ULL;
  918 + FT0 = p.d;
  919 +}
  920 +
  921 +void helper_cmpglt (void)
  922 +{
  923 + union {
  924 + double d;
  925 + uint64_t u;
  926 + } p;
  927 + double ft0, ft1;
  928 +
  929 + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
  930 + /* XXX: TODO */
  931 + }
  932 + ft0 = vaxg_to_ieee64(FT0);
  933 + ft1 = vaxg_to_ieee64(FT1);
  934 + p.u = 0;
  935 + if (float64_lt(ft0, ft1, &FP_STATUS))
  936 + p.u = 0x4000000000000000ULL;
  937 + FT0 = p.d;
  938 +}
  939 +
  940 +void helper_cmpgle (void)
  941 +{
  942 + union {
  943 + double d;
  944 + uint64_t u;
  945 + } p;
  946 + double ft0, ft1;
  947 +
  948 + if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
  949 + /* XXX: TODO */
  950 + }
  951 + ft0 = vaxg_to_ieee64(FT0);
  952 + ft1 = vaxg_to_ieee64(FT1);
  953 + p.u = 0;
  954 + if (float64_le(ft0, ft1, &FP_STATUS))
  955 + p.u = 0x4000000000000000ULL;
  956 + FT0 = p.d;
  957 +}
  958 +
  959 +void helper_cvtqs (void)
  960 +{
  961 + union {
  962 + double d;
  963 + uint64_t u;
  964 + } p;
  965 +
  966 + p.d = FT0;
  967 + FT0 = (float)p.u;
  968 +}
  969 +
  970 +void helper_cvttq (void)
  971 +{
  972 + union {
  973 + double d;
  974 + uint64_t u;
  975 + } p;
  976 +
  977 + p.u = FT0;
  978 + FT0 = p.d;
  979 +}
  980 +
  981 +void helper_cvtqt (void)
  982 +{
  983 + union {
  984 + double d;
  985 + uint64_t u;
  986 + } p;
  987 +
  988 + p.d = FT0;
  989 + FT0 = p.u;
  990 +}
  991 +
  992 +void helper_cvtqf (void)
  993 +{
  994 + union {
  995 + double d;
  996 + uint64_t u;
  997 + } p;
  998 +
  999 + p.d = FT0;
  1000 + FT0 = ieee32_to_vaxf(p.u);
  1001 +}
  1002 +
  1003 +void helper_cvtgf (void)
  1004 +{
  1005 + double ft0;
  1006 +
  1007 + ft0 = vaxg_to_ieee64(FT0);
  1008 + FT0 = ieee32_to_vaxf(ft0);
  1009 +}
  1010 +
  1011 +void helper_cvtgd (void)
  1012 +{
  1013 + /* XXX: TODO */
  1014 +}
  1015 +
  1016 +void helper_cvtgq (void)
  1017 +{
  1018 + union {
  1019 + double d;
  1020 + uint64_t u;
  1021 + } p;
  1022 +
  1023 + p.u = vaxg_to_ieee64(FT0);
  1024 + FT0 = p.d;
  1025 +}
  1026 +
  1027 +void helper_cvtqg (void)
  1028 +{
  1029 + union {
  1030 + double d;
  1031 + uint64_t u;
  1032 + } p;
  1033 +
  1034 + p.d = FT0;
  1035 + FT0 = ieee64_to_vaxg(p.u);
  1036 +}
  1037 +
  1038 +void helper_cvtdg (void)
  1039 +{
  1040 + /* XXX: TODO */
  1041 +}
  1042 +
  1043 +void helper_cvtlq (void)
  1044 +{
  1045 + union {
  1046 + double d;
  1047 + uint64_t u;
  1048 + } p, q;
  1049 +
  1050 + p.d = FT0;
  1051 + q.u = (p.u >> 29) & 0x3FFFFFFF;
  1052 + q.u |= (p.u >> 32);
  1053 + q.u = (int64_t)((int32_t)q.u);
  1054 + FT0 = q.d;
  1055 +}
  1056 +
  1057 +static inline void __helper_cvtql (int s, int v)
  1058 +{
  1059 + union {
  1060 + double d;
  1061 + uint64_t u;
  1062 + } p, q;
  1063 +
  1064 + p.d = FT0;
  1065 + q.u = ((uint64_t)(p.u & 0xC0000000)) << 32;
  1066 + q.u |= ((uint64_t)(p.u & 0x7FFFFFFF)) << 29;
  1067 + FT0 = q.d;
  1068 + if (v && (int64_t)((int32_t)p.u) != (int64_t)p.u) {
  1069 + helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
  1070 + }
  1071 + if (s) {
  1072 + /* TODO */
  1073 + }
  1074 +}
  1075 +
  1076 +void helper_cvtql (void)
  1077 +{
  1078 + __helper_cvtql(0, 0);
  1079 +}
  1080 +
  1081 +void helper_cvtqlv (void)
  1082 +{
  1083 + __helper_cvtql(0, 1);
  1084 +}
  1085 +
  1086 +void helper_cvtqlsv (void)
  1087 +{
  1088 + __helper_cvtql(1, 1);
  1089 +}
  1090 +
  1091 +void helper_cmpfeq (void)
  1092 +{
  1093 + if (float64_eq(FT0, FT1, &FP_STATUS))
  1094 + T0 = 1;
  1095 + else
  1096 + T0 = 0;
  1097 +}
  1098 +
  1099 +void helper_cmpfne (void)
  1100 +{
  1101 + if (float64_eq(FT0, FT1, &FP_STATUS))
  1102 + T0 = 0;
  1103 + else
  1104 + T0 = 1;
  1105 +}
  1106 +
  1107 +void helper_cmpflt (void)
  1108 +{
  1109 + if (float64_lt(FT0, FT1, &FP_STATUS))
  1110 + T0 = 1;
  1111 + else
  1112 + T0 = 0;
  1113 +}
  1114 +
  1115 +void helper_cmpfle (void)
  1116 +{
  1117 + if (float64_lt(FT0, FT1, &FP_STATUS))
  1118 + T0 = 1;
  1119 + else
  1120 + T0 = 0;
  1121 +}
  1122 +
  1123 +void helper_cmpfgt (void)
  1124 +{
  1125 + if (float64_le(FT0, FT1, &FP_STATUS))
  1126 + T0 = 0;
  1127 + else
  1128 + T0 = 1;
  1129 +}
  1130 +
  1131 +void helper_cmpfge (void)
  1132 +{
  1133 + if (float64_lt(FT0, FT1, &FP_STATUS))
  1134 + T0 = 0;
  1135 + else
  1136 + T0 = 1;
  1137 +}
  1138 +
  1139 +#if !defined (CONFIG_USER_ONLY)
  1140 +void helper_mfpr (int iprn)
  1141 +{
  1142 + uint64_t val;
  1143 +
  1144 + if (cpu_alpha_mfpr(env, iprn, &val) == 0)
  1145 + T0 = val;
  1146 +}
  1147 +
  1148 +void helper_mtpr (int iprn)
  1149 +{
  1150 + cpu_alpha_mtpr(env, iprn, T0, NULL);
  1151 +}
  1152 +#endif
  1153 +
  1154 +/*****************************************************************************/
  1155 +/* Softmmu support */
  1156 +#if !defined (CONFIG_USER_ONLY)
  1157 +
  1158 +#define GETPC() (__builtin_return_address(0))
  1159 +
  1160 +/* XXX: the two following helpers are pure hacks.
  1161 + * Hopefully, we emulate the PALcode, then we should never see
  1162 + * HW_LD / HW_ST instructions.
  1163 + */
  1164 +void helper_ld_phys_to_virt (void)
  1165 +{
  1166 + uint64_t tlb_addr, physaddr;
  1167 + int index, is_user;
  1168 + void *retaddr;
  1169 +
  1170 + is_user = (env->ps >> 3) & 3;
  1171 + index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  1172 + redo:
  1173 + tlb_addr = env->tlb_table[is_user][index].addr_read;
  1174 + if ((T0 & TARGET_PAGE_MASK) ==
  1175 + (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
  1176 + physaddr = T0 + env->tlb_table[is_user][index].addend;
  1177 + } else {
  1178 + /* the page is not in the TLB : fill it */
  1179 + retaddr = GETPC();
  1180 + tlb_fill(T0, 0, is_user, retaddr);
  1181 + goto redo;
  1182 + }
  1183 + T0 = physaddr;
  1184 +}
  1185 +
  1186 +void helper_st_phys_to_virt (void)
  1187 +{
  1188 + uint64_t tlb_addr, physaddr;
  1189 + int index, is_user;
  1190 + void *retaddr;
  1191 +
  1192 + is_user = (env->ps >> 3) & 3;
  1193 + index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  1194 + redo:
  1195 + tlb_addr = env->tlb_table[is_user][index].addr_write;
  1196 + if ((T0 & TARGET_PAGE_MASK) ==
  1197 + (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
  1198 + physaddr = T0 + env->tlb_table[is_user][index].addend;
  1199 + } else {
  1200 + /* the page is not in the TLB : fill it */
  1201 + retaddr = GETPC();
  1202 + tlb_fill(T0, 1, is_user, retaddr);
  1203 + goto redo;
  1204 + }
  1205 + T0 = physaddr;
  1206 +}
  1207 +
  1208 +#define MMUSUFFIX _mmu
  1209 +
  1210 +#define SHIFT 0
  1211 +#include "softmmu_template.h"
  1212 +
  1213 +#define SHIFT 1
  1214 +#include "softmmu_template.h"
  1215 +
  1216 +#define SHIFT 2
  1217 +#include "softmmu_template.h"
  1218 +
  1219 +#define SHIFT 3
  1220 +#include "softmmu_template.h"
  1221 +
  1222 +/* try to fill the TLB and return an exception if error. If retaddr is
  1223 + NULL, it means that the function was called in C code (i.e. not
  1224 + from generated code or from helper.c) */
  1225 +/* XXX: fix it to restore all registers */
  1226 +void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
  1227 +{
  1228 + TranslationBlock *tb;
  1229 + CPUState *saved_env;
  1230 + target_phys_addr_t pc;
  1231 + int ret;
  1232 +
  1233 + /* XXX: hack to restore env in all cases, even if not called from
  1234 + generated code */
  1235 + saved_env = env;
  1236 + env = cpu_single_env;
  1237 + ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, is_user, 1);
  1238 + if (!likely(ret == 0)) {
  1239 + if (likely(retaddr)) {
  1240 + /* now we have a real cpu fault */
  1241 + pc = (target_phys_addr_t)retaddr;
  1242 + tb = tb_find_pc(pc);
  1243 + if (likely(tb)) {
  1244 + /* the PC is inside the translated code. It means that we have
  1245 + a virtual CPU fault */
  1246 + cpu_restore_state(tb, env, pc, NULL);
  1247 + }
  1248 + }
  1249 + /* Exception index and error code are already set */
  1250 + cpu_loop_exit();
  1251 + }
  1252 + env = saved_env;
  1253 +}
  1254 +
  1255 +#endif
target-alpha/op_helper.h 0 → 100644
  1 +/*
  2 + * Alpha emulation cpu micro-operations helpers definitions 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 +void helper_call_pal (uint32_t palcode);
  22 +void helper_excp (uint32_t excp, uint32_t error);
  23 +void helper_amask (void);
  24 +void helper_load_pcc (void);
  25 +void helper_load_implver (void);
  26 +void helper_load_fpcr (void);
  27 +void helper_store_fpcr (void);
  28 +void helper_load_irf (void);
  29 +void helper_set_irf (void);
  30 +void helper_clear_irf (void);
  31 +void helper_addqv (void);
  32 +void helper_addlv (void);
  33 +void helper_subqv (void);
  34 +void helper_sublv (void);
  35 +void helper_mullv (void);
  36 +void helper_mulqv (void);
  37 +void helper_umulh (void);
  38 +void helper_ctpop (void);
  39 +void helper_ctlz (void);
  40 +void helper_cttz (void);
  41 +void helper_mskbl (void);
  42 +void helper_extbl (void);
  43 +void helper_insbl (void);
  44 +void helper_mskwl (void);
  45 +void helper_extwl (void);
  46 +void helper_inswl (void);
  47 +void helper_mskll (void);
  48 +void helper_extll (void);
  49 +void helper_insll (void);
  50 +void helper_zap (void);
  51 +void helper_zapnot (void);
  52 +void helper_mskql (void);
  53 +void helper_extql (void);
  54 +void helper_insql (void);
  55 +void helper_mskwh (void);
  56 +void helper_inswh (void);
  57 +void helper_extwh (void);
  58 +void helper_msklh (void);
  59 +void helper_inslh (void);
  60 +void helper_extlh (void);
  61 +void helper_mskqh (void);
  62 +void helper_insqh (void);
  63 +void helper_extqh (void);
  64 +void helper_cmpbge (void);
  65 +void helper_cmov_fir (int freg);
  66 +
  67 +double helper_ldff_raw (target_ulong ea);
  68 +void helper_stff_raw (target_ulong ea, double op);
  69 +double helper_ldfg_raw (target_ulong ea);
  70 +void helper_stfg_raw (target_ulong ea, double op);
  71 +#if !defined(CONFIG_USER_ONLY)
  72 +double helper_ldff_user (target_ulong ea);
  73 +void helper_stff_user (target_ulong ea, double op);
  74 +double helper_ldff_kernel (target_ulong ea);
  75 +void helper_stff_kernel (target_ulong ea, double op);
  76 +double helper_ldff_data (target_ulong ea);
  77 +void helper_stff_data (target_ulong ea, double op);
  78 +double helper_ldfg_user (target_ulong ea);
  79 +void helper_stfg_user (target_ulong ea, double op);
  80 +double helper_ldfg_kernel (target_ulong ea);
  81 +void helper_stfg_kernel (target_ulong ea, double op);
  82 +double helper_ldfg_data (target_ulong ea);
  83 +void helper_stfg_data (target_ulong ea, double op);
  84 +#endif
  85 +
  86 +void helper_sqrts (void);
  87 +void helper_cpys (void);
  88 +void helper_cpysn (void);
  89 +void helper_cpyse (void);
  90 +void helper_itofs (void);
  91 +void helper_ftois (void);
  92 +
  93 +void helper_sqrtt (void);
  94 +void helper_cmptun (void);
  95 +void helper_cmpteq (void);
  96 +void helper_cmptle (void);
  97 +void helper_cmptlt (void);
  98 +void helper_itoft (void);
  99 +void helper_ftoit (void);
  100 +
  101 +void helper_addf (void);
  102 +void helper_subf (void);
  103 +void helper_mulf (void);
  104 +void helper_divf (void);
  105 +void helper_sqrtf (void);
  106 +void helper_cmpfeq (void);
  107 +void helper_cmpfne (void);
  108 +void helper_cmpflt (void);
  109 +void helper_cmpfle (void);
  110 +void helper_cmpfgt (void);
  111 +void helper_cmpfge (void);
  112 +void helper_itoff (void);
  113 +
  114 +void helper_addg (void);
  115 +void helper_subg (void);
  116 +void helper_mulg (void);
  117 +void helper_divg (void);
  118 +void helper_sqrtg (void);
  119 +void helper_cmpgeq (void);
  120 +void helper_cmpglt (void);
  121 +void helper_cmpgle (void);
  122 +
  123 +void helper_cvtqs (void);
  124 +void helper_cvttq (void);
  125 +void helper_cvtqt (void);
  126 +void helper_cvtqf (void);
  127 +void helper_cvtgf (void);
  128 +void helper_cvtgd (void);
  129 +void helper_cvtgq (void);
  130 +void helper_cvtqg (void);
  131 +void helper_cvtdg (void);
  132 +void helper_cvtlq (void);
  133 +void helper_cvtql (void);
  134 +void helper_cvtqlv (void);
  135 +void helper_cvtqlsv (void);
  136 +
  137 +void helper_mfpr (int iprn);
  138 +void helper_mtpr (int iprn);
  139 +void helper_ld_phys_to_virt (void);
  140 +void helper_st_phys_to_virt (void);
  141 +void helper_tb_flush (void);
target-alpha/op_helper_mem.h 0 → 100644
  1 +/*
  2 + * Alpha emulation cpu micro-operations helpers for memory accesses 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 +/* XXX: TODO */
  22 +double glue(helper_ldff, MEMSUFFIX) (target_ulong ea)
  23 +{
  24 + return 0;
  25 +}
  26 +
  27 +void glue(helper_stff, MEMSUFFIX) (target_ulong ea, double op)
  28 +{
  29 +}
  30 +
  31 +double glue(helper_ldfg, MEMSUFFIX) (target_ulong ea)
  32 +{
  33 + return 0;
  34 +}
  35 +
  36 +void glue(helper_stfg, MEMSUFFIX) (target_ulong ea, double op)
  37 +{
  38 +}
  39 +
  40 +#undef MEMSUFFIX
target-alpha/op_mem.h 0 → 100644
  1 +/*
  2 + * Alpha emulation cpu micro-operations for memory accesses 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 +#define DEBUG_MEM_ACCESSES
  22 +#if defined (DEBUG_MEM_ACCESSES)
  23 +void helper_print_mem_EA (target_ulong EA);
  24 +#define print_mem_EA(EA) do { helper_print_mem_EA(EA); } while (0)
  25 +#else
  26 +#define print_mem_EA(EA) do { } while (0)
  27 +#endif
  28 +
  29 +static inline uint32_t glue(ldl_l, MEMSUFFIX) (target_ulong EA)
  30 +{
  31 + env->lock = EA;
  32 +
  33 + return glue(ldl, MEMSUFFIX)(EA);
  34 +}
  35 +
  36 +static inline uint32_t glue(ldq_l, MEMSUFFIX) (target_ulong EA)
  37 +{
  38 + env->lock = EA;
  39 +
  40 + return glue(ldq, MEMSUFFIX)(EA);
  41 +}
  42 +
  43 +static inline void glue(stl_c, MEMSUFFIX) (target_ulong EA, uint32_t data)
  44 +{
  45 + if (EA == env->lock) {
  46 + glue(stl, MEMSUFFIX)(EA, data);
  47 + T0 = 0;
  48 + } else {
  49 + T0 = 1;
  50 + }
  51 + env->lock = -1;
  52 +}
  53 +
  54 +static inline void glue(stq_c, MEMSUFFIX) (target_ulong EA, uint64_t data)
  55 +{
  56 + if (EA == env->lock) {
  57 + glue(stq, MEMSUFFIX)(EA, data);
  58 + T0 = 0;
  59 + } else {
  60 + T0 = 1;
  61 + }
  62 + env->lock = -1;
  63 +}
  64 +
  65 +#define ALPHA_LD_OP(name, op) \
  66 +void OPPROTO glue(glue(op_ld, name), MEMSUFFIX) (void) \
  67 +{ \
  68 + print_mem_EA(T0); \
  69 + T1 = glue(op, MEMSUFFIX)(T0); \
  70 + RETURN(); \
  71 +}
  72 +
  73 +#define ALPHA_ST_OP(name, op) \
  74 +void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void) \
  75 +{ \
  76 + print_mem_EA(T0); \
  77 + glue(op, MEMSUFFIX)(T0, T1); \
  78 + RETURN(); \
  79 +}
  80 +
  81 +ALPHA_LD_OP(bu, ldub);
  82 +ALPHA_ST_OP(b, stb);
  83 +ALPHA_LD_OP(wu, lduw);
  84 +ALPHA_ST_OP(w, stw);
  85 +ALPHA_LD_OP(l, ldl);
  86 +ALPHA_ST_OP(l, stl);
  87 +ALPHA_LD_OP(q, ldq);
  88 +ALPHA_ST_OP(q, stq);
  89 +
  90 +ALPHA_LD_OP(q_u, ldq);
  91 +ALPHA_ST_OP(q_u, stq);
  92 +
  93 +ALPHA_LD_OP(l_l, ldl_l);
  94 +ALPHA_LD_OP(q_l, ldq_l);
  95 +ALPHA_ST_OP(l_c, stl_c);
  96 +ALPHA_ST_OP(q_c, stq_c);
  97 +
  98 +#define ALPHA_LDF_OP(name, op) \
  99 +void OPPROTO glue(glue(op_ld, name), MEMSUFFIX) (void) \
  100 +{ \
  101 + print_mem_EA(T0); \
  102 + FT1 = glue(op, MEMSUFFIX)(T0); \
  103 + RETURN(); \
  104 +}
  105 +
  106 +#define ALPHA_STF_OP(name, op) \
  107 +void OPPROTO glue(glue(op_st, name), MEMSUFFIX) (void) \
  108 +{ \
  109 + print_mem_EA(T0); \
  110 + glue(op, MEMSUFFIX)(T0, FT1); \
  111 + RETURN(); \
  112 +}
  113 +
  114 +ALPHA_LDF_OP(t, ldfq);
  115 +ALPHA_STF_OP(t, stfq);
  116 +ALPHA_LDF_OP(s, ldfl);
  117 +ALPHA_STF_OP(s, stfl);
  118 +
  119 +/* VAX floating point */
  120 +ALPHA_LDF_OP(f, helper_ldff);
  121 +ALPHA_STF_OP(f, helper_stff);
  122 +ALPHA_LDF_OP(g, helper_ldfg);
  123 +ALPHA_STF_OP(g, helper_stfg);
  124 +
  125 +#undef MEMSUFFIX
target-alpha/op_template.h 0 → 100644
  1 +/*
  2 + * Alpha emulation cpu micro-operations templates 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 +/* Optimized constant loads */
  22 +#if REG < 3
  23 +void OPPROTO glue(op_reset_T, REG) (void)
  24 +{
  25 + glue(T, REG) = 0;
  26 + RETURN();
  27 +}
  28 +
  29 +void OPPROTO glue(op_reset_FT, REG) (void)
  30 +{
  31 + glue(FT, REG) = 0;
  32 + RETURN();
  33 +}
  34 +
  35 +/* XXX: This can be great on most RISC machines */
  36 +#if !defined(__i386__) && !defined(__x86_64__)
  37 +void OPPROTO glue(op_set_s16_T, REG) (void)
  38 +{
  39 + glue(T, REG) = (int16_t)PARAM(1);
  40 + RETURN();
  41 +}
  42 +
  43 +void OPPROTO glue(op_set_u16_T, REG) (void)
  44 +{
  45 + glue(T, REG) = (uint16_t)PARAM(1);
  46 + RETURN();
  47 +}
  48 +#endif
  49 +
  50 +void OPPROTO glue(op_set_s32_T, REG) (void)
  51 +{
  52 + glue(T, REG) = (int32_t)PARAM(1);
  53 + RETURN();
  54 +}
  55 +
  56 +void OPPROTO glue(op_set_u32_T, REG) (void)
  57 +{
  58 + glue(T, REG) = (uint32_t)PARAM(1);
  59 + RETURN();
  60 +}
  61 +
  62 +#if 0 // Qemu does not know how to do this...
  63 +void OPPROTO glue(op_set_64_T, REG) (void)
  64 +{
  65 + glue(T, REG) = (int64_t)PARAM(1);
  66 + RETURN();
  67 +}
  68 +#else
  69 +void OPPROTO glue(op_set_64_T, REG) (void)
  70 +{
  71 + glue(T, REG) = ((int64_t)PARAM(1) << 32) | (int64_t)PARAM(2);
  72 + RETURN();
  73 +}
  74 +#endif
  75 +
  76 +#endif /* REG < 3 */
  77 +
  78 +/* Fixed-point register moves */
  79 +#if REG < 31
  80 +void OPPROTO glue(op_load_T0_ir, REG) (void)
  81 +{
  82 + T0 = env->ir[REG];
  83 + RETURN();
  84 +}
  85 +
  86 +void OPPROTO glue(op_load_T1_ir, REG) (void)
  87 +{
  88 + T1 = env->ir[REG];
  89 + RETURN();
  90 +}
  91 +
  92 +void OPPROTO glue(op_load_T2_ir, REG) (void)
  93 +{
  94 + T2 = env->ir[REG];
  95 + RETURN();
  96 +}
  97 +
  98 +void OPPROTO glue(op_store_T0_ir, REG) (void)
  99 +{
  100 + env->ir[REG] = T0;
  101 + RETURN();
  102 +}
  103 +
  104 +void OPPROTO glue(op_store_T1_ir, REG) (void)
  105 +{
  106 + env->ir[REG] = T1;
  107 + RETURN();
  108 +}
  109 +
  110 +void OPPROTO glue(op_store_T2_ir, REG) (void)
  111 +{
  112 + env->ir[REG] = T2;
  113 + RETURN();
  114 +}
  115 +
  116 +void OPPROTO glue(op_cmov_ir, REG) (void)
  117 +{
  118 + if (T0)
  119 + env->ir[REG] = T1;
  120 + RETURN();
  121 +}
  122 +
  123 +/* floating point registers moves */
  124 +void OPPROTO glue(op_load_FT0_fir, REG) (void)
  125 +{
  126 + FT0 = env->fir[REG];
  127 + RETURN();
  128 +}
  129 +
  130 +void OPPROTO glue(op_load_FT1_fir, REG) (void)
  131 +{
  132 + FT1 = env->fir[REG];
  133 + RETURN();
  134 +}
  135 +
  136 +void OPPROTO glue(op_load_FT2_fir, REG) (void)
  137 +{
  138 + FT2 = env->fir[REG];
  139 + RETURN();
  140 +}
  141 +
  142 +void OPPROTO glue(op_store_FT0_fir, REG) (void)
  143 +{
  144 + env->fir[REG] = FT0;
  145 + RETURN();
  146 +}
  147 +
  148 +void OPPROTO glue(op_store_FT1_fir, REG) (void)
  149 +{
  150 + env->fir[REG] = FT1;
  151 + RETURN();
  152 +}
  153 +
  154 +void OPPROTO glue(op_store_FT2_fir, REG) (void)
  155 +{
  156 + env->fir[REG] = FT2;
  157 + RETURN();
  158 +}
  159 +
  160 +void OPPROTO glue(op_cmov_fir, REG) (void)
  161 +{
  162 + helper_cmov_fir(REG);
  163 + RETURN();
  164 +}
  165 +#endif /* REG < 31 */
  166 +
  167 +#undef REG
target-alpha/translate.c 0 → 100644
  1 +/*
  2 + * Alpha emulation cpu translation 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 +#include "disas.h"
  28 +
  29 +#define DO_SINGLE_STEP
  30 +#define GENERATE_NOP
  31 +#define ALPHA_DEBUG_DISAS
  32 +#define DO_TB_FLUSH
  33 +
  34 +typedef struct DisasContext DisasContext;
  35 +struct DisasContext {
  36 + uint64_t pc;
  37 + int mem_idx;
  38 +#if !defined (CONFIG_USER_ONLY)
  39 + int pal_mode;
  40 +#endif
  41 + uint32_t amask;
  42 +};
  43 +
  44 +#ifdef USE_DIRECT_JUMP
  45 +#define TBPARAM(x)
  46 +#else
  47 +#define TBPARAM(x) (long)(x)
  48 +#endif
  49 +
  50 +enum {
  51 +#define DEF(s, n, copy_size) INDEX_op_ ## s,
  52 +#include "opc.h"
  53 +#undef DEF
  54 + NB_OPS,
  55 +};
  56 +
  57 +static uint16_t *gen_opc_ptr;
  58 +static uint32_t *gen_opparam_ptr;
  59 +
  60 +#include "gen-op.h"
  61 +
  62 +static inline void gen_op_nop (void)
  63 +{
  64 +#if defined(GENERATE_NOP)
  65 + gen_op_no_op();
  66 +#endif
  67 +}
  68 +
  69 +#define GEN32(func, NAME) \
  70 +static GenOpFunc *NAME ## _table [32] = { \
  71 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  72 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  73 +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
  74 +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
  75 +NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
  76 +NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
  77 +NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
  78 +NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
  79 +}; \
  80 +static inline void func(int n) \
  81 +{ \
  82 + NAME ## _table[n](); \
  83 +}
  84 +
  85 +/* IR moves */
  86 +/* Special hacks for ir31 */
  87 +#define gen_op_load_T0_ir31 gen_op_reset_T0
  88 +#define gen_op_load_T1_ir31 gen_op_reset_T1
  89 +#define gen_op_load_T2_ir31 gen_op_reset_T2
  90 +#define gen_op_store_T0_ir31 gen_op_nop
  91 +#define gen_op_store_T1_ir31 gen_op_nop
  92 +#define gen_op_store_T2_ir31 gen_op_nop
  93 +#define gen_op_cmov_ir31 gen_op_nop
  94 +GEN32(gen_op_load_T0_ir, gen_op_load_T0_ir);
  95 +GEN32(gen_op_load_T1_ir, gen_op_load_T1_ir);
  96 +GEN32(gen_op_load_T2_ir, gen_op_load_T2_ir);
  97 +GEN32(gen_op_store_T0_ir, gen_op_store_T0_ir);
  98 +GEN32(gen_op_store_T1_ir, gen_op_store_T1_ir);
  99 +GEN32(gen_op_store_T2_ir, gen_op_store_T2_ir);
  100 +GEN32(gen_op_cmov_ir, gen_op_cmov_ir);
  101 +
  102 +static inline void gen_load_ir (DisasContext *ctx, int irn, int Tn)
  103 +{
  104 + switch (Tn) {
  105 + case 0:
  106 + gen_op_load_T0_ir(irn);
  107 + break;
  108 + case 1:
  109 + gen_op_load_T1_ir(irn);
  110 + break;
  111 + case 2:
  112 + gen_op_load_T2_ir(irn);
  113 + break;
  114 + }
  115 +}
  116 +
  117 +static inline void gen_store_ir (DisasContext *ctx, int irn, int Tn)
  118 +{
  119 + switch (Tn) {
  120 + case 0:
  121 + gen_op_store_T0_ir(irn);
  122 + break;
  123 + case 1:
  124 + gen_op_store_T1_ir(irn);
  125 + break;
  126 + case 2:
  127 + gen_op_store_T2_ir(irn);
  128 + break;
  129 + }
  130 +}
  131 +
  132 +/* FIR moves */
  133 +/* Special hacks for fir31 */
  134 +#define gen_op_load_FT0_fir31 gen_op_reset_FT0
  135 +#define gen_op_load_FT1_fir31 gen_op_reset_FT1
  136 +#define gen_op_load_FT2_fir31 gen_op_reset_FT2
  137 +#define gen_op_store_FT0_fir31 gen_op_nop
  138 +#define gen_op_store_FT1_fir31 gen_op_nop
  139 +#define gen_op_store_FT2_fir31 gen_op_nop
  140 +#define gen_op_cmov_fir31 gen_op_nop
  141 +GEN32(gen_op_load_FT0_fir, gen_op_load_FT0_fir);
  142 +GEN32(gen_op_load_FT1_fir, gen_op_load_FT1_fir);
  143 +GEN32(gen_op_load_FT2_fir, gen_op_load_FT2_fir);
  144 +GEN32(gen_op_store_FT0_fir, gen_op_store_FT0_fir);
  145 +GEN32(gen_op_store_FT1_fir, gen_op_store_FT1_fir);
  146 +GEN32(gen_op_store_FT2_fir, gen_op_store_FT2_fir);
  147 +GEN32(gen_op_cmov_fir, gen_op_cmov_fir);
  148 +
  149 +static inline void gen_load_fir (DisasContext *ctx, int firn, int Tn)
  150 +{
  151 + switch (Tn) {
  152 + case 0:
  153 + gen_op_load_FT0_fir(firn);
  154 + break;
  155 + case 1:
  156 + gen_op_load_FT1_fir(firn);
  157 + break;
  158 + case 2:
  159 + gen_op_load_FT2_fir(firn);
  160 + break;
  161 + }
  162 +}
  163 +
  164 +static inline void gen_store_fir (DisasContext *ctx, int firn, int Tn)
  165 +{
  166 + switch (Tn) {
  167 + case 0:
  168 + gen_op_store_FT0_fir(firn);
  169 + break;
  170 + case 1:
  171 + gen_op_store_FT1_fir(firn);
  172 + break;
  173 + case 2:
  174 + gen_op_store_FT2_fir(firn);
  175 + break;
  176 + }
  177 +}
  178 +
  179 +/* Memory moves */
  180 +#if defined(CONFIG_USER_ONLY)
  181 +#define OP_LD_TABLE(width) \
  182 +static GenOpFunc *gen_op_ld##width[] = { \
  183 + &gen_op_ld##width##_raw, \
  184 +}
  185 +#define OP_ST_TABLE(width) \
  186 +static GenOpFunc *gen_op_st##width[] = { \
  187 + &gen_op_st##width##_raw, \
  188 +}
  189 +#else
  190 +#define OP_LD_TABLE(width) \
  191 +static GenOpFunc *gen_op_ld##width[] = { \
  192 + &gen_op_ld##width##_kernel, \
  193 + &gen_op_ld##width##_user, /* executive */ \
  194 + &gen_op_ld##width##_data, /* supervisor */ \
  195 + &gen_op_ld##width##_data, /* user */ \
  196 +}
  197 +#define OP_ST_TABLE(width) \
  198 +static GenOpFunc *gen_op_st##width[] = { \
  199 + &gen_op_st##width##_kernel, \
  200 + &gen_op_st##width##_user, /* executive */ \
  201 + &gen_op_st##width##_data, /* supervisor */ \
  202 + &gen_op_st##width##_data, /* user */ \
  203 +}
  204 +#endif
  205 +
  206 +#define GEN_LD(width) \
  207 +OP_LD_TABLE(width); \
  208 +static void gen_ld##width (DisasContext *ctx) \
  209 +{ \
  210 + (*gen_op_ld##width[ctx->mem_idx])(); \
  211 +}
  212 +
  213 +#define GEN_ST(width) \
  214 +OP_ST_TABLE(width); \
  215 +static void gen_st##width (DisasContext *ctx) \
  216 +{ \
  217 + (*gen_op_st##width[ctx->mem_idx])(); \
  218 +}
  219 +
  220 +GEN_LD(bu);
  221 +GEN_ST(b);
  222 +GEN_LD(wu);
  223 +GEN_ST(w);
  224 +GEN_LD(l);
  225 +GEN_ST(l);
  226 +GEN_LD(q);
  227 +GEN_ST(q);
  228 +GEN_LD(q_u);
  229 +GEN_ST(q_u);
  230 +GEN_LD(l_l);
  231 +GEN_ST(l_c);
  232 +GEN_LD(q_l);
  233 +GEN_ST(q_c);
  234 +
  235 +GEN_LD(f);
  236 +GEN_ST(f);
  237 +GEN_LD(g);
  238 +GEN_ST(g);
  239 +GEN_LD(s);
  240 +GEN_ST(s);
  241 +GEN_LD(t);
  242 +GEN_ST(t);
  243 +
  244 +#if defined(__i386__) || defined(__x86_64__)
  245 +static inline void gen_op_set_s16_T0 (int16_t imm)
  246 +{
  247 + gen_op_set_s32_T0((int32_t)imm);
  248 +}
  249 +
  250 +static inline void gen_op_set_s16_T1 (int16_t imm)
  251 +{
  252 + gen_op_set_s32_T1((int32_t)imm);
  253 +}
  254 +
  255 +static inline void gen_op_set_u16_T0 (uint16_t imm)
  256 +{
  257 + gen_op_set_s32_T0((uint32_t)imm);
  258 +}
  259 +
  260 +static inline void gen_op_set_u16_T1 (uint16_t imm)
  261 +{
  262 + gen_op_set_s32_T1((uint32_t)imm);
  263 +}
  264 +#endif
  265 +
  266 +static inline void gen_set_sT0 (DisasContext *ctx, int64_t imm)
  267 +{
  268 + int32_t imm32;
  269 + int16_t imm16;
  270 +
  271 + imm32 = imm;
  272 + if (imm32 == imm) {
  273 + imm16 = imm;
  274 + if (imm16 == imm) {
  275 + if (imm == 0) {
  276 + gen_op_reset_T0();
  277 + } else {
  278 + gen_op_set_s16_T0(imm16);
  279 + }
  280 + } else {
  281 + gen_op_set_s32_T0(imm32);
  282 + }
  283 + } else {
  284 +#if 0 // Qemu does not know how to do this...
  285 + gen_op_set_64_T0(imm);
  286 +#else
  287 + gen_op_set_64_T0(imm >> 32, imm);
  288 +#endif
  289 + }
  290 +}
  291 +
  292 +static inline void gen_set_sT1 (DisasContext *ctx, int64_t imm)
  293 +{
  294 + int32_t imm32;
  295 + int16_t imm16;
  296 +
  297 + imm32 = imm;
  298 + if (imm32 == imm) {
  299 + imm16 = imm;
  300 + if (imm16 == imm) {
  301 + if (imm == 0) {
  302 + gen_op_reset_T1();
  303 + } else {
  304 + gen_op_set_s16_T1(imm16);
  305 + }
  306 + } else {
  307 + gen_op_set_s32_T1(imm32);
  308 + }
  309 + } else {
  310 +#if 0 // Qemu does not know how to do this...
  311 + gen_op_set_64_T1(imm);
  312 +#else
  313 + gen_op_set_64_T1(imm >> 32, imm);
  314 +#endif
  315 + }
  316 +}
  317 +
  318 +static inline void gen_set_uT0 (DisasContext *ctx, uint64_t imm)
  319 +{
  320 + if (!(imm >> 32)) {
  321 + if ((!imm >> 16)) {
  322 + if (imm == 0)
  323 + gen_op_reset_T0();
  324 + else
  325 + gen_op_set_u16_T0(imm);
  326 + } else {
  327 + gen_op_set_u32_T0(imm);
  328 + }
  329 + } else {
  330 +#if 0 // Qemu does not know how to do this...
  331 + gen_op_set_64_T0(imm);
  332 +#else
  333 + gen_op_set_64_T0(imm >> 32, imm);
  334 +#endif
  335 + }
  336 +}
  337 +
  338 +static inline void gen_set_uT1 (DisasContext *ctx, uint64_t imm)
  339 +{
  340 + if (!(imm >> 32)) {
  341 + if ((!imm >> 16)) {
  342 + if (imm == 0)
  343 + gen_op_reset_T1();
  344 + else
  345 + gen_op_set_u16_T1(imm);
  346 + } else {
  347 + gen_op_set_u32_T1(imm);
  348 + }
  349 + } else {
  350 +#if 0 // Qemu does not know how to do this...
  351 + gen_op_set_64_T1(imm);
  352 +#else
  353 + gen_op_set_64_T1(imm >> 32, imm);
  354 +#endif
  355 + }
  356 +}
  357 +
  358 +static inline void gen_update_pc (DisasContext *ctx)
  359 +{
  360 + if (!(ctx->pc >> 32)) {
  361 + gen_op_update_pc32(ctx->pc);
  362 + } else {
  363 +#if 0 // Qemu does not know how to do this...
  364 + gen_op_update_pc(ctx->pc);
  365 +#else
  366 + gen_op_update_pc(ctx->pc >> 32, ctx->pc);
  367 +#endif
  368 + }
  369 +}
  370 +
  371 +static inline void _gen_op_bcond (DisasContext *ctx)
  372 +{
  373 +#if 0 // Qemu does not know how to do this...
  374 + gen_op_bcond(ctx->pc);
  375 +#else
  376 + gen_op_bcond(ctx->pc >> 32, ctx->pc);
  377 +#endif
  378 +}
  379 +
  380 +static inline void gen_excp (DisasContext *ctx, int exception, int error_code)
  381 +{
  382 + gen_update_pc(ctx);
  383 + gen_op_excp(exception, error_code);
  384 +}
  385 +
  386 +static inline void gen_invalid (DisasContext *ctx)
  387 +{
  388 + gen_excp(ctx, EXCP_OPCDEC, 0);
  389 +}
  390 +
  391 +static void gen_load_mem (DisasContext *ctx,
  392 + void (*gen_load_op)(DisasContext *ctx),
  393 + int ra, int rb, int32_t disp16, int clear)
  394 +{
  395 + if (ra == 31 && disp16 == 0) {
  396 + /* UNOP */
  397 + gen_op_nop();
  398 + } else {
  399 + gen_load_ir(ctx, rb, 0);
  400 + if (disp16 != 0) {
  401 + gen_set_sT1(ctx, disp16);
  402 + gen_op_addq();
  403 + }
  404 + if (clear)
  405 + gen_op_n7();
  406 + (*gen_load_op)(ctx);
  407 + gen_store_ir(ctx, ra, 1);
  408 + }
  409 +}
  410 +
  411 +static void gen_store_mem (DisasContext *ctx,
  412 + void (*gen_store_op)(DisasContext *ctx),
  413 + int ra, int rb, int32_t disp16, int clear)
  414 +{
  415 + gen_load_ir(ctx, rb, 0);
  416 + if (disp16 != 0) {
  417 + gen_set_sT1(ctx, disp16);
  418 + gen_op_addq();
  419 + }
  420 + if (clear)
  421 + gen_op_n7();
  422 + gen_load_ir(ctx, ra, 1);
  423 + (*gen_store_op)(ctx);
  424 +}
  425 +
  426 +static void gen_load_fmem (DisasContext *ctx,
  427 + void (*gen_load_fop)(DisasContext *ctx),
  428 + int ra, int rb, int32_t disp16)
  429 +{
  430 + gen_load_ir(ctx, rb, 0);
  431 + if (disp16 != 0) {
  432 + gen_set_sT1(ctx, disp16);
  433 + gen_op_addq();
  434 + }
  435 + (*gen_load_fop)(ctx);
  436 + gen_store_fir(ctx, ra, 1);
  437 +}
  438 +
  439 +static void gen_store_fmem (DisasContext *ctx,
  440 + void (*gen_store_fop)(DisasContext *ctx),
  441 + int ra, int rb, int32_t disp16)
  442 +{
  443 + gen_load_ir(ctx, rb, 0);
  444 + if (disp16 != 0) {
  445 + gen_set_sT1(ctx, disp16);
  446 + gen_op_addq();
  447 + }
  448 + gen_load_fir(ctx, ra, 1);
  449 + (*gen_store_fop)(ctx);
  450 +}
  451 +
  452 +static void gen_bcond (DisasContext *ctx, void (*gen_test_op)(void),
  453 + int ra, int32_t disp16)
  454 +{
  455 + if (disp16 != 0) {
  456 + gen_set_uT0(ctx, ctx->pc);
  457 + gen_set_sT1(ctx, disp16 << 2);
  458 + gen_op_addq1();
  459 + } else {
  460 + gen_set_uT1(ctx, ctx->pc);
  461 + }
  462 + gen_load_ir(ctx, ra, 0);
  463 + (*gen_test_op)();
  464 + _gen_op_bcond(ctx);
  465 +}
  466 +
  467 +static void gen_fbcond (DisasContext *ctx, void (*gen_test_op)(void),
  468 + int ra, int32_t disp16)
  469 +{
  470 + if (disp16 != 0) {
  471 + gen_set_uT0(ctx, ctx->pc);
  472 + gen_set_sT1(ctx, disp16 << 2);
  473 + gen_op_addq1();
  474 + } else {
  475 + gen_set_uT1(ctx, ctx->pc);
  476 + }
  477 + gen_load_fir(ctx, ra, 0);
  478 + (*gen_test_op)();
  479 + _gen_op_bcond(ctx);
  480 +}
  481 +
  482 +static void gen_arith2 (DisasContext *ctx, void (*gen_arith_op)(void),
  483 + int rb, int rc, int islit, int8_t lit)
  484 +{
  485 + if (islit)
  486 + gen_set_sT0(ctx, lit);
  487 + else
  488 + gen_load_ir(ctx, rb, 0);
  489 + (*gen_arith_op)();
  490 + gen_store_ir(ctx, rc, 0);
  491 +}
  492 +
  493 +static void gen_arith3 (DisasContext *ctx, void (*gen_arith_op)(void),
  494 + int ra, int rb, int rc, int islit, int8_t lit)
  495 +{
  496 + gen_load_ir(ctx, ra, 0);
  497 + if (islit)
  498 + gen_set_sT1(ctx, lit);
  499 + else
  500 + gen_load_ir(ctx, rb, 1);
  501 + (*gen_arith_op)();
  502 + gen_store_ir(ctx, rc, 0);
  503 +}
  504 +
  505 +static void gen_cmov (DisasContext *ctx, void (*gen_test_op)(void),
  506 + int ra, int rb, int rc, int islit, int8_t lit)
  507 +{
  508 + gen_load_ir(ctx, ra, 1);
  509 + if (islit)
  510 + gen_set_sT0(ctx, lit);
  511 + else
  512 + gen_load_ir(ctx, rb, 0);
  513 + (*gen_test_op)();
  514 + gen_op_cmov_ir(rc);
  515 +}
  516 +
  517 +static void gen_farith2 (DisasContext *ctx, void (*gen_arith_fop)(void),
  518 + int rb, int rc)
  519 +{
  520 + gen_load_fir(ctx, rb, 0);
  521 + (*gen_arith_fop)();
  522 + gen_store_fir(ctx, rc, 0);
  523 +}
  524 +
  525 +static void gen_farith3 (DisasContext *ctx, void (*gen_arith_fop)(void),
  526 + int ra, int rb, int rc)
  527 +{
  528 + gen_load_fir(ctx, ra, 0);
  529 + gen_load_fir(ctx, rb, 1);
  530 + (*gen_arith_fop)();
  531 + gen_store_fir(ctx, rc, 0);
  532 +}
  533 +
  534 +static void gen_fcmov (DisasContext *ctx, void (*gen_test_fop)(void),
  535 + int ra, int rb, int rc)
  536 +{
  537 + gen_load_fir(ctx, ra, 0);
  538 + gen_load_fir(ctx, rb, 1);
  539 + (*gen_test_fop)();
  540 + gen_op_cmov_fir(rc);
  541 +}
  542 +
  543 +static void gen_fti (DisasContext *ctx, void (*gen_move_fop)(void),
  544 + int ra, int rc)
  545 +{
  546 + gen_load_fir(ctx, rc, 0);
  547 + (*gen_move_fop)();
  548 + gen_store_ir(ctx, ra, 0);
  549 +}
  550 +
  551 +static void gen_itf (DisasContext *ctx, void (*gen_move_fop)(void),
  552 + int ra, int rc)
  553 +{
  554 + gen_load_ir(ctx, ra, 0);
  555 + (*gen_move_fop)();
  556 + gen_store_fir(ctx, rc, 0);
  557 +}
  558 +
  559 +static void gen_s4addl (void)
  560 +{
  561 + gen_op_s4();
  562 + gen_op_addl();
  563 +}
  564 +
  565 +static void gen_s4subl (void)
  566 +{
  567 + gen_op_s4();
  568 + gen_op_subl();
  569 +}
  570 +
  571 +static void gen_s8addl (void)
  572 +{
  573 + gen_op_s8();
  574 + gen_op_addl();
  575 +}
  576 +
  577 +static void gen_s8subl (void)
  578 +{
  579 + gen_op_s8();
  580 + gen_op_subl();
  581 +}
  582 +
  583 +static void gen_s4addq (void)
  584 +{
  585 + gen_op_s4();
  586 + gen_op_addq();
  587 +}
  588 +
  589 +static void gen_s4subq (void)
  590 +{
  591 + gen_op_s4();
  592 + gen_op_subq();
  593 +}
  594 +
  595 +static void gen_s8addq (void)
  596 +{
  597 + gen_op_s8();
  598 + gen_op_addq();
  599 +}
  600 +
  601 +static void gen_s8subq (void)
  602 +{
  603 + gen_op_s8();
  604 + gen_op_subq();
  605 +}
  606 +
  607 +static void gen_amask (void)
  608 +{
  609 + gen_op_load_amask();
  610 + gen_op_bic();
  611 +}
  612 +
  613 +static int translate_one (DisasContext *ctx, uint32_t insn)
  614 +{
  615 + uint32_t palcode;
  616 + int32_t disp21, disp16, disp12;
  617 + uint16_t fn11, fn16;
  618 + uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit;
  619 + int8_t lit;
  620 + int ret;
  621 +
  622 + /* Decode all instruction fields */
  623 + opc = insn >> 26;
  624 + ra = (insn >> 21) & 0x1F;
  625 + rb = (insn >> 16) & 0x1F;
  626 + rc = insn & 0x1F;
  627 + sbz = (insn >> 13) & 0x07;
  628 + islit = (insn >> 12) & 1;
  629 + lit = (insn >> 13) & 0xFF;
  630 + palcode = insn & 0x03FFFFFF;
  631 + disp21 = ((int32_t)((insn & 0x001FFFFF) << 11)) >> 11;
  632 + disp16 = (int16_t)(insn & 0x0000FFFF);
  633 + disp12 = (int32_t)((insn & 0x00000FFF) << 20) >> 20;
  634 + fn16 = insn & 0x0000FFFF;
  635 + fn11 = (insn >> 5) & 0x000007FF;
  636 + fpfn = fn11 & 0x3F;
  637 + fn7 = (insn >> 5) & 0x0000007F;
  638 + fn2 = (insn >> 5) & 0x00000003;
  639 + ret = 0;
  640 +#if defined ALPHA_DEBUG_DISAS
  641 + if (logfile != NULL) {
  642 + fprintf(logfile, "opc %02x ra %d rb %d rc %d disp16 %04x\n",
  643 + opc, ra, rb, rc, disp16);
  644 + }
  645 +#endif
  646 + switch (opc) {
  647 + case 0x00:
  648 + /* CALL_PAL */
  649 + if (palcode >= 0x80 && palcode < 0xC0) {
  650 + /* Unprivileged PAL call */
  651 + gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x1F) << 6), 0);
  652 +#if !defined (CONFIG_USER_ONLY)
  653 + } else if (palcode < 0x40) {
  654 + /* Privileged PAL code */
  655 + if (ctx->mem_idx & 1)
  656 + goto invalid_opc;
  657 + else
  658 + gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x1F) << 6), 0);
  659 +#endif
  660 + } else {
  661 + /* Invalid PAL call */
  662 + goto invalid_opc;
  663 + }
  664 + ret = 3;
  665 + break;
  666 + case 0x01:
  667 + /* OPC01 */
  668 + goto invalid_opc;
  669 + case 0x02:
  670 + /* OPC02 */
  671 + goto invalid_opc;
  672 + case 0x03:
  673 + /* OPC03 */
  674 + goto invalid_opc;
  675 + case 0x04:
  676 + /* OPC04 */
  677 + goto invalid_opc;
  678 + case 0x05:
  679 + /* OPC05 */
  680 + goto invalid_opc;
  681 + case 0x06:
  682 + /* OPC06 */
  683 + goto invalid_opc;
  684 + case 0x07:
  685 + /* OPC07 */
  686 + goto invalid_opc;
  687 + case 0x08:
  688 + /* LDA */
  689 + gen_load_ir(ctx, rb, 0);
  690 + gen_set_sT1(ctx, disp16);
  691 + gen_op_addq();
  692 + gen_store_ir(ctx, ra, 0);
  693 + break;
  694 + case 0x09:
  695 + /* LDAH */
  696 + gen_load_ir(ctx, rb, 0);
  697 + gen_set_sT1(ctx, disp16 << 16);
  698 + gen_op_addq();
  699 + gen_store_ir(ctx, ra, 0);
  700 + break;
  701 + case 0x0A:
  702 + /* LDBU */
  703 + if (!(ctx->amask & AMASK_BWX))
  704 + goto invalid_opc;
  705 + gen_load_mem(ctx, &gen_ldbu, ra, rb, disp16, 0);
  706 + break;
  707 + case 0x0B:
  708 + /* LDQ_U */
  709 + gen_load_mem(ctx, &gen_ldq_u, ra, rb, disp16, 1);
  710 + break;
  711 + case 0x0C:
  712 + /* LDWU */
  713 + if (!(ctx->amask & AMASK_BWX))
  714 + goto invalid_opc;
  715 + gen_load_mem(ctx, &gen_ldwu, ra, rb, disp16, 0);
  716 + break;
  717 + case 0x0D:
  718 + /* STW */
  719 + if (!(ctx->amask & AMASK_BWX))
  720 + goto invalid_opc;
  721 + gen_store_mem(ctx, &gen_stw, ra, rb, disp16, 0);
  722 + break;
  723 + case 0x0E:
  724 + /* STB */
  725 + if (!(ctx->amask & AMASK_BWX))
  726 + goto invalid_opc;
  727 + gen_store_mem(ctx, &gen_stb, ra, rb, disp16, 0);
  728 + break;
  729 + case 0x0F:
  730 + /* STQ_U */
  731 + gen_store_mem(ctx, &gen_stq_u, ra, rb, disp16, 1);
  732 + break;
  733 + case 0x10:
  734 + switch (fn7) {
  735 + case 0x00:
  736 + /* ADDL */
  737 + gen_arith3(ctx, &gen_op_addl, ra, rb, rc, islit, lit);
  738 + break;
  739 + case 0x02:
  740 + /* S4ADDL */
  741 + gen_arith3(ctx, &gen_s4addl, ra, rb, rc, islit, lit);
  742 + break;
  743 + case 0x09:
  744 + /* SUBL */
  745 + gen_arith3(ctx, &gen_op_subl, ra, rb, rc, islit, lit);
  746 + break;
  747 + case 0x0B:
  748 + /* S4SUBL */
  749 + gen_arith3(ctx, &gen_s4subl, ra, rb, rc, islit, lit);
  750 + break;
  751 + case 0x0F:
  752 + /* CMPBGE */
  753 + gen_arith3(ctx, &gen_op_cmpbge, ra, rb, rc, islit, lit);
  754 + break;
  755 + case 0x12:
  756 + /* S8ADDL */
  757 + gen_arith3(ctx, &gen_s8addl, ra, rb, rc, islit, lit);
  758 + break;
  759 + case 0x1B:
  760 + /* S8SUBL */
  761 + gen_arith3(ctx, &gen_s8subl, ra, rb, rc, islit, lit);
  762 + break;
  763 + case 0x1D:
  764 + /* CMPULT */
  765 + gen_arith3(ctx, &gen_op_cmpult, ra, rb, rc, islit, lit);
  766 + break;
  767 + case 0x20:
  768 + /* ADDQ */
  769 + gen_arith3(ctx, &gen_op_addq, ra, rb, rc, islit, lit);
  770 + break;
  771 + case 0x22:
  772 + /* S4ADDQ */
  773 + gen_arith3(ctx, &gen_s4addq, ra, rb, rc, islit, lit);
  774 + break;
  775 + case 0x29:
  776 + /* SUBQ */
  777 + gen_arith3(ctx, &gen_op_subq, ra, rb, rc, islit, lit);
  778 + break;
  779 + case 0x2B:
  780 + /* S4SUBQ */
  781 + gen_arith3(ctx, &gen_s4subq, ra, rb, rc, islit, lit);
  782 + break;
  783 + case 0x2D:
  784 + /* CMPEQ */
  785 + gen_arith3(ctx, &gen_op_cmpeq, ra, rb, rc, islit, lit);
  786 + break;
  787 + case 0x32:
  788 + /* S8ADDQ */
  789 + gen_arith3(ctx, &gen_s8addq, ra, rb, rc, islit, lit);
  790 + break;
  791 + case 0x3B:
  792 + /* S8SUBQ */
  793 + gen_arith3(ctx, &gen_s8subq, ra, rb, rc, islit, lit);
  794 + break;
  795 + case 0x3D:
  796 + /* CMPULE */
  797 + gen_arith3(ctx, &gen_op_cmpule, ra, rb, rc, islit, lit);
  798 + break;
  799 + case 0x40:
  800 + /* ADDL/V */
  801 + gen_arith3(ctx, &gen_op_addlv, ra, rb, rc, islit, lit);
  802 + break;
  803 + case 0x49:
  804 + /* SUBL/V */
  805 + gen_arith3(ctx, &gen_op_sublv, ra, rb, rc, islit, lit);
  806 + break;
  807 + case 0x4D:
  808 + /* CMPLT */
  809 + gen_arith3(ctx, &gen_op_cmplt, ra, rb, rc, islit, lit);
  810 + break;
  811 + case 0x60:
  812 + /* ADDQ/V */
  813 + gen_arith3(ctx, &gen_op_addqv, ra, rb, rc, islit, lit);
  814 + break;
  815 + case 0x69:
  816 + /* SUBQ/V */
  817 + gen_arith3(ctx, &gen_op_subqv, ra, rb, rc, islit, lit);
  818 + break;
  819 + case 0x6D:
  820 + /* CMPLE */
  821 + gen_arith3(ctx, &gen_op_cmple, ra, rb, rc, islit, lit);
  822 + break;
  823 + default:
  824 + goto invalid_opc;
  825 + }
  826 + break;
  827 + case 0x11:
  828 + switch (fn7) {
  829 + case 0x00:
  830 + /* AND */
  831 + gen_arith3(ctx, &gen_op_and, ra, rb, rc, islit, lit);
  832 + break;
  833 + case 0x08:
  834 + /* BIC */
  835 + gen_arith3(ctx, &gen_op_bic, ra, rb, rc, islit, lit);
  836 + break;
  837 + case 0x14:
  838 + /* CMOVLBS */
  839 + gen_cmov(ctx, &gen_op_cmplbs, ra, rb, rc, islit, lit);
  840 + break;
  841 + case 0x16:
  842 + /* CMOVLBC */
  843 + gen_cmov(ctx, &gen_op_cmplbc, ra, rb, rc, islit, lit);
  844 + break;
  845 + case 0x20:
  846 + /* BIS */
  847 + if (ra == rb || ra == 31 || rb == 31) {
  848 + if (ra == 31 && rc == 31) {
  849 + /* NOP */
  850 + gen_op_nop();
  851 + } else {
  852 + /* MOV */
  853 + gen_load_ir(ctx, rb, 0);
  854 + gen_store_ir(ctx, rc, 0);
  855 + }
  856 + } else {
  857 + gen_arith3(ctx, &gen_op_bis, ra, rb, rc, islit, lit);
  858 + }
  859 + break;
  860 + case 0x24:
  861 + /* CMOVEQ */
  862 + gen_cmov(ctx, &gen_op_cmpeqz, ra, rb, rc, islit, lit);
  863 + break;
  864 + case 0x26:
  865 + /* CMOVNE */
  866 + gen_cmov(ctx, &gen_op_cmpnez, ra, rb, rc, islit, lit);
  867 + break;
  868 + case 0x28:
  869 + /* ORNOT */
  870 + gen_arith3(ctx, &gen_op_ornot, ra, rb, rc, islit, lit);
  871 + break;
  872 + case 0x40:
  873 + /* XOR */
  874 + gen_arith3(ctx, &gen_op_xor, ra, rb, rc, islit, lit);
  875 + break;
  876 + case 0x44:
  877 + /* CMOVLT */
  878 + gen_cmov(ctx, &gen_op_cmpltz, ra, rb, rc, islit, lit);
  879 + break;
  880 + case 0x46:
  881 + /* CMOVGE */
  882 + gen_cmov(ctx, &gen_op_cmpgez, ra, rb, rc, islit, lit);
  883 + break;
  884 + case 0x48:
  885 + /* EQV */
  886 + gen_arith3(ctx, &gen_op_eqv, ra, rb, rc, islit, lit);
  887 + break;
  888 + case 0x61:
  889 + /* AMASK */
  890 + gen_arith2(ctx, &gen_amask, rb, rc, islit, lit);
  891 + break;
  892 + case 0x64:
  893 + /* CMOVLE */
  894 + gen_cmov(ctx, &gen_op_cmplez, ra, rb, rc, islit, lit);
  895 + break;
  896 + case 0x66:
  897 + /* CMOVGT */
  898 + gen_cmov(ctx, &gen_op_cmpgtz, ra, rb, rc, islit, lit);
  899 + break;
  900 + case 0x6C:
  901 + /* IMPLVER */
  902 + gen_op_load_implver();
  903 + gen_store_ir(ctx, rc, 0);
  904 + break;
  905 + default:
  906 + goto invalid_opc;
  907 + }
  908 + break;
  909 + case 0x12:
  910 + switch (fn7) {
  911 + case 0x02:
  912 + /* MSKBL */
  913 + gen_arith3(ctx, &gen_op_mskbl, ra, rb, rc, islit, lit);
  914 + break;
  915 + case 0x06:
  916 + /* EXTBL */
  917 + gen_arith3(ctx, &gen_op_extbl, ra, rb, rc, islit, lit);
  918 + break;
  919 + case 0x0B:
  920 + /* INSBL */
  921 + gen_arith3(ctx, &gen_op_insbl, ra, rb, rc, islit, lit);
  922 + break;
  923 + case 0x12:
  924 + /* MSKWL */
  925 + gen_arith3(ctx, &gen_op_mskwl, ra, rb, rc, islit, lit);
  926 + break;
  927 + case 0x16:
  928 + /* EXTWL */
  929 + gen_arith3(ctx, &gen_op_extwl, ra, rb, rc, islit, lit);
  930 + break;
  931 + case 0x1B:
  932 + /* INSWL */
  933 + gen_arith3(ctx, &gen_op_inswl, ra, rb, rc, islit, lit);
  934 + break;
  935 + case 0x22:
  936 + /* MSKLL */
  937 + gen_arith3(ctx, &gen_op_mskll, ra, rb, rc, islit, lit);
  938 + break;
  939 + case 0x26:
  940 + /* EXTLL */
  941 + gen_arith3(ctx, &gen_op_extll, ra, rb, rc, islit, lit);
  942 + break;
  943 + case 0x2B:
  944 + /* INSLL */
  945 + gen_arith3(ctx, &gen_op_insll, ra, rb, rc, islit, lit);
  946 + break;
  947 + case 0x30:
  948 + /* ZAP */
  949 + gen_arith3(ctx, &gen_op_zap, ra, rb, rc, islit, lit);
  950 + break;
  951 + case 0x31:
  952 + /* ZAPNOT */
  953 + gen_arith3(ctx, &gen_op_zapnot, ra, rb, rc, islit, lit);
  954 + break;
  955 + case 0x32:
  956 + /* MSKQL */
  957 + gen_arith3(ctx, &gen_op_mskql, ra, rb, rc, islit, lit);
  958 + break;
  959 + case 0x34:
  960 + /* SRL */
  961 + gen_arith3(ctx, &gen_op_srl, ra, rb, rc, islit, lit);
  962 + break;
  963 + case 0x36:
  964 + /* EXTQL */
  965 + gen_arith3(ctx, &gen_op_extql, ra, rb, rc, islit, lit);
  966 + break;
  967 + case 0x39:
  968 + /* SLL */
  969 + gen_arith3(ctx, &gen_op_sll, ra, rb, rc, islit, lit);
  970 + break;
  971 + case 0x3B:
  972 + /* INSQL */
  973 + gen_arith3(ctx, &gen_op_insql, ra, rb, rc, islit, lit);
  974 + break;
  975 + case 0x3C:
  976 + /* SRA */
  977 + gen_arith3(ctx, &gen_op_sra, ra, rb, rc, islit, lit);
  978 + break;
  979 + case 0x52:
  980 + /* MSKWH */
  981 + gen_arith3(ctx, &gen_op_mskwh, ra, rb, rc, islit, lit);
  982 + break;
  983 + case 0x57:
  984 + /* INSWH */
  985 + gen_arith3(ctx, &gen_op_inswh, ra, rb, rc, islit, lit);
  986 + break;
  987 + case 0x5A:
  988 + /* EXTWH */
  989 + gen_arith3(ctx, &gen_op_extwh, ra, rb, rc, islit, lit);
  990 + break;
  991 + case 0x62:
  992 + /* MSKLH */
  993 + gen_arith3(ctx, &gen_op_msklh, ra, rb, rc, islit, lit);
  994 + break;
  995 + case 0x67:
  996 + /* INSLH */
  997 + gen_arith3(ctx, &gen_op_inslh, ra, rb, rc, islit, lit);
  998 + break;
  999 + case 0x6A:
  1000 + /* EXTLH */
  1001 + gen_arith3(ctx, &gen_op_extlh, ra, rb, rc, islit, lit);
  1002 + break;
  1003 + case 0x72:
  1004 + /* MSKQH */
  1005 + gen_arith3(ctx, &gen_op_mskqh, ra, rb, rc, islit, lit);
  1006 + break;
  1007 + case 0x77:
  1008 + /* INSQH */
  1009 + gen_arith3(ctx, &gen_op_insqh, ra, rb, rc, islit, lit);
  1010 + break;
  1011 + case 0x7A:
  1012 + /* EXTQH */
  1013 + gen_arith3(ctx, &gen_op_extqh, ra, rb, rc, islit, lit);
  1014 + break;
  1015 + default:
  1016 + goto invalid_opc;
  1017 + }
  1018 + break;
  1019 + case 0x13:
  1020 + switch (fn7) {
  1021 + case 0x00:
  1022 + /* MULL */
  1023 + gen_arith3(ctx, &gen_op_mull, ra, rb, rc, islit, lit);
  1024 + break;
  1025 + case 0x20:
  1026 + /* MULQ */
  1027 + gen_arith3(ctx, &gen_op_mulq, ra, rb, rc, islit, lit);
  1028 + break;
  1029 + case 0x30:
  1030 + /* UMULH */
  1031 + gen_arith3(ctx, &gen_op_umulh, ra, rb, rc, islit, lit);
  1032 + break;
  1033 + case 0x40:
  1034 + /* MULL/V */
  1035 + gen_arith3(ctx, &gen_op_mullv, ra, rb, rc, islit, lit);
  1036 + break;
  1037 + case 0x60:
  1038 + /* MULQ/V */
  1039 + gen_arith3(ctx, &gen_op_mulqv, ra, rb, rc, islit, lit);
  1040 + break;
  1041 + default:
  1042 + goto invalid_opc;
  1043 + }
  1044 + break;
  1045 + case 0x14:
  1046 + switch (fpfn) { /* f11 & 0x3F */
  1047 + case 0x04:
  1048 + /* ITOFS */
  1049 + if (!(ctx->amask & AMASK_FIX))
  1050 + goto invalid_opc;
  1051 + gen_itf(ctx, &gen_op_itofs, ra, rc);
  1052 + break;
  1053 + case 0x0A:
  1054 + /* SQRTF */
  1055 + if (!(ctx->amask & AMASK_FIX))
  1056 + goto invalid_opc;
  1057 + gen_farith2(ctx, &gen_op_sqrtf, rb, rc);
  1058 + break;
  1059 + case 0x0B:
  1060 + /* SQRTS */
  1061 + if (!(ctx->amask & AMASK_FIX))
  1062 + goto invalid_opc;
  1063 + gen_farith2(ctx, &gen_op_sqrts, rb, rc);
  1064 + break;
  1065 + case 0x14:
  1066 + /* ITOFF */
  1067 + if (!(ctx->amask & AMASK_FIX))
  1068 + goto invalid_opc;
  1069 +#if 0 // TODO
  1070 + gen_itf(ctx, &gen_op_itoff, ra, rc);
  1071 +#else
  1072 + goto invalid_opc;
  1073 +#endif
  1074 + break;
  1075 + case 0x24:
  1076 + /* ITOFT */
  1077 + if (!(ctx->amask & AMASK_FIX))
  1078 + goto invalid_opc;
  1079 + gen_itf(ctx, &gen_op_itoft, ra, rc);
  1080 + break;
  1081 + case 0x2A:
  1082 + /* SQRTG */
  1083 + if (!(ctx->amask & AMASK_FIX))
  1084 + goto invalid_opc;
  1085 + gen_farith2(ctx, &gen_op_sqrtg, rb, rc);
  1086 + break;
  1087 + case 0x02B:
  1088 + /* SQRTT */
  1089 + if (!(ctx->amask & AMASK_FIX))
  1090 + goto invalid_opc;
  1091 + gen_farith2(ctx, &gen_op_sqrtt, rb, rc);
  1092 + break;
  1093 + default:
  1094 + goto invalid_opc;
  1095 + }
  1096 + break;
  1097 + case 0x15:
  1098 + /* VAX floating point */
  1099 + /* XXX: rounding mode and trap are ignored (!) */
  1100 + switch (fpfn) { /* f11 & 0x3F */
  1101 + case 0x00:
  1102 + /* ADDF */
  1103 + gen_farith3(ctx, &gen_op_addf, ra, rb, rc);
  1104 + break;
  1105 + case 0x01:
  1106 + /* SUBF */
  1107 + gen_farith3(ctx, &gen_op_subf, ra, rb, rc);
  1108 + break;
  1109 + case 0x02:
  1110 + /* MULF */
  1111 + gen_farith3(ctx, &gen_op_mulf, ra, rb, rc);
  1112 + break;
  1113 + case 0x03:
  1114 + /* DIVF */
  1115 + gen_farith3(ctx, &gen_op_divf, ra, rb, rc);
  1116 + break;
  1117 + case 0x1E:
  1118 + /* CVTDG */
  1119 +#if 0 // TODO
  1120 + gen_farith2(ctx, &gen_op_cvtdg, rb, rc);
  1121 +#else
  1122 + goto invalid_opc;
  1123 +#endif
  1124 + break;
  1125 + case 0x20:
  1126 + /* ADDG */
  1127 + gen_farith3(ctx, &gen_op_addg, ra, rb, rc);
  1128 + break;
  1129 + case 0x21:
  1130 + /* SUBG */
  1131 + gen_farith3(ctx, &gen_op_subg, ra, rb, rc);
  1132 + break;
  1133 + case 0x22:
  1134 + /* MULG */
  1135 + gen_farith3(ctx, &gen_op_mulg, ra, rb, rc);
  1136 + break;
  1137 + case 0x23:
  1138 + /* DIVG */
  1139 + gen_farith3(ctx, &gen_op_divg, ra, rb, rc);
  1140 + break;
  1141 + case 0x25:
  1142 + /* CMPGEQ */
  1143 + gen_farith3(ctx, &gen_op_cmpgeq, ra, rb, rc);
  1144 + break;
  1145 + case 0x26:
  1146 + /* CMPGLT */
  1147 + gen_farith3(ctx, &gen_op_cmpglt, ra, rb, rc);
  1148 + break;
  1149 + case 0x27:
  1150 + /* CMPGLE */
  1151 + gen_farith3(ctx, &gen_op_cmpgle, ra, rb, rc);
  1152 + break;
  1153 + case 0x2C:
  1154 + /* CVTGF */
  1155 + gen_farith2(ctx, &gen_op_cvtgf, rb, rc);
  1156 + break;
  1157 + case 0x2D:
  1158 + /* CVTGD */
  1159 +#if 0 // TODO
  1160 + gen_farith2(ctx, &gen_op_cvtgd, rb, rc);
  1161 +#else
  1162 + goto invalid_opc;
  1163 +#endif
  1164 + break;
  1165 + case 0x2F:
  1166 + /* CVTGQ */
  1167 + gen_farith2(ctx, &gen_op_cvtgq, rb, rc);
  1168 + break;
  1169 + case 0x3C:
  1170 + /* CVTQF */
  1171 + gen_farith2(ctx, &gen_op_cvtqf, rb, rc);
  1172 + break;
  1173 + case 0x3E:
  1174 + /* CVTQG */
  1175 + gen_farith2(ctx, &gen_op_cvtqg, rb, rc);
  1176 + break;
  1177 + default:
  1178 + goto invalid_opc;
  1179 + }
  1180 + break;
  1181 + case 0x16:
  1182 + /* IEEE floating-point */
  1183 + /* XXX: rounding mode and traps are ignored (!) */
  1184 + switch (fpfn) { /* f11 & 0x3F */
  1185 + case 0x00:
  1186 + /* ADDS */
  1187 + gen_farith3(ctx, &gen_op_adds, ra, rb, rc);
  1188 + break;
  1189 + case 0x01:
  1190 + /* SUBS */
  1191 + gen_farith3(ctx, &gen_op_subs, ra, rb, rc);
  1192 + break;
  1193 + case 0x02:
  1194 + /* MULS */
  1195 + gen_farith3(ctx, &gen_op_muls, ra, rb, rc);
  1196 + break;
  1197 + case 0x03:
  1198 + /* DIVS */
  1199 + gen_farith3(ctx, &gen_op_divs, ra, rb, rc);
  1200 + break;
  1201 + case 0x20:
  1202 + /* ADDT */
  1203 + gen_farith3(ctx, &gen_op_addt, ra, rb, rc);
  1204 + break;
  1205 + case 0x21:
  1206 + /* SUBT */
  1207 + gen_farith3(ctx, &gen_op_subt, ra, rb, rc);
  1208 + break;
  1209 + case 0x22:
  1210 + /* MULT */
  1211 + gen_farith3(ctx, &gen_op_mult, ra, rb, rc);
  1212 + break;
  1213 + case 0x23:
  1214 + /* DIVT */
  1215 + gen_farith3(ctx, &gen_op_divt, ra, rb, rc);
  1216 + break;
  1217 + case 0x24:
  1218 + /* CMPTUN */
  1219 + gen_farith3(ctx, &gen_op_cmptun, ra, rb, rc);
  1220 + break;
  1221 + case 0x25:
  1222 + /* CMPTEQ */
  1223 + gen_farith3(ctx, &gen_op_cmpteq, ra, rb, rc);
  1224 + break;
  1225 + case 0x26:
  1226 + /* CMPTLT */
  1227 + gen_farith3(ctx, &gen_op_cmptlt, ra, rb, rc);
  1228 + break;
  1229 + case 0x27:
  1230 + /* CMPTLE */
  1231 + gen_farith3(ctx, &gen_op_cmptle, ra, rb, rc);
  1232 + break;
  1233 + case 0x2C:
  1234 + /* XXX: incorrect */
  1235 + if (fn11 == 0x2AC) {
  1236 + /* CVTST */
  1237 + gen_farith2(ctx, &gen_op_cvtst, rb, rc);
  1238 + } else {
  1239 + /* CVTTS */
  1240 + gen_farith2(ctx, &gen_op_cvtts, rb, rc);
  1241 + }
  1242 + break;
  1243 + case 0x2F:
  1244 + /* CVTTQ */
  1245 + gen_farith2(ctx, &gen_op_cvttq, rb, rc);
  1246 + break;
  1247 + case 0x3C:
  1248 + /* CVTQS */
  1249 + gen_farith2(ctx, &gen_op_cvtqs, rb, rc);
  1250 + break;
  1251 + case 0x3E:
  1252 + /* CVTQT */
  1253 + gen_farith2(ctx, &gen_op_cvtqt, rb, rc);
  1254 + break;
  1255 + default:
  1256 + goto invalid_opc;
  1257 + }
  1258 + break;
  1259 + case 0x17:
  1260 + switch (fn11) {
  1261 + case 0x010:
  1262 + /* CVTLQ */
  1263 + gen_farith2(ctx, &gen_op_cvtlq, rb, rc);
  1264 + break;
  1265 + case 0x020:
  1266 + /* CPYS */
  1267 + if (ra == rb) {
  1268 + if (ra == 31 && rc == 31) {
  1269 + /* FNOP */
  1270 + gen_op_nop();
  1271 + } else {
  1272 + /* FMOV */
  1273 + gen_load_fir(ctx, rb, 0);
  1274 + gen_store_fir(ctx, rc, 0);
  1275 + }
  1276 + } else {
  1277 + gen_farith3(ctx, &gen_op_cpys, ra, rb, rc);
  1278 + }
  1279 + break;
  1280 + case 0x021:
  1281 + /* CPYSN */
  1282 + gen_farith2(ctx, &gen_op_cpysn, rb, rc);
  1283 + break;
  1284 + case 0x022:
  1285 + /* CPYSE */
  1286 + gen_farith2(ctx, &gen_op_cpyse, rb, rc);
  1287 + break;
  1288 + case 0x024:
  1289 + /* MT_FPCR */
  1290 + gen_load_fir(ctx, ra, 0);
  1291 + gen_op_store_fpcr();
  1292 + break;
  1293 + case 0x025:
  1294 + /* MF_FPCR */
  1295 + gen_op_load_fpcr();
  1296 + gen_store_fir(ctx, ra, 0);
  1297 + break;
  1298 + case 0x02A:
  1299 + /* FCMOVEQ */
  1300 + gen_fcmov(ctx, &gen_op_cmpfeq, ra, rb, rc);
  1301 + break;
  1302 + case 0x02B:
  1303 + /* FCMOVNE */
  1304 + gen_fcmov(ctx, &gen_op_cmpfne, ra, rb, rc);
  1305 + break;
  1306 + case 0x02C:
  1307 + /* FCMOVLT */
  1308 + gen_fcmov(ctx, &gen_op_cmpflt, ra, rb, rc);
  1309 + break;
  1310 + case 0x02D:
  1311 + /* FCMOVGE */
  1312 + gen_fcmov(ctx, &gen_op_cmpfge, ra, rb, rc);
  1313 + break;
  1314 + case 0x02E:
  1315 + /* FCMOVLE */
  1316 + gen_fcmov(ctx, &gen_op_cmpfle, ra, rb, rc);
  1317 + break;
  1318 + case 0x02F:
  1319 + /* FCMOVGT */
  1320 + gen_fcmov(ctx, &gen_op_cmpfgt, ra, rb, rc);
  1321 + break;
  1322 + case 0x030:
  1323 + /* CVTQL */
  1324 + gen_farith2(ctx, &gen_op_cvtql, rb, rc);
  1325 + break;
  1326 + case 0x130:
  1327 + /* CVTQL/V */
  1328 + gen_farith2(ctx, &gen_op_cvtqlv, rb, rc);
  1329 + break;
  1330 + case 0x530:
  1331 + /* CVTQL/SV */
  1332 + gen_farith2(ctx, &gen_op_cvtqlsv, rb, rc);
  1333 + break;
  1334 + default:
  1335 + goto invalid_opc;
  1336 + }
  1337 + break;
  1338 + case 0x18:
  1339 + switch ((uint16_t)disp16) {
  1340 + case 0x0000:
  1341 + /* TRAPB */
  1342 + /* No-op. Just exit from the current tb */
  1343 + ret = 2;
  1344 + break;
  1345 + case 0x0400:
  1346 + /* EXCB */
  1347 + /* No-op. Just exit from the current tb */
  1348 + ret = 2;
  1349 + break;
  1350 + case 0x4000:
  1351 + /* MB */
  1352 + /* No-op */
  1353 + break;
  1354 + case 0x4400:
  1355 + /* WMB */
  1356 + /* No-op */
  1357 + break;
  1358 + case 0x8000:
  1359 + /* FETCH */
  1360 + /* No-op */
  1361 + break;
  1362 + case 0xA000:
  1363 + /* FETCH_M */
  1364 + /* No-op */
  1365 + break;
  1366 + case 0xC000:
  1367 + /* RPCC */
  1368 + gen_op_load_pcc();
  1369 + gen_store_ir(ctx, ra, 0);
  1370 + break;
  1371 + case 0xE000:
  1372 + /* RC */
  1373 + gen_op_load_irf();
  1374 + gen_store_ir(ctx, ra, 0);
  1375 + gen_op_clear_irf();
  1376 + break;
  1377 + case 0xE800:
  1378 + /* ECB */
  1379 + /* XXX: TODO: evict tb cache at address rb */
  1380 +#if 0
  1381 + ret = 2;
  1382 +#else
  1383 + goto invalid_opc;
  1384 +#endif
  1385 + break;
  1386 + case 0xF000:
  1387 + /* RS */
  1388 + gen_op_load_irf();
  1389 + gen_store_ir(ctx, ra, 0);
  1390 + gen_op_set_irf();
  1391 + break;
  1392 + case 0xF800:
  1393 + /* WH64 */
  1394 + /* No-op */
  1395 + break;
  1396 + default:
  1397 + goto invalid_opc;
  1398 + }
  1399 + break;
  1400 + case 0x19:
  1401 + /* HW_MFPR (PALcode) */
  1402 +#if defined (CONFIG_USER_ONLY)
  1403 + goto invalid_opc;
  1404 +#else
  1405 + if (!ctx->pal_mode)
  1406 + goto invalid_opc;
  1407 + gen_op_mfpr(insn & 0xFF);
  1408 + gen_store_ir(ctx, ra, 0);
  1409 + break;
  1410 +#endif
  1411 + case 0x1A:
  1412 + gen_load_ir(ctx, rb, 0);
  1413 + if (ra != 31) {
  1414 + gen_set_uT1(ctx, ctx->pc);
  1415 + gen_store_ir(ctx, ra, 1);
  1416 + }
  1417 + gen_op_branch();
  1418 + /* Those four jumps only differ by the branch prediction hint */
  1419 + switch (fn2) {
  1420 + case 0x0:
  1421 + /* JMP */
  1422 + break;
  1423 + case 0x1:
  1424 + /* JSR */
  1425 + break;
  1426 + case 0x2:
  1427 + /* RET */
  1428 + break;
  1429 + case 0x3:
  1430 + /* JSR_COROUTINE */
  1431 + break;
  1432 + }
  1433 + ret = 1;
  1434 + break;
  1435 + case 0x1B:
  1436 + /* HW_LD (PALcode) */
  1437 +#if defined (CONFIG_USER_ONLY)
  1438 + goto invalid_opc;
  1439 +#else
  1440 + if (!ctx->pal_mode)
  1441 + goto invalid_opc;
  1442 + gen_load_ir(ctx, rb, 0);
  1443 + gen_set_sT1(ctx, disp12);
  1444 + gen_op_addq();
  1445 + switch ((insn >> 12) & 0xF) {
  1446 + case 0x0:
  1447 + /* Longword physical access */
  1448 + gen_op_ldl_raw();
  1449 + break;
  1450 + case 0x1:
  1451 + /* Quadword physical access */
  1452 + gen_op_ldq_raw();
  1453 + break;
  1454 + case 0x2:
  1455 + /* Longword physical access with lock */
  1456 + gen_op_ldl_l_raw();
  1457 + break;
  1458 + case 0x3:
  1459 + /* Quadword physical access with lock */
  1460 + gen_op_ldq_l_raw();
  1461 + break;
  1462 + case 0x4:
  1463 + /* Longword virtual PTE fetch */
  1464 + gen_op_ldl_kernel();
  1465 + break;
  1466 + case 0x5:
  1467 + /* Quadword virtual PTE fetch */
  1468 + gen_op_ldq_kernel();
  1469 + break;
  1470 + case 0x6:
  1471 + /* Invalid */
  1472 + goto invalid_opc;
  1473 + case 0x7:
  1474 + /* Invalid */
  1475 + goto invalid_opc;
  1476 + case 0x8:
  1477 + /* Longword virtual access */
  1478 + gen_op_ld_phys_to_virt();
  1479 + gen_op_ldl_raw();
  1480 + break;
  1481 + case 0x9:
  1482 + /* Quadword virtual access */
  1483 + gen_op_ld_phys_to_virt();
  1484 + gen_op_ldq_raw();
  1485 + break;
  1486 + case 0xA:
  1487 + /* Longword virtual access with protection check */
  1488 + gen_ldl(ctx);
  1489 + break;
  1490 + case 0xB:
  1491 + /* Quadword virtual access with protection check */
  1492 + gen_ldq(ctx);
  1493 + break;
  1494 + case 0xC:
  1495 + /* Longword virtual access with altenate access mode */
  1496 + gen_op_set_alt_mode();
  1497 + gen_op_ld_phys_to_virt();
  1498 + gen_op_ldl_raw();
  1499 + gen_op_restore_mode();
  1500 + break;
  1501 + case 0xD:
  1502 + /* Quadword virtual access with altenate access mode */
  1503 + gen_op_set_alt_mode();
  1504 + gen_op_ld_phys_to_virt();
  1505 + gen_op_ldq_raw();
  1506 + gen_op_restore_mode();
  1507 + break;
  1508 + case 0xE:
  1509 + /* Longword virtual access with alternate access mode and
  1510 + * protection checks
  1511 + */
  1512 + gen_op_set_alt_mode();
  1513 + gen_op_ldl_data();
  1514 + gen_op_restore_mode();
  1515 + break;
  1516 + case 0xF:
  1517 + /* Quadword virtual access with alternate access mode and
  1518 + * protection checks
  1519 + */
  1520 + gen_op_set_alt_mode();
  1521 + gen_op_ldq_data();
  1522 + gen_op_restore_mode();
  1523 + break;
  1524 + }
  1525 + gen_store_ir(ctx, ra, 1);
  1526 + break;
  1527 +#endif
  1528 + case 0x1C:
  1529 + switch (fn7) {
  1530 + case 0x00:
  1531 + /* SEXTB */
  1532 + if (!(ctx->amask & AMASK_BWX))
  1533 + goto invalid_opc;
  1534 + gen_arith2(ctx, &gen_op_sextb, rb, rc, islit, lit);
  1535 + break;
  1536 + case 0x01:
  1537 + /* SEXTW */
  1538 + if (!(ctx->amask & AMASK_BWX))
  1539 + goto invalid_opc;
  1540 + gen_arith2(ctx, &gen_op_sextw, rb, rc, islit, lit);
  1541 + break;
  1542 + case 0x30:
  1543 + /* CTPOP */
  1544 + if (!(ctx->amask & AMASK_CIX))
  1545 + goto invalid_opc;
  1546 + gen_arith2(ctx, &gen_op_ctpop, rb, rc, 0, 0);
  1547 + break;
  1548 + case 0x31:
  1549 + /* PERR */
  1550 + if (!(ctx->amask & AMASK_MVI))
  1551 + goto invalid_opc;
  1552 + /* XXX: TODO */
  1553 + goto invalid_opc;
  1554 + break;
  1555 + case 0x32:
  1556 + /* CTLZ */
  1557 + if (!(ctx->amask & AMASK_CIX))
  1558 + goto invalid_opc;
  1559 + gen_arith2(ctx, &gen_op_ctlz, rb, rc, 0, 0);
  1560 + break;
  1561 + case 0x33:
  1562 + /* CTTZ */
  1563 + if (!(ctx->amask & AMASK_CIX))
  1564 + goto invalid_opc;
  1565 + gen_arith2(ctx, &gen_op_cttz, rb, rc, 0, 0);
  1566 + break;
  1567 + case 0x34:
  1568 + /* UNPKBW */
  1569 + if (!(ctx->amask & AMASK_MVI))
  1570 + goto invalid_opc;
  1571 + /* XXX: TODO */
  1572 + goto invalid_opc;
  1573 + break;
  1574 + case 0x35:
  1575 + /* UNPKWL */
  1576 + if (!(ctx->amask & AMASK_MVI))
  1577 + goto invalid_opc;
  1578 + /* XXX: TODO */
  1579 + goto invalid_opc;
  1580 + break;
  1581 + case 0x36:
  1582 + /* PKWB */
  1583 + if (!(ctx->amask & AMASK_MVI))
  1584 + goto invalid_opc;
  1585 + /* XXX: TODO */
  1586 + goto invalid_opc;
  1587 + break;
  1588 + case 0x37:
  1589 + /* PKLB */
  1590 + if (!(ctx->amask & AMASK_MVI))
  1591 + goto invalid_opc;
  1592 + /* XXX: TODO */
  1593 + goto invalid_opc;
  1594 + break;
  1595 + case 0x38:
  1596 + /* MINSB8 */
  1597 + if (!(ctx->amask & AMASK_MVI))
  1598 + goto invalid_opc;
  1599 + /* XXX: TODO */
  1600 + goto invalid_opc;
  1601 + break;
  1602 + case 0x39:
  1603 + /* MINSW4 */
  1604 + if (!(ctx->amask & AMASK_MVI))
  1605 + goto invalid_opc;
  1606 + /* XXX: TODO */
  1607 + goto invalid_opc;
  1608 + break;
  1609 + case 0x3A:
  1610 + /* MINUB8 */
  1611 + if (!(ctx->amask & AMASK_MVI))
  1612 + goto invalid_opc;
  1613 + /* XXX: TODO */
  1614 + goto invalid_opc;
  1615 + break;
  1616 + case 0x3B:
  1617 + /* MINUW4 */
  1618 + if (!(ctx->amask & AMASK_MVI))
  1619 + goto invalid_opc;
  1620 + /* XXX: TODO */
  1621 + goto invalid_opc;
  1622 + break;
  1623 + case 0x3C:
  1624 + /* MAXUB8 */
  1625 + if (!(ctx->amask & AMASK_MVI))
  1626 + goto invalid_opc;
  1627 + /* XXX: TODO */
  1628 + goto invalid_opc;
  1629 + break;
  1630 + case 0x3D:
  1631 + /* MAXUW4 */
  1632 + if (!(ctx->amask & AMASK_MVI))
  1633 + goto invalid_opc;
  1634 + /* XXX: TODO */
  1635 + goto invalid_opc;
  1636 + break;
  1637 + case 0x3E:
  1638 + /* MAXSB8 */
  1639 + if (!(ctx->amask & AMASK_MVI))
  1640 + goto invalid_opc;
  1641 + /* XXX: TODO */
  1642 + goto invalid_opc;
  1643 + break;
  1644 + case 0x3F:
  1645 + /* MAXSW4 */
  1646 + if (!(ctx->amask & AMASK_MVI))
  1647 + goto invalid_opc;
  1648 + /* XXX: TODO */
  1649 + goto invalid_opc;
  1650 + break;
  1651 + case 0x70:
  1652 + /* FTOIT */
  1653 + if (!(ctx->amask & AMASK_FIX))
  1654 + goto invalid_opc;
  1655 + gen_fti(ctx, &gen_op_ftoit, ra, rb);
  1656 + break;
  1657 + case 0x78:
  1658 + /* FTOIS */
  1659 + if (!(ctx->amask & AMASK_FIX))
  1660 + goto invalid_opc;
  1661 + gen_fti(ctx, &gen_op_ftois, ra, rb);
  1662 + break;
  1663 + default:
  1664 + goto invalid_opc;
  1665 + }
  1666 + break;
  1667 + case 0x1D:
  1668 + /* HW_MTPR (PALcode) */
  1669 +#if defined (CONFIG_USER_ONLY)
  1670 + goto invalid_opc;
  1671 +#else
  1672 + if (!ctx->pal_mode)
  1673 + goto invalid_opc;
  1674 + gen_load_ir(ctx, ra, 0);
  1675 + gen_op_mtpr(insn & 0xFF);
  1676 + ret = 2;
  1677 + break;
  1678 +#endif
  1679 + case 0x1E:
  1680 + /* HW_REI (PALcode) */
  1681 +#if defined (CONFIG_USER_ONLY)
  1682 + goto invalid_opc;
  1683 +#else
  1684 + if (!ctx->pal_mode)
  1685 + goto invalid_opc;
  1686 + if (rb == 31) {
  1687 + /* "Old" alpha */
  1688 + gen_op_hw_rei();
  1689 + } else {
  1690 + gen_load_ir(ctx, rb, 0);
  1691 + gen_set_uT1(ctx, (((int64_t)insn << 51) >> 51));
  1692 + gen_op_addq();
  1693 + gen_op_hw_ret();
  1694 + }
  1695 + ret = 2;
  1696 + break;
  1697 +#endif
  1698 + case 0x1F:
  1699 + /* HW_ST (PALcode) */
  1700 +#if defined (CONFIG_USER_ONLY)
  1701 + goto invalid_opc;
  1702 +#else
  1703 + if (!ctx->pal_mode)
  1704 + goto invalid_opc;
  1705 + gen_load_ir(ctx, rb, 0);
  1706 + gen_set_sT1(ctx, disp12);
  1707 + gen_op_addq();
  1708 + gen_load_ir(ctx, ra, 1);
  1709 + switch ((insn >> 12) & 0xF) {
  1710 + case 0x0:
  1711 + /* Longword physical access */
  1712 + gen_op_stl_raw();
  1713 + break;
  1714 + case 0x1:
  1715 + /* Quadword physical access */
  1716 + gen_op_stq_raw();
  1717 + break;
  1718 + case 0x2:
  1719 + /* Longword physical access with lock */
  1720 + gen_op_stl_c_raw();
  1721 + break;
  1722 + case 0x3:
  1723 + /* Quadword physical access with lock */
  1724 + gen_op_stq_c_raw();
  1725 + break;
  1726 + case 0x4:
  1727 + /* Longword virtual access */
  1728 + gen_op_st_phys_to_virt();
  1729 + gen_op_stl_raw();
  1730 + break;
  1731 + case 0x5:
  1732 + /* Quadword virtual access */
  1733 + gen_op_st_phys_to_virt();
  1734 + gen_op_stq_raw();
  1735 + break;
  1736 + case 0x6:
  1737 + /* Invalid */
  1738 + goto invalid_opc;
  1739 + case 0x7:
  1740 + /* Invalid */
  1741 + goto invalid_opc;
  1742 + case 0x8:
  1743 + /* Invalid */
  1744 + goto invalid_opc;
  1745 + case 0x9:
  1746 + /* Invalid */
  1747 + goto invalid_opc;
  1748 + case 0xA:
  1749 + /* Invalid */
  1750 + goto invalid_opc;
  1751 + case 0xB:
  1752 + /* Invalid */
  1753 + goto invalid_opc;
  1754 + case 0xC:
  1755 + /* Longword virtual access with alternate access mode */
  1756 + gen_op_set_alt_mode();
  1757 + gen_op_st_phys_to_virt();
  1758 + gen_op_ldl_raw();
  1759 + gen_op_restore_mode();
  1760 + break;
  1761 + case 0xD:
  1762 + /* Quadword virtual access with alternate access mode */
  1763 + gen_op_set_alt_mode();
  1764 + gen_op_st_phys_to_virt();
  1765 + gen_op_ldq_raw();
  1766 + gen_op_restore_mode();
  1767 + break;
  1768 + case 0xE:
  1769 + /* Invalid */
  1770 + goto invalid_opc;
  1771 + case 0xF:
  1772 + /* Invalid */
  1773 + goto invalid_opc;
  1774 + }
  1775 + ret = 2;
  1776 + break;
  1777 +#endif
  1778 + case 0x20:
  1779 + /* LDF */
  1780 +#if 0 // TODO
  1781 + gen_load_fmem(ctx, &gen_ldf, ra, rb, disp16);
  1782 +#else
  1783 + goto invalid_opc;
  1784 +#endif
  1785 + break;
  1786 + case 0x21:
  1787 + /* LDG */
  1788 +#if 0 // TODO
  1789 + gen_load_fmem(ctx, &gen_ldg, ra, rb, disp16);
  1790 +#else
  1791 + goto invalid_opc;
  1792 +#endif
  1793 + break;
  1794 + case 0x22:
  1795 + /* LDS */
  1796 + gen_load_fmem(ctx, &gen_lds, ra, rb, disp16);
  1797 + break;
  1798 + case 0x23:
  1799 + /* LDT */
  1800 + gen_load_fmem(ctx, &gen_ldt, ra, rb, disp16);
  1801 + break;
  1802 + case 0x24:
  1803 + /* STF */
  1804 +#if 0 // TODO
  1805 + gen_store_fmem(ctx, &gen_stf, ra, rb, disp16);
  1806 +#else
  1807 + goto invalid_opc;
  1808 +#endif
  1809 + break;
  1810 + case 0x25:
  1811 + /* STG */
  1812 +#if 0 // TODO
  1813 + gen_store_fmem(ctx, &gen_stg, ra, rb, disp16);
  1814 +#else
  1815 + goto invalid_opc;
  1816 +#endif
  1817 + break;
  1818 + case 0x26:
  1819 + /* STS */
  1820 + gen_store_fmem(ctx, &gen_sts, ra, rb, disp16);
  1821 + break;
  1822 + case 0x27:
  1823 + /* STT */
  1824 + gen_store_fmem(ctx, &gen_stt, ra, rb, disp16);
  1825 + break;
  1826 + case 0x28:
  1827 + /* LDL */
  1828 + gen_load_mem(ctx, &gen_ldl, ra, rb, disp16, 0);
  1829 + break;
  1830 + case 0x29:
  1831 + /* LDQ */
  1832 + gen_load_mem(ctx, &gen_ldq, ra, rb, disp16, 0);
  1833 + break;
  1834 + case 0x2A:
  1835 + /* LDL_L */
  1836 + gen_load_mem(ctx, &gen_ldl_l, ra, rb, disp16, 0);
  1837 + break;
  1838 + case 0x2B:
  1839 + /* LDQ_L */
  1840 + gen_load_mem(ctx, &gen_ldq_l, ra, rb, disp16, 0);
  1841 + break;
  1842 + case 0x2C:
  1843 + /* STL */
  1844 + gen_store_mem(ctx, &gen_stl, ra, rb, disp16, 0);
  1845 + break;
  1846 + case 0x2D:
  1847 + /* STQ */
  1848 + gen_store_mem(ctx, &gen_stq, ra, rb, disp16, 0);
  1849 + break;
  1850 + case 0x2E:
  1851 + /* STL_C */
  1852 + gen_store_mem(ctx, &gen_stl_c, ra, rb, disp16, 0);
  1853 + break;
  1854 + case 0x2F:
  1855 + /* STQ_C */
  1856 + gen_store_mem(ctx, &gen_stq_c, ra, rb, disp16, 0);
  1857 + break;
  1858 + case 0x30:
  1859 + /* BR */
  1860 + gen_set_uT0(ctx, ctx->pc);
  1861 + gen_store_ir(ctx, ra, 0);
  1862 + if (disp21 != 0) {
  1863 + gen_set_sT1(ctx, disp21 << 2);
  1864 + gen_op_addq();
  1865 + }
  1866 + gen_op_branch();
  1867 + ret = 1;
  1868 + break;
  1869 + case 0x31:
  1870 + /* FBEQ */
  1871 + gen_fbcond(ctx, &gen_op_cmpfeq, ra, disp16);
  1872 + ret = 1;
  1873 + break;
  1874 + case 0x32:
  1875 + /* FBLT */
  1876 + gen_fbcond(ctx, &gen_op_cmpflt, ra, disp16);
  1877 + ret = 1;
  1878 + break;
  1879 + case 0x33:
  1880 + /* FBLE */
  1881 + gen_fbcond(ctx, &gen_op_cmpfle, ra, disp16);
  1882 + ret = 1;
  1883 + break;
  1884 + case 0x34:
  1885 + /* BSR */
  1886 + gen_set_uT0(ctx, ctx->pc);
  1887 + gen_store_ir(ctx, ra, 0);
  1888 + if (disp21 != 0) {
  1889 + gen_set_sT1(ctx, disp21 << 2);
  1890 + gen_op_addq();
  1891 + }
  1892 + gen_op_branch();
  1893 + ret = 1;
  1894 + break;
  1895 + case 0x35:
  1896 + /* FBNE */
  1897 + gen_fbcond(ctx, &gen_op_cmpfne, ra, disp16);
  1898 + ret = 1;
  1899 + break;
  1900 + case 0x36:
  1901 + /* FBGE */
  1902 + gen_fbcond(ctx, &gen_op_cmpfge, ra, disp16);
  1903 + ret = 1;
  1904 + break;
  1905 + case 0x37:
  1906 + /* FBGT */
  1907 + gen_fbcond(ctx, &gen_op_cmpfgt, ra, disp16);
  1908 + ret = 1;
  1909 + break;
  1910 + case 0x38:
  1911 + /* BLBC */
  1912 + gen_bcond(ctx, &gen_op_cmplbc, ra, disp16);
  1913 + ret = 1;
  1914 + break;
  1915 + case 0x39:
  1916 + /* BEQ */
  1917 + gen_bcond(ctx, &gen_op_cmpeqz, ra, disp16);
  1918 + ret = 1;
  1919 + break;
  1920 + case 0x3A:
  1921 + /* BLT */
  1922 + gen_bcond(ctx, &gen_op_cmpltz, ra, disp16);
  1923 + ret = 1;
  1924 + break;
  1925 + case 0x3B:
  1926 + /* BLE */
  1927 + gen_bcond(ctx, &gen_op_cmplez, ra, disp16);
  1928 + ret = 1;
  1929 + break;
  1930 + case 0x3C:
  1931 + /* BLBS */
  1932 + gen_bcond(ctx, &gen_op_cmplbs, ra, disp16);
  1933 + ret = 1;
  1934 + break;
  1935 + case 0x3D:
  1936 + /* BNE */
  1937 + gen_bcond(ctx, &gen_op_cmpnez, ra, disp16);
  1938 + ret = 1;
  1939 + break;
  1940 + case 0x3E:
  1941 + /* BGE */
  1942 + gen_bcond(ctx, &gen_op_cmpgez, ra, disp16);
  1943 + ret = 1;
  1944 + break;
  1945 + case 0x3F:
  1946 + /* BGT */
  1947 + gen_bcond(ctx, &gen_op_cmpgtz, ra, disp16);
  1948 + ret = 1;
  1949 + break;
  1950 + invalid_opc:
  1951 + gen_invalid(ctx);
  1952 + ret = 3;
  1953 + break;
  1954 + }
  1955 +
  1956 + return ret;
  1957 +}
  1958 +
  1959 +int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
  1960 + int search_pc)
  1961 +{
  1962 +#if defined ALPHA_DEBUG_DISAS
  1963 + static int insn_count;
  1964 +#endif
  1965 + DisasContext ctx, *ctxp = &ctx;
  1966 + target_ulong pc_start;
  1967 + uint32_t insn;
  1968 + uint16_t *gen_opc_end;
  1969 + int j, lj = -1;
  1970 + int ret;
  1971 +
  1972 + pc_start = tb->pc;
  1973 + gen_opc_ptr = gen_opc_buf;
  1974 + gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
  1975 + gen_opparam_ptr = gen_opparam_buf;
  1976 + nb_gen_labels = 0;
  1977 + ctx.pc = pc_start;
  1978 + ctx.amask = env->amask;
  1979 +#if defined (CONFIG_USER_ONLY)
  1980 + ctx.mem_idx = 0;
  1981 +#else
  1982 + ctx.mem_idx = ((env->ps >> 3) & 3);
  1983 + ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1;
  1984 +#endif
  1985 + for (ret = 0; ret == 0;) {
  1986 + if (env->nb_breakpoints > 0) {
  1987 + for(j = 0; j < env->nb_breakpoints; j++) {
  1988 + if (env->breakpoints[j] == ctx.pc) {
  1989 + gen_excp(&ctx, EXCP_DEBUG, 0);
  1990 + break;
  1991 + }
  1992 + }
  1993 + }
  1994 + if (search_pc) {
  1995 + j = gen_opc_ptr - gen_opc_buf;
  1996 + if (lj < j) {
  1997 + lj++;
  1998 + while (lj < j)
  1999 + gen_opc_instr_start[lj++] = 0;
  2000 + gen_opc_pc[lj] = ctx.pc;
  2001 + gen_opc_instr_start[lj] = 1;
  2002 + }
  2003 + }
  2004 +#if defined ALPHA_DEBUG_DISAS
  2005 + insn_count++;
  2006 + if (logfile != NULL) {
  2007 + fprintf(logfile, "pc %016lx mem_idx\n", ctx.pc, ctx.mem_idx);
  2008 + }
  2009 +#endif
  2010 + insn = ldl_code(ctx.pc);
  2011 +#if defined ALPHA_DEBUG_DISAS
  2012 + insn_count++;
  2013 + if (logfile != NULL) {
  2014 + fprintf(logfile, "opcode %08x %d\n", insn, insn_count);
  2015 + }
  2016 +#endif
  2017 + ctx.pc += 4;
  2018 + ret = translate_one(ctxp, insn);
  2019 + if (ret != 0)
  2020 + break;
  2021 + /* if we reach a page boundary or are single stepping, stop
  2022 + * generation
  2023 + */
  2024 + if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) ||
  2025 + (env->singlestep_enabled)) {
  2026 + break;
  2027 + }
  2028 +#if defined (DO_SINGLE_STEP)
  2029 + break;
  2030 +#endif
  2031 + }
  2032 + if (ret != 1 && ret != 3) {
  2033 + gen_update_pc(&ctx);
  2034 + }
  2035 + gen_op_reset_T0();
  2036 +#if defined (DO_TB_FLUSH)
  2037 + gen_op_tb_flush();
  2038 +#endif
  2039 + /* Generate the return instruction */
  2040 + gen_op_exit_tb();
  2041 + *gen_opc_ptr = INDEX_op_end;
  2042 + if (search_pc) {
  2043 + j = gen_opc_ptr - gen_opc_buf;
  2044 + lj++;
  2045 + while (lj <= j)
  2046 + gen_opc_instr_start[lj++] = 0;
  2047 + tb->size = 0;
  2048 + } else {
  2049 + tb->size = ctx.pc - pc_start;
  2050 + }
  2051 +#if defined ALPHA_DEBUG_DISAS
  2052 + if (loglevel & CPU_LOG_TB_CPU) {
  2053 + cpu_dump_state(env, logfile, fprintf, 0);
  2054 + }
  2055 + if (loglevel & CPU_LOG_TB_IN_ASM) {
  2056 + fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
  2057 + target_disas(logfile, pc_start, ctx.pc - pc_start, 1);
  2058 + fprintf(logfile, "\n");
  2059 + }
  2060 + if (loglevel & CPU_LOG_TB_OP) {
  2061 + fprintf(logfile, "OP:\n");
  2062 + dump_ops(gen_opc_buf, gen_opparam_buf);
  2063 + fprintf(logfile, "\n");
  2064 + }
  2065 +#endif
  2066 +
  2067 + return 0;
  2068 +}
  2069 +
  2070 +int gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
  2071 +{
  2072 + return gen_intermediate_code_internal(env, tb, 0);
  2073 +}
  2074 +
  2075 +int gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
  2076 +{
  2077 + return gen_intermediate_code_internal(env, tb, 1);
  2078 +}
  2079 +
  2080 +CPUAlphaState * cpu_alpha_init (void)
  2081 +{
  2082 + CPUAlphaState *env;
  2083 + uint64_t hwpcb;
  2084 +
  2085 + env = qemu_mallocz(sizeof(CPUAlphaState));
  2086 + if (!env)
  2087 + return NULL;
  2088 + cpu_exec_init(env);
  2089 + tlb_flush(env, 1);
  2090 + /* XXX: should not be hardcoded */
  2091 + env->implver = IMPLVER_2106x;
  2092 + env->ps = 0x1F00;
  2093 +#if defined (CONFIG_USER_ONLY)
  2094 + env->ps |= 1 << 3;
  2095 +#endif
  2096 + pal_init(env);
  2097 + /* Initialize IPR */
  2098 + hwpcb = env->ipr[IPR_PCBB];
  2099 + env->ipr[IPR_ASN] = 0;
  2100 + env->ipr[IPR_ASTEN] = 0;
  2101 + env->ipr[IPR_ASTSR] = 0;
  2102 + env->ipr[IPR_DATFX] = 0;
  2103 + /* XXX: fix this */
  2104 + // env->ipr[IPR_ESP] = ldq_raw(hwpcb + 8);
  2105 + // env->ipr[IPR_KSP] = ldq_raw(hwpcb + 0);
  2106 + // env->ipr[IPR_SSP] = ldq_raw(hwpcb + 16);
  2107 + // env->ipr[IPR_USP] = ldq_raw(hwpcb + 24);
  2108 + env->ipr[IPR_FEN] = 0;
  2109 + env->ipr[IPR_IPL] = 31;
  2110 + env->ipr[IPR_MCES] = 0;
  2111 + env->ipr[IPR_PERFMON] = 0; /* Implementation specific */
  2112 + // env->ipr[IPR_PTBR] = ldq_raw(hwpcb + 32);
  2113 + env->ipr[IPR_SISR] = 0;
  2114 + env->ipr[IPR_VIRBND] = -1ULL;
  2115 +
  2116 + return env;
  2117 +}