nios2-dis.c revision 1.3 1 1.1 christos /* Altera Nios II disassemble routines
2 1.3 christos Copyright (C) 2012-2015 Free Software Foundation, Inc.
3 1.1 christos Contributed by Nigel Gray (ngray (at) altera.com).
4 1.1 christos Contributed by Mentor Graphics, Inc.
5 1.1 christos
6 1.1 christos This file is part of the GNU opcodes library.
7 1.1 christos
8 1.1 christos This library is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3, or (at your option)
11 1.1 christos any later version.
12 1.1 christos
13 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
14 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 1.1 christos License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with this file; see the file COPYING. If not, write to the
20 1.1 christos Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
21 1.1 christos MA 02110-1301, USA. */
22 1.1 christos
23 1.1 christos #include "sysdep.h"
24 1.1 christos #include "dis-asm.h"
25 1.1 christos #include "opcode/nios2.h"
26 1.1 christos #include "libiberty.h"
27 1.1 christos #include <string.h>
28 1.1 christos #include <assert.h>
29 1.1 christos
30 1.1 christos /* No symbol table is available when this code runs out in an embedded
31 1.1 christos system as when it is used for disassembler support in a monitor. */
32 1.1 christos #if !defined(EMBEDDED_ENV)
33 1.1 christos #define SYMTAB_AVAILABLE 1
34 1.1 christos #include "elf-bfd.h"
35 1.1 christos #include "elf/nios2.h"
36 1.1 christos #endif
37 1.1 christos
38 1.3 christos /* Default length of Nios II instruction in bytes. */
39 1.1 christos #define INSNLEN 4
40 1.1 christos
41 1.1 christos /* Data structures used by the opcode hash table. */
42 1.1 christos typedef struct _nios2_opcode_hash
43 1.1 christos {
44 1.1 christos const struct nios2_opcode *opcode;
45 1.1 christos struct _nios2_opcode_hash *next;
46 1.1 christos } nios2_opcode_hash;
47 1.1 christos
48 1.3 christos /* Hash table size. */
49 1.3 christos #define OPCODE_HASH_SIZE (IW_R1_OP_UNSHIFTED_MASK + 1)
50 1.1 christos
51 1.3 christos /* Extract the opcode from an instruction word. */
52 1.3 christos static unsigned int
53 1.3 christos nios2_r1_extract_opcode (unsigned int x)
54 1.3 christos {
55 1.3 christos return GET_IW_R1_OP (x);
56 1.3 christos }
57 1.3 christos
58 1.3 christos /* Pseudo-ops are stored in a different table than regular instructions. */
59 1.3 christos
60 1.3 christos typedef struct _nios2_disassembler_state
61 1.3 christos {
62 1.3 christos const struct nios2_opcode *opcodes;
63 1.3 christos const int *num_opcodes;
64 1.3 christos unsigned int (*extract_opcode) (unsigned int);
65 1.3 christos nios2_opcode_hash *hash[OPCODE_HASH_SIZE];
66 1.3 christos nios2_opcode_hash *ps_hash[OPCODE_HASH_SIZE];
67 1.3 christos const struct nios2_opcode *nop;
68 1.3 christos bfd_boolean init;
69 1.3 christos } nios2_disassembler_state;
70 1.3 christos
71 1.3 christos static nios2_disassembler_state
72 1.3 christos nios2_r1_disassembler_state = {
73 1.3 christos nios2_r1_opcodes,
74 1.3 christos &nios2_num_r1_opcodes,
75 1.3 christos nios2_r1_extract_opcode,
76 1.3 christos {},
77 1.3 christos {},
78 1.3 christos NULL,
79 1.3 christos 0
80 1.3 christos };
81 1.1 christos
82 1.1 christos /* Function to initialize the opcode hash table. */
83 1.1 christos static void
84 1.3 christos nios2_init_opcode_hash (nios2_disassembler_state *state)
85 1.1 christos {
86 1.1 christos unsigned int i;
87 1.1 christos register const struct nios2_opcode *op;
88 1.1 christos
89 1.3 christos for (i = 0; i < OPCODE_HASH_SIZE; i++)
90 1.3 christos for (op = state->opcodes; op < &state->opcodes[*(state->num_opcodes)]; op++)
91 1.1 christos {
92 1.1 christos nios2_opcode_hash *new_hash;
93 1.1 christos nios2_opcode_hash **bucket = NULL;
94 1.1 christos
95 1.1 christos if ((op->pinfo & NIOS2_INSN_MACRO) == NIOS2_INSN_MACRO)
96 1.1 christos {
97 1.3 christos if (i == state->extract_opcode (op->match)
98 1.1 christos && (op->pinfo & (NIOS2_INSN_MACRO_MOV | NIOS2_INSN_MACRO_MOVI)
99 1.1 christos & 0x7fffffff))
100 1.3 christos {
101 1.3 christos bucket = &(state->ps_hash[i]);
102 1.3 christos if (strcmp (op->name, "nop") == 0)
103 1.3 christos state->nop = op;
104 1.3 christos }
105 1.1 christos }
106 1.3 christos else if (i == state->extract_opcode (op->match))
107 1.3 christos bucket = &(state->hash[i]);
108 1.1 christos
109 1.1 christos if (bucket)
110 1.1 christos {
111 1.1 christos new_hash =
112 1.1 christos (nios2_opcode_hash *) malloc (sizeof (nios2_opcode_hash));
113 1.1 christos if (new_hash == NULL)
114 1.1 christos {
115 1.1 christos fprintf (stderr,
116 1.1 christos "error allocating memory...broken disassembler\n");
117 1.1 christos abort ();
118 1.1 christos }
119 1.1 christos new_hash->opcode = op;
120 1.1 christos new_hash->next = NULL;
121 1.1 christos while (*bucket)
122 1.1 christos bucket = &((*bucket)->next);
123 1.1 christos *bucket = new_hash;
124 1.1 christos }
125 1.1 christos }
126 1.3 christos state->init = 1;
127 1.3 christos
128 1.1 christos #ifdef DEBUG_HASHTABLE
129 1.3 christos for (i = 0; i < OPCODE_HASH_SIZE; ++i)
130 1.1 christos {
131 1.3 christos nios2_opcode_hash *tmp_hash = state->hash[i];
132 1.1 christos printf ("index: 0x%02X ops: ", i);
133 1.1 christos while (tmp_hash != NULL)
134 1.1 christos {
135 1.1 christos printf ("%s ", tmp_hash->opcode->name);
136 1.1 christos tmp_hash = tmp_hash->next;
137 1.1 christos }
138 1.1 christos printf ("\n");
139 1.1 christos }
140 1.1 christos
141 1.3 christos for (i = 0; i < OPCODE_HASH_SIZE; ++i)
142 1.1 christos {
143 1.3 christos nios2_opcode_hash *tmp_hash = state->ps_hash[i];
144 1.1 christos printf ("index: 0x%02X ops: ", i);
145 1.1 christos while (tmp_hash != NULL)
146 1.1 christos {
147 1.1 christos printf ("%s ", tmp_hash->opcode->name);
148 1.1 christos tmp_hash = tmp_hash->next;
149 1.1 christos }
150 1.1 christos printf ("\n");
151 1.1 christos }
152 1.1 christos #endif /* DEBUG_HASHTABLE */
153 1.1 christos }
154 1.1 christos
155 1.1 christos /* Return a pointer to an nios2_opcode struct for a given instruction
156 1.3 christos word OPCODE for bfd machine MACH, or NULL if there is an error. */
157 1.1 christos const struct nios2_opcode *
158 1.3 christos nios2_find_opcode_hash (unsigned long opcode,
159 1.3 christos unsigned long mach ATTRIBUTE_UNUSED)
160 1.1 christos {
161 1.1 christos nios2_opcode_hash *entry;
162 1.3 christos nios2_disassembler_state *state;
163 1.3 christos
164 1.3 christos state = &nios2_r1_disassembler_state;
165 1.1 christos
166 1.1 christos /* Build a hash table to shorten the search time. */
167 1.3 christos if (!state->init)
168 1.3 christos nios2_init_opcode_hash (state);
169 1.3 christos
170 1.3 christos /* Check for NOP first. Both NOP and MOV are macros that expand into
171 1.3 christos an ADD instruction, and we always want to give priority to NOP. */
172 1.3 christos if (state->nop->match == (opcode & state->nop->mask))
173 1.3 christos return state->nop;
174 1.1 christos
175 1.1 christos /* First look in the pseudo-op hashtable. */
176 1.3 christos for (entry = state->ps_hash[state->extract_opcode (opcode)];
177 1.1 christos entry; entry = entry->next)
178 1.1 christos if (entry->opcode->match == (opcode & entry->opcode->mask))
179 1.1 christos return entry->opcode;
180 1.1 christos
181 1.1 christos /* Otherwise look in the main hashtable. */
182 1.3 christos for (entry = state->hash[state->extract_opcode (opcode)];
183 1.1 christos entry; entry = entry->next)
184 1.1 christos if (entry->opcode->match == (opcode & entry->opcode->mask))
185 1.1 christos return entry->opcode;
186 1.1 christos
187 1.1 christos return NULL;
188 1.1 christos }
189 1.1 christos
190 1.1 christos /* There are 32 regular registers, 32 coprocessor registers,
191 1.1 christos and 32 control registers. */
192 1.1 christos #define NUMREGNAMES 32
193 1.1 christos
194 1.1 christos /* Return a pointer to the base of the coprocessor register name array. */
195 1.1 christos static struct nios2_reg *
196 1.1 christos nios2_coprocessor_regs (void)
197 1.1 christos {
198 1.1 christos static struct nios2_reg *cached = NULL;
199 1.1 christos
200 1.1 christos if (!cached)
201 1.1 christos {
202 1.1 christos int i;
203 1.1 christos for (i = NUMREGNAMES; i < nios2_num_regs; i++)
204 1.1 christos if (!strcmp (nios2_regs[i].name, "c0"))
205 1.1 christos {
206 1.1 christos cached = nios2_regs + i;
207 1.1 christos break;
208 1.1 christos }
209 1.1 christos assert (cached);
210 1.1 christos }
211 1.1 christos return cached;
212 1.1 christos }
213 1.1 christos
214 1.1 christos /* Return a pointer to the base of the control register name array. */
215 1.1 christos static struct nios2_reg *
216 1.1 christos nios2_control_regs (void)
217 1.1 christos {
218 1.1 christos static struct nios2_reg *cached = NULL;
219 1.1 christos
220 1.1 christos if (!cached)
221 1.1 christos {
222 1.1 christos int i;
223 1.1 christos for (i = NUMREGNAMES; i < nios2_num_regs; i++)
224 1.1 christos if (!strcmp (nios2_regs[i].name, "status"))
225 1.1 christos {
226 1.1 christos cached = nios2_regs + i;
227 1.1 christos break;
228 1.1 christos }
229 1.1 christos assert (cached);
230 1.1 christos }
231 1.1 christos return cached;
232 1.1 christos }
233 1.1 christos
234 1.3 christos /* Helper routine to report internal errors. */
235 1.3 christos static void
236 1.3 christos bad_opcode (const struct nios2_opcode *op)
237 1.3 christos {
238 1.3 christos fprintf (stderr, "Internal error: broken opcode descriptor for `%s %s'\n",
239 1.3 christos op->name, op->args);
240 1.3 christos abort ();
241 1.3 christos }
242 1.3 christos
243 1.1 christos /* The function nios2_print_insn_arg uses the character pointed
244 1.1 christos to by ARGPTR to determine how it print the next token or separator
245 1.1 christos character in the arguments to an instruction. */
246 1.1 christos static int
247 1.1 christos nios2_print_insn_arg (const char *argptr,
248 1.1 christos unsigned long opcode, bfd_vma address,
249 1.3 christos disassemble_info *info,
250 1.3 christos const struct nios2_opcode *op)
251 1.1 christos {
252 1.1 christos unsigned long i = 0;
253 1.1 christos struct nios2_reg *reg_base;
254 1.1 christos
255 1.1 christos switch (*argptr)
256 1.1 christos {
257 1.1 christos case ',':
258 1.1 christos case '(':
259 1.1 christos case ')':
260 1.1 christos (*info->fprintf_func) (info->stream, "%c", *argptr);
261 1.1 christos break;
262 1.3 christos
263 1.1 christos case 'd':
264 1.3 christos switch (op->format)
265 1.3 christos {
266 1.3 christos case iw_r_type:
267 1.3 christos i = GET_IW_R_C (opcode);
268 1.3 christos reg_base = nios2_regs;
269 1.3 christos break;
270 1.3 christos case iw_custom_type:
271 1.3 christos i = GET_IW_CUSTOM_C (opcode);
272 1.3 christos if (GET_IW_CUSTOM_READC (opcode) == 0)
273 1.3 christos reg_base = nios2_coprocessor_regs ();
274 1.3 christos else
275 1.3 christos reg_base = nios2_regs;
276 1.3 christos break;
277 1.3 christos default:
278 1.3 christos bad_opcode (op);
279 1.3 christos }
280 1.1 christos if (i < NUMREGNAMES)
281 1.1 christos (*info->fprintf_func) (info->stream, "%s", reg_base[i].name);
282 1.1 christos else
283 1.1 christos (*info->fprintf_func) (info->stream, "unknown");
284 1.1 christos break;
285 1.3 christos
286 1.1 christos case 's':
287 1.3 christos switch (op->format)
288 1.3 christos {
289 1.3 christos case iw_r_type:
290 1.3 christos i = GET_IW_R_A (opcode);
291 1.3 christos reg_base = nios2_regs;
292 1.3 christos break;
293 1.3 christos case iw_i_type:
294 1.3 christos i = GET_IW_I_A (opcode);
295 1.3 christos reg_base = nios2_regs;
296 1.3 christos break;
297 1.3 christos case iw_custom_type:
298 1.3 christos i = GET_IW_CUSTOM_A (opcode);
299 1.3 christos if (GET_IW_CUSTOM_READA (opcode) == 0)
300 1.3 christos reg_base = nios2_coprocessor_regs ();
301 1.3 christos else
302 1.3 christos reg_base = nios2_regs;
303 1.3 christos break;
304 1.3 christos default:
305 1.3 christos bad_opcode (op);
306 1.3 christos }
307 1.1 christos if (i < NUMREGNAMES)
308 1.1 christos (*info->fprintf_func) (info->stream, "%s", reg_base[i].name);
309 1.1 christos else
310 1.1 christos (*info->fprintf_func) (info->stream, "unknown");
311 1.1 christos break;
312 1.3 christos
313 1.1 christos case 't':
314 1.3 christos switch (op->format)
315 1.3 christos {
316 1.3 christos case iw_r_type:
317 1.3 christos i = GET_IW_R_B (opcode);
318 1.3 christos reg_base = nios2_regs;
319 1.3 christos break;
320 1.3 christos case iw_i_type:
321 1.3 christos i = GET_IW_I_B (opcode);
322 1.3 christos reg_base = nios2_regs;
323 1.3 christos break;
324 1.3 christos case iw_custom_type:
325 1.3 christos i = GET_IW_CUSTOM_B (opcode);
326 1.3 christos if (GET_IW_CUSTOM_READB (opcode) == 0)
327 1.3 christos reg_base = nios2_coprocessor_regs ();
328 1.3 christos else
329 1.3 christos reg_base = nios2_regs;
330 1.3 christos break;
331 1.3 christos default:
332 1.3 christos bad_opcode (op);
333 1.3 christos }
334 1.1 christos if (i < NUMREGNAMES)
335 1.1 christos (*info->fprintf_func) (info->stream, "%s", reg_base[i].name);
336 1.1 christos else
337 1.1 christos (*info->fprintf_func) (info->stream, "unknown");
338 1.1 christos break;
339 1.3 christos
340 1.1 christos case 'i':
341 1.1 christos /* 16-bit signed immediate. */
342 1.3 christos switch (op->format)
343 1.3 christos {
344 1.3 christos case iw_i_type:
345 1.3 christos i = (signed) (GET_IW_I_IMM16 (opcode) << 16) >> 16;
346 1.3 christos break;
347 1.3 christos default:
348 1.3 christos bad_opcode (op);
349 1.3 christos }
350 1.1 christos (*info->fprintf_func) (info->stream, "%ld", i);
351 1.1 christos break;
352 1.3 christos
353 1.1 christos case 'u':
354 1.1 christos /* 16-bit unsigned immediate. */
355 1.3 christos switch (op->format)
356 1.3 christos {
357 1.3 christos case iw_i_type:
358 1.3 christos i = GET_IW_I_IMM16 (opcode);
359 1.3 christos break;
360 1.3 christos default:
361 1.3 christos bad_opcode (op);
362 1.3 christos }
363 1.1 christos (*info->fprintf_func) (info->stream, "%ld", i);
364 1.1 christos break;
365 1.3 christos
366 1.1 christos case 'o':
367 1.1 christos /* 16-bit signed immediate address offset. */
368 1.3 christos switch (op->format)
369 1.3 christos {
370 1.3 christos case iw_i_type:
371 1.3 christos i = (signed) (GET_IW_I_IMM16 (opcode) << 16) >> 16;
372 1.3 christos break;
373 1.3 christos default:
374 1.3 christos bad_opcode (op);
375 1.3 christos }
376 1.1 christos address = address + 4 + i;
377 1.1 christos (*info->print_address_func) (address, info);
378 1.1 christos break;
379 1.3 christos
380 1.1 christos case 'j':
381 1.1 christos /* 5-bit unsigned immediate. */
382 1.3 christos switch (op->format)
383 1.3 christos {
384 1.3 christos case iw_r_type:
385 1.3 christos i = GET_IW_R_IMM5 (opcode);
386 1.3 christos break;
387 1.3 christos default:
388 1.3 christos bad_opcode (op);
389 1.3 christos }
390 1.1 christos (*info->fprintf_func) (info->stream, "%ld", i);
391 1.1 christos break;
392 1.3 christos
393 1.1 christos case 'l':
394 1.1 christos /* 8-bit unsigned immediate. */
395 1.3 christos switch (op->format)
396 1.3 christos {
397 1.3 christos case iw_custom_type:
398 1.3 christos i = GET_IW_CUSTOM_N (opcode);
399 1.3 christos break;
400 1.3 christos default:
401 1.3 christos bad_opcode (op);
402 1.3 christos }
403 1.1 christos (*info->fprintf_func) (info->stream, "%lu", i);
404 1.1 christos break;
405 1.3 christos
406 1.1 christos case 'm':
407 1.1 christos /* 26-bit unsigned immediate. */
408 1.3 christos switch (op->format)
409 1.3 christos {
410 1.3 christos case iw_j_type:
411 1.3 christos i = GET_IW_J_IMM26 (opcode);
412 1.3 christos break;
413 1.3 christos default:
414 1.3 christos bad_opcode (op);
415 1.3 christos }
416 1.1 christos /* This translates to an address because it's only used in call
417 1.1 christos instructions. */
418 1.1 christos address = (address & 0xf0000000) | (i << 2);
419 1.1 christos (*info->print_address_func) (address, info);
420 1.1 christos break;
421 1.3 christos
422 1.1 christos case 'c':
423 1.1 christos /* Control register index. */
424 1.3 christos switch (op->format)
425 1.3 christos {
426 1.3 christos case iw_r_type:
427 1.3 christos i = GET_IW_R_IMM5 (opcode);
428 1.3 christos break;
429 1.3 christos default:
430 1.3 christos bad_opcode (op);
431 1.3 christos }
432 1.1 christos reg_base = nios2_control_regs ();
433 1.1 christos (*info->fprintf_func) (info->stream, "%s", reg_base[i].name);
434 1.1 christos break;
435 1.3 christos
436 1.1 christos default:
437 1.1 christos (*info->fprintf_func) (info->stream, "unknown");
438 1.1 christos break;
439 1.1 christos }
440 1.1 christos return 0;
441 1.1 christos }
442 1.1 christos
443 1.1 christos /* nios2_disassemble does all the work of disassembling a Nios II
444 1.1 christos instruction opcode. */
445 1.1 christos static int
446 1.1 christos nios2_disassemble (bfd_vma address, unsigned long opcode,
447 1.1 christos disassemble_info *info)
448 1.1 christos {
449 1.1 christos const struct nios2_opcode *op;
450 1.1 christos
451 1.1 christos info->bytes_per_line = INSNLEN;
452 1.1 christos info->bytes_per_chunk = INSNLEN;
453 1.1 christos info->display_endian = info->endian;
454 1.1 christos info->insn_info_valid = 1;
455 1.1 christos info->branch_delay_insns = 0;
456 1.1 christos info->data_size = 0;
457 1.1 christos info->insn_type = dis_nonbranch;
458 1.1 christos info->target = 0;
459 1.1 christos info->target2 = 0;
460 1.1 christos
461 1.1 christos /* Find the major opcode and use this to disassemble
462 1.1 christos the instruction and its arguments. */
463 1.3 christos op = nios2_find_opcode_hash (opcode, info->mach);
464 1.1 christos
465 1.1 christos if (op != NULL)
466 1.1 christos {
467 1.3 christos const char *argstr = op->args;
468 1.3 christos (*info->fprintf_func) (info->stream, "%s", op->name);
469 1.3 christos if (argstr != NULL && *argstr != '\0')
470 1.1 christos {
471 1.3 christos (*info->fprintf_func) (info->stream, "\t");
472 1.3 christos while (*argstr != '\0')
473 1.1 christos {
474 1.3 christos nios2_print_insn_arg (argstr, opcode, address, info, op);
475 1.3 christos ++argstr;
476 1.1 christos }
477 1.1 christos }
478 1.3 christos /* Tell the caller how far to advance the program counter. */
479 1.3 christos info->bytes_per_chunk = op->size;
480 1.3 christos return op->size;
481 1.1 christos }
482 1.1 christos else
483 1.1 christos {
484 1.1 christos /* Handle undefined instructions. */
485 1.1 christos info->insn_type = dis_noninsn;
486 1.1 christos (*info->fprintf_func) (info->stream, "0x%lx", opcode);
487 1.3 christos return INSNLEN;
488 1.1 christos }
489 1.1 christos }
490 1.1 christos
491 1.1 christos
492 1.1 christos /* print_insn_nios2 is the main disassemble function for Nios II.
493 1.1 christos The function diassembler(abfd) (source in disassemble.c) returns a
494 1.1 christos pointer to this either print_insn_big_nios2 or
495 1.1 christos print_insn_little_nios2, which in turn call this function when the
496 1.1 christos bfd machine type is Nios II. print_insn_nios2 reads the
497 1.1 christos instruction word at the address given, and prints the disassembled
498 1.1 christos instruction on the stream info->stream using info->fprintf_func. */
499 1.1 christos
500 1.1 christos static int
501 1.1 christos print_insn_nios2 (bfd_vma address, disassemble_info *info,
502 1.1 christos enum bfd_endian endianness)
503 1.1 christos {
504 1.1 christos bfd_byte buffer[INSNLEN];
505 1.1 christos int status;
506 1.1 christos
507 1.1 christos status = (*info->read_memory_func) (address, buffer, INSNLEN, info);
508 1.1 christos if (status == 0)
509 1.1 christos {
510 1.1 christos unsigned long insn;
511 1.1 christos if (endianness == BFD_ENDIAN_BIG)
512 1.1 christos insn = (unsigned long) bfd_getb32 (buffer);
513 1.1 christos else
514 1.1 christos insn = (unsigned long) bfd_getl32 (buffer);
515 1.1 christos status = nios2_disassemble (address, insn, info);
516 1.1 christos }
517 1.1 christos else
518 1.1 christos {
519 1.1 christos (*info->memory_error_func) (status, address, info);
520 1.1 christos status = -1;
521 1.1 christos }
522 1.1 christos return status;
523 1.1 christos }
524 1.1 christos
525 1.1 christos /* These two functions are the main entry points, accessed from
526 1.1 christos disassemble.c. */
527 1.1 christos int
528 1.1 christos print_insn_big_nios2 (bfd_vma address, disassemble_info *info)
529 1.1 christos {
530 1.1 christos return print_insn_nios2 (address, info, BFD_ENDIAN_BIG);
531 1.1 christos }
532 1.1 christos
533 1.1 christos int
534 1.1 christos print_insn_little_nios2 (bfd_vma address, disassemble_info *info)
535 1.1 christos {
536 1.1 christos return print_insn_nios2 (address, info, BFD_ENDIAN_LITTLE);
537 1.1 christos }
538