~ubuntu-branches/ubuntu/jaunty/spim/jaunty

« back to all changes in this revision

Viewing changes to mem.c

  • Committer: Bazaar Package Importer
  • Author(s): Fernando Sanchez
  • Date: 2001-01-24 14:05:34 UTC
  • Revision ID: james.westby@ubuntu.com-20010124140534-3le9wmofforjjcd8
Tags: upstream-6.3
ImportĀ upstreamĀ versionĀ 6.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* SPIM S20 MIPS simulator.
 
2
   Code to create, maintain and access memory.
 
3
 
 
4
   Copyright (C) 1990-2000 by James Larus (larus@cs.wisc.edu).
 
5
   ALL RIGHTS RESERVED.
 
6
 
 
7
   SPIM is distributed under the following conditions:
 
8
 
 
9
     You may make copies of SPIM for your own use and modify those copies.
 
10
 
 
11
     All copies of SPIM must retain my name and copyright notice.
 
12
 
 
13
     You may not sell SPIM or distributed SPIM in conjunction with a
 
14
     commerical product or service without the expressed written consent of
 
15
     James Larus.
 
16
 
 
17
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 
18
   IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 
19
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
20
   PURPOSE. */
 
21
 
 
22
 
 
23
/* $Header: /Software/SPIM/src/mem.c 8     12/24/00 1:37p Larus $
 
24
*/
 
25
 
 
26
 
 
27
#include "spim.h"
 
28
#include "spim-utils.h"
 
29
#include "inst.h"
 
30
#include "mem.h"
 
31
#include "reg.h"
 
32
 
 
33
/* Exported Variables: */
 
34
 
 
35
reg_word R[32];
 
36
reg_word HI, LO;
 
37
int HI_present, LO_present;
 
38
mem_addr PC, nPC;
 
39
double *FPR;                    /* Dynamically allocate so overlay */
 
40
float *FGR;                     /* is possible */
 
41
int *FWR;                       /* is possible */
 
42
int FP_reg_present;             /* Presence bits for FP registers */
 
43
int FP_reg_poison;              /* Poison bits for FP registers */
 
44
int FP_spec_load;               /* Is register waiting for a speculative ld */
 
45
reg_word CpCond[4], CCR[4][32], CPR[4][32];
 
46
 
 
47
instruction **text_seg;
 
48
int text_modified;              /* Non-zero means text segment was written */
 
49
mem_addr text_top;
 
50
mem_word *data_seg;
 
51
int data_modified;              /* Non-zero means a data segment was written */
 
52
short *data_seg_h;              /* Points to same vector as DATA_SEG */
 
53
BYTE_TYPE *data_seg_b;          /* Ditto */
 
54
mem_addr data_top;
 
55
mem_addr gp_midpoint;           /* Middle of $gp area */
 
56
mem_word *stack_seg;
 
57
short *stack_seg_h;             /* Points to same vector as STACK_SEG */
 
58
BYTE_TYPE *stack_seg_b;         /* Ditto */
 
59
mem_addr stack_bot;
 
60
instruction **k_text_seg;
 
61
mem_addr k_text_top;
 
62
mem_word *k_data_seg;
 
63
short *k_data_seg_h;
 
64
BYTE_TYPE *k_data_seg_b;
 
65
mem_addr k_data_top;
 
66
 
 
67
 
 
68
/* Local functions: */
 
69
 
 
70
#ifdef __STDC__
 
71
static void free_instructions (register instruction **inst, int n);
 
72
static mem_word read_memory_mapped_IO (mem_addr addr);
 
73
static void write_memory_mapped_IO (mem_addr addr, mem_word value);
 
74
#else
 
75
static void free_instructions ();
 
76
static mem_word read_memory_mapped_IO ();
 
77
static void write_memory_mapped_IO ();
 
78
#endif
 
79
 
 
80
 
 
81
/* Local variables: */
 
82
 
 
83
static int32 data_size_limit, stack_size_limit, k_data_size_limit;
 
84
 
 
85
 
 
86
 
 
87
/* Memory is allocated in five chunks:
 
88
        text, data, stack, kernel text, and kernel data.
 
89
 
 
90
   The arrays are independent and have different semantics.
 
91
 
 
92
   text is allocated from 0x400000 up and only contains INSTRUCTIONs.
 
93
   It does not expand.
 
94
 
 
95
   data is allocated from 0x10000000 up.  It can be extended by the
 
96
   SBRK system call.  Programs can only read and write this segment.
 
97
 
 
98
   stack grows from 0x7fffefff down.  It is automatically extended.
 
99
   Programs can only read and write this segment.
 
100
 
 
101
   k_text is like text, except its is allocated from 0x80000000 up.
 
102
 
 
103
   k_data is like data, but is allocated from 0x90000000 up.
 
104
 
 
105
   Both kernel text and kernel data can only be accessed in kernel mode.
 
106
*/
 
107
 
 
108
/* The text segments contain pointers to instructions, not actual
 
109
   instructions, so they must be allocated large enough to hold as many
 
110
   pointers as there would be instructions (the two differ on machines in
 
111
   which pointers are not 32 bits long).  The following calculations round
 
112
   up in case size is not a multiple of BYTES_PER_WORD.  */
 
113
 
 
114
#define BYTES_TO_INST(N) (((N) + BYTES_PER_WORD - 1) / BYTES_PER_WORD * sizeof(instruction*))
 
115
 
 
116
 
 
117
#ifdef __STDC__
 
118
void
 
119
make_memory (int text_size, int data_size, int data_limit,
 
120
             int stack_size, int stack_limit, int k_text_size,
 
121
             int k_data_size, int k_data_limit)
 
122
#else
 
123
void
 
124
make_memory (text_size,
 
125
             data_size, data_limit,
 
126
             stack_size, stack_limit,
 
127
             k_text_size,
 
128
             k_data_size, k_data_limit)
 
129
     int text_size, data_size, data_limit, stack_size, stack_limit,
 
130
       k_text_size, k_data_size, k_data_limit;
 
131
#endif
 
132
{
 
133
  if (data_size <= 65536)
 
134
    data_size = 65536;
 
135
 
 
136
  if (text_seg == NULL)
 
137
    text_seg = (instruction **) xmalloc (BYTES_TO_INST(text_size));
 
138
  else
 
139
    {
 
140
      free_instructions (text_seg, (text_top - TEXT_BOT) / BYTES_PER_WORD);
 
141
      text_seg = (instruction **) realloc (text_seg, BYTES_TO_INST(text_size));
 
142
    }
 
143
  memclr (text_seg, BYTES_TO_INST(text_size));
 
144
  text_top = TEXT_BOT + text_size;
 
145
 
 
146
  if (data_seg == NULL)
 
147
    data_seg = (mem_word *) xmalloc (data_size);
 
148
  else
 
149
    data_seg = (mem_word *) realloc (data_seg, data_size);
 
150
  memclr (data_seg, data_size);
 
151
  data_seg_b = (BYTE_TYPE *) data_seg;
 
152
  data_seg_h = (short *) data_seg;
 
153
  data_top = DATA_BOT + data_size;
 
154
  data_size_limit = data_limit;
 
155
 
 
156
  if (stack_seg == NULL)
 
157
    stack_seg = (mem_word *) xmalloc (stack_size);
 
158
  else
 
159
    stack_seg = (mem_word *) realloc (stack_seg, stack_size);
 
160
  memclr (stack_seg, stack_size);
 
161
  stack_seg_b = (BYTE_TYPE *) stack_seg;
 
162
  stack_seg_h = (short *) stack_seg;
 
163
  stack_bot = STACK_TOP - stack_size;
 
164
  stack_size_limit = stack_limit;
 
165
 
 
166
  if (k_text_seg == NULL)
 
167
    k_text_seg = (instruction **) xmalloc (BYTES_TO_INST(k_text_size));
 
168
  else
 
169
    {
 
170
      free_instructions (k_text_seg,
 
171
                         (k_text_top - K_TEXT_BOT) / BYTES_PER_WORD);
 
172
      k_text_seg = (instruction **) realloc(k_text_seg,
 
173
                                            BYTES_TO_INST(k_text_size));
 
174
    }
 
175
  memclr (k_text_seg, BYTES_TO_INST(k_text_size));
 
176
  k_text_top = K_TEXT_BOT + k_text_size;
 
177
 
 
178
  if (k_data_seg == NULL)
 
179
    k_data_seg = (mem_word *) xmalloc (k_data_size);
 
180
  else
 
181
    k_data_seg = (mem_word *) realloc (k_data_seg, k_data_size);
 
182
  memclr (k_data_seg, k_data_size);
 
183
  k_data_seg_b = (BYTE_TYPE *) k_data_seg;
 
184
  k_data_seg_h = (short *) k_data_seg;
 
185
  k_data_top = K_DATA_BOT + k_data_size;
 
186
  k_data_size_limit = k_data_limit;
 
187
 
 
188
  text_modified = 1;
 
189
  data_modified = 1;
 
190
}
 
191
 
 
192
 
 
193
/* Free the storage used by the old instructions in memory. */
 
194
 
 
195
#ifdef __STDC__
 
196
static void
 
197
free_instructions (register instruction **inst, int n)
 
198
#else
 
199
static void
 
200
free_instructions (inst, n)
 
201
     register instruction **inst;
 
202
     int n;
 
203
#endif
 
204
{
 
205
  for ( ; n > 0; n --, inst ++)
 
206
    if (*inst)
 
207
      free_inst (*inst);
 
208
}
 
209
 
 
210
 
 
211
/* Expand the data segment by adding N bytes. */
 
212
 
 
213
#ifdef __STDC__
 
214
void
 
215
expand_data (int addl_bytes)
 
216
#else
 
217
void
 
218
expand_data (addl_bytes)
 
219
     int addl_bytes;
 
220
#endif
 
221
{
 
222
  int old_size = data_top - DATA_BOT;
 
223
  int new_size = old_size + addl_bytes;
 
224
  register mem_word *p;
 
225
 
 
226
  if (addl_bytes < 0 || (source_file && new_size > data_size_limit))
 
227
    {
 
228
      error ("Can't expand data segment by %d bytes to %d bytes\n",
 
229
             addl_bytes, new_size);
 
230
      run_error ("Use -ldata # with # > %d\n", new_size);
 
231
    }
 
232
  data_seg = (mem_word *) realloc (data_seg, new_size);
 
233
  if (data_seg == NULL)
 
234
    fatal_error ("realloc failed in expand_data\n");
 
235
  data_seg_b = (BYTE_TYPE *) data_seg;
 
236
  data_seg_h = (short *) data_seg;
 
237
  for (p = data_seg + old_size / BYTES_PER_WORD;
 
238
       p < data_seg + new_size / BYTES_PER_WORD; )
 
239
    *p ++ = 0;
 
240
  data_top += addl_bytes;
 
241
}
 
242
 
 
243
 
 
244
/* Expand the stack segment by adding N bytes.  Can't use REALLOC
 
245
   since it copies from bottom of memory blocks and stack grows down from
 
246
   top of its block. */
 
247
 
 
248
#ifdef __STDC__
 
249
void
 
250
expand_stack (int addl_bytes)
 
251
#else
 
252
void
 
253
expand_stack (addl_bytes)
 
254
     int addl_bytes;
 
255
#endif
 
256
{
 
257
  int old_size = STACK_TOP - stack_bot;
 
258
  int new_size = old_size + MAX (addl_bytes, old_size);
 
259
  mem_word *new_seg;
 
260
  register mem_word *po, *pn;
 
261
 
 
262
  if (addl_bytes < 0 || (source_file && new_size > stack_size_limit))
 
263
    {
 
264
      error ("Can't expand stack segment by %d bytes to %d bytes\n",
 
265
             addl_bytes, new_size);
 
266
      run_error ("Use -lstack # with # > %d\n", new_size);
 
267
    }
 
268
 
 
269
  new_seg = (mem_word *) xmalloc (new_size);
 
270
  po = stack_seg + (old_size / BYTES_PER_WORD - 1);
 
271
  pn = new_seg + (new_size / BYTES_PER_WORD - 1);
 
272
 
 
273
  for ( ; po >= stack_seg ; ) *pn -- = *po --;
 
274
  for ( ; pn >= new_seg ; ) *pn -- = 0;
 
275
 
 
276
  free (stack_seg);
 
277
  stack_seg = new_seg;
 
278
  stack_seg_b = (BYTE_TYPE *) stack_seg;
 
279
  stack_seg_h = (short *) stack_seg;
 
280
  stack_bot -= (new_size - old_size);
 
281
}
 
282
 
 
283
 
 
284
/* Expand the kernel data segment by adding N bytes. */
 
285
 
 
286
#ifdef __STDC__
 
287
void
 
288
expand_k_data (int addl_bytes)
 
289
#else
 
290
void
 
291
expand_k_data (addl_bytes)
 
292
     int addl_bytes;
 
293
#endif
 
294
{
 
295
  int old_size = k_data_top - K_DATA_BOT;
 
296
  int new_size = old_size + addl_bytes;
 
297
  register mem_word *p;
 
298
 
 
299
  if (addl_bytes < 0 || (source_file && new_size > k_data_size_limit))
 
300
    {
 
301
      error ("Can't expand kernel data segment by %d bytes to %d bytes\n",
 
302
             addl_bytes, new_size);
 
303
      run_error ("Use -lkdata # with # > %d\n", new_size);
 
304
    }
 
305
  k_data_seg = (mem_word *) realloc (k_data_seg, new_size);
 
306
  if (k_data_seg == NULL)
 
307
    fatal_error ("realloc failed in expand_k_data\n");
 
308
  k_data_seg_b = (BYTE_TYPE *) k_data_seg;
 
309
  k_data_seg_h = (short *) k_data_seg;
 
310
  for (p = k_data_seg + old_size / BYTES_PER_WORD;
 
311
       p < k_data_seg + new_size / BYTES_PER_WORD; )
 
312
    *p ++ = 0;
 
313
  k_data_top += addl_bytes;
 
314
}
 
315
 
 
316
 
 
317
 
 
318
/* Handle the infrequent and erroneous cases in the memory access macros. */
 
319
 
 
320
#ifdef __STDC__
 
321
instruction *
 
322
bad_text_read (mem_addr addr)
 
323
#else
 
324
instruction *
 
325
bad_text_read (addr)
 
326
     mem_addr addr;
 
327
#endif
 
328
{
 
329
  RAISE_EXCEPTION (IBUS_EXCPT, BadVAddr = addr);
 
330
  return (inst_decode (0));
 
331
}
 
332
 
 
333
 
 
334
#ifdef __STDC__
 
335
void
 
336
bad_text_write (mem_addr addr, instruction *inst)
 
337
#else
 
338
void
 
339
bad_text_write (addr, inst)
 
340
     mem_addr addr;
 
341
     instruction *inst;
 
342
#endif
 
343
{
 
344
  RAISE_EXCEPTION (IBUS_EXCPT, BadVAddr = addr);
 
345
  SET_MEM_WORD (addr, ENCODING (inst));
 
346
}
 
347
 
 
348
 
 
349
#ifdef __STDC__
 
350
mem_word
 
351
bad_mem_read (mem_addr addr, int mask, mem_word *dest)
 
352
#else
 
353
mem_word
 
354
bad_mem_read (addr, mask, dest)
 
355
     mem_addr addr;
 
356
     int mask;
 
357
     mem_word *dest;
 
358
#endif
 
359
{
 
360
  mem_word tmp;
 
361
 
 
362
  if (addr & mask)
 
363
    RAISE_EXCEPTION (ADDRL_EXCPT, BadVAddr = addr)
 
364
  else if (addr >= TEXT_BOT && addr < text_top)
 
365
    switch (mask)
 
366
      {
 
367
      case 0x0:
 
368
        tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
 
369
#ifdef BIGENDIAN
 
370
        tmp = (unsigned)tmp >> (8 * (3 - (addr & 0x3)));
 
371
#else
 
372
        tmp = (unsigned)tmp >> (8 * (addr & 0x3));
 
373
#endif
 
374
        return (0xff & tmp);
 
375
 
 
376
      case 0x1:
 
377
        tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
 
378
#ifdef BIGENDIAN
 
379
        tmp = (unsigned)tmp >> (8 * (2 - (addr & 0x2)));
 
380
#else
 
381
        tmp = (unsigned)tmp >> (8 * (addr & 0x2));
 
382
#endif
 
383
        return (0xffff & tmp);
 
384
 
 
385
      case 0x3:
 
386
        {
 
387
        instruction *inst = text_seg [(addr - TEXT_BOT) >> 2];
 
388
        if (inst == NULL)
 
389
          return 0;
 
390
        else
 
391
          return (ENCODING (inst));
 
392
        }
 
393
 
 
394
      default:
 
395
        run_error ("Bad mask (0x%x) in bad_mem_read\n", mask);
 
396
      }
 
397
  else if (addr > data_top
 
398
           && addr < stack_bot
 
399
           /* If more than 16 MB below stack, probably is bad data ref */
 
400
           && addr > stack_bot - 16*K*K)
 
401
    {
 
402
      /* Grow stack segment */
 
403
      expand_stack (stack_bot - addr + 4);
 
404
      *dest = 0;                /* Newly allocated memory */
 
405
      return (0);
 
406
    }
 
407
  else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP)
 
408
    return (read_memory_mapped_IO (addr));
 
409
  else
 
410
    /* Address out of range */
 
411
    RAISE_EXCEPTION (DBUS_EXCPT, BadVAddr = addr)
 
412
  return (0);
 
413
}
 
414
 
 
415
 
 
416
#ifdef __STDC__
 
417
void
 
418
bad_mem_write (mem_addr addr, mem_word value, int mask)
 
419
#else
 
420
void
 
421
bad_mem_write (addr, value, mask)
 
422
     mem_addr addr;
 
423
     mem_word value;
 
424
     int mask;
 
425
#endif
 
426
{
 
427
  mem_word tmp;
 
428
  
 
429
  if (addr & mask)
 
430
    /* Unaligned address fault */
 
431
    RAISE_EXCEPTION (ADDRS_EXCPT, BadVAddr = addr)
 
432
    else if (addr >= TEXT_BOT && addr < text_top)
 
433
  {
 
434
    switch (mask)
 
435
    {
 
436
    case 0x0:
 
437
      tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
 
438
#ifdef BIGENDIAN
 
439
      tmp = ((tmp & ~(0xff << (8 * (3 - (addr & 0x3)))))
 
440
               | (value & 0xff) << (8 * (3 - (addr & 0x3))));
 
441
#else
 
442
      tmp = ((tmp & ~(0xff << (8 * (addr & 0x3))))
 
443
               | (value & 0xff) << (8 * (addr & 0x3)));
 
444
#endif
 
445
      text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp);
 
446
      break;
 
447
      
 
448
    case 0x1:
 
449
      tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
 
450
#ifdef BIGENDIAN
 
451
      tmp = ((tmp & ~(0xffff << (8 * (2 - (addr & 0x2)))))
 
452
               | (value & 0xffff) << (8 * (2 - (addr & 0x2))));
 
453
#else
 
454
      tmp = ((tmp & ~(0xffff << (8 * (addr & 0x2))))
 
455
               | (value & 0xffff) << (8 * (addr & 0x2)));
 
456
#endif
 
457
      text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp);
 
458
      break;
 
459
      
 
460
    case 0x3:
 
461
      text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (value);
 
462
      break;
 
463
      
 
464
    default:
 
465
      run_error ("Bad mask (0x%x) in bad_mem_read\n", mask);
 
466
    }
 
467
    
 
468
    text_modified = 1;
 
469
  }
 
470
  else if (addr > data_top
 
471
           && addr < stack_bot
 
472
           /* If more than 16 MB below stack, probably is bad data ref */
 
473
           && addr > stack_bot - 16*K*K)
 
474
  {
 
475
    /* Grow stack segment */
 
476
    expand_stack (stack_bot - addr + 4);
 
477
    if (addr >= stack_bot)
 
478
    {
 
479
      if (mask == 0)
 
480
        stack_seg_b [addr - stack_bot] = (char)value;
 
481
      else if (mask == 1)
 
482
        stack_seg_h [(addr - stack_bot) >> 1] = (short)value;
 
483
      else
 
484
        stack_seg [(addr - stack_bot) >> 2] = value;
 
485
    }
 
486
    else
 
487
      RAISE_EXCEPTION (DBUS_EXCPT, BadVAddr = addr)
 
488
      
 
489
    data_modified = 1;
 
490
  }
 
491
  else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP)
 
492
    write_memory_mapped_IO (addr, value);
 
493
  else
 
494
    /* Address out of range */
 
495
    RAISE_EXCEPTION (DBUS_EXCPT, BadVAddr = addr)
 
496
}
 
497
 
 
498
 
 
499
 
 
500
/* Memory-mapped IO routines: */
 
501
 
 
502
static long recv_control, recv_buffer, recv_buffer_filled;
 
503
static long trans_control, trans_buffer, trans_buffer_filled;
 
504
 
 
505
 
 
506
/* Every IO_INTERVAL time steps, check if input is available and output
 
507
   is possible.  If so, update the control registers and buffers. */
 
508
 
 
509
#ifdef __STDC__
 
510
void
 
511
check_memory_mapped_IO (void)
 
512
#else
 
513
void
 
514
check_memory_mapped_IO ()
 
515
#endif
 
516
{
 
517
  static long mm_io_initialized = 0;
 
518
 
 
519
  if (!mm_io_initialized)
 
520
    {
 
521
      recv_control = RECV_READY;
 
522
      trans_control = TRANS_READY;
 
523
      mm_io_initialized = 1;
 
524
    }
 
525
 
 
526
  if (console_input_available ())
 
527
    {
 
528
      recv_buffer_filled -= IO_INTERVAL;
 
529
      if (recv_buffer_filled <= 0)
 
530
        {
 
531
          recv_buffer = get_console_char ();
 
532
          recv_control |= RECV_READY;
 
533
          recv_buffer_filled = RECV_LATENCY;
 
534
          if ((recv_control & RECV_INT_ENABLE)
 
535
              && INTERRUPTS_ON
 
536
              && (Status_Reg & RECV_INT_MASK))
 
537
            RAISE_EXCEPTION (INT_EXCPT, Cause |= RECV_INT_MASK);
 
538
        }
 
539
    }
 
540
  else if (recv_buffer_filled <= 0)
 
541
    recv_control &= ~RECV_READY;
 
542
 
 
543
  if (trans_buffer_filled > 0)
 
544
    {
 
545
      trans_buffer_filled -= IO_INTERVAL;
 
546
      if (trans_buffer_filled <= 0)
 
547
        {
 
548
          put_console_char ((char)trans_buffer);
 
549
          trans_control |= TRANS_READY;
 
550
          trans_buffer_filled = 0;
 
551
          if ((trans_control & TRANS_INT_ENABLE)
 
552
              && INTERRUPTS_ON
 
553
              && (Status_Reg & TRANS_INT_MASK))
 
554
            RAISE_EXCEPTION (INT_EXCPT, Cause |= TRANS_INT_MASK)
 
555
        }
 
556
    }
 
557
}
 
558
 
 
559
 
 
560
/* Invoked on a write in the memory-mapped IO area. */
 
561
 
 
562
#ifdef __STDC__
 
563
static void
 
564
write_memory_mapped_IO (mem_addr addr, mem_word value)
 
565
#else
 
566
static void
 
567
write_memory_mapped_IO (addr, value)
 
568
     mem_addr addr;
 
569
     mem_word value;
 
570
#endif
 
571
{
 
572
  switch (addr)
 
573
    {
 
574
    case TRANS_CTRL_ADDR:
 
575
      trans_control = ((trans_control & ~TRANS_INT_ENABLE)
 
576
                       | (value & TRANS_INT_ENABLE));
 
577
 
 
578
      if ((trans_control & TRANS_READY)
 
579
          && (trans_control & TRANS_INT_ENABLE)
 
580
          && INTERRUPTS_ON
 
581
          && (Status_Reg & TRANS_INT_MASK))
 
582
        /* Raise an interrupt immediately on enabling a ready xmitter */
 
583
        RAISE_EXCEPTION (INT_EXCPT, Cause |= TRANS_INT_MASK)
 
584
      break;
 
585
 
 
586
    case TRANS_BUFFER_ADDR:
 
587
      if (trans_control & TRANS_READY) /* Ignore if not ready */
 
588
        {
 
589
          trans_buffer = value & 0xff;
 
590
          trans_control &= ~TRANS_READY;
 
591
          trans_buffer_filled = TRANS_LATENCY;
 
592
        }
 
593
      break;
 
594
 
 
595
    case RECV_CTRL_ADDR:
 
596
      recv_control = ((recv_control & ~RECV_INT_ENABLE)
 
597
                      | (value & RECV_INT_ENABLE));
 
598
      break;
 
599
 
 
600
    case RECV_BUFFER_ADDR:
 
601
      break;
 
602
 
 
603
    default:
 
604
      run_error ("Write to unused memory-mapped IO address (0x%x)\n",
 
605
                 addr);
 
606
    }
 
607
}
 
608
 
 
609
 
 
610
/* Invoked on a read in the memory-mapped IO area. */
 
611
 
 
612
#ifdef __STDC__
 
613
static mem_word
 
614
read_memory_mapped_IO (mem_addr addr)
 
615
#else
 
616
static mem_word
 
617
read_memory_mapped_IO (addr)
 
618
     mem_addr addr;
 
619
#endif
 
620
{
 
621
  switch (addr)
 
622
    {
 
623
    case TRANS_CTRL_ADDR:
 
624
      return (trans_control);
 
625
 
 
626
    case TRANS_BUFFER_ADDR:
 
627
      return (trans_buffer & 0xff);
 
628
 
 
629
    case RECV_CTRL_ADDR:
 
630
      return (recv_control);
 
631
 
 
632
    case RECV_BUFFER_ADDR:
 
633
      recv_control &= ~RECV_READY;
 
634
      recv_buffer_filled = 0;
 
635
      return (recv_buffer & 0xff);
 
636
 
 
637
    default:
 
638
      run_error ("Read from unused memory-mapped IO address (0x%x)\n",
 
639
                 addr);
 
640
      return (0);
 
641
    }
 
642
}
 
643
 
 
644
 
 
645
 
 
646
/* Misc. routines */
 
647
 
 
648
#ifdef __STDC__
 
649
void
 
650
print_mem (mem_addr addr)
 
651
#else
 
652
void
 
653
print_mem (addr)
 
654
     mem_addr addr;
 
655
#endif
 
656
{
 
657
  mem_word value;
 
658
 
 
659
  if (addr & 0x3)
 
660
    addr &= ~0x3;               /* Address must be word-aligned */
 
661
 
 
662
  if (TEXT_BOT <= addr && addr < text_top)
 
663
    print_inst (addr);
 
664
  else if (DATA_BOT <= addr && addr < data_top)
 
665
    {
 
666
      READ_MEM_WORD (value, addr);
 
667
      write_output (message_out, "Data seg @ 0x%08x (%d) = 0x%08x (%d)\n",
 
668
                    addr, addr, value, value);
 
669
    }
 
670
  else if (stack_bot <= addr && addr < STACK_TOP)
 
671
    {
 
672
      READ_MEM_WORD (value, addr);
 
673
      write_output (message_out, "Stack seg @ 0x%08x (%d) = 0x%08x (%d)\n",
 
674
                    addr, addr, value, value);
 
675
    }
 
676
  else if (K_TEXT_BOT <= addr && addr < k_text_top)
 
677
    print_inst (addr);
 
678
  else if (K_DATA_BOT <= addr && addr < k_data_top)
 
679
    {
 
680
      READ_MEM_WORD (value, addr);
 
681
      write_output (message_out,
 
682
                    "Kernel Data seg @ 0x%08x (%d) = 0x%08x (%d)\n",
 
683
                    addr, addr, value, value);
 
684
    }
 
685
  else
 
686
    error ("Address 0x%08x (%d) to print_mem is out of bounds\n", addr, addr);
 
687
}