Statistics
| Branch: | Revision:

root / target-sparc / translate.c @ 7a3f1944

History | View | Annotate | Download (16.4 kB)

1 7a3f1944 bellard
/*
2 7a3f1944 bellard
   SPARC translation
3 7a3f1944 bellard

4 7a3f1944 bellard
   Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5 7a3f1944 bellard

6 7a3f1944 bellard
   This library is free software; you can redistribute it and/or
7 7a3f1944 bellard
   modify it under the terms of the GNU Lesser General Public
8 7a3f1944 bellard
   License as published by the Free Software Foundation; either
9 7a3f1944 bellard
   version 2 of the License, or (at your option) any later version.
10 7a3f1944 bellard

11 7a3f1944 bellard
   This library is distributed in the hope that it will be useful,
12 7a3f1944 bellard
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 7a3f1944 bellard
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 7a3f1944 bellard
   Lesser General Public License for more details.
15 7a3f1944 bellard

16 7a3f1944 bellard
   You should have received a copy of the GNU Lesser General Public
17 7a3f1944 bellard
   License along with this library; if not, write to the Free Software
18 7a3f1944 bellard
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 7a3f1944 bellard
 */
20 7a3f1944 bellard
21 7a3f1944 bellard
/*
22 7a3f1944 bellard
   SPARC has two pitfalls: Delay slots and (a)nullification.
23 7a3f1944 bellard
   This is currently solved as follows:
24 7a3f1944 bellard

25 7a3f1944 bellard
   'call' instructions simply execute the delay slot before the actual
26 7a3f1944 bellard
   control transfer instructions.
27 7a3f1944 bellard

28 7a3f1944 bellard
   'jmpl' instructions execute calculate the destination, then execute
29 7a3f1944 bellard
   the delay slot and then do the control transfer.
30 7a3f1944 bellard

31 7a3f1944 bellard
   (conditional) branch instructions are the most difficult ones, as the
32 7a3f1944 bellard
   delay slot may be nullified (ie. not executed). This happens when a
33 7a3f1944 bellard
   conditional branch is not executed (thus no control transfer happens)
34 7a3f1944 bellard
   and the 'anull' bit in the branch instruction opcode is set. This is
35 7a3f1944 bellard
   currently solved by doing a jump after the delay slot instruction.
36 7a3f1944 bellard

37 7a3f1944 bellard
   There is also one big (currently unsolved) bug in the branch code:
38 7a3f1944 bellard
   If a delay slot modifies the condition codes then the new condition
39 7a3f1944 bellard
   codes, instead of the old ones will be used.
40 7a3f1944 bellard

41 7a3f1944 bellard
   TODO-list:
42 7a3f1944 bellard

43 7a3f1944 bellard
   FPU-Instructions
44 7a3f1944 bellard
   Coprocessor-Instructions
45 7a3f1944 bellard
   Fix above bug
46 7a3f1944 bellard
   Check signedness issues
47 7a3f1944 bellard
   Privileged instructions
48 7a3f1944 bellard
   Register window overflow/underflow check
49 7a3f1944 bellard
   Optimize synthetic instructions
50 7a3f1944 bellard
   Optional alignment and privileged instruction check
51 7a3f1944 bellard

52 7a3f1944 bellard
   -- TMO, 09/03/03
53 7a3f1944 bellard
 */
54 7a3f1944 bellard
55 7a3f1944 bellard
#include <stdarg.h>
56 7a3f1944 bellard
#include <stdlib.h>
57 7a3f1944 bellard
#include <stdio.h>
58 7a3f1944 bellard
#include <string.h>
59 7a3f1944 bellard
#include <inttypes.h>
60 7a3f1944 bellard
61 7a3f1944 bellard
#include "cpu.h"
62 7a3f1944 bellard
#include "exec-all.h"
63 7a3f1944 bellard
#include "disas.h"
64 7a3f1944 bellard
65 7a3f1944 bellard
#define DEBUG_DISAS
66 7a3f1944 bellard
67 7a3f1944 bellard
typedef struct DisasContext {
68 7a3f1944 bellard
        uint8_t *pc;
69 7a3f1944 bellard
        uint8_t *npc;
70 7a3f1944 bellard
        void (*branch) (struct DisasContext *, uint32_t, uint32_t);
71 7a3f1944 bellard
        unsigned int delay_slot:2;
72 7a3f1944 bellard
        uint32_t insn;
73 7a3f1944 bellard
        uint32_t target;
74 7a3f1944 bellard
        int      is_br;
75 7a3f1944 bellard
        struct TranslationBlock *tb;
76 7a3f1944 bellard
} DisasContext;
77 7a3f1944 bellard
78 7a3f1944 bellard
static uint16_t *gen_opc_ptr;
79 7a3f1944 bellard
static uint32_t *gen_opparam_ptr;
80 7a3f1944 bellard
extern FILE *logfile;
81 7a3f1944 bellard
extern int loglevel;
82 7a3f1944 bellard
83 7a3f1944 bellard
enum {
84 7a3f1944 bellard
#define DEF(s,n,copy_size) INDEX_op_ ## s,
85 7a3f1944 bellard
#include "opc.h"
86 7a3f1944 bellard
#undef DEF
87 7a3f1944 bellard
        NB_OPS
88 7a3f1944 bellard
};
89 7a3f1944 bellard
90 7a3f1944 bellard
#include "gen-op.h"
91 7a3f1944 bellard
92 7a3f1944 bellard
#define GET_FIELD(X, FROM, TO) \
93 7a3f1944 bellard
  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
94 7a3f1944 bellard
95 7a3f1944 bellard
#define IS_IMM (insn & (1<<13))
96 7a3f1944 bellard
97 7a3f1944 bellard
static void disas_sparc_insn (DisasContext *dc);
98 7a3f1944 bellard
99 7a3f1944 bellard
typedef void (GenOpFunc)(void);
100 7a3f1944 bellard
typedef void (GenOpFunc1)(long);
101 7a3f1944 bellard
typedef void (GenOpFunc2)(long, long);
102 7a3f1944 bellard
typedef void (GenOpFunc3)(long, long, long);
103 7a3f1944 bellard
104 7a3f1944 bellard
static GenOpFunc *gen_op_movl_TN_reg[2][32] = {
105 7a3f1944 bellard
        {
106 7a3f1944 bellard
                gen_op_movl_g0_T0,
107 7a3f1944 bellard
                gen_op_movl_g1_T0,
108 7a3f1944 bellard
                gen_op_movl_g2_T0,
109 7a3f1944 bellard
                gen_op_movl_g3_T0,
110 7a3f1944 bellard
                gen_op_movl_g4_T0,
111 7a3f1944 bellard
                gen_op_movl_g5_T0,
112 7a3f1944 bellard
                gen_op_movl_g6_T0,
113 7a3f1944 bellard
                gen_op_movl_g7_T0,
114 7a3f1944 bellard
                gen_op_movl_o0_T0,
115 7a3f1944 bellard
                gen_op_movl_o1_T0,
116 7a3f1944 bellard
                gen_op_movl_o2_T0,
117 7a3f1944 bellard
                gen_op_movl_o3_T0,
118 7a3f1944 bellard
                gen_op_movl_o4_T0,
119 7a3f1944 bellard
                gen_op_movl_o5_T0,
120 7a3f1944 bellard
                gen_op_movl_o6_T0,
121 7a3f1944 bellard
                gen_op_movl_o7_T0,
122 7a3f1944 bellard
                gen_op_movl_l0_T0,
123 7a3f1944 bellard
                gen_op_movl_l1_T0,
124 7a3f1944 bellard
                gen_op_movl_l2_T0,
125 7a3f1944 bellard
                gen_op_movl_l3_T0,
126 7a3f1944 bellard
                gen_op_movl_l4_T0,
127 7a3f1944 bellard
                gen_op_movl_l5_T0,
128 7a3f1944 bellard
                gen_op_movl_l6_T0,
129 7a3f1944 bellard
                gen_op_movl_l7_T0,
130 7a3f1944 bellard
                gen_op_movl_i0_T0,
131 7a3f1944 bellard
                gen_op_movl_i1_T0,
132 7a3f1944 bellard
                gen_op_movl_i2_T0,
133 7a3f1944 bellard
                gen_op_movl_i3_T0,
134 7a3f1944 bellard
                gen_op_movl_i4_T0,
135 7a3f1944 bellard
                gen_op_movl_i5_T0,
136 7a3f1944 bellard
                gen_op_movl_i6_T0,
137 7a3f1944 bellard
                gen_op_movl_i7_T0,
138 7a3f1944 bellard
        },
139 7a3f1944 bellard
        {
140 7a3f1944 bellard
                gen_op_movl_g0_T1,
141 7a3f1944 bellard
                gen_op_movl_g1_T1,
142 7a3f1944 bellard
                gen_op_movl_g2_T1,
143 7a3f1944 bellard
                gen_op_movl_g3_T1,
144 7a3f1944 bellard
                gen_op_movl_g4_T1,
145 7a3f1944 bellard
                gen_op_movl_g5_T1,
146 7a3f1944 bellard
                gen_op_movl_g6_T1,
147 7a3f1944 bellard
                gen_op_movl_g7_T1,
148 7a3f1944 bellard
                gen_op_movl_o0_T1,
149 7a3f1944 bellard
                gen_op_movl_o1_T1,
150 7a3f1944 bellard
                gen_op_movl_o2_T1,
151 7a3f1944 bellard
                gen_op_movl_o3_T1,
152 7a3f1944 bellard
                gen_op_movl_o4_T1,
153 7a3f1944 bellard
                gen_op_movl_o5_T1,
154 7a3f1944 bellard
                gen_op_movl_o6_T1,
155 7a3f1944 bellard
                gen_op_movl_o7_T1,
156 7a3f1944 bellard
                gen_op_movl_l0_T1,
157 7a3f1944 bellard
                gen_op_movl_l1_T1,
158 7a3f1944 bellard
                gen_op_movl_l2_T1,
159 7a3f1944 bellard
                gen_op_movl_l3_T1,
160 7a3f1944 bellard
                gen_op_movl_l4_T1,
161 7a3f1944 bellard
                gen_op_movl_l5_T1,
162 7a3f1944 bellard
                gen_op_movl_l6_T1,
163 7a3f1944 bellard
                gen_op_movl_l7_T1,
164 7a3f1944 bellard
                gen_op_movl_i0_T1,
165 7a3f1944 bellard
                gen_op_movl_i1_T1,
166 7a3f1944 bellard
                gen_op_movl_i2_T1,
167 7a3f1944 bellard
                gen_op_movl_i3_T1,
168 7a3f1944 bellard
                gen_op_movl_i4_T1,
169 7a3f1944 bellard
                gen_op_movl_i5_T1,
170 7a3f1944 bellard
                gen_op_movl_i6_T1,
171 7a3f1944 bellard
                gen_op_movl_i7_T1,
172 7a3f1944 bellard
        }
173 7a3f1944 bellard
};
174 7a3f1944 bellard
175 7a3f1944 bellard
static GenOpFunc *gen_op_movl_reg_TN[3][32] = {
176 7a3f1944 bellard
        {
177 7a3f1944 bellard
                gen_op_movl_T0_g0,
178 7a3f1944 bellard
                gen_op_movl_T0_g1,
179 7a3f1944 bellard
                gen_op_movl_T0_g2,
180 7a3f1944 bellard
                gen_op_movl_T0_g3,
181 7a3f1944 bellard
                gen_op_movl_T0_g4,
182 7a3f1944 bellard
                gen_op_movl_T0_g5,
183 7a3f1944 bellard
                gen_op_movl_T0_g6,
184 7a3f1944 bellard
                gen_op_movl_T0_g7,
185 7a3f1944 bellard
                gen_op_movl_T0_o0,
186 7a3f1944 bellard
                gen_op_movl_T0_o1,
187 7a3f1944 bellard
                gen_op_movl_T0_o2,
188 7a3f1944 bellard
                gen_op_movl_T0_o3,
189 7a3f1944 bellard
                gen_op_movl_T0_o4,
190 7a3f1944 bellard
                gen_op_movl_T0_o5,
191 7a3f1944 bellard
                gen_op_movl_T0_o6,
192 7a3f1944 bellard
                gen_op_movl_T0_o7,
193 7a3f1944 bellard
                gen_op_movl_T0_l0,
194 7a3f1944 bellard
                gen_op_movl_T0_l1,
195 7a3f1944 bellard
                gen_op_movl_T0_l2,
196 7a3f1944 bellard
                gen_op_movl_T0_l3,
197 7a3f1944 bellard
                gen_op_movl_T0_l4,
198 7a3f1944 bellard
                gen_op_movl_T0_l5,
199 7a3f1944 bellard
                gen_op_movl_T0_l6,
200 7a3f1944 bellard
                gen_op_movl_T0_l7,
201 7a3f1944 bellard
                gen_op_movl_T0_i0,
202 7a3f1944 bellard
                gen_op_movl_T0_i1,
203 7a3f1944 bellard
                gen_op_movl_T0_i2,
204 7a3f1944 bellard
                gen_op_movl_T0_i3,
205 7a3f1944 bellard
                gen_op_movl_T0_i4,
206 7a3f1944 bellard
                gen_op_movl_T0_i5,
207 7a3f1944 bellard
                gen_op_movl_T0_i6,
208 7a3f1944 bellard
                gen_op_movl_T0_i7,
209 7a3f1944 bellard
        },
210 7a3f1944 bellard
        {
211 7a3f1944 bellard
                gen_op_movl_T1_g0,
212 7a3f1944 bellard
                gen_op_movl_T1_g1,
213 7a3f1944 bellard
                gen_op_movl_T1_g2,
214 7a3f1944 bellard
                gen_op_movl_T1_g3,
215 7a3f1944 bellard
                gen_op_movl_T1_g4,
216 7a3f1944 bellard
                gen_op_movl_T1_g5,
217 7a3f1944 bellard
                gen_op_movl_T1_g6,
218 7a3f1944 bellard
                gen_op_movl_T1_g7,
219 7a3f1944 bellard
                gen_op_movl_T1_o0,
220 7a3f1944 bellard
                gen_op_movl_T1_o1,
221 7a3f1944 bellard
                gen_op_movl_T1_o2,
222 7a3f1944 bellard
                gen_op_movl_T1_o3,
223 7a3f1944 bellard
                gen_op_movl_T1_o4,
224 7a3f1944 bellard
                gen_op_movl_T1_o5,
225 7a3f1944 bellard
                gen_op_movl_T1_o6,
226 7a3f1944 bellard
                gen_op_movl_T1_o7,
227 7a3f1944 bellard
                gen_op_movl_T1_l0,
228 7a3f1944 bellard
                gen_op_movl_T1_l1,
229 7a3f1944 bellard
                gen_op_movl_T1_l2,
230 7a3f1944 bellard
                gen_op_movl_T1_l3,
231 7a3f1944 bellard
                gen_op_movl_T1_l4,
232 7a3f1944 bellard
                gen_op_movl_T1_l5,
233 7a3f1944 bellard
                gen_op_movl_T1_l6,
234 7a3f1944 bellard
                gen_op_movl_T1_l7,
235 7a3f1944 bellard
                gen_op_movl_T1_i0,
236 7a3f1944 bellard
                gen_op_movl_T1_i1,
237 7a3f1944 bellard
                gen_op_movl_T1_i2,
238 7a3f1944 bellard
                gen_op_movl_T1_i3,
239 7a3f1944 bellard
                gen_op_movl_T1_i4,
240 7a3f1944 bellard
                gen_op_movl_T1_i5,
241 7a3f1944 bellard
                gen_op_movl_T1_i6,
242 7a3f1944 bellard
                gen_op_movl_T1_i7,
243 7a3f1944 bellard
        },
244 7a3f1944 bellard
        {
245 7a3f1944 bellard
                gen_op_movl_T2_g0,
246 7a3f1944 bellard
                gen_op_movl_T2_g1,
247 7a3f1944 bellard
                gen_op_movl_T2_g2,
248 7a3f1944 bellard
                gen_op_movl_T2_g3,
249 7a3f1944 bellard
                gen_op_movl_T2_g4,
250 7a3f1944 bellard
                gen_op_movl_T2_g5,
251 7a3f1944 bellard
                gen_op_movl_T2_g6,
252 7a3f1944 bellard
                gen_op_movl_T2_g7,
253 7a3f1944 bellard
                gen_op_movl_T2_o0,
254 7a3f1944 bellard
                gen_op_movl_T2_o1,
255 7a3f1944 bellard
                gen_op_movl_T2_o2,
256 7a3f1944 bellard
                gen_op_movl_T2_o3,
257 7a3f1944 bellard
                gen_op_movl_T2_o4,
258 7a3f1944 bellard
                gen_op_movl_T2_o5,
259 7a3f1944 bellard
                gen_op_movl_T2_o6,
260 7a3f1944 bellard
                gen_op_movl_T2_o7,
261 7a3f1944 bellard
                gen_op_movl_T2_l0,
262 7a3f1944 bellard
                gen_op_movl_T2_l1,
263 7a3f1944 bellard
                gen_op_movl_T2_l2,
264 7a3f1944 bellard
                gen_op_movl_T2_l3,
265 7a3f1944 bellard
                gen_op_movl_T2_l4,
266 7a3f1944 bellard
                gen_op_movl_T2_l5,
267 7a3f1944 bellard
                gen_op_movl_T2_l6,
268 7a3f1944 bellard
                gen_op_movl_T2_l7,
269 7a3f1944 bellard
                gen_op_movl_T2_i0,
270 7a3f1944 bellard
                gen_op_movl_T2_i1,
271 7a3f1944 bellard
                gen_op_movl_T2_i2,
272 7a3f1944 bellard
                gen_op_movl_T2_i3,
273 7a3f1944 bellard
                gen_op_movl_T2_i4,
274 7a3f1944 bellard
                gen_op_movl_T2_i5,
275 7a3f1944 bellard
                gen_op_movl_T2_i6,
276 7a3f1944 bellard
                gen_op_movl_T2_i7,
277 7a3f1944 bellard
        }
278 7a3f1944 bellard
};
279 7a3f1944 bellard
280 7a3f1944 bellard
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
281 7a3f1944 bellard
        gen_op_movl_T0_im,
282 7a3f1944 bellard
        gen_op_movl_T1_im,
283 7a3f1944 bellard
        gen_op_movl_T2_im
284 7a3f1944 bellard
};
285 7a3f1944 bellard
286 7a3f1944 bellard
static inline void gen_movl_imm_TN (int reg, int imm)
287 7a3f1944 bellard
{
288 7a3f1944 bellard
        gen_op_movl_TN_im[reg](imm);
289 7a3f1944 bellard
}
290 7a3f1944 bellard
291 7a3f1944 bellard
static inline void gen_movl_imm_T1 (int val)
292 7a3f1944 bellard
{
293 7a3f1944 bellard
        gen_movl_imm_TN (1, val);
294 7a3f1944 bellard
}
295 7a3f1944 bellard
296 7a3f1944 bellard
static inline void gen_movl_imm_T0 (int val)
297 7a3f1944 bellard
{
298 7a3f1944 bellard
        gen_movl_imm_TN (0, val);
299 7a3f1944 bellard
}
300 7a3f1944 bellard
301 7a3f1944 bellard
static inline void gen_movl_reg_TN (int reg, int t)
302 7a3f1944 bellard
{
303 7a3f1944 bellard
        if (reg) gen_op_movl_reg_TN[t][reg]();
304 7a3f1944 bellard
        else gen_movl_imm_TN (t, 0);
305 7a3f1944 bellard
}
306 7a3f1944 bellard
307 7a3f1944 bellard
static inline void gen_movl_reg_T0 (int reg)
308 7a3f1944 bellard
{
309 7a3f1944 bellard
        gen_movl_reg_TN (reg, 0);
310 7a3f1944 bellard
}
311 7a3f1944 bellard
312 7a3f1944 bellard
static inline void gen_movl_reg_T1 (int reg)
313 7a3f1944 bellard
{
314 7a3f1944 bellard
        gen_movl_reg_TN (reg, 1);
315 7a3f1944 bellard
}
316 7a3f1944 bellard
317 7a3f1944 bellard
static inline void gen_movl_reg_T2 (int reg)
318 7a3f1944 bellard
{
319 7a3f1944 bellard
        gen_movl_reg_TN (reg, 2);
320 7a3f1944 bellard
}
321 7a3f1944 bellard
322 7a3f1944 bellard
static inline void gen_movl_TN_reg (int reg, int t)
323 7a3f1944 bellard
{
324 7a3f1944 bellard
        if (reg) gen_op_movl_TN_reg[t][reg]();
325 7a3f1944 bellard
}
326 7a3f1944 bellard
327 7a3f1944 bellard
static inline void gen_movl_T0_reg (int reg)
328 7a3f1944 bellard
{
329 7a3f1944 bellard
        gen_movl_TN_reg (reg, 0);
330 7a3f1944 bellard
}
331 7a3f1944 bellard
332 7a3f1944 bellard
static inline void gen_movl_T1_reg (int reg)
333 7a3f1944 bellard
{
334 7a3f1944 bellard
        gen_movl_TN_reg (reg, 1);
335 7a3f1944 bellard
}
336 7a3f1944 bellard
337 7a3f1944 bellard
static void do_branch (DisasContext *dc, uint32_t target, uint32_t insn)
338 7a3f1944 bellard
{
339 7a3f1944 bellard
        unsigned int cond = GET_FIELD (insn, 3, 6), a = (insn & (1<<29)), ib = 0;
340 7a3f1944 bellard
        target += (uint32_t) dc->pc-4;
341 7a3f1944 bellard
        if (!a) disas_sparc_insn (dc);
342 7a3f1944 bellard
        switch (cond) {
343 7a3f1944 bellard
          case 0x0: gen_op_movl_T0_0 (); break;
344 7a3f1944 bellard
          case 0x1: gen_op_eval_be (); break;
345 7a3f1944 bellard
          case 0x2: gen_op_eval_ble (); break;
346 7a3f1944 bellard
          case 0x3: gen_op_eval_bl (); break;
347 7a3f1944 bellard
          case 0x4: gen_op_eval_bleu (); break;
348 7a3f1944 bellard
          case 0x5: gen_op_eval_bcs (); break;
349 7a3f1944 bellard
          case 0x6: gen_op_eval_bneg (); break;
350 7a3f1944 bellard
          case 0x7: gen_op_eval_bvs (); break;
351 7a3f1944 bellard
          case 0x8: gen_op_movl_T0_1 (); break;
352 7a3f1944 bellard
          case 0x9: gen_op_eval_bne (); break;
353 7a3f1944 bellard
          case 0xa: gen_op_eval_bg (); break;
354 7a3f1944 bellard
          case 0xb: gen_op_eval_bge (); break;
355 7a3f1944 bellard
          case 0xc: gen_op_eval_bgu (); break;
356 7a3f1944 bellard
          case 0xd: gen_op_eval_bcc (); break;
357 7a3f1944 bellard
          case 0xe: gen_op_eval_bpos (); break;
358 7a3f1944 bellard
          case 0xf: gen_op_eval_bvc (); break;
359 7a3f1944 bellard
        }
360 7a3f1944 bellard
        if (a && ((cond|0x8) != 0x8)) {
361 7a3f1944 bellard
                gen_op_generic_branch_a ((uint32_t) dc->tb,
362 7a3f1944 bellard
                                (uint32_t) dc->pc+4, target);
363 7a3f1944 bellard
                disas_sparc_insn (dc);
364 7a3f1944 bellard
                ib = 1;
365 7a3f1944 bellard
        }
366 7a3f1944 bellard
        else
367 7a3f1944 bellard
        if (cond && !a) {
368 7a3f1944 bellard
                gen_op_generic_branch ((uint32_t) dc->tb, (uint32_t) target,
369 7a3f1944 bellard
                        (uint32_t) dc->pc);
370 7a3f1944 bellard
                ib = 1;
371 7a3f1944 bellard
        }
372 7a3f1944 bellard
        if (ib) dc->is_br = DISAS_JUMP;
373 7a3f1944 bellard
}
374 7a3f1944 bellard
375 7a3f1944 bellard
/* target == 0x1 means CALL- else JMPL-instruction */
376 7a3f1944 bellard
static void do_jump (DisasContext *dc, uint32_t target, uint32_t rd)
377 7a3f1944 bellard
{
378 7a3f1944 bellard
        uint32_t orig_pc = (uint32_t) dc->pc-8;
379 7a3f1944 bellard
        if (target != 0x1)
380 7a3f1944 bellard
         gen_op_generic_jmp_1 (orig_pc, target);
381 7a3f1944 bellard
        else
382 7a3f1944 bellard
         gen_op_generic_jmp_2 (orig_pc);
383 7a3f1944 bellard
        gen_movl_T1_reg (rd);
384 7a3f1944 bellard
        dc->is_br = DISAS_JUMP;
385 7a3f1944 bellard
        gen_op_movl_T0_0 ();
386 7a3f1944 bellard
}
387 7a3f1944 bellard
388 7a3f1944 bellard
#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), b-a)
389 7a3f1944 bellard
390 7a3f1944 bellard
static int
391 7a3f1944 bellard
sign_extend (x, len)
392 7a3f1944 bellard
        int x, len;
393 7a3f1944 bellard
{
394 7a3f1944 bellard
        int signbit = (1 << (len - 1));
395 7a3f1944 bellard
        int mask = (signbit << 1) - 1;
396 7a3f1944 bellard
        return ((x & mask) ^ signbit) - signbit;
397 7a3f1944 bellard
}
398 7a3f1944 bellard
399 7a3f1944 bellard
static void disas_sparc_insn (DisasContext *dc)
400 7a3f1944 bellard
{
401 7a3f1944 bellard
        unsigned int insn, opc, rs1, rs2, rd;
402 7a3f1944 bellard
403 7a3f1944 bellard
        if (dc->delay_slot == 1) {
404 7a3f1944 bellard
                insn = dc->insn;
405 7a3f1944 bellard
        } else {
406 7a3f1944 bellard
                if (dc->delay_slot) dc->delay_slot--;
407 7a3f1944 bellard
                insn = htonl (*(unsigned int *) (dc->pc));
408 7a3f1944 bellard
                dc->pc += 4;
409 7a3f1944 bellard
        }
410 7a3f1944 bellard
411 7a3f1944 bellard
        opc = GET_FIELD (insn, 0, 1);
412 7a3f1944 bellard
413 7a3f1944 bellard
        rd  = GET_FIELD (insn, 2, 6);
414 7a3f1944 bellard
        switch (opc) {
415 7a3f1944 bellard
          case 0: /* branches/sethi */
416 7a3f1944 bellard
                {
417 7a3f1944 bellard
                        unsigned int xop = GET_FIELD (insn, 7, 9);
418 7a3f1944 bellard
                        int target;
419 7a3f1944 bellard
                        target = GET_FIELD (insn, 10, 31);
420 7a3f1944 bellard
                        switch (xop) {
421 7a3f1944 bellard
                         case 0x0: case 0x1: /* UNIMPL */
422 7a3f1944 bellard
                                printf ("UNIMPLEMENTED: %p\n", dc->pc-4);
423 7a3f1944 bellard
                                exit (23);
424 7a3f1944 bellard
                                break;
425 7a3f1944 bellard
                         case 0x2: /* BN+x */
426 7a3f1944 bellard
                        {
427 7a3f1944 bellard
                                target <<= 2;
428 7a3f1944 bellard
                                target = sign_extend (target, 22);
429 7a3f1944 bellard
                                do_branch (dc, target, insn);
430 7a3f1944 bellard
                                break;
431 7a3f1944 bellard
                        }
432 7a3f1944 bellard
                         case 0x3: /* FBN+x */
433 7a3f1944 bellard
                                break;
434 7a3f1944 bellard
                         case 0x4: /* SETHI */
435 7a3f1944 bellard
                                gen_movl_imm_T0 (target<<10);
436 7a3f1944 bellard
                                gen_movl_T0_reg (rd);
437 7a3f1944 bellard
                                break;
438 7a3f1944 bellard
                         case 0x5: /*CBN+x*/
439 7a3f1944 bellard
                                break;
440 7a3f1944 bellard
                        }
441 7a3f1944 bellard
                        break;
442 7a3f1944 bellard
                }
443 7a3f1944 bellard
          case 1: /*CALL*/
444 7a3f1944 bellard
                {
445 7a3f1944 bellard
                        unsigned int target = GET_FIELDs (insn, 2, 31) << 2;
446 7a3f1944 bellard
                        if (dc->delay_slot) {
447 7a3f1944 bellard
                                do_jump (dc, target, 15);
448 7a3f1944 bellard
                                dc->delay_slot = 0;
449 7a3f1944 bellard
                        } else {
450 7a3f1944 bellard
                                dc->insn = insn;
451 7a3f1944 bellard
                                dc->delay_slot = 2;
452 7a3f1944 bellard
                        }
453 7a3f1944 bellard
                        break;
454 7a3f1944 bellard
                }
455 7a3f1944 bellard
          case 2: /* FPU & Logical Operations */
456 7a3f1944 bellard
                {
457 7a3f1944 bellard
                        unsigned int xop = GET_FIELD (insn, 7, 12);
458 7a3f1944 bellard
                        if (xop == 58) { /* generate trap */
459 7a3f1944 bellard
                                dc->is_br = DISAS_JUMP;
460 7a3f1944 bellard
                                gen_op_jmp_im ((uint32_t) dc->pc);
461 7a3f1944 bellard
                                if (IS_IMM) gen_op_trap (GET_FIELD (insn, 25, 31));
462 7a3f1944 bellard
                                /* else XXX*/
463 7a3f1944 bellard
                                gen_op_movl_T0_0 ();
464 7a3f1944 bellard
                                break;
465 7a3f1944 bellard
                        }
466 7a3f1944 bellard
                        if (xop == 0x34 || xop == 0x35) { /* FPU Operations */
467 7a3f1944 bellard
                                exit (33);
468 7a3f1944 bellard
                        }
469 7a3f1944 bellard
                        rs1 = GET_FIELD (insn, 13, 17);
470 7a3f1944 bellard
                        gen_movl_reg_T0 (rs1);
471 7a3f1944 bellard
                        if (IS_IMM) { /* immediate */
472 7a3f1944 bellard
                                rs2 = GET_FIELDs (insn, 20, 31);
473 7a3f1944 bellard
                                gen_movl_imm_T1 (rs2);
474 7a3f1944 bellard
                        } else {              /* register */
475 7a3f1944 bellard
                                rs2 = GET_FIELD (insn, 27, 31);
476 7a3f1944 bellard
                                gen_movl_reg_T1 (rs2);
477 7a3f1944 bellard
                        }
478 7a3f1944 bellard
                        if (xop < 0x20) {
479 7a3f1944 bellard
                         switch (xop &~ 0x10) {
480 7a3f1944 bellard
                          case 0x0:
481 7a3f1944 bellard
                                gen_op_add_T1_T0 ();
482 7a3f1944 bellard
                                break;
483 7a3f1944 bellard
                          case 0x1:
484 7a3f1944 bellard
                                gen_op_and_T1_T0 ();
485 7a3f1944 bellard
                                break;
486 7a3f1944 bellard
                          case 0x2:
487 7a3f1944 bellard
                                gen_op_or_T1_T0 ();
488 7a3f1944 bellard
                                break;
489 7a3f1944 bellard
                          case 0x3:
490 7a3f1944 bellard
                                gen_op_xor_T1_T0 ();
491 7a3f1944 bellard
                                break;
492 7a3f1944 bellard
                          case 0x4:
493 7a3f1944 bellard
                                gen_op_sub_T1_T0 ();
494 7a3f1944 bellard
                                break;
495 7a3f1944 bellard
                          case 0x5:
496 7a3f1944 bellard
                                gen_op_andn_T1_T0 ();
497 7a3f1944 bellard
                                break;
498 7a3f1944 bellard
                          case 0x6:
499 7a3f1944 bellard
                                gen_op_orn_T1_T0 ();
500 7a3f1944 bellard
                                break;
501 7a3f1944 bellard
                          case 0x7:
502 7a3f1944 bellard
                                gen_op_xnor_T1_T0 ();
503 7a3f1944 bellard
                                break;
504 7a3f1944 bellard
                          case 0x8:
505 7a3f1944 bellard
                                gen_op_addx_T1_T0 ();
506 7a3f1944 bellard
                                break;
507 7a3f1944 bellard
                          case 0xa:
508 7a3f1944 bellard
                                gen_op_umul_T1_T0 ();
509 7a3f1944 bellard
                                break;
510 7a3f1944 bellard
                          case 0xb:
511 7a3f1944 bellard
                                gen_op_smul_T1_T0 ();
512 7a3f1944 bellard
                                break;
513 7a3f1944 bellard
                          case 0xc:
514 7a3f1944 bellard
                                gen_op_subx_T1_T0 ();
515 7a3f1944 bellard
                                break;
516 7a3f1944 bellard
                          case 0xe:
517 7a3f1944 bellard
                                gen_op_udiv_T1_T0 ();
518 7a3f1944 bellard
                                break;
519 7a3f1944 bellard
                          case 0xf:
520 7a3f1944 bellard
                                gen_op_sdiv_T1_T0 ();
521 7a3f1944 bellard
                                break;
522 7a3f1944 bellard
                          default:
523 7a3f1944 bellard
                                exit (17);
524 7a3f1944 bellard
                                break;
525 7a3f1944 bellard
                         }
526 7a3f1944 bellard
                         gen_movl_T0_reg (rd);
527 7a3f1944 bellard
                         if (xop & 0x10) {
528 7a3f1944 bellard
                                gen_op_set_flags ();
529 7a3f1944 bellard
                         }
530 7a3f1944 bellard
                        } else {
531 7a3f1944 bellard
                          switch (xop) {
532 7a3f1944 bellard
                                case 0x25: /* SLL */
533 7a3f1944 bellard
                                        gen_op_sll ();
534 7a3f1944 bellard
                                        break;
535 7a3f1944 bellard
                                case 0x26:
536 7a3f1944 bellard
                                        gen_op_srl ();
537 7a3f1944 bellard
                                        break;
538 7a3f1944 bellard
                                case 0x27:
539 7a3f1944 bellard
                                        gen_op_sra ();
540 7a3f1944 bellard
                                        break;
541 7a3f1944 bellard
                                case 0x28: case 0x30:
542 7a3f1944 bellard
                                {
543 7a3f1944 bellard
                                        unsigned int rdi = GET_FIELD (insn, 13, 17);
544 7a3f1944 bellard
                                        if (!rdi) (xop==0x28?gen_op_rdy ():gen_op_wry());
545 7a3f1944 bellard
                                        /* else gen_op_su_trap (); */
546 7a3f1944 bellard
                                        break;
547 7a3f1944 bellard
                                }
548 7a3f1944 bellard
                                /* Problem with jmpl: if restore is executed in the delay
549 7a3f1944 bellard
                                   slot, then the wrong registers are beeing used */
550 7a3f1944 bellard
                                case 0x38: /* jmpl */
551 7a3f1944 bellard
                                {
552 7a3f1944 bellard
                                        if (dc->delay_slot) {
553 7a3f1944 bellard
                                                gen_op_add_T1_T0 ();
554 7a3f1944 bellard
                                                do_jump (dc, 1, rd);
555 7a3f1944 bellard
                                                dc->delay_slot = 0;
556 7a3f1944 bellard
                                        } else {
557 7a3f1944 bellard
                                                gen_op_add_T1_T0 ();
558 7a3f1944 bellard
                                                gen_op_jmpl ();
559 7a3f1944 bellard
                                                dc->insn = insn;
560 7a3f1944 bellard
                                                dc->delay_slot = 2;
561 7a3f1944 bellard
                                        }
562 7a3f1944 bellard
                                        break;
563 7a3f1944 bellard
                                }
564 7a3f1944 bellard
                                case 0x3c: /* save */
565 7a3f1944 bellard
                                        gen_op_add_T1_T0 ();
566 7a3f1944 bellard
                                        gen_op_save ();
567 7a3f1944 bellard
                                        gen_movl_T0_reg (rd);
568 7a3f1944 bellard
                                        break;
569 7a3f1944 bellard
                                case 0x3d: /* restore */
570 7a3f1944 bellard
                                        gen_op_add_T1_T0 ();
571 7a3f1944 bellard
                                        gen_op_restore ();
572 7a3f1944 bellard
                                        gen_movl_T0_reg (rd);
573 7a3f1944 bellard
                                        break;
574 7a3f1944 bellard
                          }
575 7a3f1944 bellard
                        }
576 7a3f1944 bellard
                        break;
577 7a3f1944 bellard
                }
578 7a3f1944 bellard
          case 3: /* load/store instructions */
579 7a3f1944 bellard
                {
580 7a3f1944 bellard
                        unsigned int xop = GET_FIELD (insn, 7, 12);
581 7a3f1944 bellard
                        rs1 = GET_FIELD (insn, 13, 17);
582 7a3f1944 bellard
                        gen_movl_reg_T0 (rs1);
583 7a3f1944 bellard
                        if (IS_IMM) { /* immediate */
584 7a3f1944 bellard
                                rs2 = GET_FIELDs (insn, 20, 31);
585 7a3f1944 bellard
                                gen_movl_imm_T1 (rs2);
586 7a3f1944 bellard
                        } else {              /* register */
587 7a3f1944 bellard
                                rs2 = GET_FIELD (insn, 27, 31);
588 7a3f1944 bellard
                                gen_movl_reg_T1 (rs2);
589 7a3f1944 bellard
                        }
590 7a3f1944 bellard
                        gen_op_add_T1_T0 ();
591 7a3f1944 bellard
                        if (xop < 4 || xop > 7)  {
592 7a3f1944 bellard
                         switch (xop) {
593 7a3f1944 bellard
                          case 0x0: /* load word */
594 7a3f1944 bellard
                                gen_op_ld ();
595 7a3f1944 bellard
                                break;
596 7a3f1944 bellard
                          case 0x1: /* load unsigned byte */
597 7a3f1944 bellard
                                gen_op_ldub ();
598 7a3f1944 bellard
                                break;
599 7a3f1944 bellard
                          case 0x2: /* load unsigned halfword */
600 7a3f1944 bellard
                                gen_op_lduh ();
601 7a3f1944 bellard
                                break;
602 7a3f1944 bellard
                          case 0x3: /* load double word */
603 7a3f1944 bellard
                                gen_op_ldd ();
604 7a3f1944 bellard
                                gen_movl_T0_reg (rd+1);
605 7a3f1944 bellard
                                break;
606 7a3f1944 bellard
                          case 0x9: /* load signed byte */
607 7a3f1944 bellard
                                gen_op_ldsb ();
608 7a3f1944 bellard
                                break;
609 7a3f1944 bellard
                          case 0xa: /* load signed halfword */
610 7a3f1944 bellard
                                gen_op_ldsh ();
611 7a3f1944 bellard
                                break;
612 7a3f1944 bellard
                          case 0xd: /* ldstub -- XXX: should be atomically */
613 7a3f1944 bellard
                                gen_op_ldstub ();
614 7a3f1944 bellard
                                break;
615 7a3f1944 bellard
                          case 0x0f: /* swap register with memory. Also atomically */
616 7a3f1944 bellard
                                gen_op_swap ();
617 7a3f1944 bellard
                                break;
618 7a3f1944 bellard
                         }
619 7a3f1944 bellard
                         gen_movl_T1_reg (rd);
620 7a3f1944 bellard
                        } else if (xop < 8) {
621 7a3f1944 bellard
                         gen_movl_reg_T1 (rd);
622 7a3f1944 bellard
                         switch (xop) {
623 7a3f1944 bellard
                          case 0x4:
624 7a3f1944 bellard
                                gen_op_st ();
625 7a3f1944 bellard
                                break;
626 7a3f1944 bellard
                          case 0x5:
627 7a3f1944 bellard
                                gen_op_stb ();
628 7a3f1944 bellard
                                break;
629 7a3f1944 bellard
                          case 0x6:
630 7a3f1944 bellard
                                gen_op_sth ();
631 7a3f1944 bellard
                                break;
632 7a3f1944 bellard
                          case 0x7:
633 7a3f1944 bellard
                                gen_op_st ();
634 7a3f1944 bellard
                                gen_movl_reg_T1 (rd+1);
635 7a3f1944 bellard
                                gen_op_st ();
636 7a3f1944 bellard
                                break;
637 7a3f1944 bellard
                         }
638 7a3f1944 bellard
                        }
639 7a3f1944 bellard
                }
640 7a3f1944 bellard
        }
641 7a3f1944 bellard
}
642 7a3f1944 bellard
643 7a3f1944 bellard
static inline int gen_intermediate_code_internal (TranslationBlock *tb, int spc)
644 7a3f1944 bellard
{
645 7a3f1944 bellard
        uint8_t *pc_start = (uint8_t *) tb->pc;
646 7a3f1944 bellard
        uint16_t *gen_opc_end;
647 7a3f1944 bellard
        DisasContext dc;
648 7a3f1944 bellard
649 7a3f1944 bellard
        memset (&dc, 0, sizeof (dc));
650 7a3f1944 bellard
        if (spc) {
651 7a3f1944 bellard
                printf ("SearchPC not yet supported\n");
652 7a3f1944 bellard
                exit (0);
653 7a3f1944 bellard
        }
654 7a3f1944 bellard
        dc.tb = tb;
655 7a3f1944 bellard
        dc.pc = pc_start;
656 7a3f1944 bellard
657 7a3f1944 bellard
        gen_opc_ptr = gen_opc_buf;
658 7a3f1944 bellard
        gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
659 7a3f1944 bellard
        gen_opparam_ptr = gen_opparam_buf;
660 7a3f1944 bellard
661 7a3f1944 bellard
        do {
662 7a3f1944 bellard
                disas_sparc_insn (&dc);
663 7a3f1944 bellard
        } while (!dc.is_br && (gen_opc_ptr < gen_opc_end) &&
664 7a3f1944 bellard
                (dc.pc - pc_start) < (TARGET_PAGE_SIZE - 32));
665 7a3f1944 bellard
666 7a3f1944 bellard
        switch (dc.is_br) {
667 7a3f1944 bellard
          case DISAS_JUMP:
668 7a3f1944 bellard
          case DISAS_TB_JUMP:
669 7a3f1944 bellard
                gen_op_exit_tb ();
670 7a3f1944 bellard
                break;
671 7a3f1944 bellard
        }
672 7a3f1944 bellard
673 7a3f1944 bellard
        *gen_opc_ptr = INDEX_op_end;
674 7a3f1944 bellard
#ifdef DEBUG_DISAS
675 7a3f1944 bellard
        if (loglevel) {
676 7a3f1944 bellard
                fprintf (logfile, "--------------\n");
677 7a3f1944 bellard
                fprintf (logfile, "IN: %s\n", lookup_symbol (pc_start));
678 7a3f1944 bellard
                disas(logfile, pc_start, dc.pc - pc_start, 0, 0);
679 7a3f1944 bellard
                fprintf(logfile, "\n");
680 7a3f1944 bellard
                fprintf(logfile, "OP:\n");
681 7a3f1944 bellard
                dump_ops(gen_opc_buf, gen_opparam_buf);
682 7a3f1944 bellard
                fprintf(logfile, "\n");
683 7a3f1944 bellard
        }
684 7a3f1944 bellard
#endif
685 7a3f1944 bellard
686 7a3f1944 bellard
        return 0;
687 7a3f1944 bellard
}
688 7a3f1944 bellard
689 7a3f1944 bellard
int gen_intermediate_code (CPUSPARCState *env, TranslationBlock *tb)
690 7a3f1944 bellard
{
691 7a3f1944 bellard
        return gen_intermediate_code_internal(tb, 0);
692 7a3f1944 bellard
}
693 7a3f1944 bellard
694 7a3f1944 bellard
int gen_intermediate_code_pc (CPUSPARCState *env, TranslationBlock *tb)
695 7a3f1944 bellard
{
696 7a3f1944 bellard
        return gen_intermediate_code_internal(tb, 1);
697 7a3f1944 bellard
}
698 7a3f1944 bellard
699 7a3f1944 bellard
void *mycpu;
700 7a3f1944 bellard
701 7a3f1944 bellard
CPUSPARCState *cpu_sparc_init (void)
702 7a3f1944 bellard
{
703 7a3f1944 bellard
        CPUSPARCState *env;
704 7a3f1944 bellard
705 7a3f1944 bellard
        cpu_exec_init ();
706 7a3f1944 bellard
707 7a3f1944 bellard
        if (!(env = malloc (sizeof(CPUSPARCState))))
708 7a3f1944 bellard
                return (NULL);
709 7a3f1944 bellard
        memset (env, 0, sizeof (*env));
710 7a3f1944 bellard
        if (!(env->regwptr = malloc (0x2000)))
711 7a3f1944 bellard
                return (NULL);
712 7a3f1944 bellard
        memset (env->regwptr, 0, 0x2000);
713 7a3f1944 bellard
        env->regwptr += 127;
714 7a3f1944 bellard
        env->user_mode_only = 1;
715 7a3f1944 bellard
        mycpu = env;
716 7a3f1944 bellard
        return (env);
717 7a3f1944 bellard
}
718 7a3f1944 bellard
719 7a3f1944 bellard
#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
720 7a3f1944 bellard
721 7a3f1944 bellard
void cpu_sparc_dump_state (CPUSPARCState *env, FILE *f, int flags)
722 7a3f1944 bellard
{
723 7a3f1944 bellard
        int i, x;
724 7a3f1944 bellard
725 7a3f1944 bellard
        fprintf (f, "@PC: %p\n", (void *) env->pc);
726 7a3f1944 bellard
        fprintf (f, "General Registers:\n");
727 7a3f1944 bellard
        for (i=0;i<4;i++)
728 7a3f1944 bellard
                fprintf (f, "%%g%c: %%%08x\t", i+'0', env->gregs[i]);
729 7a3f1944 bellard
        fprintf (f, "\n");
730 7a3f1944 bellard
        for (;i<8;i++)
731 7a3f1944 bellard
                fprintf (f, "%%g%c: %%%08x\t", i+'0', env->gregs[i]);
732 7a3f1944 bellard
        fprintf (f, "\nCurrent Register Window:\n");
733 7a3f1944 bellard
        for (x=0;x<3;x++) {
734 7a3f1944 bellard
          for (i=0;i<4;i++)
735 7a3f1944 bellard
                fprintf (f, "%%%c%d: %%%08x\t", (x==0?'o':(x==1?'l':'i')), i, env->regwptr[i+x*8]);
736 7a3f1944 bellard
          fprintf (f, "\n");
737 7a3f1944 bellard
          for (;i<8;i++)
738 7a3f1944 bellard
                fprintf (f, "%%%c%d: %%%08x\t", (x==0?'o':x==1?'l':'i'), i, env->regwptr[i+x*8]);
739 7a3f1944 bellard
          fprintf (f, "\n");
740 7a3f1944 bellard
        }
741 7a3f1944 bellard
        fprintf (f, "PSR: %x -> %c%c%c%c\n", env->psr,
742 7a3f1944 bellard
                        GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
743 7a3f1944 bellard
                        GET_FLAG(PSR_NEG, 'N'),  GET_FLAG(PSR_CARRY, 'C'));
744 7a3f1944 bellard
}