diff --git a/hal/paging.go b/hal/paging.go index 48e4ecc..ce38223 100644 --- a/hal/paging.go +++ b/hal/paging.go @@ -1,14 +1,25 @@ package hal +const PageSize = 1024 + +var defaultRegister uint16 = 0 + type Page struct { - Referenced bool - PageNumber uint16 + Referenced bool + RegisterAddress *uint16 } -type PageTable []*Page +// PageTable uses key as page number +type PageTable map[uint16]*Page type Address uint16 +type MMU struct { + PageTable *PageTable + LoadedPages []*Page + Registers []float64 // 4k registers +} + func (address Address) PageNumber() uint16 { return uint16(address) >> 10 } @@ -17,14 +28,55 @@ func (address Address) Offset() uint16 { return uint16(address) & 0x03FF } -func (table *PageTable) Find(address Address) { +func (table PageTable) Find(address Address) { // 10 bit for one register in a page // 6 bit to address the page // 000010 | 0000000011 // -> Page 2, offset 3 // Find the page with that number + page := table[address.PageNumber()] + + // Page not loaded in "physical" register + if page.RegisterAddress == nil { + // Page Error + // TODO: Logging + + } +} + +func (mmu *MMU) Load(page *Page) { + if len(mmu.LoadedPages) >= 4 { + for index, loadedPage := range mmu.LoadedPages { + if loadedPage.Referenced { + continue + } + loadedPage.RegisterAddress = nil + mmu.LoadedPages = append(mmu.LoadedPages[:index], mmu.LoadedPages[index+1:]...) + break + } + + // Everything is referenced, we need to remove one + if len(mmu.LoadedPages) == 4 { + mmu.LoadedPages = mmu.LoadedPages[:2] + } + } + + page.RegisterAddress = mmu.findEmptyRegisterAddress() + + mmu.LoadedPages = append(mmu.LoadedPages, page) +} + +func (mmu *MMU) findEmptyRegisterAddress() *uint16 { + var i uint16 + for i = 0; i < uint16(len(mmu.Registers)/PageSize); i++ { + for _, loadedPage := range mmu.LoadedPages { + if *loadedPage.RegisterAddress == i { + continue + } + return &i + } + } - // Check if it is already loaded - // Load it if not + return &defaultRegister }