initial commit

This commit is contained in:
2025-06-26 23:46:22 +01:00
commit 373db68123
86 changed files with 18659 additions and 0 deletions
+224
View File
@@ -0,0 +1,224 @@
// a simple brainf##k interpreter,
// because I already wrote a compiler lol.
include print "./lib/io/print.dsa"
// "print hello world"
db program: "++++++++++++++++++++++++++++++++++++++++++++
>++++++++++++++++++++++++++++++++
>++++++++++++++++
>
>+
<<
[
>>
>
>++++++++++
<<
[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]
>[<+>-]
>[-]
>>
>++++++++++
<
[->-[>+>>]>[+[-<+>]>+>>]<<<<<]
>[-]
>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]
<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]
<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]
<<<<<<<.>.
>>[>>+<<-]
>[>+<<+>-]
>[<+>-]
<<<-
]
<<++..."
db error: "Invalid Instruction!"
dw stack: 0x10000
dw input: 0x30000
resb data: 1024
// set up a stack so we can call functions
_init_stack:
ldw stack, bpr
mov bpr, spr
start:
// load the start of the program into rg0
lwi program, rg0
lwi data, rg1
// rg0 is our instruction pointer
// rg1 is our data pointer
// rg2 is the value at the data pointer
// rg3 stores the current instruction
// rg4 is the expression nesting level.
lli 43, rg8 // + = 43 increment
lli 45, rg9 // - = 45 decrement
lli 62, rga // > = 62 increment pointer
lli 60, rgb // < = 60 decrement pointer
lli 46, rgc // . = 46 output
lli 44, rgd // , = 44 input
lli 91, rge // [ = 91 loop start
lli 93, rgf // ] = 93 loop end
loop_start:
// load the current instruction into rg3
ldb rg0, rg3
// switch on the instruction
// all cases will return to either loop_start or loop_end
cmp rg3, rg8
jeq increment
cmp rg3, rg9
jeq decrement
cmp rg3, rga
jeq inc_ptr
cmp rg3, rgb
jeq dec_ptr
cmp rg3, rgc
jeq output
cmp rg3, rgd
jeq input
cmp rg3, rge
jeq expr_start
cmp rg3, rgf
jeq expr_end
cmp rg3, zero
jeq end
// if we get here, we don't know what the instruction is
lwi error, rg2
pusha 2
push rg2
call print::print
pop zero
popa 2
end:
hlt
loop_end:
inc rg0
jmp loop_start
// ------------------------------------------
// increment the current cell
increment:
inc rg2
jmp loop_end
// ------------------------------------------
// decrement the current cell
decrement:
dec rg2
jmp loop_end
// ------------------------------------------
// increment the pointer
inc_ptr:
stw rg2, rg1
addi rg1, 4
ldw rg1, rg2
jmp loop_end
// ------------------------------------------
// decrement the pointer
dec_ptr:
stw rg2, rg1
subi rg1, 4
ldw rg1, rg2
jmp loop_end
// ------------------------------------------
// print the byte in the current cell
output:
pusha 2
push rg2
call print::print_byte
pop zero
popa 2
jmp loop_end
// ------------------------------------------
// read a byte into the current cell
input:
ldw input, rg2
jmp loop_end
// ------------------------------------------
// handle an open bracket instruction
expr_start:
cmp rg2, zero
jne loop_end
_traverse_right_start:
// push a register that definitely has a nonzero value
// when we pop this value from the stack
// we know we've finished traversing.
push rg8
_traverse_right:
inc rg0
ldb rg0, rg3
cmp rg3, rge
jeq open_right
cmp rg3, rgf
jeq close_right
cmp rg3, zero
jeq end
jmp _traverse_right
open_right:
// push zero to the stack
push zero
jmp _traverse_right
close_right:
// check if we've reached the bottom of the stack
pop rg4
cmp rg4, zero
jeq _traverse_right
// go to next instruction after closing bracket
inc rg0
jmp loop_start
// ------------------------------------------
// handle the close bracket instruction
expr_end:
cmp rg2, zero
jeq loop_end
_traverse_left_start:
push rg8
_traverse_left:
dec rg0
ldb rg0, rg3
cmp rg3, rge
jeq open_left
cmp rg3, rgf
jeq close_left
cmp rg3, zero
jeq end
jmp _traverse_left
open_left:
// check if we've reached the bottom of the stack
pop rg4
cmp rg4, zero
jeq _traverse_left
// go to next instruction after open bracket
inc rg0
jmp loop_start
close_left:
// push zero to the stack
push zero
jmp _traverse_left
+34
View File
@@ -0,0 +1,34 @@
include print "../io/print.dsa"
dw idt: 0xFFFF0000
setup_idt:
push bpr
mov spr, bpr
// load the IDT into the IDR
ldw idt, idr
mov bpr, spr
pop bpr
irt
setup_hard_fault_handler:
push bpr
mov spr, bpr
lwi handle_hard_fault, rg0
stw rg0, idr, 4
mov bpr, spr
pop bpr
irt
dw hard_fault_err: "FATAL: Illegal Instruction or Memory Access!"
handle_hard_fault:
call print::reset
lwi hard_fault_err, rg0
push rg0
call print::print
pop zero
hlt
+244
View File
@@ -0,0 +1,244 @@
// lib:
// print.dsa
// usage:
//
// include print "<relative path>""
//
// usage for print:
// push (register containing address of string)
// push pcx
// jmp print::print
//
// usage for reset:
// push pcx
// jmp print::reset
//
// usage for clear:
// push pcx
// jmp print::clear
//
// usage for print_byte:
// push (register containing byte)
// push pcx
// jmp print::print_byte
//
// usage for print_word:
// push (register containing word)
// push pcx
// jmp print::print_word
//
include maths "../maths/core.dsa"
dw display: 0x20000
dw current: 0x20000
// ------------------------------------------
// prints the string at addr(arg[0]) to the screen.
print:
push bpr
mov spr, bpr
ldw bpr, rg0, 8
ldw current, rg1
_print_loop:
ldb rg0, acc
stb acc, rg1
addi rg0, 1
addi rg1, 1
cmp acc, zero
jne _print_loop
jmp _end
// ------------------------------------------
// prints the value of arg[0] to the screen.
print_word:
// initialise
push bpr
mov spr, bpr
// load byte into acc
ldw bpr, rg0, 8
ldw current, rg1
addi rg1, 3
stb rg0, rg1
subi rg1, 1
shr rg0, 8
stb rg0, rg1
subi rg1, 1
shr rg0, 8
stb rg0, rg1
subi rg1, 1
shr rg0, 8
stb rg0, rg1
addi rg1, 4
jmp _end
// ------------------------------------------
// prints the last byte of arg[0] to the screen.
print_byte:
push bpr
mov spr, bpr
ldw bpr, rg0, 8
ldw current, rg1
stb rg0, rg1
addi rg1, 1
jmp _end
// ------------------------------------------
// prints the value of arg[0] to the screen in hex.
print_hex_word:
push bpr
mov spr, bpr
ldw current, rg1
ldb bpr, rg0, 8
push rg0
call _print_hex_byte
addi spr, 4
ldb bpr, rg0, 9
push rg0
call _print_hex_byte
addi spr, 4
ldb bpr, rg0, 10
push rg0
call _print_hex_byte
addi spr, 4
ldb bpr, rg0, 11
push rg0
call _print_hex_byte
addi spr, 4
jmp _end
// ------------------------------------------
// prints the last byte of arg[0] to the screen in hex.
print_hex_byte:
push bpr
mov spr, bpr
ldw bpr, rg0, 8
ldw current, rg1
call _print_hex_byte
jmp _end
// function body
_print_hex_byte:
// mask to get lower nibble
lli 0xF, rg2
// save rg0 state
push rg0
shr rg0, 4
and rg0, rg2, rg0
call _print_hex_nibble
pop rg0
and rg0, rg2, rg0
call _print_hex_nibble
return
// print a hex digit
_print_hex_nibble:
lli 10, rg3
cmp rg0, rg3
jlt _print_hex_nibble_number
addi rg0, 0x37, rg0
stb rg0, rg1
addi rg1, 1
return
// helper function.
_print_hex_nibble_number:
addi rg0, 0x30, rg0
stb rg0, rg1
addi rg1, 1
return
// ------------------------------------------
// print whitespace
print_whitespace:
push bpr
mov spr, bpr
ldw current, rg1
lli 0x20, rg0
stb rg0, rg1
addi rg1, 1
jmp _end
// ------------------------------------------
// print newline
print_newline:
push bpr
mov spr, bpr
// load variables into registers
ldw display, rg0
ldw current, rg1
// get the offset from the display base
sub rg1, rg0, rg0
lwi 80, rg2
pusha 3
push rg0
push rg2
call maths::divmod
pop zero // result
pop rg3 // remainder
popa 3
sub rg1, rg3, rg2
addi rg2, 80, rg1
// _end saves the display state
jmp _end
// ------------------------------------------
// resets the cursor position on the screen to 0x20000. (0,0)
reset:
push bpr
mov spr, bpr
ldw display, rg1
jmp _end
// ------------------------------------------
// clears the screen
clear:
push bpr
mov spr, bpr
// display size = 2000 bytes / 500 words
lli 500 rg0
ldw display, rg1
_clear_loop:
dec rg0
stw zero, rg1
addi rg1, 4
cmp rg0, zero
jgt _clear_loop
jmp _end
// ------------------------------------------
// return
_end:
stw rg1, current
mov bpr, spr
pop bpr
return
+60
View File
@@ -0,0 +1,60 @@
// multiply.dsa
// usage:
//
// include multiply "<relative path>"
//
// usage for multiply:
// push (arg1)
// push (arg0)
// call multiply::multiply
// pop (arg0)
// pop (arg1)
multiply:
push bpr
mov spr, bpr
ldw bpr, rg0, 8 // load op 2
ldw bpr, rg1, 12 // load op 1
_multiply_loop:
add rg2, rg0, rg2
dec rg1
cmp rg1, zero
jgt _multiply_loop
_multiply_end:
stw rg2, bpr, 8
mov bpr, spr
pop bpr
return
divmod:
push bpr
mov spr, bpr
ldw bpr, rg1, 8 // load op 2
ldw bpr, rg0, 12 // load op 1
lli 0, rg3
_divmod_loop:
cmp rg0, rg1
jlt _divmod_end
sub rg0, rg1, rg0
inc rg3
jmp _divmod_loop
_divmod_end:
// store div in first arg
// store mod in second arg
stw rg3, bpr, 8
stw rg0, bpr, 12
mov bpr, spr
pop bpr
return
+31
View File
@@ -0,0 +1,31 @@
include print "../io/print.dsa"
fib_n:
push bpr
mov spr, bpr
ldw bpr, rg0, 8 // load arg
mov rg1, rg2
lwi 1, rg1
start:
add rg1, rg2, rg3
pusha 4
push rg1
call print::print_hex_byte
call print::print_newline
pop zero
popa 4
mov rg2, rg1
mov rg3, rg2
dec rg0
cmp rg0, zero
jgt start
stw rg1, bpr, 8
mov bpr, spr
pop bpr
return
+80
View File
@@ -0,0 +1,80 @@
include fib: "./lib/maths/fib.dsa"
include maths: "./lib/maths/core.dsa"
include print: "./lib/io/print.dsa"
dw idt: 0xFFFF0000
dw stack: 0x10000
init:
// setup interrupt handlers
ldw idt, idr
lwi handle_hard_fault, rg0
stw rg0, idr, 4
// set up a stack.
ldw stack, bpr
mov bpr, spr
dw string: "hello world"
start:
lwi 37, rg0
lwi 12, rg1
push rg0
push rg1
call maths::divmod
pop rg0 // result
pop rg1 // remainder
push rg1
push rg0
call print::print_hex_byte
call print::print_whitespace
pop zero
call print::print_hex_byte
call print::print_newline
lwi string, rg0
//lwi 10, rg0
pusha 4
push rg0
call print::print
//call fib::fib_n
pop zero
call print::print_newline
popa 4
pusha 4
push rg0
call print::print
//call fib::fib_n
pop zero
call print::print_newline
popa 4
pusha 4
push rg0
call print::print
//call fib::fib_n
pop zero
call print::print_newline
popa 4
pusha 4
push rg0
call print::print
//call fib::fib_n
pop zero
call print::print_newline
popa 4
hlt
// fault handler in case we fail DSA.
dw hard_fault_err: "FATAL: Illegal Instruction or Memory Access!"
handle_hard_fault:
call print::clear
call print::reset
lwi hard_fault_err, rg0
push rg0
call print::print
pop zero
hlt
+80
View File
@@ -0,0 +1,80 @@
include print "./lib/io/print.dsa"
dw idt: 0xFFFF0000
dw stack: 0x10000
init:
// setup interrupt handlers
ldw idt, idr
lwi handle_hard_fault, rg0
stw rg0, idr, 4
// set up a stack.
ldw stack, bpr
mov bpr, spr
db string: "I won, the game!"
db hexbyte: 0xab
dw hexword: 0x1234abcd
db replace: "I lost"
start:
// test print string
lwi string, rg0
push rg0
call print::print
pop zero
// test print hex byte.
ldb hexbyte, rg0
push rg0
call print::print_hex_byte
pop zero
// test print hex word.
ldw hexword, rg0
push rg0
call print::print_hex_word
pop zero
// test print char
lli 0x40, rg0 // print @
push rg0
call print::print_byte
pop zero
// test newline
call print::print_newline
lwi string rg0
push rg0
call print::print
// test print word
lwi 0x31323334, rg0 // print 1234
push rg0
call print::print_word
pop zero
// test reset cursor pos
call print::reset
// test print string at reset pos
lwi replace, rg0
push rg0
call print::print
pop zero
hlt
// fault handler in case we fail DSA.
dw hard_fault_err: "FATAL: Illegal Instruction or Memory Access!"
handle_hard_fault:
call print::clear
call print::reset
lwi hard_fault_err, rg0
push rg0
call print::print
pop zero
hlt
Binary file not shown.
Binary file not shown.
+35
View File
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="http://schemas.android.com/apk/res/android"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dsa.emulator"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="35" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<!-- <uses-permission android:name="android.permission.INTERNET" /> -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:label="DSA Emulator"
android:icon="@mipmap/ic_launcher"
android:hasCode="false"
android:hardwareAccelerated="true">
<activity
android:name="android.app.NativeActivity"
android:label="DSA Emulator"
android:exported="true"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="unspecified"
android:launchMode="singleInstance">
<meta-data
android:name="android.app.lib_name"
android:value="dsa_rs" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env pwsh
$env:ANDROID_HOME = "C:\Users\jacob\AppData\Local\Android\Sdk"
$TOOL_PREFIX = "$env:ANDROID_HOME\build-tools\33.0.0"
# Only really works on Windows, for aarch64.
# Create directories
New-Item -ItemType Directory -Force -Path "..\target\apk_build\lib\arm64-v8a"
New-Item -ItemType Directory -Force -Path "..\target\apk_build\res\values"
New-Item -ItemType Directory -Force -Path "..\target\apk_build\res\mipmap-hdpi"
New-Item -ItemType Directory -Force -Path "..\target\apk_build\res\mipmap-mdpi"
New-Item -ItemType Directory -Force -Path "..\target\apk_build\res\mipmap-xhdpi"
New-Item -ItemType Directory -Force -Path "..\target\apk_build\res\mipmap-xxhdpi"
# Copy the shared library
Copy-Item "..\target\aarch64-linux-android\release\libdsa_rs.so" "..\target\apk_build\lib\arm64-v8a\"
# Copy the manifest
Copy-Item "..\resources\emulator\AndroidManifest.xml" "..\target\apk_build\AndroidManifest.xml"
# Copy the icons
Copy-Item "..\resources\emulator\AppIcon.png" "..\target\apk_build\res\mipmap-hdpi\ic_launcher.png"
Copy-Item "..\resources\emulator\AppIcon.png" "..\target\apk_build\res\mipmap-mdpi\ic_launcher.png"
Copy-Item "..\resources\emulator\AppIcon.png" "..\target\apk_build\res\mipmap-xhdpi\ic_launcher.png"
Copy-Item "..\resources\emulator\AppIcon.png" "..\target\apk_build\res\mipmap-xxhdpi\ic_launcher.png"
# Create strings.xml
@"
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">DSA Emulator</string>
</resources>
"@ | Out-File -FilePath "..\target\apk_build\res\values\strings.xml" -Encoding utf8
# Change to build directory
Push-Location "..\target\apk_build"
try {
# Compile resources
& "$TOOL_PREFIX\aapt2.exe" compile --dir res -o compiled_resources.zip
# Link resources
& "$TOOL_PREFIX\aapt2.exe" link -o unaligned.apk `
-I "$env:ANDROID_HOME\platforms\android-35\android.jar" `
--manifest AndroidManifest.xml `
compiled_resources.zip
# Add native libraries to APK
& "C:\Program Files\7-Zip\7z.exe" a -tzip unaligned.apk lib\*
# Align APK
& "$TOOL_PREFIX\zipalign.exe" -v 4 unaligned.apk aligned.apk
# Generate debug keystore if it doesn't exist
if (-not (Test-Path "debug.keystore")) {
& keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 -storepass android -keypass android -dname "CN=Android Debug,O=Android,C=US"
}
# Sign APK
& "$TOOL_PREFIX\apksigner.bat" sign --ks debug.keystore --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android --out dsa_emulator.apk aligned.apk
# Copy final APK
Copy-Item "dsa_emulator.apk" "..\dsa_emulator.apk"
Write-Host "APK created successfully at: ..\target\dsa_emulator.apk" -ForegroundColor Green
}
catch {
Write-Error "Build failed: $_"
}
finally {
# Return to original directory
Pop-Location
}
+46
View File
@@ -0,0 +1,46 @@
#!/bin/sh
export ANDROID_HOME="/mnt/c/Users/jacob/AppData/Local/Android/Sdk"
export TOOL_PREFIX="$ANDROID_HOME/build-tools/35.0.1"
# Only really works on Linux, for aarch64.
mkdir -p ../target/apk_build/lib/arm64-v8a
mkdir -p ../target/apk_build/res/values
mkdir -p ../target/apk_build/res/mipmap-hdpi
mkdir -p ../target/apk_build/res/mipmap-mdpi
mkdir -p ../target/apk_build/res/mipmap-xhdpi
mkdir -p ../target/apk_build/res/mipmap-xxhdpi
# Copy the shared library.
cp ../target/aarch64-linux-android/release/libdsa_rs.so ../target/apk_build/lib/arm64-v8a/
# Copy the manifest.
cp AndroidManifest.xml ../target/apk_build/AndroidManifest.xml
cat << EOF > ../target/apk_build/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">DSA Emulator</string>
</resources>
EOF
pushd ../target/apk_build
$TOOL_PREFIX/aapt2 compile --dir res -o compiled_resources.zip
$TOOL_PREFIX/aapt2 link -o unaligned.apk \
-I "$ANDROID_HOME/platforms/android-35/android.jar" \
--manifest AndroidManifest.xml \
compiled_resources.zip
zip -r unaligned.apk lib/
$TOOL_PREFIX/zipalign -v 4 unaligned.apk aligned.apk
keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 -storepass android -keypass android -dname "CN=Android Debug,O=Android,C=US"
$TOOL_PREFIX/apksigner sign --ks debug.keystore --ks-key-alias androiddebugkey --ks-pass pass:android --key-pass pass:android --out dsa_emulator.apk aligned.apk
cp dsa_emulator.apk ../dsa_emulator.apk
popd