| /* $Id: cy7c601.c,v 1.4 2010/02/14 14:00:23 fredette Exp $ */ |
| |
| /* ic/m68k/cy7c601.c - implementation of Cypress SPARC CY7C601 emulation: */ |
| |
| /* |
| * Copyright (c) 2005 Matt Fredette |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. All advertising materials mentioning features or use of this software |
| * must display the following acknowledgement: |
| * This product includes software developed by Matt Fredette. |
| * 4. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <tme/common.h> |
| _TME_RCSID("$Id: cy7c601.c,v 1.4 2010/02/14 14:00:23 fredette Exp $"); |
| |
| /* includes: */ |
| #include "sparc-impl.h" |
| |
| /* the format three opcode map: */ |
| #define _TME_SPARC_EXECUTE_OPMAP tme_sparc_opcodes_cy7c601 |
| const _tme_sparc32_format3 _TME_SPARC_EXECUTE_OPMAP[] = { |
| |
| /* op=2: arithmetic, logical, shift, and remaining: */ |
| |
| /* 000000 */ tme_sparc32_add, |
| /* 000001 */ tme_sparc32_and, |
| /* 000010 */ tme_sparc32_or, |
| /* 000011 */ tme_sparc32_xor, |
| /* 000100 */ tme_sparc32_sub, |
| /* 000101 */ tme_sparc32_andn, |
| /* 000110 */ tme_sparc32_orn, |
| /* 000111 */ tme_sparc32_xnor, |
| /* 001000 */ tme_sparc32_addx, |
| /* 001001 */ NULL, |
| /* 001010 */ tme_sparc32_illegal, /* the CY7C601 does not implement umul */ |
| /* 001011 */ tme_sparc32_illegal, /* the CY7C601 does not implement smul */ |
| /* 001100 */ tme_sparc32_subx, |
| /* 001101 */ NULL, |
| /* 001110 */ tme_sparc32_illegal, /* the CY7C601 does not implement udiv */ |
| /* 001111 */ tme_sparc32_illegal, /* the CY7C601 does not implement sdiv */ |
| /* 010000 */ tme_sparc32_addcc, |
| /* 010001 */ tme_sparc32_andcc, |
| /* 010010 */ tme_sparc32_orcc, |
| /* 010011 */ tme_sparc32_xorcc, |
| /* 010100 */ tme_sparc32_subcc, |
| /* 010101 */ tme_sparc32_andncc, |
| /* 010110 */ tme_sparc32_orncc, |
| /* 010111 */ tme_sparc32_xnorcc, |
| /* 011000 */ tme_sparc32_addxcc, |
| /* 011001 */ NULL, |
| /* 011010 */ tme_sparc32_illegal, /* the CY7C601 does not implement umulcc */ |
| /* 011011 */ tme_sparc32_illegal, /* the CY7C601 does not implement smulcc */ |
| /* 011100 */ tme_sparc32_subxcc, |
| /* 011101 */ NULL, |
| /* 011110 */ tme_sparc32_illegal, /* the CY7C601 does not implement udivcc */ |
| /* 011111 */ tme_sparc32_illegal, /* the CY7C601 does not implement sdivcc */ |
| /* 100000 */ tme_sparc32_taddcc, |
| /* 100001 */ tme_sparc32_tsubcc, |
| /* 100010 */ tme_sparc32_taddcctv, |
| /* 100011 */ tme_sparc32_tsubcctv, |
| /* 100100 */ tme_sparc32_mulscc, |
| /* 100101 */ tme_sparc32_sll, |
| /* 100110 */ tme_sparc32_srl, |
| /* 100111 */ tme_sparc32_sra, |
| /* 101000 */ tme_sparc32_rdasr, |
| /* 101001 */ tme_sparc32_rdpsr, |
| /* 101010 */ tme_sparc32_rdwim, |
| /* 101011 */ tme_sparc32_rdtbr, |
| /* 101100 */ NULL, |
| /* 101101 */ NULL, |
| /* 101110 */ NULL, |
| /* 101111 */ NULL, |
| /* 110000 */ tme_sparc32_wrasr, |
| /* 110001 */ tme_sparc32_wrpsr, |
| /* 110010 */ tme_sparc32_wrwim, |
| /* 110011 */ tme_sparc32_wrtbr, |
| /* 110100 */ tme_sparc32_fpop1, |
| /* 110101 */ tme_sparc32_fpop2, |
| /* 110110 */ tme_sparc32_cpop1, |
| /* 110111 */ tme_sparc32_cpop2, |
| /* 111000 */ tme_sparc32_jmpl, |
| /* 111001 */ tme_sparc32_rett, |
| /* 111010 */ tme_sparc32_ticc, |
| /* 111011 */ tme_sparc32_flush, |
| /* 111100 */ tme_sparc32_save_restore, |
| /* 111101 */ tme_sparc32_save_restore, |
| /* 111110 */ NULL, |
| /* 111111 */ NULL, |
| |
| /* op=3: memory instructions: */ |
| |
| /* 000000 */ tme_sparc32_ld, |
| /* 000001 */ tme_sparc32_ldb, |
| /* 000010 */ tme_sparc32_ldh, |
| /* 000011 */ tme_sparc32_ldd, |
| /* 000100 */ tme_sparc32_st, |
| /* 000101 */ tme_sparc32_stb, |
| /* 000110 */ tme_sparc32_sth, |
| /* 000111 */ tme_sparc32_std, |
| /* 001000 */ NULL, |
| /* 001001 */ tme_sparc32_ldb, |
| /* 001010 */ tme_sparc32_ldh, |
| /* 001011 */ NULL, |
| /* 001100 */ NULL, |
| /* 001101 */ tme_sparc32_ldstub, |
| /* 001110 */ NULL, |
| /* 001111 */ tme_sparc32_swap, |
| /* 010000 */ tme_sparc32_lda, |
| /* 010001 */ tme_sparc32_ldba, |
| /* 010010 */ tme_sparc32_ldha, |
| /* 010011 */ tme_sparc32_ldda, |
| /* 010100 */ tme_sparc32_sta, |
| /* 010101 */ tme_sparc32_stba, |
| /* 010110 */ tme_sparc32_stha, |
| /* 010111 */ tme_sparc32_stda, |
| /* 011000 */ NULL, |
| /* 011001 */ tme_sparc32_ldba, |
| /* 011010 */ tme_sparc32_ldha, |
| /* 011011 */ NULL, |
| /* 011100 */ NULL, |
| /* 011101 */ tme_sparc32_ldstuba, |
| /* 011110 */ NULL, |
| /* 011111 */ tme_sparc32_swapa, |
| /* 100000 */ tme_sparc32_ldf, |
| /* 100001 */ tme_sparc32_ldfsr, |
| /* 100010 */ NULL, |
| /* 100011 */ tme_sparc32_lddf, |
| /* 100100 */ tme_sparc32_stf, |
| /* 100101 */ tme_sparc32_stfsr, |
| /* 100110 */ tme_sparc32_stdfq, |
| /* 100111 */ tme_sparc32_stdf, |
| /* 101000 */ NULL, |
| /* 101001 */ NULL, |
| /* 101010 */ NULL, |
| /* 101011 */ NULL, |
| /* 101100 */ NULL, |
| /* 101101 */ NULL, |
| /* 101110 */ NULL, |
| /* 101111 */ NULL, |
| /* 110000 */ tme_sparc32_ldc, |
| /* 110001 */ tme_sparc32_ldcsr, |
| /* 110010 */ NULL, |
| /* 110011 */ tme_sparc32_lddc, |
| /* 110100 */ tme_sparc32_stc, |
| /* 110101 */ tme_sparc32_stcsr, |
| /* 110110 */ tme_sparc32_stdcq, |
| /* 110111 */ tme_sparc32_stdc, |
| /* 111000 */ NULL, |
| /* 111001 */ NULL, |
| /* 111010 */ NULL, |
| /* 111011 */ NULL, |
| /* 111100 */ NULL, |
| /* 111101 */ NULL, |
| /* 111110 */ NULL, |
| /* 111111 */ NULL, |
| }; |
| |
| /* make the executor for the CY7C601: */ |
| #undef TME_SPARC_VERSION |
| #define TME_SPARC_VERSION(ic) (7) |
| #undef TME_SPARC_NWINDOWS |
| #define TME_SPARC_NWINDOWS(ic) (8) |
| #define _TME_SPARC_EXECUTE_NAME _tme_sparc_execute_cy7c601 |
| #include "sparc-execute.c" |
| |
| /* this returns the version of an FPU for an cy7c601: */ |
| static tme_uint32_t |
| _tme_sparc_fpu_ver_cy7c601(struct tme_sparc *ic, const char *fpu_name, char **_output) |
| { |
| tme_uint32_t ver; |
| |
| /* if we're returning a usage: */ |
| if (_output != NULL) { |
| tme_output_append_error(_output, |
| "{ l64812/act8847 | l64814 | tms390-c602A | wtl3171/cy7c602 }"); |
| return (TME_SPARC_FSR_VER_missing); |
| } |
| |
| if (TME_ARG_IS(fpu_name, "l64812/act8847")) { |
| ver = 0; |
| } |
| else if (TME_ARG_IS(fpu_name, "l64814")) { |
| ver = 1; |
| } |
| else if (TME_ARG_IS(fpu_name, "tms390-c602A")) { |
| ver = 2; |
| } |
| else if (TME_ARG_IS(fpu_name, "wtl3171/cy7c602")) { |
| ver = 3; |
| } |
| else { |
| return (TME_SPARC_FSR_VER_missing); |
| } |
| |
| ic->tme_sparc_fpu_flags |
| = (TME_SPARC_FPU_FLAG_NO_QUAD |
| | TME_SPARC_FPU_FLAG_NO_FMUL_WIDER |
| | TME_SPARC_FPU_FLAG_OK_REG_MISALIGNED); |
| return (ver * _TME_FIELD_MASK_FACTOR(TME_SPARC_FSR_VER)); |
| } |
| |
| /* this creates and returns a new cy7c601: */ |
| TME_ELEMENT_X_NEW_DECL(tme_ic_,sparc,cy7c601) { |
| struct tme_sparc *ic; |
| tme_uint32_t psr; |
| |
| /* allocate the sparc structure: */ |
| ic = tme_new0(struct tme_sparc, 1); |
| ic->tme_sparc_element = element; |
| |
| /* initialize the synchronization parts of the structure: */ |
| tme_sparc_sync_init(ic); |
| |
| /* fill in the cy7c601-specific parts of the structure: */ |
| psr = 0; |
| TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_IMPL, 1); |
| TME_FIELD_MASK_DEPOSITU(psr, TME_SPARC32_PSR_VER, 1); |
| ic->tme_sparc32_ireg_psr = psr; |
| ic->tme_sparc_version = TME_SPARC_VERSION(ic); |
| ic->tme_sparc_nwindows = TME_SPARC_NWINDOWS(ic); |
| ic->_tme_sparc32_execute_opmap = _TME_SPARC_EXECUTE_OPMAP; |
| ic->_tme_sparc_execute = _tme_sparc_execute_cy7c601; |
| ic->_tme_sparc_fpu_ver = _tme_sparc_fpu_ver_cy7c601; |
| ic->_tme_sparc_external_check = tme_sparc32_external_check; |
| ic->_tme_sparc_ls_address_map = tme_sparc32_ls_address_map; |
| ic->_tme_sparc_ls_bus_cycle = tme_sparc32_ls_bus_cycle; |
| ic->_tme_sparc_ls_bus_fault = tme_sparc_ls_bus_fault; |
| ic->_tme_sparc_ls_trap = tme_sparc32_ls_trap; |
| ic->tme_sparc_timing_loop_cycles_each = (1 + 1); |
| #ifdef _TME_SPARC_RECODE_VERIFY |
| ic->tme_sparc_recode_verify_ic_size = sizeof(struct tme_sparc); |
| ic->tme_sparc_recode_verify_ic_size_total = sizeof(struct tme_sparc); |
| #endif /* _TME_SPARC_RECODE_VERIFY */ |
| |
| /* call the common sparc new function: */ |
| return (tme_sparc_new(ic, args, extra, _output)); |
| } |
| |
| #undef TME_SPARC_VERSION |
| #define TME_SPARC_VERSION(ic) _TME_SPARC_VERSION(ic) |
| #undef TME_SPARC_NWINDOWS |
| #define TME_SPARC_NWINDOWS(ic) _TME_SPARC_NWINDOWS(ic) |
| #undef _TME_SPARC_EXECUTE_NAME |
| #undef _TME_SPARC_EXECUTE_OPMAP |