1%%% -*- erlang-indent-level: 2 -*-
2%%%
3%%% Licensed under the Apache License, Version 2.0 (the "License");
4%%% you may not use this file except in compliance with the License.
5%%% You may obtain a copy of the License at
6%%%
7%%%     http://www.apache.org/licenses/LICENSE-2.0
8%%%
9%%% Unless required by applicable law or agreed to in writing, software
10%%% distributed under the License is distributed on an "AS IS" BASIS,
11%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12%%% See the License for the specific language governing permissions and
13%%% limitations under the License.
14%%%
15%%% Encode symbolic ARM instructions to binary form.
16%%% Copyright (C) 2005  Mikael Pettersson
17%%%
18%%% Implementation Notes:
19%%% - The Thumb instruction set is a different entity, and is
20%%%   not and never will be supported by this module.
21%%% - Instructions and instruction forms that are unpredictable
22%%%   or useless in User mode are not supported. They include:
23%%%   + Data Processing Instructions with S=1 and Rd=15.
24%%%   + The LDM(2), LDM(3), and STM(2) instructions.
25%%%   + MRS instructions that access the SPSR.
26%%%   + MSR instructions that access the SPSR.
27%%%   + The LDBRT, LDRT, STBRT, and STRT instructions.
28%%%
29%%% Instruction Operands:
30%%%
31%%% S		    ::= {s,0} | {s,1}
32%%% L		    ::= {l,0} | {l,1}
33%%% R		    ::= {r,RNum}
34%%% CR		    ::= {cr,CRNum}
35%%%
36%%% Cond	    ::= {cond,CondName}
37%%% CondName	    ::= eq | ne | cs | hs | cc | lo | mi | pl | vs
38%%%		      | vc | hi | ls | ge | lt | gt | ge | al
39%%%
40%%% Imm<N>	    ::= {imm<N>,<N bits>} for N in 4, 5, 8, 12, 16, 24, and 25
41%%%
42%%% Am1ShifterOperand
43%%%		    ::=	{Imm8,Imm4}
44%%%		      | Rm
45%%%		      | {Rm,Am1ShiftOp}
46%%% Am1ShiftOp	    ::= {ShiftOp,Imm5}
47%%%		      | {ShiftOp,Rs}
48%%%		      | rrx
49%%% ShiftOp	    ::= lsl | lsr | asr | ror
50%%%
51%%% Am2LSWUBOperand ::= {immediate_offset,Rn,Sign,Imm12}
52%%%		      | {register_offset,Rn,Sign,Rm} // redundant
53%%%		      | {scaled_register_offset,Rn,Sign,Rm,Am2ShiftOp}
54%%%		      | {immediate_pre_indexed,Rn,Sign,Imm12}
55%%%		      | {register_pre_indexed,Rn,Sign,Rm} // redundant
56%%%		      | {scaled_register_pre_indexed,Rn,Sign,Rm,Am2ShiftOp}
57%%%		      | {immediate_post_indexed,Rn,Sign,Imm12}
58%%%		      | {register_post_indexed,Rn,Sign,Rm} // redundant
59%%%		      | {scaled_register_post_indexed,Rn,Sign,Rm,Am2ShiftOp}
60%%% Am2ShiftOp	    ::= {ShiftOp,Imm5}
61%%%		      | rrx
62%%% Sign	    ::= + | -
63%%%
64%%% Am3MiscLSOperand::= {immediate_offset,Rn,Sign,Imm8}
65%%%		      | {register_offset,Rn,Sign,Rm}
66%%%		      | {immediate_pre_indexed,Rn,Sign,Imm8}
67%%%		      | {register_pre_indexed,Rn,Sign,Rm}
68%%%		      | {immediate_post_indexed,Rn,Sign,Imm8}
69%%%		      | {register_post_indexed,Rn,Sign,Rm}
70%%%
71%%% Am4LSMultiple   ::= ia | ib | da | db
72%%%		      | fd | ed | fa | ea
73%%%
74%%% Am5LSCoprocessor::= {offset,Rn,Sign,Imm8}
75%%%		      | {pre_indexed,Rn,Sign,Imm8}
76%%%		      | {post_indexed,Rn,Sign,Imm8}
77%%%		      | {unindexed,Rn,Imm8}
78
79-module(hipe_arm_encode).
80
81-export([insn_encode/2]).
82
83%%-define(TESTING,1).
84-ifdef(TESTING).
85-export([dotest/0, dotest/1]).
86-endif.
87
88-define(ASSERT(G),
89	if G -> [];
90	   true -> exit({assertion_failed,?MODULE,?LINE,??G})
91	end).
92
93bf(LeftBit, RightBit, Value) ->
94  ?ASSERT(32 > LeftBit),
95  ?ASSERT(LeftBit >= RightBit),
96  ?ASSERT(RightBit >= 0),
97  ?ASSERT(Value >= 0),
98  ?ASSERT(Value < (1 bsl ((LeftBit - RightBit) + 1))),
99  Value bsl RightBit.
100
101-define(BF(LB,RB,V), bf(LB,RB,V)).
102-define(BIT(Pos,Val), ?BF(Pos,Pos,Val)).
103%%-define(BITS(N,Val), ?BF(N,0,Val)).
104
105%%%
106%%% Addressing Modes
107%%%
108
109am1_shifter_operand(Rn, Rd, ShifterOperand) ->
110  case ShifterOperand of
111    {{imm8,Imm8},{imm4,RotImm4}} ->
112      ?BIT(25,1) bor ?BF(11,8,RotImm4) bor ?BF(7,0,Imm8);
113    {r,Rm} ->
114      %% same as Rm LSL #0
115      ?BF(3,0,Rm);
116    {{r,Rm},ShiftOp} ->
117      am1_shift_op(Rn, Rd, Rm, ShiftOp) bor ?BF(3,0,Rm)
118  end.
119
120am1_shift_op(_Rn, _Rd, _Rm, {ShiftOp,{imm5,ShiftImm5}}) ->
121  case ShiftOp of
122    'ror' -> ?ASSERT(ShiftImm5 =/= 0);	% denotes RRX form
123    _ -> []
124  end,
125  ?BF(11,7,ShiftImm5) bor shift_op_bits65(ShiftOp);
126am1_shift_op(Rn, Rd, Rm, {ShiftOp,{r,Rs}}) ->
127  ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
128  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
129  ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
130  ?ASSERT(Rs =/= 15),	% UNPREDICTABLE
131  ?BF(11,8,Rs) bor shift_op_bits65(ShiftOp) bor ?BIT(4,1);
132am1_shift_op(_Rn, _Rd, _Rm, 'rrx') ->
133  ?BF(6,5,2#11).
134
135shift_op_bits65(ShiftOp) ->
136  case ShiftOp of
137    'lsl' -> ?BF(6,5,2#00);
138    'lsr' -> ?BF(6,5,2#01);
139    'asr' -> ?BF(6,5,2#10);
140    'ror' -> ?BF(6,5,2#11)
141  end.
142
143sign('+') -> ?BIT(23,1);
144sign('-') -> 0.
145
146am2_lswub(Rd, AddressingMode) ->
147  case AddressingMode of
148    {immediate_offset,{r,Rn},Sign,{imm12,Imm12}} ->
149      ?BIT(24,1) bor sign(Sign) bor ?BF(19,16,Rn) bor ?BF(11,0,Imm12);
150    {register_offset,{r,Rn},Sign,{r,Rm}} ->
151      %% same as scaled_register_offset LSL #0
152      ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
153      ?BIT(25,1) bor ?BIT(24,1) bor sign(Sign) bor ?BF(19,16,Rn) bor ?BF(3,0,Rm);
154    {scaled_register_offset,{r,Rn},Sign,{r,Rm},ShiftOp} ->
155      ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
156      ?BIT(25,1) bor ?BIT(24,1) bor sign(Sign) bor ?BF(19,16,Rn) bor am2_shift_op(ShiftOp) bor ?BF(3,0,Rm);
157    {immediate_pre_indexed,{r,Rn},Sign,{imm12,Imm12}} ->
158      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
159      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
160      ?BIT(24,1) bor sign(Sign) bor ?BIT(21,1) bor ?BF(19,16,Rn) bor ?BF(11,0,Imm12);
161    {register_pre_indexed,{r,Rn},Sign,{r,Rm}} ->
162      %% same as scaled_register_pre_indexed LSL #0
163      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
164      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
165      ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
166      ?ASSERT(Rn =/= Rm),	% UNPREDICTABLE
167      ?BIT(25,1) bor ?BIT(24,1) bor sign(Sign) bor ?BIT(21,1) bor ?BF(19,16,Rn) bor ?BF(3,0,Rm);
168    {scaled_register_pre_indexed,{r,Rn},Sign,{r,Rm},ShiftOp} ->
169      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
170      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
171      ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
172      ?ASSERT(Rn =/= Rm),	% UNPREDICTABLE
173      ?BIT(25,1) bor ?BIT(24,1) bor sign(Sign) bor ?BIT(21,1) bor ?BF(19,16,Rn) bor am2_shift_op(ShiftOp) bor ?BF(3,0,Rm);
174    {immediate_post_indexed,{r,Rn},Sign,{imm12,Imm12}} ->
175      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
176      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
177      sign(Sign) bor ?BF(19,16,Rn) bor ?BF(11,0,Imm12);
178    {register_post_indexed,{r,Rn},Sign,{r,Rm}} ->
179      %% same as scaled_register_post_indexed LSL #0
180      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
181      ?BIT(25,1) bor sign(Sign) bor ?BF(19,6,Rn) bor ?BF(3,0,Rm);
182    {scaled_register_post_indexed,{r,Rn},Sign,{r,Rm},ShiftOp} ->
183      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
184      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
185      ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
186      ?ASSERT(Rn =/= Rm),	% UNPREDICTABLE
187      ?BIT(25,1) bor sign(Sign) bor ?BF(19,16,Rn) bor am2_shift_op(ShiftOp) bor ?BF(3,0,Rm)
188  end.
189
190am2_shift_op({ShiftOp,{imm5,ShiftImm5}}) ->
191  case ShiftOp of
192    'ror' -> ?ASSERT(ShiftImm5 =/= 0);	% denotes RRX form
193    _ -> []
194  end,
195  ?BF(11,7,ShiftImm5) bor shift_op_bits65(ShiftOp);
196am2_shift_op('rrx') ->
197  ?BF(6,5,2#11).
198
199am3_miscls(Rd, AddressingMode) ->
200  case AddressingMode of
201    {immediate_offset,{r,Rn},Sign,{imm8,Imm8}} ->
202      ?BIT(24,1) bor sign(Sign) bor ?BF(22,21,2#10) bor ?BF(19,16,Rn) bor ?BF(11,8,Imm8 bsr 4) bor ?BF(3,0,Imm8 band 2#1111);
203    {register_offset,{r,Rn},Sign,{r,Rm}} ->
204      ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
205      ?BIT(24,1) bor sign(Sign) bor ?BF(22,21,2#00) bor ?BF(19,16,Rn) bor ?BF(3,0,Rm);
206    {immediate_pre_indexed,{r,Rn},Sign,{imm8,Imm8}} ->
207      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
208      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
209      ?BIT(24,1) bor sign(Sign) bor ?BF(22,21,2#11) bor ?BF(19,16,Rn) bor ?BF(11,8,Imm8 bsr 4) bor ?BF(3,0,Imm8 band 2#1111);
210    {register_pre_indexed,{r,Rn},Sign,{r,Rm}} ->
211      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
212      ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
213      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
214      ?ASSERT(Rm =/= Rn),	% UNPREDICTABLE
215      ?BIT(24,1) bor sign(Sign) bor ?BF(22,21,2#01) bor ?BF(19,16,Rn) bor ?BF(3,0,Rm);
216    {immediate_post_indexed,{r,Rn},Sign,{imm8,Imm8}} ->
217      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
218      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
219      ?BIT(24,0) bor sign(Sign) bor ?BF(22,21,2#10) bor ?BF(19,16,Rn) bor ?BF(11,8,Imm8 bsr 4) bor ?BF(3,0,Imm8 band 2#1111);
220    {register_post_indexed,{r,Rn},Sign,{r,Rm}} ->
221      ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
222      ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
223      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
224      ?ASSERT(Rm =/= Rn),	% UNPREDICTABLE
225      ?BIT(24,0) bor sign(Sign) bor ?BF(22,21,2#00) bor ?BF(19,16,Rn) bor ?BF(3,0,Rm)
226  end.
227
228am4_ls_multiple(L, AddressingMode) ->
229  case AddressingMode of
230    'ia' -> ?BF(24,23,2#01);
231    'ib' -> ?BF(24,23,2#11);
232    'da' -> ?BF(24,23,2#00);
233    'db' -> ?BF(24,23,2#10);
234    _ ->
235      %% context-sensitive alias crap
236      case {L,AddressingMode} of
237	{1,'fa'} -> ?BF(24,23,2#00);
238	{1,'fd'} -> ?BF(24,23,2#01);
239	{1,'ea'} -> ?BF(24,23,2#10);
240	{1,'ed'} -> ?BF(24,23,2#11);
241	{0,'ed'} -> ?BF(24,23,2#00);
242	{0,'ea'} -> ?BF(24,23,2#01);
243	{0,'fd'} -> ?BF(24,23,2#10);
244	{0,'fa'} -> ?BF(24,23,2#11)
245      end
246  end.
247
248am5_ls_coprocessor(AddressingMode) ->
249  case AddressingMode of
250    {offset,{r,Rn},Sign,{imm8,Imm8}} ->
251      ?BIT(24,1) bor sign(Sign) bor ?BF(19,16,Rn) bor ?BF(7,0,Imm8);
252    {pre_indexed,{r,Rn},Sign,{imm8,Imm8}} ->
253      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
254      ?BIT(24,1) bor sign(Sign) bor ?BIT(21,1) bor ?BF(19,16,Rn) bor ?BF(7,0,Imm8);
255    {post_indexed,{r,Rn},Sign,{imm8,Imm8}} ->
256      ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
257      sign(Sign) bor ?BIT(21,1) bor ?BF(19,16,Rn) bor ?BF(7,0,Imm8);
258    {unindexed,{r,Rn},{imm8,Imm8}} ->
259      ?BIT(23,1) bor ?BF(19,16,Rn) bor ?BF(7,0,Imm8)
260  end.
261
262%%%
263
264'cond'(Cond) ->
265  case Cond of
266    'eq' -> ?BF(31,28,2#0000);	% equal
267    'ne' -> ?BF(31,28,2#0001);	% not equal
268    'cs' -> ?BF(31,28,2#0010);	% carry set
269    'hs' -> ?BF(31,28,2#0010);	% unsigned higher or same
270    'cc' -> ?BF(31,28,2#0011);	% carry clear
271    'lo' -> ?BF(31,28,2#0011);	% unsigned lower
272    'mi' -> ?BF(31,28,2#0100);	% minus/negative
273    'pl' -> ?BF(31,28,2#0101);	% plus/positive or zero
274    'vs' -> ?BF(31,28,2#0110);	% overflow
275    'vc' -> ?BF(31,28,2#0111);	% no overflow
276    'hi' -> ?BF(31,28,2#1000);	% unsigned higher
277    'ls' -> ?BF(31,28,2#1001);	% unsigned lower or same
278    'ge' -> ?BF(31,28,2#1010);	% signed greater than or equal
279    'lt' -> ?BF(31,28,2#1011);	% signed less than
280    'gt' -> ?BF(31,28,2#1100);	% signed greater than
281    'le' -> ?BF(31,28,2#1101);	% signed less than or equal
282    'al' -> ?BF(31,28,2#1110)	% always
283  end.
284
285%%%
286%%% ARM Instructions
287%%%
288
289data_processing_form(Cond, OpCode, S, Rn, Rd, ShifterOperand) ->
290  case S of
291    1 -> ?ASSERT(Rd =/= 15);	% UNPREDICTABLE in User or System mode
292    _ -> []
293  end,
294  'cond'(Cond) bor ?BF(24,21,OpCode) bor ?BIT(20,S) bor ?BF(19,16,Rn) bor ?BF(15,12,Rd) bor am1_shifter_operand(Rn,Rd,ShifterOperand).
295
296data_processing_form(OpCode, {{'cond',Cond},{s,S},{r,Rd},{r,Rn},ShifterOperand}) ->
297  data_processing_form(Cond, OpCode, S, Rn, Rd, ShifterOperand).
298
299adc(Opnds) -> data_processing_form(2#0101, Opnds).
300add(Opnds) -> data_processing_form(2#0100, Opnds).
301'and'(Opnds) -> data_processing_form(2#0000, Opnds).
302bic(Opnds) -> data_processing_form(2#1110, Opnds).
303eor(Opnds) -> data_processing_form(2#0001, Opnds).
304orr(Opnds) -> data_processing_form(2#1100, Opnds).
305rsb(Opnds) -> data_processing_form(2#0011, Opnds).
306rsc(Opnds) -> data_processing_form(2#0111, Opnds).
307sbc(Opnds) -> data_processing_form(2#0110, Opnds).
308sub(Opnds) -> data_processing_form(2#0010, Opnds).
309
310cmp_form(OpCode, {{'cond',Cond},{r,Rn},ShifterOperand}) ->
311  data_processing_form(Cond, OpCode, 1, Rn, 0, ShifterOperand).
312
313cmn(Opnds) -> cmp_form(2#1011, Opnds).
314cmp(Opnds) -> cmp_form(2#1010, Opnds).
315teq(Opnds) -> cmp_form(2#1001, Opnds).
316tst(Opnds) -> cmp_form(2#1000, Opnds).
317
318mov_form(OpCode, {{'cond',Cond},{s,S},{r,Rd},ShifterOperand}) ->
319  data_processing_form(Cond, OpCode, S, 0, Rd, ShifterOperand).
320
321mov(Opnds) -> mov_form(2#1101, Opnds).
322mvn(Opnds) -> mov_form(2#1111, Opnds).
323
324%%%
325
326b_form(L, {{'cond',Cond},{imm24,Imm24}}) ->
327  'cond'(Cond) bor ?BF(27,25,2#101) bor ?BIT(24,L) bor ?BF(23,0,Imm24).
328
329b(Opnds) -> b_form(0, Opnds).
330bl(Opnds) -> b_form(1, Opnds).
331
332bkpt({{imm16,Imm16}}) ->
333  ?BF(31,28,2#1110) bor ?BF(27,20,2#00010010) bor ?BF(19,8,Imm16 bsr 4) bor ?BF(7,4,2#0111) bor ?BF(3,0,Imm16 band 2#1111).
334
335bx_form(SubOpcode, {{'cond',Cond},{r,Rm}}, IsBlx) ->
336  case IsBlx of
337    true -> ?ASSERT(Rm =/= 15);	% UNPREDICTABLE
338    _ -> []
339  end,
340  'cond'(Cond) bor ?BF(27,20,2#00010010) bor ?BF(19,16,2#1111) bor ?BF(15,12,2#1111) bor ?BF(11,8,2#1111) bor ?BF(7,4,SubOpcode) bor ?BF(3,0,Rm).
341
342blx(Opnds) ->
343  case Opnds of
344    {{imm25,Imm25}} ->	% u16-offset!
345      ?BF(31,28,2#1111) bor ?BF(27,25,2#101) bor ?BIT(24,Imm25 band 1) bor ?BF(23,0,Imm25 bsr 1);
346    _ ->
347      bx_form(2#0011, Opnds, true)
348  end.
349
350bx(Opnds) -> bx_form(2#0001, Opnds, false).
351
352cdp_form(Cond, CpOp4, CRn, CRd, CpNum, CpOp3, CRm) ->
353  Cond bor ?BF(27,24,2#1110) bor ?BF(23,20,CpOp4) bor ?BF(19,16,CRn) bor ?BF(15,12,CRd) bor ?BF(11,8,CpNum) bor ?BF(7,5,CpOp3) bor ?BF(3,0,CRm).
354
355cdp({{'cond',Cond},{cpnum,CpNum},{cpop4,CpOp4},{cr,CRd},{cr,CRn},{cr,CRm},{cpop3,CpOp3}}) ->
356  cdp_form('cond'(Cond), CpOp4, CRn, CRd, CpNum, CpOp3, CRm).
357
358cdp2({{cpnum,CpNum},{cpop4,CpOp4},{cr,CRd},{cr,CRn},{cr,CRm},{cpop3,CpOp3}}) ->
359  cdp_form(?BF(31,28,2#1111), CpOp4, CRn, CRd, CpNum, CpOp3, CRm).
360
361clz({{'cond',Cond},{r,Rd},{r,Rm}}) ->
362  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
363  ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
364  'cond'(Cond) bor ?BF(27,20,2#00010110) bor ?BF(19,16,2#1111) bor ?BF(15,12,Rd) bor ?BF(11,8,2#1111) bor ?BF(7,4,2#0001) bor ?BF(3,0,Rm).
365
366ldstc_form(Cond, L, B20, CRd, CpNum, AddressingMode) ->
367  Cond bor ?BF(27,25,2#110) bor ?BIT(22,L) bor ?BIT(20,B20) bor ?BF(15,12,CRd) bor ?BF(11,8,CpNum) bor am5_ls_coprocessor(AddressingMode).
368
369ldstc(B20, {{'cond',Cond},{l,L},{cpnum,CpNum},{cr,CRd},AddressingMode}) ->
370  ldstc_form('cond'(Cond), L, B20, CRd, CpNum, AddressingMode).
371
372ldc(Opnds) -> ldstc(1, Opnds).
373stc(Opnds) -> ldstc(0, Opnds).
374
375ldstc2(B20, {{l,L},{cpnum,CpNum},{cr,CRd},AddressingMode}) ->
376  ldstc_form(?BF(31,28,2#1111), L, B20, CRd, CpNum, AddressingMode).
377
378ldc2(Opnds) -> ldstc2(1, Opnds).
379stc2(Opnds) -> ldstc2(0, Opnds).
380
381ldstm_form(Cond, AddressingMode, W, L, Rn, Registers) ->
382  RegisterList = register_list(Registers),
383  ?ASSERT(RegisterList =/= 0),	% UNPREDICTABLE
384  ?ASSERT(Rn =/= 15),		% UNPREDICTABLE
385  case W of
386    1 ->
387      BitRn = 1 bsl Rn,
388      case L of
389	1 ->
390	  %% LDM! Rn in Registers is UNPREDICTABLE
391	  ?ASSERT((RegisterList band BitRn) =:= 0);
392	0 ->
393	  %% STM! Rn in Registers and not lowest is UNPREDICTABLE
394	  case RegisterList band BitRn of
395	    0 -> [];
396	    _ ->
397	      ?ASSERT((RegisterList band (-RegisterList)) =:= BitRn)
398	  end
399      end;
400    _ -> []
401  end,
402  'cond'(Cond) bor ?BF(27,25,2#100) bor am4_ls_multiple(L, AddressingMode) bor ?BIT(21,W) bor ?BIT(20,L) bor ?BF(19,16,Rn) bor ?BF(15,0,RegisterList).
403
404register_list(Registers) -> register_list(Registers, 0).
405
406register_list([{r,R}|Rs], Mask) -> register_list(Rs, Mask bor (1 bsl R));
407register_list([], Mask) -> Mask.
408
409ldstm(L, Opnds) ->
410  case Opnds of
411    {{'cond',Cond},AddressingMode,{r,Rn},'!',Registers} ->
412      ldstm_form(Cond, AddressingMode, 1, L, Rn, Registers);
413    {{'cond',Cond},AddressingMode,{r,Rn},Registers} ->
414      ldstm_form(Cond, AddressingMode, 0, L, Rn, Registers)
415    %% the ldm(2), ldm(3), and stm(2) forms are UNPREDICTABLE
416    %% in User or System mode
417  end.
418
419ldm(Opnds) -> ldstm(1, Opnds).
420stm(Opnds) -> ldstm(0, Opnds).
421
422ldstr_form2(B, L, {{'cond',Cond},{r,Rd},AddressingMode}) ->
423  'cond'(Cond) bor ?BF(27,26,2#01) bor am2_lswub(Rd, AddressingMode) bor ?BIT(22,B) bor ?BIT(20,L) bor ?BF(15,12,Rd).
424
425ldr(Opnds) -> ldstr_form2(0, 1, Opnds).
426ldrb(Opnds) -> ldstr_form2(1, 1, Opnds).
427str(Opnds) -> ldstr_form2(0, 0, Opnds).
428strb(Opnds) -> ldstr_form2(1, 0, Opnds).
429
430ldstr_form3(L, SubOpcode, {{'cond',Cond},{r,Rd},AddressingMode}) ->
431  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
432  'cond'(Cond) bor am3_miscls(Rd, AddressingMode) bor ?BIT(20,L) bor ?BF(15,12,Rd) bor ?BF(7,4,SubOpcode).
433
434ldrh(Opnds) -> ldstr_form3(1, 2#1011, Opnds).
435ldrsb(Opnds) -> ldstr_form3(1, 2#1101, Opnds).
436ldrsh(Opnds) -> ldstr_form3(1, 2#1111, Opnds).
437strh(Opnds) -> ldstr_form3(0, 2#1011, Opnds).
438
439mcr_form(Cond, OP1, CRn, Rd, CpNum, OP2, CRm) ->
440  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
441  Cond bor ?BF(27,24,2#1110) bor ?BF(23,21,OP1) bor ?BF(19,16,CRn) bor ?BF(15,12,Rd) bor ?BF(11,8,CpNum) bor ?BF(7,5,OP2) bor ?BIT(4,1) bor ?BF(3,0,CRm).
442
443mcr({{'cond',Cond},{cpnum,CpNum},{cpop3,OP1},{r,Rd},{cr,CRn},{cr,CRm},{cpop3,OP2}}) ->
444  mcr_form('cond'(Cond), OP1, CRn, Rd, CpNum, OP2, CRm).
445
446mcr2({{cpnum,CpNum},{cpop3,OP1},{r,Rd},{cr,CRn},{cr,CRm},{cpop3,OP2}}) ->
447  mcr_form(?BF(31,28,2#1111), OP1, CRn, Rd, CpNum, OP2, CRm).
448
449mla({{'cond',Cond},{s,S},{r,Rd},{r,Rm},{r,Rs},{r,Rn}}) ->
450  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
451  ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
452  ?ASSERT(Rs =/= 15),	% UNPREDICTABLE
453  ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
454  ?ASSERT(Rd =/= Rm),	% UNPREDICTABLE
455  'cond'(Cond) bor ?BIT(21,1) bor ?BIT(20,S) bor ?BF(19,16,Rd) bor ?BF(15,12,Rn) bor ?BF(11,8,Rs) bor ?BF(7,4,2#1001) bor ?BF(3,0,Rm).
456
457mrc_form(Cond, OP1, CRn, Rd, CpNum, OP2, CRm) ->
458  Cond bor ?BF(27,24,2#1110) bor ?BF(23,21,OP1) bor ?BIT(20,1) bor ?BF(19,16,CRn) bor ?BF(15,12,Rd) bor ?BF(11,8,CpNum) bor ?BF(7,5,OP2) bor ?BIT(4,1) bor ?BF(3,0,CRm).
459
460mrc({{'cond',Cond},{cpnum,CpNum},{cpop3,OP1},{r,Rd},{cr,CRn},{cr,CRm},{cpop3,OP2}}) ->
461  mrc_form('cond'(Cond), OP1, CRn, Rd, CpNum, OP2, CRm).
462
463mrc2({{cpnum,CpNum},{cpop3,OP1},{r,Rd},{cr,CRn},{cr,CRm},{cpop3,OP2}}) ->
464  mrc_form(?BF(31,28,2#1111), OP1, CRn, Rd, CpNum, OP2, CRm).
465
466mrs({{'cond',Cond},{r,Rd},'cpsr'}) ->
467  %% the SPSR form is UNPREDICTABLE in User or System mode
468  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
469  'cond'(Cond) bor ?BIT(24,1) bor ?BF(19,16,2#1111) bor ?BF(15,12,Rd).
470
471msr_form(Cond, FieldMask4, Operand) ->
472  'cond'(Cond) bor ?BIT(24,1) bor ?BIT(21,1) bor ?BF(19,16,FieldMask4) bor ?BF(15,12,2#1111) bor Operand.
473
474msr(Opnds) ->
475  %% the SPSR form is UNPREDICTABLE in User or System mode
476  case Opnds of
477    {{'cond',Cond},'cpsr',{field_mask,FieldMask4},{imm8,Imm8},{imm4,RotImm4}} ->
478      msr_form(Cond, FieldMask4, ?BIT(25,1) bor ?BF(11,8,RotImm4) bor ?BF(7,0,Imm8));
479    {{'cond',Cond},'cpsr',{field_mask,FieldMask4},{r,Rm}} ->
480      msr_form(Cond, FieldMask4, ?BF(3,0,Rm))
481  end.
482
483mul({{'cond',Cond},{s,S},{r,Rd},{r,Rm},{r,Rs}}) ->
484  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
485  ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
486  ?ASSERT(Rs =/= 15),	% UNPREDICTABLE
487  ?ASSERT(Rd =/= Rm),	% UNPREDICTABLE
488  'cond'(Cond) bor ?BIT(20,S) bor ?BF(19,16,Rd) bor ?BF(11,8,Rs) bor ?BF(7,4,2#1001) bor ?BF(3,0,Rm).
489
490ml_form2(OpCode, Cond, S, RdLo, RdHi, Rm, Rs) ->
491  ?ASSERT(RdHi =/= 15),	% UNPREDICTABLE
492  ?ASSERT(RdLo =/= 15),	% UNPREDICTABLE
493  ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
494  ?ASSERT(Rs =/= 15),	% UNPREDICTABLE
495  ?ASSERT(RdHi =/= RdLo),% UNPREDICTABLE
496  ?ASSERT(RdHi =/= Rm),	% UNPREDICTABLE
497  ?ASSERT(RdLo =/= Rm),	% UNPREDICTABLE
498  'cond'(Cond) bor ?BF(27,21,OpCode) bor ?BIT(20,S) bor ?BF(19,16,RdHi) bor ?BF(15,12,RdLo) bor ?BF(11,8,Rs) bor ?BF(7,4,2#1001) bor ?BF(3,0,Rm).
499
500ml_form(OpCode, {{'cond',Cond},{s,S},{r,RdLo},{r,RdHi},{r,Rm},{r,Rs}}) ->
501  ml_form2(OpCode, Cond, S, RdLo, RdHi, Rm, Rs).
502
503%%smlal(Opnds) -> ml_form(2#0000111, Opnds).
504smull(Opnds) -> ml_form(2#0000110, Opnds).
505umlal(Opnds) -> ml_form(2#0000101, Opnds).
506umull(Opnds) -> ml_form(2#0000100, Opnds).
507
508swi({{'cond',Cond},{imm24,Imm24}}) ->
509  'cond'(Cond) bor ?BF(27,24,2#1111) bor ?BF(23,0,Imm24).
510
511swp_form(B22, {{'cond',Cond},{r,Rd},{r,Rm},{r,Rn}}) ->
512  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
513  ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
514  ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
515  ?ASSERT(Rn =/= Rm),	% UNPREDICTABLE
516  ?ASSERT(Rn =/= Rd),	% UNPREDICTABLE
517  'cond'(Cond) bor ?BIT(24,1) bor ?BIT(22,B22) bor ?BF(19,16,Rn) bor ?BF(15,12,Rd) bor ?BF(7,4,2#1001) bor ?BF(3,0,Rm).
518
519swp(Opnds) -> swp_form(0, Opnds).
520swpb(Opnds) -> swp_form(1, Opnds).
521
522%%%
523%%% Enhanced DSP Extension Instructions
524%%%
525
526ldstrd_form(OpCode, {{'cond',Cond},{r,Rd},AddressingMode}) ->
527  ?ASSERT(Rd =/= 14),		% UNPREDICTABLE
528  ?ASSERT((Rd band 1) =:= 0),	% UNDEFINED
529  %% XXX: unpredictable if write-back and base reg Rn equals Rd or Rd+1
530  %% XXX: if is load then unpredictable if index reg Rm and Rm equals Rd or Rd+1
531  'cond'(Cond) bor am3_miscls(Rd, AddressingMode) bor ?BF(15,12,Rd) bor ?BF(7,4,OpCode).
532
533ldrd(Opnds) -> ldstrd_form(2#1101, Opnds).
534strd(Opnds) -> ldstrd_form(2#1111, Opnds).
535
536mcrr({{'cond',Cond},{cpnum,CpNum},{cpop4,OP},{r,Rd},{r,Rn},{cr,CRm}}) ->
537  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
538  ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
539  'cond'(Cond) bor ?BF(27,20,2#11000100) bor ?BF(19,16,Rn) bor ?BF(15,12,Rd) bor ?BF(11,8,CpNum) bor ?BF(7,4,OP) bor ?BF(3,0,CRm).
540
541mrrc({{'cond',Cond},{cpnum,CpNum},{cpop4,OP},{r,Rd},{r,Rn},{cr,CRm}}) ->
542  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
543  ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
544  ?ASSERT(Rd =/= Rn),	% UNPREDICTABLE
545  'cond'(Cond) bor ?BF(27,20,2#11000101) bor ?BF(19,16,Rn) bor ?BF(15,12,Rd) bor ?BF(11,8,CpNum) bor ?BF(7,4,OP) bor ?BF(3,0,CRm).
546
547pld({AddressingMode}) ->
548  AM = am2_lswub(42, AddressingMode), % 42 is a dummy reg nr
549  %% not all adressing modes are allowed: bit 24 must be 1
550  %% and bit 21 must be 0
551  ?ASSERT(((AM bsr 21) band 2#1001) =:= 2#1000),
552  16#F550F000 bor AM.
553
554q_form(OpCode, {{'cond',Cond},{r,Rd},{r,Rm},{r,Rn}}) ->
555  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
556  ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
557  ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
558  'cond'(Cond) bor ?BF(27,20,OpCode) bor ?BF(19,16,Rn) bor ?BF(15,11,Rd) bor ?BF(7,4,2#0101) bor ?BF(3,0,Rm).
559
560qadd(Opnds) -> q_form(2#00010000, Opnds).
561qdadd(Opnds) -> q_form(2#00010100, Opnds).
562qdsub(Opnds) -> q_form(2#00010110, Opnds).
563qsub(Opnds) -> q_form(2#00010010, Opnds).
564
565smlaxy_form(Cond, OpCode, Rd, Rn, Rs, Y, X, Rm) ->
566  ?ASSERT(Rd =/= 15),	% UNPREDICTABLE
567  ?ASSERT(Rm =/= 15),	% UNPREDICTABLE
568  ?ASSERT(Rs =/= 15),	% UNPREDICTABLE
569  ?ASSERT(Rn =/= 15),	% UNPREDICTABLE
570  'cond'(Cond) bor ?BF(27,20,OpCode) bor ?BF(19,16,Rd) bor ?BF(15,12,Rn) bor ?BF(11,8,Rs) bor ?BIT(7,1) bor ?BIT(6,Y) bor ?BIT(5,X) bor ?BF(3,0,Rm).
571
572smla({{bt,X},{bt,Y},{'cond',Cond},{r,Rd},{r,Rm},{r,Rs},{r,Rn}}) ->
573  smlaxy_form(Cond, 2#00010000, Rd, Rn, Rs, Y, X, Rm).
574
575smlal(Opnds) -> % may be regular ARM or DSP insn :-(
576  case Opnds of
577    {{'cond',Cond},{s,S},{r,RdLo},{r,RdHi},{r,Rm},{r,Rs}} ->
578      ml_form2(2#0000111, Cond, S, RdLo, RdHi, Rm, Rs);
579    {{bt,X},{bt,Y},{'cond',Cond},{r,RdLo},{r,RdHi},{r,Rm},{r,Rs}} ->
580      ?ASSERT(RdLo =/= RdHi),	% UNPREDICTABLE
581      smlaxy_form(Cond, 2#00010100, RdHi, RdLo, Rs, Y, X, Rm)
582  end.
583
584smlaw({{bt,Y},{'cond',Cond},{r,Rd},{r,Rm},{r,Rs},{r,Rn}}) ->
585  smlaxy_form(Cond, 2#00010010, Rd, Rn, Rs, Y, 0, Rm).
586
587smul({{bt,X},{bt,Y},{'cond',Cond},{r,Rd},{r,Rm},{r,Rs}}) ->
588  smlaxy_form(Cond, 2#00010110, Rd, 0, Rs, Y, X, Rm).
589
590smulw({{bt,Y},{'cond',Cond},{r,Rd},{r,Rm},{r,Rs}}) ->
591  smlaxy_form(Cond, 2#00010010, Rd, 0, Rs, Y, 1, Rm).
592
593%%%
594%%% Main Encode Dispatch
595%%%
596
597insn_encode(Op, Opnds) ->
598  case Op of
599    'adc' -> adc(Opnds);
600    'add' -> add(Opnds);
601    'and' -> 'and'(Opnds);
602    'b' -> b(Opnds);
603    'bic' -> bic(Opnds);
604    'bkpt' -> bkpt(Opnds);
605    'bl' -> bl(Opnds);
606    'blx' -> blx(Opnds);
607    'bx' -> bx(Opnds);
608    'cdp' -> cdp(Opnds);
609    'cdp2' -> cdp2(Opnds);
610    'clz' -> clz(Opnds);
611    'cmn' -> cmn(Opnds);
612    'cmp' -> cmp(Opnds);
613    'eor' -> eor(Opnds);
614    'ldc' -> ldc(Opnds);
615    'ldc2' -> ldc2(Opnds);
616    'ldm' -> ldm(Opnds);
617    'ldr' -> ldr(Opnds);
618    'ldrb' -> ldrb(Opnds);
619    'ldrd' -> ldrd(Opnds);
620    %% ldrbt: omitted
621    'ldrh' -> ldrh(Opnds);
622    'ldrsb' -> ldrsb(Opnds);
623    'ldrsh' -> ldrsh(Opnds);
624    %% ldrt: omitted
625    'mcr' -> mcr(Opnds);
626    'mcr2' -> mcr2(Opnds);
627    'mcrr' -> mcrr(Opnds);
628    'mla' -> mla(Opnds);
629    'mov' -> mov(Opnds);
630    'mrc' -> mrc(Opnds);
631    'mrc2' -> mrc2(Opnds);
632    'mrrc' -> mrrc(Opnds);
633    'mrs' -> mrs(Opnds);
634    'msr' -> msr(Opnds);
635    'mul' -> mul(Opnds);
636    'mvn' -> mvn(Opnds);
637    'orr' -> orr(Opnds);
638    'pld' -> pld(Opnds);
639    'qadd' -> qadd(Opnds);
640    'qdadd' -> qdadd(Opnds);
641    'qdsub' -> qdsub(Opnds);
642    'qsub' -> qsub(Opnds);
643    'rsb' -> rsb(Opnds);
644    'rsc' -> rsc(Opnds);
645    'sbc' -> sbc(Opnds);
646    'smla' -> smla(Opnds);
647    'smlal' -> smlal(Opnds); % may be regular ARM or DSP insn :-(
648    'smlaw' -> smlaw(Opnds);
649    'smull' -> smull(Opnds);
650    'smul' -> smul(Opnds);
651    'smulw' -> smulw(Opnds);
652    'stc' -> stc(Opnds);
653    'stc2' -> stc2(Opnds);
654    'stm' -> stm(Opnds);
655    'str' -> str(Opnds);
656    'strb' -> strb(Opnds);
657    %% strbt: omitted
658    'strd' -> strd(Opnds);
659    'strh' -> strh(Opnds);
660    %% strt: omitted
661    'sub' -> sub(Opnds);
662    'swi' -> swi(Opnds);
663    'swp' -> swp(Opnds);
664    'swpb' -> swpb(Opnds);
665    'teq' -> teq(Opnds);
666    'tst' -> tst(Opnds);
667    'umlal' -> umlal(Opnds);
668    'umull' -> umull(Opnds);
669    _ -> exit({?MODULE,insn_encode,Op})
670  end.
671
672%%%
673%%% Testing Interface
674%%%
675
676-ifdef(TESTING).
677
678say(OS, Str) ->
679  file:write(OS, Str).
680
681hex_digit(Dig0) ->
682  Dig = Dig0 band 16#F,
683  if Dig >= 16#A -> $A + (Dig - 16#A);
684     true -> $0 + Dig
685  end.
686
687say_byte(OS, Byte) ->
688  say(OS, [hex_digit(Byte bsr 4)]),
689  say(OS, [hex_digit(Byte)]).
690
691say_word(OS, Word) ->
692  say(OS, "0x"),
693  say_byte(OS, Word bsr 24),
694  say_byte(OS, Word bsr 16),
695  say_byte(OS, Word bsr 8),
696  say_byte(OS, Word).
697
698t(OS, Op, Opnds) ->
699  Word = insn_encode(Op, Opnds),
700  say(OS, "\t.long "),
701  say_word(OS, Word),
702  say(OS, "\n").
703
704dotest1(OS) ->
705  say(OS, "\t.text\n\t.align 4\n"),
706  %%
707  Rn = {r,9},
708  Rd = {r,8},	% must be even and less than 14 for some insns
709  Rm = {r,7},
710  Rs = {r,6},
711  RdLo = Rn,
712  RdHi = Rd,
713  Registers = [Rm,Rs,Rd],	% must exclude Rn for some insns
714  CRd = {cr,15},
715  CRn = {cr,14},
716  CRm = {cr,13},
717  BT0 = {bt,0},
718  BT1 = {bt,1},
719  CpNum = {cpnum,15},
720  CpOp3 = {cpop3,16#3},
721  CpOp4 = {cpop4,16#F},
722  L0 = {l,0},
723  L1 = {l,1},
724  S0 = {s,0},
725  S1 = {s,1},
726  FieldMask4 = {field_mask,16#F},
727  Imm4 = {imm4,16#F},
728  Imm5 = {imm5,16#1F},
729  Imm8 = {imm8,16#FF},
730  Imm12 = {imm12,16#FFF},
731  Imm16 = {imm16,16#FFFF},
732  Imm24 = {imm24,16#FFFFF},
733  Imm25 = {imm25,16#FFFFF1},
734  %%
735  AM1_1 = {Imm8,Imm4},
736  AM1_2 = Rm,
737  AM1_3_1 = {Rm,{'lsl',Imm5}},
738  AM1_3_2 = {Rm,{'lsr',Imm5}},
739  AM1_3_3 = {Rm,{'asr',Imm5}},
740  AM1_3_4 = {Rm,{'ror',Imm5}},
741  AM1_3_5 = {Rm,{'lsl',Rs}},
742  AM1_3_6 = {Rm,{'lsr',Rs}},
743  AM1_3_7 = {Rm,{'asr',Rs}},
744  AM1_3_8 = {Rm,{'ror',Rs}},
745  AM1_3_9 = {Rm,'rrx'},
746  %%
747  AM2ShiftOp1 = {'lsl',Imm5},
748  AM2ShiftOp2 = {'lsr',Imm5},
749  AM2ShiftOp3 = {'asr',Imm5},
750  AM2ShiftOp4 = {'ror',Imm5},
751  AM2ShiftOp5 = 'rrx',
752  SignP = '+',
753  SignM = '-',
754  AM2_1_1 = {immediate_offset,Rn,SignP,Imm12},
755  AM2_1_2 = {immediate_offset,Rn,SignM,Imm12},
756  AM2_2_1 = {register_offset,Rn,SignP,Rm},
757  AM2_2_2 = {register_offset,Rn,SignM,Rm},
758  AM2_3_1 = {scaled_register_offset,Rn,SignP,Rm,AM2ShiftOp1},
759  AM2_3_2 = {scaled_register_offset,Rn,SignM,Rm,AM2ShiftOp2},
760  AM2_3_3 = {scaled_register_offset,Rn,SignP,Rm,AM2ShiftOp3},
761  AM2_3_4 = {scaled_register_offset,Rn,SignM,Rm,AM2ShiftOp4},
762  AM2_3_5 = {scaled_register_offset,Rn,SignP,Rm,AM2ShiftOp5},
763  AM2_4_1 = {immediate_pre_indexed,Rn,SignP,Imm12},
764  AM2_4_2 = {immediate_pre_indexed,Rn,SignM,Imm12},
765  AM2_5_1 = {register_pre_indexed,Rn,SignP,Rm},
766  AM2_5_2 = {register_pre_indexed,Rn,SignM,Rm},
767  AM2_6_1 = {scaled_register_pre_indexed,Rn,SignP,Rm,AM2ShiftOp1},
768  AM2_6_2 = {scaled_register_pre_indexed,Rn,SignM,Rm,AM2ShiftOp2},
769  AM2_6_3 = {scaled_register_pre_indexed,Rn,SignP,Rm,AM2ShiftOp3},
770  AM2_6_4 = {scaled_register_pre_indexed,Rn,SignM,Rm,AM2ShiftOp4},
771  AM2_6_5 = {scaled_register_pre_indexed,Rn,SignP,Rm,AM2ShiftOp5},
772  AM2_7_1 = {immediate_post_indexed,Rn,SignP,Imm12},
773  AM2_7_2 = {immediate_post_indexed,Rn,SignM,Imm12},
774  AM2_8_1 = {register_post_indexed,Rn,SignP,Rm},
775  AM2_8_2 = {register_post_indexed,Rn,SignM,Rm},
776  AM2_9_1 = {scaled_register_post_indexed,Rn,SignP,Rm,AM2ShiftOp1},
777  AM2_9_2 = {scaled_register_post_indexed,Rn,SignM,Rm,AM2ShiftOp2},
778  AM2_9_3 = {scaled_register_post_indexed,Rn,SignP,Rm,AM2ShiftOp3},
779  AM2_9_4 = {scaled_register_post_indexed,Rn,SignM,Rm,AM2ShiftOp4},
780  AM2_9_5 = {scaled_register_post_indexed,Rn,SignP,Rm,AM2ShiftOp5},
781  %%
782  AM3_1_1 = {immediate_offset,Rn,SignP,Imm8},
783  AM3_1_2 = {immediate_offset,Rn,SignM,Imm8},
784  AM3_2_1 = {register_offset,Rn,SignP,Rm},
785  AM3_2_2 = {register_offset,Rn,SignM,Rm},
786  AM3_3_1 = {immediate_pre_indexed,Rn,SignP,Imm8},
787  AM3_3_2 = {immediate_pre_indexed,Rn,SignM,Imm8},
788  AM3_4_1 = {register_pre_indexed,Rn,SignP,Rm},
789  AM3_4_2 = {register_pre_indexed,Rn,SignM,Rm},
790  AM3_5_1 = {immediate_post_indexed,Rn,SignP,Imm8},
791  AM3_5_2 = {immediate_post_indexed,Rn,SignM,Imm8},
792  AM3_6_1 = {register_post_indexed,Rn,SignP,Rm},
793  AM3_6_2 = {register_post_indexed,Rn,SignM,Rm},
794  %%
795  AM4_1 = 'ia',
796  AM4_2 = 'ib',
797  AM4_3 = 'da',
798  AM4_4 = 'db',
799  AM4_5 = 'fa',
800  AM4_6 = 'fd',
801  AM4_7 = 'ea',
802  AM4_8 = 'ed',
803  %%
804  AM5_1_1 = {offset,Rn,SignP,Imm8},
805  AM5_1_2 = {offset,Rn,SignM,Imm8},
806  AM5_2_1 = {pre_indexed,Rn,SignP,Imm8},
807  AM5_2_2 = {pre_indexed,Rn,SignM,Imm8},
808  AM5_3_1 = {post_indexed,Rn,SignP,Imm8},
809  AM5_3_2 = {post_indexed,Rn,SignM,Imm8},
810  AM5_4 = {unindexed,Rn,Imm8},
811  %%
812  Cond_eq = {'cond','eq'},
813  Cond_ne = {'cond','ne'},
814  Cond_cs = {'cond','cs'},
815  Cond_hs = {'cond','hs'},
816  Cond_cc = {'cond','cc'},
817  Cond_lo = {'cond','lo'},
818  Cond_mi = {'cond','mi'},
819  Cond_pl = {'cond','pl'},
820  Cond_vs = {'cond','vs'},
821  Cond_vc = {'cond','vc'},
822  Cond_hi = {'cond','hi'},
823  Cond_ls = {'cond','ls'},
824  Cond_ge = {'cond','ge'},
825  Cond_lt = {'cond','lt'},
826  Cond_gt = {'cond','gt'},
827  Cond_le = {'cond','le'},
828  Cond_al = {'cond','al'},
829  %%
830  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_1}),		% test all AM1 operands
831  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_2}),
832  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_3_1}),
833  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_3_2}),
834  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_3_3}),
835  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_3_4}),
836  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_3_5}),
837  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_3_6}),
838  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_3_7}),
839  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_3_8}),
840  t(OS,'adc',{Cond_al,S0,Rd,Rn,AM1_3_9}),
841  t(OS,'add',{Cond_al,S0,Rd,Rn,AM1_1}),		% test all S operands
842  t(OS,'add',{Cond_al,S1,Rd,Rn,AM1_1}),
843  t(OS,'and',{Cond_eq,S0,Rd,Rn,AM1_1}),		% test all Cond operands
844  t(OS,'and',{Cond_ne,S0,Rd,Rn,AM1_1}),
845  t(OS,'and',{Cond_cs,S0,Rd,Rn,AM1_1}),
846  t(OS,'and',{Cond_hs,S0,Rd,Rn,AM1_1}),
847  t(OS,'and',{Cond_cc,S0,Rd,Rn,AM1_1}),
848  t(OS,'and',{Cond_lo,S0,Rd,Rn,AM1_1}),
849  t(OS,'and',{Cond_mi,S0,Rd,Rn,AM1_1}),
850  t(OS,'and',{Cond_pl,S0,Rd,Rn,AM1_1}),
851  t(OS,'and',{Cond_vs,S0,Rd,Rn,AM1_1}),
852  t(OS,'and',{Cond_vc,S0,Rd,Rn,AM1_1}),
853  t(OS,'and',{Cond_hi,S0,Rd,Rn,AM1_1}),
854  t(OS,'and',{Cond_ls,S0,Rd,Rn,AM1_1}),
855  t(OS,'and',{Cond_ge,S0,Rd,Rn,AM1_1}),
856  t(OS,'and',{Cond_lt,S0,Rd,Rn,AM1_1}),
857  t(OS,'and',{Cond_gt,S0,Rd,Rn,AM1_1}),
858  t(OS,'and',{Cond_le,S0,Rd,Rn,AM1_1}),
859  t(OS,'and',{Cond_al,S0,Rd,Rn,AM1_1}),
860  t(OS,'b',{Cond_al,Imm24}),
861  t(OS,'bic',{Cond_al,S0,Rd,Rn,AM1_1}),
862  t(OS,'bkpt',{Imm16}),
863  t(OS,'bl',{Cond_al,Imm24}),
864  t(OS,'blx',{Imm25}),
865  t(OS,'blx',{Cond_al,Rm}),
866  t(OS,'bx',{Cond_al,Rm}),
867  t(OS,'cdp',{Cond_al,CpNum,CpOp4,CRd,CRn,CRm,CpOp3}),
868  t(OS,'cdp2',{CpNum,CpOp4,CRd,CRn,CRm,CpOp3}),
869  t(OS,'clz',{Cond_al,Rd,Rm}),
870  t(OS,'cmn',{Cond_al,Rn,AM1_1}),
871  t(OS,'cmp',{Cond_al,Rn,AM1_1}),
872  t(OS,'eor',{Cond_al,S0,Rd,Rn,AM1_1}),
873  t(OS,'ldc',{Cond_al,L0,CpNum,CRd,AM5_1_1}),	% test all AM5 operands
874  t(OS,'ldc',{Cond_al,L1,CpNum,CRd,AM5_1_2}),
875  t(OS,'ldc',{Cond_al,L0,CpNum,CRd,AM5_2_1}),
876  t(OS,'ldc',{Cond_al,L1,CpNum,CRd,AM5_2_2}),
877  t(OS,'ldc',{Cond_al,L0,CpNum,CRd,AM5_3_1}),
878  t(OS,'ldc',{Cond_al,L1,CpNum,CRd,AM5_3_2}),
879  t(OS,'ldc',{Cond_al,L0,CpNum,CRd,AM5_4}),
880  t(OS,'ldc2',{L0,CpNum,CRd,AM5_1_1}),
881  t(OS,'ldm',{Cond_al,AM4_1,Rn,'!',Registers}),
882  t(OS,'ldm',{Cond_al,AM4_1,Rn,Registers}),	% test all AM4 operands
883  t(OS,'ldm',{Cond_al,AM4_2,Rn,Registers}),	% test all AM4 operands
884  t(OS,'ldm',{Cond_al,AM4_3,Rn,Registers}),	% test all AM4 operands
885  t(OS,'ldm',{Cond_al,AM4_4,Rn,Registers}),	% test all AM4 operands
886  t(OS,'ldm',{Cond_al,AM4_5,Rn,Registers}),	% test all AM4 operands
887  t(OS,'ldm',{Cond_al,AM4_6,Rn,Registers}),	% test all AM4 operands
888  t(OS,'ldm',{Cond_al,AM4_7,Rn,Registers}),	% test all AM4 operands
889  t(OS,'ldm',{Cond_al,AM4_8,Rn,Registers}),	% test all AM4 operands
890  t(OS,'ldr',{Cond_al,Rd,AM2_1_1}),		% test all AM2 operands
891  t(OS,'ldr',{Cond_al,Rd,AM2_1_2}),
892  t(OS,'ldr',{Cond_al,Rd,AM2_2_1}),
893  t(OS,'ldr',{Cond_al,Rd,AM2_2_2}),
894  t(OS,'ldr',{Cond_al,Rd,AM2_3_1}),
895  t(OS,'ldr',{Cond_al,Rd,AM2_3_2}),
896  t(OS,'ldr',{Cond_al,Rd,AM2_3_3}),
897  t(OS,'ldr',{Cond_al,Rd,AM2_3_4}),
898  t(OS,'ldr',{Cond_al,Rd,AM2_3_5}),
899  t(OS,'ldr',{Cond_al,Rd,AM2_4_1}),
900  t(OS,'ldr',{Cond_al,Rd,AM2_4_2}),
901  t(OS,'ldr',{Cond_al,Rd,AM2_5_1}),
902  t(OS,'ldr',{Cond_al,Rd,AM2_5_2}),
903  t(OS,'ldr',{Cond_al,Rd,AM2_6_1}),
904  t(OS,'ldr',{Cond_al,Rd,AM2_6_2}),
905  t(OS,'ldr',{Cond_al,Rd,AM2_6_3}),
906  t(OS,'ldr',{Cond_al,Rd,AM2_6_4}),
907  t(OS,'ldr',{Cond_al,Rd,AM2_6_5}),
908  t(OS,'ldr',{Cond_al,Rd,AM2_7_1}),
909  t(OS,'ldr',{Cond_al,Rd,AM2_7_2}),
910  t(OS,'ldr',{Cond_al,Rd,AM2_8_1}),
911  t(OS,'ldr',{Cond_al,Rd,AM2_8_2}),
912  t(OS,'ldr',{Cond_al,Rd,AM2_9_1}),
913  t(OS,'ldr',{Cond_al,Rd,AM2_9_2}),
914  t(OS,'ldr',{Cond_al,Rd,AM2_9_3}),
915  t(OS,'ldr',{Cond_al,Rd,AM2_9_4}),
916  t(OS,'ldr',{Cond_al,Rd,AM2_9_5}),
917  t(OS,'ldrb',{Cond_al,Rd,AM2_1_1}),
918  t(OS,'ldrd',{Cond_al,Rd,AM3_1_1}),
919  t(OS,'ldrh',{Cond_al,Rd,AM3_1_1}),	% test all AM3 operands
920  t(OS,'ldrh',{Cond_al,Rd,AM3_1_2}),
921  t(OS,'ldrh',{Cond_al,Rd,AM3_2_1}),
922  t(OS,'ldrh',{Cond_al,Rd,AM3_2_2}),
923  t(OS,'ldrh',{Cond_al,Rd,AM3_3_1}),
924  t(OS,'ldrh',{Cond_al,Rd,AM3_3_2}),
925  t(OS,'ldrh',{Cond_al,Rd,AM3_4_1}),
926  t(OS,'ldrh',{Cond_al,Rd,AM3_4_2}),
927  t(OS,'ldrh',{Cond_al,Rd,AM3_5_1}),
928  t(OS,'ldrh',{Cond_al,Rd,AM3_5_2}),
929  t(OS,'ldrh',{Cond_al,Rd,AM3_6_1}),
930  t(OS,'ldrh',{Cond_al,Rd,AM3_6_2}),
931  t(OS,'ldrsb',{Cond_al,Rd,AM3_1_1}),
932  t(OS,'ldrsh',{Cond_al,Rd,AM3_1_1}),
933  t(OS,'mcr',{Cond_al,CpNum,CpOp3,Rd,CRn,CRm,CpOp3}),
934  t(OS,'mcr2',{CpNum,CpOp3,Rd,CRn,CRm,CpOp3}),
935  t(OS,'mcrr',{Cond_al,CpNum,CpOp4,Rd,Rn,CRm}),
936  t(OS,'mla',{Cond_al,S0,Rd,Rm,Rs,Rn}),
937  t(OS,'mov',{Cond_al,S0,Rd,AM1_1}),
938  t(OS,'mrc',{Cond_al,CpNum,CpOp3,Rd,CRn,CRm,CpOp3}),
939  t(OS,'mrc2',{CpNum,CpOp3,Rd,CRn,CRm,CpOp3}),
940  t(OS,'mrrc',{Cond_al,CpNum,CpOp4,Rd,Rn,CRm}),
941  t(OS,'mrs',{Cond_al,Rd,'cpsr'}),
942  t(OS,'msr',{Cond_al,'cpsr',FieldMask4,Imm8,Imm4}),
943  t(OS,'msr',{Cond_al,'cpsr',FieldMask4,Rm}),
944  t(OS,'mul',{Cond_al,S0,Rd,Rm,Rs}),
945  t(OS,'mvn',{Cond_al,S1,Rd,AM1_1}),
946  t(OS,'orr',{Cond_al,S0,Rd,Rn,AM1_1}),
947  t(OS,'pld',{AM2_1_1}),
948  t(OS,'qadd',{Cond_al,Rd,Rm,Rn}),
949  t(OS,'qdadd',{Cond_al,Rd,Rm,Rn}),
950  t(OS,'qdsub',{Cond_al,Rd,Rm,Rn}),
951  t(OS,'qsub',{Cond_al,Rd,Rm,Rn}),
952  t(OS,'rsb',{Cond_al,S0,Rd,Rn,AM1_1}),
953  t(OS,'rsc',{Cond_al,S0,Rd,Rn,AM1_1}),
954  t(OS,'sbc',{Cond_al,S0,Rd,Rn,AM1_1}),
955  t(OS,'smla',{BT0,BT0,Cond_al,Rd,Rm,Rs,Rn}),
956  t(OS,'smla',{BT0,BT1,Cond_al,Rd,Rm,Rs,Rn}),
957  t(OS,'smla',{BT1,BT0,Cond_al,Rd,Rm,Rs,Rn}),
958  t(OS,'smla',{BT1,BT1,Cond_al,Rd,Rm,Rs,Rn}),
959  t(OS,'smlal',{Cond_al,S0,RdLo,RdHi,Rm,Rs}),
960  t(OS,'smlal',{BT0,BT1,Cond_al,RdLo,RdHi,Rm,Rs}),
961  t(OS,'smlaw',{BT1,Cond_al,Rd,Rm,Rs,Rn}),
962  t(OS,'smull',{Cond_al,S0,RdLo,RdHi,Rm,Rs}),
963  t(OS,'smul',{BT1,BT0,Cond_al,Rd,Rm,Rs}),
964  t(OS,'smulw',{BT1,Cond_al,Rd,Rm,Rs}),
965  t(OS,'stc',{Cond_al,L0,CpNum,CRd,AM5_1_1}),
966  t(OS,'stc2',{L0,CpNum,CRd,AM5_1_1}),
967  t(OS,'stm',{Cond_al,AM4_1,Rn,Registers}),
968  t(OS,'str',{Cond_al,Rd,AM2_1_1}),
969  t(OS,'strb',{Cond_al,Rd,AM2_1_1}),
970  t(OS,'strd',{Cond_al,Rd,AM3_1_1}),
971  t(OS,'strh',{Cond_al,Rd,AM3_1_1}),
972  t(OS,'sub',{Cond_al,S0,Rd,Rn,AM1_1}),
973  t(OS,'swi',{Cond_al,Imm24}),
974  t(OS,'swp',{Cond_al,Rd,Rm,Rn}),
975  t(OS,'swpb',{Cond_al,Rd,Rm,Rn}),
976  t(OS,'teq',{Cond_al,Rn,AM1_1}),
977  t(OS,'tst',{Cond_al,Rn,AM1_1}),
978  t(OS,'umlal',{Cond_al,S0,RdLo,RdHi,Rm,Rs}),
979  t(OS,'umull',{Cond_al,S0,RdLo,RdHi,Rm,Rs}),
980  [].
981
982dotest() -> dotest1(group_leader()).
983
984dotest(File) ->
985  {ok,OS} = file:open(File, [write]),
986  dotest1(OS),
987  file:close(OS).
988
989-endif.
990