1 // license:BSD-3-Clause
2 // copyright-holders:Philip Bennett
3 /***************************************************************************
4 
5     am29000.c
6     Core implementation of the Am29000 emulator
7 
8     Written by Philip Bennett
9 
10     Features missing:
11     * MMU
12     * Some instructions
13     * Various exceptions
14 
15 ***************************************************************************/
16 
17 #include "emu.h"
18 #include "debugger.h"
19 #include "am29000.h"
20 #include "am29dasm.h"
21 
22 
23 DEFINE_DEVICE_TYPE(AM29000, am29000_cpu_device, "am29000", "AMC Am29000")
24 
25 
26 /***************************************************************************
27     CONSTANTS
28 ***************************************************************************/
29 
30 #define PFLAG_FETCH_EN              (1 << 0)
31 #define PFLAG_DECODE_EN             (1 << 1)
32 #define PFLAG_EXECUTE_EN            (1 << 2)
33 #define PFLAG_WRITEBACK_EN          (1 << 3)
34 #define PFLAG_IRQ                   (1 << 4)
35 #define PFLAG_LOADSTORE             (1 << 5)
36 #define PFLAG_MULTI_LOADSTORE       (1 << 6)
37 #define PFLAG_JUMP                  (1 << 7)
38 #define PFLAG_JUMP2                 (1 << 8)
39 #define PFLAG_IRET                  (1 << 9)
40 #define PFLAG_TIMER_LOADED          (1 << 10)
41 
42 #define PFLAG_RA_DEPENDENCY         (1 << 26)
43 #define PFLAG_RB_DEPENDENCY         (1 << 27)
44 
45 #define PFLAG_MEM_MULTIPLE          (1 << 29)
46 #define PFLAG_REG_WRITEBACK         (1 << 30)
47 #define PFLAG_MEM_WRITEBACK         (1 << 31)
48 
49 #define MMU_PROGRAM_ACCESS          (0)
50 #define MMU_DATA_ACCESS             (1)
51 
52 #define FREEZE_MODE                 (m_cps & CPS_FZ)
53 #define SUPERVISOR_MODE             (m_cps & CPS_SM)
54 #define USER_MODE                   (~m_cps & CPS_SM)
55 #define REGISTER_IS_PROTECTED(x)    (m_rbp & (1 << ((x) >> 4)))
56 
57 #define INST_RB_FIELD(x)            ((x) & 0xff)
58 #define INST_RA_FIELD(x)            (((x) >> 8) & 0xff)
59 #define INST_RC_FIELD(x)            (((x) >> 16) & 0xff)
60 #define INST_SA_FIELD(x)            (((x) >> 8) & 0xff)
61 
62 #define FIELD_RA                    0
63 #define FIELD_RB                    1
64 #define FIELD_RC                    2
65 
66 #define SIGNAL_EXCEPTION(x)         (signal_exception(x))
67 
68 
69 #define GET_ALU_FC                  ((m_alu >> ALU_FC_SHIFT) & ALU_FC_MASK)
70 #define GET_ALU_BP                  ((m_alu >> ALU_BP_SHIFT) & ALU_BP_MASK)
71 #define GET_CHC_CR                  ((m_chc >> CHC_CR_SHIFT) & CHC_CR_MASK)
72 
73 #define SET_ALU_FC(x)               do { m_alu &= ~(ALU_FC_MASK << ALU_FC_SHIFT); m_alu |= ((x) & ALU_FC_MASK) << ALU_FC_SHIFT; } while(0)
74 #define SET_ALU_BP(x)               do { m_alu &= ~(ALU_BP_MASK << ALU_BP_SHIFT); m_alu |= ((x) & ALU_BP_MASK) << ALU_BP_SHIFT; } while(0)
75 #define SET_CHC_CR(x)               do { m_chc &= ~(CHC_CR_MASK << CHC_CR_SHIFT); m_chc |= ((x) & CHC_CR_MASK) << CHC_CR_SHIFT; } while(0)
76 
77 
78 /***************************************************************************
79     STATE ACCESSORS
80 ***************************************************************************/
81 
am29000_cpu_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)82 am29000_cpu_device::am29000_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
83 	: cpu_device(mconfig, AM29000, tag, owner, clock)
84 	, m_program_config("program", ENDIANNESS_BIG, 32, 32, 0)
85 	, m_io_config("io", ENDIANNESS_BIG, 32, 32, 0)
86 	, m_data_config("data", ENDIANNESS_BIG, 32, 32, 0)
87 {
88 	memset( m_r, 0, sizeof(m_r) );
89 	memset( m_tlb, 0, sizeof(m_tlb) );
90 	m_vab = 0;
91 	m_ops = 0;
92 	m_cha = 0;
93 	m_chd = 0;
94 	m_chc = 0;
95 	m_rbp = 0;
96 	m_tmc = 0;
97 	m_tmr = 0;
98 	m_pc0 = 0;
99 	m_pc1 = 0;
100 	m_pc2 = 0;
101 	m_mmu = 0;
102 	m_lru = 0;
103 	m_ipc = 0;
104 	m_ipa = 0;
105 	m_ipb = 0;
106 	m_q = 0;
107 	m_alu = 0;
108 	m_fpe = 0;
109 	m_inte = 0;
110 	m_fps = 0;
111 	memset( m_exception_queue, 0, sizeof( m_exception_queue) );
112 	m_irq_active = 0;
113 	m_irq_lines = 0;
114 	m_exec_ir = 0;
115 	m_next_ir = 0;
116 	m_pl_flags = 0;
117 	m_iret_pc = 0;
118 	m_exec_pc = 0;
119 	m_next_pc = 0;
120 }
121 
memory_space_config() const122 device_memory_interface::space_config_vector am29000_cpu_device::memory_space_config() const
123 {
124 	return space_config_vector {
125 		std::make_pair(AS_PROGRAM, &m_program_config),
126 		std::make_pair(AS_DATA,    &m_data_config),
127 		std::make_pair(AS_IO,      &m_io_config)
128 	};
129 }
130 
device_start()131 void am29000_cpu_device::device_start()
132 {
133 	space(AS_PROGRAM).cache(m_cache);
134 	space(AS_PROGRAM).specific(m_program);
135 	space(AS_DATA).cache(m_datacache);
136 	space(AS_DATA).specific(m_data);
137 	space(AS_IO).specific(m_io);
138 
139 	m_cfg = (PRL_AM29000 | PRL_REV_D) << CFG_PRL_SHIFT;
140 
141 	/* Register state for saving */
142 	save_item(NAME(m_pc));
143 	save_item(NAME(m_r));
144 	save_item(NAME(m_tlb));
145 
146 	save_item(NAME(m_vab));
147 	save_item(NAME(m_ops));
148 	save_item(NAME(m_cps));
149 	save_item(NAME(m_cfg));
150 	save_item(NAME(m_cha));
151 	save_item(NAME(m_chd));
152 	save_item(NAME(m_chc));
153 	save_item(NAME(m_rbp));
154 	save_item(NAME(m_tmc));
155 	save_item(NAME(m_tmr));
156 	save_item(NAME(m_pc0));
157 	save_item(NAME(m_pc1));
158 	save_item(NAME(m_pc2));
159 	save_item(NAME(m_mmu));
160 	save_item(NAME(m_lru));
161 
162 	save_item(NAME(m_ipc));
163 	save_item(NAME(m_ipa));
164 	save_item(NAME(m_ipb));
165 	save_item(NAME(m_q));
166 
167 	save_item(NAME(m_alu));
168 	save_item(NAME(m_fpe));
169 	save_item(NAME(m_inte));
170 	save_item(NAME(m_fps));
171 
172 	save_item(NAME(m_exceptions));
173 	save_item(NAME(m_exception_queue));
174 
175 	save_item(NAME(m_irq_active));
176 	save_item(NAME(m_irq_lines));
177 
178 	save_item(NAME(m_exec_ir));
179 	save_item(NAME(m_next_ir));
180 
181 	save_item(NAME(m_pl_flags));
182 	save_item(NAME(m_next_pl_flags));
183 
184 	save_item(NAME(m_iret_pc));
185 	save_item(NAME(m_exec_pc));
186 	save_item(NAME(m_next_pc));
187 
188 	// Register state for debugger
189 	state_add( AM29000_PC,   "PC",   m_pc     ).callimport().formatstr("%08X");
190 	state_add( AM29000_VAB,  "VAB",  m_vab    ).formatstr("%08X");
191 	state_add( AM29000_OPS,  "OPS",  m_ops    ).formatstr("%08X");
192 	state_add( AM29000_CPS,  "CPS",  m_cps    ).formatstr("%08X");
193 	state_add( AM29000_CFG,  "CFG",  m_cfg    ).formatstr("%08X");
194 	state_add( AM29000_CHA,  "CHA",  m_cha    ).formatstr("%08X");
195 	state_add( AM29000_CHD,  "CHD",  m_chd    ).formatstr("%08X");
196 	state_add( AM29000_CHC,  "CHC",  m_chc    ).formatstr("%08X");
197 	state_add( AM29000_RBP,  "RBP",  m_rbp    ).formatstr("%08X");
198 	state_add( AM29000_TMC,  "TMC",  m_tmc    ).formatstr("%08X");
199 	state_add( AM29000_TMR,  "TMR",  m_tmr    ).formatstr("%08X");
200 	state_add( AM29000_PC0,  "PC0",  m_pc0    ).formatstr("%08X");
201 	state_add( AM29000_PC1,  "PC1",  m_pc1    ).formatstr("%08X");
202 	state_add( AM29000_PC2,  "PC2",  m_pc2    ).formatstr("%08X");
203 	state_add( AM29000_MMU,  "MMU",  m_mmu    ).formatstr("%08X");
204 	state_add( AM29000_LRU,  "LRU",  m_lru    ).formatstr("%08X");
205 	state_add( AM29000_IPC,  "IPC",  m_ipc    ).formatstr("%08X");
206 	state_add( AM29000_IPA,  "IPA",  m_ipa    ).formatstr("%08X");
207 	state_add( AM29000_IPB,  "IPB",  m_ipb    ).formatstr("%08X");
208 	state_add( AM29000_Q,    "Q",    m_q      ).formatstr("%08X");
209 	state_add( AM29000_ALU,  "ALU",  m_alu    ).formatstr("%08X");
210 //  state_add( AM29000_BP,   "BP",   GET_ALU_BP).formatstr("%08X");
211 //  state_add( AM29000_FC,   "FC",   GET_ALU_FC).formatstr("%08X");
212 //  state_add( AM29000_CR,   "CR",   GET_CHC_CR).formatstr("%08X");
213 	state_add( AM29000_FPE,  "FPE",  m_fpe    ).formatstr("%08X");
214 	state_add( AM29000_INTE, "INTE", m_inte   ).formatstr("%08X");
215 	state_add( AM29000_FPS,  "FPS",  m_fps    ).formatstr("%08X");
216 	state_add( AM29000_R1,   "R1",   m_r[1]   ).formatstr("%08X");
217 	state_add( AM29000_R64,  "R64",  m_r[64]  ).formatstr("%08X");
218 	state_add( AM29000_R65,  "R65",  m_r[65]  ).formatstr("%08X");
219 	state_add( AM29000_R66,  "R66",  m_r[66]  ).formatstr("%08X");
220 	state_add( AM29000_R67,  "R67",  m_r[67]  ).formatstr("%08X");
221 	state_add( AM29000_R68,  "R68",  m_r[68]  ).formatstr("%08X");
222 	state_add( AM29000_R69,  "R69",  m_r[69]  ).formatstr("%08X");
223 	state_add( AM29000_R70,  "R70",  m_r[70]  ).formatstr("%08X");
224 	state_add( AM29000_R71,  "R71",  m_r[71]  ).formatstr("%08X");
225 	state_add( AM29000_R72,  "R72",  m_r[72]  ).formatstr("%08X");
226 	state_add( AM29000_R73,  "R73",  m_r[73]  ).formatstr("%08X");
227 	state_add( AM29000_R74,  "R74",  m_r[74]  ).formatstr("%08X");
228 	state_add( AM29000_R75,  "R75",  m_r[75]  ).formatstr("%08X");
229 	state_add( AM29000_R76,  "R76",  m_r[76]  ).formatstr("%08X");
230 	state_add( AM29000_R77,  "R77",  m_r[77]  ).formatstr("%08X");
231 	state_add( AM29000_R78,  "R78",  m_r[78]  ).formatstr("%08X");
232 	state_add( AM29000_R79,  "R79",  m_r[79]  ).formatstr("%08X");
233 	state_add( AM29000_R80,  "R80",  m_r[80]  ).formatstr("%08X");
234 	state_add( AM29000_R81,  "R81",  m_r[81]  ).formatstr("%08X");
235 	state_add( AM29000_R82,  "R82",  m_r[82]  ).formatstr("%08X");
236 	state_add( AM29000_R83,  "R83",  m_r[83]  ).formatstr("%08X");
237 	state_add( AM29000_R84,  "R84",  m_r[84]  ).formatstr("%08X");
238 	state_add( AM29000_R85,  "R85",  m_r[85]  ).formatstr("%08X");
239 	state_add( AM29000_R86,  "R86",  m_r[86]  ).formatstr("%08X");
240 	state_add( AM29000_R87,  "R87",  m_r[87]  ).formatstr("%08X");
241 	state_add( AM29000_R88,  "R88",  m_r[88]  ).formatstr("%08X");
242 	state_add( AM29000_R89,  "R89",  m_r[89]  ).formatstr("%08X");
243 	state_add( AM29000_R90,  "R90",  m_r[90]  ).formatstr("%08X");
244 	state_add( AM29000_R91,  "R91",  m_r[91]  ).formatstr("%08X");
245 	state_add( AM29000_R92,  "R92",  m_r[92]  ).formatstr("%08X");
246 	state_add( AM29000_R93,  "R93",  m_r[93]  ).formatstr("%08X");
247 	state_add( AM29000_R94,  "R94",  m_r[94]  ).formatstr("%08X");
248 	state_add( AM29000_R95,  "R95",  m_r[95]  ).formatstr("%08X");
249 	state_add( AM29000_R96,  "R96",  m_r[96]  ).formatstr("%08X");
250 	state_add( AM29000_R97,  "R97",  m_r[97]  ).formatstr("%08X");
251 	state_add( AM29000_R98,  "R98",  m_r[98]  ).formatstr("%08X");
252 	state_add( AM29000_R99,  "R99",  m_r[99]  ).formatstr("%08X");
253 	state_add( AM29000_R100, "R100", m_r[100] ).formatstr("%08X");
254 	state_add( AM29000_R101, "R101", m_r[101] ).formatstr("%08X");
255 	state_add( AM29000_R102, "R102", m_r[102] ).formatstr("%08X");
256 	state_add( AM29000_R103, "R103", m_r[103] ).formatstr("%08X");
257 	state_add( AM29000_R104, "R104", m_r[104] ).formatstr("%08X");
258 	state_add( AM29000_R105, "R105", m_r[105] ).formatstr("%08X");
259 	state_add( AM29000_R106, "R106", m_r[106] ).formatstr("%08X");
260 	state_add( AM29000_R107, "R107", m_r[107] ).formatstr("%08X");
261 	state_add( AM29000_R108, "R108", m_r[108] ).formatstr("%08X");
262 	state_add( AM29000_R109, "R109", m_r[109] ).formatstr("%08X");
263 	state_add( AM29000_R110, "R110", m_r[110] ).formatstr("%08X");
264 	state_add( AM29000_R111, "R111", m_r[111] ).formatstr("%08X");
265 	state_add( AM29000_R112, "R112", m_r[112] ).formatstr("%08X");
266 	state_add( AM29000_R113, "R113", m_r[113] ).formatstr("%08X");
267 	state_add( AM29000_R114, "R114", m_r[114] ).formatstr("%08X");
268 	state_add( AM29000_R115, "R115", m_r[115] ).formatstr("%08X");
269 	state_add( AM29000_R116, "R116", m_r[116] ).formatstr("%08X");
270 	state_add( AM29000_R117, "R117", m_r[117] ).formatstr("%08X");
271 	state_add( AM29000_R118, "R118", m_r[118] ).formatstr("%08X");
272 	state_add( AM29000_R119, "R119", m_r[119] ).formatstr("%08X");
273 	state_add( AM29000_R120, "R120", m_r[120] ).formatstr("%08X");
274 	state_add( AM29000_R121, "R121", m_r[121] ).formatstr("%08X");
275 	state_add( AM29000_R122, "R122", m_r[122] ).formatstr("%08X");
276 	state_add( AM29000_R123, "R123", m_r[123] ).formatstr("%08X");
277 	state_add( AM29000_R124, "R124", m_r[124] ).formatstr("%08X");
278 	state_add( AM29000_R125, "R125", m_r[125] ).formatstr("%08X");
279 	state_add( AM29000_R126, "R126", m_r[126] ).formatstr("%08X");
280 	state_add( AM29000_R127, "R127", m_r[127] ).formatstr("%08X");
281 	state_add( AM29000_R128, "R128", m_r[128] ).formatstr("%08X");
282 	state_add( AM29000_R129, "R129", m_r[129] ).formatstr("%08X");
283 	state_add( AM29000_R130, "R130", m_r[130] ).formatstr("%08X");
284 	state_add( AM29000_R131, "R131", m_r[131] ).formatstr("%08X");
285 	state_add( AM29000_R132, "R132", m_r[132] ).formatstr("%08X");
286 	state_add( AM29000_R133, "R133", m_r[133] ).formatstr("%08X");
287 	state_add( AM29000_R134, "R134", m_r[134] ).formatstr("%08X");
288 	state_add( AM29000_R135, "R135", m_r[135] ).formatstr("%08X");
289 	state_add( AM29000_R136, "R136", m_r[136] ).formatstr("%08X");
290 	state_add( AM29000_R137, "R137", m_r[137] ).formatstr("%08X");
291 	state_add( AM29000_R138, "R138", m_r[138] ).formatstr("%08X");
292 	state_add( AM29000_R139, "R139", m_r[139] ).formatstr("%08X");
293 	state_add( AM29000_R140, "R140", m_r[140] ).formatstr("%08X");
294 	state_add( AM29000_R141, "R141", m_r[141] ).formatstr("%08X");
295 	state_add( AM29000_R142, "R142", m_r[142] ).formatstr("%08X");
296 	state_add( AM29000_R143, "R143", m_r[143] ).formatstr("%08X");
297 	state_add( AM29000_R144, "R144", m_r[144] ).formatstr("%08X");
298 	state_add( AM29000_R145, "R145", m_r[145] ).formatstr("%08X");
299 	state_add( AM29000_R146, "R146", m_r[146] ).formatstr("%08X");
300 	state_add( AM29000_R147, "R147", m_r[147] ).formatstr("%08X");
301 	state_add( AM29000_R148, "R148", m_r[148] ).formatstr("%08X");
302 	state_add( AM29000_R149, "R149", m_r[149] ).formatstr("%08X");
303 	state_add( AM29000_R150, "R150", m_r[150] ).formatstr("%08X");
304 	state_add( AM29000_R151, "R151", m_r[151] ).formatstr("%08X");
305 	state_add( AM29000_R152, "R152", m_r[152] ).formatstr("%08X");
306 	state_add( AM29000_R153, "R153", m_r[153] ).formatstr("%08X");
307 	state_add( AM29000_R154, "R154", m_r[154] ).formatstr("%08X");
308 	state_add( AM29000_R155, "R155", m_r[155] ).formatstr("%08X");
309 	state_add( AM29000_R156, "R156", m_r[156] ).formatstr("%08X");
310 	state_add( AM29000_R157, "R157", m_r[157] ).formatstr("%08X");
311 	state_add( AM29000_R158, "R158", m_r[158] ).formatstr("%08X");
312 	state_add( AM29000_R159, "R159", m_r[159] ).formatstr("%08X");
313 	state_add( AM29000_R160, "R160", m_r[160] ).formatstr("%08X");
314 	state_add( AM29000_R161, "R161", m_r[161] ).formatstr("%08X");
315 	state_add( AM29000_R162, "R162", m_r[162] ).formatstr("%08X");
316 	state_add( AM29000_R163, "R163", m_r[163] ).formatstr("%08X");
317 	state_add( AM29000_R164, "R164", m_r[164] ).formatstr("%08X");
318 	state_add( AM29000_R165, "R165", m_r[165] ).formatstr("%08X");
319 	state_add( AM29000_R166, "R166", m_r[166] ).formatstr("%08X");
320 	state_add( AM29000_R167, "R167", m_r[167] ).formatstr("%08X");
321 	state_add( AM29000_R168, "R168", m_r[168] ).formatstr("%08X");
322 	state_add( AM29000_R169, "R169", m_r[169] ).formatstr("%08X");
323 	state_add( AM29000_R170, "R170", m_r[170] ).formatstr("%08X");
324 	state_add( AM29000_R171, "R171", m_r[171] ).formatstr("%08X");
325 	state_add( AM29000_R172, "R172", m_r[172] ).formatstr("%08X");
326 	state_add( AM29000_R173, "R173", m_r[173] ).formatstr("%08X");
327 	state_add( AM29000_R174, "R174", m_r[174] ).formatstr("%08X");
328 	state_add( AM29000_R175, "R175", m_r[175] ).formatstr("%08X");
329 	state_add( AM29000_R176, "R176", m_r[176] ).formatstr("%08X");
330 	state_add( AM29000_R177, "R177", m_r[177] ).formatstr("%08X");
331 	state_add( AM29000_R178, "R178", m_r[178] ).formatstr("%08X");
332 	state_add( AM29000_R179, "R179", m_r[179] ).formatstr("%08X");
333 	state_add( AM29000_R180, "R180", m_r[180] ).formatstr("%08X");
334 	state_add( AM29000_R181, "R181", m_r[181] ).formatstr("%08X");
335 	state_add( AM29000_R182, "R182", m_r[182] ).formatstr("%08X");
336 	state_add( AM29000_R183, "R183", m_r[183] ).formatstr("%08X");
337 	state_add( AM29000_R184, "R184", m_r[184] ).formatstr("%08X");
338 	state_add( AM29000_R185, "R185", m_r[185] ).formatstr("%08X");
339 	state_add( AM29000_R186, "R186", m_r[186] ).formatstr("%08X");
340 	state_add( AM29000_R187, "R187", m_r[187] ).formatstr("%08X");
341 	state_add( AM29000_R188, "R188", m_r[188] ).formatstr("%08X");
342 	state_add( AM29000_R189, "R189", m_r[189] ).formatstr("%08X");
343 	state_add( AM29000_R190, "R190", m_r[190] ).formatstr("%08X");
344 	state_add( AM29000_R191, "R191", m_r[191] ).formatstr("%08X");
345 	state_add( AM29000_R192, "R192", m_r[192] ).formatstr("%08X");
346 	state_add( AM29000_R193, "R193", m_r[193] ).formatstr("%08X");
347 	state_add( AM29000_R194, "R194", m_r[194] ).formatstr("%08X");
348 	state_add( AM29000_R195, "R195", m_r[195] ).formatstr("%08X");
349 	state_add( AM29000_R196, "R196", m_r[196] ).formatstr("%08X");
350 	state_add( AM29000_R197, "R197", m_r[197] ).formatstr("%08X");
351 	state_add( AM29000_R198, "R198", m_r[198] ).formatstr("%08X");
352 	state_add( AM29000_R199, "R199", m_r[199] ).formatstr("%08X");
353 	state_add( AM29000_R200, "R200", m_r[200] ).formatstr("%08X");
354 	state_add( AM29000_R201, "R201", m_r[201] ).formatstr("%08X");
355 	state_add( AM29000_R202, "R202", m_r[202] ).formatstr("%08X");
356 	state_add( AM29000_R203, "R203", m_r[203] ).formatstr("%08X");
357 	state_add( AM29000_R204, "R204", m_r[204] ).formatstr("%08X");
358 	state_add( AM29000_R205, "R205", m_r[205] ).formatstr("%08X");
359 	state_add( AM29000_R206, "R206", m_r[206] ).formatstr("%08X");
360 	state_add( AM29000_R207, "R207", m_r[207] ).formatstr("%08X");
361 	state_add( AM29000_R208, "R208", m_r[208] ).formatstr("%08X");
362 	state_add( AM29000_R209, "R209", m_r[209] ).formatstr("%08X");
363 	state_add( AM29000_R210, "R210", m_r[210] ).formatstr("%08X");
364 	state_add( AM29000_R211, "R211", m_r[211] ).formatstr("%08X");
365 	state_add( AM29000_R212, "R212", m_r[212] ).formatstr("%08X");
366 	state_add( AM29000_R213, "R213", m_r[213] ).formatstr("%08X");
367 	state_add( AM29000_R214, "R214", m_r[214] ).formatstr("%08X");
368 	state_add( AM29000_R215, "R215", m_r[215] ).formatstr("%08X");
369 	state_add( AM29000_R216, "R216", m_r[216] ).formatstr("%08X");
370 	state_add( AM29000_R217, "R217", m_r[217] ).formatstr("%08X");
371 	state_add( AM29000_R218, "R218", m_r[218] ).formatstr("%08X");
372 	state_add( AM29000_R219, "R219", m_r[219] ).formatstr("%08X");
373 	state_add( AM29000_R220, "R220", m_r[220] ).formatstr("%08X");
374 	state_add( AM29000_R221, "R221", m_r[221] ).formatstr("%08X");
375 	state_add( AM29000_R222, "R222", m_r[222] ).formatstr("%08X");
376 	state_add( AM29000_R223, "R223", m_r[223] ).formatstr("%08X");
377 	state_add( AM29000_R224, "R224", m_r[224] ).formatstr("%08X");
378 	state_add( AM29000_R225, "R225", m_r[225] ).formatstr("%08X");
379 	state_add( AM29000_R226, "R226", m_r[226] ).formatstr("%08X");
380 	state_add( AM29000_R227, "R227", m_r[227] ).formatstr("%08X");
381 	state_add( AM29000_R228, "R228", m_r[228] ).formatstr("%08X");
382 	state_add( AM29000_R229, "R229", m_r[229] ).formatstr("%08X");
383 	state_add( AM29000_R230, "R230", m_r[230] ).formatstr("%08X");
384 	state_add( AM29000_R231, "R231", m_r[231] ).formatstr("%08X");
385 	state_add( AM29000_R232, "R232", m_r[232] ).formatstr("%08X");
386 	state_add( AM29000_R233, "R233", m_r[233] ).formatstr("%08X");
387 	state_add( AM29000_R234, "R234", m_r[234] ).formatstr("%08X");
388 	state_add( AM29000_R235, "R235", m_r[235] ).formatstr("%08X");
389 	state_add( AM29000_R236, "R236", m_r[236] ).formatstr("%08X");
390 	state_add( AM29000_R237, "R237", m_r[237] ).formatstr("%08X");
391 	state_add( AM29000_R238, "R238", m_r[238] ).formatstr("%08X");
392 	state_add( AM29000_R239, "R239", m_r[239] ).formatstr("%08X");
393 	state_add( AM29000_R240, "R240", m_r[240] ).formatstr("%08X");
394 	state_add( AM29000_R241, "R241", m_r[241] ).formatstr("%08X");
395 	state_add( AM29000_R242, "R242", m_r[242] ).formatstr("%08X");
396 	state_add( AM29000_R243, "R243", m_r[243] ).formatstr("%08X");
397 	state_add( AM29000_R244, "R244", m_r[244] ).formatstr("%08X");
398 	state_add( AM29000_R245, "R245", m_r[245] ).formatstr("%08X");
399 	state_add( AM29000_R246, "R246", m_r[246] ).formatstr("%08X");
400 	state_add( AM29000_R247, "R247", m_r[247] ).formatstr("%08X");
401 	state_add( AM29000_R248, "R248", m_r[248] ).formatstr("%08X");
402 	state_add( AM29000_R249, "R249", m_r[249] ).formatstr("%08X");
403 	state_add( AM29000_R250, "R250", m_r[250] ).formatstr("%08X");
404 	state_add( AM29000_R251, "R251", m_r[251] ).formatstr("%08X");
405 	state_add( AM29000_R252, "R252", m_r[252] ).formatstr("%08X");
406 	state_add( AM29000_R253, "R253", m_r[253] ).formatstr("%08X");
407 	state_add( AM29000_R254, "R254", m_r[254] ).formatstr("%08X");
408 	state_add( AM29000_R255, "R255", m_r[255] ).formatstr("%08X");
409 
410 	state_add(STATE_GENPCBASE, "CURPC", m_pc).callimport().noshow();
411 	state_add(STATE_GENFLAGS, "CURFLAGS", m_alu).formatstr("%13s").noshow();
412 
413 	set_icountptr(m_icount);
414 }
415 
416 
417 //-------------------------------------------------
418 //  state_import - import state into the device,
419 //  after it has been set
420 //-------------------------------------------------
421 
state_import(const device_state_entry & entry)422 void am29000_cpu_device::state_import(const device_state_entry &entry)
423 {
424 	switch (entry.index())
425 	{
426 	case AM29000_PC:
427 	case STATE_GENPCBASE:
428 		m_next_pc = m_pc;
429 		break;
430 	}
431 }
432 
433 
434 //-------------------------------------------------
435 //  state_string_export - export state as a string
436 //  for the debugger
437 //-------------------------------------------------
438 
state_string_export(const device_state_entry & entry,std::string & str) const439 void am29000_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
440 {
441 	switch (entry.index())
442 	{
443 		case STATE_GENFLAGS:
444 			str = string_format("%c%c%c%c%c%c%c%c%c|%3d",
445 					m_alu & ALU_V ? 'V' : '.',
446 					m_alu & ALU_Z ? 'Z' : '.',
447 					m_alu & ALU_N ? 'N' : '.',
448 					m_alu & ALU_C ? 'C' : '.',
449 					m_cps & CPS_IP ? 'I' : '.',
450 					m_cps & CPS_FZ ? 'F' : '.',
451 					m_cps & CPS_SM ? 'S' : 'U',
452 					m_cps & CPS_DI ? 'I' : '.',
453 					m_cps & CPS_DA ? 'D' : '.',
454 					(m_r[1] >> 2) & 0x7f);
455 			break;
456 	}
457 }
458 
459 
device_reset()460 void am29000_cpu_device::device_reset()
461 {
462 	m_cps = CPS_FZ | CPS_RE | CPS_PD | CPS_PI | CPS_SM | CPS_DI | CPS_DA;
463 	m_cfg &= ~(CFG_DW | CFG_CD);
464 	m_chc &= ~CHC_CV;
465 
466 	m_pc = 0;
467 	m_next_pl_flags = 0;
468 	m_exceptions = 0;
469 	m_irq_lines = 0;
470 }
471 
472 
signal_exception(uint32_t type)473 void am29000_cpu_device::signal_exception(uint32_t type)
474 {
475 	m_exception_queue[m_exceptions++] = type;
476 }
477 
478 
external_irq_check()479 void am29000_cpu_device::external_irq_check()
480 {
481 	int mask = (m_cps >> CPS_IM_SHIFT) & CPS_IM_MASK;
482 	int irq_en = !(m_cps & CPS_DI) && !(m_cps & CPS_DA);
483 	int i;
484 
485 	/* Clear interrupt pending bit to begin with */
486 	m_cps &= ~CPS_IP;
487 
488 	for (i = 0; i < 4; ++i)
489 	{
490 		if (!(m_irq_active & (1 << i)) && (m_irq_lines & (1 << i)))
491 		{
492 			if (irq_en)
493 			{
494 				if (i <= mask)
495 				{
496 					m_irq_active |= (1 << i);
497 					signal_exception(EXCEPTION_INTR0 + i);
498 					m_pl_flags |= PFLAG_IRQ;
499 					return;
500 				}
501 			}
502 			/* Set interrupt pending bit if interrupt was disabled */
503 			m_cps |= CPS_IP;
504 		}
505 		else
506 			m_irq_active &= ~(1 << i);
507 	}
508 }
509 
510 
read_program_word(uint32_t address)511 uint32_t am29000_cpu_device::read_program_word(uint32_t address)
512 {
513 	/* TODO: ROM enable? */
514 	if (m_cps & CPS_PI || m_cps & CPS_RE)
515 		return m_cache.read_dword(address);
516 	else
517 	{
518 		fatalerror("Am29000 instruction MMU translation enabled!\n");
519 	}
520 	// never executed
521 	//return 0;
522 }
523 
524 /***************************************************************************
525     HELPER FUNCTIONS
526 ***************************************************************************/
527 
get_abs_reg(uint8_t r,uint32_t iptr)528 uint32_t am29000_cpu_device::get_abs_reg(uint8_t r, uint32_t iptr)
529 {
530 	if (r & 0x80)
531 	{
532 		/* Stack pointer access */
533 		r = ((m_r[1] >> 2) & 0x7f) + (r & 0x7f);
534 		r |= 0x80;
535 	}
536 	else if (r == 0)
537 	{
538 		/* Indirect pointer access */
539 		r = (iptr >> IPX_SHIFT) & 0xff;
540 	}
541 	else if (r > 1 && r < 64)
542 	{
543 		fatalerror("Am29000: Undefined register access (%d)\n", r);
544 	}
545 	return r;
546 }
547 
548 
549 /***************************************************************************
550     CORE INCLUDE
551 ***************************************************************************/
552 
553 #include "am29ops.h"
554 
555 
556 /***************************************************************************
557     PIPELINE STAGES
558 ***************************************************************************/
559 
fetch_decode()560 void am29000_cpu_device::fetch_decode()
561 {
562 	uint32_t inst;
563 	uint32_t op_flags;
564 
565 	inst = read_program_word(m_pc);
566 	m_next_ir = inst;
567 
568 	op_flags = op_table[inst >> 24].flags;
569 
570 	/* Illegal instruction */
571 	/* TODO: This should be checked at this point */
572 #if 0
573 	if (op_flags & IFLAG_ILLEGAL)
574 	{
575 		fatalerror("Illegal instruction: %x PC:%x PC0:%x PC1:%x\n", inst, m_pc, m_pc0, m_pc1);
576 		SIGNAL_EXCEPTION(EXCEPTION_ILLEGAL_OPCODE);
577 		return;
578 	}
579 #endif
580 
581 	/* Privledge violations */
582 	if (USER_MODE)
583 	{
584 		if ((op_flags & IFLAG_SUPERVISOR_ONLY))
585 		{
586 			signal_exception(EXCEPTION_PROTECTION_VIOLATION);
587 			return;
588 		}
589 
590 		if ((op_flags & IFLAG_SPR_ACCESS))
591 		{
592 			/* TODO: Is this the right place to check this? */
593 			if (INST_SA_FIELD(inst) < 128)
594 			{
595 				SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
596 				return;
597 			}
598 		}
599 
600 		/* Register bank protection */
601 		if ((op_flags & IFLAG_RA_PRESENT) && REGISTER_IS_PROTECTED(INST_RA_FIELD(inst)))
602 		{
603 			SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
604 			return;
605 		}
606 
607 		if ((op_flags & IFLAG_RB_PRESENT) && REGISTER_IS_PROTECTED(INST_RB_FIELD(inst)))
608 		{
609 			SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
610 			return;
611 		}
612 
613 		if ((op_flags & IFLAG_RC_PRESENT) && REGISTER_IS_PROTECTED(INST_RC_FIELD(inst)))
614 		{
615 			SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
616 			return;
617 		}
618 	}
619 
620 	if (m_pl_flags & PFLAG_IRET)
621 		m_next_pc = m_iret_pc;
622 	else
623 		m_next_pc += 4;
624 }
625 
626 /***************************************************************************
627     CORE EXECUTION LOOP
628 ***************************************************************************/
629 
execute_run()630 void am29000_cpu_device::execute_run()
631 {
632 	uint32_t call_debugger = (machine().debug_flags & DEBUG_FLAG_ENABLED) != 0;
633 
634 	external_irq_check();
635 
636 	do
637 	{
638 		m_next_pl_flags = PFLAG_EXECUTE_EN;
639 
640 		if (!FREEZE_MODE)
641 		{
642 			m_pc1 = m_pc0;
643 			m_pc0 = m_pc;
644 		}
645 
646 		if (m_exceptions)
647 		{
648 			m_ops = m_cps;
649 			m_cps &= ~(CPS_TE | CPS_TP | CPS_TU | CPS_FZ | CPS_LK | CPS_WM | CPS_PD | CPS_PI | CPS_SM | CPS_DI | CPS_DA);
650 			m_cps |= (CPS_FZ | CPS_PD | CPS_PI | CPS_SM | CPS_DI | CPS_DA);
651 
652 			if (m_pl_flags & PFLAG_IRET)
653 			{
654 				m_pc0 = m_iret_pc;
655 				m_pc1 = m_next_pc;
656 			}
657 
658 
659 			if (m_cfg & CFG_VF)
660 			{
661 				uint32_t vaddr = m_vab | m_exception_queue[0] * 4;
662 				uint32_t vect = m_datacache.read_dword(vaddr);
663 
664 				m_pc = vect & ~3;
665 				m_next_pc = m_pc;
666 			}
667 			else
668 			{
669 				fatalerror("Am29000: Non vectored interrupt fetch!\n");
670 			}
671 
672 			m_exceptions = 0;
673 			m_pl_flags = 0;
674 		}
675 
676 		if (call_debugger)
677 			debugger_instruction_hook(m_pc);
678 
679 		fetch_decode();
680 
681 		if (m_pl_flags & PFLAG_EXECUTE_EN)
682 		{
683 			if (!FREEZE_MODE)
684 				m_pc2 = m_pc1;
685 
686 			(this->*op_table[m_exec_ir >> 24].opcode)();
687 		}
688 
689 		m_exec_ir = m_next_ir;
690 		m_pl_flags = m_next_pl_flags;
691 		m_exec_pc = m_pc;
692 		m_pc = m_next_pc;
693 	} while (--m_icount > 0);
694 }
695 
696 
execute_set_input(int inputnum,int state)697 void am29000_cpu_device::execute_set_input(int inputnum, int state)
698 {
699 	if (state)
700 		m_irq_lines |= (1 << inputnum);
701 	else
702 		m_irq_lines &= ~(1 << inputnum);
703 
704 	// TODO : CHECK IRQs
705 }
706 
create_disassembler()707 std::unique_ptr<util::disasm_interface> am29000_cpu_device::create_disassembler()
708 {
709 	return std::make_unique<am29000_disassembler>();
710 }
711