Statistics
| Branch: | Revision:

root / target-sparc / op.c @ 97eb5b14

History | View | Annotate | Download (11.9 kB)

1
/*
2
   SPARC micro operations
3

4
   Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
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

    
21
#include "exec.h"
22

    
23
 /*XXX*/
24
#define REGNAME g0
25
#define REG (env->gregs[0])
26
#include "op_template.h"
27
#define REGNAME g1
28
#define REG (env->gregs[1])
29
#include "op_template.h"
30
#define REGNAME g2
31
#define REG (env->gregs[2])
32
#include "op_template.h"
33
#define REGNAME g3
34
#define REG (env->gregs[3])
35
#include "op_template.h"
36
#define REGNAME g4
37
#define REG (env->gregs[4])
38
#include "op_template.h"
39
#define REGNAME g5
40
#define REG (env->gregs[5])
41
#include "op_template.h"
42
#define REGNAME g6
43
#define REG (env->gregs[6])
44
#include "op_template.h"
45
#define REGNAME g7
46
#define REG (env->gregs[7])
47
#include "op_template.h"
48
#define REGNAME i0
49
#define REG (env->regwptr[16])
50
#include "op_template.h"
51
#define REGNAME i1
52
#define REG (env->regwptr[17])
53
#include "op_template.h"
54
#define REGNAME i2
55
#define REG (env->regwptr[18])
56
#include "op_template.h"
57
#define REGNAME i3
58
#define REG (env->regwptr[19])
59
#include "op_template.h"
60
#define REGNAME i4
61
#define REG (env->regwptr[20])
62
#include "op_template.h"
63
#define REGNAME i5
64
#define REG (env->regwptr[21])
65
#include "op_template.h"
66
#define REGNAME i6
67
#define REG (env->regwptr[22])
68
#include "op_template.h"
69
#define REGNAME i7
70
#define REG (env->regwptr[23])
71
#include "op_template.h"
72
#define REGNAME l0
73
#define REG (env->regwptr[8])
74
#include "op_template.h"
75
#define REGNAME l1
76
#define REG (env->regwptr[9])
77
#include "op_template.h"
78
#define REGNAME l2
79
#define REG (env->regwptr[10])
80
#include "op_template.h"
81
#define REGNAME l3
82
#define REG (env->regwptr[11])
83
#include "op_template.h"
84
#define REGNAME l4
85
#define REG (env->regwptr[12])
86
#include "op_template.h"
87
#define REGNAME l5
88
#define REG (env->regwptr[13])
89
#include "op_template.h"
90
#define REGNAME l6
91
#define REG (env->regwptr[14])
92
#include "op_template.h"
93
#define REGNAME l7
94
#define REG (env->regwptr[15])
95
#include "op_template.h"
96
#define REGNAME o0
97
#define REG (env->regwptr[0])
98
#include "op_template.h"
99
#define REGNAME o1
100
#define REG (env->regwptr[1])
101
#include "op_template.h"
102
#define REGNAME o2
103
#define REG (env->regwptr[2])
104
#include "op_template.h"
105
#define REGNAME o3
106
#define REG (env->regwptr[3])
107
#include "op_template.h"
108
#define REGNAME o4
109
#define REG (env->regwptr[4])
110
#include "op_template.h"
111
#define REGNAME o5
112
#define REG (env->regwptr[5])
113
#include "op_template.h"
114
#define REGNAME o6
115
#define REG (env->regwptr[6])
116
#include "op_template.h"
117
#define REGNAME o7
118
#define REG (env->regwptr[7])
119
#include "op_template.h"
120
#define EIP (env->pc)
121

    
122
#define FLAG_SET(x) (env->psr&x)?1:0
123

    
124
void OPPROTO op_movl_T0_0(void)
125
{
126
    T0 = 0;
127
}
128

    
129
void OPPROTO op_movl_T0_1(void)
130
{
131
    T0 = 1;
132
}
133

    
134
void OPPROTO op_movl_T0_im(void)
135
{
136
    T0 = PARAM1;
137
}
138

    
139
void OPPROTO op_movl_T1_im(void)
140
{
141
    T1 = PARAM1;
142
}
143

    
144
void OPPROTO op_movl_T2_im(void)
145
{
146
    T2 = PARAM1;
147
}
148

    
149
void OPPROTO op_addl_T1_im(void)
150
{
151
    T1 += PARAM1;
152
}
153

    
154
void OPPROTO op_addl_T1_T2(void)
155
{
156
    T1 += T2;
157
}
158

    
159
void OPPROTO op_subl_T1_T2(void)
160
{
161
    T1 -= T2;
162
}
163

    
164
void OPPROTO op_add_T1_T0(void)
165
{
166
    T0 += T1;
167
}
168

    
169
void OPPROTO op_add_T1_T0_cc(void)
170
{
171
    unsigned int src1;
172
    src1 = T0;
173
    T0 += T1;
174
    env->psr = 0;
175
    if (!T0)
176
        env->psr |= PSR_ZERO;
177
    if ((int) T0 < 0)
178
        env->psr |= PSR_NEG;
179
    if (T0 < src1)
180
        env->psr |= PSR_CARRY;
181
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
182
        env->psr |= PSR_OVF;
183
    FORCE_RET();
184
}
185

    
186
void OPPROTO op_sub_T1_T0(void)
187
{
188
    T0 -= T1;
189
}
190

    
191
void OPPROTO op_sub_T1_T0_cc(void)
192
{
193
    unsigned int src1;
194

    
195
    src1 = T0;
196
    T0 -= T1;
197
    env->psr = 0;
198
    if (!T0)
199
        env->psr |= PSR_ZERO;
200
    if ((int) T0 < 0)
201
        env->psr |= PSR_NEG;
202
    if (src1 < T1)
203
        env->psr |= PSR_CARRY;
204
    if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
205
        env->psr |= PSR_OVF;
206
    FORCE_RET();
207
}
208

    
209
void OPPROTO op_and_T1_T0(void)
210
{
211
    T0 &= T1;
212
}
213

    
214
void OPPROTO op_or_T1_T0(void)
215
{
216
    T0 |= T1;
217
}
218

    
219
void OPPROTO op_xor_T1_T0(void)
220
{
221
    T0 ^= T1;
222
}
223

    
224
void OPPROTO op_andn_T1_T0(void)
225
{
226
    T0 &= ~T1;
227
}
228

    
229
void OPPROTO op_orn_T1_T0(void)
230
{
231
    T0 |= ~T1;
232
}
233

    
234
void OPPROTO op_xnor_T1_T0(void)
235
{
236
    T0 ^= ~T1;
237
}
238

    
239
void OPPROTO op_addx_T1_T0(void)
240
{
241
    T0 += T1 + ((env->psr & PSR_CARRY) ? 1 : 0);
242
}
243

    
244
void OPPROTO op_umul_T1_T0(void)
245
{
246
    uint64_t res;
247
    res = (uint64_t) T0 *(uint64_t) T1;
248
    T0 = res & 0xffffffff;
249
    env->y = res >> 32;
250
}
251

    
252
void OPPROTO op_smul_T1_T0(void)
253
{
254
    uint64_t res;
255
    res = (int64_t) ((int32_t) T0) * (int64_t) ((int32_t) T1);
256
    T0 = res & 0xffffffff;
257
    env->y = res >> 32;
258
}
259

    
260
void OPPROTO op_mulscc_T1_T0(void)
261
{
262
    unsigned int b1, C, V, b2, src1;
263
    C = FLAG_SET(PSR_CARRY);
264
    V = FLAG_SET(PSR_OVF);
265
    b1 = C ^ V;
266
    b2 = T0 & 1;
267
    T0 = (b1 << 31) | (T0 >> 1);
268
    if (!(env->y & 1))
269
        T1 = 0;
270
    /* do addition and update flags */
271
    src1 = T0;
272
    T0 += T1;
273
    env->psr = 0;
274
    if (!T0)
275
        env->psr |= PSR_ZERO;
276
    if ((int) T0 < 0)
277
        env->psr |= PSR_NEG;
278
    if (T0 < src1)
279
        env->psr |= PSR_CARRY;
280
    if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
281
        env->psr |= PSR_OVF;
282
    env->y = (b2 << 31) | (env->y >> 1);
283
    FORCE_RET();
284
}
285

    
286
void OPPROTO op_udiv_T1_T0(void)
287
{
288
    uint64_t x0;
289
    uint32_t x1;
290

    
291
    x0 = T0 | ((uint64_t) (env->y) << 32);
292
    x1 = T1;
293
    x0 = x0 / x1;
294
    if (x0 > 0xffffffff) {
295
        T0 = 0xffffffff;
296
        T1 = 1;
297
    } else {
298
        T0 = x0;
299
        T1 = 0;
300
    }
301
    FORCE_RET();
302
}
303

    
304
void OPPROTO op_sdiv_T1_T0(void)
305
{
306
    int64_t x0;
307
    int32_t x1;
308

    
309
    x0 = T0 | ((uint64_t) (env->y) << 32);
310
    x1 = T1;
311
    x0 = x0 / x1;
312
    if ((int32_t) x0 != x0) {
313
        T0 = x0 >> 63;
314
        T1 = 1;
315
    } else {
316
        T0 = x0;
317
        T1 = 0;
318
    }
319
    FORCE_RET();
320
}
321

    
322
void OPPROTO op_div_cc(void)
323
{
324
    env->psr = 0;
325
    if (!T0)
326
        env->psr |= PSR_ZERO;
327
    if ((int) T0 < 0)
328
        env->psr |= PSR_NEG;
329
    if (T1)
330
        env->psr |= PSR_OVF;
331
    FORCE_RET();
332
}
333

    
334
void OPPROTO op_subx_T1_T0(void)
335
{
336
    T0 -= T1 + ((env->psr & PSR_CARRY) ? 1 : 0);
337
}
338

    
339
void OPPROTO op_logic_T0_cc(void)
340
{
341
    env->psr = 0;
342
    if (!T0)
343
        env->psr |= PSR_ZERO;
344
    if ((int) T0 < 0)
345
        env->psr |= PSR_NEG;
346
    FORCE_RET();
347
}
348

    
349
void OPPROTO op_set_flags(void)
350
{
351
    env->psr = 0;
352
    if (!T0)
353
        env->psr |= PSR_ZERO;
354
    if ((unsigned int) T0 < (unsigned int) T1)
355
        env->psr |= PSR_CARRY;
356
    if ((int) T0 < (int) T1)
357
        env->psr |= PSR_OVF;
358
    if ((int) T0 < 0)
359
        env->psr |= PSR_NEG;
360
    FORCE_RET();
361
}
362

    
363
void OPPROTO op_sll(void)
364
{
365
    T0 <<= T1;
366
}
367

    
368
void OPPROTO op_srl(void)
369
{
370
    T0 >>= T1;
371
}
372

    
373
void OPPROTO op_sra(void)
374
{
375
    T0 = ((int32_t) T0) >> T1;
376
}
377

    
378
void OPPROTO op_st(void)
379
{
380
    stl((void *) T0, T1);
381
}
382

    
383
void OPPROTO op_stb(void)
384
{
385
    stb((void *) T0, T1);
386
}
387

    
388
void OPPROTO op_sth(void)
389
{
390
    stw((void *) T0, T1);
391
}
392

    
393
void OPPROTO op_std(void)
394
{
395
    stl((void *) T0, T1);
396
    stl((void *) (T0 + 4), T2);
397
}
398

    
399
void OPPROTO op_ld(void)
400
{
401
    T1 = ldl((void *) T0);
402
}
403

    
404
void OPPROTO op_ldub(void)
405
{
406
    T1 = ldub((void *) T0);
407
}
408

    
409
void OPPROTO op_lduh(void)
410
{
411
    T1 = lduw((void *) T0);
412
}
413

    
414
void OPPROTO op_ldsb(void)
415
{
416
    T1 = ldsb((void *) T0);
417
}
418

    
419
void OPPROTO op_ldsh(void)
420
{
421
    T1 = ldsw((void *) T0);
422
}
423

    
424
void OPPROTO op_ldstub(void)
425
{
426
    T1 = ldub((void *) T0);
427
    stb((void *) T0, 0xff);        /* XXX: Should be Atomically */
428
}
429

    
430
void OPPROTO op_swap(void)
431
{
432
    unsigned int tmp = ldl((void *) T0);
433
    stl((void *) T0, T1);        /* XXX: Should be Atomically */
434
    T1 = tmp;
435
}
436

    
437
void OPPROTO op_ldd(void)
438
{
439
    T1 = ldl((void *) T0);
440
    T0 = ldl((void *) (T0 + 4));
441
}
442

    
443
void OPPROTO op_wry(void)
444
{
445
    env->y = T0;
446
}
447

    
448
void OPPROTO op_rdy(void)
449
{
450
    T0 = env->y;
451
}
452

    
453
void raise_exception(int tt)
454
{
455
    env->exception_index = tt;
456
    cpu_loop_exit();
457
}   
458

    
459
void memcpy32(uint32_t *dst, const uint32_t *src)
460
{
461
    dst[0] = src[0];
462
    dst[1] = src[1];
463
    dst[2] = src[2];
464
    dst[3] = src[3];
465
    dst[4] = src[4];
466
    dst[5] = src[5];
467
    dst[6] = src[6];
468
    dst[7] = src[7];
469
}
470

    
471
static inline void set_cwp(int new_cwp)
472
{
473
    /* put the modified wrap registers at their proper location */
474
    if (env->cwp == (NWINDOWS - 1))
475
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
476
    env->cwp = new_cwp;
477
    /* put the wrap registers at their temporary location */
478
    if (new_cwp == (NWINDOWS - 1))
479
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
480
    env->regwptr = env->regbase + (new_cwp * 16);
481
}
482

    
483
/* XXX: use another pointer for %iN registers to avoid slow wrapping
484
   handling ? */
485
void OPPROTO op_save(void)
486
{
487
    int cwp;
488
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
489
    if (env->wim & (1 << cwp)) {
490
        raise_exception(TT_WIN_OVF);
491
    }
492
    set_cwp(cwp);
493
    FORCE_RET();
494
}
495

    
496
void OPPROTO op_restore(void)
497
{
498
    int cwp;
499
    cwp = (env->cwp + 1) & (NWINDOWS - 1); 
500
    if (env->wim & (1 << cwp)) {
501
        raise_exception(TT_WIN_UNF);
502
    }
503
    set_cwp(cwp);
504
    FORCE_RET();
505
}
506

    
507
void OPPROTO op_exception(void)
508
{
509
    env->exception_index = PARAM1;
510
    cpu_loop_exit();
511
}
512

    
513
void OPPROTO op_trap_T0(void)
514
{
515
    env->exception_index = TT_TRAP + (T0 & 0x7f);
516
    cpu_loop_exit();
517
}
518

    
519
void OPPROTO op_trapcc_T0(void)
520
{
521
    if (T2) {
522
        env->exception_index = TT_TRAP + (T0 & 0x7f);
523
        cpu_loop_exit();
524
    }
525
    FORCE_RET();
526
}
527

    
528
void OPPROTO op_exit_tb(void)
529
{
530
    EXIT_TB();
531
}
532

    
533
void OPPROTO op_eval_be(void)
534
{
535
    T2 = (env->psr & PSR_ZERO);
536
}
537

    
538
void OPPROTO op_eval_ble(void)
539
{
540
    unsigned int Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
541
    
542
    T2 = Z | (N ^ V);
543
}
544

    
545
void OPPROTO op_eval_bl(void)
546
{
547
    unsigned int N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
548

    
549
    T2 = N ^ V;
550
}
551

    
552
void OPPROTO op_eval_bleu(void)
553
{
554
    unsigned int Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY);
555

    
556
    T2 = C | Z;
557
}
558

    
559
void OPPROTO op_eval_bcs(void)
560
{
561
    T2 = (env->psr & PSR_CARRY);
562
}
563

    
564
void OPPROTO op_eval_bvs(void)
565
{
566
    T2 = (env->psr & PSR_OVF);
567
}
568

    
569
void OPPROTO op_eval_bneg(void)
570
{
571
    T2 = (env->psr & PSR_NEG);
572
}
573

    
574
void OPPROTO op_eval_bne(void)
575
{
576
    T2 = !(env->psr & PSR_ZERO);
577
}
578

    
579
void OPPROTO op_eval_bg(void)
580
{
581
    unsigned int Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
582

    
583
    T2 = !(Z | (N ^ V));
584
}
585

    
586
void OPPROTO op_eval_bge(void)
587
{
588
    unsigned int N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
589

    
590
    T2 = !(N ^ V);
591
}
592

    
593
void OPPROTO op_eval_bgu(void)
594
{
595
    unsigned int Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY);
596

    
597
    T2 = !(C | Z);
598
}
599

    
600
void OPPROTO op_eval_bcc(void)
601
{
602
    T2 = !(env->psr & PSR_CARRY);
603
}
604

    
605
void OPPROTO op_eval_bpos(void)
606
{
607
    T2 = !(env->psr & PSR_NEG);
608
}
609

    
610
void OPPROTO op_eval_bvc(void)
611
{
612
    T2 = !(env->psr & PSR_OVF);
613
}
614

    
615
void OPPROTO op_movl_T2_0(void)
616
{
617
    T2 = 0;
618
}
619

    
620
void OPPROTO op_movl_T2_1(void)
621
{
622
    T2 = 1;
623
}
624

    
625
void OPPROTO op_jmp_im(void)
626
{
627
    env->pc = PARAM1;
628
}
629

    
630
void OPPROTO op_movl_npc_im(void)
631
{
632
    env->npc = PARAM1;
633
}
634

    
635
void OPPROTO op_movl_npc_T0(void)
636
{
637
    env->npc = T0;
638
}
639

    
640
void OPPROTO op_next_insn(void)
641
{
642
    env->pc = env->npc;
643
    env->npc = env->npc + 4;
644
}
645

    
646
void OPPROTO op_branch(void)
647
{
648
    env->npc = PARAM3; /* XXX: optimize */
649
    JUMP_TB(op_branch, PARAM1, 0, PARAM2);
650
}
651

    
652
void OPPROTO op_branch2(void)
653
{
654
    if (T2) {
655
        env->npc = PARAM2 + 4; 
656
        JUMP_TB(op_branch2, PARAM1, 0, PARAM2);
657
    } else {
658
        env->npc = PARAM3 + 4; 
659
        JUMP_TB(op_branch2, PARAM1, 1, PARAM3);
660
    }
661
    FORCE_RET();
662
}
663

    
664
void OPPROTO op_branch_a(void)
665
{
666
    if (T2) {
667
        env->npc = PARAM2; /* XXX: optimize */
668
        JUMP_TB(op_generic_branch_a, PARAM1, 0, PARAM3);
669
    } else {
670
        env->npc = PARAM3 + 8; /* XXX: optimize */
671
        JUMP_TB(op_generic_branch_a, PARAM1, 1, PARAM3 + 4);
672
    }
673
    FORCE_RET();
674
}
675

    
676
void OPPROTO op_generic_branch(void)
677
{
678
    if (T2) {
679
        env->npc = PARAM1;
680
    } else {
681
        env->npc = PARAM2;
682
    }
683
    FORCE_RET();
684
}
685