1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
%% Copyright (c) 2001 by Erik Johansson. All Rights Reserved
3
%% -*- erlang-indent-level: 2 -*-
4
%% ====================================================================
5
%% Filename : hipe_sparc_verify.erl
6
%% Module : hipe_sparc_verify
9
%% History : * 2001-10-25 Erik Johansson (happi@csd.uu.se):
12
%% $Author: richardc $
13
%% $Date: 2002/10/01 12:47:17 $
15
%% ====================================================================
18
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
20
-module(hipe_sparc_verify).
23
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25
%% Verifies that a code sequence is well-formed.
27
%% NOTE: does not consider branch offsets.
29
verify([],Version) -> ok;
30
verify([X|Xs],Version) ->
31
case catch ver(X,Version) of
33
report('instruction ~w malformed~n',[X]);
38
ver(Label,_Version) when is_record(Label,label) ->
41
is_integer(L), L > 0 -> ok
44
ver(Nop,_Version) when is_record(Nop,nop) ->
46
ver(Comment,_Version) when is_record(Comment,comment) ->
48
ver(Align,_Version) when is_record(Align,align) ->
49
N = Align#align.alignment,
57
ver(Move,_Version) when is_record(Move,move) ->
60
case {reg(Dst),reg_or_imm13(Src)} of
63
ver(Cmov_cc,Version) when is_record(Cmov_cc,cmov_cc) ->
66
Dst = Cmov_cc#cmov_cc.dst,
67
Src = Cmov_cc#cmov_cc.src,
68
CC = Cmov_cc#cmov_cc.cc,
69
case {reg(Dst),reg_or_imm11(Src),int_cc(CC)} of
70
{true,true,true} -> ok
73
ver(Cmov_r,Version) when is_record(Cmov_r,cmov_r) ->
76
Dst = Cmov_r#cmov_r.dst,
77
Src = Cmov_r#cmov_r.src,
78
Pred = Cmov_r#cmov_r.reg,
79
Cond = Cmov_r#cmov_r.rcc,
80
case {reg(Dst),reg_or_imm10(Src),reg(Pred),reg_cc(Cond)} of
81
{true,true,true,true} -> ok
84
ver(Alu,Version) when is_record(Alu,alu) ->
89
case {reg(Dst),reg(Src1),alu_op(Op,Version),reg_or_imm13(Src2)} of
90
{true,true,true,true} ->
93
ver(Alu_cc,Version) when is_record(Alu_cc,alu_cc) ->
94
Dst = Alu_cc#alu_cc.dst,
95
Src1 = Alu_cc#alu_cc.src1,
96
Op = Alu_cc#alu_cc.op,
97
Src2 = Alu_cc#alu_cc.src2,
98
case {reg(Dst),reg(Src1),alu_cc_op(Op,Version),reg_or_imm13(Src2)} of
99
{true,true,true,true} -> ok
101
ver(Sethi,_Version) when is_record(Sethi,sethi) ->
102
Dst = Sethi#sethi.dst,
103
Const = Sethi#sethi.const,
104
case {reg(Dst),imm22(Const)} of
107
ver(Load,_Version) when is_record(Load,load) ->
109
Type = Load#load.type,
112
case {reg(Dst),loading_type(Type),reg(Src),reg_or_imm13(Off)} of
113
{true,true,true,true} -> ok
115
ver(Store,_Version) when is_record(Store,store) ->
116
Dst = Store#store.dst,
117
Off = Store#store.off,
118
Type = Store#store.type,
119
Src = Store#store.src,
120
case {reg(Dst),reg_or_imm13(Off),storing_type(Type),reg(Src)} of
121
{true,true,true,true} -> ok
123
ver(B,Version) when is_record(B,b) ->
129
case {int_cc(CC),prediction(Pred),annul_info(Annul)} of
130
{true,true,true} -> ok
133
case {int_cc(CC),prediction(Pred),annul_info(Annul)} of
134
{true,true,true} -> ok
137
ver(Br,Version) when is_record(Br,br) ->
144
case {reg(Reg),reg_cc(RC),prediction(Pred),annul_info(Annul)} of
145
{true,true,true,true} -> ok
148
ver(Jmp_link,_Version) when is_record(Jmp_link,jmp_link) ->
149
Target = Jmp_link#jmp_link.target,
150
Off = Jmp_link#jmp_link.off,
151
Link = Jmp_link#jmp_link.link,
152
case {reg(Target),reg_or_imm13(Off),reg(Link)} of
153
{true,true,true} -> ok
155
ver(Jmp,_Version) when is_record(Jmp,jmp) ->
156
Target = Jmp#jmp.target,
158
case {reg(Target),reg_or_imm13(Off)} of
161
ver(Call_link,_Version) when is_record(Call_link,call_link) ->
162
Link = Call_link#call_link.link,
168
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170
% Condition code handling.
173
reg_cc(RCond) -> % for BPr and CMOVr isns
181
_ -> false % XXX: serious error, should exit
202
_ -> false % XXX: serious error, should exit
206
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208
reg({reg,R}) when is_integer(R), R >= 0 -> true;
211
reg_or_imm13({imm,Imm}) ->
213
reg_or_imm13(Reg) -> reg(Reg).
215
reg_or_imm11({imm,Imm}) ->
217
reg_or_imm11(Reg) -> reg(Reg).
219
reg_or_imm10({imm,Imm}) ->
221
reg_or_imm10(Reg) -> reg(Reg).
223
% Note: does not verify branch offsets
225
%label_imm16({label,L}) when L > 0 -> true;
226
%label_imm16(_) -> false.
228
%label_imm19({label,L}) when L > 0 -> true;
229
%label_imm19(_) -> false.
231
%label_imm22({label,L}) when L > 0 -> true;
232
%label_imm22(_) -> false.
234
%label_imm30({label,L}) when L > 0 -> true;
235
%label_imm30(_) -> false.
237
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239
imm10(N) -> imm(N,10).
240
imm11(N) -> imm(N,11).
241
imm13(N) -> imm(N,13).
242
%imm16(N) -> imm(N,16).
243
%imm19(N) -> imm(N,19).
244
imm22(N) -> imm(N,22).
246
imm(Imm,N) when Imm >= -((1 bsl N+1)-1), Imm < (1 bsl N+1) ->
251
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253
prediction(taken) -> true;
254
prediction(untaken) -> true;
255
prediction(_) -> false.
257
annul_info(a) -> true;
258
annul_info(na) -> true;
259
annul_info(_) -> false.
261
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263
loading_type(X) -> data_type(X).
265
storing_type(X) -> data_type(X).
267
data_type(sb) -> true;
268
data_type(sh) -> true;
269
data_type(sw) -> true;
270
data_type(ub) -> true;
271
data_type(uh) -> true;
272
data_type(uw) -> true;
273
data_type(xw) -> true;
274
data_type(_) -> false.
276
alu_op(X,Version) -> int_op(X,Version).
278
alu_cc_op(X,Version) -> int_op(X,Version).
280
int_op('+',Version) -> is_version(Version,[8,9]);
281
int_op('+c',Version) -> is_version(Version,[8,9]);
282
int_op('and',Version) -> is_version(Version,[8,9]);
283
int_op('andn',Version) -> is_version(Version,[8,9]);
284
int_op('or',Version) -> is_version(Version,[8,9]);
285
int_op('orn',Version) -> is_version(Version,[8,9]);
286
int_op('xor',Version) -> is_version(Version,[8,9]);
287
int_op('xnor',Version) -> is_version(Version,[8,9]);
288
int_op('-',Version) -> is_version(Version,[8,9]);
289
int_op('-c',Version) -> is_version(Version,[8,9]);
290
int_op('<<',Version) -> is_version(Version,[8,9]);
291
int_op('>>',Version) -> is_version(Version,[8,9]);
292
int_op('>>?',Version) -> is_version(Version,[8,9]);
293
int_op('*s',Version) -> is_version(Version,[8,9]);
294
int_op('*u',Version) -> is_version(Version,[8,9]);
295
int_op('/s',Version) -> is_version(Version,[8,9]);
296
int_op('/u',Version) -> is_version(Version,[8,9]);
297
int_op('<<64',Version) -> is_version(Version,9);
298
int_op('>>64',Version) -> is_version(Version,9);
299
int_op('>>?64',Version) -> is_version(Version,9);
300
int_op('*64',Version) -> is_version(Version,9);
301
int_op('/s64',Version) -> is_version(Version,9);
302
int_op('/u64',Version) -> is_version(Version,9);
303
int_op(_,_) -> false.
305
is_version(Version,Version) -> true;
306
is_version(Version,VersionList) -> member(Version,VersionList).
308
member(Version,[Version|_]) -> true;
309
member(Version,[_|Versions]) -> member(Version,Versions);
310
member(_,[]) -> false.
313
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315
report(String,Args) -> io:format(String,Args), io:format('~n',[]).