File:  [Isaki's NoNo m68k/m88k emulator] / nono / m88xx0 / m88100.h
Revision 1.1.1.17 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:56 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

#pragma once

#include "header.h"

// 定数。
struct M88100
{
	// PID(cr0)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------+---------------+---------------+-------------+-+
	// |               0               |      REV      |     VER     |M|
	// +---------------+---------------+---------------+-------------+-+
	static const uint32 PID_REV_MASK	= 0x0000ff00; // 0 = MC88100
	static const uint32 PID_VER_MASK	= 0x000000fe;
	static const uint32 PID_MASTER		= 0x00000001;

	// PSR(cr1)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +-+-+-+-+-------+---------------+---------------+-------+-+-+-+-+
	// |S|B|S|C|                                               |D|M|I|S|
	// |U|O|E| |                       0                       |1|X|N|F|
	// +-+-+-+-+-------+---------------+---------------+-------+-+-+-+-+
	static const uint32 PSR_SUPER		= 0x80000000;
	static const uint32 PSR_BO_LE		= 0x40000000; // ByteOrder(Little)
	static const uint32 PSR_SER			= 0x20000000;
	static const uint32 PSR_C			= 0x10000000; // Carry
	static const uint32 PSR_SFD1		= 0x00000008; // SFU1 Disable
	static const uint32 PSR_MXM			= 0x00000004; // MisalignedAccessEnable
	static const uint32 PSR_IND			= 0x00000002; // Interrupt Disable
	static const uint32 PSR_SFRZ		= 0x00000001; // Shadow Freeze

	// 例外処理で使用される S*IP
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------+---------------+---------------+-----------+-+-+
	// |                            S*IP                           |V|E|
	// +---------------+---------------+---------------+-----------+-+-+
	static const uint32 SIP_MASK		= 0xfffffffcU;
	static const uint32 SIP_V			= 0x00000002;
	static const uint32 SIP_E			= 0x00000001;

	// DMTn、データ例外
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------+---------------+-+-+-+-+-------+-+-+-+-+-+-+-+-+
	// |                               |B|D|D|L|         |S|E|E|E|E|W|V|
	// |               0               |O|A|B|K|  DREG   | |3|2|1|0|R| |
	// +---------------+---------------+-+-+-+-+-------+-+-+-+-+-+-+-+-+
	static const uint32 DM_BO			= 0x00008000;
	static const uint32 DM_DAS			= 0x00004000;
	static const uint32 DM_DOUB1		= 0x00002000;
	static const uint32 DM_LOCK			= 0x00001000;
	static const uint32 DM_DREG_MASK	= 0x00000f80;
	static const uint32 DM_SIGNED		= 0x00000040;
	static const uint32 DM_EN3			= 0x00000020;
	static const uint32 DM_EN2			= 0x00000010;
	static const uint32 DM_EN1			= 0x00000008;
	static const uint32 DM_EN0			= 0x00000004;
	static const uint32 DM_EN_MASK		= (DM_EN0 | DM_EN1 | DM_EN2 | DM_EN3);
	static const uint32 DM_WRITE		= 0x00000002;
	static const uint32 DM_VALID		= 0x00000001;
	// 内部識別フラグ
	static const uint32 DM_SIZE_B		= (1U << 16) | DM_EN3;
	static const uint32 DM_SIZE_H		= (1U << 17) | DM_EN3 | DM_EN2;
	static const uint32 DM_SIZE_W		= (1U << 18) | DM_EN_MASK;
	static const uint32 DM_USR			= (1U << 20);
	static const uint32 DM_BU			= DM_SIZE_B;
	static const uint32 DM_B			= DM_SIZE_B | DM_SIGNED;
	static const uint32 DM_HU			= DM_SIZE_H;
	static const uint32 DM_H			= DM_SIZE_H | DM_SIGNED;
	static const uint32 DM_W			= DM_SIZE_W;
	static const uint32 DM_D1			= DM_SIZE_W | DM_DOUB1;
	static const uint32 DM_D2			= DM_SIZE_W;

	// FPECR(fcr0)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------+---------------+---------------+-+-+-+-+-+-+-+-+
	// |                                               |I|U|P|O|D|U|O|I|
	// |                       0                       |O|N|V|P|Z|F|V|N|
	// +---------------+---------------+---------------+-+-+-+-+-+-+-+-+
	static const uint32 FPECR_MASK	= 0x000000ff;	// 有効ビットマスク
	static const uint32 FPECR_FIOV	= 0x00000080;	// FP Integer Overflow
	static const uint32 FPECR_FUNIMP= 0x00000040;	// FP Unimplemented
	static const uint32 FPECR_FPRV	= 0x00000020;	// FP Privilege Violation
	static const uint32 FPECR_FROP	= 0x00000010;	// FP Reserved Operand
	static const uint32 FPECR_FDVZ	= 0x00000008;	// FP Divice-by-Zero
	static const uint32 FPECR_FUNF	= 0x00000004;	// FP Underflow
	static const uint32 FPECR_FOVF	= 0x00000002;	// FP Overflow
	static const uint32 FPECR_FINX	= 0x00000001;	// FP Inexact

	// FPHS1(fcr1)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +-+---------------------+---------------------------------------+
	// |S|      Exponent       |     High order 20 bits of Mantissa    |
	// +-+---------------------+---------------------------------------+

	// FPLS1(fcr2)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------------------------------------------------------+
	// |        Low order bits of Mantissa or Integer Operand          |
	// +---------------------------------------------------------------+

	// FPHS2(fcr3)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +-+---------------------+---------------------------------------+
	// |S|      Exponent       |     High order 20 bits of Mantissa    |
	// +-+---------------------+---------------------------------------+

	// FPLS2(fcr4)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------------------------------------------------------+
	// |        Low order bits of Mantissa or Integer Operand          |
	// +---------------------------------------------------------------+

	// FPPT(fcr5)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------+---------------+---------+---+---+---+---------+
	// |               0               |  OPCODE |T1 |T2 |TD | DestReg |
	// +---------------+---------------+---------+---+---+---+---------+
	static const uint32 FPPT_MASK	= 0x0000ffff;	// 有効ビットマスク
	static const uint32 FPPT_OPCODE	= 0x0000f800;	// Opcode
	static const uint32 FPPT_T1		= 0x00000600;	// Source1 Operand Size
	static const uint32 FPPT_T2		= 0x00000180;	// Source2 Operand Size
	static const uint32 FPPT_TD		= 0x00000060;	// Destination Size
	static const uint32 FPPT_DEST	= 0x0000001f;	// Destination Register No.

	// FPRH(fcr6)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +-----+-+-+-+-+-+-----+---------+-------------+-----------------+
	// |S|RM |G|R|S|A|   0   |       High Order Bits of Mantissa       |
	// +-----+-+-+-+-+-+-----+---------+-------------+-----------------+
	static const uint32 FPRH_MASK	= 0xfe1fffff;	// 有効ビットマスク
	static const uint32 FPRH_SIGN	= 0x80000000;	// Result Sign
	static const uint32 FPRH_RNDMODE= 0x60000000;	// Rounding Mode for Res.
	static const uint32 FPRH_GUARD	= 0x10000000;	// Guard  Bit for Result
	static const uint32 FPRH_ROUND	= 0x08000000;	// Round  Bit for Result
	static const uint32 FPRH_STICKY	= 0x04000000;	// Sticky Bit for Result
	static const uint32 FPRH_ADDONE	= 0x02000000;	// Add One
	static const uint32 FPRH_MANT	= 0x001fffff;	// Mantissa(High)
	static const uint32 FPRH_1		= 0x00100000;	// 隠し実数部の 1

	// FPRL(fcr7)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------------------------------------------------------+
	// |                 Low Order Bits of Mantissa                    |
	// +---------------------------------------------------------------+

	// FPIT(fcr8)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +-----------------------+-------+---------+-+-+-+-+-+-+---------+
	// |                       |       |         |D|E|E|E|E|E|         |
	// |  RESEXP (12bits)      |   0   |  OPCODE |S|V|Z|U|O|N| DestReg |
	// +-----------------------+-------+---------+-+-+-+-+-+-+---------+
	static const uint32 FPIT_MASK	= 0xfff0ffff;	// 有効ビットマスク
	static const uint32 FPIT_RESEXP	= 0xfff00000;	// Result Exponent
	static const uint32 FPIT_OPCODE	= 0x0000f800;	// Opcode
	static const uint32 FPIT_DESTSIZ= 0x00000400;	// Destination Size
	static const uint32 FPIT_EFINV	= 0x00000200;	// Enable Invalid Op.
	static const uint32 FPIT_EFDVZ	= 0x00000100;	// Enable Divide-by-Zero
	static const uint32 FPIT_EFUNF	= 0x00000080;	// Enable Underflow
	static const uint32 FPIT_EFOVF	= 0x00000040;	// Enable Overflow
	static const uint32 FPIT_EFINX	= 0x00000020;	// Enable Inexact
	static const uint32 FPIT_DEST	= 0x0000001f;	// Destination Register No.

	// FPSR(fcr62)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------+---------------+---------------+-----+-+-+-+-+-+
	// |                                                     |A|A|A|A|A|
	// |                        0                            |V|D|U|O|I|
	// +---------------+---------------+---------------+-----+-+-+-+-+-+
	static const uint32 FPSR_MASK	= 0x0000001f;	// 有効ビットマスク
	static const uint32 FPSR_AFINV	= 0x00000010;	// Acc. Invalid Op. Flag
	static const uint32 FPSR_AFDVZ	= 0x00000008;	// Acc. Divide-by-Zero Flag
	static const uint32 FPSR_AFUNF	= 0x00000004;	// Acc. Underflow Flag
	static const uint32 FPSR_AFOVF	= 0x00000002;	// Acc. Overflow Flag
	static const uint32 FPSR_AFINX	= 0x00000001;	// Acc. Inexact Flag

	// FPCR(fcr63)
	//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
	// +---------------+---------------+---+-----------+-----+-+-+-+-+-+
	// |                               |   |                 |E|E|E|E|E|
	// |               0               |RM |                 |V|D|U|O|I|
	// +---------------+---------------+---+-----------+-----+-+-+-+-+-+
	static const uint32 FPCR_MASK	= 0x0000c01f;	// 有効ビットマスク
	static const uint32 FPCR_RM		= 0x0000c000;	// Rounding Mask
	static const uint32 FPCR_EFINV	= 0x00000010;	// Enable Invalid Operation
	static const uint32 FPCR_EFDVZ	= 0x00000008;	// Enable Divide-by-Zero
	static const uint32 FPCR_EFUNF	= 0x00000004;	// Enable Underflow
	static const uint32 FPCR_EFOVF	= 0x00000002;	// Enable Overflow
	static const uint32 FPCR_EFINX	= 0x00000001;	// Enable Inexact

	// 例外ベクタ。
	static const uint32 EXCVEC_RESET			= 0;
	static const uint32 EXCVEC_INTERRUPT		= 1;
	static const uint32 EXCVEC_INST				= 2;
	static const uint32 EXCVEC_DATA				= 3;
	static const uint32 EXCVEC_MISALIGNED		= 4;
	static const uint32 EXCVEC_UNIMPL_OP		= 5;
	static const uint32 EXCVEC_PRIV				= 6;
	static const uint32 EXCVEC_BOUNDS			= 7;
	static const uint32 EXCVEC_INT_DIV			= 8;
	static const uint32 EXCVEC_INT_OVF			= 9;
	static const uint32 EXCVEC_ERROR			= 10;
	static const uint32 EXCVEC_SFU1_PRECISE		= 114;
	static const uint32 EXCVEC_SFU1_IMPRECISE	= 115;
	static const uint32 EXCVEC_SFU2_PRECISE		= 116;
	static const uint32 EXCVEC_SFU3_PRECISE		= 118;
	static const uint32 EXCVEC_SFU4_PRECISE		= 120;
	static const uint32 EXCVEC_SFU5_PRECISE		= 122;
	static const uint32 EXCVEC_SFU6_PRECISE		= 124;
	static const uint32 EXCVEC_SFU7_PRECISE		= 126;

	// 例外の優先順位 (LSB 側が優先度高)。一部カテゴリ分けも兼ねる。
	//
	// 優先度	例外
	//	1		RESET
	//	1		(ERROR)
	//	2		INST
	//	3		UNIMPL_OP
	//	4		PRIV
	//	5		INTERNAL … 内部発生例外のうちトラップ以外
	//	5		TRAP     … 内部発生例外のうちトラップのみ
	//	--		(OUTER)  …これ以降のどれかが立っているという代表ビット
	//	6		INTERRUPT
	//	7		SFU_IMPRECISE
	//	8		DATA
	//
	// ERROR 例外は Table. 6-2 には載ってないけど、実質ダブルバスフォールト
	// なので、リセットに準じる高さの気がする…。
	// TRAP は他の内部発生例外 (INTERNAL) とは区別が必要なので分けてある。
	// INTERNAL と TRAP はこの優先度だけでなくベクタ情報も必要。
	// INTERRUPT と DATA はどちらが起きても同時に処理するので、
	// どちらかを立てたまま OUTER ビットで処理させる。
	// SFU_IMPRECISE は未調査。
	static const uint32 EXCPRI_RESET			= (1U << 0);
	static const uint32 EXCPRI_ERROR			= (1U << 1);
	static const uint32 EXCPRI_INST				= (1U << 2);
	static const uint32 EXCPRI_UNIMPL_OP		= (1U << 3);
	static const uint32 EXCPRI_PRIV				= (1U << 4);
	static const uint32 EXCPRI_INTERNAL			= (1U << 5);
	static const uint32 EXCPRI_TRAP				= (1U << 6);
	static const uint32 EXCPRI_OUTER			= (1U << 7);
	static const uint32 EXCPRI_INTERRUPT		= (1U << 8);
	static const uint32 EXCPRI_SFU_IMPRECISE	= (1U << 9);
	static const uint32 EXCPRI_DATA				= (1U << 10);
	static const uint32 EXCPRI_OUTER_MASK		=
		EXCPRI_INTERRUPT | EXCPRI_SFU_IMPRECISE | EXCPRI_DATA;

	// 32bit 命令コードからディスパッチ用の 12bit に変換。
	// ops と disasm で使うため。
	static uint32 op32_to_12(uint32 op) {
		return ((op >> 20) & 0x0fc0) | ((op >> 10) & 0x003f);
	}
};

// m88100 レジスタイメージを保持する構造体。
// この構造体はコピーや比較をするので、ポインタとかは置かないこと。
struct m88100reg
{
	// 頻繁にアクセスしそうな変数はオフセットの若いほうに持ってきておく。

	// 実行中の命令
	uint64 opX {};
	// プリフェッチ命令
	uint64 opF {};

	uint32 xip {};
	uint32 nip {};
	uint32 fip {};

	uint32 r[32] {};
	union {
		uint32 cr[21] {};
		struct {
			uint32 pid;		// cr0 (ReadOnly)
			uint32 psr;		// cr1
			uint32 epsr;	// cr2
			uint32 ssbr;	// cr3
			uint32 sxip;	// cr4 (ReadOnly)
			uint32 snip;	// cr5
			uint32 sfip;	// cr6
			uint32 vbr;		// cr7
			uint32 dmt0;	// cr8
			uint32 dmd0;	// cr9
			uint32 dma0;	// cr10
			uint32 dmt1;	// cr11
			uint32 dmd1;	// cr12
			uint32 dma1;	// cr13
			uint32 dmt2;	// cr14
			uint32 dmd2;	// cr15
			uint32 dma2;	// cr16
			uint32 sr[4];	// cr17,18,19,20
		};
	};
	union {
		uint32 fcr[11] {};
		struct {
			uint32 fpecr;	// fcr0
			uint32 fphs1;	// fcr1
			uint32 fpls1;	// fcr2
			uint32 fphs2;	// fcr3
			uint32 fpls2;	// fcr4
			uint32 fppt;	// fcr5
			uint32 fprh;	// fcr6
			uint32 fprl;	// fcr7
			uint32 fpit;	// fcr8
			uint32 fpsr;	// fcr62 [9]
			uint32 fpcr;	// fcr63 [10]
		};
	};

	static const uint32 fcr_mask[11];
	static const char * const sipname[3];
	static const char * const dmt_en_str[16];
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.