aboutsummaryrefslogtreecommitdiff
path: root/sim/tic80/misc.c
blob: beb0c68d9f0d12a99d87edc09bf1846be69bbfb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
/* TIc80 Simulator.
   Copyright (C) 1997 Free Software Foundation, Inc.
   Contributed by Cygnus Support.

This file is part of GDB, the GNU debugger.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */


#include "sim-main.h"

#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif


tic80_control_regs
tic80_index2cr (int index)
{
  switch (index)
    {
    case 0x0000: return EPC_CR;
    case 0x0001: return EIP_CR;
    case 0x0002: return CONFIG_CR;
    case 0x0004: return INTPEN_CR;
    case 0x0006: return IE_CR;
    case 0x0008: return FPST_CR;
    case 0x000A: return PPERROR_CR;
    case 0x000D: return PKTREQ_CR;
    case 0x000E: return TCOUNT_CR;
    case 0x000F: return TSCALE_CR;
    case 0x0010: return FLTOP_CR;
    case 0x0011: return FLTADR_CR;
    case 0x0012: return FLTTAG_CR;
    case 0x0013: return FLTDLT_CR;
    case 0x0014: return FLTDTH_CR;
    case 0x0015: return FLT005_CR;
    case 0x0016: return FLT006_CR;
    case 0x0017: return FLT007_CR;
    case 0x0018: return FLT008_CR;
    case 0x0019: return FLT009_CR;
    case 0x001a: return FLT010_CR;
    case 0x001b: return FLT011_CR;
    case 0x001c: return FLT012_CR;
    case 0x001d: return FLT013_CR;
    case 0x001e: return FLT014_CR;
    case 0x001f: return FLT015_CR;
    case 0x0020: return SYSSTK_CR;
    case 0x0021: return SYSTMP_CR;
    case 0x0030: return MPC_CR;
    case 0x0031: return MIP_CR;
    case 0x0033: return ECOMCNTL_CR;
    case 0x0034: return ANASTAT_CR;
    case 0x0039: return BRK1_CR;
    case 0x003A: return BRK2_CR;
    case 0x0200: return ITAG0_CR;
    case 0x0201: return ITAG1_CR;
    case 0x0202: return ITAG2_CR;
    case 0x0203: return ITAG3_CR;
    case 0x0204: return ITAG4_CR;
    case 0x0205: return ITAG5_CR;
    case 0x0206: return ITAG6_CR;
    case 0x0207: return ITAG7_CR;
    case 0x0208: return ITAG8_CR;
    case 0x0209: return ITAG9_CR;
    case 0x020a: return ITAG10_CR;
    case 0x020b: return ITAG11_CR;
    case 0x020c: return ITAG12_CR;
    case 0x020d: return ITAG13_CR;
    case 0x020e: return ITAG14_CR;
    case 0x020f: return ITAG15_CR;
    case 0x0300: return ILRU_CR;
    case 0x0400: return DTAG0_CR;
    case 0x0401: return DTAG1_CR;
    case 0x0402: return DTAG2_CR;
    case 0x0403: return DTAG3_CR;
    case 0x0404: return DTAG4_CR;
    case 0x0405: return DTAG5_CR;
    case 0x0406: return DTAG6_CR;
    case 0x0407: return DTAG7_CR;
    case 0x0408: return DTAG8_CR;
    case 0x0409: return DTAG9_CR;
    case 0x040a: return DTAG10_CR;
    case 0x040b: return DTAG11_CR;
    case 0x040c: return DTAG12_CR;
    case 0x040d: return DTAG13_CR;
    case 0x040e: return DTAG14_CR;
    case 0x040f: return DTAG15_CR;
    case 0x0500: return DLRU_CR;
    case 0x4000: return IN0P_CR;
    case 0x4001: return IN1P_CR;
    case 0x4002: return OUTP_CR;
    default: return SCRATCH_CR;
    }
}



#if defined(WITH_TRACE)
/* Tracing support routines */

static char tic80_trace_buffer[1024];
static int  tic80_size_name;

#define SIZE_HEX	8
#define SIZE_DECIMAL	11

/* Initialize tracing by calculating the maximum name size */
static void
tic80_init_trace (void)
{
  int i;
  int len, max_len = 0;

  for (i = 0; i < (int)nr_itable_entries; i++) {
    len = strlen (itable[i].name);
    if (len > max_len)
      max_len = len;
  }

  tic80_size_name = max_len + sizeof(":m") - 1 + sizeof (":s") - 1;
}

/* Trace the result of an ALU operation with 2 integer inputs and an integer output */
char *
tic80_trace_alu3 (int indx,
		  unsigned32 result,
		  unsigned32 input1,
		  unsigned32 input2)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld => 0x%.*lx/%*ld",
	   tic80_size_name, itable[indx].name,
	   SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1,
	   SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2,
	   SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);

  return tic80_trace_buffer;
}

/* Trace the result of an ALU operation with 1 integer input and an integer output */
char *
tic80_trace_alu2 (int indx,
		  unsigned32 result,
		  unsigned32 input)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld %*s => 0x%.*lx/%*ld",
	   tic80_size_name, itable[indx].name,
	   SIZE_HEX, input, SIZE_DECIMAL, (long)(signed32)input,
	   SIZE_HEX + SIZE_DECIMAL + 3, "",
	   SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);

  return tic80_trace_buffer;
}

/* Trace the result of a shift instruction */
char *
tic80_trace_shift (int indx,
		   unsigned32 result,
		   unsigned32 input,
		   int i,
		   int n,
		   int merge,
		   int endmask,
		   int rotate)
{
  const char *merge_name;
  char name[40];
  char *p;

  if (!tic80_size_name)
    tic80_init_trace ();

  switch (merge)
    {
    default:	merge_name = ".??"; break;
    case 0:	merge_name = ".dz"; break;
    case 1:	merge_name = ".dm"; break;
    case 2:	merge_name = ".ds"; break;
    case 3:	merge_name = ".ez"; break;
    case 4:	merge_name = ".em"; break;
    case 5:	merge_name = ".es"; break;
    case 6:	merge_name = ".iz"; break;
    case 7:	merge_name = ".im"; break;
    }

  /* Don't use itable[indx].name, which is just sl {r,i}.  Instead reconstruct
     the name, using the i and n fields.  */
  p = strchr (itable[indx].name, ' ');
  sprintf (name, "s%s%s%s%s",
	   (n) ? "r" : "l",
	   (i) ? "i" : "",
	   merge_name,
	   (p) ? p : "");

  sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld %*s%2d,%2d => 0x%.*lx/%*ld",
	   tic80_size_name, name,
	   SIZE_HEX, input, SIZE_DECIMAL, (long)(signed32)input,
	   SIZE_HEX + SIZE_DECIMAL - 2, "",
	   rotate, endmask,
	   SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);

  return tic80_trace_buffer;
}    

/* Trace the result of an FPU operation with 2 floating point inputs and a floating point output */
void
tic80_trace_fpu3 (SIM_DESC sd,
		  sim_cpu *cpu,
		  sim_cia cia,
		  int indx,
		  sim_fpu result,
		  sim_fpu input1,
		  sim_fpu input2)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  trace_one_insn (sd, cpu, cia.ip, 1,
		  itable[indx].file, itable[indx].line_nr, "fpu",
		  "%-*s %*g %*g => %*g",
		  tic80_size_name, itable[indx].name,
		  SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input1),
		  SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input2),
		  SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&result));
}

/* Trace the result of an FPU operation with 1 floating point input and a floating point output */
void
tic80_trace_fpu2 (SIM_DESC sd,
		  sim_cpu *cpu,
		  sim_cia cia,
		  int indx,
		  sim_fpu result,
		  sim_fpu input)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  trace_one_insn (sd, cpu, cia.ip, 1,
		  itable[indx].file, itable[indx].line_nr, "fpu",
		  "%-*s %*g %-*s => %*g",
		  tic80_size_name, itable[indx].name,
		  SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input),
		  SIZE_HEX + SIZE_DECIMAL + 3, "",
		  SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (&result));
}

/* Trace the result of an FPU operation with 1 floating point input and a floating point output */
void
tic80_trace_fpu1 (SIM_DESC sd,
		  sim_cpu *cpu,
		  sim_cia cia,
		  int indx,
		  sim_fpu result)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  trace_one_insn (sd, cpu, cia.ip, 1,
		  itable[indx].file, itable[indx].line_nr, "fpu",
		  "%-*s %-*s %-*s => %*g",
		  tic80_size_name, itable[indx].name,
		  SIZE_HEX + SIZE_DECIMAL + 3, "",
		  SIZE_HEX + SIZE_DECIMAL + 3, "",
		  SIZE_HEX + SIZE_DECIMAL, sim_fpu_2d (&result));
}

/* Trace the result of an FPU operation with 1 integer input and an integer output */
void
tic80_trace_fpu2i (SIM_DESC sd,
		   sim_cpu *cpu,
		   sim_cia cia,
		   int indx,
		   unsigned32 result,
		   sim_fpu input1,
		   sim_fpu input2)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  trace_one_insn (sd, cpu, cia.ip, 1,
		  itable[indx].file, itable[indx].line_nr, "fpu",
		  "%-*s %*f %*f => 0x%.*lx %-*ld",
		  tic80_size_name, itable[indx].name,
		  SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input1),
		  SIZE_HEX + SIZE_DECIMAL + 3, sim_fpu_2d (&input2),
		  SIZE_HEX, result, SIZE_DECIMAL, (long)(signed32)result);
}

/* Trace the result of a NOP operation */
char *
tic80_trace_nop (int indx)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  sprintf (tic80_trace_buffer, "%s", itable[indx].name);
  return tic80_trace_buffer;
}

/* Trace the result of a data sink with one input */
char *
tic80_trace_sink1 (int indx, unsigned32 input)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld",
	   tic80_size_name, itable[indx].name,
	   SIZE_HEX, input, SIZE_DECIMAL, (long)(signed32)input);

  return tic80_trace_buffer;
}

/* Trace the result of a data sink with two inputs */
char *
tic80_trace_sink2 (int indx, unsigned32 input1, unsigned32 input2)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld",
	   tic80_size_name, itable[indx].name,
	   SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1,
	   SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2);

  return tic80_trace_buffer;
}

/* Trace the result of a data sink with three inputs */
char *
tic80_trace_sink3 (int indx, unsigned32 input1, unsigned32 input2, unsigned32 input3)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  sprintf (tic80_trace_buffer, "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld    0x%.*lx/%*ld",
	   tic80_size_name, itable[indx].name,
	   SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1,
	   SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2,
	   SIZE_HEX, input3, SIZE_DECIMAL, (long)(signed32)input3);

  return tic80_trace_buffer;
}

/* Trace the result of a conditional branch operation */
char *
tic80_trace_cond_br (int indx,
		     int jump_p,
		     unsigned32 cond,
		     unsigned32 target)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  if (jump_p)
    sprintf (tic80_trace_buffer,
	     "%-*s 0x%.*lx %*s 0x%.*lx/%*ld => 0x%.*lx",
	     tic80_size_name, itable[indx].name,
	     SIZE_HEX, target, SIZE_DECIMAL, "",
	     SIZE_HEX, cond, SIZE_DECIMAL, (long)(signed32)cond,
	     SIZE_HEX, target);
  else
    sprintf (tic80_trace_buffer,
	     "%-*s 0x%.*lx %*s 0x%.*lx/%*ld => [fallthrough]",
	     tic80_size_name, itable[indx].name,
	     SIZE_HEX, target, SIZE_DECIMAL, "",
	     SIZE_HEX, cond, SIZE_DECIMAL, (long)(signed32)cond);

  return tic80_trace_buffer;	       
}

/* Trace the result of a unconditional branch operation */
char *
tic80_trace_ucond_br (int indx,
		      unsigned32 target)
{
  if (!tic80_size_name)
    tic80_init_trace ();

  sprintf (tic80_trace_buffer,
	     "%-*s 0x%.*lx %*s => 0x%.*lx",
	     tic80_size_name, itable[indx].name,
	     SIZE_HEX, target, (SIZE_DECIMAL*2) + SIZE_HEX + 4, "",
	     SIZE_HEX, target);

  return tic80_trace_buffer;	       
}

/* Trace the result of a load or store operation with 2 integer addresses
   and an integer output or input */
void
tic80_trace_ldst (SIM_DESC sd,
		  sim_cpu *cpu,
		  sim_cia cia,
		  int indx,
		  int st_p,
		  int m_p,
		  int s_p,
		  unsigned32 value,
		  unsigned32 input1,
		  unsigned32 input2)
{
  char name[40];

  if (!tic80_size_name)
    tic80_init_trace ();

  strcpy (name, itable[indx].name);
  if (m_p)
    strcat (name, ":m");

  if (s_p)
    strcat (name, ":s");

  trace_one_insn (sd, cpu, cia.ip, 1,
		  itable[indx].file, itable[indx].line_nr, "memory",
		  "%-*s 0x%.*lx/%*ld 0x%.*lx/%*ld %s 0x%.*lx/%*ld",
		  tic80_size_name, name,
		  SIZE_HEX, input1, SIZE_DECIMAL, (long)(signed32)input1,
		  SIZE_HEX, input2, SIZE_DECIMAL, (long)(signed32)input2,
		  (!st_p) ? "=>" : "<=",
		  SIZE_HEX, value, SIZE_DECIMAL, (long)(signed32)value);
}

#endif /* WITH_TRACE */