summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/wtl3132.h
blob: deca6dd7f26991e27f0bea20045dd7d6489d03ce (plain) (tree)


















                                                                                                   
                                                        


















                                                       










                                                                                                                          


















































































                                                                          
                                  

















































                                                 
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay

#ifndef MAME_MACHINE_WTL3132_H
#define MAME_MACHINE_WTL3132_H

#pragma once

#include "softfloat3/source/include/softfloat.h"

class wtl3132_device : public device_t
{
public:
	wtl3132_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);

	// output lines
	auto out_fpcn() { return m_fpcn_cb.bind(); }
	auto out_fpex() { return m_fpex_cb.bind(); }
	auto out_zero() { return m_zero_cb.bind(); }
	auto out_port_x() { return m_port_x_cb.bind(); }

	// code and data ports
	void c_port_w(u64 data) { m_c_port = data; }
	u32 x_port_r() { return m_x_port.v; }
	void x_port_w(u32 data) { m_x_port.v = data; }

	// input lines
	void abort_w(int state) { m_abort = state; }
	void clk_w(int state);
	void neut_w(int state) { m_neut = state; }
	void stall_w(int state) { m_stall = state; }

	// disassembly helpers
	static std::string disassemble(u64 const code);
	static std::string reg(unsigned const reg);
	static std::string mbin(u64 const code);
	static std::string abin(u64 const code);
	static std::string adst(u64 const code);

	void state_add(device_state_interface &parent, unsigned base = 0)
	{
		parent.state_add(base + 0, "MODE", m_mode).formatstr("%04X");
		parent.state_add(base + 1, "T1", m_t1.v).formatstr("%08X");
		parent.state_add(base + 2, "T2", m_t2.v).formatstr("%08X");
		parent.state_add(base + 3, "T3", m_t3.v).formatstr("%08X");

		for (unsigned i = 0; i < 32; i++)
			parent.state_add(base + i + 4, util::string_format("F%d", i).c_str(), m_f[i].v).formatstr("%08X");
	}

	enum code_mask : u64
	{
		// opcode is 34 bits wide
		M_ENCN = 0x0'00000003, // condition output select
		M_MBIN = 0x0'00000004, // mbin input select
		M_ADST = 0x0'00000018, // alu destination select
		M_ABIN = 0x0'000000e0, // abin input select
		M_DADD = 0x0'00001f00, // d port register address
		M_IOCT = 0x0'00006000, // i/o control
		M_CWEN = 0x0'00008000, // c port write enable (active low)
		M_CADD = 0x0'001f0000, // c port register address
		M_BADD = 0x0'03e00000, // b port register address
		M_AADD = 0x0'7c000000, // a port register address
		M_F    = 0x3'80000000, // function code

		// internal pipeline control flag
		M_CANCEL = 0x80000000'00000000, // cancelled
	};

	enum code_shift : unsigned
	{
		S_ENCN =  0, // condition output select
		S_MBIN =  2, // mbin input select
		S_ADST =  3, // alu destination select
		S_ABIN =  5, // abin input select
		S_DADD =  8, // d port register address
		S_IOCT = 13, // i/o control
		S_CWEN = 15, // c port write enable (active low)
		S_CADD = 16, // c port register address
		S_BADD = 21, // b port register address
		S_AADD = 26, // a port register address
		S_F    = 31, // function code
	};

	enum function_code : unsigned
	{
		F_MISC  = 0, // miscellaneous
		F_FSUBR = 1, // negate and add
		F_FSUB  = 2, // subtract
		F_FADD  = 3, // add
		F_FMNA  = 5, // multiply, negate and add
		F_FMNS  = 6, // multiply, negate and subtract
		F_FMAC  = 7, // multiply and accumulate
	};

	enum misc_code : unsigned
	{
		MF_FCLSR = 0, // clear status register
		MF_FSTSR = 1, // read status register
		MF_FMODE = 3, // load mode register
		MF_FABS  = 4, // absolute value
		MF_FLOAT = 5, // fixed-to-float
		MF_FIX   = 6, // float-to-fixed
		MF_FLUT  = 7, // lookup operation
	};

	enum mode_mask : u16
	{
		MODE_IBA = 0x0001, // internal bypass A enable
		MODE_RTN = 0x0002, // round to nearest
		MODE_IBP = 0x0008, // input bypass enable
		MODE_OBP = 0x0010, // output bypass enable
		MODE_FXO = 0x0020, // fpex overflow enable
		MODE_CPL = 0x0040, // coprocessor load enable
		MODE_FXH = 0x0100, // fpex active high
		MODE_DBP = 0x0200, // double pump enable (3332 only)
		MODE_IBB = 0x0800, // internal bypass B enable
		MODE_YLI = 0x1000, // Y late input enable (3332 only)
	};

protected:
	virtual void device_start() override;
	virtual void device_reset() override;

	void stage1(unsigned const index);
	void stage2(unsigned const index);
	void stage3(unsigned const index);
	void stage4(unsigned const index);

private:
	devcb_write_line m_fpcn_cb;
	devcb_write_line m_fpex_cb;
	devcb_write_line m_zero_cb;
	devcb_write32 m_port_x_cb;

	// output line state
	bool m_fpcn_state;
	bool m_fpex_state;
	bool m_zero_state;

	// port state
	u64 m_c_port;
	float32_t m_x_port;
	float32_t m_x_in;
	float32_t m_x_out;

	// input line state
	int m_abort;
	int m_neut;
	int m_stall;

	// pipeline state
	u64 m_slot[4];
	unsigned m_head;

	// registers
	u16 m_mode;
	float32_t m_f[32];
	float32_t m_t1;
	float32_t m_t2;
	float32_t m_t3;
	bool m_cr;
	bool m_sr;
	bool m_zr;

	// C bus
	float32_t m_c_bus_data;
	unsigned m_c_bus_addr;
	bool m_c_bus_cwen;

	// multiplier inputs and output
	float32_t m_ma_in;
	float32_t m_mb_in;
	float32_t m_m_out;

	// accumulator buffers, inputs and output
	float32_t m_aa_in[2];
	float32_t m_ab_in[2];
	float32_t m_a_out;
};

DECLARE_DEVICE_TYPE(WTL3132, wtl3132_device)

#endif // MAME_MACHINE_WTL3132_H