00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
#include "copyright.h"
00033
#include "machine.h"
00034
#include "addrspace.h"
00035
#include "system.h"
00036
00037
00038
00039
00040
00041
unsigned int
00042 WordToHost(
unsigned int word) {
00043
#ifdef HOST_IS_BIG_ENDIAN
00044
register unsigned long result;
00045 result = (word >> 24) & 0x000000ff;
00046 result |= (word >> 8) & 0x0000ff00;
00047 result |= (word << 8) & 0x00ff0000;
00048 result |= (word << 24) & 0xff000000;
00049
return result;
00050
#else
00051
return word;
00052
#endif
00053 }
00054
00055
unsigned short
00056 ShortToHost(
unsigned short shortword) {
00057
#ifdef HOST_IS_BIG_ENDIAN
00058
register unsigned short result;
00059 result = (shortword << 8) & 0xff00;
00060 result |= (shortword >> 8) & 0x00ff;
00061
return result;
00062
#else
00063
return shortword;
00064
#endif
00065 }
00066
00067
unsigned int
00068 WordToMachine(
unsigned int word) {
return WordToHost(word); }
00069
00070
unsigned short
00071 ShortToMachine(
unsigned short shortword) {
return ShortToHost(shortword); }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
bool
00088 Machine::ReadMem(
int addr,
int size,
int *value)
00089 {
00090
int data;
00091
ExceptionType exception;
00092
int physicalAddress;
00093
00094
DEBUG(
'a',
"Reading VA 0x%x, size %d\n", addr, size);
00095
00096 exception =
Translate(addr, &physicalAddress, size,
FALSE);
00097
if (exception !=
NoException) {
00098 machine->RaiseException(exception, addr);
00099
return FALSE;
00100 }
00101
switch (size) {
00102
case 1:
00103 data = machine->mainMemory[physicalAddress];
00104 *value = data;
00105
break;
00106
00107
case 2:
00108 data = *(
unsigned short *) &machine->mainMemory[physicalAddress];
00109 *value =
ShortToHost(data);
00110
break;
00111
00112
case 4:
00113 data = *(
unsigned int *) &machine->mainMemory[physicalAddress];
00114 *value =
WordToHost(data);
00115
break;
00116
00117
default:
ASSERT(
FALSE);
00118 }
00119
00120
DEBUG(
'a',
"\tvalue read = %8.8x\n", *value);
00121
return (
TRUE);
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
bool
00138 Machine::WriteMem(
int addr,
int size,
int value)
00139 {
00140
ExceptionType exception;
00141
int physicalAddress;
00142
00143
DEBUG(
'a',
"Writing VA 0x%x, size %d, value 0x%x\n", addr, size, value);
00144
00145 exception =
Translate(addr, &physicalAddress, size,
TRUE);
00146
if (exception !=
NoException) {
00147 machine->RaiseException(exception, addr);
00148
return FALSE;
00149 }
00150
switch (size) {
00151
case 1:
00152 machine->mainMemory[physicalAddress] = (
unsigned char) (value & 0xff);
00153
break;
00154
00155
case 2:
00156 *(
unsigned short *) &machine->mainMemory[physicalAddress]
00157 =
ShortToMachine((
unsigned short) (value & 0xffff));
00158
break;
00159
00160
case 4:
00161 *(
unsigned int *) &machine->mainMemory[physicalAddress]
00162 =
WordToMachine((
unsigned int) value);
00163
break;
00164
00165
default:
ASSERT(
FALSE);
00166 }
00167
00168
return TRUE;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
ExceptionType
00187 Machine::Translate(
int virtAddr,
int* physAddr,
int size,
bool writing)
00188 {
00189
int i;
00190
unsigned int vpn, offset;
00191
TranslationEntry *entry;
00192
unsigned int pageFrame;
00193
00194
DEBUG(
'a',
"\tTranslate 0x%x, %s: ", virtAddr, writing ?
"write" :
"read");
00195
00196
00197
if (((size == 4) && (virtAddr & 0x3)) || ((size == 2) && (virtAddr & 0x1))){
00198
DEBUG(
'a',
"alignment problem at %d, size %d!\n", virtAddr, size);
00199
return AddressErrorException;
00200 }
00201
00202
00203
ASSERT(
tlb == NULL ||
pageTable == NULL);
00204
ASSERT(
tlb != NULL ||
pageTable != NULL);
00205
00206
00207
00208 vpn = (
unsigned) virtAddr /
PageSize;
00209 offset = (
unsigned) virtAddr %
PageSize;
00210
00211
if (
tlb == NULL) {
00212
if (vpn >=
pageTableSize) {
00213
DEBUG(
'a',
"virtual page # %d too large for page table size %d!\n",
00214 virtAddr,
pageTableSize);
00215
return AddressErrorException;
00216 }
else if (!
pageTable[vpn].
valid) {
00217
DEBUG(
'a',
"virtual page # %d too large for page table size %d!\n",
00218 virtAddr,
pageTableSize);
00219
return PageFaultException;
00220 }
00221 entry = &
pageTable[vpn];
00222 }
else {
00223
for (entry = NULL, i = 0; i <
TLBSize; i++)
00224
if (
tlb[i].
valid && (
tlb[i].
virtualPage == vpn)) {
00225 entry = &
tlb[i];
00226
break;
00227 }
00228
if (entry == NULL) {
00229
DEBUG(
'a',
"*** no valid TLB entry found for this virtual page!\n");
00230
return PageFaultException;
00231
00232
00233 }
00234 }
00235
00236
if (entry->
readOnly && writing) {
00237
DEBUG(
'a',
"%d mapped read-only at %d in TLB!\n", virtAddr, i);
00238
return ReadOnlyException;
00239 }
00240 pageFrame = entry->
physicalPage;
00241
00242
00243
00244
if (pageFrame >=
NumPhysPages) {
00245
DEBUG(
'a',
"*** frame %d > %d!\n", pageFrame,
NumPhysPages);
00246
return BusErrorException;
00247 }
00248 entry->
use =
TRUE;
00249
if (writing)
00250 entry->
dirty =
TRUE;
00251 *physAddr = pageFrame *
PageSize + offset;
00252
ASSERT((*physAddr >= 0) && ((*physAddr + size) <=
MemorySize));
00253
DEBUG(
'a',
"phys addr = 0x%x\n", *physAddr);
00254
return NoException;
00255 }