// prepare and execute Interrupt 13 (Disk Interrupt) void runInt13(void) { // Initialize stack and data segment M.x86.R_SS = STACK_SEGMENT; M.x86.R_DS = DATA_SEGMENT; M.x86.R_SP = STACK_START_OFFSET; // push a HLT instruction and a pointer to it onto the stack // any return will pop the pointer and jump to the HLT, thus // exiting (more or less) cleanly push_word(0xf4f4); //F4=HLT //push_word(M.x86.R_SS); //push_word(M.x86.R_SP + 2); // setupInt will push the current CS and IP to the stack to return to it, // but we want to halt, so set CS:IP to the HLT instruction we just pushed // to the stack M.x86.R_CS = M.x86.R_SS; M.x86.R_IP = M.x86.R_SP; CHECK_DBG(DEBUG_TRACE_X86EMU) { X86EMU_trace_on(); } CHECK_DBG(DEBUG_JMP) { M.x86.debug |= DEBUG_TRACEJMP_REGS_F; M.x86.debug |= DEBUG_TRACEJMP_REGS_F; M.x86.debug |= DEBUG_TRACECALL_F; M.x86.debug |= DEBUG_TRACECALL_REGS_F; } setupInt(0x13); DEBUG_PRINTF_INTR("%s(): starting execution of INT13...\n", __func__); X86EMU_exec(); DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__); }
void setupRuntime() { HiddenClass::getRoot(); object_cls = new BoxedClass(NULL, 0, sizeof(Box), false); type_cls = new BoxedClass(object_cls, offsetof(BoxedClass, attrs), sizeof(BoxedClass), false); type_cls->cls = type_cls; object_cls->cls = type_cls; none_cls = new BoxedClass(object_cls, 0, sizeof(Box), false); None = new Box(&none_flavor, none_cls); str_cls = new BoxedClass(object_cls, 0, sizeof(BoxedString), false); // It wasn't safe to add __base__ attributes until object+type+str are set up, so do that now: type_cls->giveAttr("__base__", object_cls); str_cls->giveAttr("__base__", object_cls); none_cls->giveAttr("__base__", object_cls); object_cls->giveAttr("__base__", None); tuple_cls = new BoxedClass(object_cls, 0, sizeof(BoxedTuple), false); EmptyTuple = new BoxedTuple({}); gc::registerStaticRootObj(EmptyTuple); module_cls = new BoxedClass(object_cls, offsetof(BoxedModule, attrs), sizeof(BoxedModule), false); // TODO it'd be nice to be able to do these in the respective setupType methods, // but those setup methods probably want access to these objects. // We could have a multi-stage setup process, but that seems overkill for now. bool_cls = new BoxedClass(object_cls, 0, sizeof(BoxedBool), false); int_cls = new BoxedClass(object_cls, 0, sizeof(BoxedInt), false); float_cls = new BoxedClass(object_cls, 0, sizeof(BoxedFloat), false); function_cls = new BoxedClass(object_cls, offsetof(BoxedFunction, attrs), sizeof(BoxedFunction), false); instancemethod_cls = new BoxedClass(object_cls, 0, sizeof(BoxedInstanceMethod), false); list_cls = new BoxedClass(object_cls, 0, sizeof(BoxedList), false); slice_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSlice), false); dict_cls = new BoxedClass(object_cls, 0, sizeof(BoxedDict), false); file_cls = new BoxedClass(object_cls, 0, sizeof(BoxedFile), false); set_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSet), false); member_cls = new BoxedClass(object_cls, 0, sizeof(BoxedMemberDescriptor), false); STR = typeFromClass(str_cls); BOXED_INT = typeFromClass(int_cls); BOXED_FLOAT = typeFromClass(float_cls); BOXED_BOOL = typeFromClass(bool_cls); NONE = typeFromClass(none_cls); LIST = typeFromClass(list_cls); SLICE = typeFromClass(slice_cls); MODULE = typeFromClass(module_cls); DICT = typeFromClass(dict_cls); SET = typeFromClass(set_cls); BOXED_TUPLE = typeFromClass(tuple_cls); object_cls->giveAttr("__name__", boxStrConstant("object")); object_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)objectNew, UNKNOWN, 1, 0, true, false))); object_cls->freeze(); auto typeCallObj = boxRTFunction((void*)typeCall, UNKNOWN, 1, 0, true, false); typeCallObj->internal_callable = &typeCallInternal; type_cls->giveAttr("__call__", new BoxedFunction(typeCallObj)); type_cls->giveAttr("__name__", boxStrConstant("type")); type_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)typeNew, UNKNOWN, 2))); type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, STR, 1))); type_cls->giveAttr("__str__", type_cls->getattr("__repr__")); type_cls->freeze(); none_cls->giveAttr("__name__", boxStrConstant("NoneType")); none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, STR, 1))); none_cls->giveAttr("__str__", none_cls->getattr("__repr__")); none_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)noneHash, UNKNOWN, 1))); none_cls->freeze(); module_cls->giveAttr("__name__", boxStrConstant("module")); module_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)moduleRepr, STR, 1))); module_cls->giveAttr("__str__", module_cls->getattr("__repr__")); module_cls->freeze(); member_cls->giveAttr("__name__", boxStrConstant("member")); member_cls->freeze(); setupBool(); setupInt(); setupFloat(); setupStr(); setupList(); setupDict(); setupSet(); setupTuple(); setupFile(); function_cls->giveAttr("__name__", boxStrConstant("function")); function_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)functionRepr, STR, 1))); function_cls->giveAttr("__str__", function_cls->getattr("__repr__")); function_cls->freeze(); instancemethod_cls->giveAttr("__name__", boxStrConstant("instancemethod")); instancemethod_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)instancemethodRepr, STR, 1))); instancemethod_cls->freeze(); slice_cls->giveAttr("__name__", boxStrConstant("slice")); slice_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)sliceNew, UNKNOWN, 4, 2, false, false), { NULL, None })); slice_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)sliceRepr, STR, 1))); slice_cls->giveAttr("__str__", slice_cls->getattr("__repr__")); slice_cls->giveAttr("start", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_START_OFFSET)); slice_cls->giveAttr("stop", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_STOP_OFFSET)); slice_cls->giveAttr("step", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_STEP_OFFSET)); slice_cls->freeze(); // sys is the first module that needs to be set up, due to modules // being tracked in sys.modules: setupSys(); setupBuiltins(); setupMath(); setupTime(); setupThread(); setupCAPI(); TRACK_ALLOCATIONS = true; }
// handle int1a (PCI BIOS Interrupt) static void handleInt1a(void) { // function number in AX u8 bus, devfn, offs; struct device* dev; switch (M.x86.R_AX) { case 0xb101: // Installation check CLEAR_FLAG(F_CF); // clear CF M.x86.R_EDX = 0x20494350; // " ICP" endian swapped "PCI " M.x86.R_AL = 0x1; // Config Space Mechanism 1 supported M.x86.R_BX = 0x0210; // PCI Interface Level Version 2.10 M.x86.R_CL = 0xff; // number of last PCI Bus in system TODO: check! break; case 0xb102: // Find PCI Device // device_id in CX, vendor_id in DX // device index in SI (i.e. if multiple devices with same vendor/device id // are connected). We currently only support device index 0 // DEBUG_PRINTF_INTR("%s(): function: %x: PCI Find Device\n", __func__, M.x86.R_AX); /* FixME: support SI != 0 */ #if CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES dev = dev_find_device(M.x86.R_DX, M.x86.R_CX, 0); if (dev != 0) { DEBUG_PRINTF_INTR ("%s(): function %x: PCI Find Device --> 0x%04x\n", __func__, M.x86.R_AX, M.x86.R_BX); M.x86.R_BH = dev->bus->secondary; M.x86.R_BL = dev->path.pci.devfn; M.x86.R_AH = 0x00; // return code: success CLEAR_FLAG(F_CF); #else // only allow the device to find itself... if ((M.x86.R_CX == bios_device.pci_device_id) && (M.x86.R_DX == bios_device.pci_vendor_id) // device index must be 0 && (M.x86.R_SI == 0)) { CLEAR_FLAG(F_CF); M.x86.R_AH = 0x00; // return code: success M.x86.R_BH = bios_device.bus; M.x86.R_BL = bios_device.devfn; #endif } else { DEBUG_PRINTF_INTR ("%s(): function %x: invalid device/vendor/device index! (%04x/%04x/%02x expected: %04x/%04x/00) \n", __func__, M.x86.R_AX, M.x86.R_CX, M.x86.R_DX, M.x86.R_SI, bios_device.pci_device_id, bios_device.pci_vendor_id); SET_FLAG(F_CF); M.x86.R_AH = 0x86; // return code: device not found } break; case 0xb108: //read configuration byte case 0xb109: //read configuration word case 0xb10a: //read configuration dword bus = M.x86.R_BH; devfn = M.x86.R_BL; offs = M.x86.R_DI; DEBUG_PRINTF_INTR("%s(): function: %x: PCI Config Read from device: bus: %02x, devfn: %02x, offset: %02x\n", __func__, M.x86.R_AX, bus, devfn, offs); #if CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES dev = dev_find_slot(bus, devfn); DEBUG_PRINTF_INTR("%s(): function: %x: dev_find_slot() returned: %s\n", __func__, M.x86.R_AX, dev_path(dev)); if (dev == 0) { // fail accesses to non-existent devices... #else dev = bios_device.dev; if ((bus != bios_device.bus) || (devfn != bios_device.devfn)) { // fail accesses to any device but ours... #endif printf ("%s(): Config read access invalid device! bus: %02x (%02x), devfn: %02x (%02x), offs: %02x\n", __func__, bus, bios_device.bus, devfn, bios_device.devfn, offs); SET_FLAG(F_CF); M.x86.R_AH = 0x87; //return code: bad pci register HALT_SYS(); return; } else { switch (M.x86.R_AX) { case 0xb108: M.x86.R_CL = #if CONFIG_PCI_OPTION_ROM_RUN_YABEL pci_read_config8(dev, offs); #else (u8) rtas_pci_config_read(bios_device. puid, 1, bus, devfn, offs); #endif DEBUG_PRINTF_INTR ("%s(): function %x: PCI Config Read @%02x --> 0x%02x\n", __func__, M.x86.R_AX, offs, M.x86.R_CL); break; case 0xb109: M.x86.R_CX = #if CONFIG_PCI_OPTION_ROM_RUN_YABEL pci_read_config16(dev, offs); #else (u16) rtas_pci_config_read(bios_device. puid, 2, bus, devfn, offs); #endif DEBUG_PRINTF_INTR ("%s(): function %x: PCI Config Read @%02x --> 0x%04x\n", __func__, M.x86.R_AX, offs, M.x86.R_CX); break; case 0xb10a: M.x86.R_ECX = #if CONFIG_PCI_OPTION_ROM_RUN_YABEL pci_read_config32(dev, offs); #else (u32) rtas_pci_config_read(bios_device. puid, 4, bus, devfn, offs); #endif DEBUG_PRINTF_INTR ("%s(): function %x: PCI Config Read @%02x --> 0x%08x\n", __func__, M.x86.R_AX, offs, M.x86.R_ECX); break; } CLEAR_FLAG(F_CF); M.x86.R_AH = 0x0; // return code: success } break; case 0xb10b: //write configuration byte case 0xb10c: //write configuration word case 0xb10d: //write configuration dword bus = M.x86.R_BH; devfn = M.x86.R_BL; offs = M.x86.R_DI; if ((bus != bios_device.bus) || (devfn != bios_device.devfn)) { // fail accesses to any device but ours... printf ("%s(): Config read access invalid! bus: %x (%x), devfn: %x (%x), offs: %x\n", __func__, bus, bios_device.bus, devfn, bios_device.devfn, offs); SET_FLAG(F_CF); M.x86.R_AH = 0x87; //return code: bad pci register HALT_SYS(); return; } else { switch (M.x86.R_AX) { case 0xb10b: #if CONFIG_PCI_OPTION_ROM_RUN_YABEL pci_write_config8(bios_device.dev, offs, M.x86.R_CL); #else rtas_pci_config_write(bios_device.puid, 1, bus, devfn, offs, M.x86.R_CL); #endif DEBUG_PRINTF_INTR ("%s(): function %x: PCI Config Write @%02x <-- 0x%02x\n", __func__, M.x86.R_AX, offs, M.x86.R_CL); break; case 0xb10c: #if CONFIG_PCI_OPTION_ROM_RUN_YABEL pci_write_config16(bios_device.dev, offs, M.x86.R_CX); #else rtas_pci_config_write(bios_device.puid, 2, bus, devfn, offs, M.x86.R_CX); #endif DEBUG_PRINTF_INTR ("%s(): function %x: PCI Config Write @%02x <-- 0x%04x\n", __func__, M.x86.R_AX, offs, M.x86.R_CX); break; case 0xb10d: #if CONFIG_PCI_OPTION_ROM_RUN_YABEL pci_write_config32(bios_device.dev, offs, M.x86.R_ECX); #else rtas_pci_config_write(bios_device.puid, 4, bus, devfn, offs, M.x86.R_ECX); #endif DEBUG_PRINTF_INTR ("%s(): function %x: PCI Config Write @%02x <-- 0x%08x\n", __func__, M.x86.R_AX, offs, M.x86.R_ECX); break; } CLEAR_FLAG(F_CF); M.x86.R_AH = 0x0; // return code: success } break; default: printf("%s(): unknown function (%x) for int1a handler.\n", __func__, M.x86.R_AX); DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n", M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); HALT_SYS(); break; } } // main Interrupt Handler routine, should be registered as x86emu interrupt handler void handleInterrupt(int intNum) { u8 int_handled = 0; #ifndef DEBUG_PRINT_INT10 // this printf makes output by int 10 unreadable... // so we only enable it, if int10 print is disabled DEBUG_PRINTF_INTR("%s(%x)\n", __func__, intNum); #endif /* check wether this interrupt has a function pointer set in yabel_intFuncArray and run that */ if (yabel_intFuncArray[intNum]) { DEBUG_PRINTF_INTR("%s(%x) intHandler overridden, calling it...\n", __func__, intNum); int_handled = (*yabel_intFuncArray[intNum])(); } else { switch (intNum) { case 0x10: //BIOS video interrupt case 0x42: // INT 10h relocated by EGA/VGA BIOS case 0x6d: // INT 10h relocated by VGA BIOS // get interrupt vector from IDT (4 bytes per Interrupt starting at address 0 if ((my_rdl(intNum * 4) == 0xF000F065) || //F000:F065 is default BIOS interrupt handler address (my_rdl(intNum * 4) == 0xF4F4F4F4)) //invalid { #if 0 // ignore interrupt... DEBUG_PRINTF_INTR ("%s(%x): invalid interrupt Vector (%08x) found, interrupt ignored...\n", __func__, intNum, my_rdl(intNum * 4)); DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n", M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); //HALT_SYS(); #endif handleInt10(); int_handled = 1; } break; case 0x16: // Keyboard BIOS Interrupt handleInt16(); int_handled = 1; break; case 0x1a: // PCI BIOS Interrupt handleInt1a(); int_handled = 1; break; case PMM_INT_NUM: /* The self-defined PMM INT number, this is called by * the code in PMM struct, and it is handled by * pmm_handleInt() */ pmm_handleInt(); int_handled = 1; break; default: printf("Interrupt %#x (Vector: %x) not implemented\n", intNum, my_rdl(intNum * 4)); DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n", M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX); int_handled = 1; HALT_SYS(); break; } } // if we did not handle the interrupt, jump to the interrupt vector... if (!int_handled) { setupInt(intNum); } } // prepare and execute Interrupt 10 (VGA Interrupt) void runInt10(void) { // Initialize stack and data segment M.x86.R_SS = STACK_SEGMENT; M.x86.R_DS = DATA_SEGMENT; M.x86.R_SP = STACK_START_OFFSET; // push a HLT instruction and a pointer to it onto the stack // any return will pop the pointer and jump to the HLT, thus // exiting (more or less) cleanly push_word(0xf4f4); //F4=HLT //push_word(M.x86.R_SS); //push_word(M.x86.R_SP + 2); // setupInt will push the current CS and IP to the stack to return to it, // but we want to halt, so set CS:IP to the HLT instruction we just pushed // to the stack M.x86.R_CS = M.x86.R_SS; M.x86.R_IP = M.x86.R_SP; // + 4; CHECK_DBG(DEBUG_TRACE_X86EMU) { X86EMU_trace_on(); } CHECK_DBG(DEBUG_JMP) { M.x86.debug |= DEBUG_TRACEJMP_REGS_F; M.x86.debug |= DEBUG_TRACEJMP_REGS_F; M.x86.debug |= DEBUG_TRACECALL_F; M.x86.debug |= DEBUG_TRACECALL_REGS_F; } setupInt(0x10); DEBUG_PRINTF_INTR("%s(): starting execution of INT10...\n", __func__); X86EMU_exec(); DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__); }
void setupRuntime() { HiddenClass::getRoot(); type_cls = new BoxedClass(true, NULL); type_cls->cls = type_cls; none_cls = new BoxedClass(false, NULL); None = new Box(&none_flavor, none_cls); gc::registerStaticRootObj(None); module_cls = new BoxedClass(true, NULL); bool_cls = new BoxedClass(false, NULL); int_cls = new BoxedClass(false, NULL); float_cls = new BoxedClass(false, NULL); str_cls = new BoxedClass(false, (BoxedClass::Dtor)str_dtor); function_cls = new BoxedClass(true, NULL); instancemethod_cls = new BoxedClass(false, (BoxedClass::Dtor)instancemethod_dtor); list_cls = new BoxedClass(false, (BoxedClass::Dtor)list_dtor); slice_cls = new BoxedClass(true, NULL); dict_cls = new BoxedClass(false, (BoxedClass::Dtor)dict_dtor); tuple_cls = new BoxedClass(false, (BoxedClass::Dtor)tuple_dtor); file_cls = new BoxedClass(false, (BoxedClass::Dtor)file_dtor); STR = typeFromClass(str_cls); BOXED_INT = typeFromClass(int_cls); BOXED_FLOAT = typeFromClass(float_cls); BOXED_BOOL = typeFromClass(bool_cls); NONE = typeFromClass(none_cls); LIST = typeFromClass(list_cls); SLICE = typeFromClass(slice_cls); MODULE = typeFromClass(module_cls); DICT = typeFromClass(dict_cls); BOXED_TUPLE = typeFromClass(tuple_cls); type_cls->giveAttr("__name__", boxStrConstant("type")); type_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)typeCall, NULL, 1, true))); type_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)typeNew, NULL, 2, true))); type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, NULL, 1, true))); type_cls->setattr("__str__", type_cls->peekattr("__repr__"), NULL, NULL); type_cls->freeze(); none_cls->giveAttr("__name__", boxStrConstant("NoneType")); none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, NULL, 1, false))); none_cls->setattr("__str__", none_cls->peekattr("__repr__"), NULL, NULL); none_cls->freeze(); module_cls->giveAttr("__name__", boxStrConstant("module")); module_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)moduleRepr, NULL, 1, false))); module_cls->setattr("__str__", module_cls->peekattr("__repr__"), NULL, NULL); module_cls->freeze(); setupBool(); setupInt(); setupFloat(); setupStr(); setupList(); setupDict(); setupTuple(); setupFile(); function_cls->giveAttr("__name__", boxStrConstant("function")); function_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)functionRepr, NULL, 1, false))); function_cls->setattr("__str__", function_cls->peekattr("__repr__"), NULL, NULL); function_cls->freeze(); instancemethod_cls->giveAttr("__name__", boxStrConstant("instancemethod")); instancemethod_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)instancemethodRepr, NULL, 1, true))); instancemethod_cls->freeze(); slice_cls->giveAttr("__name__", boxStrConstant("slice")); slice_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)sliceRepr, NULL, 1, true))); slice_cls->setattr("__str__", slice_cls->peekattr("__repr__"), NULL, NULL); slice_cls->freeze(); setupMath(); gc::registerStaticRootObj(math_module); setupTime(); gc::registerStaticRootObj(time_module); setupBuiltins(); gc::registerStaticRootObj(builtins_module); setupCAPI(); TRACK_ALLOCATIONS = true; }