* libcurses++, libc++ and liblightOS++ are installed into the crosscompiler directory
[lightOS.git] / kernel / x86 / v86m.cpp
blobba466f5fa80aafedcb80a316c99fe4cb7e57fe92
1 /*
2 lightOS kernel
3 Copyright (C) 2007-2009 Jörg Pfähler
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <cstdint>
20 #include <kernel/log.hpp>
21 #include <kernel/x86/v86m.hpp>
22 #include <kernel/processor.hpp>
23 using namespace std;
24 using namespace kernel;
26 #ifdef _LIGHTOS_V86
27 void kernel::push16(uint32_t **Esp, uint16_t value)
29 uint16_t *stack = reinterpret_cast<uint16_t*>(*Esp);
30 *--stack = value;
31 *Esp = reinterpret_cast<uint32_t*>(stack);
33 uint16_t kernel::pop16(uint32_t **Esp)
35 uint16_t *stack = reinterpret_cast<uint16_t*>(*Esp);
36 uint16_t result = *stack;
37 *Esp = reinterpret_cast<uint32_t*>(stack);
38 return result;
40 void kernel::virtual_8086_monitor(interrupt_stackframe &frame)
42 uint8_t *Eip = reinterpret_cast<uint8_t*>((frame.cs << 4) + frame.eip);
43 uint32_t *Esp = reinterpret_cast<uint32_t*>((frame.ss << 4) + frame.esp);
44 uint16_t *Ivt = reinterpret_cast<uint16_t*>(0);
46 switch (*Eip)
48 case 0xCD: // INT n
50 ++Eip;
51 uint8_t Number = *Eip++;
53 // Stack large enough?
54 if (frame.esp < 6)
56 FATAL("virtual-8086-monitor: Int n: Stack not large enough\n");
57 FATAL("Halting System" << endl);
58 processor::halt();
61 if (Number == 0xEF)
63 asm volatile("int $0xEF");
66 // Push the EFLAGS
67 push16(&Esp, frame.eflags & 0xFFFF);
68 // Push CS
69 push16(&Esp, frame.cs);
70 // Push IP
71 push16(&Esp, reinterpret_cast<uintptr_t>(Eip));
73 // Get new CS:EIP from IVT
74 frame.cs = *(Ivt + 2 * Number + 1);
75 frame.eip = *(Ivt + 2 * Number);
76 }break;
77 case 0xCF: // IRET
79 // Stack large enough?
80 if (frame.esp > 0xFFFA)
82 FATAL("virtual-8086-monitor: IRET: Stack not large enough\n");
83 FATAL("Halting System" << endl);
84 processor::halt();
87 // Pop IP
88 frame.eip = pop16(&Esp);
89 // Pop CS
90 frame.cs = pop16(&Esp);
91 // Pop EFLAGS
92 frame.eflags = (frame.eflags & 0xFFFF0000) | pop16(&Esp) | 0x3202;
93 }break;
94 default:
96 FATAL("virtual-8086-monitor: Unknown instruction 0x" << hex << *Eip << '\n');
97 FATAL("Halting System" << endl);
98 processor::halt();
99 }break;
102 // Set ESP
103 frame.esp = reinterpret_cast<uintptr_t>(Esp) - (frame.ss << 4);
105 #endif