1/* Register names and numbers for S/390 DWARF.
2   Copyright (C) 2006 Red Hat, Inc.
3   This file is part of elfutils.
4
5   This file is free software; you can redistribute it and/or modify
6   it under the terms of either
7
8     * the GNU Lesser General Public License as published by the Free
9       Software Foundation; either version 3 of the License, or (at
10       your option) any later version
11
12   or
13
14     * the GNU General Public License as published by the Free
15       Software Foundation; either version 2 of the License, or (at
16       your option) any later version
17
18   or both in parallel, as here.
19
20   elfutils is distributed in the hope that it will be useful, but
21   WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23   General Public License for more details.
24
25   You should have received copies of the GNU General Public License and
26   the GNU Lesser General Public License along with this program.  If
27   not, see <http://www.gnu.org/licenses/>.  */
28
29#ifdef HAVE_CONFIG_H
30# include <config.h>
31#endif
32
33#include <string.h>
34#include <dwarf.h>
35
36#define BACKEND s390_
37#include "libebl_CPU.h"
38
39
40/*
41zseries (64)
42
430-15	gpr0-gpr15	x
4416-19	fpr[0246]
4520-24	fpr[13578]
4625-27	fpr1[024]
4728	fpr9
4829-31	fpr1[135]
4932-47	cr0-cr15	x
5048-63	ar0-ar15	x
5164	psw_mask
5265	psw_address
53*/
54
55
56ssize_t
57s390_register_info (Ebl *ebl __attribute__ ((unused)),
58		    int regno, char *name, size_t namelen,
59		    const char **prefix, const char **setname,
60		    int *bits, int *type)
61{
62  if (name == NULL)
63    return 66;
64
65  if (regno < 0 || regno > 65 || namelen < 7)
66    return -1;
67
68  *prefix = "%";
69
70  *bits = ebl->class == ELFCLASS64 ? 64 : 32;
71  *type = DW_ATE_unsigned;
72  if (regno < 16)
73    {
74      *setname = "integer";
75      *type = DW_ATE_signed;
76    }
77  else if (regno < 32)
78    {
79      *setname = "FPU";
80      *type = DW_ATE_float;
81      *bits = 64;
82    }
83  else if (regno < 48 || regno > 63)
84    *setname = "control";
85  else
86    {
87      *setname = "access";
88      *bits = 32;
89    }
90
91  switch (regno)
92    {
93    case 0 ... 9:
94      name[0] = 'r';
95      name[1] = regno + '0';
96      namelen = 2;
97      break;
98
99    case 10 ... 15:
100      name[0] = 'r';
101      name[1] = '1';
102      name[2] = regno - 10 + '0';
103      namelen = 3;
104      break;
105
106    case 16 ... 31:
107      name[0] = 'f';
108      regno = (regno & 8) | ((regno & 4) >> 2) | ((regno & 3) << 1);
109      namelen = 1;
110      if (regno >= 10)
111	{
112	  regno -= 10;
113	  name[namelen++] = '1';
114	}
115      name[namelen++] = regno + '0';
116      break;
117
118    case 32 + 0 ... 32 + 9:
119    case 48 + 0 ... 48 + 9:
120      name[0] = regno < 48 ? 'c' : 'a';
121      name[1] = (regno & 15) + '0';
122      namelen = 2;
123      break;
124
125    case 32 + 10 ... 32 + 15:
126    case 48 + 10 ... 48 + 15:
127      name[0] = regno < 48 ? 'c' : 'a';
128      name[1] = '1';
129      name[2] = (regno & 15) - 10 + '0';
130      namelen = 3;
131      break;
132
133    case 64:
134      return stpcpy (name, "pswm") + 1 - name;
135    case 65:
136      *type = DW_ATE_address;
137      return stpcpy (name, "pswa") + 1 - name;
138
139    default:
140      *setname = NULL;
141      return 0;
142    }
143
144  name[namelen++] = '\0';
145  return namelen;
146}
147