diff options
Diffstat (limited to 'target-alpha/op.c')
-rw-r--r-- | target-alpha/op.c | 1103 |
1 files changed, 1103 insertions, 0 deletions
diff --git a/target-alpha/op.c b/target-alpha/op.c new file mode 100644 index 0000000000..8a22c5c087 --- /dev/null +++ b/target-alpha/op.c @@ -0,0 +1,1103 @@ +/* + * Alpha emulation cpu micro-operations for qemu. + * + * Copyright (c) 2007 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define DEBUG_OP + +#include "config.h" +#include "exec.h" + +#include "op_helper.h" + +#define REG 0 +#include "op_template.h" + +#define REG 1 +#include "op_template.h" + +#define REG 2 +#include "op_template.h" + +#define REG 3 +#include "op_template.h" + +#define REG 4 +#include "op_template.h" + +#define REG 5 +#include "op_template.h" + +#define REG 6 +#include "op_template.h" + +#define REG 7 +#include "op_template.h" + +#define REG 8 +#include "op_template.h" + +#define REG 9 +#include "op_template.h" + +#define REG 10 +#include "op_template.h" + +#define REG 11 +#include "op_template.h" + +#define REG 12 +#include "op_template.h" + +#define REG 13 +#include "op_template.h" + +#define REG 14 +#include "op_template.h" + +#define REG 15 +#include "op_template.h" + +#define REG 16 +#include "op_template.h" + +#define REG 17 +#include "op_template.h" + +#define REG 18 +#include "op_template.h" + +#define REG 19 +#include "op_template.h" + +#define REG 20 +#include "op_template.h" + +#define REG 21 +#include "op_template.h" + +#define REG 22 +#include "op_template.h" + +#define REG 23 +#include "op_template.h" + +#define REG 24 +#include "op_template.h" + +#define REG 25 +#include "op_template.h" + +#define REG 26 +#include "op_template.h" + +#define REG 27 +#include "op_template.h" + +#define REG 28 +#include "op_template.h" + +#define REG 29 +#include "op_template.h" + +#define REG 30 +#include "op_template.h" + +#define REG 31 +#include "op_template.h" + +/* Debug stuff */ +void OPPROTO op_no_op (void) +{ +#if !defined (DEBUG_OP) + __asm__ __volatile__("nop" : : : "memory"); +#endif + RETURN(); +} + +void OPPROTO op_tb_flush (void) +{ + helper_tb_flush(); + RETURN(); +} + +/* Load and stores */ +#define MEMSUFFIX _raw +#include "op_mem.h" +#if !defined(CONFIG_USER_ONLY) +#define MEMSUFFIX _user +#include "op_mem.h" +#define MEMSUFFIX _kernel +#include "op_mem.h" +/* Those are used for supervisor, executive and pal modes */ +#define MEMSUFFIX _data +#include "op_mem.h" +#endif + +/* Special operation for load and store */ +void OPPROTO op_n7 (void) +{ + T0 &= ~(uint64_t)0x7; + RETURN(); +} + +/* Misc */ +void OPPROTO op_excp (void) +{ + helper_excp(PARAM(1), PARAM(2)); + RETURN(); +} + +void OPPROTO op_load_amask (void) +{ + helper_amask(); + RETURN(); +} + +void OPPROTO op_load_pcc (void) +{ + helper_load_pcc(); + RETURN(); +} + +void OPPROTO op_load_implver (void) +{ + helper_load_implver(); + RETURN(); +} + +void OPPROTO op_load_fpcr (void) +{ + helper_load_fpcr(); + RETURN(); +} + +void OPPROTO op_store_fpcr (void) +{ + helper_store_fpcr(); + RETURN(); +} + +void OPPROTO op_load_irf (void) +{ + helper_load_irf(); + RETURN(); +} + +void OPPROTO op_set_irf (void) +{ + helper_set_irf(); + RETURN(); +} + +void OPPROTO op_clear_irf (void) +{ + helper_clear_irf(); + RETURN(); +} + +void OPPROTO op_exit_tb (void) +{ + EXIT_TB(); +} + +/* Arithmetic */ +void OPPROTO op_addq (void) +{ + T0 += T1; + RETURN(); +} + +void OPPROTO op_addqv (void) +{ + helper_addqv(); + RETURN(); +} + +void OPPROTO op_addl (void) +{ + T0 = (int64_t)((int32_t)(T0 + T1)); + RETURN(); +} + +void OPPROTO op_addlv (void) +{ + helper_addlv(); + RETURN(); +} + +void OPPROTO op_subq (void) +{ + T0 -= T1; + RETURN(); +} + +void OPPROTO op_subqv (void) +{ + helper_subqv(); + RETURN(); +} + +void OPPROTO op_subl (void) +{ + T0 = (int64_t)((int32_t)(T0 - T1)); + RETURN(); +} + +void OPPROTO op_sublv (void) +{ + helper_sublv(); + RETURN(); +} + +void OPPROTO op_s4 (void) +{ + T0 <<= 2; + RETURN(); +} + +void OPPROTO op_s8 (void) +{ + T0 <<= 3; + RETURN(); +} + +void OPPROTO op_mull (void) +{ + T0 = (int64_t)((int32_t)T0 * (int32_t)T1); + RETURN(); +} + +void OPPROTO op_mullv (void) +{ + helper_mullv(); + RETURN(); +} + +void OPPROTO op_mulq (void) +{ + T0 *= T1; + RETURN(); +} + +void OPPROTO op_mulqv (void) +{ + helper_mulqv(); + RETURN(); +} + +void OPPROTO op_umulh (void) +{ + helper_umulh(); + RETURN(); +} + +/* Logical */ +void OPPROTO op_and (void) +{ + T0 &= T1; + RETURN(); +} + +void OPPROTO op_bic (void) +{ + T0 &= ~T1; + RETURN(); +} + +void OPPROTO op_bis (void) +{ + T0 |= T1; + RETURN(); +} + +void OPPROTO op_eqv (void) +{ + T0 ^= ~T1; + RETURN(); +} + +void OPPROTO op_ornot (void) +{ + T0 |= ~T1; + RETURN(); +} + +void OPPROTO op_xor (void) +{ + T0 ^= T1; + RETURN(); +} + +void OPPROTO op_sll (void) +{ + T0 <<= T1; + RETURN(); +} + +void OPPROTO op_srl (void) +{ + T0 >>= T1; + RETURN(); +} + +void OPPROTO op_sra (void) +{ + T0 = (int64_t)T0 >> T1; + RETURN(); +} + +void OPPROTO op_sextb (void) +{ + T0 = (int64_t)((int8_t)T0); + RETURN(); +} + +void OPPROTO op_sextw (void) +{ + T0 = (int64_t)((int16_t)T0); + RETURN(); + +} + +void OPPROTO op_ctpop (void) +{ + helper_ctpop(); + RETURN(); +} + +void OPPROTO op_ctlz (void) +{ + helper_ctlz(); + RETURN(); +} + +void OPPROTO op_cttz (void) +{ + helper_cttz(); + RETURN(); +} + +void OPPROTO op_mskbl (void) +{ + helper_mskbl(); + RETURN(); +} + +void OPPROTO op_extbl (void) +{ + helper_extbl(); + RETURN(); +} + +void OPPROTO op_insbl (void) +{ + helper_insbl(); + RETURN(); +} + +void OPPROTO op_mskwl (void) +{ + helper_mskwl(); + RETURN(); +} + +void OPPROTO op_extwl (void) +{ + helper_extwl(); + RETURN(); +} + +void OPPROTO op_inswl (void) +{ + helper_inswl(); + RETURN(); +} + +void OPPROTO op_mskll (void) +{ + helper_mskll(); + RETURN(); +} + +void OPPROTO op_extll (void) +{ + helper_extll(); + RETURN(); +} + +void OPPROTO op_insll (void) +{ + helper_insll(); + RETURN(); +} + +void OPPROTO op_zap (void) +{ + helper_zap(); + RETURN(); +} + +void OPPROTO op_zapnot (void) +{ + helper_zapnot(); + RETURN(); +} + +void OPPROTO op_mskql (void) +{ + helper_mskql(); + RETURN(); +} + +void OPPROTO op_extql (void) +{ + helper_extql(); + RETURN(); +} + +void OPPROTO op_insql (void) +{ + helper_insql(); + RETURN(); +} + +void OPPROTO op_mskwh (void) +{ + helper_mskwh(); + RETURN(); +} + +void OPPROTO op_inswh (void) +{ + helper_inswh(); + RETURN(); +} + +void OPPROTO op_extwh (void) +{ + helper_extwh(); + RETURN(); +} + +void OPPROTO op_msklh (void) +{ + helper_msklh(); + RETURN(); +} + +void OPPROTO op_inslh (void) +{ + helper_inslh(); + RETURN(); +} + +void OPPROTO op_extlh (void) +{ + helper_extlh(); + RETURN(); +} + +void OPPROTO op_mskqh (void) +{ + helper_mskqh(); + RETURN(); +} + +void OPPROTO op_insqh (void) +{ + helper_insqh(); + RETURN(); +} + +void OPPROTO op_extqh (void) +{ + helper_extqh(); + RETURN(); +} + +/* Tests */ +void OPPROTO op_cmpult (void) +{ + if (T0 < T1) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmpule (void) +{ + if (T0 <= T1) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmpeq (void) +{ + if (T0 == T1) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmplt (void) +{ + if ((int64_t)T0 < (int64_t)T1) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmple (void) +{ + if ((int64_t)T0 <= (int64_t)T1) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmpbge (void) +{ + helper_cmpbge(); + RETURN(); +} + +void OPPROTO op_cmpeqz (void) +{ + if (T0 == 0) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmpnez (void) +{ + if (T0 != 0) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmpltz (void) +{ + if ((int64_t)T0 < 0) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmplez (void) +{ + if ((int64_t)T0 <= 0) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmpgtz (void) +{ + if ((int64_t)T0 > 0) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmpgez (void) +{ + if ((int64_t)T0 >= 0) + T0 = 1; + else + T0 = 0; + RETURN(); +} + +void OPPROTO op_cmplbs (void) +{ + T0 &= 1; + RETURN(); +} + +void OPPROTO op_cmplbc (void) +{ + T0 = (~T0) & 1; + RETURN(); +} + +/* Branches */ +void OPPROTO op_branch (void) +{ + env->pc = T0 & ~3; + RETURN(); +} + +void OPPROTO op_addq1 (void) +{ + T1 += T0; + RETURN(); +} + +#if 0 // Qemu does not know how to do this... +void OPPROTO op_bcond (void) +{ + if (T0) + env->pc = T1 & ~3; + else + env->pc = PARAM(1); + RETURN(); +} +#else +void OPPROTO op_bcond (void) +{ + if (T0) + env->pc = T1 & ~3; + else + env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2); + RETURN(); +} +#endif + +#if 0 // Qemu does not know how to do this... +void OPPROTO op_update_pc (void) +{ + env->pc = PARAM(1); + RETURN(); +} +#else +void OPPROTO op_update_pc (void) +{ + env->pc = ((uint64_t)PARAM(1) << 32) | (uint64_t)PARAM(2); + RETURN(); +} +#endif + +/* Optimization for 32 bits hosts architectures */ +void OPPROTO op_update_pc32 (void) +{ + env->pc = (uint64_t)PARAM(1); + RETURN(); +} + +/* IEEE floating point arithmetic */ +/* S floating (single) */ +void OPPROTO op_adds (void) +{ + FT0 = float32_add(FT0, FT1, &FP_STATUS); + RETURN(); +} + +void OPPROTO op_subs (void) +{ + FT0 = float32_sub(FT0, FT1, &FP_STATUS); + RETURN(); +} + +void OPPROTO op_muls (void) +{ + FT0 = float32_mul(FT0, FT1, &FP_STATUS); + RETURN(); +} + +void OPPROTO op_divs (void) +{ + FT0 = float32_div(FT0, FT1, &FP_STATUS); + RETURN(); +} + +void OPPROTO op_sqrts (void) +{ + helper_sqrts(); + RETURN(); +} + +void OPPROTO op_cpys (void) +{ + helper_cpys(); + RETURN(); +} + +void OPPROTO op_cpysn (void) +{ + helper_cpysn(); + RETURN(); +} + +void OPPROTO op_cpyse (void) +{ + helper_cpyse(); + RETURN(); +} + +void OPPROTO op_itofs (void) +{ + helper_itofs(); + RETURN(); +} + +void OPPROTO op_ftois (void) +{ + helper_ftois(); + RETURN(); +} + +/* T floating (double) */ +void OPPROTO op_addt (void) +{ + FT0 = float64_add(FT0, FT1, &FP_STATUS); + RETURN(); +} + +void OPPROTO op_subt (void) +{ + FT0 = float64_sub(FT0, FT1, &FP_STATUS); + RETURN(); +} + +void OPPROTO op_mult (void) +{ + FT0 = float64_mul(FT0, FT1, &FP_STATUS); + RETURN(); +} + +void OPPROTO op_divt (void) +{ + FT0 = float64_div(FT0, FT1, &FP_STATUS); + RETURN(); +} + +void OPPROTO op_sqrtt (void) +{ + helper_sqrtt(); + RETURN(); +} + +void OPPROTO op_cmptun (void) +{ + helper_cmptun(); + RETURN(); +} + +void OPPROTO op_cmpteq (void) +{ + helper_cmpteq(); + RETURN(); +} + +void OPPROTO op_cmptle (void) +{ + helper_cmptle(); + RETURN(); +} + +void OPPROTO op_cmptlt (void) +{ + helper_cmptlt(); + RETURN(); +} + +void OPPROTO op_itoft (void) +{ + helper_itoft(); + RETURN(); +} + +void OPPROTO op_ftoit (void) +{ + helper_ftoit(); + RETURN(); +} + +/* VAX floating point arithmetic */ +/* F floating */ +void OPPROTO op_addf (void) +{ + helper_addf(); + RETURN(); +} + +void OPPROTO op_subf (void) +{ + helper_subf(); + RETURN(); +} + +void OPPROTO op_mulf (void) +{ + helper_mulf(); + RETURN(); +} + +void OPPROTO op_divf (void) +{ + helper_divf(); + RETURN(); +} + +void OPPROTO op_sqrtf (void) +{ + helper_sqrtf(); + RETURN(); +} + +void OPPROTO op_cmpfeq (void) +{ + helper_cmpfeq(); + RETURN(); +} + +void OPPROTO op_cmpfne (void) +{ + helper_cmpfne(); + RETURN(); +} + +void OPPROTO op_cmpflt (void) +{ + helper_cmpflt(); + RETURN(); +} + +void OPPROTO op_cmpfle (void) +{ + helper_cmpfle(); + RETURN(); +} + +void OPPROTO op_cmpfgt (void) +{ + helper_cmpfgt(); + RETURN(); +} + +void OPPROTO op_cmpfge (void) +{ + helper_cmpfge(); + RETURN(); +} + +void OPPROTO op_itoff (void) +{ + helper_itoff(); + RETURN(); +} + +/* G floating */ +void OPPROTO op_addg (void) +{ + helper_addg(); + RETURN(); +} + +void OPPROTO op_subg (void) +{ + helper_subg(); + RETURN(); +} + +void OPPROTO op_mulg (void) +{ + helper_mulg(); + RETURN(); +} + +void OPPROTO op_divg (void) +{ + helper_divg(); + RETURN(); +} + +void OPPROTO op_sqrtg (void) +{ + helper_sqrtg(); + RETURN(); +} + +void OPPROTO op_cmpgeq (void) +{ + helper_cmpgeq(); + RETURN(); +} + +void OPPROTO op_cmpglt (void) +{ + helper_cmpglt(); + RETURN(); +} + +void OPPROTO op_cmpgle (void) +{ + helper_cmpgle(); + RETURN(); +} + +/* Floating point format conversion */ +void OPPROTO op_cvtst (void) +{ + FT0 = (float)FT0; + RETURN(); +} + +void OPPROTO op_cvtqs (void) +{ + helper_cvtqs(); + RETURN(); +} + +void OPPROTO op_cvtts (void) +{ + FT0 = (float)FT0; + RETURN(); +} + +void OPPROTO op_cvttq (void) +{ + helper_cvttq(); + RETURN(); +} + +void OPPROTO op_cvtqt (void) +{ + helper_cvtqt(); + RETURN(); +} + +void OPPROTO op_cvtqf (void) +{ + helper_cvtqf(); + RETURN(); +} + +void OPPROTO op_cvtgf (void) +{ + helper_cvtgf(); + RETURN(); +} + +void OPPROTO op_cvtgd (void) +{ + helper_cvtgd(); + RETURN(); +} + +void OPPROTO op_cvtgq (void) +{ + helper_cvtgq(); + RETURN(); +} + +void OPPROTO op_cvtqg (void) +{ + helper_cvtqg(); + RETURN(); +} + +void OPPROTO op_cvtdg (void) +{ + helper_cvtdg(); + RETURN(); +} + +void OPPROTO op_cvtlq (void) +{ + helper_cvtlq(); + RETURN(); +} + +void OPPROTO op_cvtql (void) +{ + helper_cvtql(); + RETURN(); +} + +void OPPROTO op_cvtqlv (void) +{ + helper_cvtqlv(); + RETURN(); +} + +void OPPROTO op_cvtqlsv (void) +{ + helper_cvtqlsv(); + RETURN(); +} + +/* PALcode support special instructions */ +#if !defined (CONFIG_USER_ONLY) +void OPPROTO op_hw_rei (void) +{ + env->pc = env->ipr[IPR_EXC_ADDR] & ~3; + env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1; + /* XXX: re-enable interrupts and memory mapping */ + RETURN(); +} + +void OPPROTO op_hw_ret (void) +{ + env->pc = T0 & ~3; + env->ipr[IPR_EXC_ADDR] = T0 & 1; + /* XXX: re-enable interrupts and memory mapping */ + RETURN(); +} + +void OPPROTO op_mfpr (void) +{ + helper_mfpr(PARAM(1)); + RETURN(); +} + +void OPPROTO op_mtpr (void) +{ + helper_mtpr(PARAM(1)); + RETURN(); +} + +void OPPROTO op_set_alt_mode (void) +{ + env->saved_mode = env->ps & 0xC; + env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC); + RETURN(); +} + +void OPPROTO op_restore_mode (void) +{ + env->ps = (env->ps & ~0xC) | env->saved_mode; + RETURN(); +} + +void OPPROTO op_ld_phys_to_virt (void) +{ + helper_ld_phys_to_virt(); + RETURN(); +} + +void OPPROTO op_st_phys_to_virt (void) +{ + helper_st_phys_to_virt(); + RETURN(); +} +#endif /* !defined (CONFIG_USER_ONLY) */ |