]>
Commit | Line | Data |
---|---|---|
14ade10f AG |
1 | /* |
2 | * AArch64 translation | |
3 | * | |
4 | * Copyright (c) 2013 Alexander Graf <agraf@suse.de> | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2 of the License, or (at your option) any later version. | |
10 | * | |
11 | * This library is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | #include <stdarg.h> | |
20 | #include <stdlib.h> | |
21 | #include <stdio.h> | |
22 | #include <string.h> | |
23 | #include <inttypes.h> | |
24 | ||
25 | #include "cpu.h" | |
26 | #include "tcg-op.h" | |
27 | #include "qemu/log.h" | |
28 | #include "translate.h" | |
29 | #include "qemu/host-utils.h" | |
30 | ||
31 | #include "helper.h" | |
32 | #define GEN_HELPER 1 | |
33 | #include "helper.h" | |
34 | ||
35 | static TCGv_i64 cpu_X[32]; | |
36 | static TCGv_i64 cpu_pc; | |
37 | static TCGv_i32 pstate; | |
38 | ||
39 | static const char *regnames[] = { | |
40 | "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", | |
41 | "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", | |
42 | "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", | |
43 | "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp" | |
44 | }; | |
45 | ||
46 | /* initialize TCG globals. */ | |
47 | void a64_translate_init(void) | |
48 | { | |
49 | int i; | |
50 | ||
51 | cpu_pc = tcg_global_mem_new_i64(TCG_AREG0, | |
52 | offsetof(CPUARMState, pc), | |
53 | "pc"); | |
54 | for (i = 0; i < 32; i++) { | |
55 | cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0, | |
56 | offsetof(CPUARMState, xregs[i]), | |
57 | regnames[i]); | |
58 | } | |
59 | ||
60 | pstate = tcg_global_mem_new_i32(TCG_AREG0, | |
61 | offsetof(CPUARMState, pstate), | |
62 | "pstate"); | |
63 | } | |
64 | ||
65 | void aarch64_cpu_dump_state(CPUState *cs, FILE *f, | |
66 | fprintf_function cpu_fprintf, int flags) | |
67 | { | |
68 | ARMCPU *cpu = ARM_CPU(cs); | |
69 | CPUARMState *env = &cpu->env; | |
70 | int i; | |
71 | ||
72 | cpu_fprintf(f, "PC=%016"PRIx64" SP=%016"PRIx64"\n", | |
73 | env->pc, env->xregs[31]); | |
74 | for (i = 0; i < 31; i++) { | |
75 | cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]); | |
76 | if ((i % 4) == 3) { | |
77 | cpu_fprintf(f, "\n"); | |
78 | } else { | |
79 | cpu_fprintf(f, " "); | |
80 | } | |
81 | } | |
82 | cpu_fprintf(f, "PSTATE=%c%c%c%c\n", | |
83 | env->pstate & PSTATE_N ? 'n' : '.', | |
84 | env->pstate & PSTATE_Z ? 'z' : '.', | |
85 | env->pstate & PSTATE_C ? 'c' : '.', | |
86 | env->pstate & PSTATE_V ? 'v' : '.'); | |
87 | cpu_fprintf(f, "\n"); | |
88 | } | |
89 | ||
90 | void gen_a64_set_pc_im(uint64_t val) | |
91 | { | |
92 | tcg_gen_movi_i64(cpu_pc, val); | |
93 | } | |
94 | ||
95 | static void gen_exception(int excp) | |
96 | { | |
97 | TCGv_i32 tmp = tcg_temp_new_i32(); | |
98 | tcg_gen_movi_i32(tmp, excp); | |
99 | gen_helper_exception(cpu_env, tmp); | |
100 | tcg_temp_free_i32(tmp); | |
101 | } | |
102 | ||
103 | static void gen_exception_insn(DisasContext *s, int offset, int excp) | |
104 | { | |
105 | gen_a64_set_pc_im(s->pc - offset); | |
106 | gen_exception(excp); | |
107 | s->is_jmp = DISAS_JUMP; | |
108 | } | |
109 | ||
110 | static void real_unallocated_encoding(DisasContext *s) | |
111 | { | |
112 | fprintf(stderr, "Unknown instruction: %#x\n", s->insn); | |
113 | gen_exception_insn(s, 4, EXCP_UDEF); | |
114 | } | |
115 | ||
116 | #define unallocated_encoding(s) do { \ | |
117 | fprintf(stderr, "unallocated encoding at line: %d\n", __LINE__); \ | |
118 | real_unallocated_encoding(s); \ | |
119 | } while (0) | |
120 | ||
121 | void disas_a64_insn(CPUARMState *env, DisasContext *s) | |
122 | { | |
123 | uint32_t insn; | |
124 | ||
125 | insn = arm_ldl_code(env, s->pc, s->bswap_code); | |
126 | s->insn = insn; | |
127 | s->pc += 4; | |
128 | ||
129 | switch ((insn >> 24) & 0x1f) { | |
130 | default: | |
131 | unallocated_encoding(s); | |
132 | break; | |
133 | } | |
134 | ||
135 | if (unlikely(s->singlestep_enabled) && (s->is_jmp == DISAS_TB_JUMP)) { | |
136 | /* go through the main loop for single step */ | |
137 | s->is_jmp = DISAS_JUMP; | |
138 | } | |
139 | } |