commit 9ed028ebcb746633f76fc1d4d835523ec2c8d390
parent 43ab35f9f20e1eb463efffa52579efb923d3b571
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Sun, 28 May 2023 08:30:01 -0400
asm/arm: add mul)
Diffstat:
3 files changed, 58 insertions(+), 22 deletions(-)
diff --git a/fs/asm/arm.fs b/fs/asm/arm.fs
@@ -9,31 +9,14 @@
: ,) ( 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
- 9 const rTOP 10 const rPSP 11 const rA
-12 const rIP 13 const rSP 14 const rLR 15 const rPC
-: rn) ( op r -- op ) 16 lshift or ;
-: rd) ( op r -- op ) 12 lshift or ;
-: rm) ( op r -- op ) or ;
-: rdn) tuck rd) swap rn) ;
-
-\ 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 or ;
0 cond eq) 1 cond ne) 2 cond cs) 3 cond cc)
+0 cond z) 1 cond nz) 2 cond hs) 3 cond lo)
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)
+12 cond gt) 13 cond le) 14 cond al)
-: op doer , does> @ 20 lshift $e0000000 or ;
+: op doer , does> @ 20 lshift al) ;
$00 op and) $02 op eor) $04 op sub) $06 op rsb)
$08 op add) $0a op adc) $0c op sbc) $0e op rsc)
$11 op tst) $13 op teq) $15 op cmp) $17 op cmn)
@@ -51,7 +34,7 @@ $18 op orr) $1a op mov) $1c op bic) $1e op mvn)
#? if abort" invalid immediate value" then or $02000000 or ;
\ Single Data Transfer (LDR, STR)
-$e5000000 const str) $e5100000 const ldr)
+$05000000 al) const str) str) $00100000 or const ldr)
: pre) $01000000 or ;
: post) $feffffff and ;
@@ -63,6 +46,31 @@ $e5000000 const str) $e5100000 const ldr)
: 8b) $00400000 or ;
: !) $00200000 or ;
+\ Multiply
+$90 al) const mul)
+: ismul? ( op -- f ) $0fcf00f0 and $90 = ;
+: acc) ( op r -- op ) 12 lshift or $00200000 or ;
+
+\ Parameters
+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
+ 9 const rTOP 10 const rPSP 11 const rA
+12 const rIP 13 const rSP 14 const rLR 15 const rPC
+: rn) ( op r -- op ) 16 lshift or ;
+: rd) ( op r -- op ) over ismul? 4 * 12 + lshift or ;
+: rs) ( op r -- op ) 8 lshift or ;
+: rm) ( op r -- op ) or ;
+: rdn) tuck rd) swap rn) ;
+
+\ 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 _ ;
+
\ Branching
: _rel>off >> >> 2 - $ffffff and ;
: b) ( rel32 -- op ) _rel>off $ea000000 or ;
diff --git a/fs/doc/asm/arm.txt b/fs/doc/asm/arm.txt
@@ -15,6 +15,11 @@ the first operand (Rn) and 42 as an immediate, we would do:
Symbol-wise, ")" means "accumulate", where the final ",)" means "write what has
been accumulated".
+WARNING: this assembler will not prevent you from assembling nonsensical
+instructions, checks are minimal (it does check immediate ranges though). For
+example, this means that using "rn)" on "mov)" or "rd)" on "cmp)" results in a
+broken instruction.
+
## Generic words
All operations work on registers and they pretty much all have a destination
@@ -29,6 +34,8 @@ words:
rd) Destination register
rn) First operand register
rm) Second operand register
+ rs) Used only for Multiply
+ rdn) Shortcut for rd) rn) when they're the same
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
@@ -44,7 +51,7 @@ 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)
+ eq) ne) cs) cc) z) nz) hs) lo) mi) pl) vs) vc) hi) ls) ge) lt) gt) le) al)
## Data processing instructions
@@ -60,6 +67,24 @@ To have the operation set the CPSR flags, you can use the word f) which sets the
tst) teq) cmp) and cmn) have an implied "f)".
+## Multiply
+
+The multiply instruction, mul), has a different structure than other data
+processing instructions and does Rd := Rm * Rs. For this instruction, rn) can't
+be used and there's a rs) parameter word just for this instruction (Rs is
+generally set with the lsl), lsr), etc. family of words).
+
+Additionally, there's the possibility of making a Multiply+Add through the acc)
+word, which takes a register ID in parameter.
+
+Rd cannot be the same as Rm and rPC can't be used.
+
+The f) flag works with mul). Example usages:
+
+ mul) r0 rd) r1 rm) r2 rs) ,)
+ mul) r0 rd) r1 rm) r2 rs) r3 acc) ,)
+ mul) r0 rd) r1 rm) r2 rs) f) ,)
+
## Single Data Transfer
The str) and ldr) operations only use rd) and rn), with rd) being the register
diff --git a/fs/tests/asm/arm.fs b/fs/tests/asm/arm.fs
@@ -11,4 +11,7 @@ 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
+mul) r1 rd) r2 rm) r3 rs)
+ $e0010392 over #eq \ mul r1, r2, r3
+r4 acc) $e0214392 #eq \ mla r1, r2, r3, r4
testend