From f256b901a12e219610ba32c63be492b124de782d Mon Sep 17 00:00:00 2001 From: OmniaX-dev Date: Tue, 2 Apr 2024 00:56:59 +0200 Subject: [PATCH] Implemented ExtAlu CPU extension + Bios logo --- .vscode/c_cpp_properties.json | 4 +- CMakeLists.txt | 2 +- build.nr | 2 +- extra/config/testMachine.dvm | 4 +- extra/dragon info/DragonVM Information Sheet | 10 +- extra/dragon info/todo.txt | 9 +- extra/dragon/bios.bin | Bin 4096 -> 4096 bytes extra/dragon/cmos.dr | Bin 128 -> 128 bytes extra/dss/bios/data.dss | 41 +++- extra/dss/bios/drivers.dss | 9 + extra/dss/bios/entry.dss | 149 ++++++++++-- extra/dss/bios/logo_screen.dss | 109 +++++++++ extra/dss/bios/utils.dss | 32 +-- extra/dss/newTest.dss | 27 ++- extra/make_and_debug | 2 +- extra/make_and_run | 2 +- extra/scripts/bios_flash | 2 +- src/assembler/Assembler.cpp | 90 +++++++- src/debugger/Debugger.cpp | 15 +- src/gui/RawTextRenderer.cpp | 3 + src/gui/RawTextRenderer.hpp | 2 + src/hardware/CPUExtensions.cpp | 226 +++++++++++++++++++ src/hardware/CPUExtensions.hpp | 34 ++- src/hardware/VirtualCPU.cpp | 1 + src/hardware/VirtualCPU.hpp | 2 +- src/hardware/VirtualDisplay.cpp | 31 ++- src/hardware/VirtualDisplay.hpp | 1 + src/runtime/ConfigLoader.cpp | 21 ++ src/runtime/ConfigLoader.hpp | 2 + src/runtime/DragonRuntime.cpp | 49 ++-- src/runtime/DragonRuntime.hpp | 7 +- src/tools/GlobalData.hpp | 22 ++ 32 files changed, 807 insertions(+), 103 deletions(-) create mode 100644 extra/dss/bios/logo_screen.dss diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 006aa2e..0cf1531 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -9,7 +9,7 @@ "defines": [], "compilerPath": "/usr/bin/clang++", "cStandard": "c17", - "cppStandard": "c++20", + "cppStandard": "c++23", "intelliSenseMode": "linux-clang-x64" //"compileCommands": "${workspaceFolder}/compile_commands.json" }, @@ -22,7 +22,7 @@ "defines": [], "compilerPath": "C:\\msys64\\ucrt64\\bin\\clang++", "cStandard": "c17", - "cppStandard": "c++20", + "cppStandard": "c++23", "intelliSenseMode": "windows-clang-x64" //"compileCommands": "${workspaceFolder}/compile_commands.json" } diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f92fd1..7617fdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) cmake_minimum_required(VERSION 3.18) project(${PROJ_NAME} LANGUAGES C CXX) set(CMAKE_BUILD_TYPE Debug) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) file(STRINGS "./build.nr" BUILD_NUMBER) #----------------------------------------------------------------------------------------- diff --git a/build.nr b/build.nr index 8ba317e..d6d863f 100644 --- a/build.nr +++ b/build.nr @@ -1 +1 @@ -1589 +1590 diff --git a/extra/config/testMachine.dvm b/extra/config/testMachine.dvm index c3297a4..5886c4e 100644 --- a/extra/config/testMachine.dvm +++ b/extra/config/testMachine.dvm @@ -1,7 +1,9 @@ Disks = dragon/disk1.dr Bios = dragon/bios.bin CMOS = dragon/cmos.dr -cpuext = extmov +cpuext = extmov, extalu +fixed_clock = false +clock_rate_sec = 512 SingleColor_foreground = #009900FF SingleColor_background = #111111FF \ No newline at end of file diff --git a/extra/dragon info/DragonVM Information Sheet b/extra/dragon info/DragonVM Information Sheet index dabf942..41f9e30 100644 --- a/extra/dragon info/DragonVM Information Sheet +++ b/extra/dragon info/DragonVM Information Sheet @@ -7,7 +7,13 @@ 0x0FFF ------- 0x1000 CMOS (128 Bytes) (write to this section is only allowed in BIOS Mode) + MemStart: (2 bytes) 0x0000 + MemSize: (2 bytes) 0x0002 + ClockSpeed: (2 bytes) 0x0004 BootDisk: 0x0010 + + ICC_ + ICC_OutputAddr: (2 bytes) 0x007E 0x107F ------- 0x1080 INTERRUPT VECTOR (512 Bytes) @@ -90,7 +96,8 @@ 0xE0: Refresh Screen 0xE1: Clear Screen - 0x04: Text Single Color Character + 0x04: Text Single Color Character (1 Byte) + 0x05: Text Single Color Inverted colors (1 Byte) 0x16FF ------- 0x1700 GENERIC SERIAL INTERFACE (64 Bytes) @@ -125,6 +132,7 @@ BIOS Specific - Software Interrupts: 0x08: Print buffer and flush in Text Single Mode 0x09: Flush buffer in Text Single Mode 0x0A: Store Null-Terminated String in buffer in Text Single Mode (string address stored in R9 register) + 0x0B: Toggles inverted colors in Text Single Mode 0xE0: Refresh Screen 0xE1: Clear Screen diff --git a/extra/dragon info/todo.txt b/extra/dragon info/todo.txt index 1a0c678..5d81654 100644 --- a/extra/dragon info/todo.txt +++ b/extra/dragon info/todo.txt @@ -1,9 +1,8 @@ -Text visualization for hardware interrupts (in call-tree view) -Inverted Colors in Text-Single-Color -show where interrupts are disabled (in call-tree view) +#***Inverted Colors in Text-Single-Color +#***show where interrupts are disabled (in call-tree view) +#***Text visualization for hardware interrupts (in call-tree view) #***Add possibility to specify instruction sets in machine config -Add possibility to specify required instruction sets in dasm - +#***Add possibility to specify required instruction sets in dasm #***Add "Extended mov" instruction set #***Remove old offset mov #***Implelemnt extmov mnemonics in dasm: \ No newline at end of file diff --git a/extra/dragon/bios.bin b/extra/dragon/bios.bin index 61fa67b21c169581c8a7e3a5e405289337607fec..d220f3cd4697c4dfda21d4639462b4e358b0b42a 100644 GIT binary patch literal 4096 zcmeHIL2nyH6#mw`GcJ?M>^kcpB&12S>Lw-(0R;|4m7D?+s6uQowt6L@1&PwNrXUow z2e(yKD*gZ`&fK`c2~OPMzz>Ky^B0ovW_CSsLa6A8i$}?u@4b27``&v_e|8QH}9gl`t+wlrR>SGEGxBx|G~^y zH80yMwVrXcF0cGcg;Q3;BTeF#<^F(xCDm0nXSG}%&&pjm?^)KMaBm~(S(jO+mA0i^ ztTvuyC!@jadkwVSaoC$Vnq}oVjYCChA)nQN!pU3bbjn7Hgj|Os&nfa=FVE?R%8jVw zp2~0g9({-P>bGaC8$RPA;92MU+bMV4GH9J8EoF|Y_tYt?iR&9PIl2qiAWfY2%5rnl zrEF%!KUgkvHk}*a%MjHbJLp+0?PAKWywuyT*FAWybI-C|NSAeEc0Y9Xh@i8ET$ebf z)dZW%OH$isUoOz{2{b{iSJ+wR&y!d-k7Vju=SffOkP>xvUdFLW>*@cMuU1f9Kr#eM z9-b`AX>?b1D3Cgc7Bg-g_RB2<)@h;YOip6nG11qMCi)35(XR-q z=(pAMUeZri)B9vs(g$Si{jj+oHTUC0r4vy4ZoHcmXbsqrbqJ#Nj%;zZg21pfvMRbfZLd!xll+jRe7v z;JQfY!FsKJvd)t+)d$688!g*JFyN|o!#TI9WeX6K({EHmM%QV{uqiolB`@GwmrHI={i#BJzN%2Zlw3ca{2&RP9IwHs72;+XJWV2;psPH_9rkLiB|=} zSn!vHoWvogz^<@ev%g{yj=13~z?wLz_;YIleetZ|Ln(j}55}CnCJJozMa8chejS*u zaENIfVrw_-i=g7$?i)?~V&P4^q+U}io5`+$MifJEX4%O`ME?_UuGG*kDt(ebo{>|hpK~f$F2~lyziCct(pg=O#c7a23VxlN= zkLVE%9lQiDfM{_Zfd`1qtZfBq>OJXZ{(p9NZuISyh#$CTFJF)DKYBa>KPqbiCW6S! zeAzJPn3{wOG3LgiyU5rnc52aOC0J!ERY_uOUDj@1*33%DMfdq~5!px=z(9O^0pX2A znM{^eCk`KB9KHh%KOjo{+D?z+Jl;-^IbKVr9DP379#@^1ft>h+xf5S-UW%`sW+l#= zO0vwF6=JDawkhTX?_?ggbv)+Q;JT?o`tOT@Y^<&N$8LK027FTUTUpD9)8CeA({i?I z$-DdUo?va^TrMb{2 zKc1LdQbX-z4QSD_lv^!APS;5v7y^dc)PXnhA>VzS@yXrj@ literal 128 LcmZQz7+3%R0Du4i diff --git a/extra/dss/bios/data.dss b/extra/dss/bios/data.dss index 9e052e7..89f9b68 100644 --- a/extra/dss/bios/data.dss +++ b/extra/dss/bios/data.dss @@ -13,6 +13,9 @@ @end @group CMOS_Settings + MEM_START { MemoryAddresses.CMOS + 0x0000 } + MEM_SIZE { MemoryAddresses.CMOS + 0x0002 } + CLOCK_SPEED { MemoryAddresses.CMOS + 0x0004 } BOOT_DISK { MemoryAddresses.CMOS + 0x0010 } @end @@ -34,6 +37,7 @@ VIDEO_MODE { MemoryAddresses.VGA + 0x0000 } SIGNAL { MemoryAddresses.VGA + 0x0003 } TEXT_SINGLE_CHAR { MemoryAddresses.VGA + 0x0004 } + TEXT_SIGNLE_INVERT { MemoryAddresses.VGA + 0x0005 } BUFF_START { MemoryAddresses.VGA + 0x00E0 } @end @@ -73,6 +77,39 @@ ## =============================================================================================== .data - $_bios_name "DragonBIOS" $_bios_version_number_maj 0x00, 0x00 - $_bios_version_number_min 0x00, 0x03 \ No newline at end of file + $_bios_version_number_min 0x00, 0x03 + $_bios_name " DragonBIOS " + $_clock_str " Clock: " + $_mem_str " Memory: " + $_hz_str " Hz" + $_byte_str " Bytes" + + $_bios_logo_2_line_1 "|===================================================|" + $_bios_logo_2_line_2 "| '$$$o. |" + $_bios_logo_2_line_3 "| '$$$$bo... ..o: |" + $_bios_logo_2_line_4 "| '$$$$$$$$booocS$$$ .. ,. |" + $_bios_logo_2_line_5 "| '. '*$$$$SP V$o..o$$. .$$$b |" + $_bios_logo_2_line_6 "| '$$o. .$$$$$o. ...A$$$$$$$$$$$$$$b |" + $_bios_logo_2_line_7 "| ''bo. '*$$$$$$$$$$$$$$$$$$$$P*$$$$$$$$: |" + $_bios_logo_2_line_8 "| '$$. V$$$$$$$$$P'**''*'' VP * 'l |" + $_bios_logo_2_line_9 "| '$$$o.4$$$$$$$$X |" + $_bios_logo_2_line_10 "| '*$$$$$$$$$$$$$AoA$o..oooooo.. .b |" + $_bios_logo_2_line_11 "| .X$$$$$$$$$$$P'' ''*oo,, ,$P |" + $_bios_logo_2_line_12 "| $$P''V$$$$$$$: . ''*****' |" + $_bios_logo_2_line_13 "| .*' A$$$$$$$$o.4; . |" + $_bios_logo_2_line_14 "| .oP'' '$$$$$$b. .$; |" + $_bios_logo_2_line_15 "| A$$$$$$$$$$P |" + $_bios_logo_2_line_16 "| ' '$$$$$P' |" + $_bios_logo_2_line_17 "| $$P*' |" + $_bios_logo_2_line_18 "| .$' |" + $_bios_logo_2_line_19 "|===================================================|" + + ## $_bios_logo_line_1 " _____ ____ _____ ____ _____ " + ## $_bios_logo_line_2 " | __ \ | _ \_ _/ __ \ / ____| " + ## $_bios_logo_line_3 " | | | |_ __ __ _ __ _ ___ _ __ | |_) || || | | | (___ " + ## $_bios_logo_line_4 " | | | | '__/ _` |/ _` |/ _ \| '_ \| _ < | || | | |\___ \ " + ## $_bios_logo_line_5 " | |__| | | | (_| | (_| | (_) | | | | |_) || || |__| |____) | " + ## $_bios_logo_line_6 " |_____/|_| \__,_|\__, |\___/|_| |_|____/_____\____/|_____/ " + ## $_bios_logo_line_7 " __/ | " + ## $_bios_logo_line_8 " |___/ " \ No newline at end of file diff --git a/extra/dss/bios/drivers.dss b/extra/dss/bios/drivers.dss index 1df8fef..0fba845 100644 --- a/extra/dss/bios/drivers.dss +++ b/extra/dss/bios/drivers.dss @@ -52,6 +52,7 @@ _int_30_handler: jeq $_int_30_print_buffer_and_flush_text_single, 0x0008 jeq $_int_30_flush_buffer_text_single, 0x0009 jeq $_int_30_store_string_text_single, 0x000A + jeq $_int_30_invert_colors_text_single, 0x000B jeq $_int_30_clear_screen, 0x00E0 jeq $_int_30_refresh_screen, 0x00E1 jmp $_int_30_end @@ -105,6 +106,14 @@ _int_30_store_string_text_single: movb ACC, *R9 jne $_int_30_store_string_text_single, 0 jmp $_int_30_end +_int_30_invert_colors_text_single: + movb ACC, [VGA_Registers.TEXT_SIGNLE_INVERT] + jne $_int_30_invert_colors_text_single_normal, 0 + movb [VGA_Registers.TEXT_SIGNLE_INVERT], 1 + jmp $_int_30_end +_int_30_invert_colors_text_single_normal: + movb [VGA_Registers.TEXT_SIGNLE_INVERT], 0 + jmp $_int_30_end _int_30_clear_screen: diff --git a/extra/dss/bios/entry.dss b/extra/dss/bios/entry.dss index 538c2c2..2f37e4c 100644 --- a/extra/dss/bios/entry.dss +++ b/extra/dss/bios/entry.dss @@ -14,23 +14,8 @@ mov R8, 0x30 ## -Passing the interrupt's code to setup int 0x20 ## -Calling int 0x20 with 0x00 as parameter, to set new handler up - mov R10, 0x03 - mov R9, $_bios_name - int 0x30 - mov R10, 0x01 - mov R9, 32 - int 0x30 - mov R10, 0x04 - mov R9, [$_bios_version_number_maj] - int 0x30 - mov R10, 0x01 - mov R9, 46 - int 0x30 - mov R10, 0x04 - mov R9, [$_bios_version_number_min] - int 0x30 - mov R10, 0x02 - int 0x30 + push 0 + call $_print_machine_info ## MBR Loading and FL, 0b1111111111111110 ## Disable interrupts @@ -49,4 +34,134 @@ @include @include +_print_machine_info: + + + mov R9, $_bios_logo_2_line_1 + mov R10, 0x0A + int 0x30 + + mov R10, 0x08 ## Print and flush buffer + int 0x30 + + mov R10, 0x02 + int 0x30 + + + + mov R9, $_bios_logo_2_line_2 + mov R10, 0x0A + int 0x30 + + mov R10, 0x08 ## Print and flush buffer + int 0x30 + + + + mov R10, 0x0A + mov R9, $_bios_name + int 0x30 ## Print BIOS Name + + mov R10, 0x05 + mov R9, [$_bios_version_number_maj] + int 0x30 ## Print BIOS Version (Major) + + mov R10, 0x06 + mov R9, 46 + int 0x30 ## Print '.' character + + mov R10, 0x05 + mov R9, [$_bios_version_number_min] + int 0x30 ## Print BIOS Version (Minor) + + mov R10, 0x02 + int 0x30 ## Print New Line + + + + + + + mov R9, $_bios_logo_2_line_3 + mov R10, 0x0A + int 0x30 + + mov R10, 0x08 ## Print and flush buffer + int 0x30 + + + + mov R10, 0x0A + mov R9, $_clock_str + int 0x30 ## Print Clock label + + mov R10, 0x05 + mov R9, [CMOS_Settings.CLOCK_SPEED] + int 0x30 ## Print Clock speed + + mov R10, 0x0A + mov R9, $_hz_str + int 0x30 ## Print hz label + + mov R10, 0x02 + int 0x30 ## Print New Line + + + + + + + mov R9, $_bios_logo_2_line_4 + mov R10, 0x0A + int 0x30 + + mov R10, 0x08 ## Print and flush buffer + int 0x30 + + + + mov R10, 0x0A + mov R9, $_mem_str + int 0x30 ## Print Memory label + + mov R10, 0x05 + mov R9, [CMOS_Settings.MEM_START] + int 0x30 ## Print Memory start + + mov R10, 0x06 + mov R9, 47 + int 0x30 ## Print '/' character + + mov R10, 0x05 + mov R9, [CMOS_Settings.MEM_SIZE] + int 0x30 ## Print Memory size + + mov R10, 0x0A + mov R9, $_byte_str + int 0x30 ## Print bytes label + + mov R10, 0x02 + int 0x30 ## Print New Line + + + + + + mov R9, $_bios_logo_2_line_5 + mov R7, 4 + mov ACC, 19 +_print_machine_info_logo_loop: + inc R7 + mov R10, 0x0A + int 0x30 + addip R9, 54 ## 90 is the length of a line + mov R10, 0x08 + int 0x30 + mov R10, 0x02 + int 0x30 + jls $_print_machine_info_logo_loop, R7 + + + ret + .fixed 4096, 0x00 ## BIOS Needs to be 4096 Bytes exactly diff --git a/extra/dss/bios/logo_screen.dss b/extra/dss/bios/logo_screen.dss new file mode 100644 index 0000000..105461c --- /dev/null +++ b/extra/dss/bios/logo_screen.dss @@ -0,0 +1,109 @@ +@guard _LOGO_SCREEN_DSS_ + +_print_logo_screen: + + mov R9, $_bios_logo_2_line_2 + mov R10, 0x0A + int 0x30 + + + + + mov R9, $_bios_logo_2_line_2 + mov R10, 0x0A + int 0x30 + + mov R10, 0x03 + mov R9, $_bios_name + int 0x30 ## Print BIOS Name + + mov R10, 0x04 + mov R9, [$_bios_version_number_maj] + int 0x30 ## Print BIOS Version (Major) + + mov R10, 0x01 + mov R9, 46 + int 0x30 ## Print '.' character + + mov R10, 0x04 + mov R9, [$_bios_version_number_min] + int 0x30 ## Print BIOS Version (Minor) + + mov R10, 0x02 + int 0x30 ## Print New Line + + + + + mov R9, $_bios_logo_2_line_3 + mov R10, 0x0A + int 0x30 + + mov R10, 0x03 + mov R9, $_clock_str + int 0x30 ## Print Clock label + + mov R10, 0x04 + mov R9, [CMOS_Settings.CLOCK_SPEED] + int 0x30 ## Print Clock speed + + mov R10, 0x03 + mov R9, $_hz_str + int 0x30 ## Print hz label + + mov R10, 0x02 + int 0x30 ## Print New Line + + + + + mov R9, $_bios_logo_2_line_4 + mov R10, 0x0A + int 0x30 + + mov R10, 0x03 + mov R9, $_mem_str + int 0x30 ## Print Memory label + + mov R10, 0x04 + mov R9, [CMOS_Settings.MEM_START] + int 0x30 ## Print Memory start + + mov R10, 0x01 + mov R9, 47 + int 0x30 ## Print '/' character + + mov R10, 0x04 + mov R9, [CMOS_Settings.MEM_SIZE] + int 0x30 ## Print Memory size + + mov R10, 0x03 + mov R9, $_byte_str + int 0x30 ## Print bytes label + + mov R10, 0x02 + int 0x30 ## Print New Line + + + + + mov R9, $_bios_logo_2_line_5 + mov R7, 4 + mov ACC, 19 + mov R10, 0x0B + int 0x30 +_print_machine_info_logo_loop: + inc R7 + mov R10, 0x0A + int 0x30 + addip R9, 54 ## 90 is the length of a line + mov R10, 0x08 + int 0x30 + mov R10, 0x02 + int 0x30 + debug_break + jls $_print_machine_info_logo_loop, R7 + mov R10, 0x0B + int 0x30 + + ret \ No newline at end of file diff --git a/extra/dss/bios/utils.dss b/extra/dss/bios/utils.dss index 8205ae0..957350d 100644 --- a/extra/dss/bios/utils.dss +++ b/extra/dss/bios/utils.dss @@ -45,46 +45,26 @@ _set_interrupt_vector_entry_end: _print_integer: mov R1, 0 arg ACC - mov R3, 0 ## Used as boolean, 0 = positive, 1 = negative - jle $_print_integer_not_negative, 0 - mov R3, 1 - jeq $_print_integer_overflow_case, 0x8000 - neg ACC - jmp $_print_integer_loop -_print_integer_overflow_case: ## Hardcoded for -32768 (0x8000) - push 56 - push 54 - push 55 - push 50 - push 51 - mov R1, 5 - jmp $_print_integer_loop_end -_print_integer_not_negative: + debug_break jne $_print_integer_loop, 0 push 48 ## '0' ASCII is 48 inc R1 jmp $_print_integer_loop_end _print_integer_loop: jeq $_print_integer_loop_end, 0 - div ACC, 10 - mov R2, ACC - add RV, 48 ## '0' ASCII is 48 - push ACC + divipu ACC, 10 + addipu RV, 48 + push RV inc R1 - mov ACC, R2 + debug_break jmp $_print_integer_loop _print_integer_loop_end: - mov ACC, R3 - jne $_print_integer_no_sign, 1 - push 45 ## '-' ASCII is 45 - inc R1 -_print_integer_no_sign: pop R9 dec R1 movb [VGA_Registers.TEXT_SINGLE_CHAR], R9 movb [VGA_Registers.SIGNAL], reg(S_REG_1) mov ACC, R1 - jne $_print_integer_no_sign, 0 + jne $_print_integer_loop_end, 0 ret diff --git a/extra/dss/newTest.dss b/extra/dss/newTest.dss index bb601c9..6c5f800 100644 --- a/extra/dss/newTest.dss +++ b/extra/dss/newTest.dss @@ -10,19 +10,30 @@ $string "Hello World!!" .code + mov R10, 0x00 mov R9, $_text_entered_handler mov R8, 0xA2 - int 0x20 + int 0x20 ## Enable text entered handler + mov R10, 0x00 mov R9, $_key_pressed_handler mov R8, 0xA0 - int 0x20 + int 0x20 ## Enable key pressed handler + + mov R10, 0x0B + int 0x30 ## Invert colors - mov R10, 0x01 mov R9, 62 - int 0x30 + int 0x30 ## Print first prompt char + + mov R10, 0x0B + int 0x30 ## Invert colors + + mov R10, 0x01 + mov R9, 32 + int 0x30 ## Print space mov R1, 0 ## Zero the counter @@ -59,7 +70,6 @@ no_clear_screen: jmp $infinite_loop ## jump to the beginning of infinite loop hlt - _text_entered_handler: mov R9, [0x1282] mov R10, 0x01 @@ -72,9 +82,16 @@ _key_pressed_handler: jne $_key_pressed_handler_end, 13 mov R10, 0x02 int 0x30 + mov R10, 0x0B + int 0x30 ## Invert colors mov R10, 0x01 mov R9, 62 int 0x30 + mov R10, 0x0B + int 0x30 ## Invert colors + mov R10, 0x01 + mov R9, 32 + int 0x30 jmp $_key_pressed_handler_end _key_pressed_handler_backspace: debug_break diff --git a/extra/make_and_debug b/extra/make_and_debug index 1d753dc..3cd9d86 100755 --- a/extra/make_and_debug +++ b/extra/make_and_debug @@ -17,7 +17,7 @@ if [ $? -eq 0 ]; then /bin/bash ./load_mbr cd .. printf "${green}Compiling Test Program...\n" - ./dasm dss/newTest.dss -o newTest.bin --extmov --save-disassembly disassembly/newTest.dds --verbose + ./dasm dss/newTest.dss -o newTest.bin --extmov --extalu --save-disassembly disassembly/newTest.dds --verbose printf "\n${green}Running Application...\n\n${clear}" ./ddb config/testMachine.dvm --force-load newTest.bin 0x00 --verbose-load cp dragon/disk1.dr ../extra/dragon/disk1.dr diff --git a/extra/make_and_run b/extra/make_and_run index ac569a3..fd22f20 100755 --- a/extra/make_and_run +++ b/extra/make_and_run @@ -17,7 +17,7 @@ if [ $? -eq 0 ]; then /bin/bash ./load_mbr cd .. printf "${green}Compiling Test Program...\n" - ./dasm dss/newTest.dss -o newTest.bin --extmov --save-disassembly disassembly/newTest.dds --verbose + ./dasm dss/newTest.dss -o newTest.bin --extmov --extalu --save-disassembly disassembly/newTest.dds --verbose printf "\n${green}Running Application...\n\n${clear}" ./dvm config/testMachine.dvm --force-load newTest.bin 0x00 cp dragon/disk1.dr ../extra/dragon/disk1.dr diff --git a/extra/scripts/bios_flash b/extra/scripts/bios_flash index ceb6cc2..f11cb3f 100644 --- a/extra/scripts/bios_flash +++ b/extra/scripts/bios_flash @@ -6,5 +6,5 @@ clear='\033[0m' printf "${green}Reloading BIOS...\n${clear}" cd .. cp ../extra/dss/bios/* ./dss/bios/ -./dasm dss/bios/entry.dss -o dragon/bios.bin --save-disassembly disassembly/bios.dds --verbose --save-exports +./dasm dss/bios/entry.dss -o dragon/bios.bin --extalu --save-disassembly disassembly/bios.dds --verbose --save-exports cp dragon/bios.bin ../extra/dragon/bios.bin diff --git a/src/assembler/Assembler.cpp b/src/assembler/Assembler.cpp index 50d91fb..d0825eb 100644 --- a/src/assembler/Assembler.cpp +++ b/src/assembler/Assembler.cpp @@ -150,6 +150,8 @@ namespace dragon } else if (edit == "--extmov") args.cpu_extensions.push_back("extmov"); + else if (edit == "--extalu") + args.cpu_extensions.push_back("extalu"); else if (edit == "--verbose") args.verbose = true; else if (edit == "--save-exports") @@ -178,7 +180,10 @@ namespace dragon out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Used to save any specified exports in the code.").reset().nl(); tmpCommand = "--extmov"; tmpCommand.addRightPadding(commandLength); - out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Enables the CPU extension.").reset().nl(); + out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Enables mnemonics for the CPU extension.").reset().nl(); + tmpCommand = "--extalu"; + tmpCommand.addRightPadding(commandLength); + out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Enables mnemonics for the CPU extension.").reset().nl(); tmpCommand = "--help"; tmpCommand.addRightPadding(commandLength); out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Displays this help message.").reset().nl(); @@ -1303,6 +1308,64 @@ namespace dragon opEdit.trim(); int16_t word = 0x0000; auto st = opEdit.tokenize(","); + if (STDVEC_CONTAINS(cpuExtensions, "extalu")) + { + auto st = opEdit.tokenize(","); + if (instEdit == "addipu" || instEdit == "subipu" || instEdit == "mulipu" || instEdit == "divipu" || instEdit == "addip" || instEdit == "subip" || instEdit == "mulip" || instEdit == "divip") + { + m_code.push_back(data::OpCodes::Ext02); + m_code.push_back(0x00); + eOperandType opType = parseOperand(st.next(), word); + if (opType != eOperandType::Register) + { + std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n"; + exit(0); + return; + } + m_code.push_back((uint8_t)word); + opType = parseOperand(st.next(), word); + + if (opType == eOperandType::Immediate) + { + if (instEdit == "addip") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::addip_imm_in_reg; + else if (instEdit == "subip") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::subip_imm_in_reg; + else if (instEdit == "mulip") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::mulip_imm_in_reg; + else if (instEdit == "divip") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::divip_imm_in_reg; + else if (instEdit == "addipu") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::addipu_imm_in_reg; + else if (instEdit == "subipu") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::subipu_imm_in_reg; + else if (instEdit == "mulipu") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::mulipu_imm_in_reg; + else if (instEdit == "divipu") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::divipu_imm_in_reg; + m_code.push_back((uint8_t)((word & 0xFF00) >> 8)); + m_code.push_back((uint8_t)(word & 0x00FF)); + } + else if (opType == eOperandType::Register) + { + if (instEdit == "addip") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::addip_reg_in_reg; + else if (instEdit == "subip") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::subip_reg_in_reg; + else if (instEdit == "mulip") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::mulip_reg_in_reg; + else if (instEdit == "divip") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::divip_reg_in_reg; + else if (instEdit == "addipu") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::addipu_reg_in_reg; + else if (instEdit == "subipu") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::subipu_reg_in_reg; + else if (instEdit == "mulipu") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::mulipu_reg_in_reg; + else if (instEdit == "divipu") m_code[m_code.size() - 2] = hw::cpuext::ExtAlu::OpCodes::divipu_reg_in_reg; + m_code.push_back((uint8_t)word); + } + else + { + std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Immediate or register required\n"; + exit(0); + return; + } + return; + } + } + else if (instEdit == "addipu" || instEdit == "subipu" || instEdit == "mulipu" || instEdit == "divipu" || instEdit == "addip" || instEdit == "subip" || instEdit == "mulip" || instEdit == "divip") + { + std::cout << "ExtAlu instruction detected, please add '--extalu' flag to dasm.\n"; + exit(0); + return; + } + if (instEdit == "mov") { m_code.push_back(0x00); @@ -1634,10 +1697,10 @@ namespace dragon int16_t word2 = 0x0000; int16_t word3 = 0x0000; auto st = opEdit.tokenize(","); - m_code.push_back(data::OpCodes::Ext01); - m_code.push_back(0x00); if (instEdit == "omov") { + m_code.push_back(data::OpCodes::Ext01); + m_code.push_back(0x00); if (st.count() != 3) { std::cout << "Invalid operand number; " << line << "3 -> 3 required\n"; @@ -1793,6 +1856,8 @@ namespace dragon } else if (instEdit == "omovb") { + m_code.push_back(data::OpCodes::Ext01); + m_code.push_back(0x00); if (st.count() != 3) { std::cout << "Invalid operand number; " << line << "3 -> 3 required\n"; @@ -1946,6 +2011,8 @@ namespace dragon } else if (instEdit == "movo") { + m_code.push_back(data::OpCodes::Ext01); + m_code.push_back(0x00); if (st.count() != 3) { std::cout << "Invalid operand number; " << line << "3 -> 3 required\n"; @@ -2097,6 +2164,8 @@ namespace dragon } else if (instEdit == "movbo") { + m_code.push_back(data::OpCodes::Ext01); + m_code.push_back(0x00); if (st.count() != 3) { std::cout << "Invalid operand number; " << line << "3 -> 3 required\n"; @@ -2246,16 +2315,13 @@ namespace dragon return; } } - else - { - std::cout << "Unknown instruction; " << line << " (" << instEdit << ")\n"; - exit(0); - } + return; } else if (instEdit == "omov" || instEdit == "omovb" || instEdit == "movo" || instEdit == "movbo") { std::cout << "ExtMov instruction detected, please add '--extmov' flag to dasm.\n"; exit(0); + return; } } @@ -2271,11 +2337,15 @@ namespace dragon m_disassembly.insert(m_disassembly.begin(), { (uint16_t)(m_loadAddress + 3), "[----------DATA_SECTION----------]" }); m_disassembly.insert(m_disassembly.begin(), { m_loadAddress, ostd::String("jmp ").add(ostd::Utils::getHexStr(entryAddr, true, 2)) }); for (auto& d : m_symbolTable) + { symbols.push_back(d.second); + for (int32_t i = 0; i < d.second.bytes.size(); i++) + newCode.push_back(0x00); + } for (int32_t i = symbols.size() - 1; i >= 0; i--) { - for (auto& dd : symbols[i].bytes) - newCode.push_back(dd); + for (int32_t j = 0; j < symbols[i].bytes.size(); j++) + newCode[symbols[i].address - m_loadAddress + j] = symbols[i].bytes[j]; } for (auto& b : m_code) newCode.push_back(b); diff --git a/src/debugger/Debugger.cpp b/src/debugger/Debugger.cpp index 820676f..aaa9200 100644 --- a/src/debugger/Debugger.cpp +++ b/src/debugger/Debugger.cpp @@ -1038,10 +1038,13 @@ namespace dragon auto& callStack = minfo.callStack; int32_t level = -1; ostd::String ch_ang_u = ""; - ch_ang_u.addChar((unsigned char)218); + //TODO: Find a fix for the UTF characters + ch_ang_u.add("┌"); + // ch_ang_u.addChar((unsigned char)218); ostd::String ch_ang_l = "|"; ostd::String ch_ang_d = ""; - ch_ang_d.addChar((unsigned char)192); + ch_ang_d.add("└"); + // ch_ang_d.addChar((unsigned char)192); for (auto& call : callStack) { ostd::String call_info = call.info.new_trim().toLower(); @@ -1056,7 +1059,7 @@ namespace dragon } else if (call_info == "hw int") { - call_str = ch_ang_u + "hwi " + ostd::Utils::getHexStr(call.addr, true, 1); + call_str = ch_ang_u + "hwi " + ostd::Utils::getHexStr(call.addr, true, 1) + " (" + data::InterruptCodes::getInterruptName(call.addr) + ")"; level++; } else if (call_info == "ret") @@ -1095,7 +1098,11 @@ namespace dragon rgx.fg("\\$\\w+", "Green"); //Labels out.fg(ostd::ConsoleColors::BrightGray).p("|").reset(); - out.fg(ostd::ConsoleColors::Magenta).p(ostd::Utils::getHexStr(call.inst_addr, true, 2)); + if (call.interrupts_disabled) + out.fg(ostd::ConsoleColors::BrightGray); + else + out.fg(ostd::ConsoleColors::Magenta); + out.p(ostd::Utils::getHexStr(call.inst_addr, true, 2)); out.fg(ostd::ConsoleColors::BrightGray).p("| > ").reset(); out.pStyled(rgx).nl().reset(); diff --git a/src/gui/RawTextRenderer.cpp b/src/gui/RawTextRenderer.cpp index 34992e3..d1d3787 100644 --- a/src/gui/RawTextRenderer.cpp +++ b/src/gui/RawTextRenderer.cpp @@ -25,6 +25,9 @@ namespace dragon drawCharacter((uint8_t*)screenPixels, screenWidth, screenHeight, (uint8_t*)fontPixels, x, y, c, color, background); x += FONT_CHAR_W; } + s_cursor_pos_x = x; + if (s_cursor_pos_x >= CONSOLE_CHARS_H) + s_cursor_pos_x = 0; return true; } diff --git a/src/gui/RawTextRenderer.hpp b/src/gui/RawTextRenderer.hpp index 9b0fc7d..88b07e2 100644 --- a/src/gui/RawTextRenderer.hpp +++ b/src/gui/RawTextRenderer.hpp @@ -26,5 +26,7 @@ namespace dragon inline static constexpr int32_t FONT_H_CHARS = 16; inline static constexpr int32_t CONSOLE_CHARS_H = 90; inline static constexpr int32_t CONSOLE_CHARS_V = 21; + + inline static int8_t s_cursor_pos_x = 0; }; } \ No newline at end of file diff --git a/src/hardware/CPUExtensions.cpp b/src/hardware/CPUExtensions.cpp index fb09b03..6d3961f 100644 --- a/src/hardware/CPUExtensions.cpp +++ b/src/hardware/CPUExtensions.cpp @@ -464,6 +464,232 @@ namespace dragon return true; } + + + + ostd::String ExtAlu::getOpCodeString(uint8_t opCode) + { + switch (opCode) + { + case OpCodes::addipu_reg_in_reg: return m_name + "_addipu_reg_in_reg"; + case OpCodes::addipu_imm_in_reg: return m_name + "_addipu_imm_in_reg"; + case OpCodes::subipu_reg_in_reg: return m_name + "_subipu_reg_in_reg"; + case OpCodes::subipu_imm_in_reg: return m_name + "_subipu_imm_in_reg"; + case OpCodes::mulipu_reg_in_reg: return m_name + "_mulipu_reg_in_reg"; + case OpCodes::mulipu_imm_in_reg: return m_name + "_mulipu_imm_in_reg"; + case OpCodes::divipu_reg_in_reg: return m_name + "_divipu_reg_in_reg"; + case OpCodes::divipu_imm_in_reg: return m_name + "_divipu_imm_in_reg"; + case OpCodes::addip_reg_in_reg: return m_name + "_addip_reg_in_reg"; + case OpCodes::addip_imm_in_reg: return m_name + "_addip_imm_in_reg"; + case OpCodes::subip_reg_in_reg: return m_name + "_subip_reg_in_reg"; + case OpCodes::subip_imm_in_reg: return m_name + "_subip_imm_in_reg"; + case OpCodes::mulip_reg_in_reg: return m_name + "_mulip_reg_in_reg"; + case OpCodes::mulip_imm_in_reg: return m_name + "_mulip_imm_in_reg"; + case OpCodes::divip_reg_in_reg: return m_name + "_divip_reg_in_reg"; + case OpCodes::divip_imm_in_reg: return m_name + "_divip_imm_in_reg"; + default: return m_name + "_UNKNOWN_INST"; + } + } + + uint8_t ExtAlu::getInstructionSIze(uint8_t opCode) + { + switch (opCode) + { + case OpCodes::addipu_reg_in_reg: return 3; + case OpCodes::addipu_imm_in_reg: return 4; + case OpCodes::subipu_reg_in_reg: return 3; + case OpCodes::subipu_imm_in_reg: return 4; + case OpCodes::mulipu_reg_in_reg: return 3; + case OpCodes::mulipu_imm_in_reg: return 4; + case OpCodes::divipu_reg_in_reg: return 3; + case OpCodes::divipu_imm_in_reg: return 4; + case OpCodes::addip_reg_in_reg: return 3; + case OpCodes::addip_imm_in_reg: return 4; + case OpCodes::subip_reg_in_reg: return 3; + case OpCodes::subip_imm_in_reg: return 4; + case OpCodes::mulip_reg_in_reg: return 3; + case OpCodes::mulip_imm_in_reg: return 4; + case OpCodes::divip_reg_in_reg: return 3; + case OpCodes::divip_imm_in_reg: return 4; + default: return 0; + } + } + + bool ExtAlu::execute(VirtualCPU& vcpu) + { + auto& mem = DragonRuntime::memMap; + uint8_t inst = vcpu.fetch8(); + switch (inst) + { + case OpCodes::addipu_reg_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint8_t src_reg = vcpu.fetch8(); + uint16_t dest_val = vcpu.readRegister(dest_reg); + uint16_t src_val = vcpu.readRegister(src_reg); + uint16_t res = dest_val + src_val; + vcpu.writeRegister16(dest_reg, (int16_t)res); + } + break; + case OpCodes::addipu_imm_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint16_t src_val = vcpu.fetch16(); + uint16_t dest_val = vcpu.readRegister(dest_reg); + uint16_t res = dest_val + src_val; + vcpu.writeRegister16(dest_reg, (int16_t)res); + } + break; + case OpCodes::subipu_reg_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint8_t src_reg = vcpu.fetch8(); + uint16_t dest_val = vcpu.readRegister(dest_reg); + uint16_t src_val = vcpu.readRegister(src_reg); + uint16_t res = dest_val - src_val; + vcpu.writeRegister16(dest_reg, (int16_t)res); + } + break; + case OpCodes::subipu_imm_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint16_t src_val = vcpu.fetch16(); + uint16_t dest_val = vcpu.readRegister(dest_reg); + uint16_t res = dest_val - src_val; + vcpu.writeRegister16(dest_reg, (int16_t)res); + } + break; + case OpCodes::mulipu_reg_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint8_t src_reg = vcpu.fetch8(); + uint16_t dest_val = vcpu.readRegister(dest_reg); + uint16_t src_val = vcpu.readRegister(src_reg); + uint16_t res = dest_val * src_val; + vcpu.writeRegister16(dest_reg, (int16_t)res); + } + break; + case OpCodes::mulipu_imm_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint16_t src_val = vcpu.fetch16(); + uint16_t dest_val = vcpu.readRegister(dest_reg); + uint16_t res = dest_val * src_val; + vcpu.writeRegister16(dest_reg, (int16_t)res); + } + break; + case OpCodes::divipu_reg_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint8_t src_reg = vcpu.fetch8(); + uint16_t dest_val = vcpu.readRegister(dest_reg); + uint16_t src_val = vcpu.readRegister(src_reg); + uint16_t res = dest_val / src_val; + uint16_t rv = dest_val % src_val; + vcpu.writeRegister16(dest_reg, (int16_t)res); + vcpu.writeRegister16(data::Registers::RV, (int16_t)rv); + } + break; + case OpCodes::divipu_imm_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint16_t src_val = vcpu.fetch16(); + uint16_t dest_val = vcpu.readRegister(dest_reg); + uint16_t res = dest_val / src_val; + uint16_t rv = dest_val % src_val; + vcpu.writeRegister16(dest_reg, (int16_t)res); + vcpu.writeRegister16(data::Registers::RV, (int16_t)rv); + } + break; + case OpCodes::addip_reg_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint8_t src_reg = vcpu.fetch8(); + int16_t dest_val = vcpu.readRegister(dest_reg); + int16_t src_val = vcpu.readRegister(src_reg); + int16_t res = dest_val + src_val; + vcpu.writeRegister16(dest_reg, res); + } + break; + case OpCodes::addip_imm_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint16_t src_val = vcpu.fetch16(); + int16_t dest_val = vcpu.readRegister(dest_reg); + int16_t res = dest_val + src_val; + vcpu.writeRegister16(dest_reg, res); + } + break; + case OpCodes::subip_reg_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint8_t src_reg = vcpu.fetch8(); + int16_t dest_val = vcpu.readRegister(dest_reg); + int16_t src_val = vcpu.readRegister(src_reg); + int16_t res = dest_val - src_val; + vcpu.writeRegister16(dest_reg, res); + } + break; + case OpCodes::subip_imm_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint16_t src_val = vcpu.fetch16(); + int16_t dest_val = vcpu.readRegister(dest_reg); + int16_t res = dest_val - src_val; + vcpu.writeRegister16(dest_reg, res); + } + break; + case OpCodes::mulip_reg_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint8_t src_reg = vcpu.fetch8(); + int16_t dest_val = vcpu.readRegister(dest_reg); + int16_t src_val = vcpu.readRegister(src_reg); + int16_t res = dest_val * src_val; + vcpu.writeRegister16(dest_reg, res); + } + break; + case OpCodes::mulip_imm_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint16_t src_val = vcpu.fetch16(); + int16_t dest_val = vcpu.readRegister(dest_reg); + int16_t res = dest_val * src_val; + vcpu.writeRegister16(dest_reg, res); + } + break; + case OpCodes::divip_reg_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint8_t src_reg = vcpu.fetch8(); + int16_t dest_val = vcpu.readRegister(dest_reg); + int16_t src_val = vcpu.readRegister(src_reg); + int16_t res = dest_val / src_val; + int16_t rv = dest_val % src_val; + vcpu.writeRegister16(dest_reg, res); + vcpu.writeRegister16(data::Registers::RV, rv); + } + break; + case OpCodes::divip_imm_in_reg: + { + uint8_t dest_reg = vcpu.fetch8(); + uint16_t src_val = vcpu.fetch16(); + int16_t dest_val = vcpu.readRegister(dest_reg); + int16_t res = dest_val / src_val; + int16_t rv = dest_val % src_val; + vcpu.writeRegister16(dest_reg, res); + vcpu.writeRegister16(data::Registers::RV, rv); + } + break; + default: + { + //TODO: Error + return false; + } + } + return true; + } + } } } \ No newline at end of file diff --git a/src/hardware/CPUExtensions.hpp b/src/hardware/CPUExtensions.hpp index a386d5c..24cbb55 100644 --- a/src/hardware/CPUExtensions.hpp +++ b/src/hardware/CPUExtensions.hpp @@ -59,6 +59,38 @@ namespace dragon uint8_t getInstructionSIze(uint8_t opCode) override; bool execute(VirtualCPU& vcpu) override; }; - } + + class ExtAlu : public data::CPUExtension + { + public: class OpCodes + { + public: + inline static constexpr uint8_t addipu_reg_in_reg = 0x10; + inline static constexpr uint8_t addipu_imm_in_reg = 0x11; + inline static constexpr uint8_t subipu_reg_in_reg = 0x12; + inline static constexpr uint8_t subipu_imm_in_reg = 0x13; + inline static constexpr uint8_t mulipu_reg_in_reg = 0x14; + inline static constexpr uint8_t mulipu_imm_in_reg = 0x15; + inline static constexpr uint8_t divipu_reg_in_reg = 0x16; + inline static constexpr uint8_t divipu_imm_in_reg = 0x17; + + inline static constexpr uint8_t addip_reg_in_reg = 0x20; + inline static constexpr uint8_t addip_imm_in_reg = 0x21; + inline static constexpr uint8_t subip_reg_in_reg = 0x22; + inline static constexpr uint8_t subip_imm_in_reg = 0x23; + inline static constexpr uint8_t mulip_reg_in_reg = 0x24; + inline static constexpr uint8_t mulip_imm_in_reg = 0x25; + inline static constexpr uint8_t divip_reg_in_reg = 0x26; + inline static constexpr uint8_t divip_imm_in_reg = 0x27; + }; + public: + inline ExtAlu(void) : data::CPUExtension(data::OpCodes::Ext02, "extalu") { } + ostd::String getOpCodeString(uint8_t opCode) override; + uint8_t getInstructionSIze(uint8_t opCode) override; + bool execute(VirtualCPU& vcpu) override; + }; + } + + } } \ No newline at end of file diff --git a/src/hardware/VirtualCPU.cpp b/src/hardware/VirtualCPU.cpp index fe2f5e6..2424a66 100644 --- a/src/hardware/VirtualCPU.cpp +++ b/src/hardware/VirtualCPU.cpp @@ -174,6 +174,7 @@ namespace dragon interruptData.info = "HW INT"; interruptData.addr = intValue; interruptData.inst_addr = 0x0000; + interruptData.interrupts_disabled = !readFlag(data::Flags::InterruptsEnabled); ostd::SignalHandler::emitSignal(DragonRuntime::SignalListener::Signal_HardwareInterruptOccurred, ostd::tSignalPriority::RealTime, interruptData); } } diff --git a/src/hardware/VirtualCPU.hpp b/src/hardware/VirtualCPU.hpp index b21762a..c9d378c 100644 --- a/src/hardware/VirtualCPU.hpp +++ b/src/hardware/VirtualCPU.hpp @@ -20,7 +20,7 @@ namespace dragon int16_t readRegister(uint8_t reg); int16_t writeRegister16(uint8_t reg, int16_t value); int8_t writeRegister8(uint8_t reg, int8_t value); - //TODO: Implement writeRegister8 and writeRegister16 functions (maybe for readRegister aswell) + //TODO: Implement readRegister8 and readRegister16 functions int8_t fetch8(void); int16_t fetch16(void); diff --git a/src/hardware/VirtualDisplay.cpp b/src/hardware/VirtualDisplay.cpp index 31bee4f..5576b32 100644 --- a/src/hardware/VirtualDisplay.cpp +++ b/src/hardware/VirtualDisplay.cpp @@ -17,13 +17,22 @@ namespace dragon void VirtualDisplay::onRender(void) { auto& config = DragonRuntime::machine_config; + auto& mem = DragonRuntime::memMap; + uint16_t vga_addr = data::MemoryMapAddresses::VideoCardInterface_Start; + uint8_t invert_colors = mem.read8(vga_addr + tRegisters::TextSingleInvertColors); if (m_refreshScreen) { - m_renderer.clear(config.singleColor_background); + if (invert_colors == 0) + m_renderer.clear(config.singleColor_background); + else + m_renderer.clear(config.singleColor_foreground); for (int32_t i = 0; i < m_singleTextLines.size(); i++) { auto& line = m_singleTextLines[i]; - RawTextRenderer::drawString(line, 0, i, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground); + if (invert_colors == 0) + RawTextRenderer::drawString(line, 0, i, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground, config.singleColor_background); + else + RawTextRenderer::drawString(line, 0, i, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_background, config.singleColor_foreground); } m_refreshScreen = false; } @@ -82,10 +91,16 @@ namespace dragon void VirtualDisplay::single_text_add_char_to_line(char c) { auto& config = DragonRuntime::machine_config; + auto& mem = DragonRuntime::memMap; + uint16_t vga_addr = data::MemoryMapAddresses::VideoCardInterface_Start; + uint8_t invert_colors = mem.read8(vga_addr + tRegisters::TextSingleInvertColors); if (m_singleTextLines.size() == 0) { m_singleTextLines.push_back(ostd::String().addChar(c)); - RawTextRenderer::drawString(ostd::String().addChar(c), 0, 0, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground); + if (invert_colors == 0) + RawTextRenderer::drawString(ostd::String().addChar(c), 0, 0, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground, config.singleColor_background); + else + RawTextRenderer::drawString(ostd::String().addChar(c), 0, 0, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_background, config.singleColor_foreground); return; } auto& line = m_singleTextLines[m_singleTextLines.size() - 1]; @@ -97,12 +112,18 @@ namespace dragon { m_singleTextLines.push_back(ostd::String().addChar(c)); auto& line = m_singleTextLines[m_singleTextLines.size() - 1]; - RawTextRenderer::drawString(ostd::String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground); + if (invert_colors == 0) + RawTextRenderer::drawString(ostd::String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground, config.singleColor_background); + else + RawTextRenderer::drawString(ostd::String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_background, config.singleColor_foreground); } else { line.addChar(c); - RawTextRenderer::drawString(ostd::String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground); + if (invert_colors == 0) + RawTextRenderer::drawString(ostd::String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_foreground, config.singleColor_background); + else + RawTextRenderer::drawString(ostd::String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_fontPixels, config.singleColor_background, config.singleColor_foreground); } } else return; diff --git a/src/hardware/VirtualDisplay.hpp b/src/hardware/VirtualDisplay.hpp index c9599b6..093cc18 100644 --- a/src/hardware/VirtualDisplay.hpp +++ b/src/hardware/VirtualDisplay.hpp @@ -14,6 +14,7 @@ namespace dragon inline static constexpr uint8_t VideoMode = 0x00; inline static constexpr uint8_t Signal = 0x03; inline static constexpr uint8_t TextSingleCharacter = 0x04; + inline static constexpr uint8_t TextSingleInvertColors = 0x05; }; public: struct tVideoModeValues { diff --git a/src/runtime/ConfigLoader.cpp b/src/runtime/ConfigLoader.cpp index 4534d00..9e9e2bc 100644 --- a/src/runtime/ConfigLoader.cpp +++ b/src/runtime/ConfigLoader.cpp @@ -45,6 +45,10 @@ namespace dragon { config.cpuext_list[ext_nr++] = new hw::cpuext::ExtMov; } + else if (lineEdit == "extalu") + { + config.cpuext_list[ext_nr++] = new hw::cpuext::ExtAlu; + } else continue; //TODO: Warning } } @@ -68,6 +72,23 @@ namespace dragon lineEdit = tokens.next(); config.singleColor_background.set(lineEdit); } + else if (lineEdit == "clock_rate_sec") + { + lineEdit = tokens.next(); + lineEdit.trim().toLower(); + if (!lineEdit.isNumeric()) continue; //TODO: Error + config.clock_rate_sec = lineEdit.toInt(); + } + else if (lineEdit == "fixed_clock") + { + lineEdit = tokens.next(); + lineEdit.trim().toLower(); + if (lineEdit == "true") + config.fixed_clock = true; + else if (lineEdit == "false") + config.fixed_clock = false; + else continue; //TODO: Error + } else continue; //TODO: Warning } return validate_machine_config(config); diff --git a/src/runtime/ConfigLoader.hpp b/src/runtime/ConfigLoader.hpp index 1935b2e..f9a8ad8 100644 --- a/src/runtime/ConfigLoader.hpp +++ b/src/runtime/ConfigLoader.hpp @@ -10,6 +10,8 @@ namespace dragon { std::map vdisk_paths; std::map cpuext_list; + int32_t clock_rate_sec { 500 }; + bool fixed_clock { true }; ostd::String bios_path; ostd::String cmos_path; ostd::Color singleColor_background; diff --git a/src/runtime/DragonRuntime.cpp b/src/runtime/DragonRuntime.cpp index 01de622..ea4a1a1 100644 --- a/src/runtime/DragonRuntime.cpp +++ b/src/runtime/DragonRuntime.cpp @@ -280,14 +280,8 @@ namespace dragon } memMap.mapDevice(ram, dragon::data::MemoryMapAddresses::Memory_Start, dragon::data::MemoryMapAddresses::Memory_End, false, "RAM"); - //Default VideoBios Colors - uint8_t default_bios_video_color = 0x4; if (verbose) - { out.fg(ostd::ConsoleColors::Magenta).p(" Initializing vCPU reset sequence:").nl(); - // out.p(" BIOSVideo default colors: ").p(ostd::Utils::getHexStr(default_bios_video_color).cpp_str()).nl(); - } - // memMap.write8(dragon::data::MemoryMapAddresses::BIOSVideo_Start, default_bios_video_color); uint16_t reset_ip_addr = 0x0000; if (verbose) @@ -314,6 +308,21 @@ namespace dragon } } + if (verbose) + { + out.fg(ostd::ConsoleColors::BrightYellow).p(" Fixed clock enabled: ").p(STR_BOOL(machine_config.fixed_clock)).nl(); + if (machine_config.fixed_clock) + out.fg(ostd::ConsoleColors::BrightYellow).p(" Clock speed: ").p(machine_config.clock_rate_sec).p(" Hz").nl(); + } + + vCMOS.write16(data::CMOSRegisters::MemoryStart, data::MemoryMapAddresses::Memory_Start); + vCMOS.write16(data::CMOSRegisters::MemorySize, data::MemoryMapAddresses::Memory_End); + vCMOS.write16(data::CMOSRegisters::ClockSpeed, machine_config.clock_rate_sec); + if (verbose) + out.fg(ostd::ConsoleColors::BrightYellow).p(" Loading CMOS Machine info").nl(); + + + out.nl().nl(); s_trackMachineInfo = trackMachineInfoDiff; s_trackCallStack = trackCallStack; @@ -327,10 +336,14 @@ namespace dragon void DragonRuntime::runMachine(void) { - double clock_speed_us = 2000; + double clock_speed_us = 1000000.0 / machine_config.clock_rate_sec; double acc = 0; + uint64_t avg_count = 0; + uint64_t _time = 0; + double avg_tot = 0; ostd::Timer clock_timer; bool running = true; + bool fixed_clock = machine_config.fixed_clock; while (running || vDiskInterface.isBusy()) { clock_timer.startCount(ostd::eTimeUnits::Microseconds); @@ -346,15 +359,17 @@ namespace dragon processErrors(); break; } - uint64_t _time = clock_timer.endCount(); - if (_time < clock_speed_us) - ostd::Utils::sleep(clock_speed_us - _time, ostd::eTimeUnits::Microseconds); - acc++; if (acc == 500) { - std::cout << _time << "\n"; + avg_count++; + avg_tot += _time; + s_avgInstTime = (uint64_t)std::round(avg_tot / avg_count); acc = 0; } + _time = clock_timer.endCount(); + acc++; + if (_time < clock_speed_us && fixed_clock) + ostd::Utils::sleep(clock_speed_us - _time, ostd::eTimeUnits::Microseconds); } } @@ -485,26 +500,26 @@ namespace dragon if (inst == data::OpCodes::CallImm) { uint16_t call_addr = memMap.read16(instAddr + 1); - minfo.callStack.push_back({ "CALL IMM", call_addr, instAddr }); + minfo.callStack.push_back({ "CALL IMM", call_addr, instAddr, !interrupts_enabled }); } else if (inst == data::OpCodes::CallReg) { uint8_t reg_addr = memMap.read8(instAddr + 1); uint16_t call_addr = cpu.readRegister(reg_addr); - minfo.callStack.push_back({ "CALL REG", call_addr, instAddr }); + minfo.callStack.push_back({ "CALL REG", call_addr, instAddr, !interrupts_enabled }); } else if (interrupts_enabled && inst == data::OpCodes::Int) { uint8_t int_num = memMap.read8(instAddr + 1); - minfo.callStack.push_back({ "INT", int_num, instAddr }); + minfo.callStack.push_back({ "INT", int_num, instAddr, !interrupts_enabled }); } else if (inst == data::OpCodes::Ret) { - minfo.callStack.push_back({ "RET", 0x0000, instAddr }); + minfo.callStack.push_back({ "RET", 0x0000, instAddr, !interrupts_enabled }); } else if (interrupts_enabled && inst == data::OpCodes::RetInt) { - minfo.callStack.push_back({ "RET INT", 0x0000, instAddr }); + minfo.callStack.push_back({ "RET INT", 0x0000, instAddr, !interrupts_enabled }); } } diff --git a/src/runtime/DragonRuntime.hpp b/src/runtime/DragonRuntime.hpp index ea95ed1..5b6e229 100644 --- a/src/runtime/DragonRuntime.hpp +++ b/src/runtime/DragonRuntime.hpp @@ -30,10 +30,11 @@ namespace dragon public: struct tCallInfo : public ostd::BaseObject { inline tCallInfo(void) { } - inline tCallInfo(const ostd::String& _info, uint16_t _addr, uint16_t _inst_addr) : info(_info), addr(_addr), inst_addr(_inst_addr) { } + inline tCallInfo(const ostd::String& _info, uint16_t _addr, uint16_t _inst_addr, bool ints_disabled) : info(_info), addr(_addr), inst_addr(_inst_addr), interrupts_disabled(ints_disabled) { } ostd::String info; uint16_t addr; uint16_t inst_addr; + bool interrupts_disabled; }; public: struct tCommandLineArgs { @@ -101,6 +102,7 @@ namespace dragon inline static const tMachineDebugInfo& getMachineInfoDiff(void) { return s_machineInfo; } inline static bool hasError(void) { return data::ErrorHandler::hasError(); } inline static ostd::ConsoleOutputHandler& output(void) { return out; } + inline static uint64_t getAvgClockSpeed(void) { return (uint64_t)std::round(1000000.0 / s_avgInstTime); } private: static void __get_machine_footprint(tMachineDebugInfo* machineInfo, std::vector trackedAddresses, bool previous); @@ -129,12 +131,15 @@ namespace dragon inline static tMachineConfig machine_config; + inline static uint64_t s_avgInstTime { 0 }; + private: inline static tMachineDebugInfo s_machineInfo; inline static bool s_trackMachineInfo { false }; inline static bool s_trackCallStack { false }; inline static SignalListener s_signalListener; + public: inline static const int32_t RETURN_VAL_CLOSE_DEBUGGER = 128; inline static const int32_t RETURN_VAL_CLOSE_RUNTIME = 256; diff --git a/src/tools/GlobalData.hpp b/src/tools/GlobalData.hpp index f2175c4..29bacb7 100644 --- a/src/tools/GlobalData.hpp +++ b/src/tools/GlobalData.hpp @@ -194,6 +194,28 @@ namespace dragon inline static constexpr uint8_t KeyPressed = 0xA0; inline static constexpr uint8_t KeyReleased = 0xA1; inline static constexpr uint8_t TextEntered = 0xA2; + + inline static ostd::String getInterruptName(uint8_t code) + { + switch (code) + { + case DiskInterfaceFFinished: return "Disk_Interface_Finished"; + case KeyPressed: return "Key_Pressed"; + case KeyReleased: return "Key_Released"; + case TextEntered: return "Text_Entered"; + default: return "UNKNOWN"; + } + return "UNKNOWN"; + } + }; + + class CMOSRegisters + { + public: + inline static constexpr uint8_t MemoryStart = 0x00; + inline static constexpr uint8_t MemorySize = 0x02; + inline static constexpr uint8_t ClockSpeed = 0x04; + inline static constexpr uint8_t BootDisk = 0x10; }; class CPUExtension