aboutsummaryrefslogtreecommitdiff
path: root/examples/example2a_measure_time_wasm/instructions.wat
diff options
context:
space:
mode:
Diffstat (limited to 'examples/example2a_measure_time_wasm/instructions.wat')
-rw-r--r--examples/example2a_measure_time_wasm/instructions.wat110
1 files changed, 110 insertions, 0 deletions
diff --git a/examples/example2a_measure_time_wasm/instructions.wat b/examples/example2a_measure_time_wasm/instructions.wat
new file mode 100644
index 0000000..3a6be34
--- /dev/null
+++ b/examples/example2a_measure_time_wasm/instructions.wat
@@ -0,0 +1,110 @@
+;; See instructions.wat of soc_print_number test. A lot has been taken from
+;; there.
+;; Relevant addresses are VGA text memory (0xFFC00), VGA regs (0x100600),
+;; lower half of timer reg (0x1BFC08) and led2 reg (0x1BFC06).
+
+(module
+ (memory 0 2)
+ ;; print number in decimal at address $dest, return address after
+ ;; the last digit
+ (func $print (param $number i32) (param $dest i32) (result i32)
+ (local $adr1 i32)
+ (local $adr2 i32)
+ ;; remember the initial address to write at
+ (set_local $adr1 (get_local $dest))
+ (loop $again
+ ;; prepare address for store operation later
+ (get_local $dest)
+ ;; compute the last digit of number
+ (i32.rem_u (get_local $number)
+ (i32.const 10))
+ ;; 0x30 is ASCII encoding of digit 0
+ (i32.add (i32.const 0x30))
+ ;; write digit's ASCII char to memory
+ (i32.store8 offset=0x0 align=1)
+ ;; increment the pointer
+ (set_local $dest (i32.add (i32.const 1)
+ (get_local $dest)))
+ ;; divide our number by 10
+ (set_local $number (i32.div_u (get_local $number)
+ (i32.const 10)))
+ ;; break the loop, if number is 0
+ (br_if $again (get_local $number)))
+
+ ;; digit chars are now in the reverse order - swap them in a loop
+ (set_local $adr2 (i32.sub (get_local $dest)
+ (i32.const 1)))
+ (loop $again
+ ;; prepare address for later store operation
+ (get_local $adr2)
+ ;; load value on the left
+ (i32.load8_u offset=0x0 align=1
+ (get_local $adr1))
+ ;; prepare address for later store operation
+ (get_local $adr1)
+ ;; load value on the right
+ (i32.load8_u offset=0x0 align=1
+ (get_local $adr2))
+ ;; write value on the left
+ (i32.store8 offset=0x0 align=1)
+ ;; write value on the right
+ (i32.store8 offset=0x0 align=1)
+
+ ;; increase $adr1
+ (set_local $adr1 (i32.add (get_local $adr1)
+ (i32.const 1)))
+ ;; decrease $adr2
+ (set_local $adr2 (i32.sub (get_local $adr2)
+ (i32.const 1)))
+ ;; loop until adr1 and adr2 cross/meet
+ (br_if $again (i32.lt_u (get_local $adr1)
+ (get_local $adr2))))
+ ;; return the address we finished at
+ (get_local $dest))
+ (func $main
+ (local $counter i32)
+ (local $adr i32)
+
+ ;; reset the timer (although it should already be resetted, anyway...)
+ (i32.store16 offset=0x1BFC08 align=1
+ (i32.const 0x0) (i32.const 0x0))
+
+ ;; initialize counter
+ (set_local $counter (i32.const 0))
+
+ ;; add numbers from 1 to 100
+ (i32.const 0)
+ (loop $again (param i32) (result i32)
+ (set_local $counter (i32.add
+ (get_local $counter)
+ (i32.const 1)))
+ (i32.add (get_local $counter))
+ (br_if $again (i32.lt_u
+ (get_local $counter)
+ (i32.const 100))))
+ ;; we now leave sum on the stack for later
+
+ ;; light led2
+ (i32.store16 offset=0x1BFC06 align=1
+ (i32.const 0x0) (i32.const 0x1))
+
+ ;; print timer value
+ (set_local $adr (call $print
+ ;; read timer value
+ (i32.load16_u offset=0x1BFC08 align=1
+ (i32.const 0x0))
+ (i32.const 0xFFC00)))
+
+ ;; print ascii underscore '_'
+ (i32.store8 offset=0x0 align=1
+ (get_local $adr) (i32.const 0x5F))
+
+ ;; print computed sum
+ (set_local $adr (call $print
+ ;; sum's already on the stack
+ (i32.add (get_local $adr) (i32.const 1))))
+
+ ;; write a non-zero value to the VGA power-on reg at 0x100600 (0x100A00)
+ (i32.store16 offset=0x100600 align=2
+ (i32.const 0) (i32.const 1)))
+ (export "main" (func $main)))