OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [arm/] [neon-gen.ml] - Blame information for rev 709

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
(* Auto-generate ARM Neon intrinsics header file.
2
   Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
3
   Contributed by CodeSourcery.
4
 
5
   This file is part of GCC.
6
 
7
   GCC is free software; you can redistribute it and/or modify it under
8
   the terms of the GNU General Public License as published by the Free
9
   Software Foundation; either version 3, or (at your option) any later
10
   version.
11
 
12
   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
   for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with GCC; see the file COPYING3.  If not see
19
   .
20
 
21
   This is an O'Caml program.  The O'Caml compiler is available from:
22
 
23
     http://caml.inria.fr/
24
 
25
   Or from your favourite OS's friendly packaging system. Tested with version
26
   3.09.2, though other versions will probably work too.
27
 
28
   Compile with:
29
     ocamlc -c neon.ml
30
     ocamlc -o neon-gen neon.cmo neon-gen.ml
31
 
32
   Run with:
33
     ./neon-gen > arm_neon.h
34
*)
35
 
36
open Neon
37
 
38
(* The format codes used in the following functions are documented at:
39
     http://caml.inria.fr/pub/docs/manual-ocaml/libref/Format.html\
40
     #6_printflikefunctionsforprettyprinting
41
   (one line, remove the backslash.)
42
*)
43
 
44
(* Following functions can be used to approximate GNU indentation style.  *)
45
let start_function () =
46
  Format.printf "@[";
47
  ref 0
48
 
49
let end_function nesting =
50
  match !nesting with
51
 
52
  | _ -> failwith ("Bad nesting (ending function at level "
53
                   ^ (string_of_int !nesting) ^ ")")
54
 
55
let open_braceblock nesting =
56
  begin match !nesting with
57
 
58
  | _ -> Format.printf "@,@[  @<0>{@[@,"
59
  end;
60
  incr nesting
61
 
62
let close_braceblock nesting =
63
  decr nesting;
64
  match !nesting with
65
 
66
  | _ -> Format.printf "@]@,@<0>}@]"
67
 
68
let print_function arity fnname body =
69
  let ffmt = start_function () in
70
  Format.printf "__extension__ static __inline ";
71
  let inl = "__attribute__ ((__always_inline__))" in
72
  begin match arity with
73
    Arity0 ret ->
74
      Format.printf "%s %s@,%s (void)" (string_of_vectype ret) inl fnname
75
  | Arity1 (ret, arg0) ->
76
      Format.printf "%s %s@,%s (%s __a)" (string_of_vectype ret) inl fnname
77
                                        (string_of_vectype arg0)
78
  | Arity2 (ret, arg0, arg1) ->
79
      Format.printf "%s %s@,%s (%s __a, %s __b)"
80
        (string_of_vectype ret) inl fnname (string_of_vectype arg0)
81
        (string_of_vectype arg1)
82
  | Arity3 (ret, arg0, arg1, arg2) ->
83
      Format.printf "%s %s@,%s (%s __a, %s __b, %s __c)"
84
        (string_of_vectype ret) inl fnname (string_of_vectype arg0)
85
        (string_of_vectype arg1) (string_of_vectype arg2)
86
  | Arity4 (ret, arg0, arg1, arg2, arg3) ->
87
      Format.printf "%s %s@,%s (%s __a, %s __b, %s __c, %s __d)"
88
        (string_of_vectype ret) inl fnname (string_of_vectype arg0)
89
        (string_of_vectype arg1) (string_of_vectype arg2)
90
        (string_of_vectype arg3)
91
  end;
92
  open_braceblock ffmt;
93
  let rec print_lines = function
94
    [] -> ()
95
  | [line] -> Format.printf "%s" line
96
  | line::lines -> Format.printf "%s@," line; print_lines lines in
97
  print_lines body;
98
  close_braceblock ffmt;
99
  end_function ffmt
100
 
101
let return_by_ptr features = List.mem ReturnPtr features
102
 
103
let union_string num elts base =
104
  let itype = inttype_for_array num elts in
105
  let iname = string_of_inttype itype
106
  and sname = string_of_vectype (T_arrayof (num, elts)) in
107
  Printf.sprintf "union { %s __i; %s __o; } %s" sname iname base
108
 
109
let rec signed_ctype = function
110
    T_uint8x8 | T_poly8x8 -> T_int8x8
111
  | T_uint8x16 | T_poly8x16 -> T_int8x16
112
  | T_uint16x4 | T_poly16x4 -> T_int16x4
113
  | T_uint16x8 | T_poly16x8 -> T_int16x8
114
  | T_uint32x2 -> T_int32x2
115
  | T_uint32x4 -> T_int32x4
116
  | T_uint64x1 -> T_int64x1
117
  | T_uint64x2 -> T_int64x2
118
  (* Cast to types defined by mode in arm.c, not random types pulled in from
119
     the  header in use. This fixes incompatible pointer errors when
120
     compiling with C++.  *)
121
  | T_uint8 | T_int8 -> T_intQI
122
  | T_uint16 | T_int16 -> T_intHI
123
  | T_uint32 | T_int32 -> T_intSI
124
  | T_uint64 | T_int64 -> T_intDI
125
  | T_float32 -> T_floatSF
126
  | T_poly8 -> T_intQI
127
  | T_poly16 -> T_intHI
128
  | T_arrayof (n, elt) -> T_arrayof (n, signed_ctype elt)
129
  | T_ptrto elt -> T_ptrto (signed_ctype elt)
130
  | T_const elt -> T_const (signed_ctype elt)
131
  | x -> x
132
 
133
let add_cast ctype cval =
134
  let stype = signed_ctype ctype in
135
  if ctype <> stype then
136
    Printf.sprintf "(%s) %s" (string_of_vectype stype) cval
137
  else
138
    cval
139
 
140
let cast_for_return to_ty = "(" ^ (string_of_vectype to_ty) ^ ")"
141
 
142
(* Return a tuple of a list of declarations to go at the start of the function,
143
   and a list of statements needed to return THING.  *)
144
let return arity return_by_ptr thing =
145
  match arity with
146
    Arity0 (ret) | Arity1 (ret, _) | Arity2 (ret, _, _) | Arity3 (ret, _, _, _)
147
  | Arity4 (ret, _, _, _, _) ->
148
    match ret with
149
      T_arrayof (num, vec) ->
150
        if return_by_ptr then
151
          let sname = string_of_vectype ret in
152
          [Printf.sprintf "%s __rv;" sname],
153
          [thing ^ ";"; "return __rv;"]
154
        else
155
          let uname = union_string num vec "__rv" in
156
          [uname ^ ";"], ["__rv.__o = " ^ thing ^ ";"; "return __rv.__i;"]
157
    | T_void -> [], [thing ^ ";"]
158
    | _ ->
159
        [], ["return " ^ (cast_for_return ret) ^ thing ^ ";"]
160
 
161
let rec element_type ctype =
162
  match ctype with
163
    T_arrayof (_, v) -> element_type v
164
  | _ -> ctype
165
 
166
let params return_by_ptr ps =
167
  let pdecls = ref [] in
168
  let ptype t p =
169
    match t with
170
      T_arrayof (num, elts) ->
171
        let uname = union_string num elts (p ^ "u") in
172
        let decl = Printf.sprintf "%s = { %s };" uname p in
173
        pdecls := decl :: !pdecls;
174
        p ^ "u.__o"
175
    | _ -> add_cast t p in
176
  let plist = match ps with
177
    Arity0 _ -> []
178
  | Arity1 (_, t1) -> [ptype t1 "__a"]
179
  | Arity2 (_, t1, t2) -> [ptype t1 "__a"; ptype t2 "__b"]
180
  | Arity3 (_, t1, t2, t3) -> [ptype t1 "__a"; ptype t2 "__b"; ptype t3 "__c"]
181
  | Arity4 (_, t1, t2, t3, t4) ->
182
      [ptype t1 "__a"; ptype t2 "__b"; ptype t3 "__c"; ptype t4 "__d"] in
183
  match ps with
184
    Arity0 ret | Arity1 (ret, _) | Arity2 (ret, _, _) | Arity3 (ret, _, _, _)
185
  | Arity4 (ret, _, _, _, _) ->
186
      if return_by_ptr then
187
        !pdecls, add_cast (T_ptrto (element_type ret)) "&__rv.val[0]" :: plist
188
      else
189
        !pdecls, plist
190
 
191
let modify_params features plist =
192
  let is_flipped =
193
    List.exists (function Flipped _ -> true | _ -> false) features in
194
  if is_flipped then
195
    match plist with
196
      [ a; b ] -> [ b; a ]
197
    | _ ->
198
      failwith ("Don't know how to flip args " ^ (String.concat ", " plist))
199
  else
200
    plist
201
 
202
(* !!! Decide whether to add an extra information word based on the shape
203
   form.  *)
204
let extra_word shape features paramlist bits =
205
  let use_word =
206
    match shape with
207
      All _ | Long | Long_noreg _ | Wide | Wide_noreg _ | Narrow
208
    | By_scalar _ | Wide_scalar | Wide_lane | Binary_imm _ | Long_imm
209
    | Narrow_imm -> true
210
    | _ -> List.mem InfoWord features
211
  in
212
    if use_word then
213
      paramlist @ [string_of_int bits]
214
    else
215
      paramlist
216
 
217
(* Bit 0 represents signed (1) vs unsigned (0), or float (1) vs poly (0).
218
   Bit 1 represents floats & polynomials (1), or ordinary integers (0).
219
   Bit 2 represents rounding (1) vs none (0).  *)
220
let infoword_value elttype features =
221
  let bits01 =
222
    match elt_class elttype with
223
      Signed | ConvClass (Signed, _) | ConvClass (_, Signed) -> 0b001
224
    | Poly -> 0b010
225
    | Float -> 0b011
226
    | _ -> 0b000
227
  and rounding_bit = if List.mem Rounding features then 0b100 else 0b000 in
228
  bits01 lor rounding_bit
229
 
230
(* "Cast" type operations will throw an exception in mode_of_elt (actually in
231
   elt_width, called from there). Deal with that here, and generate a suffix
232
   with multiple modes ().  *)
233
let rec mode_suffix elttype shape =
234
  try
235
    let mode = mode_of_elt elttype shape in
236
    string_of_mode mode
237
  with MixedMode (dst, src) ->
238
    let dstmode = mode_of_elt dst shape
239
    and srcmode = mode_of_elt src shape in
240
    string_of_mode dstmode ^ string_of_mode srcmode
241
 
242
let print_variant opcode features shape name (ctype, asmtype, elttype) =
243
  let bits = infoword_value elttype features in
244
  let modesuf = mode_suffix elttype shape in
245
  let return_by_ptr = return_by_ptr features in
246
  let pdecls, paramlist = params return_by_ptr ctype in
247
  let paramlist' = modify_params features paramlist in
248
  let paramlist'' = extra_word shape features paramlist' bits in
249
  let parstr = String.concat ", " paramlist'' in
250
  let builtin = Printf.sprintf "__builtin_neon_%s%s (%s)"
251
                  (builtin_name features name) modesuf parstr in
252
  let rdecls, stmts = return ctype return_by_ptr builtin in
253
  let body = pdecls @ rdecls @ stmts
254
  and fnname = (intrinsic_name name) ^ "_" ^ (string_of_elt elttype) in
255
  print_function ctype fnname body
256
 
257
(* When this function processes the element types in the ops table, it rewrites
258
   them in a list of tuples (a,b,c):
259
     a : C type as an "arity", e.g. Arity1 (T_poly8x8, T_poly8x8)
260
     b : Asm type : a single, processed element type, e.g. P16. This is the
261
         type which should be attached to the asm opcode.
262
     c : Variant type : the unprocessed type for this variant (e.g. in add
263
         instructions which don't care about the sign, b might be i16 and c
264
         might be s16.)
265
*)
266
 
267
let print_op (opcode, features, shape, name, munge, types) =
268
  let sorted_types = List.sort compare types in
269
  let munged_types = List.map
270
    (fun elt -> let c, asm = munge shape elt in c, asm, elt) sorted_types in
271
  List.iter
272
    (fun variant -> print_variant opcode features shape name variant)
273
    munged_types
274
 
275
let print_ops ops =
276
  List.iter print_op ops
277
 
278
(* Output type definitions. Table entries are:
279
     cbase : "C" name for the type.
280
     abase : "ARM" base name for the type (i.e. int in int8x8_t).
281
     esize : element size.
282
     enum : element count.
283
*)
284
 
285
let deftypes () =
286
  let typeinfo = [
287
    (* Doubleword vector types.  *)
288
    "__builtin_neon_qi", "int", 8, 8;
289
    "__builtin_neon_hi", "int", 16, 4;
290
    "__builtin_neon_si", "int", 32, 2;
291
    "__builtin_neon_di", "int", 64, 1;
292
    "__builtin_neon_sf", "float", 32, 2;
293
    "__builtin_neon_poly8", "poly", 8, 8;
294
    "__builtin_neon_poly16", "poly", 16, 4;
295
    "__builtin_neon_uqi", "uint", 8, 8;
296
    "__builtin_neon_uhi", "uint", 16, 4;
297
    "__builtin_neon_usi", "uint", 32, 2;
298
    "__builtin_neon_udi", "uint", 64, 1;
299
 
300
    (* Quadword vector types.  *)
301
    "__builtin_neon_qi", "int", 8, 16;
302
    "__builtin_neon_hi", "int", 16, 8;
303
    "__builtin_neon_si", "int", 32, 4;
304
    "__builtin_neon_di", "int", 64, 2;
305
    "__builtin_neon_sf", "float", 32, 4;
306
    "__builtin_neon_poly8", "poly", 8, 16;
307
    "__builtin_neon_poly16", "poly", 16, 8;
308
    "__builtin_neon_uqi", "uint", 8, 16;
309
    "__builtin_neon_uhi", "uint", 16, 8;
310
    "__builtin_neon_usi", "uint", 32, 4;
311
    "__builtin_neon_udi", "uint", 64, 2
312
  ] in
313
  List.iter
314
    (fun (cbase, abase, esize, enum) ->
315
      let attr =
316
        match enum with
317
          1 -> ""
318
        | _ -> Printf.sprintf "\t__attribute__ ((__vector_size__ (%d)))"
319
                              (esize * enum / 8) in
320
      Format.printf "typedef %s %s%dx%d_t%s;@\n" cbase abase esize enum attr)
321
    typeinfo;
322
  Format.print_newline ();
323
  (* Extra types not in .  *)
324
  Format.printf "typedef float float32_t;\n";
325
  Format.printf "typedef __builtin_neon_poly8 poly8_t;\n";
326
  Format.printf "typedef __builtin_neon_poly16 poly16_t;\n"
327
 
328
(* Output structs containing arrays, for load & store instructions etc.  *)
329
 
330
let arrtypes () =
331
  let typeinfo = [
332
    "int", 8;    "int", 16;
333
    "int", 32;   "int", 64;
334
    "uint", 8;   "uint", 16;
335
    "uint", 32;  "uint", 64;
336
    "float", 32; "poly", 8;
337
    "poly", 16
338
  ] in
339
  let writestruct elname elsize regsize arrsize =
340
    let elnum = regsize / elsize in
341
    let structname =
342
      Printf.sprintf "%s%dx%dx%d_t" elname elsize elnum arrsize in
343
    let sfmt = start_function () in
344
    Format.printf "typedef struct %s" structname;
345
    open_braceblock sfmt;
346
    Format.printf "%s%dx%d_t val[%d];" elname elsize elnum arrsize;
347
    close_braceblock sfmt;
348
    Format.printf " %s;" structname;
349
    end_function sfmt;
350
  in
351
    for n = 2 to 4 do
352
      List.iter
353
        (fun (elname, elsize) ->
354
          writestruct elname elsize 64 n;
355
          writestruct elname elsize 128 n)
356
        typeinfo
357
    done
358
 
359
let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
360
 
361
(* Do it.  *)
362
 
363
let _ =
364
  print_lines [
365
"/* ARM NEON intrinsics include file. This file is generated automatically";
366
"   using neon-gen.ml.  Please do not edit manually.";
367
"";
368
"   Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.";
369
"   Contributed by CodeSourcery.";
370
"";
371
"   This file is part of GCC.";
372
"";
373
"   GCC is free software; you can redistribute it and/or modify it";
374
"   under the terms of the GNU General Public License as published";
375
"   by the Free Software Foundation; either version 3, or (at your";
376
"   option) any later version.";
377
"";
378
"   GCC is distributed in the hope that it will be useful, but WITHOUT";
379
"   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
380
"   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public";
381
"   License for more details.";
382
"";
383
"   Under Section 7 of GPL version 3, you are granted additional";
384
"   permissions described in the GCC Runtime Library Exception, version";
385
"   3.1, as published by the Free Software Foundation.";
386
"";
387
"   You should have received a copy of the GNU General Public License and";
388
"   a copy of the GCC Runtime Library Exception along with this program;";
389
"   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see";
390
"   .  */";
391
"";
392
"#ifndef _GCC_ARM_NEON_H";
393
"#define _GCC_ARM_NEON_H 1";
394
"";
395
"#ifndef __ARM_NEON__";
396
"#error You must enable NEON instructions (e.g. -mfloat-abi=softfp -mfpu=neon) to use arm_neon.h";
397
"#else";
398
"";
399
"#ifdef __cplusplus";
400
"extern \"C\" {";
401
"#endif";
402
"";
403
"#include ";
404
""];
405
  deftypes ();
406
  arrtypes ();
407
  Format.print_newline ();
408
  print_ops ops;
409
  Format.print_newline ();
410
  print_ops reinterp;
411
  print_lines [
412
"#ifdef __cplusplus";
413
"}";
414
"#endif";
415
"#endif";
416
"#endif"]

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.