duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 4d28f512ef3a22445a37d5f3abd55af351b9b0d6
parent d04ddb213355773a93fbdb413de59edd7fec7ad9
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Tue, 23 May 2023 15:37:33 -0400

asm/arm: rewrite to get rid of global states

see doc/asm/arm

Diffstat:
Mfs/asm/arm.fs | 126+++++++++++++++++++++++++++++--------------------------------------------------
Afs/doc/asm/arm.txt | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Afs/doc/hw/arm/arch.txt | 3+++
Afs/doc/hw/arm/rpi/rpi.txt | 10++++++++++
Mfs/lib/endian.fs | 7+++++--
Mfs/tests/asm/arm.fs | 15++++++---------
Mfs/xcomp/arm/rpi/kernel.fs | 31+++++++++++++++++--------------
7 files changed, 160 insertions(+), 105 deletions(-)

diff --git a/fs/asm/arm.fs b/fs/asm/arm.fs @@ -1,91 +1,57 @@ \ ARM assembler +?f<< /lib/math.fs +?f<< /lib/endian.fs ?f<< /asm/label.fs +: ,) ( op -- ) le, ; + 0 const r0 1 const r1 2 const r2 3 const r3 4 const r4 5 const r5 6 const r6 7 const r7 8 const r8 9 const r9 10 const r10 11 const r11 12 const r12 13 const r13 14 const r14 15 const r15 11 const rFP 12 const rIP 13 const rSP 14 const rLR 15 const rPC - -14 ( AL ) value curcond \ current condition flag -0 value shift \ contains the whole "shift" field (8 bits) --1 value imm \ 32-bit value. will be shifted later -0 value setcond \ set condition flag -\ those 2 below are only for LDR and STR -0 value sdtflags \ I P U B W -0 value sdtoff - -: cond doer , does> @ to curcond ; -0 cond EQ 1 cond NE 2 cond CS 3 cond CC -4 cond MI 5 cond PL 6 cond VS 7 cond VC -8 cond HI 9 cond LS 10 cond GE 11 cond LT -12 cond GT 13 cond LE - -\ immediate shift operations -: lsl) 3 lshift to shift ; -: lsr) 3 lshift 2 or to shift ; -: asr) 3 lshift 4 or to shift ; -: ror) 3 lshift 6 or to shift ; -\ register shift operations -: rlsl) 4 lshift 1 or to shift ; -: rlsr) 4 lshift 3 or to shift ; -: rasr) 4 lshift 5 or to shift ; -: rror) 4 lshift 7 or to shift ; - -: i) to imm ; -: s) 1 to setcond ; -: imm? imm -1 <> ; -: asm$ - 14 ( AL ) to curcond 0 to shift -1 to imm 0 to setcond 0 to sdtflags - 0 to sdtoff ; -: op, ( op -- ) curcond 28 lshift or , asm$ ; -: oprdrn, ( rd rn op -- ) - swap 16 lshift or swap 12 lshift or ( opcode ) op, ; - -\ Data processing ops -: shiftedimm $10 imm begin ( shift n ) - dup $100 >= while - dup 1 and if abort" invalid immediate value" then - >> >> swap 1- swap repeat ( shift n ) swap 8 lshift or ; -: _ ( rd rop1 rop2? opcode -- ) - 21 lshift setcond 20 lshift or - imm? if ( rd rop1 opcode ) - shiftedimm or $02000000 or - else ( rd rop1 rop2 opcode ) - shift $ff and 4 lshift or or then ( rd rop1 opcode ) oprdrn, ; - -: op ( opcode -- ) doer , does> @ _ ; -0 op and, 1 op eor, 2 op sub, 3 op rsb, -4 op add, 5 op adc, 6 op sbc, 7 op rsc, -12 op orr, 14 op bic, - -\ TST TEQ CMP CMN have no destination register and s) is implicit -: op ( opcode -- ) doer , does> @ s) imm? if 0 rot> else >r 0 rot> r> then _ ; -8 op tst, 9 op teq, 10 op cmp, 11 op cmn, - -\ MOV and MVN only have one operand -: op ( opcode -- ) doer , does> @ 0 imm? if swap else rot> then _ ; -13 op mov, 15 op mvn, - +: rn) ( op r -- op ) 16 lshift or ; +: rd) ( op r -- op ) 12 lshift or ; +: rm) ( op r -- op ) or ; + +\ immediate shift operations ( op n -- op ) +: _ ( op n type -- op ) dip 3 lshift | << or 4 lshift or ; +: lsl) 0 _ ; : lsr) 1 _ ; : asr) 2 _ ; : ror) 3 _ ; +\ register shift operations ( op r -- op ) +: _ ( op r type -- op ) dip 4 lshift | << 1+ or 4 lshift or ; +: rlsl) 0 _ ; : rlsr) 1 _ ; : rasr) 2 _ ; : rror) 3 _ ; + +: cond doer , does> @ 28 lshift swap $0fffffff and ; +0 cond eq) 1 cond ne) 2 cond cs) 3 cond cc) +4 cond mi) 5 cond pl) 6 cond vs) 7 cond vc) +8 cond hi) 9 cond ls) 10 cond ge) 11 cond lt) +12 cond gt) 13 cond le) + +: op doer , does> @ 21 lshift $e0000000 or ; +0 op and) 1 op eor) 2 op sub) 3 op rsb) +4 op add) 5 op adc) 6 op sbc) 7 op rsc) +8 op tst) 9 op teq) 10 op cmp) 11 op cmn) +12 op orr) 13 op mov) 14 op bic) 15 op mvn) + +: #? ( n -- immop rest ) + r! dup if log2 then 7 - max0 dup 1 and if 1+ then ( shift ) \ V1=n + r@ over rshift ( shift b ) + 2dup swap lshift r> -^ ( shift b rest ) + rot neg $1e and 7 lshift rot or ( rest imm ) swap ; + +: i) ( op n -- op ) + #? if abort" invalid immediate value" then or $02000000 or ; \ Single Data Transfer (LDR, STR) - -: pre) sdtflags $8 or to sdtflags ; -: post) sdtflags $17 and to sdtflags ; -: +) to sdtoff sdtflags $4 or to sdtflags ; -: -) to sdtoff sdtflags $1b and to sdtflags ; -: +i) sdtflags $f and to sdtflags +) ; -: -i) sdtflags $f and to sdtflags -) ; -: +r) sdtflags $10 or to sdtflags +) ; -: -r) sdtflags $10 or to sdtflags -) ; -: 8b) sdtflags $2 or to sdtflags ; -: !) sdtflags $1 or to sdtflags ; - -: op ( lflag -- ) doer , does> @ ( rd rn lflag ) - 20 lshift sdtflags 21 lshift or $04000000 or sdtoff or ( rd rn opcode ) - sdtflags $10 and if \ is a register offset - shift $ff and 4 lshift or then ( rd rn opcode ) - oprdrn, ; - -0 op str, 1 op ldr, +$e4000000 const str) $e4100000 const ldr) + +: pre) $01000000 or ; +: post) $feffffff and ; +: 12b# ( n -- ) $fffff000 and if abort" invalid offset" then ; +: +i) ( op n -- op ) dup 12b# or $00800000 or ; +: -i) ( op n -- op ) dup 12b# or $ff7fffff and ; +: +r) ( op r -- op ) +i) $02000000 or ; +: -r) ( op r -- op ) -i) $02000000 or ; +: 8b) $00400000 or ; +: !) $00200000 or ; diff --git a/fs/doc/asm/arm.txt b/fs/doc/asm/arm.txt @@ -0,0 +1,73 @@ +# ARM assembler + +ARM instructions all encode to a 32-bit number and the way these encoding work +incite us to deviate a little bit from the general Dusk assembler mechanism: +Instead of pushing arguments to PS and then call the "operation writer" word, +we instead begin the the operation mnemonic and "accumulate" arguments into it. +When all arguments are accumulated, the number of PS is exactly what we want to +write, which we can do with "le,", of which ",)" is an alias. + +For example, to write a "add" instruction with r4 as a destination (Rd), r5 as +the first operand (Rn) and 42 as an immediate, we would do: + + add) r4 rd) r5 rn) 42 i) ,) + +Symbol-wise, ")" means "accumulate", where the final ",)" means "write what has +been accumulated". + +## Generic words + +All operations work on registers and they pretty much all have a destination +register and one or two operand registers. Each register has a constant word: + + r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 + rFP rIP rSP rLR rPC + +These constants are meant to be used in conjunction with these accumulator +words: + + rd) Destination register + rn) First operand register + rm) Second operand register + +Whenever there's a second operand register, the barrel shifter can be configured +with these words which all have the ( op n -- op ) signature, "op" being the +accumulated operation: + + lsl) lsr) asr) ror) n = shift by "n" bits + rlsl) rlsr) rasr) rror) n = register id containing the amount to shift by + +Immediates replace the rm) operand and can be specified with the i) word. Shift +encoding is automatically performed by i) and will abort with an error message +if the specified immediate can't be encoded. + +All operations can be conditionally executed. This condition is activated by one +of these words: + + eq) ne) cs) cc) mi) pl) vs) vc) hi) ls) ge) lt) gt) le) + +## Data processing instructions + +All those instructions except mov) and mvn) have 3 operators: + + and) eor) sub) rsb) add) adc) sbc) rsc) + tst) teq) cmp) cmn) orr) mov) bic) mvn) + +## Single Data Transfer + +The str) and ldr) operations only use rd) and rn), with rd) being the register +containing the value to store or the register being the target for the load +operation. rn) is the register containing the target adress for the store/load +operation. + +Many options come with those two operations and they are enabled with those +words: + + +i) op n -- op Add offset "n" to rn) + -i) op n -- op Subtract offset "n" from rn) + +r) op r -- op Add offset in register "r" to rn) + -r) op r -- op Subtract offset in register "r" from rn) + pre) op -- op Add offset before transfer + post) op -- op Add offset after transfer (default) + 8b) op -- op Load/Store operation is 8-bit + !) op -- op Write effective address back to rn) diff --git a/fs/doc/hw/arm/arch.txt b/fs/doc/hw/arm/arch.txt @@ -0,0 +1,3 @@ +# ARM architecture + +TODO diff --git a/fs/doc/hw/arm/rpi/rpi.txt b/fs/doc/hw/arm/rpi/rpi.txt @@ -0,0 +1,10 @@ +# Raspberry Pi + +The main source of information for Raspberry Pi development is from the +Raspberry Pi foundation itself[1]. + +This Git repository contains, for example, the BCM2835 technical documentation, +which is the main document against which Dusk's first foray into the ARM world +(Raspberry Pi model 1) is built. + +[1]: https://github.com/raspberrypi/documentation.git diff --git a/fs/lib/endian.fs b/fs/lib/endian.fs @@ -5,10 +5,12 @@ $1234 here ! here c@ $34 = const LITTLE_ENDIAN? alias @ le@ :16b 16b @ ; alias ! le! :16b 16b ! ; +alias , le, :16b 16b , ; LITTLE_ENDIAN? not [if] abort" TODO" [then] alias @ be@ :16b 16b @ ; alias ! be! :16b 16b ! ; +alias , be, :16b 16b , ; LITTLE_ENDIAN? [if] code be@ ( a -- n ) W>A, A) 8b) @, 8 i) <<, @@ -29,4 +31,6 @@ LITTLE_ENDIAN? [if] code16b W>A, drop, A) 1 +) 8b) !, 8 i) >>, A) 8b) !, drop, exit, -[then] -\ No newline at end of file + + : be, here be! 4 allot ; :16b here 16b be! 2 allot ; +[then] diff --git a/fs/tests/asm/arm.fs b/fs/tests/asm/arm.fs @@ -3,15 +3,12 @@ ARCH S" i386" s= [if] ." ARM assembler messes up i386 asm, skipping" nl> \s [then] ?f<< /asm/arm.fs -\ We don't have an ARM port yet, we can't actually test. For now, all we do is -\ spit binary contents of our ops for manual disassembly checks. -: spit ( a u -- ) swap >r for 8b to@+ V1 .x1 next rdrop ; testbegin \ Tests for asm/arm.fs -code foo1 - r0 42 i) mov, \ mov r0, #42 - r1 r2 r3 +r) pre) 1 lsr) ldr, \ ldr r1, [r2, r3 lsr #1] - r3 $3f0000 i) mov, \ mov r3, #3f0000 - -current here over - spit +mov) r0 rd) 42 i) + $e3a0002a #eq \ mov r0, #42 +ldr) r1 rd) r2 rn) r3 +r) pre) 1 lsr) + $e79210a3 #eq \ ldr r1, [r2, r3 lsr #1] +mov) r3 rd) $3f0000 i) + $e3a039fc #eq \ mov r3, #3f0000 testend diff --git a/fs/xcomp/arm/rpi/kernel.fs b/fs/xcomp/arm/rpi/kernel.fs @@ -27,36 +27,39 @@ $8c const UART0_TDR $8000 to binstart 0 align4 here to org -r0 MMIO_BASE i) mov, \ r0 = MMIO_BASE -r0 r0 GPIO_BASE i) add, \ r0 = GPIO_BASE -r2 r0 UART0_BASE i) add, \ r2 = UART0_BASE +mov) r0 rd) MMIO_BASE i) ,) \ r0 = MMIO_BASE +add) r0 rd) r0 rn) GPIO_BASE i) ,) \ r0 = GPIO_BASE +add) r2 rd) r0 rn) UART0_BASE i) ,) \ r2 = UART0_BASE \ Disable UART0 -r3 r2 UART0_CR i) add, r1 0 i) mov, r1 r3 str, +add) r3 rd) r2 rn) UART0_CR i) ,) mov) r1 rd) 0 i) ,) str) r1 rd) r3 rn) ,) \ Disable pull up/down for all GPIO pins & delay for 150 cycles. -r3 r0 GPPUD i) add, r1 0 i) mov, r1 r3 str, +add) r3 rd) r0 rn) GPPUD i) ,) mov) r1 rd) 0 i) ,) str) r1 rd) r3 rn) ,) \ TODO: add delay \ Disable pull up/down for pin 14,15 & delay for 150 cycles. -r3 r0 GPPUDCLK0 i) add, r1 $c000 i) mov, r1 r3 str, +add) r3 rd) r0 rn) GPPUDCLK0 i) ,) mov) r1 rd) $c000 i) ,) str) r1 rd) r3 rn) ,) \ TODO: add delay \ Write 0 to GPPUDCLK0 to make it take effect. -r3 r0 GPPUDCLK0 i) add, r1 0 i) mov, r1 r3 str, +add) r3 rd) r0 rn) GPPUDCLK0 i) ,) mov) r1 rd) 0 i) ,) str) r1 rd) r3 rn) ,) \ Clear pending interrupts. -r3 r2 UART0_ICR i) add, r1 $700 i) mov, r1 r1 $ff i) add, r1 r3 str, +add) r3 rd) r2 rn) UART0_ICR i) ,) mov) r1 rd) $700 i) ,) +add) r1 rd) r1 rn) $ff i) ,) str) r1 rd) r3 rn) ,) \ Set integer & fractional part of baud rate. \ Divider = UART_CLOCK/(16 * Baud) \ Fraction part register = (Fractional part * 64) + 0.5 \ Baud = 115200. \ Divider = 3000000 / (16 * 115200) = 1.627 = ~1. -r3 r2 UART0_IBRD i) add, r1 1 i) mov, r1 r3 str, +add) r3 rd) r2 rn) UART0_IBRD i) ,) mov) r1 rd) 1 i) ,) str) r1 rd) r3 rn) ,) \ Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40. -r3 r2 UART0_FBRD i) add, r1 40 i) mov, r1 r3 str, +add) r3 rd) r2 rn) UART0_FBRD i) ,) mov) r1 rd) 40 i) ,) str) r1 rd) r3 rn) ,) \ Enable FIFO & 8 bit data transmission (1 stop bit, no parity). -r3 r2 UART0_LCRH i) add, r1 $70 i) mov, r1 r3 str, +add) r3 rd) r2 rn) UART0_LCRH i) ,) mov) r1 rd) $70 i) ,) str) r1 rd) r3 rn) ,) \ Mask all interrupts. -r3 r2 UART0_IMSC i) add, r1 $700 i) mov, r1 r1 $f2 i) add, r1 r3 str, +add) r3 rd) r2 rn) UART0_IMSC i) ,) mov) r1 rd) $700 i) ,) +add) r1 rd) r1 rn) $f2 i) ,) str) r1 rd) r3 rn) ,) \ Enable UART0, receive & transfer part of UART. -r3 r2 UART0_CR i) add, r1 $300 i) mov, r1 r1 $01 i) add, r1 r3 str, +add) r3 rd) r2 rn) UART0_CR i) ,) mov) r1 rd) $300 i) ,) +add) r1 rd) r1 rn) $01 i) ,) str) r1 rd) r3 rn) ,) -r3 r2 UART0_DR i) add, r1 'X' i) mov, r1 r3 str, +add) r3 rd) r2 rn) UART0_DR i) ,) mov) r1 rd) 'X' i) ,) str) r1 rd) r3 rn) ,) $eafffffe , \ hardcoded "b -2"