OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [sim/] [tic80/] [tic80.igen] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
// Texas Instruments TMS320C80 (MVP) Simulator.
2
 
3
 
4
// The following is called when ever an illegal instruction is encountered.
5
:internal::::illegal:
6
{
7
  sim_io_eprintf (SD, "0x%lx: illegal instruction\n", (unsigned long) cia.ip);
8
  sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIM_SIGILL);
9
}
10
 
11
// The following is called when ever an FP op is attempted with FPU disabled.
12
:internal::::fp_unavailable:
13
{
14
  sim_io_eprintf (SD, "0x%lx: floating-point unavailable\n", (unsigned long) cia.ip);
15
  sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIM_SIGFPE);
16
}
17
 
18
// Handle a branch instruction
19
:function:::instruction_address:do_branch:int annul, address_word target, int rLink_p, unsigned32 *rLink
20
{
21
  instruction_address nia;
22
  if (annul)
23
    {
24
      if (rLink_p)
25
        *rLink = cia.dp;
26
      nia.ip = target;
27
      nia.dp = target + 4;
28
    }
29
  else
30
    {
31
      if (rLink_p)
32
        *rLink = cia.dp + sizeof (instruction_word);
33
      nia.ip = cia.dp;
34
      nia.dp = target;
35
    }
36
  return nia;
37
}
38
 
39
// Signed Integer Add - add source1, source2, dest
40
:function:::void:do_add:unsigned32 *rDest, signed32 source1, signed32 source2
41
{
42
  unsigned32 result;
43
  ALU_BEGIN (source1);
44
  ALU_ADD (source2);
45
  ALU_END (result);
46
  *rDest = result;
47
  TRACE_ALU3 (MY_INDEX, result, source1, source2);
48
  /* FIXME - a signed add may cause an exception */
49
}
50
31.Dest,26.Source2,21.0b101100,15.0,14.SignedImmediate::::add i
51
"add , r, r"
52
{
53
  do_add (_SD, rDest, vSource1, vSource2);
54
}
55
31.Dest,26.Source2,21.0b11101100,13.0,12.0,11./,4.Source1::::add r
56
"add r, r, r"
57
{
58
  do_add (_SD, rDest, vSource1, vSource2);
59
}
60
31.Dest,26.Source2,21.0b11101100,13.0,12.1,11./+LongSignedImmediate::::add l
61
"add 0x%08lx, r, r"
62
{
63
  do_add (_SD, rDest, LongSignedImmediate, vSource2);
64
}
65
 
66
 
67
// Unsigned Integer Add - addu source1, source2, dest
68
:function:::void:do_addu:unsigned32 *rDest, unsigned32 source1, unsigned32 source2
69
{
70
  unsigned32 result = source1 + source2;
71
  TRACE_ALU3 (MY_INDEX, result, source1, source2);
72
  *rDest = result;
73
}
74
 
75
31.Dest,26.Source2,21.0b101100,15.1,14.SignedImmediate::::addu i
76
"addu , r, r"
77
{
78
  do_addu (_SD, rDest, vSource1, vSource2);
79
}
80
31.Dest,26.Source2,21.0b11101100,13.1,12.0,11./,4.Source1::::addu r
81
"addu r, r, r"
82
{
83
  do_addu (_SD, rDest, vSource1, vSource2);
84
}
85
31.Dest,26.Source2,21.0b11101100,13.1,12.1,11./+LongSignedImmediate::::addu l
86
"addu 0x%08lx, r, r"
87
{
88
  do_addu (_SD, rDest, LongSignedImmediate, vSource2);
89
}
90
 
91
 
92
:function:::void:do_and:signed32 *rDest, signed32 source1, signed32 source2
93
{
94
  unsigned32 result = source1 & source2;
95
  TRACE_ALU3 (MY_INDEX, result, source1, source2);
96
  *rDest = result;
97
}
98
 
99
 
100
// and, and.tt
101
31.Dest,26.Source2,21.0b0010001,14.UnsignedImmediate::::and.tt i
102
"and.tt , r, r"
103
{
104
  do_and (_SD, rDest, vSource1, vSource2);
105
}
106
31.Dest,26.Source2,21.0b110010001,12.0,11./,4.Source1::::and.tt r
107
"and.tt r, r, r"
108
{
109
  do_and (_SD, rDest, vSource1, vSource2);
110
}
111
31.Dest,26.Source2,21.0b110010001,12.1,11./+LongSignedImmediate::::and.tt l
112
"and.tt 0x%08lx, r, r"
113
{
114
  do_and (_SD, rDest, LongSignedImmediate, vSource2);
115
 
116
}
117
 
118
// and.ff
119
31.Dest,26.Source2,21.0b0011000,14.UnsignedImmediate::::and.ff i
120
"and.ff , r, r"
121
{
122
  do_and (_SD, rDest, ~vSource1, ~vSource2);
123
}
124
31.Dest,26.Source2,21.0b110011000,12.0,11./,4.Source1::::and.ff r
125
"and.ff r, r, r"
126
{
127
  do_and (_SD, rDest, ~vSource1, ~vSource2);
128
}
129
31.Dest,26.Source2,21.0b110011000,12.1,11./+LongSignedImmediate::::and.ff l
130
"and.ff 0x%08lx, r, r"
131
{
132
  do_and (_SD, rDest, ~LongSignedImmediate, ~vSource2);
133
}
134
 
135
// and.ft
136
31.Dest,26.Source2,21.0b0010100,14.UnsignedImmediate::::and.ft i
137
"and.ft , r, r"
138
{
139
  do_and (_SD, rDest, ~vSource1, vSource2);
140
}
141
31.Dest,26.Source2,21.0b110010100,12.0,11./,4.Source1::::and.ft r
142
"and.ft r, r, r"
143
{
144
  do_and (_SD, rDest, ~vSource1, vSource2);
145
}
146
31.Dest,26.Source2,21.0b110010100,12.1,11./+LongSignedImmediate::::and.ft l
147
"and.ft 0x%08lx, r, r"
148
{
149
  do_and (_SD, rDest, ~LongSignedImmediate, vSource2);
150
}
151
 
152
// and.tf
153
31.Dest,26.Source2,21.0b0010010,14.UnsignedImmediate::::and.tf i
154
"and.tf , r, r"
155
{
156
  do_and (_SD, rDest, vSource1, ~vSource2);
157
}
158
31.Dest,26.Source2,21.0b110010010,12.0,11./,4.Source1::::and.tf r
159
"and.tf r, r, r"
160
{
161
  do_and (_SD, rDest, vSource1, ~vSource2);
162
}
163
31.Dest,26.Source2,21.0b110010010,12.1,11./+LongSignedImmediate::::and.tf l
164
"and.tf 0x%08lx, r, r"
165
{
166
  do_and (_SD, rDest, LongSignedImmediate, ~vSource2);
167
}
168
 
169
// bbo[.a]
170
:function:::instruction_address:do_bbo:instruction_address nia, int bitnum, unsigned32 source, int annul, unsigned32 offset
171
{
172
  int jump_p;
173
  address_word target = cia.ip + 4 * offset;
174
  if (MASKED32 (source, bitnum, bitnum))
175
    {
176
      nia = do_branch (_SD, annul, target, 0, NULL);
177
      jump_p = 1;
178
    }
179
  else
180
    jump_p = 0;
181
  TRACE_COND_BR(MY_INDEX, jump_p, bitnum, target, -1, -1);
182
  return nia;
183
}
184
:%s::::A:int A
185
{
186
  if (A)
187
    return ".a";
188
  else
189
    return "";
190
}
191
31.BITNUM,26.Source,21.0b100101,15.A,14.SignedOffset::::bbo i
192
"bbo%s , r, "
193
{
194
  nia = do_bbo (_SD, nia, bitnum, vSource, A, vSignedOffset);
195
}
196
31.BITNUM,26.Source,21.0b11100101,13.A,12.0,11./,4.IndOff::::bbo r
197
"bbo%s r, r, "
198
{
199
  nia = do_bbo (_SD, nia, bitnum, vSource, A, rIndOff);
200
}
201
31.BITNUM,26.Source,21.0b11100101,13.A,12.1,11./+LongSignedImmediate::::bbo l
202
"bbo%s , r, "
203
{
204
  nia = do_bbo (_SD, nia, bitnum, vSource, A, LongSignedImmediate);
205
}
206
 
207
// bbz[.a]
208
:function:::instruction_address:do_bbz:instruction_address nia, int bitnum, unsigned32 source, int annul, unsigned32 offset
209
{
210
  int jump_p;
211
  address_word target = cia.ip + 4 * offset;
212
  if (!MASKED32 (source, bitnum, bitnum))
213
    {
214
      nia = do_branch (_SD, annul, target, 0, NULL);
215
      jump_p = 1;
216
    }
217
  else
218
    jump_p = 0;
219
  TRACE_COND_BR(MY_INDEX, jump_p, bitnum, target, -1, -1);
220
  return nia;
221
}
222
31.BITNUM,26.Source,21.0b100100,15.A,14.SignedOffset::::bbz i
223
"bbz%s , r, "
224
{
225
  nia = do_bbz (_SD, nia, bitnum, vSource, A, vSignedOffset);
226
}
227
31.BITNUM,26.Source,21.0b11100100,13.A,12.0,11./,4.IndOff::::bbz r
228
"bbz%s r, r, "
229
{
230
  nia = do_bbz (_SD, nia, bitnum, vSource, A, rIndOff);
231
}
232
31.BITNUM,26.Source,21.0b11100100,13.A,12.1,11./+LongSignedImmediate::::bbz l
233
"bbz%s , r, "
234
{
235
  nia = do_bbz (_SD, nia, bitnum, vSource, A, LongSignedImmediate);
236
}
237
 
238
// bcnd[.a]
239
:function:::instruction_address:do_bcnd:instruction_address nia, int Cond, unsigned32 source, int annul, unsigned32 offset
240
{
241
  int condition;
242
  int size = EXTRACTED32 (Cond, 31 - 27, 30 - 27);
243
  int code = EXTRACTED32 (Cond, 29 - 27, 27 - 27);
244
  signed32 val = 0;
245
  address_word target = cia.ip + 4 * offset;
246
  switch (size)
247
    {
248
    case 0: val = SEXT32 (source, 7); break;
249
    case 1: val = SEXT32 (source, 15); break;
250
    case 2: val = source; break;
251
    default: sim_engine_abort (SD, CPU, cia, "bcnd - reserved size");
252
    }
253
  switch (code)
254
    {
255
    case 0: condition = 0; break;
256
    case 1: condition = val > 0; break;
257
    case 2: condition = val == 0; break;
258
    case 3: condition = val >= 0; break;
259
    case 4: condition = val < 0; break;
260
    case 5: condition = val != 0; break;
261
    case 6: condition = val <= 0; break;
262
    default: condition = 1; break;
263
    }
264
  if (condition)
265
    {
266
      nia = do_branch (_SD, annul, target, 0, NULL);
267
    }
268
  TRACE_COND_BR(MY_INDEX, condition, val, target, size, code);
269
  return nia;
270
}
271
31.Code,26.Source,21.0b100110,15.A,14.SignedOffset::::bcnd i
272
"bcnd%s , r, "
273
{
274
  nia = do_bcnd (_SD, nia, Code, vSource, A, vSignedOffset);
275
}
276
31.Code,26.Source,21.0b11100110,13.A,12.0,11./,4.IndOff::::bcnd r
277
"bcnd%s r, r, "
278
{
279
  nia = do_bcnd (_SD, nia, Code, vSource, A, rIndOff);
280
}
281
31.Code,26.Source,21.0b11100110,13.A,12.1,11./+LongSignedImmediate::::bcnd l
282
"bcnd%s , r, "
283
{
284
  nia = do_bcnd (_SD, nia, Code, vSource, A, LongSignedImmediate);
285
}
286
 
287
// br[.a] - see bbz[.a]
288
 
289
 
290
// brcr
291
:function:::sim_cia:do_brcr:instruction_address nia, int cr
292
{
293
  if (cr >= 0x4000 || !(CPU)->is_user_mode)
294
    {
295
      unsigned32 control = CR (cr);
296
      unsigned32 ie = control & 0x00000001;
297
      unsigned32 pc = control & 0xfffffffc;
298
      unsigned32 is_user_mode = control & 0x00000002;
299
      (CPU)->is_user_mode = is_user_mode;
300
      nia.dp = pc;
301
      if (ie)
302
        (CPU)->cr[IE_CR] |= IE_CR_IE;
303
      else
304
        (CPU)->cr[IE_CR] &= ~IE_CR_IE;
305
    }
306
  TRACE_UCOND_BR (MY_INDEX, nia.dp);
307
  return nia;
308
}
309
31.//,27.0,26.//,21.0b0000110,14.UCRN::::brcr i
310
"brcr CR[]"
311
{
312
  nia = do_brcr (_SD, nia, UCRN);
313
}
314
31.//,27.0,26.//,21.0b110000110,12.0,11./,4.INDCR::::brcr r
315
"brcr CR[r]"
316
{
317
  nia = do_brcr (_SD, nia, UCRN);
318
}
319
31.//,27.0,26.//,21.0b110000110,12.1,11./+UnsignedControlRegisterNumber::::brcr l
320
"brcr CR[]"
321
{
322
  nia = do_brcr (_SD, nia, UnsignedControlRegisterNumber);
323
}
324
 
325
// bsr[.a]
326
:function:::instruction_address:do_bsr:instruction_address nia, signed32 *rLink, int annul, unsigned32 offset
327
{
328
  address_word target = cia.ip + 4 * offset;
329
  nia = do_branch (_SD, annul, target, 1, rLink);
330
  TRACE_UCOND_BR (MY_INDEX, target);
331
  return nia;
332
}
333
31.Link,26./,21.0b100000,15.A,14.SignedOffset::::bsr i
334
"bsr%s , r"
335
{
336
  nia = do_bsr (_SD, nia, rLink, A, vSignedOffset);
337
}
338
31.Link,26./,21.0b11100000,13.A,12.0,11./,4.IndOff::::bsr r
339
"bsr%s r, r"
340
{
341
  nia = do_bsr (_SD, nia, rLink, A, rIndOff);
342
}
343
31.Link,26./,21.0b11100000,13.A,12.1,11./+LongSignedImmediate::::bsr l
344
"bsr%s , r"
345
{
346
  nia = do_bsr (_SD, nia, rLink, A, LongSignedImmediate);
347
}
348
 
349
// cmnd
350
:function:::void:do_cmnd:signed32 source
351
{
352
  int Reset = EXTRACTED32 (source, 31, 31);
353
  int Halt = EXTRACTED32 (source, 30, 30);
354
  int Unhalt = EXTRACTED32 (source, 29, 29);
355
  /* int ICR = EXTRACTED32 (source, 28, 28); */
356
  /* int DCR = EXTRACTED32 (source, 27, 27); */
357
  int Task = EXTRACTED32 (source, 14, 14);
358
  int Msg = EXTRACTED32 (source, 13, 13);
359
  int VC = EXTRACTED32 (source, 10, 10);
360
  int TC = EXTRACTED32 (source, 9, 9);
361
  int MP = EXTRACTED32 (source, 8, 8);
362
  int PP = EXTRACTED32 (source, 3, 0);
363
  /* what is implemented? */
364
  if (PP != 0)
365
    sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - PPs not supported",
366
                      (unsigned long) cia.ip);
367
  if (VC != 0)
368
    sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - VC not supported",
369
                      (unsigned long) cia.ip);
370
  if (TC != 0)
371
    sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - TC not supported",
372
                      (unsigned long) cia.ip);
373
  if (MP)
374
    {
375
      if (Reset || Halt)
376
        sim_engine_halt (SD, CPU, NULL, cia, sim_exited, 0);
377
      if (Unhalt)
378
        sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not unhalt the MP",
379
                          (unsigned long) cia.ip);
380
      /* if (ICR || DCR); */
381
      if (Task)
382
        sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not Task the MP",
383
                          (unsigned long) cia.ip);
384
      if (Msg)
385
        sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Msg to MP not suported",
386
                          (unsigned long) cia.ip);
387
    }
388
  TRACE_SINK1 (MY_INDEX, source);
389
}
390
31./,21.0b0000010,14.UI::::cmnd i
391
"cmnd "
392
{
393
  do_cmnd (_SD, UI);
394
}
395
31./,21.0b110000010,12.0,11./,4.Source::::cmnd r
396
"cmnd r"
397
{
398
  do_cmnd (_SD, vSource);
399
}
400
31./,21.0b110000010,12.1,11./+LongUnsignedImmediate::::cmnd l
401
"cmnd "
402
{
403
  do_cmnd (_SD, LongUnsignedImmediate);
404
}
405
 
406
// cmp
407
:function:::unsigned32:cmp_vals:signed32 s1, unsigned32 u1, signed32 s2, unsigned32 u2
408
{
409
  unsigned32 field = 0;
410
  if (s1 == s2) field |= 0x001;
411
  if (s1 != s2) field |= 0x002;
412
  if (s1 >  s2) field |= 0x004;
413
  if (s1 <= s2) field |= 0x008;
414
  if (s1 <  s2) field |= 0x010;
415
  if (s1 >= s2) field |= 0x020;
416
  if (u1 >  u2) field |= 0x040;
417
  if (u1 <= u2) field |= 0x080;
418
  if (u1 <  u2) field |= 0x100;
419
  if (u1 >= u2) field |= 0x200;
420
  return field;
421
}
422
:function:::void:do_cmp:unsigned32 *rDest, unsigned32 source1, unsigned32 source2
423
{
424
  unsigned32 field = 0;
425
  field |= cmp_vals (_SD, source1, source1, source2, source2) << 20;
426
  field |= cmp_vals (_SD, (signed16)source1, (unsigned16)source1,
427
         (signed16)source2, (unsigned16)source2) << 10;
428
  field |= cmp_vals (_SD, (signed8)source1, (unsigned8)source1,
429
          (signed8)source2, (unsigned8)source2);
430
  TRACE_CMP (MY_INDEX, field, source1, source2);
431
  *rDest = field;
432
}
433
31.Dest,26.Source2,21.0b1010000,14.SignedImmediate::::cmp i
434
"cmp , r, r"
435
{
436
  do_cmp (_SD, rDest, vSource1, vSource2);
437
}
438
31.Dest,26.Source2,21.0b111010000,12.0,11./,4.Source1::::cmp r
439
"cmp r, r, r"
440
{
441
  do_cmp (_SD, rDest, vSource1, vSource2);
442
}
443
31.Dest,26.Source2,21.0b111010000,12.1,11./+LongSignedImmediate::::cmp l
444
"cmp 0x%08lx, r, r"
445
{
446
  do_cmp (_SD, rDest, LongSignedImmediate, vSource2);
447
}
448
 
449
// dcache
450
:%s::::F:int F
451
{
452
  if (F)
453
    return "f";
454
  else
455
    return "c";
456
}
457
31./,27.F,26.Source2,21.0b0111,17.m,16.0b00,14.SignedOffset::::dcache i
458
"dcache%s  (r%s)"
459
{
460
  TRACE_NOP (MY_INDEX);
461
  /* NOP */
462
}
463
31./,27.F,26.Source2,21.0b110111,15.m,14.0b00,12.0,11./,4.Source1::::dcache r
464
"dcache%s r (r%s)"
465
{
466
  TRACE_NOP (MY_INDEX);
467
  /* NOP */
468
}
469
31./,27.F,26.Source2,21.0b110111,15.m,14.0b00,12.1,11./+LongSignedImmediate::::dcache l
470
"dcache%s  (r%s)"
471
{
472
  TRACE_NOP (MY_INDEX);
473
  /* NOP */
474
}
475
 
476
// dld[{.b|.h|.d}]
477
void::function::do_dld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset
478
{
479
  do_ld (_SD, Dest, base, rBase, m, sz, S, offset);
480
}
481
31.Dest,26.Base,21.0b110100,15.m,14.sz,12.0,11.S,10.1,9./,4.IndOff::::dld r
482
"dld%s r%s (r%s), r"
483
{
484
  do_dld (_SD, Dest, vBase, rBase, m, sz, S, rIndOff);
485
}
486
31.Dest,26.Base,21.0b110100,15.m,14.sz,12.1,11.S,10.1,9./+LongSignedImmediateOffset::::dld l
487
"dld%s 0x%08lx%s (r%s), r"
488
{
489
  do_dld (_SD, Dest, vBase, rBase, m, sz, S, LongSignedImmediateOffset);
490
}
491
 
492
// dld.u[{.b|.h|.d}]
493
void::function::do_dld_u:unsigned32 *rDest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset
494
{
495
  do_ld_u (_SD, rDest, base, rBase, m, sz, S, offset);
496
}
497
31.Dest,26.Base,21.0b110101,15.m,14.sz,12.0,11.S,10.1,9./,4.IndOff::::dld.u r
498
"dld.u%s r%s (r%s), r"
499
{
500
  do_dld_u (_SD, rDest, vBase, rBase, m, sz, S, rIndOff);
501
}
502
31.Dest,26.Base,21.0b110101,15.m,14.sz,12.1,11.S,10.1,9./+LongSignedImmediateOffset::::dld.u l
503
"dld.u%s 0x%08lx%s (r%s), r"
504
{
505
  do_dld_u (_SD, rDest, vBase, rBase, m, sz, S, LongSignedImmediateOffset);
506
}
507
 
508
// dst[{.b|.h|.d}]
509
void::function::do_dst:int Source, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset
510
{
511
  do_st (_SD, Source, base, rBase, m, sz, S, offset);
512
}
513
31.Source,26.Base,21.0b110110,15.m,14.sz,12.0,11.S,10.1,9./,4.IndOff::::dst r
514
"dst%s r%s (r%s), r"
515
{
516
  do_dst (_SD, Source, vBase, rBase, m, sz, S, rIndOff);
517
}
518
31.Source,26.Base,21.0b110110,15.m,14.sz,12.1,11.S,10.1,9./+LongSignedImmediateOffset::::dst l
519
"dst%s 0x%08lx%s (r%s), r"
520
{
521
  do_dst (_SD, Source, vBase, rBase, m, sz, S, LongSignedImmediateOffset);
522
}
523
 
524
// estop
525
31./,21.0b1111111,14.1,13.0,12.0,11./::::estop
526
 
527
// etrap
528
31./,27.1,26./,21.0b0000001,14.UTN::::etrap i
529
31./,27.1,26./,21.0b110000001,12.0,11./,4.iUTN::::etrap r
530
31./,27.1,26./,21.0b110000001,12.1,11./::::etrap l
531
 
532
 
533
// exts - see shift.ds
534
 
535
 
536
// extu - see shift.dz
537
 
538
 
539
sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision
540
{
541
  sim_fpu ans;
542
  switch (precision)
543
    {
544
    case 0: /* single */
545
      sim_fpu_32to (&ans, val);
546
      break;
547
    case 1: /* double */
548
      if (reg < 0)
549
        sim_engine_abort (SD, CPU, cia, "DP immediate invalid");
550
      if (reg & 1)
551
        sim_engine_abort (SD, CPU, cia, "DP FP register must be even");
552
      if (reg <= 1)
553
        sim_engine_abort (SD, CPU, cia, "DP FP register must be >= 2");
554
      sim_fpu_232to (&ans, GPR (reg + 1), GPR (reg));
555
      break;
556
    case 2: /* 32 bit signed integer */
557
      sim_fpu_i32to (&ans, val, 0);
558
      break;
559
    case 3: /* 32 bit unsigned integer */
560
      sim_fpu_u32to (&ans, val, 0);
561
      break;
562
    default:
563
      sim_engine_abort (SD, CPU, cia, "Unsupported FP precision");
564
    }
565
  return ans;
566
}
567
void::function::set_fp_reg:int Dest, sim_fpu val, int PD
568
{
569
  switch (PD)
570
    {
571
    case 0: /* single */
572
      {
573
        sim_fpu_to32 (&GPR (Dest), &val);
574
        break;
575
      }
576
    case 1: /* double */
577
      {
578
        if (Dest & 1)
579
          sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be even");
580
        if (Dest <= 1)
581
          sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be >= 2");
582
        sim_fpu_to232 (&GPR (Dest + 1), &GPR (Dest + 0), &val);
583
        break;
584
      }
585
    case 2: /* signed */
586
      {
587
        sim_fpu_to32i (&GPR (Dest), &val, 0);
588
        break;
589
      }
590
    case 3: /* unsigned */
591
      {
592
        sim_fpu_to32u (&GPR (Dest), &val, 0);
593
        break;
594
      }
595
    default:
596
      sim_engine_abort (SD, CPU, cia, "Unsupported FP precision");
597
    }
598
 
599
}
600
// fadd.{s|d}{s|d}{s|d}
601
void::function::do_fadd:int Dest, int PD, sim_fpu s1, sim_fpu s2
602
{
603
  sim_fpu ans;
604
  sim_fpu_add (&ans, &s1, &s2);
605
  TRACE_FPU3 (ans, s1, s2);
606
  set_fp_reg (_SD, Dest, ans, PD);
607
}
608
const char *::function::str_PX:int PX
609
{
610
  switch (PX)
611
    {
612
    case 0: return "s";
613
    case 1: return "d";
614
    case 2: return "i";
615
    case 3: return "u";
616
    default: return "?";
617
    }
618
}
619
31.Dest,26.Source2,21.0b111110000,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::f::fadd r
620
"fadd.%s%s%s r, r, r"
621
{
622
  do_fadd (_SD, Dest, PD,
623
           get_fp_reg (_SD, Source1, vSource1, P1),
624
           get_fp_reg (_SD, Source2, vSource2, P2));
625
}
626
31.Dest,26.Source2,21.0b111110000,12.1,11.r,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fadd l
627
"fadd.%s%s%s 0x%08lx, r, r"
628
{
629
  do_fadd (_SD, Dest, PD,
630
           get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1),
631
           get_fp_reg (_SD, Source2, vSource2, P2));
632
 
633
}
634
 
635
// fcmp.{s|d}{s|d}{s|d}
636
void::function::do_fcmp:unsigned32 *rDest, sim_fpu s1, sim_fpu s2
637
{
638
  unsigned32 result = 0;
639
  if (sim_fpu_is_nan (&s1) || sim_fpu_is_nan (&s2))
640
    result |= BIT32 (30);
641
  else
642
    {
643
      result |= BIT32 (31);
644
      if (sim_fpu_is_eq (&s1, &s2)) result |= BIT32(20);
645
      if (sim_fpu_is_ne (&s1, &s2)) result |= BIT32(21);
646
      if (sim_fpu_is_gt (&s1, &s2)) result |= BIT32(22);
647
      if (sim_fpu_is_le (&s1, &s2)) result |= BIT32(23);
648
      if (sim_fpu_is_lt (&s1, &s2)) result |= BIT32(24);
649
      if (sim_fpu_is_ge (&s1, &s2)) result |= BIT32(25);
650
      if (sim_fpu_is_lt (&s1, &sim_fpu_zero)
651
          || sim_fpu_is_gt (&s1, &s2)) result |= BIT32(26);
652
      if (sim_fpu_is_lt (&sim_fpu_zero, &s1)
653
          && sim_fpu_is_lt (&s1, &s2)) result |= BIT32(27);
654
      if (sim_fpu_is_le (&sim_fpu_zero, &s1)
655
          && sim_fpu_is_le (&s1, &s2)) result |= BIT32(28);
656
      if (sim_fpu_is_le (&s1, &sim_fpu_zero)
657
          || sim_fpu_is_ge (&s1, &s2)) result |= BIT32(29);
658
    }
659
  *rDest = result;
660
  TRACE_FPU2CMP (result, s1, s2);
661
}
662
31.Dest,26.Source2,21.0b111110101,12.0,11./,10.0,8.P2,6.P1,4.Source1::f::fcmp r
663
"fcmp.%s%s r, r, r"
664
{
665
  do_fcmp (_SD, rDest,
666
           get_fp_reg (_SD, Source1, vSource1, P1),
667
           get_fp_reg (_SD, Source2, vSource2, P2));
668
}
669
31.Dest,26.Source2,21.0b111110101,12.1,11./,10.0,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fcmp l
670
"fcmp.%s%s 0x%08lx, r, r"
671
{
672
  do_fcmp (_SD, rDest,
673
           get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1),
674
           get_fp_reg (_SD, Source2, vSource2, P2));
675
}
676
 
677
 
678
// fdiv.{s|d}{s|d}{s|d}
679
void::function::do_fdiv:int Dest, int PD, sim_fpu s1, sim_fpu s2
680
{
681
  sim_fpu ans;
682
  sim_fpu_div (&ans, &s1, &s2);
683
  TRACE_FPU3 (ans, s1, s2);
684
  set_fp_reg (_SD, Dest, ans, PD);
685
}
686
31.Dest,26.Source2,21.0b111110011,12.0,11./,10.PD,8.P2,6.P1,4.Source1::f::fdiv r
687
"fdiv.%s%s%s r, r, r"
688
{
689
  do_fdiv (_SD, Dest, PD,
690
           get_fp_reg (_SD, Source1, vSource1, P1),
691
           get_fp_reg (_SD, Source2, vSource2, P2));
692
}
693
31.Dest,26.Source2,21.0b111110011,12.1,11./,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fdiv l
694
"fdiv.%s%s%s 0x%08lx, r, r"
695
{
696
  do_fdiv (_SD, Dest, PD,
697
           get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1),
698
           get_fp_reg (_SD, Source2, vSource2, P2));
699
}
700
 
701
// fmpy.{s|d|i|u}{s|d|i|u}{s|d|i|u}
702
void::function::do_fmpy:int Dest, int PD, sim_fpu s1, sim_fpu s2
703
{
704
  switch (PD)
705
    {
706
    case 2: /* signed */
707
      {
708
        signed64 i1;
709
        signed64 i2;
710
        sim_fpu_to64i (&i1, &s1, 0);
711
        sim_fpu_to64i (&i2, &s2, 0);
712
        GPR (Dest) = i1 * i2;
713
        TRACE_FPU2I (GPR (Dest), s1, s2);
714
        break;
715
      }
716
    case 3: /* unsigned */
717
      {
718
        unsigned64 u1;
719
        unsigned64 u2;
720
        sim_fpu_to64u (&u1, &s1, 0);
721
        sim_fpu_to64u (&u2, &s2, 0);
722
        GPR (Dest) = u1 * u2;
723
        TRACE_FPU2I (GPR (Dest), s1, s2);
724
        break;
725
      }
726
    default:
727
      {
728
        sim_fpu ans;
729
        sim_fpu_mul (&ans, &s1, &s2);
730
        set_fp_reg (_SD, Dest, ans, PD);
731
        TRACE_FPU3 (ans, s1, s2);
732
      }
733
    }
734
}
735
31.Dest,26.Source2,21.0b111110010,12.0,11./,10.PD,8.P2,6.P1,4.Source1::f::fmpy r
736
"fmpy.%s%s%s r, r, r"
737
{
738
  do_fmpy (_SD, Dest, PD,
739
           get_fp_reg (_SD, Source1, vSource1, P1),
740
           get_fp_reg (_SD, Source2, vSource2, P2));
741
}
742
31.Dest,26.Source2,21.0b111110010,12.1,11./,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fmpy l
743
"fmpy.%s%s%s 0x%08lx, r, r"
744
{
745
  do_fmpy (_SD, Dest, PD,
746
           get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1),
747
           get_fp_reg (_SD, Source2, vSource2, P2));
748
}
749
 
750
// frndm.{s|d|i|u}{s|d|i|u}
751
void::function::do_frnd:int Dest, int PD, sim_fpu s1
752
{
753
  set_fp_reg (_SD, Dest, s1, PD);
754
  TRACE_FPU1 (s1);
755
}
756
31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b11,6.P1,4.Source::f::frndm r
757
"frndm.%s%s r, r"
758
{
759
  do_frnd (_SD, Dest, PD,
760
           get_fp_reg (_SD, Source, vSource, P1));
761
}
762
31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b11,6.P1,4./+SinglePrecisionFloatingPoint::f::frndm l
763
"frndm.%s%s 0x%08lx, r"
764
{
765
  do_frnd (_SD, Dest, PD,
766
           get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1));
767
}
768
 
769
// frndn.{s|d|i|u}{s|d|i|u}
770
31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b00,6.P1,4.Source::f::frndn r
771
"frndn.%s%s r, r"
772
{
773
  do_frnd (_SD, Dest, PD,
774
           get_fp_reg (_SD, Source, vSource, P1));
775
}
776
31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b00,6.P1,4./+SinglePrecisionFloatingPoint::f::frndn l
777
"frndn.%s%s 0x%08lx, r"
778
{
779
  do_frnd (_SD, Dest, PD,
780
           get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1));
781
}
782
 
783
// frndp.{s|d|i|u}{s|d|i|u}
784
31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b10,6.P1,4.Source::f::frndp r
785
"frndp.%s%s r, r"
786
{
787
  do_frnd (_SD, Dest, PD,
788
           get_fp_reg (_SD, Source, vSource, P1));
789
}
790
31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b10,6.P1,4./+SinglePrecisionFloatingPoint::f::frndp l
791
"frndp.%s%s 0x%08lx, r"
792
{
793
  do_frnd (_SD, Dest, PD,
794
           get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1));
795
}
796
 
797
// frndz.{s|d|i|u}{s|d|i|u}
798
31.Dest,26./,21.0b111110100,12.0,11.r,10.PD,8.0b01,6.P1,4.Source::f::frndz r
799
"frndz.%s%s r, r"
800
{
801
  do_frnd (_SD, Dest, PD,
802
           get_fp_reg (_SD, Source, vSource, P1));
803
}
804
31.Dest,26./,21.0b111110100,12.1,11.r,10.PD,8.0b01,6.P1,4./+SinglePrecisionFloatingPoint::f::frndz l
805
"frndz.%s%s 0x%08lx, r"
806
{
807
  do_frnd (_SD, Dest, PD,
808
           get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1));
809
}
810
 
811
// fsqrt.{s|d}{s|d}{s|d}
812
#void::function::do_fsqrt:unsigned32 *rDest, unsigned32 Source, unsigned32 Source2
813
#  sim_io_error ("fsqrt");
814
31.Dest,26./,21.0b111110111,12.0,11./,10.PD,8.//,6.P1,4.Source::f::fsqrt r
815
"fsqrt.%s%s r, r"
816
#  do_fsqrt (_SD, rDest, vSource);
817
31.Dest,26./,21.0b111110111,12.1,11./,10.PD,8.//,6.P1,4./+SinglePrecisionFloatingPoint::f::fsqrt l
818
"fsqrt.%s%s 0x%08lx, r"
819
#  do_fsqrt (_SD, rDest, SinglePrecisionFloatingPoint);
820
 
821
 
822
// fsub.{s|d}{s|d}{s|d}
823
void::function::do_fsub:int Dest, int PD, sim_fpu s1, sim_fpu s2
824
{
825
  sim_fpu ans;
826
  sim_fpu_sub (&ans, &s1, &s2);
827
  TRACE_FPU3 (ans, s1, s2);
828
  set_fp_reg (_SD, Dest, ans, PD);
829
}
830
31.Dest,26.Source2,21.0b111110001,12.0,11.r,10.PD,8.P2,6.P1,4.Source1::f::fsub r
831
"fsub.%s%s%s r, r, r"
832
{
833
  do_fsub (_SD, Dest, PD,
834
           get_fp_reg (_SD, Source1, vSource1, P1),
835
           get_fp_reg (_SD, Source2, vSource2, P2));
836
}
837
31.Dest,26.Source2,21.0b111110001,12.1,11.r,10.PD,8.P2,6.P1,4./+SinglePrecisionFloatingPoint::f::fsub l
838
"fsub.%s%s%s 0x%08lx, r, r"
839
{
840
  do_fsub (_SD, Dest, PD,
841
           get_fp_reg (_SD, -1, SinglePrecisionFloatingPoint, P1),
842
           get_fp_reg (_SD, Source2, vSource2, P2));
843
}
844
 
845
// illop
846
31./,21.0b0000000,14./::::illop
847
"illop"
848
31./,21.0b111111111,12./::::illop l
849
"illop"
850
 
851
 
852
// ins - see sl.im
853
 
854
 
855
// jsr[.a]
856
instruction_address::function::do_jsr:instruction_address nia, signed32 *rLink, int annul, unsigned32 offset, unsigned32 base
857
{
858
  address_word target = offset + base;
859
  TRACE_UCOND_BR (MY_INDEX, target);
860
  nia = do_branch (_SD, annul, target, 1, rLink);
861
  if (nia.dp & 0x3)
862
    sim_engine_abort (SD, CPU, cia,
863
                      "0x%lx: destination address 0x%lx misaligned",
864
                      (unsigned long) cia.ip,
865
                      (unsigned long) nia.dp);
866
  return nia;
867
}
868
31.Link,26.Base,21.0b100010,15.A,14.SignedOffset::::jsr i
869
"jsr%s , r"
870
{
871
  nia = do_jsr (_SD, nia, rLink, A, vSignedOffset, vBase);
872
}
873
31.Link,26.Base,21.0b11100010,13.A,12.0,11./,4.IndOff::::jsr r
874
"jsr%s r, r"
875
{
876
  nia = do_jsr (_SD, nia, rLink, A, rIndOff, vBase);
877
}
878
31.Link,26.Base,21.0b11100010,13.A,12.1,11./+LongSignedImmediate::::jsr l
879
"jsr%s , r"
880
{
881
  nia = do_jsr (_SD, nia, rLink, A, LongSignedImmediate, vBase);
882
}
883
 
884
// ld[{.b.h.d}]
885
void::function::do_ld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset
886
{
887
  unsigned32 addr;
888
  switch (sz)
889
    {
890
    case 0:
891
      addr = base + (S ? (offset << 0) : offset);
892
      if (m)
893
        *rBase = addr;
894
      GPR(Dest) = MEM (signed, addr, 1);
895
      break;
896
    case 1:
897
      addr = base + (S ? (offset << 1) : offset);
898
      if (m)
899
        *rBase = addr;
900
      GPR(Dest) = MEM (signed, addr, 2);
901
      break;
902
    case 2:
903
      addr = base + (S ? (offset << 2) : offset);
904
      if (m)
905
        *rBase = addr;
906
      GPR(Dest) = MEM (signed, addr, 4);
907
      break;
908
    case 3:
909
      {
910
        signed64 val;
911
        if (Dest & 0x1)
912
          sim_engine_abort (SD, CPU, cia, "0x%lx: ld.d to odd register %d",
913
                            cia.ip, Dest);
914
        addr = base + (S ? (offset << 3) : offset);
915
        if (m)
916
          *rBase = addr;
917
        val = MEM (signed, addr, 8);
918
        GPR(Dest + 1) = VH4_8 (val);
919
        GPR(Dest + 0) = VL4_8 (val);
920
      }
921
      break;
922
    default:
923
      addr = -1;
924
      sim_engine_abort (SD, CPU, cia, "ld - invalid sz %d", sz);
925
    }
926
  TRACE_LD (GPR(Dest), m, S, base, offset);
927
}
928
const char *::function::str_sz:int sz
929
{
930
  switch (sz)
931
    {
932
    case 0: return ".b";
933
    case 1: return ".h";
934
    case 2: return "";
935
    case 3: return ".d";
936
    default: return "?";
937
    }
938
}
939
const char *::function::str_m:int m
940
{
941
  if (m)
942
    return ":m";
943
  else
944
    return "";
945
}
946
const char *::function::str_S:int S
947
{
948
  if (S)
949
    return ":s";
950
  else
951
    return "";
952
}
953
31.Dest,26.Base,21.0b0100,17.m,16.sz,14.SignedOffset::::ld i
954
"ld%s  (r%s), r"
955
{
956
  do_ld (_SD, Dest, vBase, rBase, m, sz, 0, vSignedOffset);
957
}
958
31.Dest,26.Base,21.0b110100,15.m,14.sz,12.0,11.S,10.0,9./,4.IndOff::::ld r
959
"ld%s r%s (r%s), r"
960
{
961
  do_ld (_SD, Dest, vBase, rBase, m, sz, S, rIndOff);
962
}
963
31.Dest,26.Base,21.0b110100,15.m,14.sz,12.1,11.S,10.0,9./+LongSignedImmediateOffset::::ld l
964
"ld%s 0x%08lx%s (r%s), r"
965
{
966
  do_ld (_SD, Dest, vBase, rBase, m, sz, S, LongSignedImmediateOffset);
967
}
968
 
969
// ld.u[{.b.h.d}]
970
void::function::do_ld_u:unsigned32 *rDest, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset
971
{
972
  unsigned32 addr;
973
  switch (sz)
974
    {
975
    case 0:
976
      addr = base + (S ? (offset << 0) : offset);
977
      *rDest = MEM (unsigned, addr, 1);
978
      break;
979
    case 1:
980
      addr = base + (S ? (offset << 1) : offset);
981
      *rDest = MEM (unsigned, addr, 2);
982
      break;
983
    default:
984
      addr = -1;
985
      sim_engine_abort (SD, CPU, cia, "ld.u - invalid sz %d", sz);
986
    }
987
  if (m)
988
    *rBase = addr;
989
  TRACE_LD (m, S, *rDest, base, offset);
990
}
991
31.Dest,26.Base,21.0b0101,17.m,16.sz,14.SignedOffset::::ld.u i
992
"ld.u%s  (r%s), r"
993
{
994
  do_ld_u (_SD, rDest, vBase, rBase, m, sz, 0, vSignedOffset);
995
}
996
31.Dest,26.Base,21.0b110101,15.m,14.sz,12.0,11.S,10.0,9./,4.IndOff::::ld.u r
997
"ld.u%s r%s (r%s), r"
998
{
999
  do_ld_u (_SD, rDest, vBase, rBase, m, sz, S, rIndOff);
1000
}
1001
31.Dest,26.Base,21.0b110101,15.m,14.sz,12.1,11.S,10.0,9./+LongSignedImmediateOffset::::ld.u l
1002
"ld.u%s 0x%08lx%s (r%s), r"
1003
{
1004
  do_ld_u (_SD, rDest, vBase, rBase, m, sz, S, LongSignedImmediateOffset);
1005
}
1006
 
1007
// lmo
1008
31.Dest,26.Source,21.0b111111000,12.0,11./::::lmo
1009
"lmo r, r"
1010
{
1011
  int b;
1012
  for (b = 0; b < 32; b++)
1013
    if (vSource & BIT32 (31 - b))
1014
      break;
1015
  TRACE_ALU2 (MY_INDEX, b, vSource);
1016
  *rDest = b;
1017
}
1018
 
1019
 
1020
// nop - see rdcr 0, r0
1021
 
1022
 
1023
void::function::do_or:unsigned32 *rDest, unsigned32 Source1, unsigned32 Source2
1024
{
1025
  unsigned32 result = Source1 | Source2;
1026
  TRACE_ALU3 (MY_INDEX, result, Source1, Source2);
1027
  *rDest = result;
1028
}
1029
 
1030
// or, or.tt
1031
31.Dest,26.Source2,21.0b0010111,14.UnsignedImmediate::::or.tt i
1032
"or.tt , r, r"
1033
{
1034
  do_or (_SD, rDest, vSource1, vSource2);
1035
}
1036
31.Dest,26.Source2,21.0b110010111,12.0,11./,4.Source1::::or.tt r
1037
"or.tt r, r, r"
1038
{
1039
  do_or (_SD, rDest, vSource1, vSource2);
1040
}
1041
31.Dest,26.Source2,21.0b110010111,12.1,11./+LongUnsignedImmediate::::or.tt l
1042
"or.tt 0x%08lx, r, r"
1043
{
1044
  do_or (_SD, rDest, LongUnsignedImmediate, vSource2);
1045
}
1046
 
1047
// or.ff
1048
31.Dest,26.Source2,21.0b0011110,14.UnsignedImmediate::::or.ff i
1049
"or.ff , r, r"
1050
{
1051
  do_or (_SD, rDest, ~vSource1, ~vSource2);
1052
}
1053
31.Dest,26.Source2,21.0b110011110,12.0,11./,4.Source1::::or.ff r
1054
"or.ff r, r, r"
1055
{
1056
  do_or (_SD, rDest, ~vSource1, ~vSource2);
1057
}
1058
31.Dest,26.Source2,21.0b110011110,12.1,11./+LongUnsignedImmediate::::or.ff l
1059
"or.ff 0x%08lx, r, r"
1060
{
1061
  do_or (_SD, rDest, ~LongUnsignedImmediate, ~vSource2);
1062
}
1063
 
1064
// or.ft
1065
31.Dest,26.Source2,21.0b0011101,14.UnsignedImmediate::::or.ft i
1066
"or.ft , r, r"
1067
{
1068
  do_or (_SD, rDest, ~vSource1, vSource2);
1069
}
1070
31.Dest,26.Source2,21.0b110011101,12.0,11./,4.Source1::::or.ft r
1071
"or.ft r, r, r"
1072
{
1073
  do_or (_SD, rDest, ~vSource1, vSource2);
1074
}
1075
31.Dest,26.Source2,21.0b110011101,12.1,11./+LongUnsignedImmediate::::or.ft l
1076
"or.ft 0x%08lx, r, r"
1077
{
1078
  do_or (_SD, rDest, ~LongUnsignedImmediate, vSource2);
1079
}
1080
 
1081
// or.tf
1082
31.Dest,26.Source2,21.0b0011011,14.UnsignedImmediate::::or.tf i
1083
"or.tf , r, r"
1084
{
1085
  do_or (_SD, rDest, vSource1, ~vSource2);
1086
}
1087
31.Dest,26.Source2,21.0b110011011,12.0,11./,4.Source1::::or.tf r
1088
"or.tf r, r, r"
1089
{
1090
  do_or (_SD, rDest, vSource1, ~vSource2);
1091
}
1092
31.Dest,26.Source2,21.0b110011011,12.1,11./+LongUnsignedImmediate::::or.tf l
1093
"or.tf 0x%08lx, r, r"
1094
{
1095
  do_or (_SD, rDest, LongUnsignedImmediate, ~vSource2);
1096
}
1097
 
1098
// rdcr
1099
void::function::do_rdcr:unsigned32 Dest, int cr
1100
{
1101
  TRACE_SINK2 (MY_INDEX, Dest, cr);
1102
  GPR (Dest) = CR (cr);
1103
}
1104
31.Dest,26.0,21.0b0000100,14.UCRN::::rdcr i
1105
"rdcr CR[], r"
1106
{
1107
  do_rdcr (_SD, Dest, UCRN);
1108
}
1109
31.Dest,26.0,21.0b110000100,12.0,11./,4.INDCR::::rdcr r
1110
"rdcr CR[r], r"
1111
{
1112
  do_rdcr (_SD, Dest, UCRN);
1113
}
1114
31.Dest,26.0,21.0b110000100,12.1,11./+UnsignedControlRegisterNumber::::rdcr l
1115
"rdcr CR[], r"
1116
{
1117
  do_rdcr (_SD, Dest, UnsignedControlRegisterNumber);
1118
}
1119
 
1120
// rmo
1121
31.Dest,26.Source,21.0b111111001,12.0,11./::::rmo
1122
"rmo r, r"
1123
{
1124
  int b;
1125
  for (b = 0; b < 32; b++)
1126
    if (vSource & BIT32 (b))
1127
      break;
1128
  if (b < 32)
1129
    b = 31 - b;
1130
  TRACE_ALU2 (MY_INDEX, b, vSource);
1131
  *rDest = b;
1132
}
1133
 
1134
// rotl - see sl.dz
1135
 
1136
 
1137
// rotr - see sl.dz
1138
 
1139
 
1140
// shl - see sl.iz
1141
 
1142
 
1143
// sl.{d|e|i}{m|s|z}
1144
void::function::do_shift:int Dest, unsigned32 source, int Merge, int i, int n, int EndMask, int Rotate
1145
{
1146
  /* see 10-30 for a reasonable description */
1147
  unsigned32 input = source;
1148
  unsigned32 rotated;
1149
  unsigned32 endmask;
1150
  unsigned32 shiftmask;
1151
  unsigned32 cm;
1152
  int nRotate;
1153
  /* rotate the source */
1154
  if (n)
1155
    {
1156
      rotated = ROTR32 (source, Rotate);
1157
      nRotate = (- Rotate) & 31;
1158
    }
1159
  else
1160
    {
1161
      rotated = ROTL32 (source, Rotate);
1162
      nRotate = Rotate;
1163
    }
1164
  /* form the end mask */
1165
  if (EndMask == 0)
1166
    endmask = ~ (unsigned32)0;
1167
  else
1168
    endmask = (1 << EndMask) - 1;
1169
  if (i)
1170
    endmask = ~endmask;
1171
  /* form the shiftmask */
1172
  switch (Merge)
1173
    {
1174
    case 0: case 1: case 2:
1175
      shiftmask = ~ (unsigned32)0;  /* disabled */
1176
      break;
1177
    case 3: case 5:      /* enabled - 0 -> 32 */
1178
      if (nRotate == 0)
1179
        shiftmask = ~ (unsigned32)0;
1180
      else
1181
        shiftmask = ((1 << nRotate) - 1);  /* enabled - 0 -> 0 */
1182
      break;
1183
    case 4:
1184
      shiftmask = ((1 << nRotate) - 1);  /* enabled - 0 -> 0 */
1185
      break;
1186
    case 6: case 7:
1187
      shiftmask = ~((1 << nRotate) - 1);  /* inverted */
1188
      break;
1189
    default:
1190
      sim_engine_abort (SD, CPU, cia,
1191
                        "0x%lx: Invalid merge (%d) for shift",
1192
                        (long) cia.ip, (int) source);
1193
      shiftmask = 0;
1194
    }
1195
  /* and the composite mask */
1196
  cm = shiftmask & endmask;
1197
  /* and merge */
1198
  switch (Merge)
1199
    {
1200
    case 0: case 3: case 6:    /* zero */
1201
      GPR (Dest) = rotated & cm;
1202
      break;
1203
    case 1: case 4: case 7:    /* merge */
1204
      GPR (Dest) = (rotated & cm) | (GPR (Dest) & ~cm);
1205
      break;
1206
    case 2: case 5:      /* sign */
1207
      {
1208
        int b;
1209
        GPR (Dest) = rotated & cm;
1210
        for (b = 1; b <= 31; b++)
1211
          if (!MASKED32 (cm, b, b))
1212
            GPR (Dest) |= INSERTED32 (EXTRACTED32 (GPR (Dest), b - 1, b - 1),
1213
                                      b, b);
1214
      }
1215
      break;
1216
    default:
1217
      sim_engine_abort (SD, CPU, cia,
1218
                        "0x%lx: Invalid merge (%d)",
1219
                        (long) cia.ip, (int) source);
1220
    }
1221
  TRACE_SHIFT (MY_INDEX, GPR (Dest), input, i, n, Merge, EndMask, Rotate);
1222
}
1223
const char *::function::str_Merge:int Merge
1224
{
1225
  switch (Merge)
1226
    {
1227
    case 0: return "dz";
1228
    case 1: return "dm";
1229
    case 2: return "ds";
1230
    case 3: return "ez";
1231
    case 4: return "em";
1232
    case 5: return "es";
1233
    case 6: return "iz";
1234
    case 7: return "im";
1235
    default: return "?";
1236
    }
1237
}
1238
31.Dest,26.Source,21.0b0001,17.Merge,14./,11.i,10.n,9.EndMask,4.Rotate::::sl i
1239
"sl.%s , , r, r"
1240
{
1241
  do_shift (_SD, Dest, vSource, Merge, i, n, EndMask, Rotate);
1242
}
1243
31.Dest,26.Source,21.0b110001,15.Merge,12.0,11.i,10.n,9.EndMask,4.RotReg::::sl r
1244
"sl.%s r, , r, r"
1245
{
1246
  do_shift (_SD, Dest, vSource, Merge, i, n, EndMask, GPR (RotReg) & 31);
1247
}
1248
 
1249
// sli.{d|e|i}{m|s|z} - see shift
1250
 
1251
 
1252
// sr.{d|e|i}{m|s|z} - see shift
1253
 
1254
 
1255
// sra - see sr.es - see shift
1256
 
1257
 
1258
// sri.{d|e|i}{m|s|z} - see shift
1259
 
1260
 
1261
// srl - see sr.ez
1262
 
1263
 
1264
// st[{.b|.h|.d}]
1265
void::function::do_st:int Source, unsigned32 base, unsigned32 *rBase, int m , int sz, int S, unsigned32 offset
1266
{
1267
  unsigned32 addr;
1268
  switch (sz)
1269
    {
1270
    case 0:
1271
      addr = base + (S ? (offset << 0) : offset);
1272
      STORE (addr, 1, GPR(Source));
1273
      break;
1274
    case 1:
1275
      addr = base + (S ? (offset << 1) : offset);
1276
      STORE (addr, 2, GPR(Source));
1277
      break;
1278
    case 2:
1279
      addr = base + (S ? (offset << 2) : offset);
1280
      STORE (addr, 4, GPR(Source));
1281
      break;
1282
    case 3:
1283
      {
1284
        signed64 val;
1285
        if (Source & 0x1)
1286
          sim_engine_abort (SD, CPU, cia,
1287
                            "0x%lx: st.d with odd source register %d",
1288
                            cia.ip, Source);
1289
        addr = base + (S ? (offset << 3) : offset);
1290
        val = U8_4 (GPR(Source + 1), GPR(Source));
1291
        STORE (addr, 8, val);
1292
      }
1293
      break;
1294
    default:
1295
      addr = -1;
1296
      sim_engine_abort (SD, CPU, cia, "st - invalid sz %d", sz);
1297
    }
1298
  if (m)
1299
    *rBase = addr;
1300
  TRACE_ST (Source, m, S, base, offset);
1301
}
1302
31.Source,26.Base,21.0b0110,17.m,16.sz,14.SignedOffset::::st i
1303
"st%s  (r%s), r"
1304
{
1305
  do_st (_SD, Source, vBase, rBase, m, sz, 0, vSignedOffset);
1306
}
1307
31.Source,26.Base,21.0b110110,15.m,14.sz,12.0,11.S,10.0,9./,4.IndOff::::st r
1308
"st%s r%s (r%s), r"
1309
{
1310
  do_st (_SD, Source, vBase, rBase, m, sz, S, rIndOff);
1311
}
1312
31.Source,26.Base,21.0b110110,15.m,14.sz,12.1,11.S,10.0,9./+LongSignedImmediateOffset::::st l
1313
"st%s 0x%08lx%s (r%s), r"
1314
{
1315
  do_st (_SD, Source, vBase, rBase, m, sz, S, LongSignedImmediateOffset);
1316
}
1317
 
1318
// sub
1319
void::function::do_sub:signed32 *rDest, signed32 Source1, signed32 Source2
1320
{
1321
  ALU_BEGIN (Source1);
1322
  ALU_SUB (Source2);
1323
  ALU_END (*rDest);
1324
  TRACE_ALU3 (MY_INDEX, *rDest, Source1, Source2);
1325
}
1326
31.Dest,26.Source2,21.0b101101,15.0,14.SignedImmediate::::sub i
1327
"sub , r, r"
1328
{
1329
  do_sub (_SD, rDest, vSource1, vSource2);
1330
}
1331
31.Dest,26.Source2,21.0b11101101,13.0,12.0,11./,4.Source1::::sub r
1332
"sub r, r, r"
1333
{
1334
  do_sub (_SD, rDest, vSource1, vSource2);
1335
}
1336
31.Dest,26.Source2,21.0b11101101,13.0,12.1,11./+LongSignedImmediate::::sub l
1337
"sub 0x%08lx, r, r"
1338
{
1339
  do_sub (_SD, rDest, LongSignedImmediate, vSource2);
1340
}
1341
 
1342
// subu
1343
void::function::do_subu:unsigned32 *rDest, unsigned32 Source1, signed32 Source2
1344
{
1345
  unsigned32 result = Source1 - Source2;
1346
  TRACE_ALU3 (MY_INDEX, result, Source1, Source2);
1347
  *rDest = result;
1348
}
1349
// NOTE - the book has 15.1 which conflicts with subu.
1350
31.Dest,26.Source2,21.0b101101,15.1,14.SignedImmediate::::subu i
1351
"subu , r, r"
1352
{
1353
  do_subu (_SD, rDest, vSource1, vSource2);
1354
}
1355
31.Dest,26.Source2,21.0b11101101,13.1,12.0,11./,4.Source1::::subu r
1356
"subu r, r, r"
1357
{
1358
  do_subu (_SD, rDest, vSource1, vSource2);
1359
}
1360
31.Dest,26.Source2,21.0b11101101,13.1,12.1,11./+LongSignedImmediate::::subu l
1361
"subu 0x%08lx, r, r"
1362
{
1363
  do_subu (_SD, rDest, LongSignedImmediate, vSource2);
1364
}
1365
 
1366
// swcr
1367
void::function::do_swcr:int Dest, signed32 source, signed32 cr
1368
{
1369
  tic80_control_regs reg = tic80_index2cr (cr);
1370
  /* cache the old CR value */
1371
  unsigned32 old_cr = CR (cr);
1372
  /* Handle the write if allowed */
1373
  if (cr >= 0x4000 || !(CPU)->is_user_mode)
1374
    switch (reg)
1375
      {
1376
      case INTPEN_CR:
1377
        CR (cr) &= ~source;
1378
        break;
1379
      default:
1380
        CR (cr) = source;
1381
        break;
1382
      }
1383
  /* Finish off the read */
1384
  GPR (Dest) = old_cr;
1385
  TRACE_SINK3 (MY_INDEX, source, cr, Dest);
1386
}
1387
31.Dest,26.Source,21.0b000010,15.1,14.UCRN::::swcr i
1388
"swcr CR[], r"
1389
{
1390
  do_swcr (_SD, Dest, vSource, UCRN);
1391
}
1392
31.Dest,26.Source,21.0b11000010,13.1,12.0,11./,4.INDCR::::swcr r
1393
"swcr CR[r], r"
1394
{
1395
  do_swcr (_SD, Dest, vSource, UCRN);
1396
}
1397
31.Dest,26.Source,21.0b11000010,13.1,12.1,11./+LongUnsignedControlRegisterNumber::::swcr l
1398
"swcr CR[], r"
1399
{
1400
  do_swcr (_SD, Dest, vSource, LongUnsignedControlRegisterNumber);
1401
}
1402
 
1403
// trap
1404
void::function::do_trap:unsigned32 trap_number
1405
{
1406
  int i;
1407
  TRACE_SINK1 (MY_INDEX, trap_number);
1408
  switch (trap_number)
1409
    {
1410
    case 72:
1411
      switch (GPR(15))
1412
        {
1413
        case 1: /* EXIT */
1414
          {
1415
            sim_engine_halt (SD, CPU, NULL, cia, sim_exited, GPR(2));
1416
            break;
1417
          }
1418
        case 4: /* WRITE */
1419
          {
1420
            unsigned i;
1421
            if (GPR(2) == 1)
1422
        for (i = 0; i < GPR(6); i++)
1423
                {
1424
            char c;
1425
            c = MEM (unsigned, GPR(4) + i, 1);
1426
                  sim_io_write_stdout (SD, &c, 1);
1427
                }
1428
            else if (GPR(2) == 2)
1429
        for (i = 0; i < GPR(6); i++)
1430
                {
1431
            char c;
1432
            c = MEM (unsigned, GPR(4) + i, 1);
1433
                  sim_io_write_stderr (SD, &c, 1);
1434
                }
1435
            else
1436
              sim_engine_abort (SD, CPU, cia,
1437
                                "0x%lx: write to invalid fid %d",
1438
                                (long) cia.ip, (int) GPR(2));
1439
            GPR(2) = GPR(6);
1440
            break;
1441
          }
1442
        case 20: /* GETPID */
1443
    {
1444
      GPR(2) = getpid ();
1445
      break;
1446
    }
1447
        case 37: /* KILL */
1448
    if ( GPR (2) != (unsigned) getpid ())
1449
      {
1450
        int ret = kill (GPR(2), GPR(4));
1451
        if (ret < 0)
1452
          ret = -errno;
1453
        GPR (2) = ret;
1454
        break;
1455
      }
1456
    else
1457
      {
1458
        sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, GPR(4));
1459
        break;
1460
      }
1461
        default:
1462
    /* For system calls which are defined, just return EINVAL instead of trapping */
1463
    if (GPR(15) <= 204)
1464
      {
1465
        GPR(2) = -22;    /* -EINVAL */
1466
        break;
1467
      }
1468
          sim_engine_abort (SD, CPU, cia,
1469
                            "0x%lx: unknown syscall %d",
1470
                            (long) cia.ip, (int) GPR(15));
1471
        }
1472
      break;
1473
    case 73:
1474
      sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGTRAP);
1475
 
1476
    /* Add a few traps for now to print the register state */
1477
    case 74:
1478
    case 75:
1479
    case 76:
1480
    case 77:
1481
    case 78:
1482
    case 79:
1483
      if (!TRACE_ALU_P (CPU))
1484
        trace_one_insn (SD, CPU, cia.ip, 1, itable[MY_INDEX].file,
1485
            itable[MY_INDEX].line_nr, "trap",
1486
            "Trap %ld", (long) trap_number);
1487
 
1488
      for (i = 0; i < 32; i++)
1489
        sim_io_eprintf (SD, "%s0x%.8lx%s", ((i % 8) == 0) ? "\t" : " ", (long)GPR(i),
1490
            (((i+1) % 8) == 0) ? "\n" : "");
1491
      sim_io_write_stderr (SD, "\n", 1);
1492
      break;
1493
 
1494
    default:
1495
      sim_engine_abort (SD, CPU, cia,
1496
                        "0x%lx: unsupported trap %d",
1497
                        (long) cia.ip, (int) trap_number);
1498
    }
1499
}
1500
31./,27.0,26./,21.0b0000001,14.UTN::::trap i
1501
"trap "
1502
{
1503
  do_trap (_SD, UTN);
1504
}
1505
31./,27.0,26./,21.0b110000001,12.0,11./,4.INDTR::::trap r
1506
"trap r"
1507
{
1508
  do_trap (_SD, UTN);
1509
}
1510
31./,27.0,26./,21.0b110000001,12.1,11./+UTN::::trap l
1511
"trap 0x%08lx"
1512
{
1513
  do_trap (_SD, UTN);
1514
}
1515
 
1516
// vadd.{s|d}{s|d}
1517
31.*,26.Dest,21.0b11110,16./,15.0b000,12.0,11./,10.*,9.*,7.PD,6.*,5.P1,4.Source::f::vadd r
1518
31.*,26.Dest,21.0b11110,16./,15.0b000,12.1,11./,10.*,9.*,7.PD,6.*,5.P1,4.Source::f::vadd l
1519
 
1520
 
1521
// vld{0|1}.{s|d} - see above - same instruction
1522
#31.Dest,26.*,21.0b11110,16.*,10.1,9.S,8.*,6.p,7.******::f::vld
1523
 
1524
 
1525
// vmac.ss{s|d}
1526
#31.*,   26.Source2,21.0b11110,16.a0,15.0b110,12.0,11.a1,10.*,9.*, 8.Z,7./,6.*,5./,4.Source1::f::vmac.ss ra
1527
31.Dest,26.Source2,21.0b11110,16.a0,15.0b110,12.0,11.a1,10.0,9.PD,8.Z,7./,6.0,5./,4.Source1::f::vmac.ss rr
1528
#31.*,   26.Source2,21.0b11110,16.a0,15.0b110,12.1,11.a1,10.*,9.*, 8.Z,7./,6.*,5./,4./::f::vmac.ss ia
1529
31.Dest,26.Source2,21.0b11110,16.a0,15.0b110,12.1,11.a1,10.0,9.PD,8.Z,7./,6.0,5./,4./::f::vmac.ss ir
1530
 
1531
 
1532
// vmpy.{s|d}{s|d}
1533
31.*,26.Dest,21.0b11110,16./,15.0b010,12.0,11./,10.*,8.*,7.PD,6.*,5.P1,4.Source::f::vmpy r
1534
31.*,26.Dest,21.0b11110,16./,15.0b010,12.1,11./,10.*,8.*,7.PD,6.*,5.P1,4./::f::vmpy l
1535
 
1536
 
1537
// vmsc.ss{s|d}
1538
#31.*,   26.Source2,21.0b11110,16.a0,15.0b111,12.0,11.a1,10.*,9.*, 8.Z,7./,6.*,5./,4.Source1::f::vmsc.ss ra
1539
31.Dest,26.Source2,21.0b11110,16.a0,15.0b111,12.0,11.a1,10.0,9.PD,8.Z,7./,6.0,5./,4.Source1::f::vmsc.ss rr
1540
#31.*,   26.Source2,21.0b11110,16.a0,15.0b111,12.1,11.a1,10.*,9.*, 8.Z,7./,6.*,5./,4./::f::vmsc.ss ia
1541
31.Dest,26.Source2,21.0b11110,16.a0,15.0b111,12.1,11.a1,10.0,9.PD,8.Z,7./,6.0,5./,4./::f::vmsc.ss ir
1542
 
1543
 
1544
// vmsub.{s|d}{s|d}
1545
31.*,26.Dest,21.0b11110,16.a0,15.0b011,12.0,11.a1,10.*,8.Z,7.PD,6.*,5./,4.Source::f::vmsub r
1546
31.*,26.Dest,21.0b11110,16.a0,15.0b011,12.1,11.a1,10.*,8.Z,7.PD,6.*,5./,4./::f::vmsub l
1547
 
1548
 
1549
// vrnd.{s|d}{s|d}
1550
31.*,26.Dest,21.0b11110,16.a0,15.0b100,12.0,11.a1,10.*,8.PD,6.*,5.P1,4.Source::f::vrnd f r
1551
31.*,26.Dest,21.0b11110,16.a0,15.0b100,12.1,11.a1,10.*,8.PD,6.*,5.P1,4./::f::vrnd f l
1552
 
1553
 
1554
// vrnd.{i|u}{s|d}
1555
31.*,26.Dest,21.0b11110,16./,15.0b101,12.0,11./,10.*,8./,7.PD,6.*,5.P1,4.Source::f::vrnd i r
1556
31.*,26.Dest,21.0b11110,16./,15.0b101,12.1,11./,10.*,8./,7.PD,6.*,5.P1,4./::f::vrnd i l
1557
 
1558
 
1559
// vst.{s|d} - see above - same instruction
1560
#31.Source,26.*,21.0b11110,16.*,10.0,9.S,8.*,6.1,5.*::f::vst
1561
 
1562
 
1563
// vsub.{i|u}{s|d}
1564
31.*,26.Dest,21.0b11110,16./,15.0b001,12.0,11./,10.*,8./,7.PD,6.*,5.P1,4.Source::f::vsub r
1565
31.*,26.Dest,21.0b11110,16./,15.0b001,12.1,11./,10.*,8./,7.PD,6.*,5.P1,4./::f::vsub l
1566
 
1567
 
1568
// wrcr - see swcr, creg, source, r0
1569
 
1570
 
1571
// xnor
1572
void::function::do_xnor:signed32 *rDest, signed32 source1, signed32 source2
1573
{
1574
  unsigned32 result = ~ (source1 ^ source2);
1575
  TRACE_ALU3 (MY_INDEX, result, source1, source2);
1576
  *rDest = result;
1577
}
1578
31.Dest,26.Source2,21.0b0011001,14.UnsignedImmediate::::xnor i
1579
"xnor , r, r"
1580
{
1581
  do_xnor (_SD, rDest, vSource1, vSource2);
1582
}
1583
31.Dest,26.Source2,21.0b110011001,12.0,11./,4.Source1::::xnor r
1584
"xnor r, r, r"
1585
{
1586
  do_xnor (_SD, rDest, vSource1, vSource2);
1587
}
1588
31.Dest,26.Source2,21.0b110011001,12.1,11./+LongUnsignedImmediate::::xnor l
1589
"xnor 0x%08lx, r, r"
1590
{
1591
  do_xnor (_SD, rDest, LongUnsignedImmediate, vSource2);
1592
}
1593
 
1594
// xor
1595
void::function::do_xor:signed32 *rDest, signed32 source1, signed32 source2
1596
{
1597
  unsigned32 result = source1 ^ source2;
1598
  TRACE_ALU3 (MY_INDEX, result, source1, source2);
1599
  *rDest = result;
1600
}
1601
31.Dest,26.Source2,21.0b0010110,14.UnsignedImmediate::::xor i
1602
"xor , r, r"
1603
{
1604
  do_xor (_SD, rDest, vSource1, vSource2);
1605
}
1606
31.Dest,26.Source2,21.0b110010110,12.0,11./,4.Source1::::xor r
1607
"xor r, r, r"
1608
{
1609
  do_xor (_SD, rDest, vSource1, vSource2);
1610
}
1611
31.Dest,26.Source2,21.0b110010110,12.1,11./+LongUnsignedImmediate::::xor l
1612
"xor 0x%08lx, r, r"
1613
{
1614
  do_xor (_SD, rDest, LongUnsignedImmediate, vSource2);
1615
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.