]> git.proxmox.com Git - mirror_qemu.git/blame - target/nios2/translate.c
tcg: Rename cpu_env to tcg_env
[mirror_qemu.git] / target / nios2 / translate.c
CommitLineData
032c76bc
CW
1/*
2 * Altera Nios II emulation for qemu: main translation routines.
3 *
4 * Copyright (C) 2016 Marek Vasut <marex@denx.de>
5 * Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
6 * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
7 * (Portions of this file that were originally from nios2sim-ng.)
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, see
21 * <http://www.gnu.org/licenses/lgpl-2.1.html>
22 */
23
9d808657 24#include "qemu/osdep.h"
032c76bc 25#include "cpu.h"
dcb32f1d 26#include "tcg/tcg-op.h"
032c76bc
CW
27#include "exec/exec-all.h"
28#include "disas/disas.h"
29#include "exec/helper-proto.h"
30#include "exec/helper-gen.h"
31#include "exec/log.h"
77fc6f5e 32#include "exec/translator.h"
90c84c56 33#include "qemu/qemu-print.h"
24ca3134 34#include "semihosting/semihost.h"
77fc6f5e 35
d53106c9
RH
36#define HELPER_H "helper.h"
37#include "exec/helper-info.c.inc"
38#undef HELPER_H
39
40
77fc6f5e 41/* is_jmp field values */
77fc6f5e 42#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
032c76bc
CW
43
44#define INSTRUCTION_FLG(func, flags) { (func), (flags) }
45#define INSTRUCTION(func) \
46 INSTRUCTION_FLG(func, 0)
47#define INSTRUCTION_NOP() \
48 INSTRUCTION_FLG(nop, 0)
49#define INSTRUCTION_UNIMPLEMENTED() \
50 INSTRUCTION_FLG(gen_excp, EXCP_UNIMPL)
51#define INSTRUCTION_ILLEGAL() \
52 INSTRUCTION_FLG(gen_excp, EXCP_ILLEGAL)
53
54/* Special R-Type instruction opcode */
55#define INSN_R_TYPE 0x3A
56
57/* I-Type instruction parsing */
1746338e
RH
58typedef struct {
59 uint8_t op;
60 union {
61 uint16_t u;
62 int16_t s;
63 } imm16;
64 uint8_t b;
65 uint8_t a;
66} InstrIType;
67
032c76bc 68#define I_TYPE(instr, code) \
1746338e 69 InstrIType (instr) = { \
032c76bc 70 .op = extract32((code), 0, 6), \
4ae4b609 71 .imm16.u = extract32((code), 6, 16), \
032c76bc
CW
72 .b = extract32((code), 22, 5), \
73 .a = extract32((code), 27, 5), \
74 }
75
3d1f63d0
RH
76typedef target_ulong ImmFromIType(const InstrIType *);
77
78static target_ulong imm_unsigned(const InstrIType *i)
79{
80 return i->imm16.u;
81}
82
83static target_ulong imm_signed(const InstrIType *i)
84{
85 return i->imm16.s;
86}
87
cd419bc6
RH
88static target_ulong imm_shifted(const InstrIType *i)
89{
90 return i->imm16.u << 16;
91}
92
032c76bc 93/* R-Type instruction parsing */
1746338e
RH
94typedef struct {
95 uint8_t op;
96 uint8_t imm5;
97 uint8_t opx;
98 uint8_t c;
99 uint8_t b;
100 uint8_t a;
101} InstrRType;
102
032c76bc 103#define R_TYPE(instr, code) \
1746338e 104 InstrRType (instr) = { \
032c76bc
CW
105 .op = extract32((code), 0, 6), \
106 .imm5 = extract32((code), 6, 5), \
107 .opx = extract32((code), 11, 6), \
108 .c = extract32((code), 17, 5), \
109 .b = extract32((code), 22, 5), \
110 .a = extract32((code), 27, 5), \
111 }
112
113/* J-Type instruction parsing */
1746338e
RH
114typedef struct {
115 uint8_t op;
116 uint32_t imm26;
117} InstrJType;
118
032c76bc 119#define J_TYPE(instr, code) \
1746338e 120 InstrJType (instr) = { \
032c76bc
CW
121 .op = extract32((code), 0, 6), \
122 .imm26 = extract32((code), 6, 26), \
123 }
124
cd419bc6 125typedef void GenFn2i(TCGv, TCGv, target_long);
7c849046 126typedef void GenFn3(TCGv, TCGv, TCGv);
3099c41b 127typedef void GenFn4(TCGv, TCGv, TCGv, TCGv);
cd419bc6 128
032c76bc 129typedef struct DisasContext {
e9150ea5 130 DisasContextBase base;
032c76bc 131 target_ulong pc;
032c76bc 132 int mem_idx;
945a5bd3 133 uint32_t tb_flags;
7eed8e40 134 TCGv sink;
796945d5 135 const ControlRegState *cr_state;
3a030870 136 bool eic_present;
032c76bc
CW
137} DisasContext;
138
f1ec078f 139static TCGv cpu_R[NUM_GP_REGS];
17a406ee 140static TCGv cpu_pc;
945a5bd3
RH
141#ifndef CONFIG_USER_ONLY
142static TCGv cpu_crs_R[NUM_GP_REGS];
143#endif
438aabed 144
032c76bc
CW
145typedef struct Nios2Instruction {
146 void (*handler)(DisasContext *dc, uint32_t code, uint32_t flags);
147 uint32_t flags;
148} Nios2Instruction;
149
150static uint8_t get_opcode(uint32_t code)
151{
152 I_TYPE(instr, code);
153 return instr.op;
154}
155
156static uint8_t get_opxcode(uint32_t code)
157{
158 R_TYPE(instr, code);
159 return instr.opx;
160}
161
718db077 162static TCGv load_gpr(DisasContext *dc, unsigned reg)
032c76bc 163{
718db077 164 assert(reg < NUM_GP_REGS);
945a5bd3
RH
165
166 /*
167 * With shadow register sets, register r0 does not necessarily contain 0,
168 * but it is overwhelmingly likely that it does -- software is supposed
169 * to have set r0 to 0 in every shadow register set before use.
170 */
171 if (unlikely(reg == R_ZERO) && FIELD_EX32(dc->tb_flags, TBFLAGS, R0_0)) {
718db077 172 return tcg_constant_tl(0);
032c76bc 173 }
945a5bd3
RH
174 if (FIELD_EX32(dc->tb_flags, TBFLAGS, CRS0)) {
175 return cpu_R[reg];
176 }
177#ifdef CONFIG_USER_ONLY
178 g_assert_not_reached();
179#else
180 return cpu_crs_R[reg];
181#endif
032c76bc
CW
182}
183
7eed8e40
RH
184static TCGv dest_gpr(DisasContext *dc, unsigned reg)
185{
186 assert(reg < NUM_GP_REGS);
945a5bd3
RH
187
188 /*
189 * The spec for shadow register sets isn't clear, but we assume that
190 * writes to r0 are discarded regardless of CRS.
191 */
7eed8e40
RH
192 if (unlikely(reg == R_ZERO)) {
193 if (dc->sink == NULL) {
194 dc->sink = tcg_temp_new();
195 }
196 return dc->sink;
197 }
945a5bd3
RH
198 if (FIELD_EX32(dc->tb_flags, TBFLAGS, CRS0)) {
199 return cpu_R[reg];
200 }
201#ifdef CONFIG_USER_ONLY
202 g_assert_not_reached();
203#else
204 return cpu_crs_R[reg];
205#endif
7eed8e40
RH
206}
207
e84f1768 208static void t_gen_helper_raise_exception(DisasContext *dc, uint32_t index)
032c76bc 209{
e84f1768
RH
210 /* Note that PC is advanced for all hardware exceptions. */
211 tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
ad75a51e 212 gen_helper_raise_exception(tcg_env, tcg_constant_i32(index));
e9150ea5 213 dc->base.is_jmp = DISAS_NORETURN;
032c76bc
CW
214}
215
032c76bc
CW
216static void gen_goto_tb(DisasContext *dc, int n, uint32_t dest)
217{
e9150ea5 218 const TranslationBlock *tb = dc->base.tb;
032c76bc 219
6082414e 220 if (translator_use_goto_tb(&dc->base, dest)) {
032c76bc 221 tcg_gen_goto_tb(n);
17a406ee 222 tcg_gen_movi_tl(cpu_pc, dest);
07ea28b4 223 tcg_gen_exit_tb(tb, n);
032c76bc 224 } else {
17a406ee 225 tcg_gen_movi_tl(cpu_pc, dest);
0e6f22c5 226 tcg_gen_lookup_and_goto_ptr();
032c76bc 227 }
3ad5935c 228 dc->base.is_jmp = DISAS_NORETURN;
032c76bc
CW
229}
230
bd9154aa
RH
231static void gen_jumpr(DisasContext *dc, int regno, bool is_call)
232{
410c6aaa
RH
233 TCGLabel *l = gen_new_label();
234 TCGv test = tcg_temp_new();
235 TCGv dest = load_gpr(dc, regno);
236
237 tcg_gen_andi_tl(test, dest, 3);
238 tcg_gen_brcondi_tl(TCG_COND_NE, test, 0, l);
410c6aaa
RH
239
240 tcg_gen_mov_tl(cpu_pc, dest);
bd9154aa
RH
241 if (is_call) {
242 tcg_gen_movi_tl(dest_gpr(dc, R_RA), dc->base.pc_next);
243 }
0e6f22c5 244 tcg_gen_lookup_and_goto_ptr();
410c6aaa
RH
245
246 gen_set_label(l);
ad75a51e 247 tcg_gen_st_tl(dest, tcg_env, offsetof(CPUNios2State, ctrl[CR_BADADDR]));
410c6aaa
RH
248 t_gen_helper_raise_exception(dc, EXCP_UNALIGND);
249
bd9154aa
RH
250 dc->base.is_jmp = DISAS_NORETURN;
251}
252
032c76bc
CW
253static void gen_excp(DisasContext *dc, uint32_t code, uint32_t flags)
254{
255 t_gen_helper_raise_exception(dc, flags);
256}
257
48b7eac2 258static bool gen_check_supervisor(DisasContext *dc)
032c76bc 259{
945a5bd3 260 if (FIELD_EX32(dc->tb_flags, TBFLAGS, U)) {
032c76bc
CW
261 /* CPU in user mode, privileged instruction called, stop. */
262 t_gen_helper_raise_exception(dc, EXCP_SUPERI);
48b7eac2 263 return false;
032c76bc 264 }
48b7eac2 265 return true;
032c76bc
CW
266}
267
268/*
269 * Used as a placeholder for all instructions which do not have
270 * an effect on the simulator (e.g. flush, sync)
271 */
272static void nop(DisasContext *dc, uint32_t code, uint32_t flags)
273{
274 /* Nothing to do here */
275}
276
277/*
278 * J-Type instructions
279 */
280static void jmpi(DisasContext *dc, uint32_t code, uint32_t flags)
281{
282 J_TYPE(instr, code);
283 gen_goto_tb(dc, 0, (dc->pc & 0xF0000000) | (instr.imm26 << 2));
032c76bc
CW
284}
285
286static void call(DisasContext *dc, uint32_t code, uint32_t flags)
287{
7eed8e40 288 tcg_gen_movi_tl(dest_gpr(dc, R_RA), dc->base.pc_next);
032c76bc
CW
289 jmpi(dc, code, flags);
290}
291
292/*
293 * I-Type instructions
294 */
295/* Load instructions */
296static void gen_ldx(DisasContext *dc, uint32_t code, uint32_t flags)
297{
298 I_TYPE(instr, code);
299
300 TCGv addr = tcg_temp_new();
7eed8e40 301 TCGv data = dest_gpr(dc, instr.b);
032c76bc 302
4ae4b609 303 tcg_gen_addi_tl(addr, load_gpr(dc, instr.a), instr.imm16.s);
a978c37b
RH
304#ifdef CONFIG_USER_ONLY
305 flags |= MO_UNALN;
306#else
307 flags |= MO_ALIGN;
308#endif
032c76bc 309 tcg_gen_qemu_ld_tl(data, addr, dc->mem_idx, flags);
032c76bc
CW
310}
311
312/* Store instructions */
313static void gen_stx(DisasContext *dc, uint32_t code, uint32_t flags)
314{
315 I_TYPE(instr, code);
316 TCGv val = load_gpr(dc, instr.b);
317
318 TCGv addr = tcg_temp_new();
4ae4b609 319 tcg_gen_addi_tl(addr, load_gpr(dc, instr.a), instr.imm16.s);
a978c37b
RH
320#ifdef CONFIG_USER_ONLY
321 flags |= MO_UNALN;
322#else
323 flags |= MO_ALIGN;
324#endif
032c76bc 325 tcg_gen_qemu_st_tl(val, addr, dc->mem_idx, flags);
032c76bc
CW
326}
327
328/* Branch instructions */
329static void br(DisasContext *dc, uint32_t code, uint32_t flags)
330{
331 I_TYPE(instr, code);
332
77b42a2d 333 gen_goto_tb(dc, 0, dc->base.pc_next + (instr.imm16.s & -4));
032c76bc
CW
334}
335
336static void gen_bxx(DisasContext *dc, uint32_t code, uint32_t flags)
337{
338 I_TYPE(instr, code);
339
340 TCGLabel *l1 = gen_new_label();
7eed8e40 341 tcg_gen_brcond_tl(flags, load_gpr(dc, instr.a), load_gpr(dc, instr.b), l1);
77b42a2d 342 gen_goto_tb(dc, 0, dc->base.pc_next);
032c76bc 343 gen_set_label(l1);
77b42a2d 344 gen_goto_tb(dc, 1, dc->base.pc_next + (instr.imm16.s & -4));
032c76bc
CW
345}
346
347/* Comparison instructions */
3d1f63d0
RH
348static void do_i_cmpxx(DisasContext *dc, uint32_t insn,
349 TCGCond cond, ImmFromIType *imm)
350{
351 I_TYPE(instr, insn);
7eed8e40
RH
352 tcg_gen_setcondi_tl(cond, dest_gpr(dc, instr.b),
353 load_gpr(dc, instr.a), imm(&instr));
032c76bc
CW
354}
355
3d1f63d0
RH
356#define gen_i_cmpxx(fname, imm) \
357 static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
358 { do_i_cmpxx(dc, code, flags, imm); }
359
360gen_i_cmpxx(gen_cmpxxsi, imm_signed)
361gen_i_cmpxx(gen_cmpxxui, imm_unsigned)
032c76bc
CW
362
363/* Math/logic instructions */
cd419bc6
RH
364static void do_i_math_logic(DisasContext *dc, uint32_t insn,
365 GenFn2i *fn, ImmFromIType *imm,
366 bool x_op_0_eq_x)
367{
368 I_TYPE(instr, insn);
369 target_ulong val;
370
371 if (unlikely(instr.b == R_ZERO)) {
372 /* Store to R_ZERO is ignored -- this catches the canonical NOP. */
373 return;
374 }
375
376 val = imm(&instr);
377
945a5bd3 378 if (instr.a == R_ZERO && FIELD_EX32(dc->tb_flags, TBFLAGS, R0_0)) {
cd419bc6 379 /* This catches the canonical expansions of movi and movhi. */
7eed8e40 380 tcg_gen_movi_tl(dest_gpr(dc, instr.b), x_op_0_eq_x ? val : 0);
cd419bc6 381 } else {
7eed8e40 382 fn(dest_gpr(dc, instr.b), load_gpr(dc, instr.a), val);
cd419bc6 383 }
032c76bc
CW
384}
385
cd419bc6
RH
386#define gen_i_math_logic(fname, insn, x_op_0, imm) \
387 static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
388 { do_i_math_logic(dc, code, tcg_gen_##insn##_tl, imm, x_op_0); }
389
390gen_i_math_logic(addi, addi, 1, imm_signed)
391gen_i_math_logic(muli, muli, 0, imm_signed)
032c76bc 392
cd419bc6
RH
393gen_i_math_logic(andi, andi, 0, imm_unsigned)
394gen_i_math_logic(ori, ori, 1, imm_unsigned)
395gen_i_math_logic(xori, xori, 1, imm_unsigned)
032c76bc 396
cd419bc6
RH
397gen_i_math_logic(andhi, andi, 0, imm_shifted)
398gen_i_math_logic(orhi , ori, 1, imm_shifted)
399gen_i_math_logic(xorhi, xori, 1, imm_shifted)
032c76bc 400
3a030870
RH
401/* rB <- prs.rA + sigma(IMM16) */
402static void rdprs(DisasContext *dc, uint32_t code, uint32_t flags)
403{
404 if (!dc->eic_present) {
405 t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
406 return;
407 }
408 if (!gen_check_supervisor(dc)) {
409 return;
410 }
411
412#ifdef CONFIG_USER_ONLY
413 g_assert_not_reached();
414#else
415 I_TYPE(instr, code);
416 TCGv dest = dest_gpr(dc, instr.b);
ad75a51e 417 gen_helper_rdprs(dest, tcg_env, tcg_constant_i32(instr.a));
3a030870
RH
418 tcg_gen_addi_tl(dest, dest, instr.imm16.s);
419#endif
420}
421
032c76bc
CW
422/* Prototype only, defined below */
423static void handle_r_type_instr(DisasContext *dc, uint32_t code,
424 uint32_t flags);
425
426static const Nios2Instruction i_type_instructions[] = {
427 INSTRUCTION(call), /* call */
428 INSTRUCTION(jmpi), /* jmpi */
429 INSTRUCTION_ILLEGAL(),
430 INSTRUCTION_FLG(gen_ldx, MO_UB), /* ldbu */
431 INSTRUCTION(addi), /* addi */
432 INSTRUCTION_FLG(gen_stx, MO_UB), /* stb */
433 INSTRUCTION(br), /* br */
434 INSTRUCTION_FLG(gen_ldx, MO_SB), /* ldb */
435 INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_GE), /* cmpgei */
436 INSTRUCTION_ILLEGAL(),
437 INSTRUCTION_ILLEGAL(),
6ab17902 438 INSTRUCTION_FLG(gen_ldx, MO_TEUW), /* ldhu */
032c76bc 439 INSTRUCTION(andi), /* andi */
6ab17902 440 INSTRUCTION_FLG(gen_stx, MO_TEUW), /* sth */
032c76bc 441 INSTRUCTION_FLG(gen_bxx, TCG_COND_GE), /* bge */
6ab17902 442 INSTRUCTION_FLG(gen_ldx, MO_TESW), /* ldh */
032c76bc
CW
443 INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_LT), /* cmplti */
444 INSTRUCTION_ILLEGAL(),
445 INSTRUCTION_ILLEGAL(),
446 INSTRUCTION_NOP(), /* initda */
447 INSTRUCTION(ori), /* ori */
6ab17902 448 INSTRUCTION_FLG(gen_stx, MO_TEUL), /* stw */
032c76bc 449 INSTRUCTION_FLG(gen_bxx, TCG_COND_LT), /* blt */
6ab17902 450 INSTRUCTION_FLG(gen_ldx, MO_TEUL), /* ldw */
032c76bc
CW
451 INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_NE), /* cmpnei */
452 INSTRUCTION_ILLEGAL(),
453 INSTRUCTION_ILLEGAL(),
454 INSTRUCTION_NOP(), /* flushda */
455 INSTRUCTION(xori), /* xori */
456 INSTRUCTION_ILLEGAL(),
457 INSTRUCTION_FLG(gen_bxx, TCG_COND_NE), /* bne */
458 INSTRUCTION_ILLEGAL(),
459 INSTRUCTION_FLG(gen_cmpxxsi, TCG_COND_EQ), /* cmpeqi */
460 INSTRUCTION_ILLEGAL(),
461 INSTRUCTION_ILLEGAL(),
462 INSTRUCTION_FLG(gen_ldx, MO_UB), /* ldbuio */
463 INSTRUCTION(muli), /* muli */
464 INSTRUCTION_FLG(gen_stx, MO_UB), /* stbio */
465 INSTRUCTION_FLG(gen_bxx, TCG_COND_EQ), /* beq */
466 INSTRUCTION_FLG(gen_ldx, MO_SB), /* ldbio */
467 INSTRUCTION_FLG(gen_cmpxxui, TCG_COND_GEU), /* cmpgeui */
468 INSTRUCTION_ILLEGAL(),
469 INSTRUCTION_ILLEGAL(),
6ab17902 470 INSTRUCTION_FLG(gen_ldx, MO_TEUW), /* ldhuio */
032c76bc 471 INSTRUCTION(andhi), /* andhi */
6ab17902 472 INSTRUCTION_FLG(gen_stx, MO_TEUW), /* sthio */
032c76bc 473 INSTRUCTION_FLG(gen_bxx, TCG_COND_GEU), /* bgeu */
6ab17902 474 INSTRUCTION_FLG(gen_ldx, MO_TESW), /* ldhio */
032c76bc
CW
475 INSTRUCTION_FLG(gen_cmpxxui, TCG_COND_LTU), /* cmpltui */
476 INSTRUCTION_ILLEGAL(),
477 INSTRUCTION_UNIMPLEMENTED(), /* custom */
478 INSTRUCTION_NOP(), /* initd */
479 INSTRUCTION(orhi), /* orhi */
6ab17902 480 INSTRUCTION_FLG(gen_stx, MO_TESL), /* stwio */
032c76bc 481 INSTRUCTION_FLG(gen_bxx, TCG_COND_LTU), /* bltu */
6ab17902 482 INSTRUCTION_FLG(gen_ldx, MO_TEUL), /* ldwio */
3a030870 483 INSTRUCTION(rdprs), /* rdprs */
032c76bc
CW
484 INSTRUCTION_ILLEGAL(),
485 INSTRUCTION_FLG(handle_r_type_instr, 0), /* R-Type */
486 INSTRUCTION_NOP(), /* flushd */
487 INSTRUCTION(xorhi), /* xorhi */
488 INSTRUCTION_ILLEGAL(),
489 INSTRUCTION_ILLEGAL(),
490 INSTRUCTION_ILLEGAL(),
491};
492
493/*
494 * R-Type instructions
495 */
496/*
497 * status <- estatus
498 * PC <- ea
499 */
500static void eret(DisasContext *dc, uint32_t code, uint32_t flags)
501{
48b7eac2
RH
502 if (!gen_check_supervisor(dc)) {
503 return;
504 }
b106e7b7 505
8d855c89
AG
506#ifdef CONFIG_USER_ONLY
507 g_assert_not_reached();
508#else
6bcc59ca
RH
509 if (FIELD_EX32(dc->tb_flags, TBFLAGS, CRS0)) {
510 TCGv tmp = tcg_temp_new();
ad75a51e
RH
511 tcg_gen_ld_tl(tmp, tcg_env, offsetof(CPUNios2State, ctrl[CR_ESTATUS]));
512 gen_helper_eret(tcg_env, tmp, load_gpr(dc, R_EA));
6bcc59ca 513 } else {
ad75a51e 514 gen_helper_eret(tcg_env, load_gpr(dc, R_SSTATUS), load_gpr(dc, R_EA));
6bcc59ca 515 }
8d855c89
AG
516 dc->base.is_jmp = DISAS_NORETURN;
517#endif
032c76bc
CW
518}
519
520/* PC <- ra */
521static void ret(DisasContext *dc, uint32_t code, uint32_t flags)
522{
bd9154aa 523 gen_jumpr(dc, R_RA, false);
032c76bc
CW
524}
525
48da43b2
RH
526/*
527 * status <- bstatus
528 * PC <- ba
529 */
032c76bc
CW
530static void bret(DisasContext *dc, uint32_t code, uint32_t flags)
531{
48da43b2
RH
532 if (!gen_check_supervisor(dc)) {
533 return;
534 }
032c76bc 535
48da43b2
RH
536#ifdef CONFIG_USER_ONLY
537 g_assert_not_reached();
538#else
f1ec078f 539 TCGv tmp = tcg_temp_new();
ad75a51e
RH
540 tcg_gen_ld_tl(tmp, tcg_env, offsetof(CPUNios2State, ctrl[CR_BSTATUS]));
541 gen_helper_eret(tcg_env, tmp, load_gpr(dc, R_BA));
f1ec078f 542
48da43b2
RH
543 dc->base.is_jmp = DISAS_NORETURN;
544#endif
032c76bc
CW
545}
546
547/* PC <- rA */
548static void jmp(DisasContext *dc, uint32_t code, uint32_t flags)
549{
550 R_TYPE(instr, code);
551
bd9154aa 552 gen_jumpr(dc, instr.a, false);
032c76bc
CW
553}
554
555/* rC <- PC + 4 */
556static void nextpc(DisasContext *dc, uint32_t code, uint32_t flags)
557{
558 R_TYPE(instr, code);
559
7eed8e40 560 tcg_gen_movi_tl(dest_gpr(dc, instr.c), dc->base.pc_next);
032c76bc
CW
561}
562
563/*
564 * ra <- PC + 4
565 * PC <- rA
566 */
567static void callr(DisasContext *dc, uint32_t code, uint32_t flags)
568{
569 R_TYPE(instr, code);
570
bd9154aa 571 gen_jumpr(dc, instr.a, true);
032c76bc
CW
572}
573
574/* rC <- ctlN */
575static void rdctl(DisasContext *dc, uint32_t code, uint32_t flags)
576{
796945d5
RH
577 if (!gen_check_supervisor(dc)) {
578 return;
579 }
580
581#ifdef CONFIG_USER_ONLY
582 g_assert_not_reached();
583#else
032c76bc 584 R_TYPE(instr, code);
7eed8e40 585 TCGv t1, t2, dest = dest_gpr(dc, instr.c);
032c76bc 586
796945d5
RH
587 /* Reserved registers read as zero. */
588 if (nios2_cr_reserved(&dc->cr_state[instr.imm5])) {
7eed8e40 589 tcg_gen_movi_tl(dest, 0);
0b6e8f5b
RH
590 return;
591 }
592
b8f036a9 593 switch (instr.imm5) {
8d8d73b5
RH
594 case CR_IPENDING:
595 /*
596 * The value of the ipending register is synthetic.
597 * In hw, this is the AND of a set of hardware irq lines
598 * with the ienable register. In qemu, we re-use the space
599 * of CR_IPENDING to store the set of irq lines, and so we
600 * must perform the AND here, and anywhere else we need the
601 * guest value of ipending.
602 */
f1ec078f
RH
603 t1 = tcg_temp_new();
604 t2 = tcg_temp_new();
ad75a51e
RH
605 tcg_gen_ld_tl(t1, tcg_env, offsetof(CPUNios2State, ctrl[CR_IPENDING]));
606 tcg_gen_ld_tl(t2, tcg_env, offsetof(CPUNios2State, ctrl[CR_IENABLE]));
7eed8e40 607 tcg_gen_and_tl(dest, t1, t2);
8d8d73b5 608 break;
032c76bc 609 default:
ad75a51e 610 tcg_gen_ld_tl(dest, tcg_env,
b8f036a9 611 offsetof(CPUNios2State, ctrl[instr.imm5]));
032c76bc
CW
612 break;
613 }
796945d5 614#endif
032c76bc
CW
615}
616
617/* ctlN <- rA */
618static void wrctl(DisasContext *dc, uint32_t code, uint32_t flags)
619{
48b7eac2
RH
620 if (!gen_check_supervisor(dc)) {
621 return;
622 }
032c76bc 623
48b7eac2
RH
624#ifdef CONFIG_USER_ONLY
625 g_assert_not_reached();
626#else
304c05df
RH
627 R_TYPE(instr, code);
628 TCGv v = load_gpr(dc, instr.a);
796945d5
RH
629 uint32_t ofs = offsetof(CPUNios2State, ctrl[instr.imm5]);
630 uint32_t wr = dc->cr_state[instr.imm5].writable;
631 uint32_t ro = dc->cr_state[instr.imm5].readonly;
632
633 /* Skip reserved or readonly registers. */
634 if (wr == 0) {
635 return;
636 }
304c05df 637
b8f036a9 638 switch (instr.imm5) {
032c76bc 639 case CR_PTEADDR:
ad75a51e 640 gen_helper_mmu_write_pteaddr(tcg_env, v);
304c05df 641 break;
032c76bc 642 case CR_TLBACC:
ad75a51e 643 gen_helper_mmu_write_tlbacc(tcg_env, v);
304c05df 644 break;
032c76bc 645 case CR_TLBMISC:
ad75a51e 646 gen_helper_mmu_write_tlbmisc(tcg_env, v);
032c76bc 647 break;
b72c9d59
RH
648 case CR_STATUS:
649 case CR_IENABLE:
650 /* If interrupts were enabled using WRCTL, trigger them. */
651 dc->base.is_jmp = DISAS_UPDATE;
652 /* fall through */
032c76bc 653 default:
796945d5
RH
654 if (wr == -1) {
655 /* The register is entirely writable. */
ad75a51e 656 tcg_gen_st_tl(v, tcg_env, ofs);
796945d5
RH
657 } else {
658 /*
659 * The register is partially read-only or reserved:
660 * merge the value.
661 */
662 TCGv n = tcg_temp_new();
663
664 tcg_gen_andi_tl(n, v, wr);
665
666 if (ro != 0) {
667 TCGv o = tcg_temp_new();
ad75a51e 668 tcg_gen_ld_tl(o, tcg_env, ofs);
796945d5
RH
669 tcg_gen_andi_tl(o, o, ro);
670 tcg_gen_or_tl(n, n, o);
796945d5
RH
671 }
672
ad75a51e 673 tcg_gen_st_tl(n, tcg_env, ofs);
796945d5 674 }
032c76bc
CW
675 break;
676 }
032c76bc
CW
677#endif
678}
679
3a030870
RH
680/* prs.rC <- rA */
681static void wrprs(DisasContext *dc, uint32_t code, uint32_t flags)
682{
683 if (!dc->eic_present) {
684 t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
685 return;
686 }
687 if (!gen_check_supervisor(dc)) {
688 return;
689 }
690
691#ifdef CONFIG_USER_ONLY
692 g_assert_not_reached();
693#else
694 R_TYPE(instr, code);
ad75a51e 695 gen_helper_wrprs(tcg_env, tcg_constant_i32(instr.c),
3a030870
RH
696 load_gpr(dc, instr.a));
697 /*
698 * The expected write to PRS[r0] is 0, from CRS[r0].
699 * If not, and CRS == PRS (which we cannot tell from here),
700 * we may now have a non-zero value in our current r0.
701 * By ending the TB, we re-evaluate tb_flags and find out.
702 */
703 if (instr.c == 0
704 && (instr.a != 0 || !FIELD_EX32(dc->tb_flags, TBFLAGS, R0_0))) {
705 dc->base.is_jmp = DISAS_UPDATE;
706 }
707#endif
708}
709
032c76bc
CW
710/* Comparison instructions */
711static void gen_cmpxx(DisasContext *dc, uint32_t code, uint32_t flags)
712{
713 R_TYPE(instr, code);
7eed8e40
RH
714 tcg_gen_setcond_tl(flags, dest_gpr(dc, instr.c),
715 load_gpr(dc, instr.a), load_gpr(dc, instr.b));
032c76bc
CW
716}
717
718/* Math/logic instructions */
7c849046
RH
719static void do_ri_math_logic(DisasContext *dc, uint32_t insn, GenFn2i *fn)
720{
721 R_TYPE(instr, insn);
7eed8e40 722 fn(dest_gpr(dc, instr.c), load_gpr(dc, instr.a), instr.imm5);
7c849046
RH
723}
724
725static void do_rr_math_logic(DisasContext *dc, uint32_t insn, GenFn3 *fn)
726{
727 R_TYPE(instr, insn);
7eed8e40 728 fn(dest_gpr(dc, instr.c), load_gpr(dc, instr.a), load_gpr(dc, instr.b));
032c76bc
CW
729}
730
7c849046
RH
731#define gen_ri_math_logic(fname, insn) \
732 static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
733 { do_ri_math_logic(dc, code, tcg_gen_##insn##_tl); }
734
735#define gen_rr_math_logic(fname, insn) \
736 static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
737 { do_rr_math_logic(dc, code, tcg_gen_##insn##_tl); }
738
739gen_rr_math_logic(add, add)
740gen_rr_math_logic(sub, sub)
741gen_rr_math_logic(mul, mul)
032c76bc 742
7c849046
RH
743gen_rr_math_logic(and, and)
744gen_rr_math_logic(or, or)
745gen_rr_math_logic(xor, xor)
746gen_rr_math_logic(nor, nor)
032c76bc 747
7c849046
RH
748gen_ri_math_logic(srai, sari)
749gen_ri_math_logic(srli, shri)
750gen_ri_math_logic(slli, shli)
751gen_ri_math_logic(roli, rotli)
032c76bc 752
3099c41b
RH
753static void do_rr_mul_high(DisasContext *dc, uint32_t insn, GenFn4 *fn)
754{
755 R_TYPE(instr, insn);
7eed8e40 756 TCGv discard = tcg_temp_new();
3099c41b 757
7eed8e40
RH
758 fn(discard, dest_gpr(dc, instr.c),
759 load_gpr(dc, instr.a), load_gpr(dc, instr.b));
032c76bc
CW
760}
761
3099c41b
RH
762#define gen_rr_mul_high(fname, insn) \
763 static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
764 { do_rr_mul_high(dc, code, tcg_gen_##insn##_tl); }
765
766gen_rr_mul_high(mulxss, muls2)
767gen_rr_mul_high(mulxuu, mulu2)
768gen_rr_mul_high(mulxsu, mulsu2)
032c76bc 769
541cb627
RH
770static void do_rr_shift(DisasContext *dc, uint32_t insn, GenFn3 *fn)
771{
772 R_TYPE(instr, insn);
7eed8e40 773 TCGv sh = tcg_temp_new();
541cb627 774
7eed8e40
RH
775 tcg_gen_andi_tl(sh, load_gpr(dc, instr.b), 31);
776 fn(dest_gpr(dc, instr.c), load_gpr(dc, instr.a), sh);
541cb627
RH
777}
778
779#define gen_rr_shift(fname, insn) \
780 static void (fname)(DisasContext *dc, uint32_t code, uint32_t flags) \
781 { do_rr_shift(dc, code, tcg_gen_##insn##_tl); }
782
783gen_rr_shift(sra, sar)
784gen_rr_shift(srl, shr)
785gen_rr_shift(sll, shl)
786gen_rr_shift(rol, rotl)
787gen_rr_shift(ror, rotr)
032c76bc
CW
788
789static void divs(DisasContext *dc, uint32_t code, uint32_t flags)
790{
791 R_TYPE(instr, (code));
ad75a51e 792 gen_helper_divs(dest_gpr(dc, instr.c), tcg_env,
345b7a87 793 load_gpr(dc, instr.a), load_gpr(dc, instr.b));
032c76bc
CW
794}
795
796static void divu(DisasContext *dc, uint32_t code, uint32_t flags)
797{
798 R_TYPE(instr, (code));
ad75a51e 799 gen_helper_divu(dest_gpr(dc, instr.c), tcg_env,
345b7a87 800 load_gpr(dc, instr.a), load_gpr(dc, instr.b));
032c76bc
CW
801}
802
87d7bfdb
RH
803static void trap(DisasContext *dc, uint32_t code, uint32_t flags)
804{
805#ifdef CONFIG_USER_ONLY
806 /*
807 * The imm5 field is not stored anywhere on real hw; the kernel
808 * has to load the insn and extract the field. But we can make
809 * things easier for cpu_loop if we pop this into env->error_code.
810 */
811 R_TYPE(instr, code);
ad75a51e 812 tcg_gen_st_i32(tcg_constant_i32(instr.imm5), tcg_env,
87d7bfdb
RH
813 offsetof(CPUNios2State, error_code));
814#endif
815 t_gen_helper_raise_exception(dc, EXCP_TRAP);
816}
817
24ca3134
RH
818static void gen_break(DisasContext *dc, uint32_t code, uint32_t flags)
819{
820#ifndef CONFIG_USER_ONLY
821 /* The semihosting instruction is "break 1". */
cab9f193 822 bool is_user = FIELD_EX32(dc->tb_flags, TBFLAGS, U);
24ca3134 823 R_TYPE(instr, code);
cab9f193 824 if (semihosting_enabled(is_user) && instr.imm5 == 1) {
24ca3134
RH
825 t_gen_helper_raise_exception(dc, EXCP_SEMIHOST);
826 return;
827 }
828#endif
829
830 t_gen_helper_raise_exception(dc, EXCP_BREAK);
831}
832
032c76bc
CW
833static const Nios2Instruction r_type_instructions[] = {
834 INSTRUCTION_ILLEGAL(),
835 INSTRUCTION(eret), /* eret */
836 INSTRUCTION(roli), /* roli */
837 INSTRUCTION(rol), /* rol */
838 INSTRUCTION_NOP(), /* flushp */
839 INSTRUCTION(ret), /* ret */
840 INSTRUCTION(nor), /* nor */
841 INSTRUCTION(mulxuu), /* mulxuu */
842 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_GE), /* cmpge */
843 INSTRUCTION(bret), /* bret */
844 INSTRUCTION_ILLEGAL(),
845 INSTRUCTION(ror), /* ror */
846 INSTRUCTION_NOP(), /* flushi */
847 INSTRUCTION(jmp), /* jmp */
848 INSTRUCTION(and), /* and */
849 INSTRUCTION_ILLEGAL(),
850 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LT), /* cmplt */
851 INSTRUCTION_ILLEGAL(),
852 INSTRUCTION(slli), /* slli */
853 INSTRUCTION(sll), /* sll */
3a030870 854 INSTRUCTION(wrprs), /* wrprs */
032c76bc
CW
855 INSTRUCTION_ILLEGAL(),
856 INSTRUCTION(or), /* or */
857 INSTRUCTION(mulxsu), /* mulxsu */
858 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_NE), /* cmpne */
859 INSTRUCTION_ILLEGAL(),
860 INSTRUCTION(srli), /* srli */
861 INSTRUCTION(srl), /* srl */
862 INSTRUCTION(nextpc), /* nextpc */
863 INSTRUCTION(callr), /* callr */
864 INSTRUCTION(xor), /* xor */
865 INSTRUCTION(mulxss), /* mulxss */
866 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_EQ), /* cmpeq */
867 INSTRUCTION_ILLEGAL(),
868 INSTRUCTION_ILLEGAL(),
869 INSTRUCTION_ILLEGAL(),
870 INSTRUCTION(divu), /* divu */
871 INSTRUCTION(divs), /* div */
872 INSTRUCTION(rdctl), /* rdctl */
873 INSTRUCTION(mul), /* mul */
874 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_GEU), /* cmpgeu */
875 INSTRUCTION_NOP(), /* initi */
876 INSTRUCTION_ILLEGAL(),
877 INSTRUCTION_ILLEGAL(),
878 INSTRUCTION_ILLEGAL(),
87d7bfdb 879 INSTRUCTION(trap), /* trap */
032c76bc
CW
880 INSTRUCTION(wrctl), /* wrctl */
881 INSTRUCTION_ILLEGAL(),
882 INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU), /* cmpltu */
883 INSTRUCTION(add), /* add */
884 INSTRUCTION_ILLEGAL(),
885 INSTRUCTION_ILLEGAL(),
24ca3134 886 INSTRUCTION(gen_break), /* break */
032c76bc
CW
887 INSTRUCTION_ILLEGAL(),
888 INSTRUCTION(nop), /* nop */
889 INSTRUCTION_ILLEGAL(),
890 INSTRUCTION_ILLEGAL(),
891 INSTRUCTION(sub), /* sub */
892 INSTRUCTION(srai), /* srai */
893 INSTRUCTION(sra), /* sra */
894 INSTRUCTION_ILLEGAL(),
895 INSTRUCTION_ILLEGAL(),
896 INSTRUCTION_ILLEGAL(),
897 INSTRUCTION_ILLEGAL(),
898};
899
900static void handle_r_type_instr(DisasContext *dc, uint32_t code, uint32_t flags)
901{
902 uint8_t opx;
903 const Nios2Instruction *instr;
904
905 opx = get_opxcode(code);
906 if (unlikely(opx >= ARRAY_SIZE(r_type_instructions))) {
907 goto illegal_op;
908 }
909
910 instr = &r_type_instructions[opx];
911 instr->handler(dc, code, instr->flags);
912
913 return;
914
915illegal_op:
916 t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
917}
918
b8f036a9 919static const char * const gr_regnames[NUM_GP_REGS] = {
032c76bc
CW
920 "zero", "at", "r2", "r3",
921 "r4", "r5", "r6", "r7",
922 "r8", "r9", "r10", "r11",
923 "r12", "r13", "r14", "r15",
924 "r16", "r17", "r18", "r19",
925 "r20", "r21", "r22", "r23",
926 "et", "bt", "gp", "sp",
927 "fp", "ea", "ba", "ra",
b8f036a9
RH
928};
929
5dfb910d 930#ifndef CONFIG_USER_ONLY
b8f036a9 931static const char * const cr_regnames[NUM_CR_REGS] = {
032c76bc 932 "status", "estatus", "bstatus", "ienable",
5dfb910d 933 "ipending", "cpuid", "res6", "exception",
032c76bc
CW
934 "pteaddr", "tlbacc", "tlbmisc", "reserved1",
935 "badaddr", "config", "mpubase", "mpuacc",
5dfb910d
RH
936 "res16", "res17", "res18", "res19",
937 "res20", "res21", "res22", "res23",
938 "res24", "res25", "res26", "res27",
939 "res28", "res29", "res30", "res31",
032c76bc 940};
5dfb910d 941#endif
032c76bc 942
032c76bc 943/* generate intermediate code for basic block 'tb'. */
d67cbd93 944static void nios2_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
032c76bc 945{
d67cbd93 946 DisasContext *dc = container_of(dcbase, DisasContext, base);
9c489ea6 947 CPUNios2State *env = cs->env_ptr;
796945d5 948 Nios2CPU *cpu = env_archcpu(env);
d67cbd93 949 int page_insns;
032c76bc 950
d67cbd93 951 dc->mem_idx = cpu_mmu_index(env, false);
796945d5 952 dc->cr_state = cpu->cr_state;
945a5bd3 953 dc->tb_flags = dc->base.tb->flags;
3a030870 954 dc->eic_present = cpu->eic_present;
e9150ea5 955
d67cbd93
RH
956 /* Bound the number of insns to execute to those left on the page. */
957 page_insns = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
958 dc->base.max_insns = MIN(page_insns, dc->base.max_insns);
959}
e9150ea5 960
d67cbd93
RH
961static void nios2_tr_tb_start(DisasContextBase *db, CPUState *cs)
962{
963}
032c76bc 964
d67cbd93
RH
965static void nios2_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
966{
967 tcg_gen_insn_start(dcbase->pc_next);
968}
032c76bc 969
d67cbd93
RH
970static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
971{
972 DisasContext *dc = container_of(dcbase, DisasContext, base);
973 CPUNios2State *env = cs->env_ptr;
1ff375d7
RH
974 const Nios2Instruction *instr;
975 uint32_t code, pc;
976 uint8_t op;
e9150ea5 977
1ff375d7
RH
978 pc = dc->base.pc_next;
979 dc->pc = pc;
980 dc->base.pc_next = pc + 4;
032c76bc 981
d67cbd93 982 /* Decode an instruction */
1ff375d7
RH
983 code = cpu_ldl_code(env, pc);
984 op = get_opcode(code);
985
986 if (unlikely(op >= ARRAY_SIZE(i_type_instructions))) {
987 t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
988 return;
989 }
990
7eed8e40
RH
991 dc->sink = NULL;
992
1ff375d7
RH
993 instr = &i_type_instructions[op];
994 instr->handler(dc, code, instr->flags);
d67cbd93
RH
995}
996
997static void nios2_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
998{
999 DisasContext *dc = container_of(dcbase, DisasContext, base);
032c76bc 1000
032c76bc 1001 /* Indicate where the next block should start */
e9150ea5 1002 switch (dc->base.is_jmp) {
d67cbd93 1003 case DISAS_TOO_MANY:
5b843284
RH
1004 gen_goto_tb(dc, 0, dc->base.pc_next);
1005 break;
1006
c7694535 1007 case DISAS_UPDATE:
5b843284 1008 /* Save the current PC, and return to the main loop. */
17a406ee 1009 tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
07ea28b4 1010 tcg_gen_exit_tb(NULL, 0);
032c76bc
CW
1011 break;
1012
42928f2c 1013 case DISAS_NORETURN:
032c76bc
CW
1014 /* nothing more to generate */
1015 break;
032c76bc 1016
d67cbd93
RH
1017 default:
1018 g_assert_not_reached();
032c76bc 1019 }
d67cbd93
RH
1020}
1021
8eb806a7
RH
1022static void nios2_tr_disas_log(const DisasContextBase *dcbase,
1023 CPUState *cpu, FILE *logfile)
d67cbd93 1024{
8eb806a7
RH
1025 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
1026 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
d67cbd93
RH
1027}
1028
1029static const TranslatorOps nios2_tr_ops = {
1030 .init_disas_context = nios2_tr_init_disas_context,
1031 .tb_start = nios2_tr_tb_start,
1032 .insn_start = nios2_tr_insn_start,
d67cbd93
RH
1033 .translate_insn = nios2_tr_translate_insn,
1034 .tb_stop = nios2_tr_tb_stop,
1035 .disas_log = nios2_tr_disas_log,
1036};
1037
597f9b2d 1038void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
306c8721 1039 target_ulong pc, void *host_pc)
d67cbd93
RH
1040{
1041 DisasContext dc;
306c8721 1042 translator_loop(cs, tb, max_insns, pc, host_pc, &nios2_tr_ops, &dc.base);
032c76bc
CW
1043}
1044
90c84c56 1045void nios2_cpu_dump_state(CPUState *cs, FILE *f, int flags)
032c76bc
CW
1046{
1047 Nios2CPU *cpu = NIOS2_CPU(cs);
1048 CPUNios2State *env = &cpu->env;
1049 int i;
1050
17a406ee 1051 qemu_fprintf(f, "IN: PC=%x %s\n", env->pc, lookup_symbol(env->pc));
032c76bc 1052
b8f036a9
RH
1053 for (i = 0; i < NUM_GP_REGS; i++) {
1054 qemu_fprintf(f, "%9s=%8.8x ", gr_regnames[i], env->regs[i]);
1055 if ((i + 1) % 4 == 0) {
1056 qemu_fprintf(f, "\n");
1057 }
1058 }
5dfb910d
RH
1059
1060#if !defined(CONFIG_USER_ONLY)
796945d5
RH
1061 int j;
1062
1063 for (i = j = 0; i < NUM_CR_REGS; i++) {
1064 if (!nios2_cr_reserved(&cpu->cr_state[i])) {
1065 qemu_fprintf(f, "%9s=%8.8x ", cr_regnames[i], env->ctrl[i]);
1066 if (++j % 4 == 0) {
1067 qemu_fprintf(f, "\n");
1068 }
032c76bc
CW
1069 }
1070 }
796945d5
RH
1071 if (j % 4 != 0) {
1072 qemu_fprintf(f, "\n");
1073 }
1074 if (cpu->mmu_present) {
1075 qemu_fprintf(f, " mmu write: VPN=%05X PID %02X TLBACC %08X\n",
1076 env->mmu.pteaddr_wr & R_CR_PTEADDR_VPN_MASK,
1077 FIELD_EX32(env->mmu.tlbmisc_wr, CR_TLBMISC, PID),
1078 env->mmu.tlbacc_wr);
1079 }
032c76bc 1080#endif
90c84c56 1081 qemu_fprintf(f, "\n\n");
032c76bc
CW
1082}
1083
1084void nios2_tcg_init(void)
1085{
945a5bd3 1086#ifndef CONFIG_USER_ONLY
ad75a51e 1087 TCGv_ptr crs = tcg_global_mem_new_ptr(tcg_env,
945a5bd3 1088 offsetof(CPUNios2State, regs), "crs");
032c76bc 1089
945a5bd3
RH
1090 for (int i = 0; i < NUM_GP_REGS; i++) {
1091 cpu_crs_R[i] = tcg_global_mem_new(crs, 4 * i, gr_regnames[i]);
1092 }
1093
1094#define offsetof_regs0(N) offsetof(CPUNios2State, shadow_regs[0][N])
1095#else
1096#define offsetof_regs0(N) offsetof(CPUNios2State, regs[N])
1097#endif
1098
1099 for (int i = 0; i < NUM_GP_REGS; i++) {
ad75a51e 1100 cpu_R[i] = tcg_global_mem_new(tcg_env, offsetof_regs0(i),
b8f036a9 1101 gr_regnames[i]);
032c76bc 1102 }
945a5bd3
RH
1103
1104#undef offsetof_regs0
1105
ad75a51e 1106 cpu_pc = tcg_global_mem_new(tcg_env,
17a406ee 1107 offsetof(CPUNios2State, pc), "pc");
032c76bc 1108}