]> gitweb.factorcode.org Git - factor.git/blob - basis/cpu/arm/assembler/assembler.factor
arm: implement prolog and epilog
[factor.git] / basis / cpu / arm / assembler / assembler.factor
1 ! Copyright (C) 2020 Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors combinators cpu.arm.assembler.opcodes io.binary
4 kernel make math math.bitwise namespaces sequences ;
5 IN: cpu.arm.assembler
6
7 ! pre-index mode: computed addres is the base-register + offset
8 ! ldr X1, [X2, #4]!
9 ! post-index mode: computed address is the base-register
10 ! ldr X1, [X2], #4
11 ! in both modes, the base-register is updated
12
13 ERROR: arm64-encoding-imm original n-bits-requested truncated ;
14 : ?bits ( x n -- x ) 2dup bits dup reach = [ 2drop ] [ arm64-encoding-imm ] if ; inline
15
16 ! : ip ( -- address ) arm64-assembler get ip>> ;
17
18 : ADR ( imm21 Rd -- )
19     [ [ 2 bits ] [ -2 shift 19 ?bits ] bi ] dip ADR-encode ;
20
21 : ADRP ( imm21 Rd -- )
22     [ [ 2 bits ] [ -2 shift 19 ?bits ] bi ] dip ADRP-encode ;
23
24 : LDR-pre ( imm9 Rn Rt -- ) LDRpre64-encode ;
25 : LDR-post ( imm9 Rn Rt -- ) LDRpost64-encode ;
26 : LDR-uoff ( imm12 Rn Rt -- ) [ 8 / ] 2dip LDRuoff64-encode ;
27
28 : MOVwi64 ( imm Rt -- ) [ 0 ] 2dip MOVwi64-encode ;
29 : MOVr64 ( Rn Rd -- ) MOVr64-encode ;
30
31 : RET ( register/f -- ) X30 or RET-encode ;
32
33 ! stp     x29, x30, [sp,#-16]!
34 ! -16 SP X30 X29 STP-pre
35 : STP-pre ( offset register-offset register-mid register -- )
36     [ 8 / 7 bits ] 3dip swapd STPpre64-encode ;
37
38 : STP-post ( offset register-offset register-mid register -- )
39     [ 8 / 7 bits ] 3dip swapd STPpost64-encode ;
40
41 : STP-signed-offset ( offset register-offset register-mid register -- )
42     [ 8 / 7 bits ] 3dip swapd STPsoff64-encode ;
43
44
45 : LDP-pre ( offset register-offset register-mid register -- )
46     [ 8 / 7 bits ] 3dip swapd LDPpre64-encode ;
47
48 : LDP-post ( offset register-offset register-mid register -- )
49     [ 8 / 7 bits ] 3dip swapd LDPpost64-encode ;
50
51 : LDP-signed-offset ( offset register-offset register-mid register -- )
52     [ 8 / 7 bits ] 3dip swapd LDPsoff64-encode ;
53
54 ! Some instructions allow an immediate literal of n bits
55 ! or n bits shifted. This means there are invalid immediate
56 ! values, e.g. imm12 of 1, 4096, but not 4097
57 ERROR: imm-out-of-range imm n ;
58 : imm-lower? ( imm n -- ? )
59     on-bits unmask 0 > not ;
60
61  : imm-upper? ( imm n -- ? )
62     [ on-bits ] [ shift ] bi unmask 0 > not ;
63
64 : prepare-split-imm ( imm n -- imm upper? )
65     {
66         { [ 2dup imm-lower? ] [ drop f ] }
67         { [ 2dup imm-upper? ] [ drop t ] }
68         [ imm-out-of-range ]
69     } cond ;
70
71 : ADDi32 ( imm12 Rn Rd -- )
72     [ 12 prepare-split-imm 1 0 ? swap ] 2dip
73     ADDi32-encode ;
74
75 : ADDi64 ( imm12 Rn Rd -- )
76     [ 12 prepare-split-imm 1 0 ? swap ] 2dip
77     ADDi64-encode ;
78
79 : SUBi32 ( imm12 Rn Rd -- )
80     [ 12 prepare-split-imm 1 0 ? swap ] 2dip
81     SUBi32-encode ;
82
83 : SUBi64 ( imm12 Rn Rd -- )
84     [ 12 prepare-split-imm 1 0 ? swap ] 2dip
85     SUBi64-encode ;
86
87 : CMPi32 ( imm12 Rd -- )
88     [ 12 prepare-split-imm 1 0 ? swap ] dip
89     CMPi32-encode ;
90
91 : CMPi64 ( imm12 Rd -- )
92     [ 12 prepare-split-imm 1 0 ? swap ] dip
93     CMPi64-encode ;
94
95 : STRuoff32 ( imm12 Rn Rt -- )
96     [ -2 shift ] 2dip STRuoff32-encode ;
97
98 : STRuoff64 ( imm12 Rn Rt -- )
99     [ -3 shift ] 2dip STRuoff64-encode ;
100
101 : STRr64 ( Rm Rn Rt -- )
102     [ 0 0 ] 2dip STRr64-encode ;
103
104 : ASRi32 ( imm6 Rn Rd -- ) [ 6 ?bits ] 2dip ASRi32-encode ;
105 : ASRi64 ( imm6 Rn Rd -- ) [ 6 ?bits ] 2dip ASRi64-encode ;
106 : LSLi32 ( imm6 Rn Rd -- ) [ 6 ?bits ] 2dip LSLi32-encode ;
107 : LSLi64 ( imm6 Rn Rd -- ) [ 6 ?bits ] 2dip LSLi64-encode ;
108 : LSRi32 ( imm6 Rn Rd -- ) [ 6 ?bits ] 2dip LSRi32-encode ;
109 : LSRi64 ( imm6 Rn Rd -- ) [ 6 ?bits ] 2dip LSRi64-encode ;
110
111 : SVC ( imm16 -- ) 16 ?bits SVC-encode ;
112
113 : with-output-variable ( value variable quot -- value )
114     over [ get ] curry compose with-variable ; inline
115
116 : ADC32 ( Rm Rn Rd -- ) ADC32-encode ;
117 : ADCS32 ( Rm Rn Rd -- ) ADCS32-encode ;
118 : ADC64 ( Rm Rn Rd -- ) ADC64-encode ;
119 : ADCS64 ( Rm Rn Rd -- ) ADCS64-encode ;
120
121 : BRK ( imm16 -- ) 16 ?bits BRK-encode ;
122 : HLT ( imm16 -- ) 16 ?bits HLT-encode ;
123
124 : CBNZ ( imm19 Rt -- ) [ 19 ?bits ] dip CBNZ64-encode ;
125 ! cond4 is EQ NE CS HS CC LO MI PL VS VC HI LS GE LT GT LE AL NV
126 : CSEL ( Rm Rn Rd cond4 -- ) -rot CSEL64-encode ;
127 : CSET ( Rd cond4 -- ) swap CSET64-encode ;
128 : CSETM ( Rd cond4 -- ) swap CSETM64-encode ;
129
130 ! B but that is breakpoint
131 : Br ( imm26 -- ) 26 ?bits B-encode ;
132 : B.cond ( imm19 cond4 -- ) [ 19 ?bits ] dip B.cond-encode ;
133 ! : BL ( offset -- ) ip - 4 / BL-encode ;
134 : BL ( offset -- ) BL-encode ;
135 : BR ( Rn -- ) BR-encode ;
136 : BLR ( Rn -- ) BLR-encode ;