File:  [RetroPC.NET] / np2 / i386c / ia32 / ia32.c
Revision 1.1: download - view: text, annotated - select for diffs
Mon Dec 8 09:55:31 2003 JST (21 years, 10 months ago) by yui
Branches: MAIN
CVS tags: HEAD
add IA32 etc... (T.Yui)

/*	$Id: ia32.c,v 1.1 2003/12/08 00:55:31 yui Exp $	*/

/*
 * Copyright (c) 2002-2003 NONAKA Kimihiro
 * 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. 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 "compiler.h"
#include "cpu.h"
#include "ia32.mcr"


CPU_REGS	cpu_regs;
CPU_SYSREGS	cpu_sysregs;
CPU_STAT	cpu_stat;
CPU_INST	cpu_inst;
CPU_INST	cpu_inst_default;
I386CORE	i386core;

// #if defined(USE_ASM)
BYTE iflags[] = {
	0x44, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
	0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
	0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
	0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
	0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
	0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
	0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
	0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
	0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
	0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
	0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
	0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
	0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
	0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
	0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04,
	0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00,
	0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
	0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
	0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
	0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
	0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
	0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
	0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
	0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
	0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
	0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
	0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
	0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
	0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
	0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
	0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80,
	0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84,
};
// #endif	/* USE_ASM */

BYTE	*reg8_b20[0x100];
BYTE	*reg8_b53[0x100];
WORD	*reg16_b20[0x100];
WORD	*reg16_b53[0x100];
DWORD	*reg32_b20[0x100];
DWORD	*reg32_b53[0x100];


void
ia32_init(void)
{
	int i;

	memset(&cpu_regs, 0, sizeof(cpu_regs));
	memset(&cpu_sysregs, 0, sizeof(cpu_sysregs));
	memset(&cpu_stat, 0, sizeof(cpu_stat));
	memset(&cpu_inst_default, 0, sizeof(cpu_inst_default));

	CPU_EDX = (CPU_FAMILY << 8) | (CPU_MODEL << 4) | CPU_STEPPING;
	CPU_EFLAG = 2;
	CPU_CR0 = CPU_CR0_CD | CPU_CR0_NW | CPU_CR0_ET;
	CPU_MXCSR = 0x1f80;
	CPU_GDTR_LIMIT = 0xffff;
	CPU_IDTR_LIMIT = 0xffff;

	for (i = 0; i < CPU_SEGREG_NUM; ++i) {
		CPU_STAT_SREG_INIT(i);
	}
	CPU_LDTR_LIMIT = 0xffff;
	CPU_TR_LIMIT = 0xffff;

	for (i = 0; i < 0x100; ++i) {
		/* 8bit */
		if (i & 0x20) {
			/* h */
			reg8_b53[i] = &CPU_REGS_BYTEH((i >> 3) & 3);
		} else {
			/* l */
			reg8_b53[i] = &CPU_REGS_BYTEL((i >> 3) & 3);
		}

		if (i & 0x04) {
			/* h */
			reg8_b20[i] = &CPU_REGS_BYTEH(i & 3);
		} else {
			/* l */
			reg8_b20[i] = &CPU_REGS_BYTEL(i & 3);
		}

		/* 16bit */
		reg16_b53[i] = &CPU_REGS_WORD((i >> 3) & 7);
		reg16_b20[i] = &CPU_REGS_WORD(i & 7);

		/* 32bit */
		reg32_b53[i] = &CPU_REGS_DWORD((i >> 3) & 7);
		reg32_b20[i] = &CPU_REGS_DWORD(i & 7);
	}

	resolve_init();
#if defined(SUPPORT_TLB)
	tlb_init();
#endif
#ifdef USE_FPU
	fpu_init();
#endif
}

/*
 * ¥â¡¼¥ÉÁ«°Ü
 */
void FASTCALL
change_pm(BOOL onoff)
{
	int i;

	if (onoff) {
		for (i = 0; i < CPU_SEGREG_NUM; i++) {
			CPU_STAT_SREG(i).valid = TRUE;
			CPU_STAT_SREG(i).dpl = 0;
		}
		VERBOSE(("Entering to Protected-Mode..."));
	} else {
		VERBOSE(("Leaveing from Protected-Mode..."));
	}
	CPU_STAT_CPL = 0;
	CPU_STAT_PM = onoff;
}

void FASTCALL
change_pg(BOOL onoff)
{

	if (onoff) {
		VERBOSE(("Entering to Paging-Mode..."));
	} else {
		VERBOSE(("Leaveing from Pagin-Mode..."));
	}
	CPU_STAT_PAGING = onoff;
}

void FASTCALL
change_vm(BOOL onoff)
{
	descriptor_t sd;
	int i;

	if (onoff) {
		for (i = 0; i < CPU_SEGREG_NUM; i++) {
			sd.u.seg.limit = 0xffff;
			CPU_SET_SEGDESC_DEFAULT(&sd, i, CPU_REGS_SREG(i));
			sd.dpl = 3;
			CPU_STAT_SREG(i) = sd;
		}
		VERBOSE(("Entering to Virtual-8086-Mode..."));
	} else {
		VERBOSE(("Leaveing from Virtual-8086-Mode..."));
	}
	CPU_STAT_VM86 = onoff;
}

/*
 * flags
 */
static void
modify_eflags(DWORD new_flags, DWORD mask)
{
	DWORD orig = CPU_EFLAG;

	new_flags &= ALL_EFLAG;
	mask &= ALL_EFLAG;
	CPU_EFLAG = (REAL_EFLAGREG & ~mask) | (new_flags & mask) | 0x2;

	CPU_OV = CPU_FLAG & O_FLAG;
	CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG);
	if ((orig ^ CPU_EFLAG) & VM_FLAG) {
		if (CPU_EFLAG & VM_FLAG) {
			change_vm(1);
		} else {
			change_vm(0);
		}
	}
}

void
set_flags(WORD new_flags, WORD mask)
{

	mask &= I_FLAG|IOPL_FLAG;
	mask |= SZAPC_FLAG|T_FLAG|D_FLAG|O_FLAG|NT_FLAG;
	modify_eflags(new_flags, mask);
}

void
set_eflags(DWORD new_flags, DWORD mask)
{

	mask &= I_FLAG|IOPL_FLAG|RF_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG;
	mask |= SZAPC_FLAG|T_FLAG|D_FLAG|O_FLAG|NT_FLAG;
	mask |= AC_FLAG|ID_FLAG;
	modify_eflags(new_flags, mask);
}

RetroPC.NET-CVS <cvs@retropc.net>