blob: f89311080451ff08fa3d6a18474a69014a4aaf76 [file] [log] [blame]
/* $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