xref: /netbsd-src/external/gpl3/gdb/dist/cpu/epiphany.opc (revision ba340e457da88a40806d62ac0f140844ca1436e9)
1a2e2270fSchristos/* Adapteva epiphany opcode support.  -*- C -*-
2a2e2270fSchristos
3a2e2270fSchristos   Copyright 2009, 2011 Free Software Foundation, Inc.
4a2e2270fSchristos
5a2e2270fSchristos   Contributed by Embecosm on behalf of Adapteva, Inc.
6a2e2270fSchristos
7a2e2270fSchristos   This file is part of the GNU Binutils and of GDB.
8a2e2270fSchristos
9a2e2270fSchristos   This program is free software; you can redistribute it and/or modify
10a2e2270fSchristos   it under the terms of the GNU General Public License as published by
11a2e2270fSchristos   the Free Software Foundation; either version 3 of the License, or
12a2e2270fSchristos   (at your option) any later version.
13a2e2270fSchristos
14a2e2270fSchristos   This program is distributed in the hope that it will be useful,
15a2e2270fSchristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
16a2e2270fSchristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17a2e2270fSchristos   GNU General Public License for more details.
18a2e2270fSchristos
19a2e2270fSchristos   You should have received a copy of the GNU General Public License
20a2e2270fSchristos   along with this program; if not, write to the Free Software
21a2e2270fSchristos   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22a2e2270fSchristos   MA 02110-1301, USA.  */
23a2e2270fSchristos
24a2e2270fSchristos/*
25a2e2270fSchristos   Each section is delimited with start and end markers.
26a2e2270fSchristos
27a2e2270fSchristos   <arch>-opc.h additions use: "-- opc.h"
28a2e2270fSchristos   <arch>-opc.c additions use: "-- opc.c"
29a2e2270fSchristos   <arch>-asm.c additions use: "-- asm.c"
30a2e2270fSchristos   <arch>-dis.c additions use: "-- dis.c"
31a2e2270fSchristos   <arch>-ibd.h additions use: "-- ibd.h".  */
32a2e2270fSchristos
33a2e2270fSchristos/* -- opc.h */
34a2e2270fSchristos
35a2e2270fSchristos/* enumerate relaxation types for gas. */
36a2e2270fSchristostypedef enum epiphany_relax_types
37a2e2270fSchristos{
38a2e2270fSchristos  EPIPHANY_RELAX_NONE=0,
39a2e2270fSchristos  EPIPHANY_RELAX_NEED_RELAXING,
40a2e2270fSchristos
41a2e2270fSchristos  EPIPHANY_RELAX_BRANCH_SHORT,	/* Fits into +127..-128 */
42a2e2270fSchristos  EPIPHANY_RELAX_BRANCH_LONG,	/* b/bl/b<cond> +-2*16 */
43a2e2270fSchristos
44a2e2270fSchristos  EPIPHANY_RELAX_ARITH_SIMM3,	/* add/sub -7..3 */
45a2e2270fSchristos  EPIPHANY_RELAX_ARITH_SIMM11,	/* add/sub -2**11-1 .. 2**10-1 */
46a2e2270fSchristos
47a2e2270fSchristos  EPIPHANY_RELAX_MOV_IMM8,		/* mov r,imm8 */
48a2e2270fSchristos  EPIPHANY_RELAX_MOV_IMM16,	/* mov r,imm16 */
49a2e2270fSchristos
50a2e2270fSchristos  EPIPHANY_RELAX_LDST_IMM3,	/* (ldr|str)* r,[r,disp3] */
51a2e2270fSchristos  EPIPHANY_RELAX_LDST_IMM11	/* (ldr|str)* r,[r,disp11] */
52a2e2270fSchristos
53a2e2270fSchristos} EPIPHANY_RELAX_TYPES;
54a2e2270fSchristos
55a2e2270fSchristos/* Override disassembly hashing... */
56a2e2270fSchristos
57a2e2270fSchristos/* Can only depend on instruction having 4 decode bits which gets us to the
58a2e2270fSchristos   major groups of 16/32 instructions. */
59a2e2270fSchristos#undef CGEN_DIS_HASH_SIZE
60a2e2270fSchristos#if 1
61a2e2270fSchristos
62a2e2270fSchristos/* hash code on the 4 LSBs */
63a2e2270fSchristos#define CGEN_DIS_HASH_SIZE 16
64a2e2270fSchristos
65a2e2270fSchristos#define CGEN_DIS_HASH(buf, value) ((*buf) & 0xf)
66a2e2270fSchristos#else
67a2e2270fSchristos#define CGEN_DIS_HASH_SIZE 1
68a2e2270fSchristos#define CGEN_DIS_HASH(buf, value) 0
69a2e2270fSchristos#endif
70a2e2270fSchristos
71a2e2270fSchristosextern const char * parse_shortregs (CGEN_CPU_DESC cd,
72a2e2270fSchristos				     const char ** strp,
73a2e2270fSchristos				     CGEN_KEYWORD * keywords,
74a2e2270fSchristos				     long * valuep);
75a2e2270fSchristos
76a2e2270fSchristosextern const char * parse_branch_addr (CGEN_CPU_DESC cd,
77a2e2270fSchristos				       const char ** strp,
78a2e2270fSchristos				       int opindex,
79a2e2270fSchristos				       int opinfo,
80a2e2270fSchristos				       enum cgen_parse_operand_result * resultp,
81a2e2270fSchristos				       bfd_vma *valuep);
82a2e2270fSchristos
83a2e2270fSchristos/* Allows reason codes to be output when assembler errors occur.  */
84a2e2270fSchristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS
85a2e2270fSchristos
86a2e2270fSchristos
87a2e2270fSchristos/* -- opc.c */
88a2e2270fSchristos
89a2e2270fSchristos
90a2e2270fSchristos
91a2e2270fSchristos/* -- asm.c */
92a2e2270fSchristosconst char *
93a2e2270fSchristosparse_shortregs (CGEN_CPU_DESC cd,
94a2e2270fSchristos		 const char ** strp,
95a2e2270fSchristos		 CGEN_KEYWORD * keywords,
96a2e2270fSchristos		 long * regno)
97a2e2270fSchristos{
98a2e2270fSchristos  const char * errmsg;
99a2e2270fSchristos
100a2e2270fSchristos  /* Parse register.  */
101a2e2270fSchristos  errmsg = cgen_parse_keyword (cd, strp, keywords, regno);
102a2e2270fSchristos
103a2e2270fSchristos  if (errmsg)
104a2e2270fSchristos    return errmsg;
105a2e2270fSchristos
106a2e2270fSchristos  if (*regno > 7)
107a2e2270fSchristos    errmsg = _("register unavailable for short instructions");
108a2e2270fSchristos
109a2e2270fSchristos  return errmsg;
110a2e2270fSchristos}
111a2e2270fSchristos
112a2e2270fSchristosstatic const char * parse_simm_not_reg (CGEN_CPU_DESC, const char **, int,
113a2e2270fSchristos					long *);
114a2e2270fSchristos
115a2e2270fSchristosstatic const char *
116a2e2270fSchristosparse_uimm_not_reg (CGEN_CPU_DESC cd,
117a2e2270fSchristos		    const char ** strp,
118a2e2270fSchristos		    int opindex,
119a2e2270fSchristos		    unsigned long * valuep)
120a2e2270fSchristos{
121a2e2270fSchristos  long * svalp = (void *) valuep;
122a2e2270fSchristos  return parse_simm_not_reg (cd, strp, opindex, svalp);
123a2e2270fSchristos}
124a2e2270fSchristos
125a2e2270fSchristos/* Handle simm3/simm11/imm3/imm12.  */
126a2e2270fSchristos
127a2e2270fSchristosstatic const char *
128a2e2270fSchristosparse_simm_not_reg (CGEN_CPU_DESC cd,
129a2e2270fSchristos		   const char ** strp,
130a2e2270fSchristos		   int opindex,
131a2e2270fSchristos		   long * valuep)
132a2e2270fSchristos{
133a2e2270fSchristos  const char * errmsg;
134a2e2270fSchristos
135a2e2270fSchristos  int   sign = 0;
136a2e2270fSchristos  int   bits = 0;
137a2e2270fSchristos
138a2e2270fSchristos  switch (opindex)
139a2e2270fSchristos    {
140a2e2270fSchristos    case EPIPHANY_OPERAND_SIMM3:
141a2e2270fSchristos      sign = 1; bits = 3; break;
142a2e2270fSchristos    case EPIPHANY_OPERAND_SIMM11:
143a2e2270fSchristos      sign = 1; bits = 11; break;
144a2e2270fSchristos    case EPIPHANY_OPERAND_DISP3:
145a2e2270fSchristos      sign = 0; bits = 3; break;
146a2e2270fSchristos    case EPIPHANY_OPERAND_DISP11:
147a2e2270fSchristos      /* Load/store displacement is a sign-magnitude 12 bit value.  */
148a2e2270fSchristos      sign = 0; bits = 11; break;
149a2e2270fSchristos    }
150a2e2270fSchristos
151a2e2270fSchristos  /* First try to parse as a register name and reject the operand.  */
152a2e2270fSchristos  errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names,valuep);
153a2e2270fSchristos  if (!errmsg)
154a2e2270fSchristos    return _("register name used as immediate value");
155a2e2270fSchristos
156a2e2270fSchristos  errmsg = (sign ? cgen_parse_signed_integer (cd, strp, opindex, valuep)
157a2e2270fSchristos	    : cgen_parse_unsigned_integer (cd, strp, opindex,
158a2e2270fSchristos					  (unsigned long *) valuep));
159a2e2270fSchristos  if (errmsg)
160a2e2270fSchristos    return errmsg;
161a2e2270fSchristos
162a2e2270fSchristos  if (sign)
163a2e2270fSchristos    errmsg = cgen_validate_signed_integer (*valuep,
164a2e2270fSchristos					  -((1L << bits) - 1), (1 << (bits - 1)) - 1);
165a2e2270fSchristos  else
166a2e2270fSchristos    errmsg = cgen_validate_unsigned_integer (*valuep, 0, (1L << bits) - 1);
167a2e2270fSchristos
168a2e2270fSchristos  return errmsg;
169a2e2270fSchristos}
170a2e2270fSchristos
171a2e2270fSchristosstatic const char *
172a2e2270fSchristosparse_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
173a2e2270fSchristos		 const char ** strp,
174a2e2270fSchristos		 int opindex ATTRIBUTE_UNUSED,
175a2e2270fSchristos		 unsigned long *valuep)
176a2e2270fSchristos{
177a2e2270fSchristos  if (**strp == '#')
178a2e2270fSchristos    ++*strp;			/* Skip leading hashes.  */
179a2e2270fSchristos
180a2e2270fSchristos  if (**strp == '-')
181a2e2270fSchristos    {
182a2e2270fSchristos      *valuep = 1;
183a2e2270fSchristos      ++*strp;
184a2e2270fSchristos    }
185a2e2270fSchristos  else if (**strp == '+')
186a2e2270fSchristos    {
187a2e2270fSchristos      *valuep = 0;
188a2e2270fSchristos      ++*strp;
189a2e2270fSchristos    }
190a2e2270fSchristos  else
191a2e2270fSchristos    *valuep = 0;
192a2e2270fSchristos
193a2e2270fSchristos  return NULL;
194a2e2270fSchristos}
195a2e2270fSchristos
196a2e2270fSchristosstatic const char *
197a2e2270fSchristosparse_imm8 (CGEN_CPU_DESC cd,
198a2e2270fSchristos	    const char ** strp,
199a2e2270fSchristos	    int opindex,
200a2e2270fSchristos	    bfd_reloc_code_real_type code,
201a2e2270fSchristos	    enum cgen_parse_operand_result * result_type,
202a2e2270fSchristos	    bfd_vma * valuep)
203a2e2270fSchristos{
204a2e2270fSchristos  const char * errmsg;
205a2e2270fSchristos  enum cgen_parse_operand_result rt;
206a2e2270fSchristos  long dummyval;
207a2e2270fSchristos
208a2e2270fSchristos  if (!result_type)
209a2e2270fSchristos    result_type = &rt;
210a2e2270fSchristos
211a2e2270fSchristos  code = BFD_RELOC_NONE;
212a2e2270fSchristos
213a2e2270fSchristos  if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names, &dummyval)
214a2e2270fSchristos      || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
215a2e2270fSchristos			      &dummyval))
216a2e2270fSchristos    /* Don't treat "mov ip,ip" as a move-immediate.  */
217a2e2270fSchristos    return _("register source in immediate move");
218a2e2270fSchristos
219a2e2270fSchristos  errmsg = cgen_parse_address (cd, strp, opindex, code, result_type, valuep);
220a2e2270fSchristos  if (errmsg)
221a2e2270fSchristos    return errmsg;
222a2e2270fSchristos
223a2e2270fSchristos  if (*result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
224a2e2270fSchristos    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xff);
225a2e2270fSchristos  else
226a2e2270fSchristos    errmsg = _("byte relocation unsupported");
227a2e2270fSchristos
228a2e2270fSchristos  *valuep &= 0xff;
229a2e2270fSchristos  return errmsg;
230a2e2270fSchristos}
231a2e2270fSchristos
232a2e2270fSchristosstatic const char * MISSING_CLOSE_PARENTHESIS = N_("missing `)'");
233a2e2270fSchristos
234a2e2270fSchristosstatic const char *
235a2e2270fSchristosparse_imm16 (CGEN_CPU_DESC cd,
236a2e2270fSchristos	     const char ** strp,
237a2e2270fSchristos	     int opindex,
238a2e2270fSchristos	     bfd_reloc_code_real_type code ATTRIBUTE_UNUSED,
239a2e2270fSchristos	     enum cgen_parse_operand_result * result_type,
240a2e2270fSchristos	     bfd_vma * valuep)
241a2e2270fSchristos{
242a2e2270fSchristos  const char * errmsg;
243a2e2270fSchristos  enum cgen_parse_operand_result rt;
244a2e2270fSchristos  long dummyval;
245a2e2270fSchristos
246a2e2270fSchristos  if (!result_type)
247a2e2270fSchristos    result_type = &rt;
248a2e2270fSchristos
249a2e2270fSchristos  if (strncasecmp (*strp, "%high(", 6) == 0)
250a2e2270fSchristos    {
251a2e2270fSchristos      *strp += 6;
252a2e2270fSchristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_HIGH,
253a2e2270fSchristos				   result_type, valuep);
254a2e2270fSchristos      if (**strp != ')')
255a2e2270fSchristos	return MISSING_CLOSE_PARENTHESIS;
256a2e2270fSchristos      ++*strp;
257a2e2270fSchristos      *valuep >>= 16;
258a2e2270fSchristos    }
259a2e2270fSchristos  else if (strncasecmp (*strp, "%low(", 5) == 0)
260a2e2270fSchristos    {
261a2e2270fSchristos      *strp += 5;
262a2e2270fSchristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_LOW,
263a2e2270fSchristos				   result_type, valuep);
264a2e2270fSchristos      if (**strp != ')')
265a2e2270fSchristos	return MISSING_CLOSE_PARENTHESIS;
266a2e2270fSchristos      ++*strp;
267a2e2270fSchristos    }
268a2e2270fSchristos  else if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names,
269a2e2270fSchristos				&dummyval)
270a2e2270fSchristos	   || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
271a2e2270fSchristos				   &dummyval))
272a2e2270fSchristos    /* Don't treat "mov ip,ip" as a move-immediate.  */
273a2e2270fSchristos    return _("register source in immediate move");
274a2e2270fSchristos  else
275a2e2270fSchristos    errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
276a2e2270fSchristos				 result_type, valuep);
277a2e2270fSchristos
278a2e2270fSchristos  if (!errmsg && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
279a2e2270fSchristos    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xffff);
280a2e2270fSchristos
281a2e2270fSchristos  *valuep &= 0xffff;
282a2e2270fSchristos  return errmsg;
283a2e2270fSchristos}
284a2e2270fSchristos
285a2e2270fSchristosconst char *
286a2e2270fSchristosparse_branch_addr (CGEN_CPU_DESC cd,
287a2e2270fSchristos		   const char ** strp,
288a2e2270fSchristos		   int opindex,
289a2e2270fSchristos		   int opinfo ATTRIBUTE_UNUSED,
290a2e2270fSchristos		   enum cgen_parse_operand_result * resultp ATTRIBUTE_UNUSED,
291a2e2270fSchristos		   bfd_vma *valuep ATTRIBUTE_UNUSED)
292a2e2270fSchristos{
293a2e2270fSchristos  const char * errmsg;
294a2e2270fSchristos  enum cgen_parse_operand_result result_type;
295a2e2270fSchristos  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
296a2e2270fSchristos  bfd_vma value;
297a2e2270fSchristos
298a2e2270fSchristos  switch (opindex)
299a2e2270fSchristos    {
300a2e2270fSchristos    case EPIPHANY_OPERAND_SIMM24:
301a2e2270fSchristos      code = BFD_RELOC_EPIPHANY_SIMM24;
302a2e2270fSchristos      break;
303a2e2270fSchristos
304a2e2270fSchristos    case EPIPHANY_OPERAND_SIMM8:
305a2e2270fSchristos      code = BFD_RELOC_EPIPHANY_SIMM8;
306a2e2270fSchristos      break;
307a2e2270fSchristos
308a2e2270fSchristos    default:
309a2e2270fSchristos      errmsg = _("ABORT: unknown operand");
310a2e2270fSchristos      return errmsg;
311a2e2270fSchristos    }
312a2e2270fSchristos
313a2e2270fSchristos  errmsg = cgen_parse_address (cd, strp, opindex, code,
314a2e2270fSchristos			       &result_type, &value);
315a2e2270fSchristos  if (errmsg == NULL)
316a2e2270fSchristos    {
317a2e2270fSchristos      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
318a2e2270fSchristos	{
319a2e2270fSchristos	  /* Act as if we had done a PC-relative branch, ala .+num.  */
320a2e2270fSchristos	  char buf[20];
321a2e2270fSchristos	  const char * bufp = (const char *) buf;
322a2e2270fSchristos
323a2e2270fSchristos	  sprintf (buf, ".+%ld", (long) value);
324a2e2270fSchristos	  errmsg = cgen_parse_address (cd, &bufp, opindex, code, &result_type,
325a2e2270fSchristos				       &value);
326a2e2270fSchristos	}
327a2e2270fSchristos
328a2e2270fSchristos      if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
329a2e2270fSchristos	{
330a2e2270fSchristos	  /* This will happen for things like (s2-s1) where s2 and s1
331a2e2270fSchristos	     are labels.  */
332a2e2270fSchristos	  /* Nothing further to be done.  */
333a2e2270fSchristos	}
334a2e2270fSchristos      else
335a2e2270fSchristos	errmsg = _("Not a pc-relative address.");
336a2e2270fSchristos    }
337a2e2270fSchristos  return errmsg;
338a2e2270fSchristos}
339a2e2270fSchristos
340a2e2270fSchristos/* -- dis.c */
341a2e2270fSchristos
342a2e2270fSchristos#define CGEN_PRINT_INSN epiphany_print_insn
343a2e2270fSchristos
344a2e2270fSchristosstatic int
345a2e2270fSchristosepiphany_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
346a2e2270fSchristos{
347a2e2270fSchristos  bfd_byte buf[CGEN_MAX_INSN_SIZE];
348a2e2270fSchristos  int buflen;
349a2e2270fSchristos  int status;
350a2e2270fSchristos
351a2e2270fSchristos  info->bytes_per_chunk = 2;
352*ba340e45Schristos  info->bytes_per_line = 4;
353a2e2270fSchristos
354a2e2270fSchristos  /* Attempt to read the base part of the insn.  */
355*ba340e45Schristos  buflen = cd->base_insn_bitsize / 8;
356a2e2270fSchristos  status = (*info->read_memory_func) (pc, buf, buflen, info);
357a2e2270fSchristos
358a2e2270fSchristos  /* Try again with the minimum part, if min < base.  */
359a2e2270fSchristos  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
360a2e2270fSchristos    {
361*ba340e45Schristos      buflen = cd->min_insn_bitsize / 8;
362a2e2270fSchristos      status = (*info->read_memory_func) (pc, buf, buflen, info);
363a2e2270fSchristos    }
364a2e2270fSchristos
365a2e2270fSchristos  if (status != 0)
366a2e2270fSchristos    {
367a2e2270fSchristos      (*info->memory_error_func) (status, pc, info);
368a2e2270fSchristos      return -1;
369a2e2270fSchristos    }
370a2e2270fSchristos
371a2e2270fSchristos  return print_insn (cd, pc, info, buf, buflen);
372a2e2270fSchristos}
373a2e2270fSchristos
374a2e2270fSchristos
375a2e2270fSchristosstatic void
376a2e2270fSchristosprint_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
377a2e2270fSchristos		 void * dis_info,
378a2e2270fSchristos		 long value,
379a2e2270fSchristos		 unsigned int attrs ATTRIBUTE_UNUSED,
380a2e2270fSchristos		 bfd_vma pc ATTRIBUTE_UNUSED,
381a2e2270fSchristos		 int length ATTRIBUTE_UNUSED)
382a2e2270fSchristos{
383a2e2270fSchristos  disassemble_info *info = (disassemble_info *) dis_info;
384a2e2270fSchristos  (*info->fprintf_func) (info->stream, value ? "-" : "+");
385a2e2270fSchristos}
386a2e2270fSchristos
387a2e2270fSchristosstatic void
388a2e2270fSchristosprint_simm_not_reg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
389a2e2270fSchristos		    void * dis_info,
390a2e2270fSchristos		    long value,
391a2e2270fSchristos		    unsigned int attrs ATTRIBUTE_UNUSED,
392a2e2270fSchristos		    bfd_vma pc ATTRIBUTE_UNUSED,
393a2e2270fSchristos		    int length ATTRIBUTE_UNUSED)
394a2e2270fSchristos{
395a2e2270fSchristos  print_address (cd, dis_info, value, attrs, pc, length);
396a2e2270fSchristos}
397a2e2270fSchristos
398a2e2270fSchristosstatic void
399a2e2270fSchristosprint_uimm_not_reg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
400a2e2270fSchristos		    void * dis_info,
401a2e2270fSchristos		    unsigned long value,
402a2e2270fSchristos		    unsigned int attrs ATTRIBUTE_UNUSED,
403a2e2270fSchristos		    bfd_vma pc ATTRIBUTE_UNUSED,
404a2e2270fSchristos		    int length ATTRIBUTE_UNUSED)
405a2e2270fSchristos{
406a2e2270fSchristos  disassemble_info *info = (disassemble_info *)dis_info;
407a2e2270fSchristos
408a2e2270fSchristos  if (value & 0x800)
409a2e2270fSchristos    (*info->fprintf_func) (info->stream, "-");
410a2e2270fSchristos
411a2e2270fSchristos  value &= 0x7ff;
412a2e2270fSchristos  print_address (cd, dis_info, value, attrs, pc, length);
413a2e2270fSchristos}
414a2e2270fSchristos
415a2e2270fSchristos
416a2e2270fSchristos/* -- */
417a2e2270fSchristos
418