1/* V810 Emulator
2 *
3 * Copyright (C) 2006 David Tucker
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20
21    // Macro test taken from http://gcc.gnu.org/viewcvs/trunk/gcc/testsuite/gcc.dg/20020919-1.c?view=markup&pathrev=142696
22    //#if defined (__powerpc__) || defined (__PPC__) || defined (__ppc__)	|| defined (__POWERPC__) || defined (PPC) || defined (_IBMR2)
23    //	v810_timestamp_t timestamp_rl asm("15") = v810_timestamp;
24    //#elif defined(__x86_64__)
25    //	v810_timestamp_t timestamp_rl asm("r11") = v810_timestamp;
26    //#else
27	v810_timestamp_t timestamp_rl = v810_timestamp;
28    //#endif
29
30    uint32 opcode;
31    uint32 tmp2;
32    int val = 0;
33
34
35    #define ADDCLOCK(__n) { timestamp += __n; }
36
37    #define CHECK_HALTED();	{ if(Halted && timestamp < next_event_ts) { timestamp = next_event_ts; } }
38
39    while(Running)
40    {
41     #ifdef RB_DEBUGMODE
42     uint32 old_PC = RB_GETPC();
43     #endif
44     uint32 tmpop;
45
46     assert(timestamp_rl <= next_event_ts);
47
48     if(!IPendingCache)
49     {
50      if(Halted)
51      {
52       timestamp_rl = next_event_ts;
53      }
54      else if(in_bstr)
55      {
56       tmpop = in_bstr_to;
57       opcode = tmpop >> 9;
58       goto op_BSTR;
59      }
60     }
61
62     while(timestamp_rl < next_event_ts)
63     {
64	#ifdef RB_DEBUGMODE
65	old_PC = RB_GETPC();
66	#endif
67
68        P_REG[0] = 0; //Zero the Zero Reg!!!
69
70	RB_CPUHOOK(RB_GETPC());
71
72	{
73	 //printf("%08x\n", RB_GETPC());
74	 {
75	  v810_timestamp_t timestamp = timestamp_rl;
76
77	  tmpop = RB_RDOP(0, 0);
78
79	  timestamp_rl = timestamp;
80	 }
81
82       	 opcode = (tmpop >> 9) | IPendingCache;
83
84	 //printf("%02x\n", opcode >> 1);
85#if HAVE_COMPUTED_GOTO
86	 #define CGBEGIN static const void *const op_goto_table[256] = {
87	 #define CGE(l) &&l,
88	 #define CGEND }; goto *op_goto_table[opcode];
89#else
90	 /* (uint8) cast for cheaper alternative to generated branch+compare bounds check instructions, but still more
91 	    expensive than computed goto which needs no masking nor bounds checking.
92         */
93	 #define CGBEGIN { enum { CGESB = 1 + __COUNTER__ }; switch((uint8)opcode) {
94	 #define CGE(l) case __COUNTER__ - CGESB: goto l;
95	 #define CGEND } }
96#endif
97
98	 CGBEGIN
99		CGE(op_MOV)   CGE(op_MOV)   CGE(op_ADD)   CGE(op_ADD)   CGE(op_SUB)     CGE(op_SUB)     CGE(op_CMP)     CGE(op_CMP)
100		CGE(op_SHL)   CGE(op_SHL)   CGE(op_SHR)   CGE(op_SHR)   CGE(op_JMP)     CGE(op_JMP)     CGE(op_SAR)     CGE(op_SAR)
101		CGE(op_MUL)   CGE(op_MUL)   CGE(op_DIV)   CGE(op_DIV)   CGE(op_MULU)    CGE(op_MULU)    CGE(op_DIVU)    CGE(op_DIVU)
102		CGE(op_OR)    CGE(op_OR)    CGE(op_AND)   CGE(op_AND)   CGE(op_XOR)     CGE(op_XOR)     CGE(op_NOT)     CGE(op_NOT)
103		CGE(op_MOV_I) CGE(op_MOV_I) CGE(op_ADD_I) CGE(op_ADD_I) CGE(op_SETF)    CGE(op_SETF)    CGE(op_CMP_I)   CGE(op_CMP_I)
104		CGE(op_SHL_I) CGE(op_SHL_I) CGE(op_SHR_I) CGE(op_SHR_I) CGE(op_EI)      CGE(op_EI)      CGE(op_SAR_I)   CGE(op_SAR_I)
105		CGE(op_TRAP)  CGE(op_TRAP)  CGE(op_RETI)  CGE(op_RETI)  CGE(op_HALT)    CGE(op_HALT)    CGE(op_INVALID) CGE(op_INVALID)
106		CGE(op_LDSR)  CGE(op_LDSR)  CGE(op_STSR)  CGE(op_STSR)  CGE(op_DI)      CGE(op_DI)      CGE(op_BSTR)    CGE(op_BSTR)
107		CGE(op_BV)    CGE(op_BL)    CGE(op_BE)    CGE(op_BNH)   CGE(op_BN)      CGE(op_BR)      CGE(op_BLT)     CGE(op_BLE)
108		CGE(op_BNV)   CGE(op_BNL)   CGE(op_BNE)   CGE(op_BH)    CGE(op_BP)      CGE(op_NOP)     CGE(op_BGE)     CGE(op_BGT)
109		CGE(op_MOVEA) CGE(op_MOVEA) CGE(op_ADDI)  CGE(op_ADDI)  CGE(op_JR)      CGE(op_JR)      CGE(op_JAL)     CGE(op_JAL)
110		CGE(op_ORI)   CGE(op_ORI)   CGE(op_ANDI)  CGE(op_ANDI)  CGE(op_XORI)    CGE(op_XORI)    CGE(op_MOVHI)   CGE(op_MOVHI)
111		CGE(op_LD_B)  CGE(op_LD_B)  CGE(op_LD_H)  CGE(op_LD_H)  CGE(op_INVALID) CGE(op_INVALID) CGE(op_LD_W)    CGE(op_LD_W)
112		CGE(op_ST_B)  CGE(op_ST_B)  CGE(op_ST_H)  CGE(op_ST_H)  CGE(op_INVALID) CGE(op_INVALID) CGE(op_ST_W)    CGE(op_ST_W)
113		CGE(op_IN_B)  CGE(op_IN_B)  CGE(op_IN_H)  CGE(op_IN_H)  CGE(op_CAXI)    CGE(op_CAXI)    CGE(op_IN_W)    CGE(op_IN_W)
114		CGE(op_OUT_B) CGE(op_OUT_B) CGE(op_OUT_H) CGE(op_OUT_H) CGE(op_FPP)     CGE(op_FPP)     CGE(op_OUT_W)   CGE(op_OUT_W)
115
116		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
117		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
118		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
119		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
120		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
121		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
122		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
123		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
124
125		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
126		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
127		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
128		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
129		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
130		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
131		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID)
132		CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INT_HANDLER)
133	 CGEND
134
135	// Bit string subopcodes
136        #define DO_AM_BSTR()							\
137            const uint32 arg1 = (tmpop >> 5) & 0x1F;				\
138            const uint32 arg2 = (tmpop & 0x1F);					\
139            RB_INCPCBY2();
140
141
142        #define DO_AM_FPP()							\
143            const uint32 arg1 = (tmpop >> 5) & 0x1F;				\
144            const uint32 arg2 = (tmpop & 0x1F);					\
145            const uint32 arg3 = ((RB_RDOP(2) >> 10)&0x3F);			\
146	    RB_INCPCBY4();
147
148
149        #define DO_AM_UDEF()					\
150            RB_INCPCBY2();
151
152        #define DO_AM_I()					\
153            const uint32 arg1 = tmpop & 0x1F;			\
154            const uint32 arg2 = (tmpop >> 5) & 0x1F;		\
155            RB_INCPCBY2();
156
157	#define DO_AM_II() DO_AM_I();
158
159
160        #define DO_AM_IV()					\
161	    const uint32 arg1 = ((tmpop & 0x000003FF) << 16) | RB_RDOP(2);	\
162
163
164        #define DO_AM_V()					\
165            const uint32 arg3 = (tmpop >> 5) & 0x1F;		\
166            const uint32 arg2 = tmpop & 0x1F;			\
167            const uint32 arg1 = RB_RDOP(2);	\
168            RB_INCPCBY4();
169
170
171        #define DO_AM_VIa()					\
172            const uint32 arg1 = RB_RDOP(2);	\
173            const uint32 arg2 = tmpop & 0x1F;			\
174            const uint32 arg3 = (tmpop >> 5) & 0x1F;		\
175            RB_INCPCBY4();						\
176
177
178        #define DO_AM_VIb()					\
179            const uint32 arg1 = (tmpop >> 5) & 0x1F;		\
180            const uint32 arg2 = RB_RDOP(2);	\
181            const uint32 arg3 = (tmpop & 0x1F);			\
182            RB_INCPCBY4();					\
183
184        #define DO_AM_IX()					\
185            const uint32 arg1 = (tmpop & 0x1);			\
186            RB_INCPCBY2();					\
187
188        #define DO_AM_III()					\
189            const uint32 arg1 = tmpop & 0x1FE;
190
191	#include "v810_do_am.h"
192
193	 #define BEGIN_OP(meowtmpop) { op_##meowtmpop: v810_timestamp_t timestamp = timestamp_rl; DO_##meowtmpop ##_AM();
194	 #define END_OP()		timestamp_rl = timestamp; goto OpFinished; }
195	 #define END_OP_SKIPLO()       	timestamp_rl = timestamp; goto OpFinishedSkipLO; }
196
197	BEGIN_OP(MOV);
198	    ADDCLOCK(1);
199            SetPREG(arg2, P_REG[arg1]);
200	END_OP();
201
202
203	BEGIN_OP(ADD);
204             ADDCLOCK(1);
205             uint32 temp = P_REG[arg2] + P_REG[arg1];
206
207             SetFlag(PSW_OV, ((P_REG[arg2]^(~P_REG[arg1]))&(P_REG[arg2]^temp))&0x80000000);
208             SetFlag(PSW_CY, temp < P_REG[arg2]);
209
210             SetPREG(arg2, temp);
211	     SetSZ(P_REG[arg2]);
212	END_OP();
213
214
215	BEGIN_OP(SUB);
216             ADDCLOCK(1);
217	     uint32 temp = P_REG[arg2] - P_REG[arg1];
218
219             SetFlag(PSW_OV, ((P_REG[arg2]^P_REG[arg1])&(P_REG[arg2]^temp))&0x80000000);
220             SetFlag(PSW_CY, temp > P_REG[arg2]);
221
222	     SetPREG(arg2, temp);
223	     SetSZ(P_REG[arg2]);
224	END_OP();
225
226
227	BEGIN_OP(CMP);
228             ADDCLOCK(1);
229 	     uint32 temp = P_REG[arg2] - P_REG[arg1];
230
231	     SetSZ(temp);
232             SetFlag(PSW_OV, ((P_REG[arg2]^P_REG[arg1])&(P_REG[arg2]^temp))&0x80000000);
233	     SetFlag(PSW_CY, temp > P_REG[arg2]);
234	END_OP();
235
236
237	BEGIN_OP(SHL);
238            ADDCLOCK(1);
239            val = P_REG[arg1] & 0x1F;
240
241            // set CY before we destroy the regisrer info....
242            SetFlag(PSW_CY, (val != 0) && ((P_REG[arg2] >> (32 - val))&0x01) );
243	    SetFlag(PSW_OV, FALSE);
244            SetPREG(arg2, P_REG[arg2] << val);
245	    SetSZ(P_REG[arg2]);
246	END_OP();
247
248	BEGIN_OP(SHR);
249            ADDCLOCK(1);
250            val = P_REG[arg1] & 0x1F;
251            // set CY before we destroy the regisrer info....
252            SetFlag(PSW_CY, (val) && ((P_REG[arg2] >> (val-1))&0x01));
253	    SetFlag(PSW_OV, FALSE);
254	    SetPREG(arg2, P_REG[arg2] >> val);
255	    SetSZ(P_REG[arg2]);
256	END_OP();
257
258	BEGIN_OP(JMP);
259
260	    (void)arg2;		// arg2 is unused.
261
262            ADDCLOCK(3);
263            RB_SETPC((P_REG[arg1] & 0xFFFFFFFE));
264	    if(RB_AccurateMode)
265	    {
266	     BRANCH_ALIGN_CHECK(PC);
267	    }
268	    RB_ADDBT(old_PC, RB_GETPC(), 0);
269	END_OP();
270
271	BEGIN_OP(SAR);
272            ADDCLOCK(1);
273            val = P_REG[arg1] & 0x1F;
274
275	    SetFlag(PSW_CY, (val) && ((P_REG[arg2]>>(val-1))&0x01) );
276	    SetFlag(PSW_OV, FALSE);
277
278	    SetPREG(arg2, (uint32) ((int32)P_REG[arg2] >> val));
279
280	    SetSZ(P_REG[arg2]);
281	END_OP();
282
283	BEGIN_OP(OR);
284            ADDCLOCK(1);
285            SetPREG(arg2, P_REG[arg1] | P_REG[arg2]);
286	    SetFlag(PSW_OV, FALSE);
287	    SetSZ(P_REG[arg2]);
288	END_OP();
289
290	BEGIN_OP(AND);
291            ADDCLOCK(1);
292            SetPREG(arg2, P_REG[arg1] & P_REG[arg2]);
293	    SetFlag(PSW_OV, FALSE);
294	    SetSZ(P_REG[arg2]);
295	END_OP();
296
297	BEGIN_OP(XOR);
298            ADDCLOCK(1);
299	    SetPREG(arg2, P_REG[arg1] ^ P_REG[arg2]);
300	    SetFlag(PSW_OV, FALSE);
301	    SetSZ(P_REG[arg2]);
302	END_OP();
303
304	BEGIN_OP(NOT);
305            ADDCLOCK(1);
306	    SetPREG(arg2, ~P_REG[arg1]);
307	    SetFlag(PSW_OV, FALSE);
308	    SetSZ(P_REG[arg2]);
309	END_OP();
310
311	BEGIN_OP(MOV_I);
312            ADDCLOCK(1);
313            SetPREG(arg2,sign_5(arg1));
314	END_OP();
315
316	BEGIN_OP(ADD_I);
317             ADDCLOCK(1);
318             uint32 temp = P_REG[arg2] + sign_5(arg1);
319
320             SetFlag(PSW_OV, ((P_REG[arg2]^(~sign_5(arg1)))&(P_REG[arg2]^temp))&0x80000000);
321	     SetFlag(PSW_CY, (uint32)temp < P_REG[arg2]);
322
323             SetPREG(arg2, (uint32)temp);
324	     SetSZ(P_REG[arg2]);
325	END_OP();
326
327
328	BEGIN_OP(SETF);
329		ADDCLOCK(1);
330
331		P_REG[arg2] = 0;
332
333		switch (arg1 & 0x0F)
334		{
335			case COND_V:
336				if (TESTCOND_V) P_REG[arg2] = 1;
337				break;
338			case COND_C:
339				if (TESTCOND_C) P_REG[arg2] = 1;
340				break;
341			case COND_Z:
342				if (TESTCOND_Z) P_REG[arg2] = 1;
343				break;
344			case COND_NH:
345				if (TESTCOND_NH) P_REG[arg2] = 1;
346				break;
347			case COND_S:
348				if (TESTCOND_S) P_REG[arg2] = 1;
349				break;
350			case COND_T:
351				P_REG[arg2] = 1;
352				break;
353			case COND_LT:
354				if (TESTCOND_LT) P_REG[arg2] = 1;
355				break;
356			case COND_LE:
357				if (TESTCOND_LE) P_REG[arg2] = 1;
358				break;
359			case COND_NV:
360				if (TESTCOND_NV) P_REG[arg2] = 1;
361				break;
362			case COND_NC:
363				if (TESTCOND_NC) P_REG[arg2] = 1;
364				break;
365			case COND_NZ:
366				if (TESTCOND_NZ) P_REG[arg2] = 1;
367				break;
368			case COND_H:
369				if (TESTCOND_H) P_REG[arg2] = 1;
370				break;
371			case COND_NS:
372				if (TESTCOND_NS) P_REG[arg2] = 1;
373				break;
374			case COND_F:
375				//always false! do nothing more
376				break;
377			case COND_GE:
378				if (TESTCOND_GE) P_REG[arg2] = 1;
379				break;
380			case COND_GT:
381				if (TESTCOND_GT) P_REG[arg2] = 1;
382				break;
383		}
384	END_OP();
385
386	BEGIN_OP(CMP_I);
387             ADDCLOCK(1);
388	     uint32 temp = P_REG[arg2] - sign_5(arg1);
389
390	     SetSZ(temp);
391             SetFlag(PSW_OV, ((P_REG[arg2]^(sign_5(arg1)))&(P_REG[arg2]^temp))&0x80000000);
392	     SetFlag(PSW_CY, temp > P_REG[arg2]);
393	END_OP();
394
395	BEGIN_OP(SHR_I);
396            ADDCLOCK(1);
397	    SetFlag(PSW_CY, arg1 && ((P_REG[arg2] >> (arg1-1))&0x01) );
398            // set CY before we destroy the regisrer info....
399            SetPREG(arg2, P_REG[arg2] >> arg1);
400	    SetFlag(PSW_OV, FALSE);
401	    SetSZ(P_REG[arg2]);
402	END_OP();
403
404	BEGIN_OP(SHL_I);
405            ADDCLOCK(1);
406            SetFlag(PSW_CY, arg1 && ((P_REG[arg2] >> (32 - arg1))&0x01) );
407            // set CY before we destroy the regisrer info....
408
409            SetPREG(arg2, P_REG[arg2] << arg1);
410	    SetFlag(PSW_OV, FALSE);
411	    SetSZ(P_REG[arg2]);
412	END_OP();
413
414	BEGIN_OP(SAR_I);
415            ADDCLOCK(1);
416 	    SetFlag(PSW_CY, arg1 && ((P_REG[arg2]>>(arg1-1))&0x01) );
417
418            SetPREG(arg2, (uint32) ((int32)P_REG[arg2] >> arg1));
419
420	    SetFlag(PSW_OV, FALSE);
421	    SetSZ(P_REG[arg2]);
422	END_OP();
423
424	BEGIN_OP(LDSR);		// Loads a Sys Reg with the value in specified PR
425             ADDCLOCK(1);	// ?
426
427	     SetSREG(timestamp, arg1 & 0x1F, P_REG[arg2 & 0x1F]);
428	END_OP();
429
430	BEGIN_OP(STSR);		// Loads a PR with the value in specified Sys Reg
431             ADDCLOCK(1);	// ?
432             P_REG[arg2 & 0x1F] = GetSREG(arg1 & 0x1F);
433	END_OP();
434
435        BEGIN_OP(EI);
436	    (void)arg1;         // arg1 is unused.
437	    (void)arg2;         // arg2 is unused.
438
439	    if(VBMode)
440	    {
441             ADDCLOCK(1);
442             S_REG[PSW] = S_REG[PSW] &~ PSW_ID;
443	     RecalcIPendingCache();
444	    }
445	    else
446	    {
447	     ADDCLOCK(1);
448	     RB_DECPCBY2();
449             Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP);
450             CHECK_HALTED();
451	    }
452        END_OP();
453
454	BEGIN_OP(DI);
455            (void)arg1;         // arg1 is unused.
456            (void)arg2;         // arg2 is unused.
457
458            if(VBMode)
459            {
460             ADDCLOCK(1);
461             S_REG[PSW] |= PSW_ID;
462	     IPendingCache = 0;
463	    }
464	    else
465            {
466             ADDCLOCK(1);
467	     RB_DECPCBY2();
468             Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP);
469             CHECK_HALTED();
470            }
471	END_OP();
472
473
474	#define COND_BRANCH(cond)			\
475		if(cond) 				\
476		{ 					\
477		 ADDCLOCK(3);				\
478		 RB_PCRELCHANGE(sign_9(arg1) & 0xFFFFFFFE);	\
479		 if(RB_AccurateMode)			\
480		 {					\
481		  BRANCH_ALIGN_CHECK(PC);		\
482		 }					\
483		 RB_ADDBT(old_PC, RB_GETPC(), 0);			\
484		}					\
485		else					\
486		{					\
487		 ADDCLOCK(1);				\
488		 RB_INCPCBY2();				\
489		}
490
491	BEGIN_OP(BV);
492		COND_BRANCH(TESTCOND_V);
493	END_OP();
494
495
496	BEGIN_OP(BL);
497        	COND_BRANCH(TESTCOND_L);
498	END_OP();
499
500	BEGIN_OP(BE);
501        	COND_BRANCH(TESTCOND_E);
502	END_OP();
503
504	BEGIN_OP(BNH);
505          	COND_BRANCH(TESTCOND_NH);
506	END_OP();
507
508	BEGIN_OP(BN);
509          	COND_BRANCH(TESTCOND_N);
510	END_OP();
511
512	BEGIN_OP(BR);
513          	COND_BRANCH(TRUE);
514	END_OP();
515
516	BEGIN_OP(BLT);
517          	COND_BRANCH(TESTCOND_LT);
518	END_OP();
519
520	BEGIN_OP(BLE);
521          	COND_BRANCH(TESTCOND_LE);
522	END_OP();
523
524	BEGIN_OP(BNV);
525          	COND_BRANCH(TESTCOND_NV);
526	END_OP();
527
528	BEGIN_OP(BNL);
529          	COND_BRANCH(TESTCOND_NL);
530	END_OP();
531
532	BEGIN_OP(BNE);
533          	COND_BRANCH(TESTCOND_NE);
534	END_OP();
535
536	BEGIN_OP(BH);
537          	COND_BRANCH(TESTCOND_H);
538	END_OP();
539
540	BEGIN_OP(BP);
541          	COND_BRANCH(TESTCOND_P);
542	END_OP();
543
544	BEGIN_OP(BGE);
545          	COND_BRANCH(TESTCOND_GE);
546	END_OP();
547
548	BEGIN_OP(BGT);
549          	COND_BRANCH(TESTCOND_GT);
550	END_OP();
551
552	BEGIN_OP(JR);
553            ADDCLOCK(3);
554            RB_PCRELCHANGE(sign_26(arg1) & 0xFFFFFFFE);
555            if(RB_AccurateMode)
556            {
557             BRANCH_ALIGN_CHECK(PC);
558            }
559            RB_ADDBT(old_PC, RB_GETPC(), 0);
560	END_OP();
561
562	BEGIN_OP(JAL);
563            ADDCLOCK(3);
564	    P_REG[31] = RB_GETPC() + 4;
565            RB_PCRELCHANGE(sign_26(arg1) & 0xFFFFFFFE);
566            if(RB_AccurateMode)
567            {
568             BRANCH_ALIGN_CHECK(PC);
569            }
570            RB_ADDBT(old_PC, RB_GETPC(), 0);
571	END_OP();
572
573	BEGIN_OP(MOVEA);
574            ADDCLOCK(1);
575	    SetPREG(arg3, P_REG[arg2] + sign_16(arg1));
576	END_OP();
577
578	BEGIN_OP(ADDI);
579             ADDCLOCK(1);
580             uint32 temp = P_REG[arg2] + sign_16(arg1);
581
582             SetFlag(PSW_OV, ((P_REG[arg2]^(~sign_16(arg1)))&(P_REG[arg2]^temp))&0x80000000);
583	     SetFlag(PSW_CY, (uint32)temp < P_REG[arg2]);
584
585             SetPREG(arg3, (uint32)temp);
586	     SetSZ(P_REG[arg3]);
587	END_OP();
588
589	BEGIN_OP(ORI);
590            ADDCLOCK(1);
591            SetPREG(arg3, arg1 | P_REG[arg2]);
592	    SetFlag(PSW_OV, FALSE);
593	    SetSZ(P_REG[arg3]);
594	END_OP();
595
596	BEGIN_OP(ANDI);
597            ADDCLOCK(1);
598            SetPREG(arg3, (arg1 & P_REG[arg2]));
599	    SetFlag(PSW_OV, FALSE);
600	    SetSZ(P_REG[arg3]);
601	END_OP();
602
603	BEGIN_OP(XORI);
604            ADDCLOCK(1);
605	    SetPREG(arg3, arg1 ^ P_REG[arg2]);
606	    SetFlag(PSW_OV, FALSE);
607	    SetSZ(P_REG[arg3]);
608	END_OP();
609
610	BEGIN_OP(MOVHI);
611            ADDCLOCK(1);
612            SetPREG(arg3, (arg1 << 16) + P_REG[arg2]);
613	END_OP();
614
615	// LD.B
616	BEGIN_OP(LD_B);
617		        ADDCLOCK(1);
618			tmp2 = (sign_16(arg1)+P_REG[arg2])&0xFFFFFFFF;
619
620			SetPREG(arg3, sign_8(MemRead8(timestamp, tmp2)));
621
622			//should be 3 clocks when executed alone, 2 when precedes another LD, or 1
623			//when precedes an instruction with many clocks (I'm guessing FP, MUL, DIV, etc)
624			if(lastop >= 0)
625			{
626				if(lastop == LASTOP_LD)
627				{
628				 ADDCLOCK(1);
629				}
630				else
631				{
632				 ADDCLOCK(2);
633				}
634			}
635			lastop = LASTOP_LD;
636	END_OP_SKIPLO();
637
638	// LD.H
639	BEGIN_OP(LD_H);
640                        ADDCLOCK(1);
641			tmp2 = (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFE;
642		        SetPREG(arg3, sign_16(MemRead16(timestamp, tmp2)));
643
644		        if(lastop >= 0)
645			{
646                                if(lastop == LASTOP_LD)
647				{
648				 ADDCLOCK(1);
649				}
650                                else
651				{
652				 ADDCLOCK(2);
653				}
654                        }
655			lastop = LASTOP_LD;
656	END_OP_SKIPLO();
657
658
659	// LD.W
660	BEGIN_OP(LD_W);
661                        ADDCLOCK(1);
662
663                        tmp2 = (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFC;
664
665	                if(MemReadBus32[tmp2 >> 24])
666			{
667			 SetPREG(arg3, MemRead32(timestamp, tmp2));
668
669			 if(lastop >= 0)
670			 {
671				if(lastop == LASTOP_LD)
672				{
673				 ADDCLOCK(1);
674				}
675				else
676				{
677				 ADDCLOCK(2);
678				}
679			 }
680			}
681			else
682			{
683			 uint32 rv;
684
685			 rv = MemRead16(timestamp, tmp2);
686			 rv |= MemRead16(timestamp, tmp2 | 2) << 16;
687
688                         SetPREG(arg3, rv);
689
690                         if(lastop >= 0)
691                         {
692                                if(lastop == LASTOP_LD)
693				{
694				 ADDCLOCK(3);
695				}
696                                else
697				{
698				 ADDCLOCK(4);
699				}
700                         }
701			}
702			lastop = LASTOP_LD;
703	END_OP_SKIPLO();
704
705	// ST.B
706	BEGIN_OP(ST_B);
707             ADDCLOCK(1);
708             MemWrite8(timestamp, sign_16(arg2)+P_REG[arg3], P_REG[arg1] & 0xFF);
709
710             if(lastop == LASTOP_ST)
711	     {
712	      ADDCLOCK(1);
713	     }
714	     lastop = LASTOP_ST;
715	END_OP_SKIPLO();
716
717	// ST.H
718	BEGIN_OP(ST_H);
719             ADDCLOCK(1);
720
721             MemWrite16(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFE, P_REG[arg1] & 0xFFFF);
722
723             if(lastop == LASTOP_ST)
724	     {
725	      ADDCLOCK(1);
726	     }
727	     lastop = LASTOP_ST;
728	END_OP_SKIPLO();
729
730	// ST.W
731	BEGIN_OP(ST_W);
732             ADDCLOCK(1);
733  	     tmp2 = (sign_16(arg2)+P_REG[arg3]) & 0xFFFFFFFC;
734
735	     if(MemWriteBus32[tmp2 >> 24])
736	     {
737	      MemWrite32(timestamp, tmp2, P_REG[arg1]);
738
739              if(lastop == LASTOP_ST)
740	      {
741	       ADDCLOCK(1);
742	      }
743	     }
744	     else
745	     {
746              MemWrite16(timestamp, tmp2, P_REG[arg1] & 0xFFFF);
747              MemWrite16(timestamp, tmp2 | 2, P_REG[arg1] >> 16);
748
749              if(lastop == LASTOP_ST)
750	      {
751	       ADDCLOCK(3);
752	      }
753	     }
754	     lastop = LASTOP_ST;
755	END_OP_SKIPLO();
756
757	// IN.B
758	BEGIN_OP(IN_B);
759	    {
760             ADDCLOCK(3);
761             SetPREG(arg3, IORead8(timestamp, sign_16(arg1)+P_REG[arg2]));
762	    }
763	    lastop = LASTOP_IN;
764	END_OP_SKIPLO();
765
766
767	// IN.H
768	BEGIN_OP(IN_H);
769	    {
770             ADDCLOCK(3);
771             SetPREG(arg3, IORead16(timestamp, (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFE));
772	    }
773	    lastop = LASTOP_IN;
774	END_OP_SKIPLO();
775
776
777	// IN.W
778	BEGIN_OP(IN_W);
779	     if(IORead32)
780	     {
781              ADDCLOCK(3);
782              SetPREG(arg3, IORead32(timestamp, (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFC));
783	     }
784	     else
785	     {
786	      uint32 eff_addr = (sign_16(arg1) + P_REG[arg2]) & 0xFFFFFFFC;
787	      uint32 rv;
788
789	      ADDCLOCK(5);
790
791	      rv = IORead16(timestamp, eff_addr);
792	      rv |= IORead16(timestamp, eff_addr | 2) << 16;
793
794              SetPREG(arg3, rv);
795	     }
796	     lastop = LASTOP_IN;
797	END_OP_SKIPLO();
798
799
800	// OUT.B
801	BEGIN_OP(OUT_B);
802             ADDCLOCK(1);
803             IOWrite8(timestamp, sign_16(arg2)+P_REG[arg3],P_REG[arg1]&0xFF);
804
805	     if(lastop == LASTOP_OUT)
806	     {
807	      ADDCLOCK(1);
808	     }
809	     lastop = LASTOP_OUT;
810	END_OP_SKIPLO();
811
812
813	// OUT.H
814	BEGIN_OP(OUT_H);
815             ADDCLOCK(1);
816             IOWrite16(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFE,P_REG[arg1]&0xFFFF);
817
818             if(lastop == LASTOP_OUT)
819             {
820              ADDCLOCK(1);
821             }
822	     lastop = LASTOP_OUT;
823	END_OP_SKIPLO();
824
825
826	// OUT.W
827	BEGIN_OP(OUT_W);
828             ADDCLOCK(1);
829
830	     if(IOWrite32)
831              IOWrite32(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFC,P_REG[arg1]);
832	     else
833	     {
834	      uint32 eff_addr = (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFC;
835              IOWrite16(timestamp, eff_addr, P_REG[arg1] & 0xFFFF);
836              IOWrite16(timestamp, eff_addr | 2, P_REG[arg1] >> 16);
837	     }
838
839             if(lastop == LASTOP_OUT)
840             {
841	      if(IOWrite32)
842              {
843	       ADDCLOCK(1);
844	      }
845	      else
846	      {
847	       ADDCLOCK(3);
848	      }
849             }
850	     lastop = LASTOP_OUT;
851	END_OP_SKIPLO();
852
853	BEGIN_OP(NOP);
854            (void)arg1;         // arg1 is unused.
855
856            ADDCLOCK(1);
857	    RB_INCPCBY2();
858	END_OP();
859
860	BEGIN_OP(RETI);
861            (void)arg1;         // arg1 is unused.
862
863            ADDCLOCK(10);
864
865            //Return from Trap/Interupt
866            if(S_REG[PSW] & PSW_NP) { // Read the FE Reg
867                RB_SETPC(S_REG[FEPC] & 0xFFFFFFFE);
868                S_REG[PSW] = S_REG[FEPSW];
869            } else { 	//Read the EI Reg Interupt
870                RB_SETPC(S_REG[EIPC] & 0xFFFFFFFE);
871                S_REG[PSW] = S_REG[EIPSW];
872            }
873	    RecalcIPendingCache();
874
875            RB_ADDBT(old_PC, RB_GETPC(), 0);
876	END_OP();
877
878	BEGIN_OP(MUL);
879             ADDCLOCK(13);
880
881             uint64 temp = (int64)(int32)P_REG[arg1] * (int32)P_REG[arg2];
882
883             SetPREG(30, (uint32)(temp >> 32));
884             SetPREG(arg2, temp);
885	     SetSZ(P_REG[arg2]);
886	     SetFlag(PSW_OV, temp != (uint64)(int64)(int32)(uint32)temp);
887	     lastop = -1;
888	END_OP_SKIPLO();
889
890	BEGIN_OP(MULU);
891             ADDCLOCK(13);
892             uint64 temp = (uint64)P_REG[arg1] * (uint64)P_REG[arg2];
893
894             SetPREG(30, (uint32)(temp >> 32));
895 	     SetPREG(arg2, (uint32)temp);
896
897	     SetSZ(P_REG[arg2]);
898	     SetFlag(PSW_OV, temp != (uint32)temp);
899	     lastop = -1;
900	END_OP_SKIPLO();
901
902	BEGIN_OP(DIVU);
903            ADDCLOCK(36);
904            if(P_REG[arg1] == 0) // Divide by zero!
905	    {
906	     RB_DECPCBY2();
907	     Exception(ZERO_DIV_HANDLER_ADDR, ECODE_ZERO_DIV);
908	     CHECK_HALTED();
909            }
910	    else
911	    {
912	     // Careful here, since arg2 can be == 30
913	     uint32 quotient = (uint32)P_REG[arg2] / (uint32)P_REG[arg1];
914	     uint32 remainder = (uint32)P_REG[arg2] % (uint32)P_REG[arg1];
915
916	     SetPREG(30, remainder);
917             SetPREG(arg2, quotient);
918
919	     SetFlag(PSW_OV, FALSE);
920	     SetSZ(quotient);
921            }
922	    lastop = -1;
923	END_OP_SKIPLO();
924
925	BEGIN_OP(DIV);
926             //if(P_REG[arg1] & P_REG[arg2] & 0x80000000)
927             //{
928             // printf("Div: %08x %08x\n", P_REG[arg1], P_REG[arg2]);
929             //}
930
931            ADDCLOCK(38);
932            if((uint32)P_REG[arg1] == 0) // Divide by zero!
933	    {
934	     RB_DECPCBY2();
935	     Exception(ZERO_DIV_HANDLER_ADDR, ECODE_ZERO_DIV);
936	     CHECK_HALTED();
937            }
938	    else
939	    {
940                if((P_REG[arg2]==0x80000000)&&(P_REG[arg1]==0xFFFFFFFF))
941		{
942			SetFlag(PSW_OV, TRUE);
943			P_REG[30]=0;
944	                SetPREG(arg2, 0x80000000);
945	                SetSZ(P_REG[arg2]);
946		}
947		else
948		{
949		     // Careful here, since arg2 can be == 30
950        	     uint32 quotient = (int32)P_REG[arg2] / (int32)P_REG[arg1];
951	             uint32 remainder = (int32)P_REG[arg2] % (int32)P_REG[arg1];
952
953	             SetPREG(30, remainder);
954	             SetPREG(arg2, quotient);
955
956	             SetFlag(PSW_OV, FALSE);
957	             SetSZ(quotient);
958		}
959	    }
960	    lastop = -1;
961	END_OP_SKIPLO();
962
963	BEGIN_OP(FPP);
964            ADDCLOCK(1);
965	    fpu_subop(timestamp, arg3, arg1, arg2);
966	    lastop = -1;
967	    CHECK_HALTED();
968	END_OP_SKIPLO();
969
970	BEGIN_OP(BSTR);
971	    if(!in_bstr)
972	    {
973             ADDCLOCK(1);
974	    }
975
976            if(bstr_subop(timestamp, arg2, arg1))
977	    {
978	     RB_DECPCBY2();
979             in_bstr = TRUE;
980             in_bstr_to = tmpop;
981	    }
982	    else
983	    {
984	     in_bstr = FALSE;
985	     have_src_cache = have_dst_cache = FALSE;
986	    }
987	END_OP();
988
989	BEGIN_OP(HALT);
990            (void)arg1;         // arg1 is unused.
991
992            ADDCLOCK(1);
993	    Halted = HALT_HALT;
994            //printf("Untested opcode: HALT\n");
995	END_OP();
996
997	BEGIN_OP(TRAP);
998            (void)arg2;         // arg2 is unused.
999
1000            ADDCLOCK(15);
1001
1002	    Exception(TRAP_HANDLER_BASE + (arg1 & 0x10), ECODE_TRAP_BASE + (arg1 & 0x1F));
1003	    CHECK_HALTED();
1004	END_OP();
1005
1006	BEGIN_OP(CAXI);
1007            //printf("Untested opcode: caxi\n");
1008
1009	    // Lock bus(N/A)
1010
1011            ADDCLOCK(26);
1012
1013	    {
1014	     uint32 addr, tmp, compare_temp;
1015	     uint32 to_write;
1016
1017             addr = sign_16(arg1) + P_REG[arg2];
1018	     addr &= ~3;
1019
1020	     if(MemReadBus32[addr >> 24])
1021	      tmp = MemRead32(timestamp, addr);
1022	     else
1023	     {
1024	      tmp = MemRead16(timestamp, addr);
1025	      tmp |= MemRead16(timestamp, addr | 2) << 16;
1026	     }
1027
1028             compare_temp = P_REG[arg3] - tmp;
1029
1030             SetSZ(compare_temp);
1031             SetFlag(PSW_OV, ((P_REG[arg3]^tmp)&(P_REG[arg3]^compare_temp))&0x80000000);
1032             SetFlag(PSW_CY, compare_temp > P_REG[arg3]);
1033
1034	     if(!compare_temp) // If they're equal...
1035	      to_write = P_REG[30];
1036	     else
1037	      to_write = tmp;
1038
1039	     if(MemWriteBus32[addr >> 24])
1040	      MemWrite32(timestamp, addr, to_write);
1041	     else
1042	     {
1043              MemWrite16(timestamp, addr, to_write & 0xFFFF);
1044              MemWrite16(timestamp, addr | 2, to_write >> 16);
1045	     }
1046	     P_REG[arg3] = tmp;
1047	    }
1048
1049	    // Unlock bus(N/A)
1050
1051	END_OP();
1052
1053
1054
1055	op_INT_HANDLER:
1056	{
1057	 int iNum = ilevel;
1058
1059	 S_REG[EIPC]  = GetPC();
1060	 S_REG[EIPSW] = S_REG[PSW];
1061
1062	 SetPC(0xFFFFFE00 | (iNum << 4));
1063
1064	 RB_ADDBT(old_PC, RB_GETPC(), 0xFE00 | (iNum << 4));
1065
1066	 S_REG[ECR] = 0xFE00 | (iNum << 4);
1067
1068	 S_REG[PSW] |= PSW_EP;
1069	 S_REG[PSW] |= PSW_ID;
1070	 S_REG[PSW] &= ~PSW_AE;
1071
1072	 // Now, set need to set the interrupt enable level to he level that is being processed + 1,
1073	 // saturating at 15.
1074	 iNum++;
1075
1076	 if(iNum > 0x0F)
1077	  iNum = 0x0F;
1078
1079	 S_REG[PSW] &= ~PSW_IA;
1080	 S_REG[PSW] |= iNum << 16;
1081
1082	 // Accepting an interrupt takes us out of normal HALT status, of course!
1083	 Halted = HALT_NONE;
1084
1085	 // Invalidate our bitstring state(forces the instruction to be re-read, and the r/w buffers reloaded).
1086	 in_bstr = FALSE;
1087	 have_src_cache = FALSE;
1088	 have_dst_cache = FALSE;
1089
1090	 IPendingCache = 0;
1091
1092 	 goto OpFinished;
1093	}
1094
1095
1096	BEGIN_OP(INVALID);
1097	    RB_DECPCBY2();
1098	    if(!RB_AccurateMode)
1099	    {
1100	     RB_SETPC(RB_GETPC());
1101	     if((uint32)(RB_RDOP(0, 0) >> 9) != opcode)
1102	     {
1103	      //printf("Trampoline: %08x %02x\n", RB_GETPC(), opcode >> 1);
1104	     }
1105	     else
1106	     {
1107              ADDCLOCK(1);
1108              Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP);
1109              CHECK_HALTED();
1110	     }
1111	    }
1112	    else
1113	    {
1114	     ADDCLOCK(1);
1115	     Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP);
1116	     CHECK_HALTED();
1117	    }
1118	END_OP();
1119
1120	}
1121
1122	OpFinished:	;
1123	lastop = opcode;
1124	OpFinishedSkipLO: ;
1125     }	// end  while(timestamp_rl < next_event_ts)
1126     next_event_ts = event_handler(timestamp_rl);
1127     //printf("Next: %d, Cur: %d\n", next_event_ts, timestamp);
1128    }
1129
1130v810_timestamp = timestamp_rl;
1131