commit 0cea10a86ec571464d114fb420feb3cea0f4634e
parent 141628ce0db0f671283ccc4ec446a3dc7fda84f3
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Mon, 24 Oct 2022 14:24:12 -0400
asm/arm: add LDR and STR
Diffstat:
2 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/fs/asm/arm.fs b/fs/asm/arm.fs
@@ -10,6 +10,10 @@
14 ( AL ) value curcond \ current condition flag
0 value shift \ contains the whole "shift" field (8 bits)
-1 value imm \ must be < $ff
+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
@@ -29,26 +33,54 @@
: rror) 4 lshift 7 or to shift ;
: i) to imm ;
+: s) 1 to setcond ;
: imm? imm 0>= ;
-: asm$ 14 ( AL ) to curcond 0 to shift -1 to imm ;
+: 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
: _ ( rd rop1 rop2? opcode -- )
- 21 lshift
+ 21 lshift setcond 20 lshift or
imm? if ( rd rop1 opcode )
shift $f and 8 lshift imm or or $02000000 or
else ( rd rop1 rop2 opcode )
- shift $ff and 4 lshift or or then ( rd rop1 opcode )
- swap 12 lshift or swap 16 lshift or ( opcode ) op, ;
+ 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,
-8 op tst, 9 op teq, 10 op cmp, 11 op cmn,
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,
+
+\ 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,
diff --git a/fs/tests/asm/arm.fs b/fs/tests/asm/arm.fs
@@ -6,7 +6,8 @@
testbegin
\ Tests for asm/arm.fs
code foo1
- r0 42 i) mov,
+ r0 42 i) mov, \ mov r0, #42
+ r1 r2 r3 +r) pre) 1 lsr) ldr, \ ldr r1, [r2, r3 lsr #1]
current here over - spit
testend