;; -*- Mode: Lisp; -*- (in-package :b32-asm) (tagbody (defmacro jc (addr) `(progn (jnc (+ @ 2)) (jmp ,addr))) (defmacro jz (addr) `(progn (jnz (+ @ 2)) (jmp ,addr))) (defmacro call (addr) `(progn (lod '(jmp (+ @ 2))) (jmp ,addr))) (defmacro halt () '(jmp @)) (defmacro stoi (addr) ;; A <- [[addr]] `(progn (sto aux) (lod ,addr) (ior '(sto 0)) (sto (+ @ 2)) (lod aux) (sto 0))) (defmacro lodi (addr) ;; [[addr]] <- A `(progn (lod ,addr) (ior '(lod 0)) (sto (+ @ 1)) (lod 0))) (defconstant +tty+ #xF00000) (:bss) aux (ds 1) ;; ;; div --- unsigned integer divison ;; (:bss) div.x (dw 0) ;dividend div.y (dw 0) ;divisor div.q (dw 0) ;quotient div.m (dw 0) ;"mask" div.tmp (dw 0) ;temporary (:text) (jmp start) (:text) div (sto div.ret) (lod '0) (sto div.q) (lod '1) (sto div.m) ;m = 1 div.L1 ;; while x <= 2y, shift both y and m left ;; and 2y still fits (lod div.y) (and '#x80000000) (jnz div.L2) (lod div.y) (add div.y) (sto div.tmp) (lod div.x) (sub div.tmp) (jc div.L2) ;does not fit (lod div.tmp) (sto div.y) ;y = y + y (lod div.m) (add div.m) (sto div.m) ;m = m + k (jmp div.L1) div.L2 (lod div.x) (sub div.y) (jc div.L3) (sto div.x) (lod div.q) (add div.m) (sto div.q) div.L3 (lod div.m) (asr) (and '#x7FFFFFFF) (jz div.done) (sto div.m) (lod div.y) (asr) (and '#x7FFFFFFF) (sto div.y) (jmp div.L2) div.done (lod div.q) div.ret (jmp @) ;; ;; pru -- Print unsigned number in PRU.N in base PRU.BASE ;; (:bss) pru.n (dw 0) ;number to print pru.base (dw 10) ;print base pru.buf (ds 32) ;output buffer pru.ptr (ds 1) (:text) pru (sto pru.done) (lod 'pru.buf) (sto pru.ptr) pru.L1 ;; n = n / base, div.x = n % base (lod pru.n) (sto div.x) (lod pru.base) (sto div.y) (call div) (sto pru.n) ;; put remainder (= digit to print) into buffer (lod div.x) (stoi pru.ptr) ;; until n=0, continue (lod pru.n) (jz pru.L2) ;; ptr++ (lod pru.ptr) (add '1) (sto pru.ptr) (jmp pru.L1) ;loop pru.L2 ;; Output buffer in reverse (lodi pru.ptr) ;A = *ptr (sub '10) (jc pru.L4) ;<= 10 (add '(- #\A #\0 10)) ;correct for printing A..Z pru.L4 (add '(+ 10 #\0)) ;correct for ASCII and prior (SUB '10) (sto +tty+) (lod pru.ptr) (sub '1) (sto pru.ptr) ;ptr++ ;; check for end (sub '(- pru.buf 1)) (jnz pru.L2) ;loop pru.done (jmp 0) ;; ;; pri -- print signed number in pri.n in base pru.base ;; (:bss) (defconstant pri.n pru.n) ;shared (:text) pri (sto pru.done) ;setup for tail call ;; check for negative numbers (lod pri.n) (and '#x80000000) (jz (+ pru 1)) ;positive, tail call ;; print sign (lod '#\-) (sto +tty+) ;; negate (lod '0) (sub pri.n) (sto pru.n) (jmp (+ pru 1)) ;tail call ;; ;; prs -- print zero terminated string pointed to by prs.s ;; (:bss) prs.s (dw 0) (:text) prs (sto prs.done) prs.L1 (lodi prs.s) (jz prs.done) (sto +tty+) (lod prs.s) (add '1) (sto prs.s) (jmp prs.L1) prs.done (jmp 0) ) #+NIL (tagbody ;; ;; hello -- base 36 demo ;; (:text) hello (sto hello.done) (lod '36) (sto pru.base) (lod '29234652) (sto pru.n) (call pru) (lod '#\space) (sto +tty+) (lod '22342248) (sto pru.n) (call pru) (lod '#\space) (sto +tty+) (lod '13801) (sto pru.n) (call pru) (lod '#\space) (sto +tty+) (lod '1004137) (sto pru.n) (call pru) (lod '573386) (sto pru.n) (call pru) hello.done (jmp 0))