| /* |
| * 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 "host-utils.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(); |
| } |
| |
| /* Load and stores */ |
| #define MEMSUFFIX _raw |
| #include "op_mem.h" |
| #if !defined(CONFIG_USER_ONLY) |
| #define MEMSUFFIX _kernel |
| #include "op_mem.h" |
| #define MEMSUFFIX _executive |
| #include "op_mem.h" |
| #define MEMSUFFIX _supervisor |
| #include "op_mem.h" |
| #define MEMSUFFIX _user |
| #include "op_mem.h" |
| /* This is used for pal modes */ |
| #define MEMSUFFIX _data |
| #include "op_mem.h" |
| #endif |
| |
| /* Misc */ |
| void OPPROTO op_load_fpcr (void) |
| { |
| helper_load_fpcr(); |
| RETURN(); |
| } |
| |
| void OPPROTO op_store_fpcr (void) |
| { |
| helper_store_fpcr(); |
| RETURN(); |
| } |
| |
| /* Tests */ |
| #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 |
| |
| /* 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) */ |