1 /* 2 * sys-emu - A system emulator for tutorials 3 * Copyright (C) 2018 - 2019 osdevelopment-info 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Affero General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Affero General Public License for more details. 14 * 15 * You should have received a copy of the GNU Affero General Public License 16 * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 */ 18 package info.osdevelopment.sysemu.processor 19 20 import info.osdevelopment.sysemu.memory.Memory 21 import scala.util.Try 22 23 /** 24 * An abstract class defining a processor in a system. 25 * @param descriptor the descriptor of the processor. 26 */ 27 abstract class Processor (val descriptor: ProcessorDescriptor) { 28 29 val name: String = descriptor.name 30 val maxMemory: Long = descriptor.maxMemory 31 val romName: String = descriptor.romName 32 33 /** 34 * The memory map of the processor. 35 */ 36 val memoryMap: collection.mutable.Map[Long, Memory] = collection.mutable.Map[Long, Memory]() 37 38 /** 39 * Adds a memory area to this processor. The memory has a base address (the lowest address handled by this 40 * processor). 41 * @param baseAddress the base address of the memory to add 42 * @param memory the memory to add 43 */ 44 def addMemory(baseAddress: Long, memory: Memory): Unit = { 45 memoryMap.foreach(address => { 46 val startAddress = address._1 47 val endAddress = startAddress + address._2.size 48 if (baseAddress >= startAddress & baseAddress < endAddress) 49 throw new IllegalMemoryLayoutException("Memory overlaps") 50 if (baseAddress + memory.size >= startAddress & baseAddress + memory.size < endAddress) 51 throw new IllegalMemoryLayoutException("Memory overlaps") 52 if (baseAddress <= startAddress & baseAddress + memory.size >= endAddress) 53 throw new IllegalMemoryLayoutException("Memory overlaps") 54 }) 55 if (baseAddress + memory.size > maxMemory) throw new IllegalMemoryLayoutException("Memory exceeds max memory") 56 memoryMap += baseAddress -> memory 57 } 58 59 /** 60 * All registers of all cores when the cores are stopped. 61 * 62 * The result is Success if the cores can return the registers. When Failure is returned then the cores 63 * cannot return the registers at the moment, e.g. because any is running at the moment. 64 * 65 * The key of the map is the register name. 66 * 67 * @return A Try containing a Map with the core as key and a Map with the register name as key and the register as 68 * value. 69 */ 70 def registers: Try[Map[Int, Map[String, Register]]] 71 72 /** 73 * All registers of a core when the core is stopped. 74 * 75 * The result is Success if the core can return the registers. When Failure is returned then the core 76 * cannot return the registers at the moment, e.g. because it is running at the moment. 77 * 78 * The key of the map is the register name. 79 * 80 * @param core the core for which the registers should be queried 81 * @return A Try containing a Map with the register name as key and the register as value. 82 */ 83 def registers(core: Int): Try[Map[String, Register]] 84 85 /** 86 * Return the register with the given name of the given core, e.g. "AX" or "D1". 87 * 88 * @param core the core for which the register should be returned 89 * @param name the name of the register to return 90 * @return the register named by name. Failure if the register does not exist or cannot be returned. 91 */ 92 def register(core: Int, name: String): Try[Register] 93 94 /** 95 * Sets the register of the processor to the given content. 96 * 97 * The returned register (in case of Success(_)) contains the new register content. Failure is returned in case that 98 * - the processor is running and therefore the register cannot be set 99 * - the register is unknown to the processor 100 * - the value of the register is invalid 101 * 102 * @param register the register to set 103 * @return Success with the new register value or Failure if the register cannot be set. 104 */ 105 def register(register: Register): Try[Register] 106 107 /** 108 * Calculates the start address for a ROM/BIOS based on the size. The start address may be constant or dynamic 109 * depending on the size (e.g. for x86). The start address is not necessarily the start address for the processor. 110 * The start address is None if the ROM/BIOS is too large for the processor. 111 * @return the start address for the ROM/BIOS depending on the architecture 112 */ 113 def calculateRomStart(romSize: Long): Option[Long] 114 115 /** 116 * Resets the processor and starts it new. 117 */ 118 def reset(): Unit 119 120 /** 121 * Do a single step of the processor (normally execute the next instruction). 122 */ 123 def step(): Unit 124 125 }
Line | Stmt Id | Pos | Tree | Symbol | Code |
---|---|---|---|---|---|
29 | 286 | 1093 - 1108 | Select | info.osdevelopment.sysemu.processor.ProcessorDescriptor.name | Processor.this.descriptor.name |
30 | 287 | 1133 - 1153 | Select | info.osdevelopment.sysemu.processor.ProcessorDescriptor.maxMemory | Processor.this.descriptor.maxMemory |
31 | 288 | 1178 - 1196 | Select | info.osdevelopment.sysemu.processor.ProcessorDescriptor.romName | Processor.this.descriptor.romName |
36 | 289 | 1306 - 1344 | Apply | scala.collection.MapFactory.Delegate.apply | scala.collection.mutable.Map.apply[Long, info.osdevelopment.sysemu.memory.Memory]() |
45 | 312 | 1653 - 2219 | Apply | scala.collection.IterableOnceOps.foreach | Processor.this.memoryMap.foreach[Unit](((address: (Long, info.osdevelopment.sysemu.memory.Memory)) => { val startAddress: Long = address._1; val endAddress: Long = startAddress.+(address._2.size); if (baseAddress.>=(startAddress).&(baseAddress.<(endAddress))) throw new IllegalMemoryLayoutException("Memory overlaps") else (); if (baseAddress.+(memory.size).>=(startAddress).&(baseAddress.+(memory.size).<(endAddress))) throw new IllegalMemoryLayoutException("Memory overlaps") else (); if (baseAddress.<=(startAddress).&(baseAddress.+(memory.size).>=(endAddress))) throw new IllegalMemoryLayoutException("Memory overlaps") else () })) |
46 | 290 | 1709 - 1719 | Select | scala.Tuple2._1 | address._1 |
47 | 292 | 1743 - 1773 | Apply | scala.Long.+ | startAddress.+(address._2.size) |
47 | 291 | 1758 - 1773 | Select | info.osdevelopment.sysemu.memory.Memory.size | address._2.size |
48 | 298 | 1780 - 1780 | Block | <nosymbol> | () |
48 | 294 | 1784 - 1838 | Apply | scala.Boolean.& | baseAddress.>=(startAddress).&(baseAddress.<(endAddress)) |
48 | 297 | 1780 - 1780 | Literal | <nosymbol> | () |
48 | 293 | 1814 - 1838 | Apply | scala.Long.< | baseAddress.<(endAddress) |
49 | 295 | 1848 - 1905 | Throw | <nosymbol> | throw new IllegalMemoryLayoutException("Memory overlaps") |
49 | 296 | 1848 - 1905 | Block | <nosymbol> | throw new IllegalMemoryLayoutException("Memory overlaps") |
50 | 304 | 1912 - 1912 | Literal | <nosymbol> | () |
50 | 301 | 1916 - 1998 | Apply | scala.Boolean.& | baseAddress.+(memory.size).>=(startAddress).&(baseAddress.+(memory.size).<(endAddress)) |
50 | 300 | 1960 - 1998 | Apply | scala.Long.< | baseAddress.+(memory.size).<(endAddress) |
50 | 299 | 1930 - 1941 | Select | info.osdevelopment.sysemu.memory.Memory.size | memory.size |
50 | 305 | 1912 - 1912 | Block | <nosymbol> | () |
51 | 303 | 2008 - 2065 | Block | <nosymbol> | throw new IllegalMemoryLayoutException("Memory overlaps") |
51 | 302 | 2008 - 2065 | Throw | <nosymbol> | throw new IllegalMemoryLayoutException("Memory overlaps") |
52 | 307 | 2076 - 2145 | Apply | scala.Boolean.& | baseAddress.<=(startAddress).&(baseAddress.+(memory.size).>=(endAddress)) |
52 | 310 | 2072 - 2072 | Literal | <nosymbol> | () |
52 | 306 | 2106 - 2145 | Apply | scala.Long.>= | baseAddress.+(memory.size).>=(endAddress) |
52 | 311 | 2072 - 2072 | Block | <nosymbol> | () |
53 | 309 | 2155 - 2212 | Block | <nosymbol> | throw new IllegalMemoryLayoutException("Memory overlaps") |
53 | 308 | 2155 - 2212 | Throw | <nosymbol> | throw new IllegalMemoryLayoutException("Memory overlaps") |
55 | 313 | 2242 - 2253 | Select | info.osdevelopment.sysemu.memory.Memory.size | memory.size |
55 | 316 | 2267 - 2334 | Throw | <nosymbol> | throw new IllegalMemoryLayoutException("Memory exceeds max memory") |
55 | 319 | 2224 - 2224 | Block | <nosymbol> | () |
55 | 318 | 2224 - 2224 | Literal | <nosymbol> | () |
55 | 315 | 2228 - 2265 | Apply | scala.Long.> | baseAddress.+(memory.size).>(Processor.this.maxMemory) |
55 | 317 | 2267 - 2334 | Block | <nosymbol> | throw new IllegalMemoryLayoutException("Memory exceeds max memory") |
55 | 314 | 2256 - 2265 | Select | info.osdevelopment.sysemu.processor.Processor.maxMemory | Processor.this.maxMemory |
56 | 322 | 2349 - 2349 | Literal | <nosymbol> | () |
56 | 321 | 2339 - 2373 | Apply | scala.collection.mutable.Growable.+= | Processor.this.memoryMap.+=(scala.Predef.ArrowAssoc[Long](baseAddress).->[info.osdevelopment.sysemu.memory.Memory](memory)) |
56 | 320 | 2352 - 2373 | Apply | scala.Predef.ArrowAssoc.-> | scala.Predef.ArrowAssoc[Long](baseAddress).->[info.osdevelopment.sysemu.memory.Memory](memory) |