1 // 2 // Copyright (c) 2010-2025 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using Endianess = ELFSharp.ELF.Endianess; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Utilities.Binding; 11 using Antmicro.Renode.Exceptions; 12 using Antmicro.Renode.Peripherals.IRQControllers; 13 using System; 14 using System.Collections.Generic; 15 16 namespace Antmicro.Renode.Peripherals.CPU 17 { 18 [GPIO(NumberOfInputs = 1)] 19 public abstract class BaseX86 : TranslationCPU 20 { BaseX86(string cpuType, IMachine machine, LAPIC lapic, CpuBitness bitness)21 public BaseX86(string cpuType, IMachine machine, LAPIC lapic, CpuBitness bitness): base(cpuType, machine, Endianess.LittleEndian, bitness) 22 { 23 Lapic = lapic; 24 } 25 SetDescriptor(SegmentDescriptor descriptor, uint selector, uint baseAddress, uint limit, uint flags)26 public void SetDescriptor(SegmentDescriptor descriptor, uint selector, uint baseAddress, uint limit, uint flags) 27 { 28 switch(descriptor) 29 { 30 case SegmentDescriptor.CS: 31 TlibSetCsDescriptor(selector, baseAddress, limit, flags); 32 break; 33 default: 34 throw new RecoverableException($"Setting the {descriptor} descriptor is not implemented"); 35 } 36 } 37 38 public bool HltAsNop 39 { 40 get => neverWaitForInterrupt; 41 set 42 { 43 neverWaitForInterrupt = value; 44 } 45 } 46 47 public LAPIC Lapic { get; } 48 DecodeInterrupt(int number)49 protected override Interrupt DecodeInterrupt(int number) 50 { 51 if(number == 0) 52 { 53 return Interrupt.Hard; 54 } 55 throw InvalidInterruptNumberException; 56 } 57 GetExceptionDescription(ulong exceptionIndex)58 protected override string GetExceptionDescription(ulong exceptionIndex) 59 { 60 return ExceptionDescriptionsMap.TryGetValue(exceptionIndex, out var result) 61 ? result 62 : base.GetExceptionDescription(exceptionIndex); 63 } 64 65 [Export] ReadByteFromPort(uint address)66 private uint ReadByteFromPort(uint address) 67 { 68 return (uint)ReadByteFromBus(IoPortBaseAddress + address); 69 } 70 71 [Export] ReadWordFromPort(uint address)72 private uint ReadWordFromPort(uint address) 73 { 74 return (uint)ReadWordFromBus(IoPortBaseAddress + address); 75 } 76 77 [Export] ReadDoubleWordFromPort(uint address)78 private uint ReadDoubleWordFromPort(uint address) 79 { 80 return (uint)ReadDoubleWordFromBus(IoPortBaseAddress + address); 81 } 82 83 [Export] WriteByteToPort(uint address, uint value)84 private void WriteByteToPort(uint address, uint value) 85 { 86 WriteByteToBus(IoPortBaseAddress + address, value); 87 88 } 89 90 [Export] WriteWordToPort(uint address, uint value)91 private void WriteWordToPort(uint address, uint value) 92 { 93 WriteWordToBus(IoPortBaseAddress + address, value); 94 } 95 96 [Export] WriteDoubleWordToPort(uint address, uint value)97 private void WriteDoubleWordToPort(uint address, uint value) 98 { 99 WriteDoubleWordToBus(IoPortBaseAddress + address, value); 100 } 101 102 [Export] GetPendingInterrupt()103 private int GetPendingInterrupt() 104 { 105 return Lapic.GetPendingInterrupt(); 106 } 107 108 [Export] GetInstructionCount()109 private ulong GetInstructionCount() 110 { 111 return this.ExecutedInstructions; 112 } 113 114 // 649: Field '...' is never assigned to, and will always have its default value null 115 #pragma warning disable 649 116 117 [Import] 118 private Action<uint, uint, uint, uint> TlibSetCsDescriptor; 119 120 #pragma warning restore 649 121 122 private readonly Dictionary<ulong, string> ExceptionDescriptionsMap = new Dictionary<ulong, string> 123 { 124 {0, "Division by zero"}, 125 {1, "Single-step interrupt"}, 126 {2, "NMI"}, 127 {3, "Breakpoint"}, 128 {4, "Overflow"}, 129 {5, "Bounds"}, 130 {6, "Invalid Opcode"}, 131 {7, "Coprocessor not available"}, 132 {8, "Double Fault"}, 133 {9, "Coprocessor Segment Overrun"}, 134 {10, "Invalid Task State Segment"}, 135 {11, "Segment not present"}, 136 {12, "Stack Fault"}, 137 {13, "General protection fault"}, 138 {14, "Page Fault"}, 139 {16, "Math Fault"}, 140 {17, "Alignment Check"}, 141 {18, "Machine Check"}, 142 {256, "System call"} 143 }; 144 145 private const uint IoPortBaseAddress = 0xE0000000; 146 147 public enum SegmentDescriptor 148 { 149 CS, 150 SS, 151 DS, 152 ES, 153 FS, 154 GS 155 } 156 } 157 } 158