Revision 4fa551d7

b/target-cris/op.c
1
/*
2
 *  CRIS emulation micro-operations for qemu.
3
 *
4
 *  Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#include "exec.h"
21

  
22
#define REGNAME r0
23
#define REG (env->regs[0])
24
#include "op_template.h"
25

  
26
#define REGNAME r1
27
#define REG (env->regs[1])
28
#include "op_template.h"
29

  
30
#define REGNAME r2
31
#define REG (env->regs[2])
32
#include "op_template.h"
33

  
34
#define REGNAME r3
35
#define REG (env->regs[3])
36
#include "op_template.h"
37

  
38
#define REGNAME r4
39
#define REG (env->regs[4])
40
#include "op_template.h"
41

  
42
#define REGNAME r5
43
#define REG (env->regs[5])
44
#include "op_template.h"
45

  
46
#define REGNAME r6
47
#define REG (env->regs[6])
48
#include "op_template.h"
49

  
50
#define REGNAME r7
51
#define REG (env->regs[7])
52
#include "op_template.h"
53

  
54
#define REGNAME r8
55
#define REG (env->regs[8])
56
#include "op_template.h"
57

  
58
#define REGNAME r9
59
#define REG (env->regs[9])
60
#include "op_template.h"
61

  
62
#define REGNAME r10
63
#define REG (env->regs[10])
64
#include "op_template.h"
65

  
66
#define REGNAME r11
67
#define REG (env->regs[11])
68
#include "op_template.h"
69

  
70
#define REGNAME r12
71
#define REG (env->regs[12])
72
#include "op_template.h"
73

  
74
#define REGNAME r13
75
#define REG (env->regs[13])
76
#include "op_template.h"
77

  
78
#define REGNAME r14
79
#define REG (env->regs[14])
80
#include "op_template.h"
81

  
82
#define REGNAME r15
83
#define REG (env->regs[15])
84
#include "op_template.h"
85

  
86

  
87
#define REGNAME p0
88
#define REG (env->pregs[0])
89
#include "op_template.h"
90

  
91
#define REGNAME p1
92
#define REG (env->pregs[1])
93
#include "op_template.h"
94

  
95
#define REGNAME p2
96
#define REG (env->pregs[2])
97
#include "op_template.h"
98

  
99
#define REGNAME p3
100
#define REG (env->pregs[3])
101
#include "op_template.h"
102

  
103
#define REGNAME p4
104
#define REG (env->pregs[4])
105
#include "op_template.h"
106

  
107
#define REGNAME p5
108
#define REG (env->pregs[5])
109
#include "op_template.h"
110

  
111
#define REGNAME p6
112
#define REG (env->pregs[6])
113
#include "op_template.h"
114

  
115
#define REGNAME p7
116
#define REG (env->pregs[7])
117
#include "op_template.h"
118

  
119
#define REGNAME p8
120
#define REG (env->pregs[8])
121
#include "op_template.h"
122

  
123
#define REGNAME p9
124
#define REG (env->pregs[9])
125
#include "op_template.h"
126

  
127
#define REGNAME p10
128
#define REG (env->pregs[10])
129
#include "op_template.h"
130

  
131
#define REGNAME p11
132
#define REG (env->pregs[11])
133
#include "op_template.h"
134

  
135
#define REGNAME p12
136
#define REG (env->pregs[12])
137
#include "op_template.h"
138

  
139
#define REGNAME p13
140
#define REG (env->pregs[13])
141
#include "op_template.h"
142

  
143
#define REGNAME p14
144
#define REG (env->pregs[14])
145
#include "op_template.h"
146

  
147
#define REGNAME p15
148
#define REG (env->pregs[15])
149
#include "op_template.h"
150

  
151
/* Microcode.  */
152

  
153
void OPPROTO op_exit_tb (void)
154
{
155
	EXIT_TB();
156
}
157

  
158
void OPPROTO op_goto_tb0 (void)
159
{
160
	GOTO_TB(op_goto_tb0, PARAM1, 0);
161
	RETURN();
162
}
163

  
164
void OPPROTO op_goto_tb1 (void)
165
{
166
	GOTO_TB(op_goto_tb1, PARAM1, 1);
167
	RETURN();
168
}
169

  
170
void OPPROTO op_break_im(void)
171
{
172
	env->trapnr = PARAM1;
173
	env->exception_index = EXCP_BREAK;
174
	cpu_loop_exit();
175
}
176

  
177
void OPPROTO op_debug(void)
178
{
179
	env->exception_index = EXCP_DEBUG;
180
	cpu_loop_exit();
181
}
182

  
183
void OPPROTO op_exec_insn(void)
184
{
185
	env->stats.exec_insns++;
186
	RETURN();
187
}
188
void OPPROTO op_exec_load(void)
189
{
190
	env->stats.exec_loads++;
191
	RETURN();
192
}
193
void OPPROTO op_exec_store(void)
194
{
195
	env->stats.exec_stores++;
196
	RETURN();
197
}
198

  
199
void OPPROTO op_ccs_lshift (void)
200
{
201
	uint32_t ccs;
202

  
203
	/* Apply the ccs shift.  */
204
	ccs = env->pregs[SR_CCS];
205
	ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2);
206
	env->pregs[SR_CCS] = ccs;
207
}
208
void OPPROTO op_ccs_rshift (void)
209
{
210
	uint32_t ccs;
211

  
212
	/* Apply the ccs shift.  */
213
	ccs = env->pregs[SR_CCS];
214
	ccs = (ccs & 0xc0000000) | (ccs >> 10);
215
	env->pregs[SR_CCS] = ccs;
216
}
217

  
218
void OPPROTO op_setf (void)
219
{
220
	env->pregs[SR_CCS] |= PARAM1;
221
	RETURN();
222
}
223

  
224
void OPPROTO op_clrf (void)
225
{
226
	env->pregs[SR_CCS] &= ~PARAM1;
227
	RETURN();
228
}
229

  
230
void OPPROTO op_movl_debug1_T0 (void)
231
{
232
	env->debug1 = T0;
233
	RETURN();
234
}
235

  
236
void OPPROTO op_movl_debug2_T0 (void)
237
{
238
	env->debug2 = T0;
239
	RETURN();
240
}
241

  
242
void OPPROTO op_movl_debug3_T0 (void)
243
{
244
	env->debug3 = T0;
245
	RETURN();
246
}
247
void OPPROTO op_movl_debug1_T1 (void)
248
{
249
	env->debug1 = T1;
250
	RETURN();
251
}
252

  
253
void OPPROTO op_movl_debug2_T1 (void)
254
{
255
	env->debug2 = T1;
256
	RETURN();
257
}
258

  
259
void OPPROTO op_movl_debug3_T1 (void)
260
{
261
	env->debug3 = T1;
262
	RETURN();
263
}
264
void OPPROTO op_movl_debug3_im (void)
265
{
266
	env->debug3 = PARAM1;
267
	RETURN();
268
}
269
void OPPROTO op_movl_T0_flags (void)
270
{
271
	T0 = env->pregs[SR_CCS];
272
	RETURN();
273
}
274
void OPPROTO op_movl_flags_T0 (void)
275
{
276
	env->pregs[SR_CCS] = T0;
277
	RETURN();
278
}
279

  
280
void OPPROTO op_movl_sreg_T0 (void)
281
{
282
	env->sregs[env->pregs[SR_SRS]][PARAM1] = T0;
283
	RETURN();
284
}
285

  
286
void OPPROTO op_movl_tlb_lo_T0 (void)
287
{
288
	int srs;
289
	srs = env->pregs[SR_SRS];
290
	if (srs == 1 || srs == 2)
291
	{
292
		int set;
293
		int idx;
294
		uint32_t lo, hi;
295

  
296
		idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
297
		set >>= 4;
298
		set &= 3;
299

  
300
		idx &= 31;
301
		/* We've just made a write to tlb_lo.  */
302
		lo = env->sregs[SFR_RW_MM_TLB_LO];
303
		hi = env->sregs[SFR_RW_MM_TLB_HI];
304
		env->tlbsets[srs - 1][set][idx].lo = lo;
305
		env->tlbsets[srs - 1][set][idx].hi = hi;
306
	}
307

  
308
	RETURN();
309
}
310

  
311
void OPPROTO op_movl_T0_sreg (void)
312
{
313
	T0 = env->sregs[env->pregs[SR_SRS]][PARAM1];
314
	RETURN();
315
}
316

  
317
void OPPROTO op_update_cc (void)
318
{
319
	env->cc_op = PARAM1;
320
	env->cc_dest = PARAM2;
321
	env->cc_src = PARAM3;
322
	RETURN();
323
}
324

  
325
void OPPROTO op_update_cc_op (void)
326
{
327
	env->cc_op = PARAM1;
328
	RETURN();
329
}
330

  
331
void OPPROTO op_update_cc_mask (void)
332
{
333
	env->cc_mask = PARAM1;
334
	RETURN();
335
}
336

  
337
void OPPROTO op_update_cc_dest_T0 (void)
338
{
339
	env->cc_dest = T0;
340
	RETURN();
341
}
342

  
343
void OPPROTO op_update_cc_result_T0 (void)
344
{
345
	env->cc_result = T0;
346
	RETURN();
347
}
348

  
349
void OPPROTO op_update_cc_size_im (void)
350
{
351
	env->cc_size = PARAM1;
352
	RETURN();
353
}
354

  
355
void OPPROTO op_update_cc_src_T1 (void)
356
{
357
	env->cc_src = T1;
358
	RETURN();
359
}
360
void OPPROTO op_update_cc_x (void)
361
{
362
	env->cc_x_live = PARAM1;
363
	env->cc_x = PARAM2;
364
	RETURN();
365
}
366

  
367
/* FIXME: is this allowed?  */
368
extern inline void evaluate_flags_writeback(uint32_t flags)
369
{
370
	int x;
371

  
372
	/* Extended arithmetics, leave the z flag alone.  */
373
	env->debug3 = env->pregs[SR_CCS];
374

  
375
	if (env->cc_x_live)
376
		x = env->cc_x;
377
	else
378
		x = env->pregs[SR_CCS] & X_FLAG;
379

  
380
	if ((x || env->cc_op == CC_OP_ADDC)
381
	    && flags & Z_FLAG)
382
		env->cc_mask &= ~Z_FLAG;
383

  
384
	/* all insn clear the x-flag except setf or clrf.  */
385
	env->pregs[SR_CCS] &= ~(env->cc_mask | X_FLAG);
386
	flags &= env->cc_mask;
387
	env->pregs[SR_CCS] |= flags;
388
	RETURN();
389
}
390

  
391
void OPPROTO op_evaluate_flags_muls(void)
392
{
393
	uint32_t src;
394
	uint32_t dst;
395
	uint32_t res;
396
	uint32_t flags = 0;
397
	/* were gonna have to redo the muls.  */
398
	int64_t tmp, t0 ,t1;
399
	int32_t mof;
400
	int dneg;
401

  
402
	src = env->cc_src;
403
	dst = env->cc_dest;
404
	res = env->cc_result;
405

  
406

  
407
	/* cast into signed values to make GCC sign extend.  */
408
	t0 = (int32_t)src;
409
	t1 = (int32_t)dst;
410
	dneg = ((int32_t)res) < 0;
411

  
412
	tmp = t0 * t1;
413
	mof = tmp >> 32;
414
	if (tmp == 0)
415
		flags |= Z_FLAG;
416
	else if (tmp < 0)
417
		flags |= N_FLAG;
418
	if ((dneg && mof != -1)
419
	    || (!dneg && mof != 0))
420
		flags |= V_FLAG;
421
	evaluate_flags_writeback(flags);
422
	RETURN();
423
}
424

  
425
void OPPROTO op_evaluate_flags_mulu(void)
426
{
427
	uint32_t src;
428
	uint32_t dst;
429
	uint32_t res;
430
	uint32_t flags = 0;
431
	/* were gonna have to redo the muls.  */
432
	uint64_t tmp, t0 ,t1;
433
	uint32_t mof;
434

  
435
	src = env->cc_src;
436
	dst = env->cc_dest;
437
	res = env->cc_result;
438

  
439

  
440
	/* cast into signed values to make GCC sign extend.  */
441
	t0 = src;
442
	t1 = dst;
443

  
444
	tmp = t0 * t1;
445
	mof = tmp >> 32;
446
	if (tmp == 0)
447
		flags |= Z_FLAG;
448
	else if (tmp >> 63)
449
		flags |= N_FLAG;
450
	if (mof)
451
		flags |= V_FLAG;
452

  
453
	evaluate_flags_writeback(flags);
454
	RETURN();
455
}
456

  
457
void OPPROTO op_evaluate_flags_mcp(void)
458
{
459
	uint32_t src;
460
	uint32_t dst;
461
	uint32_t res;
462
	uint32_t flags = 0;
463

  
464
	src = env->cc_src;
465
	dst = env->cc_dest;
466
	res = env->cc_result;
467

  
468
	if ((res & 0x80000000L) != 0L)
469
	{
470
		flags |= N_FLAG;
471
		if (((src & 0x80000000L) == 0L)
472
		    && ((dst & 0x80000000L) == 0L))
473
		{
474
			flags |= V_FLAG;
475
		}
476
		else if (((src & 0x80000000L) != 0L) &&
477
			 ((dst & 0x80000000L) != 0L))
478
		{
479
			flags |= R_FLAG;
480
		}
481
	}
482
	else
483
	{
484
		if (res == 0L)
485
			flags |= Z_FLAG;
486
		if (((src & 0x80000000L) != 0L)
487
		    && ((dst & 0x80000000L) != 0L))
488
			flags |= V_FLAG;
489
		if ((dst & 0x80000000L) != 0L
490
		    || (src & 0x80000000L) != 0L)
491
			flags |= R_FLAG;
492
	}
493

  
494
	evaluate_flags_writeback(flags);
495
	RETURN();
496
}
497

  
498
void OPPROTO op_evaluate_flags_alu_4(void)
499
{
500
	uint32_t src;
501
	uint32_t dst;
502
	uint32_t res;
503
	uint32_t flags = 0;
504

  
505
	src = env->cc_src;
506
	dst = env->cc_dest;
507
	res = env->cc_result;
508

  
509
	if ((res & 0x80000000L) != 0L)
510
	{
511
		flags |= N_FLAG;
512
		if (((src & 0x80000000L) == 0L)
513
		    && ((dst & 0x80000000L) == 0L))
514
		{
515
			flags |= V_FLAG;
516
		}
517
		else if (((src & 0x80000000L) != 0L) &&
518
			 ((dst & 0x80000000L) != 0L))
519
		{
520
			flags |= C_FLAG;
521
		}
522
	}
523
	else
524
	{
525
		if (res == 0L)
526
			flags |= Z_FLAG;
527
		if (((src & 0x80000000L) != 0L)
528
		    && ((dst & 0x80000000L) != 0L))
529
			flags |= V_FLAG;
530
		if ((dst & 0x80000000L) != 0L
531
		    || (src & 0x80000000L) != 0L)
532
			flags |= C_FLAG;
533
	}
534

  
535
	if (env->cc_op == CC_OP_SUB
536
	    || env->cc_op == CC_OP_CMP) {
537
		flags ^= C_FLAG;
538
	}
539
	evaluate_flags_writeback(flags);
540
	RETURN();
541
}
542

  
543
void OPPROTO op_evaluate_flags_move_4 (void)
544
{
545
	uint32_t src;
546
	uint32_t res;
547
	uint32_t flags = 0;
548

  
549
	src = env->cc_src;
550
	res = env->cc_result;
551

  
552
	if ((int32_t)res < 0)
553
		flags |= N_FLAG;
554
	else if (res == 0L)
555
		flags |= Z_FLAG;
556

  
557
	evaluate_flags_writeback(flags);
558
	RETURN();
559
}
560
void OPPROTO op_evaluate_flags_move_2 (void)
561
{
562
	uint32_t src;
563
	uint32_t flags = 0;
564
	uint16_t res;
565

  
566
	src = env->cc_src;
567
	res = env->cc_result;
568

  
569
	if ((int16_t)res < 0L)
570
		flags |= N_FLAG;
571
	else if (res == 0)
572
		flags |= Z_FLAG;
573

  
574
	evaluate_flags_writeback(flags);
575
	RETURN();
576
}
577

  
578
/* TODO: This is expensive. We could split things up and only evaluate part of
579
   CCR on a need to know basis. For now, we simply re-evaluate everything.  */
580
void OPPROTO op_evaluate_flags (void)
581
{
582
	uint32_t src;
583
	uint32_t dst;
584
	uint32_t res;
585
	uint32_t flags = 0;
586

  
587
	src = env->cc_src;
588
	dst = env->cc_dest;
589
	res = env->cc_result;
590

  
591

  
592
	/* Now, evaluate the flags. This stuff is based on
593
	   Per Zander's CRISv10 simulator.  */
594
	switch (env->cc_size)
595
	{
596
		case 1:
597
			if ((res & 0x80L) != 0L)
598
			{
599
				flags |= N_FLAG;
600
				if (((src & 0x80L) == 0L)
601
				    && ((dst & 0x80L) == 0L))
602
				{
603
					flags |= V_FLAG;
604
				}
605
				else if (((src & 0x80L) != 0L)
606
					 && ((dst & 0x80L) != 0L))
607
				{
608
					flags |= C_FLAG;
609
				}
610
			}
611
			else
612
			{
613
				if ((res & 0xFFL) == 0L)
614
				{
615
					flags |= Z_FLAG;
616
				}
617
				if (((src & 0x80L) != 0L)
618
				    && ((dst & 0x80L) != 0L))
619
				{
620
					flags |= V_FLAG;
621
				}
622
				if ((dst & 0x80L) != 0L
623
				    || (src & 0x80L) != 0L)
624
				{
625
					flags |= C_FLAG;
626
				}
627
			}
628
			break;
629
		case 2:
630
			if ((res & 0x8000L) != 0L)
631
			{
632
				flags |= N_FLAG;
633
				if (((src & 0x8000L) == 0L)
634
				    && ((dst & 0x8000L) == 0L))
635
				{
636
					flags |= V_FLAG;
637
				}
638
				else if (((src & 0x8000L) != 0L)
639
					 && ((dst & 0x8000L) != 0L))
640
				{
641
					flags |= C_FLAG;
642
				}
643
			}
644
			else
645
			{
646
				if ((res & 0xFFFFL) == 0L)
647
				{
648
					flags |= Z_FLAG;
649
				}
650
				if (((src & 0x8000L) != 0L)
651
				    && ((dst & 0x8000L) != 0L))
652
				{
653
					flags |= V_FLAG;
654
				}
655
				if ((dst & 0x8000L) != 0L
656
				    || (src & 0x8000L) != 0L)
657
				{
658
					flags |= C_FLAG;
659
				}
660
			}
661
			break;
662
		case 4:
663
			if ((res & 0x80000000L) != 0L)
664
			{
665
				flags |= N_FLAG;
666
				if (((src & 0x80000000L) == 0L)
667
				    && ((dst & 0x80000000L) == 0L))
668
				{
669
					flags |= V_FLAG;
670
				}
671
				else if (((src & 0x80000000L) != 0L) &&
672
					 ((dst & 0x80000000L) != 0L))
673
				{
674
					flags |= C_FLAG;
675
				}
676
			}
677
			else
678
			{
679
				if (res == 0L)
680
					flags |= Z_FLAG;
681
				if (((src & 0x80000000L) != 0L)
682
				    && ((dst & 0x80000000L) != 0L))
683
					flags |= V_FLAG;
684
				if ((dst & 0x80000000L) != 0L
685
				    || (src & 0x80000000L) != 0L)
686
					flags |= C_FLAG;
687
			}
688
			break;
689
		default:
690
			break;
691
	}
692

  
693
	if (env->cc_op == CC_OP_SUB
694
	    || env->cc_op == CC_OP_CMP) {
695
		flags ^= C_FLAG;
696
	}
697
	evaluate_flags_writeback(flags);
698
	RETURN();
699
}
700

  
701
void OPPROTO op_extb_T0_T0 (void)
702
{
703
	T0 = ((int8_t)T0);
704
	RETURN();
705
}
706
void OPPROTO op_extb_T1_T0 (void)
707
{
708
	T1 = ((int8_t)T0);
709
	RETURN();
710
}
711
void OPPROTO op_extb_T1_T1 (void)
712
{
713
	T1 = ((int8_t)T1);
714
	RETURN();
715
}
716
void OPPROTO op_zextb_T0_T0 (void)
717
{
718
	T0 = ((uint8_t)T0);
719
	RETURN();
720
}
721
void OPPROTO op_zextb_T1_T0 (void)
722
{
723
	T1 = ((uint8_t)T0);
724
	RETURN();
725
}
726
void OPPROTO op_zextb_T1_T1 (void)
727
{
728
	T1 = ((uint8_t)T1);
729
	RETURN();
730
}
731
void OPPROTO op_extw_T0_T0 (void)
732
{
733
	T0 = ((int16_t)T0);
734
	RETURN();
735
}
736
void OPPROTO op_extw_T1_T0 (void)
737
{
738
	T1 = ((int16_t)T0);
739
	RETURN();
740
}
741
void OPPROTO op_extw_T1_T1 (void)
742
{
743
	T1 = ((int16_t)T1);
744
	RETURN();
745
}
746

  
747
void OPPROTO op_zextw_T0_T0 (void)
748
{
749
	T0 = ((uint16_t)T0);
750
	RETURN();
751
}
752
void OPPROTO op_zextw_T1_T0 (void)
753
{
754
	T1 = ((uint16_t)T0);
755
	RETURN();
756
}
757

  
758
void OPPROTO op_zextw_T1_T1 (void)
759
{
760
	T1 = ((uint16_t)T1);
761
	RETURN();
762
}
763

  
764
void OPPROTO op_movl_T0_im (void)
765
{
766
	T0 = PARAM1;
767
	RETURN();
768
}
769
void OPPROTO op_movl_T1_im (void)
770
{
771
	T1 = PARAM1;
772
	RETURN();
773
}
774

  
775
void OPPROTO op_addl_T0_im (void)
776
{
777
	T0 += PARAM1;
778
	RETURN();
779
}
780

  
781
void OPPROTO op_addl_T1_im (void)
782
{
783
	T1 += PARAM1;
784
	RETURN();
785

  
786
}
787
void OPPROTO op_subl_T0_im (void)
788
{
789
	T0 -= PARAM1;
790
	RETURN();
791
}
792

  
793
void OPPROTO op_addxl_T0_C (void)
794
{
795
	if (env->pregs[SR_CCS] & X_FLAG)
796
		T0 += !!(env->pregs[SR_CCS] & C_FLAG);
797
	RETURN();
798
}
799
void OPPROTO op_subxl_T0_C (void)
800
{
801
	if (env->pregs[SR_CCS] & X_FLAG)
802
		T0 -= !!(env->pregs[SR_CCS] & C_FLAG);
803
	RETURN();
804
}
805
void OPPROTO op_addl_T0_C (void)
806
{
807
	T0 += !!(env->pregs[SR_CCS] & C_FLAG);
808
	RETURN();
809
}
810
void OPPROTO op_addl_T0_R (void)
811
{
812
	T0 += !!(env->pregs[SR_CCS] & R_FLAG);
813
	RETURN();
814
}
815

  
816
void OPPROTO op_clr_R (void)
817
{
818
	env->pregs[SR_CCS] &= ~R_FLAG;
819
	RETURN();
820
}
821

  
822

  
823
void OPPROTO op_andl_T0_im (void)
824
{
825
	T0 &= PARAM1;
826
	RETURN();
827
}
828

  
829
void OPPROTO op_andl_T1_im (void)
830
{
831
	T1 &= PARAM1;
832
	RETURN();
833
}
834

  
835
void OPPROTO op_movl_T0_T1 (void)
836
{
837
	T0 = T1;
838
	RETURN();
839
}
840

  
841
void OPPROTO op_swp_T0_T1 (void)
842
{
843
	T0 ^= T1;
844
	T1 ^= T0;
845
	T0 ^= T1;
846
	RETURN();
847
}
848

  
849
void OPPROTO op_movl_T1_T0 (void)
850
{
851
	T1 = T0;
852
	RETURN();
853
}
854

  
855
void OPPROTO op_movl_pc_T0 (void)
856
{
857
	env->pc = T0;
858
	RETURN();
859
}
860

  
861
void OPPROTO op_movl_T0_0 (void)
862
{
863
	T0 = 0;
864
	RETURN();
865
}
866

  
867
void OPPROTO op_addl_T0_T1 (void)
868
{
869
	T0 += T1;
870
	RETURN();
871
}
872

  
873
void OPPROTO op_subl_T0_T1 (void)
874
{
875
	T0 -= T1;
876
	RETURN();
877
}
878

  
879
void OPPROTO op_absl_T1_T1 (void)
880
{
881
	int32_t st = T1;
882

  
883
	T1 = st < 0 ? -st : st;
884
	RETURN();
885
}
886

  
887
void OPPROTO op_muls_T0_T1 (void)
888
{
889
	int64_t tmp, t0 ,t1;
890

  
891
	/* cast into signed values to make GCC sign extend these babies.  */
892
	t0 = (int32_t)T0;
893
	t1 = (int32_t)T1;
894

  
895
	tmp = t0 * t1;
896
	T0 = tmp & 0xffffffff;
897
	env->pregs[REG_MOF] = tmp >> 32;
898
	RETURN();
899
}
900

  
901
void OPPROTO op_mulu_T0_T1 (void)
902
{
903
	uint64_t tmp, t0 ,t1;
904
	t0 = T0;
905
	t1 = T1;
906

  
907
	tmp = t0 * t1;
908
	T0 = tmp & 0xffffffff;
909
	env->pregs[REG_MOF] = tmp >> 32;
910
	RETURN();
911
}
912

  
913
void OPPROTO op_dstep_T0_T1 (void)
914
{
915
	T0 <<= 1;
916
	if (T0 >= T1)
917
		T0 -= T1;
918
	RETURN();
919
}
920

  
921
void OPPROTO op_orl_T0_T1 (void)
922
{
923
	T0 |= T1;
924
	RETURN();
925
}
926

  
927
void OPPROTO op_andl_T0_T1 (void)
928
{
929
	T0 &= T1;
930
	RETURN();
931
}
932

  
933
void OPPROTO op_xorl_T0_T1 (void)
934
{
935
	T0 ^= T1;
936
	RETURN();
937
}
938

  
939
void OPPROTO op_lsll_T0_T1 (void)
940
{
941
	int s = T1;
942
	if (s > 31)
943
		T0 = 0;
944
	else
945
		T0 <<= s;
946
	RETURN();
947
}
948

  
949
void OPPROTO op_lsll_T0_im (void)
950
{
951
	T0 <<= PARAM1;
952
	RETURN();
953
}
954

  
955
void OPPROTO op_lsrl_T0_T1 (void)
956
{
957
	int s = T1;
958
	if (s > 31)
959
		T0 = 0;
960
	else
961
		T0 >>= s;
962
	RETURN();
963
}
964

  
965
/* Rely on GCC emitting an arithmetic shift for signed right shifts.  */
966
void OPPROTO op_asrl_T0_T1 (void)
967
{
968
	int s = T1;
969
	if (s > 31)
970
		T0 = T0 & 0x80000000 ? -1 : 0;
971
	else
972
		T0 = (int32_t)T0 >> s;
973
	RETURN();
974
}
975

  
976
void OPPROTO op_btst_T0_T1 (void)
977
{
978
	/* FIXME: clean this up.  */
979

  
980
	/* des ref:
981
	   The N flag is set according to the selected bit in the dest reg.
982
	   The Z flag is set if the selected bit and all bits to the right are
983
	   zero.
984
	   The destination reg is not affected.*/
985
	unsigned int fz, sbit, bset, mask, masked_t0;
986

  
987
	sbit = T1 & 31;
988
        bset = !!(T0 & (1 << sbit));
989
	mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1;
990
	masked_t0 = T0 & mask;
991
	fz = !(masked_t0 | bset);
992
	/* Set the N and Z flags accordingly.  */
993
	T0 = (bset << 3) | (fz << 2);
994
	RETURN();
995
}
996

  
997
void OPPROTO op_bound_T0_T1 (void)
998
{
999
	if (T0 > T1)
1000
		T0 = T1;
1001
	RETURN();
1002
}
1003

  
1004
void OPPROTO op_lz_T0_T1 (void)
1005
{
1006
	if (T1 == 0)
1007
		T0 = 32;
1008
	else
1009
		T0 = __builtin_clz(T1);
1010
	RETURN();
1011
}
1012

  
1013
void OPPROTO op_negl_T0_T1 (void)
1014
{
1015
	T0 = -T1;
1016
	RETURN();
1017
}
1018

  
1019
void OPPROTO op_negl_T1_T1 (void)
1020
{
1021
	T1 = -T1;
1022
	RETURN();
1023
}
1024

  
1025
void OPPROTO op_not_T0_T0 (void)
1026
{
1027
	T0 = ~(T0);
1028
	RETURN();
1029
}
1030
void OPPROTO op_not_T1_T1 (void)
1031
{
1032
	T1 = ~(T1);
1033
	RETURN();
1034
}
1035

  
1036
void OPPROTO op_swapw_T0_T0 (void)
1037
{
1038
	T0 = (T0 << 16) | ((T0 >> 16));
1039
	RETURN();
1040
}
1041

  
1042
void OPPROTO op_swapb_T0_T0 (void)
1043
{
1044
	T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff);
1045
	RETURN();
1046
}
1047

  
1048
void OPPROTO op_swapr_T0_T0 (void)
1049
{
1050
	T0 = (((T0 << 7) & 0x80808080) |
1051
	      ((T0 << 5) & 0x40404040) |
1052
	      ((T0 << 3) & 0x20202020) |
1053
	      ((T0 << 1) & 0x10101010) |
1054
	      ((T0 >> 1) & 0x08080808) |
1055
	      ((T0 >> 3) & 0x04040404) |
1056
	      ((T0 >> 5) & 0x02020202) |
1057
	      ((T0 >> 7) & 0x01010101));
1058
	RETURN();
1059
}
1060

  
1061
void OPPROTO op_tst_cc_eq (void) {
1062
	uint32_t flags = env->pregs[SR_CCS];
1063
	int z_set;
1064

  
1065
	z_set = !!(flags & Z_FLAG);
1066
	T0 = z_set;
1067
	RETURN();
1068
}
1069

  
1070
void OPPROTO op_tst_cc_eq_fast (void) {
1071
	T0 = !(env->cc_result);
1072
	RETURN();
1073
}
1074

  
1075
void OPPROTO op_tst_cc_ne (void) {
1076
	uint32_t flags = env->pregs[SR_CCS];
1077
	int z_set;
1078

  
1079
	z_set = !!(flags & Z_FLAG);
1080
	T0 = !z_set;
1081
	RETURN();
1082
}
1083
void OPPROTO op_tst_cc_ne_fast (void) {
1084
	T0 = !!(env->cc_result);
1085
	RETURN();
1086
}
1087

  
1088
void OPPROTO op_tst_cc_cc (void) {
1089
	uint32_t flags = env->pregs[SR_CCS];
1090
	int c_set;
1091

  
1092
	c_set = !!(flags & C_FLAG);
1093
	T0 = !c_set;
1094
	RETURN();
1095
}
1096
void OPPROTO op_tst_cc_cs (void) {
1097
	uint32_t flags = env->pregs[SR_CCS];
1098
	int c_set;
1099

  
1100
	c_set = !!(flags & C_FLAG);
1101
	T0 = c_set;
1102
	RETURN();
1103
}
1104

  
1105
void OPPROTO op_tst_cc_vc (void) {
1106
	uint32_t flags = env->pregs[SR_CCS];
1107
	int v_set;
1108

  
1109
	v_set = !!(flags & V_FLAG);
1110
	T0 = !v_set;
1111
	RETURN();
1112
}
1113
void OPPROTO op_tst_cc_vs (void) {
1114
	uint32_t flags = env->pregs[SR_CCS];
1115
	int v_set;
1116

  
1117
	v_set = !!(flags & V_FLAG);
1118
	T0 = v_set;
1119
	RETURN();
1120
}
1121
void OPPROTO op_tst_cc_pl (void) {
1122
	uint32_t flags = env->pregs[SR_CCS];
1123
	int n_set;
1124

  
1125
	n_set = !!(flags & N_FLAG);
1126
	T0 = !n_set;
1127
	RETURN();
1128
}
1129
void OPPROTO op_tst_cc_pl_fast (void) {
1130
	T0 = ((int32_t)env->cc_result) >= 0;
1131
	RETURN();
1132
}
1133

  
1134
void OPPROTO op_tst_cc_mi (void) {
1135
	uint32_t flags = env->pregs[SR_CCS];
1136
	int n_set;
1137

  
1138
	n_set = !!(flags & N_FLAG);
1139
	T0 = n_set;
1140
	RETURN();
1141
}
1142
void OPPROTO op_tst_cc_mi_fast (void) {
1143
	T0 = ((int32_t)env->cc_result) < 0;
1144
	RETURN();
1145
}
1146

  
1147
void OPPROTO op_tst_cc_ls (void) {
1148
	uint32_t flags = env->pregs[SR_CCS];
1149
	int c_set;
1150
	int z_set;
1151

  
1152
	c_set = !!(flags & C_FLAG);
1153
	z_set = !!(flags & Z_FLAG);
1154
	T0 = c_set || z_set;
1155
	RETURN();
1156
}
1157
void OPPROTO op_tst_cc_hi (void) {
1158
	uint32_t flags = env->pregs[SR_CCS];
1159
	int z_set;
1160
	int c_set;
1161

  
1162
	z_set = !!(flags & Z_FLAG);
1163
	c_set = !!(flags & C_FLAG);
1164
	T0 = !c_set && !z_set;
1165
	RETURN();
1166

  
1167
}
1168

  
1169
void OPPROTO op_tst_cc_ge (void) {
1170
	uint32_t flags = env->pregs[SR_CCS];
1171
	int n_set;
1172
	int v_set;
1173

  
1174
	n_set = !!(flags & N_FLAG);
1175
	v_set = !!(flags & V_FLAG);
1176
	T0 = (n_set && v_set) || (!n_set && !v_set);
1177
	RETURN();
1178
}
1179

  
1180
void OPPROTO op_tst_cc_ge_fast (void) {
1181
	T0 = ((int32_t)env->cc_src < (int32_t)env->cc_dest);
1182
	RETURN();
1183
}
1184

  
1185
void OPPROTO op_tst_cc_lt (void) {
1186
	uint32_t flags = env->pregs[SR_CCS];
1187
	int n_set;
1188
	int v_set;
1189

  
1190
	n_set = !!(flags & N_FLAG);
1191
	v_set = !!(flags & V_FLAG);
1192
	T0 = (n_set && !v_set) || (!n_set && v_set);
1193
	RETURN();
1194
}
1195

  
1196
void OPPROTO op_tst_cc_gt (void) {
1197
	uint32_t flags = env->pregs[SR_CCS];
1198
	int n_set;
1199
	int v_set;
1200
	int z_set;
1201

  
1202
	n_set = !!(flags & N_FLAG);
1203
	v_set = !!(flags & V_FLAG);
1204
	z_set = !!(flags & Z_FLAG);
1205
	T0 = (n_set && v_set && !z_set)
1206
		|| (!n_set && !v_set && !z_set);
1207
	RETURN();
1208
}
1209

  
1210
void OPPROTO op_tst_cc_le (void) {
1211
	uint32_t flags = env->pregs[SR_CCS];
1212
	int n_set;
1213
	int v_set;
1214
	int z_set;
1215

  
1216
	n_set = !!(flags & N_FLAG);
1217
	v_set = !!(flags & V_FLAG);
1218
	z_set = !!(flags & Z_FLAG);
1219
	T0 = z_set || (n_set && !v_set) || (!n_set && v_set);
1220
	RETURN();
1221
}
1222

  
1223
void OPPROTO op_tst_cc_p (void) {
1224
	uint32_t flags = env->pregs[SR_CCS];
1225
	int p_set;
1226

  
1227
	p_set = !!(flags & P_FLAG);
1228
	T0 = p_set;
1229
	RETURN();
1230
}
1231

  
1232
/* Evaluate the if the branch should be taken or not. Needs to be done in
1233
   the original sequence. The acutal branch is rescheduled to right after the
1234
   delay-slot.  */
1235
void OPPROTO op_evaluate_bcc (void)
1236
{
1237
	env->btaken = T0;
1238
	RETURN();
1239
}
1240

  
1241
/* this one is used on every alu op, optimize it!.  */
1242
void OPPROTO op_goto_if_not_x (void)
1243
{
1244
	if (env->pregs[SR_CCS] & X_FLAG)
1245
		GOTO_LABEL_PARAM(1);
1246
	RETURN();
1247
}
1248

  
1249
void OPPROTO op_cc_jmp (void)
1250
{
1251
	if (env->btaken)
1252
		env->pc = PARAM1;
1253
	else
1254
		env->pc = PARAM2;
1255
	RETURN();
1256
}
1257

  
1258
void OPPROTO op_cc_ngoto (void)
1259
{
1260
	if (!env->btaken)
1261
		GOTO_LABEL_PARAM(1);
1262
	RETURN();
1263
}
1264

  
1265
void OPPROTO op_movl_btarget_T0 (void)
1266
{
1267
	env->btarget = T0;
1268
	RETURN();
1269
}
1270

  
1271
void OPPROTO op_jmp (void)
1272
{
1273
	env->pc = env->btarget;
1274
	RETURN();
1275
}
1276

  
1277
/* Load and store */
1278
#define MEMSUFFIX _raw
1279
#include "op_mem.c"
1280
#undef MEMSUFFIX
1281
#if !defined(CONFIG_USER_ONLY)
1282
#define MEMSUFFIX _user
1283
#include "op_mem.c"
1284
#undef MEMSUFFIX
1285

  
1286
#define MEMSUFFIX _kernel
1287
#include "op_mem.c"
1288
#undef MEMSUFFIX
1289
#endif

Also available in: Unified diff