1
/* SPIM S20 MIPS simulator.
2
Code to create, maintain and access memory.
4
Copyright (C) 1990-2000 by James Larus (larus@cs.wisc.edu).
7
SPIM is distributed under the following conditions:
9
You may make copies of SPIM for your own use and modify those copies.
11
All copies of SPIM must retain my name and copyright notice.
13
You may not sell SPIM or distributed SPIM in conjunction with a
14
commerical product or service without the expressed written consent of
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
23
/* $Header: /Software/SPIM/src/mem.c 8 12/24/00 1:37p Larus $
28
#include "spim-utils.h"
33
/* Exported Variables: */
37
int HI_present, LO_present;
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];
47
instruction **text_seg;
48
int text_modified; /* Non-zero means text segment was written */
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 */
55
mem_addr gp_midpoint; /* Middle of $gp area */
57
short *stack_seg_h; /* Points to same vector as STACK_SEG */
58
BYTE_TYPE *stack_seg_b; /* Ditto */
60
instruction **k_text_seg;
64
BYTE_TYPE *k_data_seg_b;
68
/* Local functions: */
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);
75
static void free_instructions ();
76
static mem_word read_memory_mapped_IO ();
77
static void write_memory_mapped_IO ();
81
/* Local variables: */
83
static int32 data_size_limit, stack_size_limit, k_data_size_limit;
87
/* Memory is allocated in five chunks:
88
text, data, stack, kernel text, and kernel data.
90
The arrays are independent and have different semantics.
92
text is allocated from 0x400000 up and only contains INSTRUCTIONs.
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.
98
stack grows from 0x7fffefff down. It is automatically extended.
99
Programs can only read and write this segment.
101
k_text is like text, except its is allocated from 0x80000000 up.
103
k_data is like data, but is allocated from 0x90000000 up.
105
Both kernel text and kernel data can only be accessed in kernel mode.
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. */
114
#define BYTES_TO_INST(N) (((N) + BYTES_PER_WORD - 1) / BYTES_PER_WORD * sizeof(instruction*))
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)
124
make_memory (text_size,
125
data_size, data_limit,
126
stack_size, stack_limit,
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;
133
if (data_size <= 65536)
136
if (text_seg == NULL)
137
text_seg = (instruction **) xmalloc (BYTES_TO_INST(text_size));
140
free_instructions (text_seg, (text_top - TEXT_BOT) / BYTES_PER_WORD);
141
text_seg = (instruction **) realloc (text_seg, BYTES_TO_INST(text_size));
143
memclr (text_seg, BYTES_TO_INST(text_size));
144
text_top = TEXT_BOT + text_size;
146
if (data_seg == NULL)
147
data_seg = (mem_word *) xmalloc (data_size);
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;
156
if (stack_seg == NULL)
157
stack_seg = (mem_word *) xmalloc (stack_size);
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;
166
if (k_text_seg == NULL)
167
k_text_seg = (instruction **) xmalloc (BYTES_TO_INST(k_text_size));
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));
175
memclr (k_text_seg, BYTES_TO_INST(k_text_size));
176
k_text_top = K_TEXT_BOT + k_text_size;
178
if (k_data_seg == NULL)
179
k_data_seg = (mem_word *) xmalloc (k_data_size);
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;
193
/* Free the storage used by the old instructions in memory. */
197
free_instructions (register instruction **inst, int n)
200
free_instructions (inst, n)
201
register instruction **inst;
205
for ( ; n > 0; n --, inst ++)
211
/* Expand the data segment by adding N bytes. */
215
expand_data (int addl_bytes)
218
expand_data (addl_bytes)
222
int old_size = data_top - DATA_BOT;
223
int new_size = old_size + addl_bytes;
224
register mem_word *p;
226
if (addl_bytes < 0 || (source_file && new_size > data_size_limit))
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);
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; )
240
data_top += addl_bytes;
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
250
expand_stack (int addl_bytes)
253
expand_stack (addl_bytes)
257
int old_size = STACK_TOP - stack_bot;
258
int new_size = old_size + MAX (addl_bytes, old_size);
260
register mem_word *po, *pn;
262
if (addl_bytes < 0 || (source_file && new_size > stack_size_limit))
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);
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);
273
for ( ; po >= stack_seg ; ) *pn -- = *po --;
274
for ( ; pn >= new_seg ; ) *pn -- = 0;
278
stack_seg_b = (BYTE_TYPE *) stack_seg;
279
stack_seg_h = (short *) stack_seg;
280
stack_bot -= (new_size - old_size);
284
/* Expand the kernel data segment by adding N bytes. */
288
expand_k_data (int addl_bytes)
291
expand_k_data (addl_bytes)
295
int old_size = k_data_top - K_DATA_BOT;
296
int new_size = old_size + addl_bytes;
297
register mem_word *p;
299
if (addl_bytes < 0 || (source_file && new_size > k_data_size_limit))
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);
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; )
313
k_data_top += addl_bytes;
318
/* Handle the infrequent and erroneous cases in the memory access macros. */
322
bad_text_read (mem_addr addr)
329
RAISE_EXCEPTION (IBUS_EXCPT, BadVAddr = addr);
330
return (inst_decode (0));
336
bad_text_write (mem_addr addr, instruction *inst)
339
bad_text_write (addr, inst)
344
RAISE_EXCEPTION (IBUS_EXCPT, BadVAddr = addr);
345
SET_MEM_WORD (addr, ENCODING (inst));
351
bad_mem_read (mem_addr addr, int mask, mem_word *dest)
354
bad_mem_read (addr, mask, dest)
363
RAISE_EXCEPTION (ADDRL_EXCPT, BadVAddr = addr)
364
else if (addr >= TEXT_BOT && addr < text_top)
368
tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
370
tmp = (unsigned)tmp >> (8 * (3 - (addr & 0x3)));
372
tmp = (unsigned)tmp >> (8 * (addr & 0x3));
377
tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
379
tmp = (unsigned)tmp >> (8 * (2 - (addr & 0x2)));
381
tmp = (unsigned)tmp >> (8 * (addr & 0x2));
383
return (0xffff & tmp);
387
instruction *inst = text_seg [(addr - TEXT_BOT) >> 2];
391
return (ENCODING (inst));
395
run_error ("Bad mask (0x%x) in bad_mem_read\n", mask);
397
else if (addr > data_top
399
/* If more than 16 MB below stack, probably is bad data ref */
400
&& addr > stack_bot - 16*K*K)
402
/* Grow stack segment */
403
expand_stack (stack_bot - addr + 4);
404
*dest = 0; /* Newly allocated memory */
407
else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP)
408
return (read_memory_mapped_IO (addr));
410
/* Address out of range */
411
RAISE_EXCEPTION (DBUS_EXCPT, BadVAddr = addr)
418
bad_mem_write (mem_addr addr, mem_word value, int mask)
421
bad_mem_write (addr, value, mask)
430
/* Unaligned address fault */
431
RAISE_EXCEPTION (ADDRS_EXCPT, BadVAddr = addr)
432
else if (addr >= TEXT_BOT && addr < text_top)
437
tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
439
tmp = ((tmp & ~(0xff << (8 * (3 - (addr & 0x3)))))
440
| (value & 0xff) << (8 * (3 - (addr & 0x3))));
442
tmp = ((tmp & ~(0xff << (8 * (addr & 0x3))))
443
| (value & 0xff) << (8 * (addr & 0x3)));
445
text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp);
449
tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);
451
tmp = ((tmp & ~(0xffff << (8 * (2 - (addr & 0x2)))))
452
| (value & 0xffff) << (8 * (2 - (addr & 0x2))));
454
tmp = ((tmp & ~(0xffff << (8 * (addr & 0x2))))
455
| (value & 0xffff) << (8 * (addr & 0x2)));
457
text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp);
461
text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (value);
465
run_error ("Bad mask (0x%x) in bad_mem_read\n", mask);
470
else if (addr > data_top
472
/* If more than 16 MB below stack, probably is bad data ref */
473
&& addr > stack_bot - 16*K*K)
475
/* Grow stack segment */
476
expand_stack (stack_bot - addr + 4);
477
if (addr >= stack_bot)
480
stack_seg_b [addr - stack_bot] = (char)value;
482
stack_seg_h [(addr - stack_bot) >> 1] = (short)value;
484
stack_seg [(addr - stack_bot) >> 2] = value;
487
RAISE_EXCEPTION (DBUS_EXCPT, BadVAddr = addr)
491
else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP)
492
write_memory_mapped_IO (addr, value);
494
/* Address out of range */
495
RAISE_EXCEPTION (DBUS_EXCPT, BadVAddr = addr)
500
/* Memory-mapped IO routines: */
502
static long recv_control, recv_buffer, recv_buffer_filled;
503
static long trans_control, trans_buffer, trans_buffer_filled;
506
/* Every IO_INTERVAL time steps, check if input is available and output
507
is possible. If so, update the control registers and buffers. */
511
check_memory_mapped_IO (void)
514
check_memory_mapped_IO ()
517
static long mm_io_initialized = 0;
519
if (!mm_io_initialized)
521
recv_control = RECV_READY;
522
trans_control = TRANS_READY;
523
mm_io_initialized = 1;
526
if (console_input_available ())
528
recv_buffer_filled -= IO_INTERVAL;
529
if (recv_buffer_filled <= 0)
531
recv_buffer = get_console_char ();
532
recv_control |= RECV_READY;
533
recv_buffer_filled = RECV_LATENCY;
534
if ((recv_control & RECV_INT_ENABLE)
536
&& (Status_Reg & RECV_INT_MASK))
537
RAISE_EXCEPTION (INT_EXCPT, Cause |= RECV_INT_MASK);
540
else if (recv_buffer_filled <= 0)
541
recv_control &= ~RECV_READY;
543
if (trans_buffer_filled > 0)
545
trans_buffer_filled -= IO_INTERVAL;
546
if (trans_buffer_filled <= 0)
548
put_console_char ((char)trans_buffer);
549
trans_control |= TRANS_READY;
550
trans_buffer_filled = 0;
551
if ((trans_control & TRANS_INT_ENABLE)
553
&& (Status_Reg & TRANS_INT_MASK))
554
RAISE_EXCEPTION (INT_EXCPT, Cause |= TRANS_INT_MASK)
560
/* Invoked on a write in the memory-mapped IO area. */
564
write_memory_mapped_IO (mem_addr addr, mem_word value)
567
write_memory_mapped_IO (addr, value)
574
case TRANS_CTRL_ADDR:
575
trans_control = ((trans_control & ~TRANS_INT_ENABLE)
576
| (value & TRANS_INT_ENABLE));
578
if ((trans_control & TRANS_READY)
579
&& (trans_control & TRANS_INT_ENABLE)
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)
586
case TRANS_BUFFER_ADDR:
587
if (trans_control & TRANS_READY) /* Ignore if not ready */
589
trans_buffer = value & 0xff;
590
trans_control &= ~TRANS_READY;
591
trans_buffer_filled = TRANS_LATENCY;
596
recv_control = ((recv_control & ~RECV_INT_ENABLE)
597
| (value & RECV_INT_ENABLE));
600
case RECV_BUFFER_ADDR:
604
run_error ("Write to unused memory-mapped IO address (0x%x)\n",
610
/* Invoked on a read in the memory-mapped IO area. */
614
read_memory_mapped_IO (mem_addr addr)
617
read_memory_mapped_IO (addr)
623
case TRANS_CTRL_ADDR:
624
return (trans_control);
626
case TRANS_BUFFER_ADDR:
627
return (trans_buffer & 0xff);
630
return (recv_control);
632
case RECV_BUFFER_ADDR:
633
recv_control &= ~RECV_READY;
634
recv_buffer_filled = 0;
635
return (recv_buffer & 0xff);
638
run_error ("Read from unused memory-mapped IO address (0x%x)\n",
650
print_mem (mem_addr addr)
660
addr &= ~0x3; /* Address must be word-aligned */
662
if (TEXT_BOT <= addr && addr < text_top)
664
else if (DATA_BOT <= addr && addr < data_top)
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);
670
else if (stack_bot <= addr && addr < STACK_TOP)
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);
676
else if (K_TEXT_BOT <= addr && addr < k_text_top)
678
else if (K_DATA_BOT <= addr && addr < k_data_top)
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);
686
error ("Address 0x%08x (%d) to print_mem is out of bounds\n", addr, addr);