/* * Copyright 1993,1994,1995 Emin Gun Sirer * MIPSI - Mips Instruction Set Simulator. */ #include #include #include "config.h" #include "main.h" #include "mem.h" #define STACKSZ 100 * K #define STACKDELTA 100 * K Segment segment[9]; /* define the externs in mem.h */ mem_word *textseg, *dataseg, *stackseg; unsigned long textsize, datasize, stacksize; mem_addr pbreak, pstaddress; /* we use the inlined macro otherwise */ #include "memaddr.c" #define DEBUG(p) printf p /* * this is to allow passing NULL pointers in system calls without causing * illegal address traps and translating non-null pointers. Can replace * mem_address for "VAX bug compatibility" :-). */ extern host_addr mem_address_nullok(mem_addr addr, c_rw rw) { Segment s; unsigned long diff; if(addr == 0) return 0; redo: /* * we do the range comparison by an unsigned subtraction */ s = segment[(addr >> 28)]; diff = addr - s.base; if(diff <= s.size) return (host_addr) ((char *)s.segment + diff); /* * expand stack if necessary -- segment[8] is always a stack segment * if the pointer is within a meg of sp, increase sp. */ if((segment[8].base - addr) < (1 * M)) { expand_stack(); goto redo; } /* we have to set Cause and BadVAddr */ BadVAddr = addr; /* * Let's seg fault right here */ *(char *)0 = '\0'; } static void setsegtype(mem_addr base, host_addr segloc, unsigned long size, Id id) { int seg; for(seg = base >> 28; seg <= ((base + size) >> 28); ++seg) { segment[seg].segmentid = id; segment[seg].base = base; segment[seg].segment = segloc; segment[seg].size = size; } } static void updatesegmentmap(void) { setsegtype(0x00400000, textseg, textsize, Text); setsegtype(0x10000000, dataseg, datasize, Data); setsegtype(0x80000000-stacksize, stackseg, stacksize, Stack); } extern void make_memory(unsigned long textsz, unsigned long datasz) { textseg = (mem_word *) galloc(textsz); textsize = textsz; dataseg = (mem_word *) galloc(datasz); datasize = datasz; stackseg = (mem_word *) galloc(STACKSZ); stacksize = STACKSZ; updatesegmentmap(); } extern void free_memory(void) { free(textseg); free(dataseg); free(stackseg); } /* Expand the data segment by delta */ extern void expand_data(long delta) { unsigned long oldsize = datasize; DEBUG(("Expanding data segment by %d\n", delta)); datasize += delta; dataseg = (mem_word *) grealloc(dataseg, datasize); if(delta > 0) bzero((char *)dataseg + oldsize, delta); updatesegmentmap(); } /* Expand the stack segment */ void expand_stack(void) { int oldsize = stacksize; DEBUG(("Expanding stack\n")); stacksize += STACKDELTA; stackseg = (mem_word *) grealloc(stackseg, stacksize); memmove((char*)stackseg+STACKDELTA, stackseg, oldsize); updatesegmentmap(); } void print_memstats(void) { int i; printf("Text space used 0x%x\n", segment[0].size); printf("Data space used 0x%x\n", segment[1].size); printf("Max stack space 0x%x\n", segment[8].size); }