summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/wtl3132.h
blob: deca6dd7f26991e27f0bea20045dd7d6489d03ce (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// 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